diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | doc/protocol.xml | 26 | ||||
-rw-r--r-- | src/DecoderAPI.cxx | 53 | ||||
-rw-r--r-- | src/DecoderInternal.cxx | 43 | ||||
-rw-r--r-- | src/DecoderInternal.hxx | 46 | ||||
-rw-r--r-- | src/DecoderThread.cxx | 9 | ||||
-rw-r--r-- | src/OutputThread.cxx | 16 | ||||
-rw-r--r-- | src/filter/AutoConvertFilterPlugin.cxx | 6 | ||||
-rw-r--r-- | src/filter/ConvertFilterPlugin.cxx | 65 | ||||
-rw-r--r-- | src/filter/ConvertFilterPlugin.hxx | 6 | ||||
-rw-r--r-- | src/pcm/PcmConvert.cxx | 68 | ||||
-rw-r--r-- | src/pcm/PcmConvert.hxx | 36 | ||||
-rw-r--r-- | src/pcm/PcmResample.cxx | 8 | ||||
-rw-r--r-- | src/pcm/PcmResampleFallback.cxx | 8 | ||||
-rw-r--r-- | src/pcm/PcmResampleInternal.hxx | 4 | ||||
-rw-r--r-- | test/run_convert.cxx | 12 |
16 files changed, 268 insertions, 140 deletions
diff --git a/configure.ac b/configure.ac index b55c19e30..e2f2eba7e 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ(2.60) -AC_INIT(mpd, 0.18.5, musicpd-dev-team@lists.sourceforge.net) +AC_INIT(mpd, 0.19~git, musicpd-dev-team@lists.sourceforge.net) VERSION_MAJOR=0 VERSION_MINOR=18 diff --git a/doc/protocol.xml b/doc/protocol.xml index abc74e4e6..f72cd1afd 100644 --- a/doc/protocol.xml +++ b/doc/protocol.xml @@ -1952,6 +1952,32 @@ OK <para> Shows information about all outputs. </para> + <screen> +outputid: 0 +outputname: My ALSA Device +outputenabled: 0 +OK + </screen> + <para> + Return information: + </para> + <itemizedlist> + <listitem> + <para> + <varname>outputid</varname>: ID of the output. May change between executions + </para> + </listitem> + <listitem> + <para> + <varname>outputname</varname>: Name of the output. It can be any. + </para> + </listitem> + <listitem> + <para> + <varname>outputenabled</varname>: Status of the output. 0 if disabled, 1 if enabled. + </para> + </listitem> + </itemizedlist> </listitem> </varlistentry> </variablelist> diff --git a/src/DecoderAPI.cxx b/src/DecoderAPI.cxx index 4fea02bef..1494e3f80 100644 --- a/src/DecoderAPI.cxx +++ b/src/DecoderAPI.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "DecoderAPI.hxx" #include "DecoderError.hxx" +#include "pcm/PcmConvert.hxx" #include "AudioConfig.hxx" #include "ReplayGainConfig.hxx" #include "MusicChunk.hxx" @@ -47,6 +48,7 @@ decoder_initialized(Decoder &decoder, assert(dc.state == DecoderState::START); assert(dc.pipe != nullptr); + assert(decoder.convert == nullptr); assert(decoder.stream_tag == nullptr); assert(decoder.decoder_tag == nullptr); assert(!decoder.seeking); @@ -59,19 +61,28 @@ decoder_initialized(Decoder &decoder, dc.seekable = seekable; dc.total_time = total_time; - dc.Lock(); - dc.state = DecoderState::DECODE; - dc.client_cond.signal(); - dc.Unlock(); - FormatDebug(decoder_domain, "audio_format=%s, seekable=%s", audio_format_to_string(dc.in_audio_format, &af_string), seekable ? "true" : "false"); - if (dc.in_audio_format != dc.out_audio_format) + if (dc.in_audio_format != dc.out_audio_format) { FormatDebug(decoder_domain, "converting to %s", audio_format_to_string(dc.out_audio_format, &af_string)); + + decoder.convert = new PcmConvert(); + + Error error; + if (!decoder.convert->Open(dc.in_audio_format, + dc.out_audio_format, + error)) + decoder.error = std::move(error); + } + + dc.Lock(); + dc.state = DecoderState::DECODE; + dc.client_cond.signal(); + dc.Unlock(); } /** @@ -129,6 +140,10 @@ gcc_pure static DecoderCommand decoder_get_virtual_command(Decoder &decoder) { + if (decoder.error.IsDefined()) + /* an error has occurred: stop the decoder plugin */ + return DecoderCommand::STOP; + const DecoderControl &dc = decoder.dc; assert(dc.pipe != nullptr); @@ -312,12 +327,12 @@ do_send_tag(Decoder &decoder, const Tag &tag) if (decoder.chunk != nullptr) { /* there is a partial chunk - flush it, we want the tag in a new chunk */ - decoder_flush_chunk(decoder); + decoder.FlushChunk(); } assert(decoder.chunk == nullptr); - chunk = decoder_get_chunk(decoder); + chunk = decoder.GetChunk(); if (chunk == nullptr) { assert(decoder.dc.command != DecoderCommand::NONE); return decoder.dc.command; @@ -388,13 +403,13 @@ decoder_data(Decoder &decoder, return cmd; } - if (dc.in_audio_format != dc.out_audio_format) { + if (decoder.convert != nullptr) { + assert(dc.in_audio_format != dc.out_audio_format); + Error error; - data = decoder.conv_state.Convert(dc.in_audio_format, - data, length, - dc.out_audio_format, - &length, - error); + data = decoder.convert->Convert(data, length, + &length, + error); if (data == nullptr) { /* the PCM conversion has failed - stop playback, since we have no better way to @@ -402,13 +417,15 @@ decoder_data(Decoder &decoder, LogError(error); return DecoderCommand::STOP; } + } else { + assert(dc.in_audio_format == dc.out_audio_format); } while (length > 0) { struct music_chunk *chunk; bool full; - chunk = decoder_get_chunk(decoder); + chunk = decoder.GetChunk(); if (chunk == nullptr) { assert(dc.command != DecoderCommand::NONE); return dc.command; @@ -421,7 +438,7 @@ decoder_data(Decoder &decoder, kbit_rate); if (dest.IsNull()) { /* the chunk is full, flush it */ - decoder_flush_chunk(decoder); + decoder.FlushChunk(); continue; } @@ -440,7 +457,7 @@ decoder_data(Decoder &decoder, full = chunk->Expand(dc.out_audio_format, nbytes); if (full) { /* the chunk is full, flush it */ - decoder_flush_chunk(decoder); + decoder.FlushChunk(); } data = (const uint8_t *)data + nbytes; @@ -532,7 +549,7 @@ decoder_replay_gain(Decoder &decoder, /* flush the current chunk because the new replay gain values affect the following samples */ - decoder_flush_chunk(decoder); + decoder.FlushChunk(); } } else decoder.replay_gain_serial = 0; diff --git a/src/DecoderInternal.cxx b/src/DecoderInternal.cxx index d5f40ad48..38e54a36c 100644 --- a/src/DecoderInternal.cxx +++ b/src/DecoderInternal.cxx @@ -20,6 +20,7 @@ #include "config.h" #include "DecoderInternal.hxx" #include "DecoderControl.hxx" +#include "pcm/PcmConvert.hxx" #include "MusicPipe.hxx" #include "MusicBuffer.hxx" #include "MusicChunk.hxx" @@ -32,6 +33,11 @@ Decoder::~Decoder() /* caller must flush the chunk */ assert(chunk == nullptr); + if (convert != nullptr) { + convert->Close(); + delete convert; + } + delete song_tag; delete stream_tag; delete decoder_tag; @@ -51,24 +57,21 @@ need_chunks(DecoderControl &dc) } struct music_chunk * -decoder_get_chunk(Decoder &decoder) +Decoder::GetChunk() { - DecoderControl &dc = decoder.dc; DecoderCommand cmd; - if (decoder.chunk != nullptr) - return decoder.chunk; + if (chunk != nullptr) + return chunk; do { - decoder.chunk = dc.buffer->Allocate(); - if (decoder.chunk != nullptr) { - decoder.chunk->replay_gain_serial = - decoder.replay_gain_serial; - if (decoder.replay_gain_serial != 0) - decoder.chunk->replay_gain_info = - decoder.replay_gain_info; - - return decoder.chunk; + chunk = dc.buffer->Allocate(); + if (chunk != nullptr) { + chunk->replay_gain_serial = replay_gain_serial; + if (replay_gain_serial != 0) + chunk->replay_gain_info = replay_gain_info; + + return chunk; } dc.Lock(); @@ -80,18 +83,16 @@ decoder_get_chunk(Decoder &decoder) } void -decoder_flush_chunk(Decoder &decoder) +Decoder::FlushChunk() { - DecoderControl &dc = decoder.dc; - - assert(decoder.chunk != nullptr); + assert(chunk != nullptr); - if (decoder.chunk->IsEmpty()) - dc.buffer->Return(decoder.chunk); + if (chunk->IsEmpty()) + dc.buffer->Return(chunk); else - dc.pipe->Push(decoder.chunk); + dc.pipe->Push(chunk); - decoder.chunk = nullptr; + chunk = nullptr; dc.Lock(); if (dc.client_is_waiting) diff --git a/src/DecoderInternal.hxx b/src/DecoderInternal.hxx index 46069a561..87c6828d4 100644 --- a/src/DecoderInternal.hxx +++ b/src/DecoderInternal.hxx @@ -21,9 +21,10 @@ #define MPD_DECODER_INTERNAL_HXX #include "DecoderCommand.hxx" -#include "pcm/PcmConvert.hxx" #include "ReplayGainInfo.hxx" +#include "util/Error.hxx" +class PcmConvert; struct DecoderControl; struct InputStream; struct Tag; @@ -31,7 +32,11 @@ struct Tag; struct Decoder { DecoderControl &dc; - PcmConvert conv_state; + /** + * For converting input data to the configured audio format. + * nullptr means no conversion necessary. + */ + PcmConvert *convert; /** * The time stamp of the next data chunk, in seconds. @@ -83,8 +88,15 @@ struct Decoder { */ unsigned replay_gain_serial; + /** + * An error has occurred (in DecoderAPI.cxx), and the plugin + * will be asked to stop. + */ + Error error; + Decoder(DecoderControl &_dc, bool _initial_seek_pending, Tag *_tag) :dc(_dc), + convert(nullptr), timestamp(0), initial_seek_pending(_initial_seek_pending), initial_seek_running(false), @@ -95,23 +107,21 @@ struct Decoder { } ~Decoder(); -}; -/** - * Returns the current chunk the decoder writes to, or allocates a new - * chunk if there is none. - * - * @return the chunk, or NULL if we have received a decoder command - */ -struct music_chunk * -decoder_get_chunk(Decoder &decoder); + /** + * Returns the current chunk the decoder writes to, or allocates a new + * chunk if there is none. + * + * @return the chunk, or NULL if we have received a decoder command + */ + music_chunk *GetChunk(); -/** - * Flushes the current chunk. - * - * Caller must not lock the #DecoderControl object. - */ -void -decoder_flush_chunk(Decoder &decoder); + /** + * Flushes the current chunk. + * + * Caller must not lock the #DecoderControl object. + */ + void FlushChunk(); +}; #endif diff --git a/src/DecoderThread.cxx b/src/DecoderThread.cxx index 72fc3cfb4..2df131d19 100644 --- a/src/DecoderThread.cxx +++ b/src/DecoderThread.cxx @@ -356,11 +356,16 @@ decoder_run_song(DecoderControl &dc, /* flush the last chunk */ if (decoder.chunk != nullptr) - decoder_flush_chunk(decoder); + decoder.FlushChunk(); dc.Lock(); - if (ret) + if (decoder.error.IsDefined()) { + /* copy the Error from sruct Decoder to + DecoderControl */ + dc.state = DecoderState::ERROR; + dc.error = std::move(decoder.error); + } else if (ret) dc.state = DecoderState::STOP; else { dc.state = DecoderState::ERROR; diff --git a/src/OutputThread.cxx b/src/OutputThread.cxx index 30d3ba30f..dc81643f3 100644 --- a/src/OutputThread.cxx +++ b/src/OutputThread.cxx @@ -184,7 +184,15 @@ ao_open(struct audio_output *ao) return; } - convert_filter_set(ao->convert_filter, ao->out_audio_format); + if (!convert_filter_set(ao->convert_filter, ao->out_audio_format, + error)) { + FormatError(error, "Failed to convert for \"%s\" [%s]", + ao->name, ao->plugin->name); + + ao_filter_close(ao); + ao->fail_timer = g_timer_new(); + return; + } ao->open = true; @@ -233,7 +241,9 @@ ao_reopen_filter(struct audio_output *ao) ao_filter_close(ao); const AudioFormat filter_audio_format = ao_filter_open(ao, ao->in_audio_format, error); - if (!filter_audio_format.IsDefined()) { + if (!filter_audio_format.IsDefined() || + !convert_filter_set(ao->convert_filter, ao->out_audio_format, + error)) { FormatError(error, "Failed to open filter for \"%s\" [%s]", ao->name, ao->plugin->name); @@ -254,8 +264,6 @@ ao_reopen_filter(struct audio_output *ao) return; } - - convert_filter_set(ao->convert_filter, ao->out_audio_format); } static void diff --git a/src/filter/AutoConvertFilterPlugin.cxx b/src/filter/AutoConvertFilterPlugin.cxx index 918a16e53..44adc8a66 100644 --- a/src/filter/AutoConvertFilterPlugin.cxx +++ b/src/filter/AutoConvertFilterPlugin.cxx @@ -88,7 +88,11 @@ AutoConvertFilter::Open(AudioFormat &in_audio_format, Error &error) assert(audio_format2 == in_audio_format); - convert_filter_set(convert, child_audio_format); + if (!convert_filter_set(convert, child_audio_format, error)) { + delete convert; + filter->Close(); + return AudioFormat::Undefined(); + } } else /* no */ convert = nullptr; diff --git a/src/filter/ConvertFilterPlugin.cxx b/src/filter/ConvertFilterPlugin.cxx index 040f8426f..416b6e81a 100644 --- a/src/filter/ConvertFilterPlugin.cxx +++ b/src/filter/ConvertFilterPlugin.cxx @@ -39,21 +39,18 @@ class ConvertFilter final : public Filter { /** * The output audio format; the consumer of this plugin - * expects PCM data in this format. This defaults to - * #in_audio_format, and can be set with convert_filter_set(). + * expects PCM data in this format. + * + * If this is AudioFormat::Undefined(), then the #PcmConvert + * attribute is not open. This can mean that Set() has failed + * or that no conversion is necessary. */ AudioFormat out_audio_format; Manual<PcmConvert> state; public: - void Set(const AudioFormat &_out_audio_format) { - assert(in_audio_format.IsValid()); - assert(out_audio_format.IsValid()); - assert(_out_audio_format.IsValid()); - - out_audio_format = _out_audio_format; - } + bool Set(const AudioFormat &_out_audio_format, Error &error); virtual AudioFormat Open(AudioFormat &af, Error &error) override; virtual void Close() override; @@ -69,12 +66,40 @@ convert_filter_init(gcc_unused const config_param ¶m, return new ConvertFilter(); } +bool +ConvertFilter::Set(const AudioFormat &_out_audio_format, Error &error) +{ + assert(in_audio_format.IsValid()); + assert(_out_audio_format.IsValid()); + + if (_out_audio_format == out_audio_format) + /* no change */ + return true; + + if (out_audio_format.IsValid()) { + out_audio_format.Clear(); + state->Close(); + } + + if (_out_audio_format == in_audio_format) + /* optimized special case: no-op */ + return true; + + if (!state->Open(in_audio_format, _out_audio_format, error)) + return false; + + out_audio_format = _out_audio_format; + return true; +} + AudioFormat ConvertFilter::Open(AudioFormat &audio_format, gcc_unused Error &error) { assert(audio_format.IsValid()); - in_audio_format = out_audio_format = audio_format; + in_audio_format = audio_format; + out_audio_format.Clear(); + state.Construct(); return in_audio_format; @@ -83,6 +108,11 @@ ConvertFilter::Open(AudioFormat &audio_format, gcc_unused Error &error) void ConvertFilter::Close() { + assert(in_audio_format.IsValid()); + + if (out_audio_format.IsValid()) + state->Close(); + state.Destruct(); poison_undefined(&in_audio_format, sizeof(in_audio_format)); @@ -93,15 +123,15 @@ const void * ConvertFilter::FilterPCM(const void *src, size_t src_size, size_t *dest_size_r, Error &error) { - if (in_audio_format == out_audio_format) { + assert(in_audio_format.IsValid()); + + if (!out_audio_format.IsValid()) { /* optimized special case: no-op */ *dest_size_r = src_size; return src; } - return state->Convert(in_audio_format, - src, src_size, - out_audio_format, dest_size_r, + return state->Convert(src, src_size, dest_size_r, error); } @@ -110,10 +140,11 @@ const struct filter_plugin convert_filter_plugin = { convert_filter_init, }; -void -convert_filter_set(Filter *_filter, const AudioFormat out_audio_format) +bool +convert_filter_set(Filter *_filter, AudioFormat out_audio_format, + Error &error) { ConvertFilter *filter = (ConvertFilter *)_filter; - filter->Set(out_audio_format); + return filter->Set(out_audio_format, error); } diff --git a/src/filter/ConvertFilterPlugin.hxx b/src/filter/ConvertFilterPlugin.hxx index c814aaf49..f414e59bf 100644 --- a/src/filter/ConvertFilterPlugin.hxx +++ b/src/filter/ConvertFilterPlugin.hxx @@ -21,6 +21,7 @@ #define MPD_CONVERT_FILTER_PLUGIN_HXX class Filter; +class Error; struct AudioFormat; /** @@ -29,7 +30,8 @@ struct AudioFormat; * format switch is a violation of the filter API, this filter must be * the last in a chain. */ -void -convert_filter_set(Filter *filter, AudioFormat out_audio_format); +bool +convert_filter_set(Filter *filter, AudioFormat out_audio_format, + Error &error); #endif diff --git a/src/pcm/PcmConvert.cxx b/src/pcm/PcmConvert.cxx index 8eafe527c..cca2f701e 100644 --- a/src/pcm/PcmConvert.cxx +++ b/src/pcm/PcmConvert.cxx @@ -32,23 +32,48 @@ const Domain pcm_convert_domain("pcm_convert"); PcmConvert::PcmConvert() { +#ifndef NDEBUG + src_format.Clear(); + dest_format.Clear(); +#endif } PcmConvert::~PcmConvert() { + assert(!src_format.IsValid()); + assert(!dest_format.IsValid()); +} + +bool +PcmConvert::Open(AudioFormat _src_format, AudioFormat _dest_format, + gcc_unused Error &error) +{ + assert(!src_format.IsValid()); + assert(!dest_format.IsValid()); + assert(_src_format.IsValid()); + assert(_dest_format.IsValid()); + + src_format = _src_format; + dest_format = _dest_format; + + return true; } void -PcmConvert::Reset() +PcmConvert::Close() { dsd.Reset(); resampler.Reset(); + +#ifndef NDEBUG + src_format.Clear(); + dest_format.Clear(); +#endif } inline const int16_t * -PcmConvert::Convert16(const AudioFormat src_format, - const void *src_buffer, size_t src_size, - const AudioFormat dest_format, size_t *dest_size_r, +PcmConvert::Convert16(const void *src_buffer, size_t src_size, + size_t *dest_size_r, Error &error) { const int16_t *buf; @@ -96,9 +121,8 @@ PcmConvert::Convert16(const AudioFormat src_format, } inline const int32_t * -PcmConvert::Convert24(const AudioFormat src_format, - const void *src_buffer, size_t src_size, - const AudioFormat dest_format, size_t *dest_size_r, +PcmConvert::Convert24(const void *src_buffer, size_t src_size, + size_t *dest_size_r, Error &error) { const int32_t *buf; @@ -145,9 +169,8 @@ PcmConvert::Convert24(const AudioFormat src_format, } inline const int32_t * -PcmConvert::Convert32(const AudioFormat src_format, - const void *src_buffer, size_t src_size, - const AudioFormat dest_format, size_t *dest_size_r, +PcmConvert::Convert32(const void *src_buffer, size_t src_size, + size_t *dest_size_r, Error &error) { const int32_t *buf; @@ -194,9 +217,8 @@ PcmConvert::Convert32(const AudioFormat src_format, } inline const float * -PcmConvert::ConvertFloat(const AudioFormat src_format, - const void *src_buffer, size_t src_size, - const AudioFormat dest_format, size_t *dest_size_r, +PcmConvert::ConvertFloat(const void *src_buffer, size_t src_size, + size_t *dest_size_r, Error &error) { const float *buffer = (const float *)src_buffer; @@ -251,9 +273,7 @@ PcmConvert::ConvertFloat(const AudioFormat src_format, } const void * -PcmConvert::Convert(AudioFormat src_format, - const void *src, size_t src_size, - const AudioFormat dest_format, +PcmConvert::Convert(const void *src, size_t src_size, size_t *dest_size_r, Error &error) { @@ -279,23 +299,23 @@ PcmConvert::Convert(AudioFormat src_format, switch (dest_format.format) { case SampleFormat::S16: - return Convert16(src_format, src, src_size, - dest_format, dest_size_r, + return Convert16(src, src_size, + dest_size_r, error); case SampleFormat::S24_P32: - return Convert24(src_format, src, src_size, - dest_format, dest_size_r, + return Convert24(src, src_size, + dest_size_r, error); case SampleFormat::S32: - return Convert32(src_format, src, src_size, - dest_format, dest_size_r, + return Convert32(src, src_size, + dest_size_r, error); case SampleFormat::FLOAT: - return ConvertFloat(src_format, src, src_size, - dest_format, dest_size_r, + return ConvertFloat(src, src_size, + dest_size_r, error); default: diff --git a/src/pcm/PcmConvert.hxx b/src/pcm/PcmConvert.hxx index 40f785179..4bace1d36 100644 --- a/src/pcm/PcmConvert.hxx +++ b/src/pcm/PcmConvert.hxx @@ -24,10 +24,10 @@ #include "PcmDsd.hxx" #include "PcmResample.hxx" #include "PcmBuffer.hxx" +#include "AudioFormat.hxx" #include <stddef.h> -struct AudioFormat; class Error; /** @@ -48,17 +48,23 @@ class PcmConvert { /** the buffer for converting the channel count */ PcmBuffer channels_buffer; + AudioFormat src_format, dest_format; + public: PcmConvert(); ~PcmConvert(); + /** + * Prepare the object. Call Close() when done. + */ + bool Open(AudioFormat _src_format, AudioFormat _dest_format, + Error &error); /** - * Reset the pcm_convert_state object. Use this at the - * boundary between two distinct songs and each time the - * format changes. + * Close the object after it was prepared with Open(). After + * that, it may be reused by calling Open() again. */ - void Reset(); + void Close(); /** * Converts PCM data between two audio formats. @@ -72,34 +78,24 @@ public: * ignore errors * @return the destination buffer, or NULL on error */ - const void *Convert(AudioFormat src_format, - const void *src, size_t src_size, - AudioFormat dest_format, + const void *Convert(const void *src, size_t src_size, size_t *dest_size_r, Error &error); private: - const int16_t *Convert16(AudioFormat src_format, - const void *src_buffer, size_t src_size, - AudioFormat dest_format, + const int16_t *Convert16(const void *src_buffer, size_t src_size, size_t *dest_size_r, Error &error); - const int32_t *Convert24(AudioFormat src_format, - const void *src_buffer, size_t src_size, - AudioFormat dest_format, + const int32_t *Convert24(const void *src_buffer, size_t src_size, size_t *dest_size_r, Error &error); - const int32_t *Convert32(AudioFormat src_format, - const void *src_buffer, size_t src_size, - AudioFormat dest_format, + const int32_t *Convert32(const void *src_buffer, size_t src_size, size_t *dest_size_r, Error &error); - const float *ConvertFloat(AudioFormat src_format, - const void *src_buffer, size_t src_size, - AudioFormat dest_format, + const float *ConvertFloat(const void *src_buffer, size_t src_size, size_t *dest_size_r, Error &error); }; diff --git a/src/pcm/PcmResample.cxx b/src/pcm/PcmResample.cxx index 01f269ea9..b30e01407 100644 --- a/src/pcm/PcmResample.cxx +++ b/src/pcm/PcmResample.cxx @@ -101,7 +101,7 @@ PcmResampler::ResampleFloat(unsigned channels, unsigned src_rate, not do any math on the sample values, so this hack is possible: */ return (const float *) - pcm_resample_fallback_32(this, channels, + pcm_resample_fallback_32(buffer, channels, src_rate, (const int32_t *)src_buffer, src_size, dest_rate, dest_size_r); @@ -123,7 +123,7 @@ PcmResampler::Resample16(unsigned channels, (void)error_r; #endif - return pcm_resample_fallback_16(this, channels, + return pcm_resample_fallback_16(buffer, channels, src_rate, src_buffer, src_size, dest_rate, dest_size_r); } @@ -144,7 +144,7 @@ PcmResampler::Resample32(unsigned channels, unsigned src_rate, (void)error_r; #endif - return pcm_resample_fallback_32(this, channels, + return pcm_resample_fallback_32(buffer, channels, src_rate, src_buffer, src_size, dest_rate, dest_size_r); } @@ -167,7 +167,7 @@ PcmResampler::Resample24(unsigned channels, unsigned src_rate, /* reuse the 32 bit code - the resampler code doesn't care if the upper 8 bits are actually used */ - return pcm_resample_fallback_32(this, channels, + return pcm_resample_fallback_32(buffer, channels, src_rate, src_buffer, src_size, dest_rate, dest_size_r); } diff --git a/src/pcm/PcmResampleFallback.cxx b/src/pcm/PcmResampleFallback.cxx index a62cd64f7..ca92e5a83 100644 --- a/src/pcm/PcmResampleFallback.cxx +++ b/src/pcm/PcmResampleFallback.cxx @@ -24,7 +24,7 @@ /* resampling code blatantly ripped from ESD */ const int16_t * -pcm_resample_fallback_16(PcmResampler *state, +pcm_resample_fallback_16(PcmBuffer &buffer, unsigned channels, unsigned src_rate, const int16_t *src_buffer, size_t src_size, @@ -37,7 +37,7 @@ pcm_resample_fallback_16(PcmResampler *state, (src_frames * dest_rate + src_rate - 1) / src_rate; unsigned dest_samples = dest_frames * channels; size_t dest_size = dest_samples * sizeof(*src_buffer); - int16_t *dest_buffer = (int16_t *)state->buffer.Get(dest_size); + int16_t *dest_buffer = (int16_t *)buffer.Get(dest_size); assert((src_size % (sizeof(*src_buffer) * channels)) == 0); @@ -65,7 +65,7 @@ pcm_resample_fallback_16(PcmResampler *state, } const int32_t * -pcm_resample_fallback_32(PcmResampler *state, +pcm_resample_fallback_32(PcmBuffer &buffer, unsigned channels, unsigned src_rate, const int32_t *src_buffer, size_t src_size, @@ -78,7 +78,7 @@ pcm_resample_fallback_32(PcmResampler *state, (src_frames * dest_rate + src_rate - 1) / src_rate; unsigned dest_samples = dest_frames * channels; size_t dest_size = dest_samples * sizeof(*src_buffer); - int32_t *dest_buffer = (int32_t *)state->buffer.Get(dest_size); + int32_t *dest_buffer = (int32_t *)buffer.Get(dest_size); assert((src_size % (sizeof(*src_buffer) * channels)) == 0); diff --git a/src/pcm/PcmResampleInternal.hxx b/src/pcm/PcmResampleInternal.hxx index 5090c13d1..94cef94ff 100644 --- a/src/pcm/PcmResampleInternal.hxx +++ b/src/pcm/PcmResampleInternal.hxx @@ -81,7 +81,7 @@ pcm_resample_lsr_24(PcmResampler *state, #endif const int16_t * -pcm_resample_fallback_16(PcmResampler *state, +pcm_resample_fallback_16(PcmBuffer &buffer, unsigned channels, unsigned src_rate, const int16_t *src_buffer, size_t src_size, @@ -89,7 +89,7 @@ pcm_resample_fallback_16(PcmResampler *state, size_t *dest_size_r); const int32_t * -pcm_resample_fallback_32(PcmResampler *state, +pcm_resample_fallback_32(PcmBuffer &buffer, unsigned channels, unsigned src_rate, const int32_t *src_buffer, diff --git a/test/run_convert.cxx b/test/run_convert.cxx index 0e873a3b3..d9a1b7f08 100644 --- a/test/run_convert.cxx +++ b/test/run_convert.cxx @@ -90,6 +90,11 @@ int main(int argc, char **argv) const size_t in_frame_size = in_audio_format.GetFrameSize(); PcmConvert state; + if (!state.Open(in_audio_format, out_audio_format_mask, error)) { + g_printerr("Failed to open PcmConvert: %s\n", + error.GetMessage()); + return EXIT_FAILURE; + } FifoBuffer<uint8_t, 4096> buffer; @@ -115,9 +120,10 @@ int main(int argc, char **argv) buffer.Consume(src.size); size_t length; - output = state.Convert(in_audio_format, src.data, src.size, - out_audio_format, &length, error); + output = state.Convert(src.data, src.size, + &length, error); if (output == NULL) { + state.Close(); g_printerr("Failed to convert: %s\n", error.GetMessage()); return 2; } @@ -125,5 +131,7 @@ int main(int argc, char **argv) gcc_unused ssize_t ignored = write(1, output, length); } + state.Close(); + return EXIT_SUCCESS; } |