pcm/Convert: migrate from class Error to C++ exceptions

This commit is contained in:
Max Kellermann 2016-09-05 12:19:20 +02:00
parent 860064c812
commit ae1eb9ccde
27 changed files with 197 additions and 305 deletions

View File

@ -520,10 +520,7 @@ try {
archive_plugin_init_all();
#endif
if (!pcm_convert_global_init(error)) {
LogError(error);
return EXIT_FAILURE;
}
pcm_convert_global_init();
decoder_plugin_init_all();

View File

@ -73,11 +73,12 @@ decoder_initialized(Decoder &decoder,
decoder.convert = new PcmConvert();
Error error;
if (!decoder.convert->Open(dc.in_audio_format,
dc.out_audio_format,
error))
decoder.error = std::make_exception_ptr(std::move(error));
try {
decoder.convert->Open(dc.in_audio_format,
dc.out_audio_format);
} catch (...) {
decoder.error = std::current_exception();
}
}
const ScopeLock protect(dc.mutex);
@ -484,19 +485,17 @@ decoder_data(Decoder &decoder,
if (decoder.convert != nullptr) {
assert(dc.in_audio_format != dc.out_audio_format);
Error error;
auto result = decoder.convert->Convert({data, length},
error);
if (data == nullptr) {
try {
auto result = decoder.convert->Convert({data, length});
data = result.data;
length = result.size;
} catch (const std::runtime_error &e) {
/* the PCM conversion has failed - stop
playback, since we have no better way to
bail out */
LogError(error);
LogError(e);
return DecoderCommand::STOP;
}
data = result.data;
length = result.size;
} else {
assert(dc.in_audio_format == dc.out_audio_format);
}

View File

@ -25,7 +25,6 @@
#include "pcm/PcmConvert.hxx"
#include "util/Manual.hxx"
#include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
#include "AudioFormat.hxx"
#include "poison.h"
@ -88,9 +87,7 @@ ConvertFilter::Set(const AudioFormat &_out_audio_format)
/* optimized special case: no-op */
return;
Error error;
if (!state.Open(in_audio_format, _out_audio_format, error))
throw std::runtime_error(error.GetMessage());
state.Open(in_audio_format, _out_audio_format);
out_audio_format = _out_audio_format;
}
@ -125,12 +122,7 @@ ConvertFilter::FilterPCM(ConstBuffer<void> src)
/* optimized special case: no-op */
return src;
Error error;
auto result = state.Convert(src, error);
if (result.IsNull())
throw std::runtime_error(error.GetMessage());
return result;
return state.Convert(src);
}
const struct filter_plugin convert_filter_plugin = {

View File

@ -76,9 +76,7 @@ public:
mixer(_mixer), base(_base), mode(REPLAY_GAIN_OFF) {
info.Clear();
Error error;
if (!pv.Open(out_audio_format.format, error))
throw std::runtime_error(error.GetMessage());
pv.Open(out_audio_format.format);
}
void SetInfo(const ReplayGainInfo *_info) {

View File

@ -25,7 +25,6 @@
#include "pcm/Volume.hxx"
#include "AudioFormat.hxx"
#include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
#include <stdexcept>
@ -35,9 +34,7 @@ class VolumeFilter final : public Filter {
public:
explicit VolumeFilter(const AudioFormat &audio_format)
:Filter(audio_format) {
Error error;
if (!pv.Open(out_audio_format.format, error))
throw std::runtime_error(error.GetMessage());
pv.Open(out_audio_format.format);
}
unsigned GetVolume() const {

View File

@ -22,14 +22,13 @@
#include "PcmChannels.hxx"
#include "Domain.hxx"
#include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
#include "util/RuntimeError.hxx"
#include <assert.h>
bool
void
PcmChannelsConverter::Open(SampleFormat _format,
unsigned _src_channels, unsigned _dest_channels,
gcc_unused Error &error)
unsigned _src_channels, unsigned _dest_channels)
{
assert(_format != SampleFormat::UNDEFINED);
@ -41,16 +40,13 @@ PcmChannelsConverter::Open(SampleFormat _format,
break;
default:
error.Format(pcm_domain,
"PCM channel conversion for %s is not implemented",
sample_format_to_string(_format));
return false;
throw FormatRuntimeError("PCM channel conversion for %s is not implemented",
sample_format_to_string(_format));
}
format = _format;
src_channels = _src_channels;
dest_channels = _dest_channels;
return true;
}
void
@ -62,7 +58,7 @@ PcmChannelsConverter::Close()
}
ConstBuffer<void>
PcmChannelsConverter::Convert(ConstBuffer<void> src, gcc_unused Error &error)
PcmChannelsConverter::Convert(ConstBuffer<void> src)
{
switch (format) {
case SampleFormat::UNDEFINED:

View File

@ -28,7 +28,6 @@
#include <assert.h>
#endif
class Error;
template<typename T> struct ConstBuffer;
/**
@ -53,15 +52,14 @@ public:
/**
* Opens the object, prepare for Convert().
*
* Throws std::runtime_error on error.
*
* @param format the sample format
* @param src_channels the number of source channels
* @param dest_channels the number of destination channels
* @param error location to store the error
* @return true on success
*/
bool Open(SampleFormat format,
unsigned src_channels, unsigned dest_channels,
Error &error);
void Open(SampleFormat format,
unsigned src_channels, unsigned dest_channels);
/**
* Closes the object. After that, you may call Open() again.
@ -71,13 +69,13 @@ public:
/**
* Convert a block of PCM data.
*
* Throws std::runtime_error on error.
*
* @param src the input buffer
* @param error location to store the error
* @return the destination buffer on success,
* ConstBuffer::Null() on error
* @return the destination buffer
*/
gcc_pure
ConstBuffer<void> Convert(ConstBuffer<void> src, Error &error);
ConstBuffer<void> Convert(ConstBuffer<void> src);
};
#endif

View File

@ -25,7 +25,7 @@
#include "config/ConfigError.hxx"
#include "config/Block.hxx"
#include "config/Param.hxx"
#include "util/Error.hxx"
#include "util/RuntimeError.hxx"
#ifdef ENABLE_LIBSAMPLERATE
#include "LibsamplerateResampler.hxx"
@ -112,7 +112,7 @@ MigrateResamplerConfig(const config_param *param, ConfigBlock &buffer)
}
static const ConfigBlock *
GetResamplerConfig(ConfigBlock &buffer, Error &error)
GetResamplerConfig(ConfigBlock &buffer)
{
const auto *old_param =
config_get_param(ConfigOption::SAMPLERATE_CONVERTER);
@ -120,49 +120,39 @@ GetResamplerConfig(ConfigBlock &buffer, Error &error)
if (block == nullptr)
return MigrateResamplerConfig(old_param, buffer);
if (old_param != nullptr) {
error.Format(config_domain,
"Cannot use both 'resampler' (line %d) and 'samplerate_converter' (line %d)",
block->line, old_param->line);
return nullptr;
}
if (old_param != nullptr)
throw FormatRuntimeError("Cannot use both 'resampler' (line %d) and 'samplerate_converter' (line %d)",
block->line, old_param->line);
return block;
}
bool
pcm_resampler_global_init(Error &error)
void
pcm_resampler_global_init()
{
ConfigBlock buffer;
const auto *block = GetResamplerConfig(buffer, error);
if (block == nullptr)
return false;
const auto *block = GetResamplerConfig(buffer);
const char *plugin_name = block->GetBlockValue("plugin");
if (plugin_name == nullptr) {
error.Format(config_domain,
"'plugin' missing in line %d", block->line);
return false;
}
if (plugin_name == nullptr)
throw FormatRuntimeError("'plugin' missing in line %d",
block->line);
if (strcmp(plugin_name, "internal") == 0) {
selected_resampler = SelectedResampler::FALLBACK;
return true;
#ifdef ENABLE_SOXR
} else if (strcmp(plugin_name, "soxr") == 0) {
selected_resampler = SelectedResampler::SOXR;
return pcm_resample_soxr_global_init(*block, error);
pcm_resample_soxr_global_init(*block);
#endif
#ifdef ENABLE_LIBSAMPLERATE
} else if (strcmp(plugin_name, "libsamplerate") == 0) {
selected_resampler = SelectedResampler::LIBSAMPLERATE;
return pcm_resample_lsr_global_init(*block, error);
pcm_resample_lsr_global_init(*block);
#endif
} else {
error.Format(config_domain,
"No such resampler plugin: %s",
plugin_name);
return false;
throw FormatRuntimeError("No such resampler plugin: %s",
plugin_name);
}
}

View File

@ -22,11 +22,10 @@
#include "check.h"
class Error;
class PcmResampler;
bool
pcm_resampler_global_init(Error &error);
void
pcm_resampler_global_init();
/**
* Create a #PcmResampler instance from the implementation class

View File

@ -23,8 +23,7 @@
#include <assert.h>
AudioFormat
FallbackPcmResampler::Open(AudioFormat &af, unsigned new_sample_rate,
gcc_unused Error &error)
FallbackPcmResampler::Open(AudioFormat &af, unsigned new_sample_rate)
{
assert(af.IsValid());
assert(audio_valid_sample_rate(new_sample_rate));
@ -116,7 +115,7 @@ pcm_resample_fallback_void(PcmBuffer &buffer,
}
ConstBuffer<void>
FallbackPcmResampler::Resample(ConstBuffer<void> src, gcc_unused Error &error)
FallbackPcmResampler::Resample(ConstBuffer<void> src)
{
switch (format.format) {
case SampleFormat::UNDEFINED:

View File

@ -36,11 +36,9 @@ class FallbackPcmResampler final : public PcmResampler {
PcmBuffer buffer;
public:
virtual AudioFormat Open(AudioFormat &af, unsigned new_sample_rate,
Error &error) override;
virtual void Close() override;
virtual ConstBuffer<void> Resample(ConstBuffer<void> src,
Error &error) override;
AudioFormat Open(AudioFormat &af, unsigned new_sample_rate) override;
void Close() override;
ConstBuffer<void> Resample(ConstBuffer<void> src) override;
};
#endif

View File

@ -20,15 +20,13 @@
#include "config.h"
#include "FormatConverter.hxx"
#include "PcmFormat.hxx"
#include "Domain.hxx"
#include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
#include "util/RuntimeError.hxx"
#include <assert.h>
bool
PcmFormatConverter::Open(SampleFormat _src_format, SampleFormat _dest_format,
Error &error)
void
PcmFormatConverter::Open(SampleFormat _src_format, SampleFormat _dest_format)
{
assert(_src_format != SampleFormat::UNDEFINED);
assert(_dest_format != SampleFormat::UNDEFINED);
@ -40,11 +38,9 @@ PcmFormatConverter::Open(SampleFormat _src_format, SampleFormat _dest_format,
case SampleFormat::S8:
case SampleFormat::DSD:
error.Format(pcm_domain,
"PCM conversion from %s to %s is not implemented",
sample_format_to_string(_src_format),
sample_format_to_string(_dest_format));
return false;
throw FormatRuntimeError("PCM conversion from %s to %s is not implemented",
sample_format_to_string(_src_format),
sample_format_to_string(_dest_format));
case SampleFormat::S16:
case SampleFormat::S24_P32:
@ -55,7 +51,6 @@ PcmFormatConverter::Open(SampleFormat _src_format, SampleFormat _dest_format,
src_format = _src_format;
dest_format = _dest_format;
return true;
}
void
@ -68,7 +63,7 @@ PcmFormatConverter::Close()
}
ConstBuffer<void>
PcmFormatConverter::Convert(ConstBuffer<void> src, gcc_unused Error &error)
PcmFormatConverter::Convert(ConstBuffer<void> src)
{
switch (dest_format) {
case SampleFormat::UNDEFINED:

View File

@ -29,7 +29,6 @@
#include <assert.h>
#endif
class Error;
template<typename T> struct ConstBuffer;
/**
@ -56,13 +55,12 @@ public:
/**
* Opens the object, prepare for Convert().
*
* Throws std::runtime_error on error.
*
* @param src_format the sample format of incoming data
* @param dest_format the sample format of outgoing data
* @param error location to store the error
* @return true on success
*/
bool Open(SampleFormat src_format, SampleFormat dest_format,
Error &error);
void Open(SampleFormat src_format, SampleFormat dest_format);
/**
* Closes the object. After that, you may call Open() again.
@ -72,13 +70,13 @@ public:
/**
* Convert a block of PCM data.
*
* Throws std::runtime_error on error.
*
* @param src the input buffer
* @param error location to store the error
* @return the destination buffer on success,
* ConstBuffer::Null() on error
* @return the destination buffer
*/
gcc_pure
ConstBuffer<void> Convert(ConstBuffer<void> src, Error &error);
ConstBuffer<void> Convert(ConstBuffer<void> src);
};
#endif

View File

@ -32,33 +32,28 @@ GluePcmResampler::~GluePcmResampler()
delete resampler;
}
bool
GluePcmResampler::Open(AudioFormat src_format, unsigned new_sample_rate,
Error &error)
void
GluePcmResampler::Open(AudioFormat src_format, unsigned new_sample_rate)
{
assert(src_format.IsValid());
assert(audio_valid_sample_rate(new_sample_rate));
AudioFormat requested_format = src_format;
AudioFormat dest_format = resampler->Open(requested_format,
new_sample_rate,
error);
if (!dest_format.IsValid())
return false;
new_sample_rate);
assert(dest_format.IsValid());
assert(requested_format.channels == src_format.channels);
assert(dest_format.channels == src_format.channels);
assert(dest_format.sample_rate == new_sample_rate);
if (requested_format.format != src_format.format &&
!format_converter.Open(src_format.format, requested_format.format,
error))
return false;
if (requested_format.format != src_format.format)
format_converter.Open(src_format.format,
requested_format.format);
src_sample_format = src_format.format;
requested_sample_format = requested_format.format;
output_sample_format = dest_format.format;
return true;
}
void
@ -71,15 +66,12 @@ GluePcmResampler::Close()
}
ConstBuffer<void>
GluePcmResampler::Resample(ConstBuffer<void> src, Error &error)
GluePcmResampler::Resample(ConstBuffer<void> src)
{
assert(!src.IsNull());
if (requested_sample_format != src_sample_format) {
src = format_converter.Convert(src, error);
if (src.IsNull())
return nullptr;
}
if (requested_sample_format != src_sample_format)
src = format_converter.Convert(src);
return resampler->Resample(src, error);
return resampler->Resample(src);
}

View File

@ -24,7 +24,6 @@
#include "AudioFormat.hxx"
#include "FormatConverter.hxx"
class Error;
class PcmResampler;
template<typename T> struct ConstBuffer;
@ -49,15 +48,14 @@ public:
GluePcmResampler();
~GluePcmResampler();
bool Open(AudioFormat src_format, unsigned new_sample_rate,
Error &error);
void Open(AudioFormat src_format, unsigned new_sample_rate);
void Close();
SampleFormat GetOutputSampleFormat() const {
return output_sample_format;
}
ConstBuffer<void> Resample(ConstBuffer<void> src, Error &error);
ConstBuffer<void> Resample(ConstBuffer<void> src);
};
#endif

View File

@ -21,7 +21,7 @@
#include "LibsamplerateResampler.hxx"
#include "config/Block.hxx"
#include "util/ASCII.hxx"
#include "util/Error.hxx"
#include "util/RuntimeError.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
@ -63,26 +63,21 @@ lsr_parse_converter(const char *s)
return false;
}
bool
pcm_resample_lsr_global_init(const ConfigBlock &block, Error &error)
void
pcm_resample_lsr_global_init(const ConfigBlock &block)
{
const char *converter = block.GetBlockValue("type", "2");
if (!lsr_parse_converter(converter)) {
error.Format(libsamplerate_domain,
"unknown samplerate converter '%s'", converter);
return false;
}
if (!lsr_parse_converter(converter))
throw FormatRuntimeError("unknown samplerate converter '%s'",
converter);
FormatDebug(libsamplerate_domain,
"libsamplerate converter '%s'",
src_get_name(lsr_converter));
return true;
}
AudioFormat
LibsampleratePcmResampler::Open(AudioFormat &af, unsigned new_sample_rate,
Error &error)
LibsampleratePcmResampler::Open(AudioFormat &af, unsigned new_sample_rate)
{
assert(af.IsValid());
assert(audio_valid_sample_rate(new_sample_rate));
@ -96,12 +91,9 @@ LibsampleratePcmResampler::Open(AudioFormat &af, unsigned new_sample_rate,
int src_error;
state = src_new(lsr_converter, channels, &src_error);
if (!state) {
error.Format(libsamplerate_domain, src_error,
"libsamplerate initialization has failed: %s",
src_strerror(src_error));
return AudioFormat::Undefined();
}
if (!state)
throw FormatRuntimeError("libsamplerate initialization has failed: %s",
src_strerror(src_error));
memset(&data, 0, sizeof(data));
@ -122,22 +114,8 @@ LibsampleratePcmResampler::Close()
state = src_delete(state);
}
static bool
src_process(SRC_STATE *state, SRC_DATA *data, Error &error)
{
int result = src_process(state, data);
if (result != 0) {
error.Format(libsamplerate_domain, result,
"libsamplerate has failed: %s",
src_strerror(result));
return false;
}
return true;
}
inline ConstBuffer<float>
LibsampleratePcmResampler::Resample2(ConstBuffer<float> src, Error &error)
LibsampleratePcmResampler::Resample2(ConstBuffer<float> src)
{
assert(src.size % channels == 0);
@ -151,15 +129,17 @@ LibsampleratePcmResampler::Resample2(ConstBuffer<float> src, Error &error)
data.input_frames = src_frames;
data.output_frames = dest_frames;
if (!src_process(state, &data, error))
return nullptr;
int result = src_process(state, &data);
if (result != 0)
throw FormatRuntimeError("libsamplerate has failed: %s",
src_strerror(result));
return ConstBuffer<float>(data.data_out,
data.output_frames_gen * channels);
}
ConstBuffer<void>
LibsampleratePcmResampler::Resample(ConstBuffer<void> src, Error &error)
LibsampleratePcmResampler::Resample(ConstBuffer<void> src)
{
return Resample2(ConstBuffer<float>::FromVoid(src), error).ToVoid();
return Resample2(ConstBuffer<float>::FromVoid(src)).ToVoid();
}

View File

@ -42,17 +42,15 @@ class LibsampleratePcmResampler final : public PcmResampler {
PcmBuffer buffer;
public:
virtual AudioFormat Open(AudioFormat &af, unsigned new_sample_rate,
Error &error) override;
virtual void Close() override;
virtual ConstBuffer<void> Resample(ConstBuffer<void> src,
Error &error) override;
AudioFormat Open(AudioFormat &af, unsigned new_sample_rate) override;
void Close() override;
ConstBuffer<void> Resample(ConstBuffer<void> src) override;
private:
ConstBuffer<float> Resample2(ConstBuffer<float> src, Error &error);
ConstBuffer<float> Resample2(ConstBuffer<float> src);
};
bool
pcm_resample_lsr_global_init(const ConfigBlock &block, Error &error);
void
pcm_resample_lsr_global_init(const ConfigBlock &block);
#endif

View File

@ -22,15 +22,14 @@
#include "Domain.hxx"
#include "ConfiguredResampler.hxx"
#include "AudioFormat.hxx"
#include "util/Error.hxx"
#include "util/ConstBuffer.hxx"
#include <assert.h>
bool
pcm_convert_global_init(Error &error)
void
pcm_convert_global_init()
{
return pcm_resampler_global_init(error);
pcm_resampler_global_init();
}
PcmConvert::PcmConvert()
@ -47,9 +46,8 @@ PcmConvert::~PcmConvert()
assert(!dest_format.IsValid());
}
bool
PcmConvert::Open(const AudioFormat _src_format, const AudioFormat _dest_format,
Error &error)
void
PcmConvert::Open(const AudioFormat _src_format, const AudioFormat _dest_format)
{
assert(!src_format.IsValid());
assert(!dest_format.IsValid());
@ -62,39 +60,42 @@ PcmConvert::Open(const AudioFormat _src_format, const AudioFormat _dest_format,
enable_resampler = format.sample_rate != _dest_format.sample_rate;
if (enable_resampler) {
if (!resampler.Open(format, _dest_format.sample_rate, error))
return false;
resampler.Open(format, _dest_format.sample_rate);
format.format = resampler.GetOutputSampleFormat();
format.sample_rate = _dest_format.sample_rate;
}
enable_format = format.format != _dest_format.format;
if (enable_format &&
!format_converter.Open(format.format, _dest_format.format,
error)) {
if (enable_resampler)
resampler.Close();
return false;
if (enable_format) {
try {
format_converter.Open(format.format,
_dest_format.format);
} catch (...) {
if (enable_resampler)
resampler.Close();
throw;
}
}
format.format = _dest_format.format;
enable_channels = format.channels != _dest_format.channels;
if (enable_channels &&
!channels_converter.Open(format.format, format.channels,
_dest_format.channels, error)) {
if (enable_format)
format_converter.Close();
if (enable_resampler)
resampler.Close();
return false;
if (enable_channels) {
try {
channels_converter.Open(format.format, format.channels,
_dest_format.channels);
} catch (...) {
if (enable_format)
format_converter.Close();
if (enable_resampler)
resampler.Close();
throw;
}
}
src_format = _src_format;
dest_format = _dest_format;
return true;
}
void
@ -118,39 +119,27 @@ PcmConvert::Close()
}
ConstBuffer<void>
PcmConvert::Convert(ConstBuffer<void> buffer, Error &error)
PcmConvert::Convert(ConstBuffer<void> buffer)
{
#ifdef ENABLE_DSD
if (src_format.format == SampleFormat::DSD) {
auto s = ConstBuffer<uint8_t>::FromVoid(buffer);
auto d = dsd.ToFloat(src_format.channels, s);
if (d.IsNull()) {
error.Set(pcm_domain,
"DSD to PCM conversion failed");
return nullptr;
}
if (d.IsNull())
throw std::runtime_error("DSD to PCM conversion failed");
buffer = d.ToVoid();
}
#endif
if (enable_resampler) {
buffer = resampler.Resample(buffer, error);
if (buffer.IsNull())
return nullptr;
}
if (enable_resampler)
buffer = resampler.Resample(buffer);
if (enable_format) {
buffer = format_converter.Convert(buffer, error);
if (buffer.IsNull())
return nullptr;
}
if (enable_format)
buffer = format_converter.Convert(buffer);
if (enable_channels) {
buffer = channels_converter.Convert(buffer, error);
if (buffer.IsNull())
return nullptr;
}
if (enable_channels)
buffer = channels_converter.Convert(buffer);
return buffer;
}

View File

@ -31,7 +31,6 @@
#endif
template<typename T> struct ConstBuffer;
class Error;
/**
* This object is statically allocated (within another struct), and
@ -57,9 +56,10 @@ public:
/**
* Prepare the object. Call Close() when done.
*
* Throws std::runtime_error on error.
*/
bool Open(AudioFormat _src_format, AudioFormat _dest_format,
Error &error);
void Open(AudioFormat _src_format, AudioFormat _dest_format);
/**
* Close the object after it was prepared with Open(). After
@ -70,14 +70,15 @@ public:
/**
* Converts PCM data between two audio formats.
*
* Throws std::runtime_error on error.
*
* @param src the source PCM buffer
* @param error location to store the error occurring
* @return the destination buffer, or nullptr on error
* @return the destination buffer
*/
ConstBuffer<void> Convert(ConstBuffer<void> src, Error &error);
ConstBuffer<void> Convert(ConstBuffer<void> src);
};
bool
pcm_convert_global_init(Error &error);
void
pcm_convert_global_init();
#endif

View File

@ -24,7 +24,6 @@
#include "Compiler.h"
struct AudioFormat;
class Error;
/**
* This is an interface for plugins that convert PCM data to a
@ -37,16 +36,17 @@ public:
/**
* Opens the resampler, preparing it for Resample().
*
* Throws std::runtime_error on error.
*
* @param af the audio format of incoming data; the plugin may
* modify the object to enforce another input format (however,
* it may not request a different input sample rate)
* @param new_sample_rate the requested output sample rate
* @param error location to store the error
* @return the format of outgoing data or
* AudioFormat::Undefined() on error
* @return the format of outgoing data
*/
virtual AudioFormat Open(AudioFormat &af, unsigned new_sample_rate,
Error &error) = 0;
virtual AudioFormat Open(AudioFormat &af,
unsigned new_sample_rate) = 0;
/**
* Closes the resampler. After that, you may call Open()
@ -58,14 +58,11 @@ public:
* Resamples a block of PCM data.
*
* @param src the input buffer
* @param error location to store the error occurring
* @return the destination buffer on success (will be
* invalidated by filter_close() or filter_filter()), nullptr on
* error
* @return the destination buffer (will be invalidated by
* filter_close() or filter_filter())
*/
gcc_pure
virtual ConstBuffer<void> Resample(ConstBuffer<void> src,
Error &error) = 0;
virtual ConstBuffer<void> Resample(ConstBuffer<void> src) = 0;
};
#endif

View File

@ -21,7 +21,7 @@
#include "SoxrResampler.hxx"
#include "AudioFormat.hxx"
#include "config/Block.hxx"
#include "util/Error.hxx"
#include "util/RuntimeError.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
@ -80,18 +80,16 @@ soxr_parse_quality(const char *quality)
return SOXR_INVALID_RECIPE;
}
bool
pcm_resample_soxr_global_init(const ConfigBlock &block, Error &error)
void
pcm_resample_soxr_global_init(const ConfigBlock &block)
{
const char *quality_string = block.GetBlockValue("quality");
unsigned long recipe = soxr_parse_quality(quality_string);
if (recipe == SOXR_INVALID_RECIPE) {
assert(quality_string != nullptr);
error.Format(soxr_domain,
"unknown quality setting '%s' in line %d",
quality_string, block.line);
return false;
throw FormatRuntimeError("unknown quality setting '%s' in line %d",
quality_string, block.line);
}
soxr_quality = soxr_quality_spec(recipe, 0);
@ -102,13 +100,10 @@ pcm_resample_soxr_global_init(const ConfigBlock &block, Error &error)
const unsigned n_threads = block.GetBlockValue("threads", 1);
soxr_runtime = soxr_runtime_spec(n_threads);
return true;
}
AudioFormat
SoxrPcmResampler::Open(AudioFormat &af, unsigned new_sample_rate,
Error &error)
SoxrPcmResampler::Open(AudioFormat &af, unsigned new_sample_rate)
{
assert(af.IsValid());
assert(audio_valid_sample_rate(new_sample_rate));
@ -117,11 +112,9 @@ SoxrPcmResampler::Open(AudioFormat &af, unsigned new_sample_rate,
soxr = soxr_create(af.sample_rate, new_sample_rate,
af.channels, &e,
nullptr, &soxr_quality, &soxr_runtime);
if (soxr == nullptr) {
error.Format(soxr_domain,
"soxr initialization has failed: %s", e);
return AudioFormat::Undefined();
}
if (soxr == nullptr)
throw FormatRuntimeError("soxr initialization has failed: %s",
e);
FormatDebug(soxr_domain, "soxr engine '%s'", soxr_engine(soxr));
@ -147,7 +140,7 @@ SoxrPcmResampler::Close()
}
ConstBuffer<void>
SoxrPcmResampler::Resample(ConstBuffer<void> src, Error &error)
SoxrPcmResampler::Resample(ConstBuffer<void> src)
{
const size_t frame_size = channels * sizeof(float);
assert(src.size % frame_size == 0);
@ -162,10 +155,8 @@ SoxrPcmResampler::Resample(ConstBuffer<void> src, Error &error)
size_t i_done, o_done;
soxr_error_t e = soxr_process(soxr, src.data, n_frames, &i_done,
output_buffer, o_frames, &o_done);
if (e != nullptr) {
error.Format(soxr_domain, "soxr error: %s", e);
return nullptr;
}
if (e != nullptr)
throw FormatRuntimeError("soxr error: %s", e);
return { output_buffer, o_done * frame_size };
}

View File

@ -39,14 +39,12 @@ class SoxrPcmResampler final : public PcmResampler {
PcmBuffer buffer;
public:
virtual AudioFormat Open(AudioFormat &af, unsigned new_sample_rate,
Error &error) override;
virtual void Close() override;
virtual ConstBuffer<void> Resample(ConstBuffer<void> src,
Error &error) override;
AudioFormat Open(AudioFormat &af, unsigned new_sample_rate) override;
void Close() override;
ConstBuffer<void> Resample(ConstBuffer<void> src) override;
};
bool
pcm_resample_soxr_global_init(const ConfigBlock &block, Error &error);
void
pcm_resample_soxr_global_init(const ConfigBlock &block);
#endif

View File

@ -24,7 +24,7 @@
#include "Traits.hxx"
#include "util/ConstBuffer.hxx"
#include "util/WritableBuffer.hxx"
#include "util/Error.hxx"
#include "util/RuntimeError.hxx"
#include "PcmDither.cxx" // including the .cxx file to get inlined templates
@ -97,17 +97,15 @@ pcm_volume_change_float(float *dest, const float *src, size_t n,
dest[i] = src[i] * volume;
}
bool
PcmVolume::Open(SampleFormat _format, Error &error)
void
PcmVolume::Open(SampleFormat _format)
{
assert(format == SampleFormat::UNDEFINED);
switch (_format) {
case SampleFormat::UNDEFINED:
error.Format(pcm_domain,
"Software volume for %s is not implemented",
sample_format_to_string(_format));
return false;
throw FormatRuntimeError("Software volume for %s is not implemented",
sample_format_to_string(_format));
case SampleFormat::S8:
case SampleFormat::S16:
@ -122,7 +120,6 @@ PcmVolume::Open(SampleFormat _format, Error &error)
}
format = _format;
return true;
}
ConstBuffer<void>

View File

@ -28,7 +28,6 @@
#include <assert.h>
#endif
class Error;
template<typename T> struct ConstBuffer;
/**
@ -93,11 +92,11 @@ public:
/**
* Opens the object, prepare for Apply().
*
* Throws std::runtime_error on error.
*
* @param format the sample format
* @param error location to store the error
* @return true on success
*/
bool Open(SampleFormat format, Error &error);
void Open(SampleFormat format);
/**
* Closes the object. After that, you may call Open() again.

View File

@ -38,8 +38,9 @@
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int
main(int argc, char **argv)
try {
AudioFormat in_audio_format, out_audio_format;
if (argc != 3) {
@ -68,10 +69,7 @@ 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)) {
LogError(error, "Failed to open PcmConvert");
return EXIT_FAILURE;
}
state.Open(in_audio_format, out_audio_format_mask);
StaticFifoBuffer<uint8_t, 4096> buffer;
@ -96,12 +94,7 @@ int main(int argc, char **argv)
buffer.Consume(src.size);
auto output = state.Convert({src.data, src.size}, error);
if (output.IsNull()) {
state.Close();
LogError(error, "Failed to convert");
return EXIT_FAILURE;
}
auto output = state.Convert({src.data, src.size});
gcc_unused ssize_t ignored = write(1, output.data,
output.size);
@ -110,4 +103,7 @@ int main(int argc, char **argv)
state.Close();
return EXIT_SUCCESS;
} catch (const std::exception &e) {
LogError(e);
return EXIT_FAILURE;
}

View File

@ -36,8 +36,9 @@
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int
main(int argc, char **argv)
try {
static char buffer[4096];
ssize_t nbytes;
@ -56,10 +57,7 @@ int main(int argc, char **argv)
}
PcmVolume pv;
if (!pv.Open(audio_format.format, error)) {
fprintf(stderr, "%s\n", error.GetMessage());
return EXIT_FAILURE;
}
pv.Open(audio_format.format);
while ((nbytes = read(0, buffer, sizeof(buffer))) > 0) {
auto dest = pv.Apply({buffer, size_t(nbytes)});
@ -67,4 +65,7 @@ int main(int argc, char **argv)
}
pv.Close();
} catch (const std::exception &e) {
LogError(e);
return EXIT_FAILURE;
}

View File

@ -22,7 +22,6 @@
#include "pcm/Volume.hxx"
#include "pcm/Traits.hxx"
#include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
#include "test_pcm_util.hxx"
#include <algorithm>
@ -37,7 +36,7 @@ TestVolume(G g=G())
typedef typename Traits::value_type value_type;
PcmVolume pv;
CPPUNIT_ASSERT(pv.Open(F, IgnoreError()));
pv.Open(F);
constexpr size_t N = 509;
static value_type zero[N];
@ -96,7 +95,7 @@ void
PcmVolumeTest::TestVolumeFloat()
{
PcmVolume pv;
CPPUNIT_ASSERT(pv.Open(SampleFormat::FLOAT, IgnoreError()));
pv.Open(SampleFormat::FLOAT);
constexpr size_t N = 509;
static float zero[N];