aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--doc/protocol.xml26
-rw-r--r--src/DecoderAPI.cxx53
-rw-r--r--src/DecoderInternal.cxx43
-rw-r--r--src/DecoderInternal.hxx46
-rw-r--r--src/DecoderThread.cxx9
-rw-r--r--src/OutputThread.cxx16
-rw-r--r--src/filter/AutoConvertFilterPlugin.cxx6
-rw-r--r--src/filter/ConvertFilterPlugin.cxx65
-rw-r--r--src/filter/ConvertFilterPlugin.hxx6
-rw-r--r--src/pcm/PcmConvert.cxx68
-rw-r--r--src/pcm/PcmConvert.hxx36
-rw-r--r--src/pcm/PcmResample.cxx8
-rw-r--r--src/pcm/PcmResampleFallback.cxx8
-rw-r--r--src/pcm/PcmResampleInternal.hxx4
-rw-r--r--test/run_convert.cxx12
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 &param,
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;
}