diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/DecoderAPI.cxx | 9 | ||||
-rw-r--r-- | src/DecoderInternal.cxx | 2 | ||||
-rw-r--r-- | src/DecoderInternal.hxx | 5 | ||||
-rw-r--r-- | src/PcmConvert.cxx (renamed from src/pcm_convert.c) | 170 | ||||
-rw-r--r-- | src/PcmConvert.hxx | 114 | ||||
-rw-r--r-- | src/filter/ConvertFilterPlugin.cxx | 17 | ||||
-rw-r--r-- | src/pcm_convert.h | 100 |
7 files changed, 214 insertions, 203 deletions
diff --git a/src/DecoderAPI.cxx b/src/DecoderAPI.cxx index b68af19bb..d86b93fb4 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 80f0adfd8..e390fdfd7 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 ae50a62e2..3423e3f95 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/pcm_convert.c b/src/PcmConvert.cxx index 1d8ae9575..175584c83 100644 --- a/src/pcm_convert.c +++ b/src/PcmConvert.cxx @@ -18,9 +18,13 @@ */ #include "config.h" -#include "pcm_convert.h" +#include "PcmConvert.hxx" + +extern "C" { #include "pcm_channels.h" #include "pcm_format.h" +} + #include "pcm_pack.h" #include "audio_format.h" @@ -32,58 +36,58 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "pcm" -void pcm_convert_init(struct pcm_convert_state *state) +PcmConvert::PcmConvert() { - memset(state, 0, sizeof(*state)); + memset(this, 0, sizeof(*this)); - pcm_dsd_init(&state->dsd); - pcm_resample_init(&state->resample); - pcm_dither_24_init(&state->dither); + pcm_dsd_init(&dsd); + pcm_resample_init(&resample); + pcm_dither_24_init(&dither); - pcm_buffer_init(&state->format_buffer); - pcm_buffer_init(&state->channels_buffer); + pcm_buffer_init(&format_buffer); + pcm_buffer_init(&channels_buffer); } -void pcm_convert_deinit(struct pcm_convert_state *state) +PcmConvert::~PcmConvert() { - pcm_dsd_deinit(&state->dsd); - pcm_resample_deinit(&state->resample); + pcm_dsd_deinit(&dsd); + pcm_resample_deinit(&resample); - pcm_buffer_deinit(&state->format_buffer); - pcm_buffer_deinit(&state->channels_buffer); + pcm_buffer_deinit(&format_buffer); + pcm_buffer_deinit(&channels_buffer); } void -pcm_convert_reset(struct pcm_convert_state *state) +PcmConvert::Reset() { - pcm_dsd_reset(&state->dsd); - pcm_resample_reset(&state->resample); + pcm_dsd_reset(&dsd); + pcm_resample_reset(&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) +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(&state->format_buffer, &state->dither, - src_format->format, src_buffer, src_size, + 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(src_format->format)); + sample_format_to_string(sample_format(src_format->format))); return NULL; } if (src_format->channels != dest_format->channels) { - buf = pcm_convert_channels_16(&state->channels_buffer, + buf = pcm_convert_channels_16(&channels_buffer, dest_format->channels, src_format->channels, buf, len, &len); @@ -98,7 +102,7 @@ pcm_convert_16(struct pcm_convert_state *state, } if (src_format->sample_rate != dest_format->sample_rate) { - buf = pcm_resample_16(&state->resample, + buf = pcm_resample_16(&resample, dest_format->channels, src_format->sample_rate, buf, len, dest_format->sample_rate, &len, @@ -111,29 +115,29 @@ pcm_convert_16(struct pcm_convert_state *state, 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) +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(&state->format_buffer, src_format->format, + 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(src_format->format)); + sample_format_to_string(sample_format(src_format->format))); return NULL; } if (src_format->channels != dest_format->channels) { - buf = pcm_convert_channels_24(&state->channels_buffer, + buf = pcm_convert_channels_24(&channels_buffer, dest_format->channels, src_format->channels, buf, len, &len); @@ -148,7 +152,7 @@ pcm_convert_24(struct pcm_convert_state *state, } if (src_format->sample_rate != dest_format->sample_rate) { - buf = pcm_resample_24(&state->resample, + buf = pcm_resample_24(&resample, dest_format->channels, src_format->sample_rate, buf, len, dest_format->sample_rate, &len, @@ -161,29 +165,29 @@ pcm_convert_24(struct pcm_convert_state *state, 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) +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(&state->format_buffer, src_format->format, + 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(src_format->format)); + sample_format_to_string(sample_format(src_format->format))); return NULL; } if (src_format->channels != dest_format->channels) { - buf = pcm_convert_channels_32(&state->channels_buffer, + buf = pcm_convert_channels_32(&channels_buffer, dest_format->channels, src_format->channels, buf, len, &len); @@ -198,7 +202,7 @@ pcm_convert_32(struct pcm_convert_state *state, } if (src_format->sample_rate != dest_format->sample_rate) { - buf = pcm_resample_32(&state->resample, + buf = pcm_resample_32(&resample, dest_format->channels, src_format->sample_rate, buf, len, dest_format->sample_rate, &len, @@ -211,34 +215,33 @@ pcm_convert_32(struct pcm_convert_state *state, 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) +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 = src_buffer; + 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(&state->format_buffer, - src_format->format, + 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(src_format->format)); + 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(&state->channels_buffer, + buffer = pcm_convert_channels_float(&channels_buffer, dest_format->channels, src_format->channels, buffer, size, &size); @@ -256,7 +259,7 @@ pcm_convert_float(struct pcm_convert_state *state, libsamplerate */ if (src_format->sample_rate != dest_format->sample_rate) { - buffer = pcm_resample_float(&state->resample, + buffer = pcm_resample_float(&resample, dest_format->channels, src_format->sample_rate, buffer, size, @@ -271,20 +274,19 @@ pcm_convert_float(struct pcm_convert_state *state, } 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) +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(&state->dsd, + const float *f = pcm_dsd_to_float(&dsd, src_format->channels, - false, src, src_size, - &f_size); + 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"); @@ -299,35 +301,31 @@ pcm_convert(struct pcm_convert_state *state, src_size = f_size; } - switch (dest_format->format) { + switch (sample_format(dest_format->format)) { case SAMPLE_FORMAT_S16: - return pcm_convert_16(state, - src_format, src, src_size, - dest_format, dest_size_r, - error_r); + return Convert16(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); + return Convert24(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); + return Convert32(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); + 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(dest_format->format)); + 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 000000000..bec30af45 --- /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 <glib.h> + +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 04f34842d..23c912b05 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<PcmConvert> 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.h b/src/pcm_convert.h deleted file mode 100644 index 0668a2b66..000000000 --- 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 <glib.h> - -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 |