pcm/PcmConvert: eliminate Open() and Close()

Let the constructor and destructor do this.  This means that all users
have to be converted to allocate PcmConvert dynamically.
This commit is contained in:
Max Kellermann 2019-04-04 20:55:39 +02:00
parent 00b04468dc
commit e78d825059
9 changed files with 53 additions and 99 deletions

View File

@ -37,15 +37,16 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
DecoderBridge::DecoderBridge(DecoderControl &_dc, bool _initial_seek_pending,
std::unique_ptr<Tag> _tag) noexcept
:dc(_dc),
initial_seek_pending(_initial_seek_pending),
song_tag(std::move(_tag)) {}
DecoderBridge::~DecoderBridge() DecoderBridge::~DecoderBridge()
{ {
/* caller must flush the chunk */ /* caller must flush the chunk */
assert(current_chunk == nullptr); assert(current_chunk == nullptr);
if (convert != nullptr) {
convert->Close();
delete convert;
}
} }
bool bool
@ -255,11 +256,9 @@ DecoderBridge::Ready(const AudioFormat audio_format,
FormatDebug(decoder_domain, "converting to %s", FormatDebug(decoder_domain, "converting to %s",
ToString(dc.out_audio_format).c_str()); ToString(dc.out_audio_format).c_str());
convert = new PcmConvert();
try { try {
convert->Open(dc.in_audio_format, convert = std::make_unique<PcmConvert>(dc.in_audio_format,
dc.out_audio_format); dc.out_audio_format);
} catch (...) { } catch (...) {
error = std::current_exception(); error = std::current_exception();
} }

View File

@ -44,7 +44,7 @@ public:
* For converting input data to the configured audio format. * For converting input data to the configured audio format.
* nullptr means no conversion necessary. * nullptr means no conversion necessary.
*/ */
PcmConvert *convert = nullptr; std::unique_ptr<PcmConvert> convert;
/** /**
* The time stamp of the next data chunk, in seconds. * The time stamp of the next data chunk, in seconds.
@ -107,10 +107,7 @@ public:
std::exception_ptr error; std::exception_ptr error;
DecoderBridge(DecoderControl &_dc, bool _initial_seek_pending, DecoderBridge(DecoderControl &_dc, bool _initial_seek_pending,
std::unique_ptr<Tag> _tag) std::unique_ptr<Tag> _tag) noexcept;
:dc(_dc),
initial_seek_pending(_initial_seek_pending),
song_tag(std::move(_tag)) {}
~DecoderBridge(); ~DecoderBridge();

View File

@ -41,31 +41,25 @@ class ConvertFilter final : public Filter {
* This object is only "open" if #in_audio_format != * This object is only "open" if #in_audio_format !=
* #out_audio_format. * #out_audio_format.
*/ */
PcmConvert state; std::unique_ptr<PcmConvert> state;
public: public:
ConvertFilter(const AudioFormat &audio_format); ConvertFilter(const AudioFormat &audio_format);
~ConvertFilter();
void Set(const AudioFormat &_out_audio_format); void Set(const AudioFormat &_out_audio_format);
void Reset() noexcept override { void Reset() noexcept override {
if (IsActive()) if (state)
state.Reset(); state->Reset();
} }
ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override; ConstBuffer<void> FilterPCM(ConstBuffer<void> src) override;
ConstBuffer<void> Flush() override { ConstBuffer<void> Flush() override {
return IsActive() return state
? state.Flush() ? state->Flush()
: nullptr; : nullptr;
} }
private:
bool IsActive() const noexcept {
return out_audio_format != in_audio_format;
}
}; };
class PreparedConvertFilter final : public PreparedFilter { class PreparedConvertFilter final : public PreparedFilter {
@ -82,16 +76,17 @@ ConvertFilter::Set(const AudioFormat &_out_audio_format)
/* no change */ /* no change */
return; return;
if (IsActive()) { if (state) {
out_audio_format = in_audio_format; out_audio_format = in_audio_format;
state.Close(); state.reset();
} }
if (_out_audio_format == in_audio_format) if (_out_audio_format == in_audio_format)
/* optimized special case: no-op */ /* optimized special case: no-op */
return; return;
state.Open(in_audio_format, _out_audio_format); state = std::make_unique<PcmConvert>(in_audio_format,
_out_audio_format);
out_audio_format = _out_audio_format; out_audio_format = _out_audio_format;
} }
@ -110,17 +105,11 @@ PreparedConvertFilter::Open(AudioFormat &audio_format)
return std::make_unique<ConvertFilter>(audio_format); return std::make_unique<ConvertFilter>(audio_format);
} }
ConvertFilter::~ConvertFilter()
{
if (IsActive())
state.Close();
}
ConstBuffer<void> ConstBuffer<void>
ConvertFilter::FilterPCM(ConstBuffer<void> src) ConvertFilter::FilterPCM(ConstBuffer<void> src)
{ {
return IsActive() return state
? state.Convert(src) ? state->Convert(src)
/* optimized special case: no-op */ /* optimized special case: no-op */
: src; : src;
} }

View File

@ -18,17 +18,21 @@
*/ */
#include "DecoderClient.hxx" #include "DecoderClient.hxx"
#include "pcm/PcmConvert.hxx"
#include "input/InputStream.hxx" #include "input/InputStream.hxx"
#include "util/ConstBuffer.hxx" #include "util/ConstBuffer.hxx"
ChromaprintDecoderClient::ChromaprintDecoderClient() = default;
ChromaprintDecoderClient::~ChromaprintDecoderClient() noexcept = default;
void void
ChromaprintDecoderClient::PrintResult() ChromaprintDecoderClient::PrintResult()
{ {
if (!ready) if (!ready)
throw std::runtime_error("Decoding failed"); throw std::runtime_error("Decoding failed");
if (need_convert) { if (convert) {
auto flushed = convert.Flush(); auto flushed = convert->Flush();
auto data = ConstBuffer<int16_t>::FromVoid(flushed); auto data = ConstBuffer<int16_t>::FromVoid(flushed);
chromaprint.Feed(data.data, data.size); chromaprint.Feed(data.data, data.size);
} }
@ -48,8 +52,8 @@ ChromaprintDecoderClient::Ready(AudioFormat audio_format, bool, SignedSongTime)
const AudioFormat src_audio_format = audio_format; const AudioFormat src_audio_format = audio_format;
audio_format.format = SampleFormat::S16; audio_format.format = SampleFormat::S16;
convert.Open(src_audio_format, audio_format); convert = std::make_unique<PcmConvert>(src_audio_format,
need_convert = true; audio_format);
} }
chromaprint.Start(audio_format.sample_rate, audio_format.channels); chromaprint.Start(audio_format.sample_rate, audio_format.channels);
@ -70,8 +74,8 @@ ChromaprintDecoderClient::SubmitData(InputStream *,
ConstBuffer<void> src{_data, length}; ConstBuffer<void> src{_data, length};
ConstBuffer<int16_t> data; ConstBuffer<int16_t> data;
if (need_convert) { if (convert) {
auto result = convert.Convert(src); auto result = convert->Convert(src);
data = ConstBuffer<int16_t>::FromVoid(result); data = ConstBuffer<int16_t>::FromVoid(result);
} else } else
data = ConstBuffer<int16_t>::FromVoid(src); data = ConstBuffer<int16_t>::FromVoid(src);

View File

@ -22,17 +22,18 @@
#include "Context.hxx" #include "Context.hxx"
#include "decoder/Client.hxx" #include "decoder/Client.hxx"
#include "pcm/PcmConvert.hxx"
#include "thread/Mutex.hxx" #include "thread/Mutex.hxx"
#include <memory>
#include <stdint.h> #include <stdint.h>
class PcmConvert;
class ChromaprintDecoderClient : public DecoderClient { class ChromaprintDecoderClient : public DecoderClient {
bool ready = false; bool ready = false;
bool need_convert = false; std::unique_ptr<PcmConvert> convert;
PcmConvert convert;
Chromaprint::Context chromaprint; Chromaprint::Context chromaprint;
@ -41,10 +42,8 @@ class ChromaprintDecoderClient : public DecoderClient {
public: public:
Mutex mutex; Mutex mutex;
~ChromaprintDecoderClient() noexcept { ChromaprintDecoderClient();
if (need_convert) ~ChromaprintDecoderClient() noexcept;
convert.Close();
}
void PrintResult(); void PrintResult();

View File

@ -29,27 +29,12 @@ pcm_convert_global_init(const ConfigData &config)
pcm_resampler_global_init(config); pcm_resampler_global_init(config);
} }
PcmConvert::PcmConvert() noexcept PcmConvert::PcmConvert(const AudioFormat _src_format,
const AudioFormat _dest_format)
:src_format(_src_format), dest_format(_dest_format)
{ {
#ifndef NDEBUG assert(src_format.IsValid());
src_format.Clear(); assert(dest_format.IsValid());
dest_format.Clear();
#endif
}
PcmConvert::~PcmConvert() noexcept
{
assert(!src_format.IsValid());
assert(!dest_format.IsValid());
}
void
PcmConvert::Open(const AudioFormat _src_format, const AudioFormat _dest_format)
{
assert(!src_format.IsValid());
assert(!dest_format.IsValid());
assert(_src_format.IsValid());
assert(_dest_format.IsValid());
AudioFormat format = _src_format; AudioFormat format = _src_format;
if (format.format == SampleFormat::DSD) if (format.format == SampleFormat::DSD)
@ -90,13 +75,9 @@ PcmConvert::Open(const AudioFormat _src_format, const AudioFormat _dest_format)
throw; throw;
} }
} }
src_format = _src_format;
dest_format = _dest_format;
} }
void PcmConvert::~PcmConvert() noexcept
PcmConvert::Close() noexcept
{ {
if (enable_channels) if (enable_channels)
channels_converter.Close(); channels_converter.Close();
@ -108,11 +89,6 @@ PcmConvert::Close() noexcept
#ifdef ENABLE_DSD #ifdef ENABLE_DSD
dsd.Reset(); dsd.Reset();
#endif #endif
#ifndef NDEBUG
src_format.Clear();
dest_format.Clear();
#endif
} }
void void

View File

@ -47,27 +47,19 @@ class PcmConvert {
PcmFormatConverter format_converter; PcmFormatConverter format_converter;
PcmChannelsConverter channels_converter; PcmChannelsConverter channels_converter;
AudioFormat src_format, dest_format; const AudioFormat src_format, dest_format;
bool enable_resampler, enable_format, enable_channels; bool enable_resampler, enable_format, enable_channels;
public: public:
PcmConvert() noexcept;
/**
* Throws on error.
*/
PcmConvert(AudioFormat _src_format, AudioFormat _dest_format);
~PcmConvert() noexcept; ~PcmConvert() noexcept;
/**
* Prepare the object. Call Close() when done.
*
* Throws std::runtime_error on error.
*/
void Open(AudioFormat _src_format, AudioFormat _dest_format);
/**
* Close the object after it was prepared with Open(). After
* that, it may be reused by calling Open() again.
*/
void Close() noexcept;
/** /**
* Reset the filter's state, e.g. drop/flush buffers. * Reset the filter's state, e.g. drop/flush buffers.
*/ */

View File

@ -18,6 +18,7 @@
*/ */
#include "ConfigGlue.hxx" #include "ConfigGlue.hxx"
#include "pcm/PcmConvert.hxx"
#include "lib/chromaprint/DecoderClient.hxx" #include "lib/chromaprint/DecoderClient.hxx"
#include "event/Thread.hxx" #include "event/Thread.hxx"
#include "decoder/DecoderList.hxx" #include "decoder/DecoderList.hxx"

View File

@ -53,8 +53,7 @@ try {
const size_t in_frame_size = in_audio_format.GetFrameSize(); const size_t in_frame_size = in_audio_format.GetFrameSize();
PcmConvert state; PcmConvert state(in_audio_format, out_audio_format);
state.Open(in_audio_format, out_audio_format);
StaticFifoBuffer<uint8_t, 4096> buffer; StaticFifoBuffer<uint8_t, 4096> buffer;
@ -94,8 +93,6 @@ try {
output.size); output.size);
} }
state.Close();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} catch (...) { } catch (...) {
PrintException(std::current_exception()); PrintException(std::current_exception());