You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

84 lines
2.0 KiB
C++

// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
#include "ChannelsConverter.hxx"
#include "PcmChannels.hxx"
#include "pcm/Features.h" // for ENABLE_DSD
#include "lib/fmt/AudioFormatFormatter.hxx"
#include "lib/fmt/RuntimeError.hxx"
#include "util/SpanCast.hxx"
#include <cassert>
#include <utility> // for std::unreachable()
void
PcmChannelsConverter::Open(SampleFormat _format,
unsigned _src_channels, unsigned _dest_channels)
{
assert(_format != SampleFormat::UNDEFINED);
switch (_format) {
case SampleFormat::DSD:
case SampleFormat::S16:
case SampleFormat::S24_P32:
case SampleFormat::S32:
case SampleFormat::FLOAT:
break;
default:
throw FmtRuntimeError("PCM channel conversion for {} is not implemented",
_format);
}
format = _format;
src_channels = _src_channels;
dest_channels = _dest_channels;
}
void
PcmChannelsConverter::Close() noexcept
{
#ifndef NDEBUG
format = SampleFormat::UNDEFINED;
#endif
}
std::span<const std::byte>
PcmChannelsConverter::Convert(std::span<const std::byte> src) noexcept
{
switch (format) {
case SampleFormat::UNDEFINED:
case SampleFormat::S8:
std::unreachable();
case SampleFormat::DSD:
#ifdef ENABLE_DSD
return pcm_convert_channels_dsd(buffer, dest_channels, src_channels, src);
#else
std::unreachable();
#endif
case SampleFormat::S16:
return std::as_bytes(pcm_convert_channels_16(buffer, dest_channels,
src_channels,
FromBytesStrict<const int16_t>(src)));
case SampleFormat::S24_P32:
return std::as_bytes(pcm_convert_channels_24(buffer, dest_channels,
src_channels,
FromBytesStrict<const int32_t>(src)));
case SampleFormat::S32:
return std::as_bytes(pcm_convert_channels_32(buffer, dest_channels,
src_channels,
FromBytesStrict<const int32_t>(src)));
case SampleFormat::FLOAT:
return std::as_bytes(pcm_convert_channels_float(buffer, dest_channels,
src_channels,
FromBytesStrict<const float>(src)));
}
std::unreachable();
}