diff options
Diffstat (limited to 'src/filter')
-rw-r--r-- | src/filter/AutoConvertFilterPlugin.cxx | 6 | ||||
-rw-r--r-- | src/filter/ConvertFilterPlugin.cxx | 66 | ||||
-rw-r--r-- | src/filter/ConvertFilterPlugin.hxx | 6 | ||||
-rw-r--r-- | src/filter/NormalizeFilterPlugin.cxx | 1 | ||||
-rw-r--r-- | src/filter/ReplayGainFilterPlugin.cxx | 61 | ||||
-rw-r--r-- | src/filter/RouteFilterPlugin.cxx | 1 | ||||
-rw-r--r-- | src/filter/VolumeFilterPlugin.cxx | 65 |
7 files changed, 89 insertions, 117 deletions
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..e718844e7 100644 --- a/src/filter/ConvertFilterPlugin.cxx +++ b/src/filter/ConvertFilterPlugin.cxx @@ -28,7 +28,6 @@ #include "poison.h" #include <assert.h> -#include <string.h> class ConvertFilter final : public Filter { /** @@ -39,21 +38,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 +65,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 +107,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 +122,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 +139,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/filter/NormalizeFilterPlugin.cxx b/src/filter/NormalizeFilterPlugin.cxx index 6c4f6b0e5..93cca9fef 100644 --- a/src/filter/NormalizeFilterPlugin.cxx +++ b/src/filter/NormalizeFilterPlugin.cxx @@ -25,7 +25,6 @@ #include "AudioFormat.hxx" #include "AudioCompress/compress.h" -#include <assert.h> #include <string.h> class NormalizeFilter final : public Filter { diff --git a/src/filter/ReplayGainFilterPlugin.cxx b/src/filter/ReplayGainFilterPlugin.cxx index b2dcde4cc..998fda6f7 100644 --- a/src/filter/ReplayGainFilterPlugin.cxx +++ b/src/filter/ReplayGainFilterPlugin.cxx @@ -26,8 +26,9 @@ #include "ReplayGainInfo.hxx" #include "ReplayGainConfig.hxx" #include "MixerControl.hxx" -#include "pcm/PcmVolume.hxx" +#include "pcm/Volume.hxx" #include "pcm/PcmBuffer.hxx" +#include "util/ConstBuffer.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" #include "Log.hxx" @@ -55,8 +56,8 @@ class ReplayGainFilter final : public Filter { ReplayGainInfo info; /** - * The current volume, between 0 and a value that may or may not exceed - * #PCM_VOLUME_1. + * About the current volume: it is between 0 and a value that + * may or may not exceed #PCM_VOLUME_1. * * If the default value of true is used for replaygain_limit, the * application of the volume to the signal will never cause clipping. @@ -66,16 +67,11 @@ class ReplayGainFilter final : public Filter { * maintain a consistent audio level. Whether clipping will actually * occur depends on what value the user is using for replaygain_preamp. */ - unsigned volume; - - AudioFormat format; - - PcmBuffer buffer; + PcmVolume pv; public: ReplayGainFilter() - :mixer(nullptr), mode(REPLAY_GAIN_OFF), - volume(PCM_VOLUME_1) { + :mixer(nullptr), mode(REPLAY_GAIN_OFF) { info.Clear(); } @@ -125,6 +121,7 @@ public: void ReplayGainFilter::Update() { + unsigned volume = PCM_VOLUME_1; if (mode != REPLAY_GAIN_OFF) { const auto &tuple = info.tuples[mode]; float scale = tuple.CalculateScale(replay_gain_preamp, @@ -134,8 +131,9 @@ ReplayGainFilter::Update() "scale=%f\n", (double)scale); volume = pcm_float_to_volume(scale); - } else - volume = PCM_VOLUME_1; + } + + pv.SetVolume(volume); if (mixer != nullptr) { /* update the hardware mixer volume */ @@ -160,48 +158,25 @@ replay_gain_filter_init(gcc_unused const config_param ¶m, AudioFormat ReplayGainFilter::Open(AudioFormat &af, gcc_unused Error &error) { - format = af; + if (!pv.Open(af.format, error)) + return AudioFormat::Undefined(); - return format; + return af; } void ReplayGainFilter::Close() { - buffer.Clear(); + pv.Close(); } const void * ReplayGainFilter::FilterPCM(const void *src, size_t src_size, - size_t *dest_size_r, Error &error) + size_t *dest_size_r, gcc_unused Error &error) { - - *dest_size_r = src_size; - - if (volume == PCM_VOLUME_1) - /* optimized special case: 100% volume = no-op */ - return src; - - void *dest = buffer.Get(src_size); - if (volume <= 0) { - /* optimized special case: 0% volume = memset(0) */ - /* XXX is this valid for all sample formats? What - about floating point? */ - memset(dest, 0, src_size); - return dest; - } - - memcpy(dest, src, src_size); - - bool success = pcm_volume(dest, src_size, - format.format, - volume); - if (!success) { - error.Set(replay_gain_domain, "pcm_volume() has failed"); - return nullptr; - } - - return dest; + const auto dest = pv.Apply({src, src_size}); + *dest_size_r = dest.size; + return dest.data; } const struct filter_plugin replay_gain_filter_plugin = { diff --git a/src/filter/RouteFilterPlugin.cxx b/src/filter/RouteFilterPlugin.cxx index d9042c21f..d2dc2d563 100644 --- a/src/filter/RouteFilterPlugin.cxx +++ b/src/filter/RouteFilterPlugin.cxx @@ -43,7 +43,6 @@ #include "ConfigError.hxx" #include "ConfigData.hxx" #include "AudioFormat.hxx" -#include "CheckAudioFormat.hxx" #include "FilterPlugin.hxx" #include "FilterInternal.hxx" #include "FilterRegistry.hxx" diff --git a/src/filter/VolumeFilterPlugin.cxx b/src/filter/VolumeFilterPlugin.cxx index 1b663f6eb..8b9c6f8e9 100644 --- a/src/filter/VolumeFilterPlugin.cxx +++ b/src/filter/VolumeFilterPlugin.cxx @@ -22,9 +22,9 @@ #include "FilterPlugin.hxx" #include "FilterInternal.hxx" #include "FilterRegistry.hxx" -#include "pcm/PcmVolume.hxx" -#include "pcm/PcmBuffer.hxx" +#include "pcm/Volume.hxx" #include "AudioFormat.hxx" +#include "util/ConstBuffer.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" @@ -32,29 +32,15 @@ #include <string.h> class VolumeFilter final : public Filter { - /** - * The current volume, from 0 to #PCM_VOLUME_1. - */ - unsigned volume; - - AudioFormat format; - - PcmBuffer buffer; + PcmVolume pv; public: - VolumeFilter() - :volume(PCM_VOLUME_1) {} - unsigned GetVolume() const { - assert(volume <= PCM_VOLUME_1); - - return volume; + return pv.GetVolume(); } void SetVolume(unsigned _volume) { - assert(_volume <= PCM_VOLUME_1); - - volume = _volume; + pv.SetVolume(_volume); } virtual AudioFormat Open(AudioFormat &af, Error &error) override; @@ -73,50 +59,27 @@ volume_filter_init(gcc_unused const config_param ¶m, } AudioFormat -VolumeFilter::Open(AudioFormat &audio_format, gcc_unused Error &error) +VolumeFilter::Open(AudioFormat &audio_format, Error &error) { - format = audio_format; + if (!pv.Open(audio_format.format, error)) + return AudioFormat::Undefined(); - return format; + return audio_format; } void VolumeFilter::Close() { - buffer.Clear(); + pv.Close(); } const void * VolumeFilter::FilterPCM(const void *src, size_t src_size, - size_t *dest_size_r, Error &error) + size_t *dest_size_r, gcc_unused Error &error) { - *dest_size_r = src_size; - - if (volume >= PCM_VOLUME_1) - /* optimized special case: 100% volume = no-op */ - return src; - - void *dest = buffer.Get(src_size); - - if (volume <= 0) { - /* optimized special case: 0% volume = memset(0) */ - /* XXX is this valid for all sample formats? What - about floating point? */ - memset(dest, 0, src_size); - return dest; - } - - memcpy(dest, src, src_size); - - bool success = pcm_volume(dest, src_size, - format.format, - volume); - if (!success) { - error.Set(volume_domain, "pcm_volume() has failed"); - return NULL; - } - - return dest; + const auto dest = pv.Apply({src, src_size}); + *dest_size_r = dest.size; + return dest.data; } const struct filter_plugin volume_filter_plugin = { |