pcm/PcmConvert: move code to new class PcmChannelsConverter
This commit is contained in:
		@@ -338,6 +338,7 @@ libpcm_a_SOURCES = \
 | 
				
			|||||||
	src/pcm/PcmPack.cxx src/pcm/PcmPack.hxx \
 | 
						src/pcm/PcmPack.cxx src/pcm/PcmPack.hxx \
 | 
				
			||||||
	src/pcm/PcmFormat.cxx src/pcm/PcmFormat.hxx \
 | 
						src/pcm/PcmFormat.cxx src/pcm/PcmFormat.hxx \
 | 
				
			||||||
	src/pcm/FormatConverter.cxx src/pcm/FormatConverter.hxx \
 | 
						src/pcm/FormatConverter.cxx src/pcm/FormatConverter.hxx \
 | 
				
			||||||
 | 
						src/pcm/ChannelsConverter.cxx src/pcm/ChannelsConverter.hxx \
 | 
				
			||||||
	src/pcm/PcmResample.cxx src/pcm/PcmResample.hxx \
 | 
						src/pcm/PcmResample.cxx src/pcm/PcmResample.hxx \
 | 
				
			||||||
	src/pcm/PcmResampleFallback.cxx \
 | 
						src/pcm/PcmResampleFallback.cxx \
 | 
				
			||||||
	src/pcm/PcmResampleInternal.hxx \
 | 
						src/pcm/PcmResampleInternal.hxx \
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										115
									
								
								src/pcm/ChannelsConverter.cxx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/pcm/ChannelsConverter.cxx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2003-2013 The Music Player Daemon Project
 | 
				
			||||||
 | 
					 * http://www.musicpd.org
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					 * with this program; if not, write to the Free Software Foundation, Inc.,
 | 
				
			||||||
 | 
					 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					#include "ChannelsConverter.hxx"
 | 
				
			||||||
 | 
					#include "PcmChannels.hxx"
 | 
				
			||||||
 | 
					#include "PcmConvert.hxx"
 | 
				
			||||||
 | 
					#include "util/ConstBuffer.hxx"
 | 
				
			||||||
 | 
					#include "util/Error.hxx"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool
 | 
				
			||||||
 | 
					PcmChannelsConverter::Open(SampleFormat _format,
 | 
				
			||||||
 | 
								   unsigned _src_channels, unsigned _dest_channels,
 | 
				
			||||||
 | 
								   gcc_unused Error &error)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						assert(_format != SampleFormat::UNDEFINED);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (_format) {
 | 
				
			||||||
 | 
						case SampleFormat::S16:
 | 
				
			||||||
 | 
						case SampleFormat::S24_P32:
 | 
				
			||||||
 | 
						case SampleFormat::S32:
 | 
				
			||||||
 | 
						case SampleFormat::FLOAT:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							error.Format(pcm_convert_domain,
 | 
				
			||||||
 | 
								     "PCM channel conversion for %s is not implemented",
 | 
				
			||||||
 | 
								     sample_format_to_string(format));
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						format = _format;
 | 
				
			||||||
 | 
						src_channels = _src_channels;
 | 
				
			||||||
 | 
						dest_channels = _dest_channels;
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					PcmChannelsConverter::Close()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifndef NDEBUG
 | 
				
			||||||
 | 
						format = SampleFormat::UNDEFINED;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ConstBuffer<void>
 | 
				
			||||||
 | 
					PcmChannelsConverter::Convert(ConstBuffer<void> src, Error &error)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const void *result = nullptr;
 | 
				
			||||||
 | 
						size_t result_size = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (format) {
 | 
				
			||||||
 | 
						case SampleFormat::UNDEFINED:
 | 
				
			||||||
 | 
						case SampleFormat::S8:
 | 
				
			||||||
 | 
						case SampleFormat::DSD:
 | 
				
			||||||
 | 
							assert(false);
 | 
				
			||||||
 | 
							gcc_unreachable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case SampleFormat::S16:
 | 
				
			||||||
 | 
							result = pcm_convert_channels_16(buffer, dest_channels,
 | 
				
			||||||
 | 
											 src_channels,
 | 
				
			||||||
 | 
											 (const int16_t *)src.data,
 | 
				
			||||||
 | 
											 src.size, &result_size);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case SampleFormat::S24_P32:
 | 
				
			||||||
 | 
							result = pcm_convert_channels_24(buffer, dest_channels,
 | 
				
			||||||
 | 
											 src_channels,
 | 
				
			||||||
 | 
											 (const int32_t *)src.data,
 | 
				
			||||||
 | 
											 src.size, &result_size);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case SampleFormat::S32:
 | 
				
			||||||
 | 
							result = pcm_convert_channels_32(buffer, dest_channels,
 | 
				
			||||||
 | 
											 src_channels,
 | 
				
			||||||
 | 
											 (const int32_t *)src.data,
 | 
				
			||||||
 | 
											 src.size, &result_size);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case SampleFormat::FLOAT:
 | 
				
			||||||
 | 
							result = pcm_convert_channels_float(buffer, dest_channels,
 | 
				
			||||||
 | 
											    src_channels,
 | 
				
			||||||
 | 
											    (const float *)src.data,
 | 
				
			||||||
 | 
											    src.size, &result_size);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (result == nullptr) {
 | 
				
			||||||
 | 
							error.Format(pcm_convert_domain,
 | 
				
			||||||
 | 
								     "Conversion from %u to %u channels "
 | 
				
			||||||
 | 
								     "is not implemented",
 | 
				
			||||||
 | 
								     src_channels, dest_channels);
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return { result, result_size };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										83
									
								
								src/pcm/ChannelsConverter.hxx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								src/pcm/ChannelsConverter.hxx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2003-2013 The Music Player Daemon Project
 | 
				
			||||||
 | 
					 * http://www.musicpd.org
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					 * with this program; if not, write to the Free Software Foundation, Inc.,
 | 
				
			||||||
 | 
					 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef MPD_PCM_CHANNELS_CONVERTER_HXX
 | 
				
			||||||
 | 
					#define MPD_PCM_CHANNELS_CONVERTER_HXX
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "check.h"
 | 
				
			||||||
 | 
					#include "AudioFormat.hxx"
 | 
				
			||||||
 | 
					#include "PcmBuffer.hxx"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NDEBUG
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Error;
 | 
				
			||||||
 | 
					template<typename T> struct ConstBuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A class that converts samples from one format to another.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class PcmChannelsConverter {
 | 
				
			||||||
 | 
						SampleFormat format;
 | 
				
			||||||
 | 
						unsigned src_channels, dest_channels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PcmBuffer buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					#ifndef NDEBUG
 | 
				
			||||||
 | 
						PcmChannelsConverter()
 | 
				
			||||||
 | 
							:format(SampleFormat::UNDEFINED) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						~PcmChannelsConverter() {
 | 
				
			||||||
 | 
							assert(format == SampleFormat::UNDEFINED);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Opens the object, prepare for Convert().
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @param format the sample format
 | 
				
			||||||
 | 
						 * @param src_channels the number of source channels
 | 
				
			||||||
 | 
						 * @param dest_channels the number of destination channels
 | 
				
			||||||
 | 
						 * @param error location to store the error
 | 
				
			||||||
 | 
						 * @return true on success
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						bool Open(SampleFormat format,
 | 
				
			||||||
 | 
							  unsigned src_channels, unsigned dest_channels,
 | 
				
			||||||
 | 
							  Error &error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Closes the object.  After that, you may call Open() again.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						void Close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Convert a block of PCM data.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @param src the input buffer
 | 
				
			||||||
 | 
						 * @param error location to store the error
 | 
				
			||||||
 | 
						 * @return the destination buffer on success,
 | 
				
			||||||
 | 
						 * ConstBuffer::Null() on error
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						gcc_pure
 | 
				
			||||||
 | 
						ConstBuffer<void> Convert(ConstBuffer<void> src, Error &error);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@@ -19,7 +19,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#include "PcmConvert.hxx"
 | 
					#include "PcmConvert.hxx"
 | 
				
			||||||
#include "PcmChannels.hxx"
 | 
					 | 
				
			||||||
#include "AudioFormat.hxx"
 | 
					#include "AudioFormat.hxx"
 | 
				
			||||||
#include "util/ConstBuffer.hxx"
 | 
					#include "util/ConstBuffer.hxx"
 | 
				
			||||||
#include "util/Error.hxx"
 | 
					#include "util/Error.hxx"
 | 
				
			||||||
@@ -72,12 +71,22 @@ PcmConvert::Open(AudioFormat _src_format, AudioFormat _dest_format,
 | 
				
			|||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	format.format = dest_format.format;
 | 
						format.format = dest_format.format;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (format.channels != dest_format.channels &&
 | 
				
			||||||
 | 
						    !channels_converter.Open(format.format, format.channels,
 | 
				
			||||||
 | 
									     dest_format.channels, error)) {
 | 
				
			||||||
 | 
							format_converter.Close();
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
PcmConvert::Close()
 | 
					PcmConvert::Close()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (src_format.channels != dest_format.channels)
 | 
				
			||||||
 | 
							channels_converter.Close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (src_format.format != dest_format.format)
 | 
						if (src_format.format != dest_format.format)
 | 
				
			||||||
		format_converter.Close();
 | 
							format_converter.Close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -96,25 +105,11 @@ PcmConvert::Convert16(ConstBuffer<int16_t> src, AudioFormat format,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	assert(format.format == SampleFormat::S16);
 | 
						assert(format.format == SampleFormat::S16);
 | 
				
			||||||
	assert(dest_format.format == SampleFormat::S16);
 | 
						assert(dest_format.format == SampleFormat::S16);
 | 
				
			||||||
 | 
						assert(format.channels == dest_format.channels);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto buf = src.data;
 | 
						auto buf = src.data;
 | 
				
			||||||
	size_t len = src.size * sizeof(*src.data);
 | 
						size_t len = src.size * sizeof(*src.data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (format.channels != dest_format.channels) {
 | 
					 | 
				
			||||||
		buf = pcm_convert_channels_16(channels_buffer,
 | 
					 | 
				
			||||||
					      dest_format.channels,
 | 
					 | 
				
			||||||
					      format.channels,
 | 
					 | 
				
			||||||
					      buf, len, &len);
 | 
					 | 
				
			||||||
		if (buf == nullptr) {
 | 
					 | 
				
			||||||
			error.Format(pcm_convert_domain,
 | 
					 | 
				
			||||||
				     "Conversion from %u to %u channels "
 | 
					 | 
				
			||||||
				     "is not implemented",
 | 
					 | 
				
			||||||
				     format.channels,
 | 
					 | 
				
			||||||
				     dest_format.channels);
 | 
					 | 
				
			||||||
			return nullptr;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (format.sample_rate != dest_format.sample_rate) {
 | 
						if (format.sample_rate != dest_format.sample_rate) {
 | 
				
			||||||
		buf = resampler.Resample16(dest_format.channels,
 | 
							buf = resampler.Resample16(dest_format.channels,
 | 
				
			||||||
					   format.sample_rate, buf, len,
 | 
										   format.sample_rate, buf, len,
 | 
				
			||||||
@@ -133,25 +128,11 @@ PcmConvert::Convert24(ConstBuffer<int32_t> src, AudioFormat format,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	assert(format.format == SampleFormat::S24_P32);
 | 
						assert(format.format == SampleFormat::S24_P32);
 | 
				
			||||||
	assert(dest_format.format == SampleFormat::S24_P32);
 | 
						assert(dest_format.format == SampleFormat::S24_P32);
 | 
				
			||||||
 | 
						assert(format.channels == dest_format.channels);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto buf = src.data;
 | 
						auto buf = src.data;
 | 
				
			||||||
	size_t len = src.size * sizeof(*src.data);
 | 
						size_t len = src.size * sizeof(*src.data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (format.channels != dest_format.channels) {
 | 
					 | 
				
			||||||
		buf = pcm_convert_channels_24(channels_buffer,
 | 
					 | 
				
			||||||
					      dest_format.channels,
 | 
					 | 
				
			||||||
					      format.channels,
 | 
					 | 
				
			||||||
					      buf, len, &len);
 | 
					 | 
				
			||||||
		if (buf == nullptr) {
 | 
					 | 
				
			||||||
			error.Format(pcm_convert_domain,
 | 
					 | 
				
			||||||
				     "Conversion from %u to %u channels "
 | 
					 | 
				
			||||||
				     "is not implemented",
 | 
					 | 
				
			||||||
				     format.channels,
 | 
					 | 
				
			||||||
				     dest_format.channels);
 | 
					 | 
				
			||||||
			return nullptr;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (format.sample_rate != dest_format.sample_rate) {
 | 
						if (format.sample_rate != dest_format.sample_rate) {
 | 
				
			||||||
		buf = resampler.Resample24(dest_format.channels,
 | 
							buf = resampler.Resample24(dest_format.channels,
 | 
				
			||||||
					   format.sample_rate, buf, len,
 | 
										   format.sample_rate, buf, len,
 | 
				
			||||||
@@ -170,25 +151,11 @@ PcmConvert::Convert32(ConstBuffer<int32_t> src, AudioFormat format,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	assert(format.format == SampleFormat::S32);
 | 
						assert(format.format == SampleFormat::S32);
 | 
				
			||||||
	assert(dest_format.format == SampleFormat::S32);
 | 
						assert(dest_format.format == SampleFormat::S32);
 | 
				
			||||||
 | 
						assert(format.channels == dest_format.channels);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto buf = src.data;
 | 
						auto buf = src.data;
 | 
				
			||||||
	size_t len = src.size * sizeof(*src.data);
 | 
						size_t len = src.size * sizeof(*src.data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (format.channels != dest_format.channels) {
 | 
					 | 
				
			||||||
		buf = pcm_convert_channels_32(channels_buffer,
 | 
					 | 
				
			||||||
					      dest_format.channels,
 | 
					 | 
				
			||||||
					      format.channels,
 | 
					 | 
				
			||||||
					      buf, len, &len);
 | 
					 | 
				
			||||||
		if (buf == nullptr) {
 | 
					 | 
				
			||||||
			error.Format(pcm_convert_domain,
 | 
					 | 
				
			||||||
				     "Conversion from %u to %u channels "
 | 
					 | 
				
			||||||
				     "is not implemented",
 | 
					 | 
				
			||||||
				     format.channels,
 | 
					 | 
				
			||||||
				     dest_format.channels);
 | 
					 | 
				
			||||||
			return nullptr;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (format.sample_rate != dest_format.sample_rate) {
 | 
						if (format.sample_rate != dest_format.sample_rate) {
 | 
				
			||||||
		buf = resampler.Resample32(dest_format.channels,
 | 
							buf = resampler.Resample32(dest_format.channels,
 | 
				
			||||||
					   format.sample_rate, buf, len,
 | 
										   format.sample_rate, buf, len,
 | 
				
			||||||
@@ -207,27 +174,11 @@ PcmConvert::ConvertFloat(ConstBuffer<float> src, AudioFormat format,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	assert(format.format == SampleFormat::FLOAT);
 | 
						assert(format.format == SampleFormat::FLOAT);
 | 
				
			||||||
	assert(dest_format.format == SampleFormat::FLOAT);
 | 
						assert(dest_format.format == SampleFormat::FLOAT);
 | 
				
			||||||
 | 
						assert(format.channels == dest_format.channels);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto buffer = src.data;
 | 
						auto buffer = src.data;
 | 
				
			||||||
	size_t size = src.size * sizeof(*src.data);
 | 
						size_t size = src.size * sizeof(*src.data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* convert channels */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (format.channels != dest_format.channels) {
 | 
					 | 
				
			||||||
		buffer = pcm_convert_channels_float(channels_buffer,
 | 
					 | 
				
			||||||
						    dest_format.channels,
 | 
					 | 
				
			||||||
						    format.channels,
 | 
					 | 
				
			||||||
						    buffer, size, &size);
 | 
					 | 
				
			||||||
		if (buffer == nullptr) {
 | 
					 | 
				
			||||||
			error.Format(pcm_convert_domain,
 | 
					 | 
				
			||||||
				     "Conversion from %u to %u channels "
 | 
					 | 
				
			||||||
				     "is not implemented",
 | 
					 | 
				
			||||||
				     format.channels,
 | 
					 | 
				
			||||||
				     dest_format.channels);
 | 
					 | 
				
			||||||
			return nullptr;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* resample with float, because this is the best format for
 | 
						/* resample with float, because this is the best format for
 | 
				
			||||||
	   libsamplerate */
 | 
						   libsamplerate */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -274,6 +225,14 @@ PcmConvert::Convert(const void *src, size_t src_size,
 | 
				
			|||||||
		format.format = dest_format.format;
 | 
							format.format = dest_format.format;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (format.channels != dest_format.channels) {
 | 
				
			||||||
 | 
							buffer = channels_converter.Convert(buffer, error);
 | 
				
			||||||
 | 
							if (buffer.IsNull())
 | 
				
			||||||
 | 
								return nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							format.channels = dest_format.channels;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (dest_format.format) {
 | 
						switch (dest_format.format) {
 | 
				
			||||||
	case SampleFormat::S16:
 | 
						case SampleFormat::S16:
 | 
				
			||||||
		buffer = Convert16(ConstBuffer<int16_t>::FromVoid(buffer),
 | 
							buffer = Convert16(ConstBuffer<int16_t>::FromVoid(buffer),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,6 +24,7 @@
 | 
				
			|||||||
#include "PcmResample.hxx"
 | 
					#include "PcmResample.hxx"
 | 
				
			||||||
#include "PcmBuffer.hxx"
 | 
					#include "PcmBuffer.hxx"
 | 
				
			||||||
#include "FormatConverter.hxx"
 | 
					#include "FormatConverter.hxx"
 | 
				
			||||||
 | 
					#include "ChannelsConverter.hxx"
 | 
				
			||||||
#include "AudioFormat.hxx"
 | 
					#include "AudioFormat.hxx"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stddef.h>
 | 
					#include <stddef.h>
 | 
				
			||||||
@@ -43,9 +44,7 @@ class PcmConvert {
 | 
				
			|||||||
	PcmResampler resampler;
 | 
						PcmResampler resampler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	PcmFormatConverter format_converter;
 | 
						PcmFormatConverter format_converter;
 | 
				
			||||||
 | 
						PcmChannelsConverter channels_converter;
 | 
				
			||||||
	/** the buffer for converting the channel count */
 | 
					 | 
				
			||||||
	PcmBuffer channels_buffer;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	AudioFormat src_format, dest_format;
 | 
						AudioFormat src_format, dest_format;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user