From 361404fd59e817560e4564f15466e94c2a0d7551 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 30 Jan 2013 23:40:56 +0100 Subject: pcm_convert: convert to C++ --- src/DecoderAPI.cxx | 9 +- src/DecoderInternal.cxx | 2 - src/DecoderInternal.hxx | 5 +- src/PcmConvert.cxx | 331 ++++++++++++++++++++++++++++++++++++ src/PcmConvert.hxx | 114 +++++++++++++ src/filter/ConvertFilterPlugin.cxx | 17 +- src/pcm_convert.c | 333 ------------------------------------- src/pcm_convert.h | 100 ----------- 8 files changed, 461 insertions(+), 450 deletions(-) create mode 100644 src/PcmConvert.cxx create mode 100644 src/PcmConvert.hxx delete mode 100644 src/pcm_convert.c delete mode 100644 src/pcm_convert.h (limited to 'src') diff --git a/src/DecoderAPI.cxx b/src/DecoderAPI.cxx index b68af19b..d86b93fb 100644 --- a/src/DecoderAPI.cxx +++ b/src/DecoderAPI.cxx @@ -402,10 +402,11 @@ decoder_data(struct decoder *decoder, } if (!audio_format_equals(&dc->in_audio_format, &dc->out_audio_format)) { - data = pcm_convert(&decoder->conv_state, - &dc->in_audio_format, data, length, - &dc->out_audio_format, &length, - &error); + data = decoder->conv_state.Convert(&dc->in_audio_format, + data, length, + &dc->out_audio_format, + &length, + &error); if (data == NULL) { /* the PCM conversion has failed - stop playback, since we have no better way to diff --git a/src/DecoderInternal.cxx b/src/DecoderInternal.cxx index 80f0adfd..e390fdfd 100644 --- a/src/DecoderInternal.cxx +++ b/src/DecoderInternal.cxx @@ -40,8 +40,6 @@ decoder::~decoder() if (decoder_tag != nullptr) tag_free(decoder_tag); - - pcm_convert_deinit(&conv_state); } /** diff --git a/src/DecoderInternal.hxx b/src/DecoderInternal.hxx index ae50a62e..3423e3f9 100644 --- a/src/DecoderInternal.hxx +++ b/src/DecoderInternal.hxx @@ -21,7 +21,7 @@ #define MPD_DECODER_INTERNAL_HXX #include "decoder_command.h" -#include "pcm_convert.h" +#include "PcmConvert.hxx" #include "replay_gain_info.h" struct input_stream; @@ -29,7 +29,7 @@ struct input_stream; struct decoder { struct decoder_control *dc; - struct pcm_convert_state conv_state; + PcmConvert conv_state; /** * The time stamp of the next data chunk, in seconds. @@ -91,7 +91,6 @@ struct decoder { song_tag(_tag), stream_tag(nullptr), decoder_tag(nullptr), chunk(nullptr), replay_gain_serial(0) { - pcm_convert_init(&conv_state); } ~decoder(); diff --git a/src/PcmConvert.cxx b/src/PcmConvert.cxx new file mode 100644 index 00000000..175584c8 --- /dev/null +++ b/src/PcmConvert.cxx @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2003-2011 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 "PcmConvert.hxx" + +extern "C" { +#include "pcm_channels.h" +#include "pcm_format.h" +} + +#include "pcm_pack.h" +#include "audio_format.h" + +#include +#include +#include +#include + +#undef G_LOG_DOMAIN +#define G_LOG_DOMAIN "pcm" + +PcmConvert::PcmConvert() +{ + memset(this, 0, sizeof(*this)); + + pcm_dsd_init(&dsd); + pcm_resample_init(&resample); + pcm_dither_24_init(&dither); + + pcm_buffer_init(&format_buffer); + pcm_buffer_init(&channels_buffer); +} + +PcmConvert::~PcmConvert() +{ + pcm_dsd_deinit(&dsd); + pcm_resample_deinit(&resample); + + pcm_buffer_deinit(&format_buffer); + pcm_buffer_deinit(&channels_buffer); +} + +void +PcmConvert::Reset() +{ + pcm_dsd_reset(&dsd); + pcm_resample_reset(&resample); +} + +inline const int16_t * +PcmConvert::Convert16(const audio_format *src_format, + const void *src_buffer, size_t src_size, + const audio_format *dest_format, size_t *dest_size_r, + GError **error_r) +{ + const int16_t *buf; + size_t len; + + assert(dest_format->format == SAMPLE_FORMAT_S16); + + buf = pcm_convert_to_16(&format_buffer, &dither, + sample_format(src_format->format), + src_buffer, src_size, + &len); + if (buf == NULL) { + g_set_error(error_r, pcm_convert_quark(), 0, + "Conversion from %s to 16 bit is not implemented", + sample_format_to_string(sample_format(src_format->format))); + return NULL; + } + + if (src_format->channels != dest_format->channels) { + buf = pcm_convert_channels_16(&channels_buffer, + dest_format->channels, + src_format->channels, + buf, len, &len); + if (buf == NULL) { + g_set_error(error_r, pcm_convert_quark(), 0, + "Conversion from %u to %u channels " + "is not implemented", + src_format->channels, + dest_format->channels); + return NULL; + } + } + + if (src_format->sample_rate != dest_format->sample_rate) { + buf = pcm_resample_16(&resample, + dest_format->channels, + src_format->sample_rate, buf, len, + dest_format->sample_rate, &len, + error_r); + if (buf == NULL) + return NULL; + } + + *dest_size_r = len; + return buf; +} + +inline const int32_t * +PcmConvert::Convert24(const audio_format *src_format, + const void *src_buffer, size_t src_size, + const audio_format *dest_format, size_t *dest_size_r, + GError **error_r) +{ + const int32_t *buf; + size_t len; + + assert(dest_format->format == SAMPLE_FORMAT_S24_P32); + + buf = pcm_convert_to_24(&format_buffer, + sample_format(src_format->format), + src_buffer, src_size, &len); + if (buf == NULL) { + g_set_error(error_r, pcm_convert_quark(), 0, + "Conversion from %s to 24 bit is not implemented", + sample_format_to_string(sample_format(src_format->format))); + return NULL; + } + + if (src_format->channels != dest_format->channels) { + buf = pcm_convert_channels_24(&channels_buffer, + dest_format->channels, + src_format->channels, + buf, len, &len); + if (buf == NULL) { + g_set_error(error_r, pcm_convert_quark(), 0, + "Conversion from %u to %u channels " + "is not implemented", + src_format->channels, + dest_format->channels); + return NULL; + } + } + + if (src_format->sample_rate != dest_format->sample_rate) { + buf = pcm_resample_24(&resample, + dest_format->channels, + src_format->sample_rate, buf, len, + dest_format->sample_rate, &len, + error_r); + if (buf == NULL) + return NULL; + } + + *dest_size_r = len; + return buf; +} + +inline const int32_t * +PcmConvert::Convert32(const audio_format *src_format, + const void *src_buffer, size_t src_size, + const audio_format *dest_format, size_t *dest_size_r, + GError **error_r) +{ + const int32_t *buf; + size_t len; + + assert(dest_format->format == SAMPLE_FORMAT_S32); + + buf = pcm_convert_to_32(&format_buffer, + sample_format(src_format->format), + src_buffer, src_size, &len); + if (buf == NULL) { + g_set_error(error_r, pcm_convert_quark(), 0, + "Conversion from %s to 32 bit is not implemented", + sample_format_to_string(sample_format(src_format->format))); + return NULL; + } + + if (src_format->channels != dest_format->channels) { + buf = pcm_convert_channels_32(&channels_buffer, + dest_format->channels, + src_format->channels, + buf, len, &len); + if (buf == NULL) { + g_set_error(error_r, pcm_convert_quark(), 0, + "Conversion from %u to %u channels " + "is not implemented", + src_format->channels, + dest_format->channels); + return NULL; + } + } + + if (src_format->sample_rate != dest_format->sample_rate) { + buf = pcm_resample_32(&resample, + dest_format->channels, + src_format->sample_rate, buf, len, + dest_format->sample_rate, &len, + error_r); + if (buf == NULL) + return buf; + } + + *dest_size_r = len; + return buf; +} + +inline const float * +PcmConvert::ConvertFloat(const audio_format *src_format, + const void *src_buffer, size_t src_size, + const audio_format *dest_format, size_t *dest_size_r, + GError **error_r) +{ + const float *buffer = (const float *)src_buffer; + size_t size = src_size; + + assert(dest_format->format == SAMPLE_FORMAT_FLOAT); + + /* convert to float now */ + + buffer = pcm_convert_to_float(&format_buffer, + sample_format(src_format->format), + buffer, size, &size); + if (buffer == NULL) { + g_set_error(error_r, pcm_convert_quark(), 0, + "Conversion from %s to float is not implemented", + sample_format_to_string(sample_format(src_format->format))); + return NULL; + } + + /* convert channels */ + + if (src_format->channels != dest_format->channels) { + buffer = pcm_convert_channels_float(&channels_buffer, + dest_format->channels, + src_format->channels, + buffer, size, &size); + if (buffer == NULL) { + g_set_error(error_r, pcm_convert_quark(), 0, + "Conversion from %u to %u channels " + "is not implemented", + src_format->channels, + dest_format->channels); + return NULL; + } + } + + /* resample with float, because this is the best format for + libsamplerate */ + + if (src_format->sample_rate != dest_format->sample_rate) { + buffer = pcm_resample_float(&resample, + dest_format->channels, + src_format->sample_rate, + buffer, size, + dest_format->sample_rate, &size, + error_r); + if (buffer == NULL) + return NULL; + } + + *dest_size_r = size; + return buffer; +} + +const void * +PcmConvert::Convert(const audio_format *src_format, + const void *src, size_t src_size, + const audio_format *dest_format, + size_t *dest_size_r, + GError **error_r) +{ + struct audio_format float_format; + if (src_format->format == SAMPLE_FORMAT_DSD) { + size_t f_size; + const float *f = pcm_dsd_to_float(&dsd, + src_format->channels, + false, (const uint8_t *)src, + src_size, &f_size); + if (f == NULL) { + g_set_error_literal(error_r, pcm_convert_quark(), 0, + "DSD to PCM conversion failed"); + return NULL; + } + + float_format = *src_format; + float_format.format = SAMPLE_FORMAT_FLOAT; + + src_format = &float_format; + src = f; + src_size = f_size; + } + + switch (sample_format(dest_format->format)) { + case SAMPLE_FORMAT_S16: + return Convert16(src_format, src, src_size, + dest_format, dest_size_r, + error_r); + + case SAMPLE_FORMAT_S24_P32: + return Convert24(src_format, src, src_size, + dest_format, dest_size_r, + error_r); + + case SAMPLE_FORMAT_S32: + return Convert32(src_format, src, src_size, + dest_format, dest_size_r, + error_r); + + case SAMPLE_FORMAT_FLOAT: + return ConvertFloat(src_format, src, src_size, + dest_format, dest_size_r, + error_r); + + default: + g_set_error(error_r, pcm_convert_quark(), 0, + "PCM conversion to %s is not implemented", + sample_format_to_string(sample_format(dest_format->format))); + return NULL; + } +} diff --git a/src/PcmConvert.hxx b/src/PcmConvert.hxx new file mode 100644 index 00000000..bec30af4 --- /dev/null +++ b/src/PcmConvert.hxx @@ -0,0 +1,114 @@ +/* + * 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 PCM_CONVERT_HXX +#define PCM_CONVERT_HXX + +extern "C" { +#include "pcm_dsd.h" +#include "pcm_resample.h" +#include "pcm_dither.h" +#include "pcm_buffer.h" +} + +#include + +struct audio_format; + +/** + * This object is statically allocated (within another struct), and + * holds buffer allocations and the state for all kinds of PCM + * conversions. + */ +class PcmConvert { + struct pcm_dsd dsd; + + struct pcm_resample_state resample; + + struct pcm_dither dither; + + /** the buffer for converting the sample format */ + struct pcm_buffer format_buffer; + + /** the buffer for converting the channel count */ + struct pcm_buffer channels_buffer; + +public: + PcmConvert(); + ~PcmConvert(); + + + /** + * Reset the pcm_convert_state object. Use this at the + * boundary between two distinct songs and each time the + * format changes. + */ + void Reset(); + + /** + * Converts PCM data between two audio formats. + * + * @param src_format the source audio format + * @param src the source PCM buffer + * @param src_size the size of #src in bytes + * @param dest_format the requested destination audio format + * @param dest_size_r returns the number of bytes of the destination buffer + * @param error_r location to store the error occurring, or NULL to + * ignore errors + * @return the destination buffer, or NULL on error + */ + const void *Convert(const audio_format *src_format, + const void *src, size_t src_size, + const audio_format *dest_format, + size_t *dest_size_r, + GError **error_r); + +private: + const int16_t *Convert16(const audio_format *src_format, + const void *src_buffer, size_t src_size, + const audio_format *dest_format, + size_t *dest_size_r, + GError **error_r); + + const int32_t *Convert24(const audio_format *src_format, + const void *src_buffer, size_t src_size, + const audio_format *dest_format, + size_t *dest_size_r, + GError **error_r); + + const int32_t *Convert32(const audio_format *src_format, + const void *src_buffer, size_t src_size, + const audio_format *dest_format, + size_t *dest_size_r, + GError **error_r); + + const float *ConvertFloat(const audio_format *src_format, + const void *src_buffer, size_t src_size, + const audio_format *dest_format, + size_t *dest_size_r, + GError **error_r); +}; + +static inline GQuark +pcm_convert_quark(void) +{ + return g_quark_from_static_string("pcm_convert"); +} + +#endif diff --git a/src/filter/ConvertFilterPlugin.cxx b/src/filter/ConvertFilterPlugin.cxx index 04f34842..23c912b0 100644 --- a/src/filter/ConvertFilterPlugin.cxx +++ b/src/filter/ConvertFilterPlugin.cxx @@ -23,7 +23,8 @@ #include "filter_internal.h" #include "filter_registry.h" #include "conf.h" -#include "pcm_convert.h" +#include "PcmConvert.hxx" +#include "util/Manual.hxx" #include "audio_format.h" #include "poison.h" @@ -51,7 +52,7 @@ struct ConvertFilter { */ struct audio_format out_audio_format; - struct pcm_convert_state state; + Manual state; ConvertFilter() { filter_init(&base, &convert_filter_plugin); @@ -81,7 +82,7 @@ convert_filter_open(struct filter *_filter, struct audio_format *audio_format, assert(audio_format_valid(audio_format)); filter->in_audio_format = filter->out_audio_format = *audio_format; - pcm_convert_init(&filter->state); + filter->state.Construct(); return &filter->in_audio_format; } @@ -91,7 +92,7 @@ convert_filter_close(struct filter *_filter) { ConvertFilter *filter = (ConvertFilter *)_filter; - pcm_convert_deinit(&filter->state); + filter->state.Destruct(); poison_undefined(&filter->in_audio_format, sizeof(filter->in_audio_format)); @@ -113,10 +114,10 @@ convert_filter_filter(struct filter *_filter, const void *src, size_t src_size, return src; } - dest = pcm_convert(&filter->state, &filter->in_audio_format, - src, src_size, - &filter->out_audio_format, dest_size_r, - error_r); + dest = filter->state->Convert(&filter->in_audio_format, + src, src_size, + &filter->out_audio_format, dest_size_r, + error_r); if (dest == NULL) return NULL; diff --git a/src/pcm_convert.c b/src/pcm_convert.c deleted file mode 100644 index 1d8ae957..00000000 --- a/src/pcm_convert.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (C) 2003-2011 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 "pcm_convert.h" -#include "pcm_channels.h" -#include "pcm_format.h" -#include "pcm_pack.h" -#include "audio_format.h" - -#include -#include -#include -#include - -#undef G_LOG_DOMAIN -#define G_LOG_DOMAIN "pcm" - -void pcm_convert_init(struct pcm_convert_state *state) -{ - memset(state, 0, sizeof(*state)); - - pcm_dsd_init(&state->dsd); - pcm_resample_init(&state->resample); - pcm_dither_24_init(&state->dither); - - pcm_buffer_init(&state->format_buffer); - pcm_buffer_init(&state->channels_buffer); -} - -void pcm_convert_deinit(struct pcm_convert_state *state) -{ - pcm_dsd_deinit(&state->dsd); - pcm_resample_deinit(&state->resample); - - pcm_buffer_deinit(&state->format_buffer); - pcm_buffer_deinit(&state->channels_buffer); -} - -void -pcm_convert_reset(struct pcm_convert_state *state) -{ - pcm_dsd_reset(&state->dsd); - pcm_resample_reset(&state->resample); -} - -static const int16_t * -pcm_convert_16(struct pcm_convert_state *state, - const struct audio_format *src_format, - const void *src_buffer, size_t src_size, - const struct audio_format *dest_format, size_t *dest_size_r, - GError **error_r) -{ - const int16_t *buf; - size_t len; - - assert(dest_format->format == SAMPLE_FORMAT_S16); - - buf = pcm_convert_to_16(&state->format_buffer, &state->dither, - src_format->format, src_buffer, src_size, - &len); - if (buf == NULL) { - g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %s to 16 bit is not implemented", - sample_format_to_string(src_format->format)); - return NULL; - } - - if (src_format->channels != dest_format->channels) { - buf = pcm_convert_channels_16(&state->channels_buffer, - dest_format->channels, - src_format->channels, - buf, len, &len); - if (buf == NULL) { - g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %u to %u channels " - "is not implemented", - src_format->channels, - dest_format->channels); - return NULL; - } - } - - if (src_format->sample_rate != dest_format->sample_rate) { - buf = pcm_resample_16(&state->resample, - dest_format->channels, - src_format->sample_rate, buf, len, - dest_format->sample_rate, &len, - error_r); - if (buf == NULL) - return NULL; - } - - *dest_size_r = len; - return buf; -} - -static const int32_t * -pcm_convert_24(struct pcm_convert_state *state, - const struct audio_format *src_format, - const void *src_buffer, size_t src_size, - const struct audio_format *dest_format, size_t *dest_size_r, - GError **error_r) -{ - const int32_t *buf; - size_t len; - - assert(dest_format->format == SAMPLE_FORMAT_S24_P32); - - buf = pcm_convert_to_24(&state->format_buffer, src_format->format, - src_buffer, src_size, &len); - if (buf == NULL) { - g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %s to 24 bit is not implemented", - sample_format_to_string(src_format->format)); - return NULL; - } - - if (src_format->channels != dest_format->channels) { - buf = pcm_convert_channels_24(&state->channels_buffer, - dest_format->channels, - src_format->channels, - buf, len, &len); - if (buf == NULL) { - g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %u to %u channels " - "is not implemented", - src_format->channels, - dest_format->channels); - return NULL; - } - } - - if (src_format->sample_rate != dest_format->sample_rate) { - buf = pcm_resample_24(&state->resample, - dest_format->channels, - src_format->sample_rate, buf, len, - dest_format->sample_rate, &len, - error_r); - if (buf == NULL) - return NULL; - } - - *dest_size_r = len; - return buf; -} - -static const int32_t * -pcm_convert_32(struct pcm_convert_state *state, - const struct audio_format *src_format, - const void *src_buffer, size_t src_size, - const struct audio_format *dest_format, size_t *dest_size_r, - GError **error_r) -{ - const int32_t *buf; - size_t len; - - assert(dest_format->format == SAMPLE_FORMAT_S32); - - buf = pcm_convert_to_32(&state->format_buffer, src_format->format, - src_buffer, src_size, &len); - if (buf == NULL) { - g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %s to 32 bit is not implemented", - sample_format_to_string(src_format->format)); - return NULL; - } - - if (src_format->channels != dest_format->channels) { - buf = pcm_convert_channels_32(&state->channels_buffer, - dest_format->channels, - src_format->channels, - buf, len, &len); - if (buf == NULL) { - g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %u to %u channels " - "is not implemented", - src_format->channels, - dest_format->channels); - return NULL; - } - } - - if (src_format->sample_rate != dest_format->sample_rate) { - buf = pcm_resample_32(&state->resample, - dest_format->channels, - src_format->sample_rate, buf, len, - dest_format->sample_rate, &len, - error_r); - if (buf == NULL) - return buf; - } - - *dest_size_r = len; - return buf; -} - -static const float * -pcm_convert_float(struct pcm_convert_state *state, - const struct audio_format *src_format, - const void *src_buffer, size_t src_size, - const struct audio_format *dest_format, size_t *dest_size_r, - GError **error_r) -{ - const float *buffer = src_buffer; - size_t size = src_size; - - assert(dest_format->format == SAMPLE_FORMAT_FLOAT); - - /* convert to float now */ - - buffer = pcm_convert_to_float(&state->format_buffer, - src_format->format, - buffer, size, &size); - if (buffer == NULL) { - g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %s to float is not implemented", - sample_format_to_string(src_format->format)); - return NULL; - } - - /* convert channels */ - - if (src_format->channels != dest_format->channels) { - buffer = pcm_convert_channels_float(&state->channels_buffer, - dest_format->channels, - src_format->channels, - buffer, size, &size); - if (buffer == NULL) { - g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %u to %u channels " - "is not implemented", - src_format->channels, - dest_format->channels); - return NULL; - } - } - - /* resample with float, because this is the best format for - libsamplerate */ - - if (src_format->sample_rate != dest_format->sample_rate) { - buffer = pcm_resample_float(&state->resample, - dest_format->channels, - src_format->sample_rate, - buffer, size, - dest_format->sample_rate, &size, - error_r); - if (buffer == NULL) - return NULL; - } - - *dest_size_r = size; - return buffer; -} - -const void * -pcm_convert(struct pcm_convert_state *state, - const struct audio_format *src_format, - const void *src, size_t src_size, - const struct audio_format *dest_format, - size_t *dest_size_r, - GError **error_r) -{ - struct audio_format float_format; - if (src_format->format == SAMPLE_FORMAT_DSD) { - size_t f_size; - const float *f = pcm_dsd_to_float(&state->dsd, - src_format->channels, - false, src, src_size, - &f_size); - if (f == NULL) { - g_set_error_literal(error_r, pcm_convert_quark(), 0, - "DSD to PCM conversion failed"); - return NULL; - } - - float_format = *src_format; - float_format.format = SAMPLE_FORMAT_FLOAT; - - src_format = &float_format; - src = f; - src_size = f_size; - } - - switch (dest_format->format) { - case SAMPLE_FORMAT_S16: - return pcm_convert_16(state, - src_format, src, src_size, - dest_format, dest_size_r, - error_r); - - case SAMPLE_FORMAT_S24_P32: - return pcm_convert_24(state, - src_format, src, src_size, - dest_format, dest_size_r, - error_r); - - case SAMPLE_FORMAT_S32: - return pcm_convert_32(state, - src_format, src, src_size, - dest_format, dest_size_r, - error_r); - - case SAMPLE_FORMAT_FLOAT: - return pcm_convert_float(state, - src_format, src, src_size, - dest_format, dest_size_r, - error_r); - - default: - g_set_error(error_r, pcm_convert_quark(), 0, - "PCM conversion to %s is not implemented", - sample_format_to_string(dest_format->format)); - return NULL; - } -} diff --git a/src/pcm_convert.h b/src/pcm_convert.h deleted file mode 100644 index 0668a2b6..00000000 --- a/src/pcm_convert.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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 PCM_CONVERT_H -#define PCM_CONVERT_H - -#include "pcm_dsd.h" -#include "pcm_resample.h" -#include "pcm_dither.h" -#include "pcm_buffer.h" - -#include - -struct audio_format; - -/** - * This object is statically allocated (within another struct), and - * holds buffer allocations and the state for all kinds of PCM - * conversions. - */ -struct pcm_convert_state { - struct pcm_dsd dsd; - - struct pcm_resample_state resample; - - struct pcm_dither dither; - - /** the buffer for converting the sample format */ - struct pcm_buffer format_buffer; - - /** the buffer for converting the channel count */ - struct pcm_buffer channels_buffer; -}; - -static inline GQuark -pcm_convert_quark(void) -{ - return g_quark_from_static_string("pcm_convert"); -} - -G_BEGIN_DECLS - -/** - * Initializes a pcm_convert_state object. - */ -void pcm_convert_init(struct pcm_convert_state *state); - -/** - * Deinitializes a pcm_convert_state object and frees allocated - * memory. - */ -void pcm_convert_deinit(struct pcm_convert_state *state); - -/** - * Reset the pcm_convert_state object. Use this at the boundary - * between two distinct songs and each time the format changes. - */ -void -pcm_convert_reset(struct pcm_convert_state *state); - -/** - * Converts PCM data between two audio formats. - * - * @param state an initialized pcm_convert_state object - * @param src_format the source audio format - * @param src the source PCM buffer - * @param src_size the size of #src in bytes - * @param dest_format the requested destination audio format - * @param dest_size_r returns the number of bytes of the destination buffer - * @param error_r location to store the error occurring, or NULL to - * ignore errors - * @return the destination buffer, or NULL on error - */ -const void * -pcm_convert(struct pcm_convert_state *state, - const struct audio_format *src_format, - const void *src, size_t src_size, - const struct audio_format *dest_format, - size_t *dest_size_r, - GError **error_r); - -G_END_DECLS - -#endif -- cgit v1.2.3