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++
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();
|
|
}
|