audio_format: convert to C++

This commit is contained in:
Max Kellermann 2013-08-03 21:00:50 +02:00
parent 67f591a9ce
commit d1e7b4e381
121 changed files with 1251 additions and 1275 deletions

View File

@ -51,7 +51,6 @@ src_mpd_LDADD = \
mpd_headers = \ mpd_headers = \
src/check.h \ src/check.h \
src/ack.h \ src/ack.h \
src/audio_format.h \
src/filter_internal.h \ src/filter_internal.h \
src/command.h \ src/command.h \
src/conf.h \ src/conf.h \
@ -97,7 +96,7 @@ src_mpd_SOURCES = \
src/notify.cxx src/notify.hxx \ src/notify.cxx src/notify.hxx \
src/AudioConfig.cxx src/AudioConfig.hxx \ src/AudioConfig.cxx src/AudioConfig.hxx \
src/CheckAudioFormat.cxx src/CheckAudioFormat.hxx \ src/CheckAudioFormat.cxx src/CheckAudioFormat.hxx \
src/audio_format.c \ src/AudioFormat.cxx src/AudioFormat.hxx \
src/AudioParser.cxx src/AudioParser.hxx \ src/AudioParser.cxx src/AudioParser.hxx \
src/protocol/ArgParser.cxx src/protocol/ArgParser.hxx \ src/protocol/ArgParser.cxx src/protocol/ArgParser.hxx \
src/protocol/Result.cxx src/protocol/Result.hxx \ src/protocol/Result.cxx src/protocol/Result.hxx \
@ -1173,8 +1172,7 @@ test_run_decoder_SOURCES = test/run_decoder.cxx \
src/Tag.cxx src/TagNames.c src/TagPool.cxx src/TagHandler.cxx \ src/Tag.cxx src/TagNames.c src/TagPool.cxx src/TagHandler.cxx \
src/ReplayGainInfo.cxx \ src/ReplayGainInfo.cxx \
src/fd_util.c \ src/fd_util.c \
src/CheckAudioFormat.cxx \ src/AudioFormat.cxx src/CheckAudioFormat.cxx \
src/audio_format.c \
$(ARCHIVE_SRC) \ $(ARCHIVE_SRC) \
$(INPUT_SRC) \ $(INPUT_SRC) \
$(TAG_SRC) \ $(TAG_SRC) \
@ -1221,7 +1219,7 @@ test_run_filter_SOURCES = test/run_filter.cxx \
test/stdbin.h \ test/stdbin.h \
src/FilterPlugin.cxx src/FilterRegistry.cxx \ src/FilterPlugin.cxx src/FilterRegistry.cxx \
src/CheckAudioFormat.cxx \ src/CheckAudioFormat.cxx \
src/audio_format.c \ src/AudioFormat.cxx \
src/AudioParser.cxx \ src/AudioParser.cxx \
src/ReplayGainInfo.cxx \ src/ReplayGainInfo.cxx \
src/AudioCompress/compress.c src/AudioCompress/compress.c
@ -1240,7 +1238,7 @@ test_run_encoder_SOURCES = test/run_encoder.cxx \
test/stdbin.h \ test/stdbin.h \
src/Tag.cxx src/TagNames.c src/TagPool.cxx \ src/Tag.cxx src/TagNames.c src/TagPool.cxx \
src/CheckAudioFormat.cxx \ src/CheckAudioFormat.cxx \
src/audio_format.c \ src/AudioFormat.cxx \
src/AudioParser.cxx src/AudioParser.cxx
test_run_encoder_LDADD = \ test_run_encoder_LDADD = \
$(ENCODER_LIBS) \ $(ENCODER_LIBS) \
@ -1258,7 +1256,7 @@ test_test_vorbis_encoder_SOURCES = test/test_vorbis_encoder.cxx \
test/stdbin.h \ test/stdbin.h \
src/Tag.cxx src/TagNames.c src/TagPool.cxx \ src/Tag.cxx src/TagNames.c src/TagPool.cxx \
src/CheckAudioFormat.cxx \ src/CheckAudioFormat.cxx \
src/audio_format.c \ src/AudioFormat.cxx \
src/AudioParser.cxx \ src/AudioParser.cxx \
$(ENCODER_SRC) $(ENCODER_SRC)
test_test_vorbis_encoder_CPPFLAGS = $(AM_CPPFLAGS) \ test_test_vorbis_encoder_CPPFLAGS = $(AM_CPPFLAGS) \
@ -1289,7 +1287,7 @@ test_run_normalize_LDADD = \
$(GLIB_LIBS) $(GLIB_LIBS)
test_run_convert_SOURCES = test/run_convert.cxx \ test_run_convert_SOURCES = test/run_convert.cxx \
src/audio_format.c \ src/AudioFormat.cxx \
src/CheckAudioFormat.cxx \ src/CheckAudioFormat.cxx \
src/AudioParser.cxx src/AudioParser.cxx
test_run_convert_LDADD = \ test_run_convert_LDADD = \
@ -1313,7 +1311,7 @@ test_run_output_SOURCES = test/run_output.cxx \
test/stdbin.h \ test/stdbin.h \
src/IOThread.cxx \ src/IOThread.cxx \
src/CheckAudioFormat.cxx \ src/CheckAudioFormat.cxx \
src/audio_format.c \ src/AudioFormat.cxx \
src/AudioParser.cxx \ src/AudioParser.cxx \
src/Timer.cxx src/clock.c \ src/Timer.cxx src/clock.c \
src/Tag.cxx src/TagNames.c src/TagPool.cxx \ src/Tag.cxx src/TagNames.c src/TagPool.cxx \

View File

@ -19,18 +19,19 @@
#include "config.h" #include "config.h"
#include "AudioConfig.hxx" #include "AudioConfig.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include "AudioParser.hxx" #include "AudioParser.hxx"
#include "conf.h" #include "conf.h"
#include "mpd_error.h" #include "mpd_error.h"
static struct audio_format configured_audio_format; static AudioFormat configured_audio_format;
void getOutputAudioFormat(const struct audio_format *inAudioFormat, AudioFormat
struct audio_format *outAudioFormat) getOutputAudioFormat(AudioFormat inAudioFormat)
{ {
*outAudioFormat = *inAudioFormat; AudioFormat out_audio_format = inAudioFormat;
audio_format_mask_apply(outAudioFormat, &configured_audio_format); out_audio_format.ApplyMask(configured_audio_format);
return out_audio_format;
} }
void initAudioConfig(void) void initAudioConfig(void)
@ -42,7 +43,7 @@ void initAudioConfig(void)
if (param == NULL) if (param == NULL)
return; return;
ret = audio_format_parse(&configured_audio_format, param->value, ret = audio_format_parse(configured_audio_format, param->value,
true, &error); true, &error);
if (!ret) if (!ret)
MPD_ERROR("error parsing line %i: %s", MPD_ERROR("error parsing line %i: %s",

View File

@ -20,10 +20,10 @@
#ifndef MPD_AUDIO_CONFIG_HXX #ifndef MPD_AUDIO_CONFIG_HXX
#define MPD_AUDIO_CONFIG_HXX #define MPD_AUDIO_CONFIG_HXX
struct audio_format; struct AudioFormat;
void getOutputAudioFormat(const struct audio_format *inFormat, AudioFormat
struct audio_format *outFormat); getOutputAudioFormat(AudioFormat inFormat);
/* make sure initPlayerData is called before this function!! */ /* make sure initPlayerData is called before this function!! */
void initAudioConfig(void); void initAudioConfig(void);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2003-2011 The Music Player Daemon Project * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org * http://www.musicpd.org
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -17,53 +17,52 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "audio_format.h" #include "AudioFormat.hxx"
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
void void
audio_format_mask_apply(struct audio_format *af, AudioFormat::ApplyMask(AudioFormat mask)
const struct audio_format *mask)
{ {
assert(audio_format_valid(af)); assert(IsValid());
assert(audio_format_mask_valid(mask)); assert(mask.IsMaskValid());
if (mask->sample_rate != 0) if (mask.sample_rate != 0)
af->sample_rate = mask->sample_rate; sample_rate = mask.sample_rate;
if (mask->format != SAMPLE_FORMAT_UNDEFINED) if (mask.format != SampleFormat::UNDEFINED)
af->format = mask->format; format = mask.format;
if (mask->channels != 0) if (mask.channels != 0)
af->channels = mask->channels; channels = mask.channels;
assert(audio_format_valid(af)); assert(IsValid());
} }
const char * const char *
sample_format_to_string(enum sample_format format) sample_format_to_string(SampleFormat format)
{ {
switch (format) { switch (format) {
case SAMPLE_FORMAT_UNDEFINED: case SampleFormat::UNDEFINED:
return "?"; return "?";
case SAMPLE_FORMAT_S8: case SampleFormat::S8:
return "8"; return "8";
case SAMPLE_FORMAT_S16: case SampleFormat::S16:
return "16"; return "16";
case SAMPLE_FORMAT_S24_P32: case SampleFormat::S24_P32:
return "24"; return "24";
case SAMPLE_FORMAT_S32: case SampleFormat::S32:
return "32"; return "32";
case SAMPLE_FORMAT_FLOAT: case SampleFormat::FLOAT:
return "f"; return "f";
case SAMPLE_FORMAT_DSD: case SampleFormat::DSD:
return "dsd"; return "dsd";
} }
@ -73,15 +72,14 @@ sample_format_to_string(enum sample_format format)
} }
const char * const char *
audio_format_to_string(const struct audio_format *af, audio_format_to_string(const AudioFormat af,
struct audio_format_string *s) struct audio_format_string *s)
{ {
assert(af != NULL); assert(s != nullptr);
assert(s != NULL);
snprintf(s->buffer, sizeof(s->buffer), "%u:%s:%u", snprintf(s->buffer, sizeof(s->buffer), "%u:%s:%u",
af->sample_rate, sample_format_to_string(af->format), af.sample_rate, sample_format_to_string(af.format),
af->channels); af.channels);
return s->buffer; return s->buffer;
} }

315
src/AudioFormat.hxx Normal file
View File

@ -0,0 +1,315 @@
/*
* Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPD_AUDIO_FORMAT_HXX
#define MPD_AUDIO_FORMAT_HXX
#include "gcc.h"
#include <stdint.h>
#include <assert.h>
#if defined(WIN32) && GCC_CHECK_VERSION(4,6)
/* on WIN32, "FLOAT" is already defined, and this triggers -Wshadow */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
#endif
enum class SampleFormat : uint8_t {
UNDEFINED = 0,
S8,
S16,
/**
* Signed 24 bit integer samples, packed in 32 bit integers
* (the most significant byte is filled with the sign bit).
*/
S24_P32,
S32,
/**
* 32 bit floating point samples in the host's format. The
* range is -1.0f to +1.0f.
*/
FLOAT,
/**
* Direct Stream Digital. 1-bit samples; each frame has one
* byte (8 samples) per channel.
*/
DSD,
};
#if defined(WIN32) && GCC_CHECK_VERSION(4,6)
#pragma GCC diagnostic pop
#endif
static constexpr unsigned MAX_CHANNELS = 8;
/**
* This structure describes the format of a raw PCM stream.
*/
struct AudioFormat {
/**
* The sample rate in Hz. A better name for this attribute is
* "frame rate", because technically, you have two samples per
* frame in stereo sound.
*/
uint32_t sample_rate;
/**
* The format samples are stored in. See the #sample_format
* enum for valid values.
*/
SampleFormat format;
/**
* The number of channels. Only mono (1) and stereo (2) are
* fully supported currently.
*/
uint8_t channels;
AudioFormat() = default;
constexpr AudioFormat(uint32_t _sample_rate,
SampleFormat _format, uint8_t _channels)
:sample_rate(_sample_rate),
format(_format), channels(_channels) {}
static constexpr AudioFormat Undefined() {
return AudioFormat(0, SampleFormat::UNDEFINED,0);
}
/**
* Clears the #audio_format object, i.e. sets all attributes to an
* undefined (invalid) value.
*/
void Clear() {
sample_rate = 0;
format = SampleFormat::UNDEFINED;
channels = 0;
}
/**
* Checks whether the object has a defined value.
*/
constexpr bool IsDefined() const {
return sample_rate != 0;
}
/**
* Checks whether the object is full, i.e. all attributes are
* defined. This is more complete than IsDefined(), but
* slower.
*/
constexpr bool IsFullyDefined() const {
return sample_rate != 0 && format != SampleFormat::UNDEFINED &&
channels != 0;
}
/**
* Checks whether the object has at least one defined value.
*/
constexpr bool IsMaskDefined() const {
return sample_rate != 0 || format != SampleFormat::UNDEFINED ||
channels != 0;
}
bool IsValid() const;
bool IsMaskValid() const;
constexpr bool operator==(const AudioFormat other) const {
return sample_rate == other.sample_rate &&
format == other.format &&
channels == other.channels;
}
constexpr bool operator!=(const AudioFormat other) const {
return !(*this == other);
}
void ApplyMask(AudioFormat mask);
/**
* Returns the size of each (mono) sample in bytes.
*/
unsigned GetSampleSize() const;
/**
* Returns the size of each full frame in bytes.
*/
unsigned GetFrameSize() const;
/**
* Returns the floating point factor which converts a time
* span to a storage size in bytes.
*/
double GetTimeToSize() const;
};
/**
* Buffer for audio_format_string().
*/
struct audio_format_string {
char buffer[24];
};
/**
* Checks whether the sample rate is valid.
*
* @param sample_rate the sample rate in Hz
*/
static constexpr inline bool
audio_valid_sample_rate(unsigned sample_rate)
{
return sample_rate > 0 && sample_rate < (1 << 30);
}
/**
* Checks whether the sample format is valid.
*
* @param bits the number of significant bits per sample
*/
static inline bool
audio_valid_sample_format(SampleFormat format)
{
switch (format) {
case SampleFormat::S8:
case SampleFormat::S16:
case SampleFormat::S24_P32:
case SampleFormat::S32:
case SampleFormat::FLOAT:
case SampleFormat::DSD:
return true;
case SampleFormat::UNDEFINED:
break;
}
return false;
}
/**
* Checks whether the number of channels is valid.
*/
static constexpr inline bool
audio_valid_channel_count(unsigned channels)
{
return channels >= 1 && channels <= MAX_CHANNELS;
}
/**
* Returns false if the format is not valid for playback with MPD.
* This function performs some basic validity checks.
*/
inline bool
AudioFormat::IsValid() const
{
return audio_valid_sample_rate(sample_rate) &&
audio_valid_sample_format(format) &&
audio_valid_channel_count(channels);
}
/**
* Returns false if the format mask is not valid for playback with
* MPD. This function performs some basic validity checks.
*/
inline bool
AudioFormat::IsMaskValid() const
{
return (sample_rate == 0 ||
audio_valid_sample_rate(sample_rate)) &&
(format == SampleFormat::UNDEFINED ||
audio_valid_sample_format(format)) &&
(channels == 0 || audio_valid_channel_count(channels));
}
gcc_const
static inline unsigned
sample_format_size(SampleFormat format)
{
switch (format) {
case SampleFormat::S8:
return 1;
case SampleFormat::S16:
return 2;
case SampleFormat::S24_P32:
case SampleFormat::S32:
case SampleFormat::FLOAT:
return 4;
case SampleFormat::DSD:
/* each frame has 8 samples per channel */
return 1;
case SampleFormat::UNDEFINED:
return 0;
}
assert(false);
gcc_unreachable();
}
inline unsigned
AudioFormat::GetSampleSize() const
{
return sample_format_size(format);
}
inline unsigned
AudioFormat::GetFrameSize() const
{
return GetSampleSize() * channels;
}
inline double
AudioFormat::GetTimeToSize() const
{
return sample_rate * GetFrameSize();
}
/**
* Renders a #sample_format enum into a string, e.g. for printing it
* in a log file.
*
* @param format a #sample_format enum value
* @return the string
*/
gcc_pure gcc_malloc
const char *
sample_format_to_string(SampleFormat format);
/**
* Renders the #audio_format object into a string, e.g. for printing
* it in a log file.
*
* @param af the #audio_format object
* @param s a buffer to print into
* @return the string, or NULL if the #audio_format object is invalid
*/
gcc_pure gcc_malloc
const char *
audio_format_to_string(AudioFormat af,
struct audio_format_string *s);
#endif

View File

@ -24,7 +24,7 @@
#include "config.h" #include "config.h"
#include "AudioParser.hxx" #include "AudioParser.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "gcc.h" #include "gcc.h"
@ -69,27 +69,27 @@ parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r,
static bool static bool
parse_sample_format(const char *src, bool mask, parse_sample_format(const char *src, bool mask,
enum sample_format *sample_format_r, SampleFormat *sample_format_r,
const char **endptr_r, GError **error_r) const char **endptr_r, GError **error_r)
{ {
unsigned long value; unsigned long value;
char *endptr; char *endptr;
enum sample_format sample_format; SampleFormat sample_format;
if (mask && *src == '*') { if (mask && *src == '*') {
*sample_format_r = SAMPLE_FORMAT_UNDEFINED; *sample_format_r = SampleFormat::UNDEFINED;
*endptr_r = src + 1; *endptr_r = src + 1;
return true; return true;
} }
if (*src == 'f') { if (*src == 'f') {
*sample_format_r = SAMPLE_FORMAT_FLOAT; *sample_format_r = SampleFormat::FLOAT;
*endptr_r = src + 1; *endptr_r = src + 1;
return true; return true;
} }
if (memcmp(src, "dsd", 3) == 0) { if (memcmp(src, "dsd", 3) == 0) {
*sample_format_r = SAMPLE_FORMAT_DSD; *sample_format_r = SampleFormat::DSD;
*endptr_r = src + 3; *endptr_r = src + 3;
return true; return true;
} }
@ -103,11 +103,11 @@ parse_sample_format(const char *src, bool mask,
switch (value) { switch (value) {
case 8: case 8:
sample_format = SAMPLE_FORMAT_S8; sample_format = SampleFormat::S8;
break; break;
case 16: case 16:
sample_format = SAMPLE_FORMAT_S16; sample_format = SampleFormat::S16;
break; break;
case 24: case 24:
@ -115,11 +115,11 @@ parse_sample_format(const char *src, bool mask,
/* for backwards compatibility */ /* for backwards compatibility */
endptr += 2; endptr += 2;
sample_format = SAMPLE_FORMAT_S24_P32; sample_format = SampleFormat::S24_P32;
break; break;
case 32: case 32:
sample_format = SAMPLE_FORMAT_S32; sample_format = SampleFormat::S32;
break; break;
default: default:
@ -162,14 +162,14 @@ parse_channel_count(const char *src, bool mask, uint8_t *channels_r,
} }
bool bool
audio_format_parse(struct audio_format *dest, const char *src, audio_format_parse(AudioFormat &dest, const char *src,
bool mask, GError **error_r) bool mask, GError **error_r)
{ {
uint32_t rate; uint32_t rate;
enum sample_format sample_format; SampleFormat sample_format;
uint8_t channels; uint8_t channels;
audio_format_clear(dest); dest.Clear();
/* parse sample rate */ /* parse sample rate */
@ -191,7 +191,7 @@ audio_format_parse(struct audio_format *dest, const char *src,
#if GCC_CHECK_VERSION(4,7) #if GCC_CHECK_VERSION(4,7)
/* workaround -Wmaybe-uninitialized false positive */ /* workaround -Wmaybe-uninitialized false positive */
sample_format = SAMPLE_FORMAT_UNDEFINED; sample_format = SampleFormat::UNDEFINED;
#endif #endif
if (!parse_sample_format(src, mask, &sample_format, &src, error_r)) if (!parse_sample_format(src, mask, &sample_format, &src, error_r))
@ -214,9 +214,10 @@ audio_format_parse(struct audio_format *dest, const char *src,
return false; return false;
} }
audio_format_init(dest, rate, sample_format, channels); dest = AudioFormat(rate, sample_format, channels);
assert(mask ? audio_format_mask_valid(dest) assert(mask
: audio_format_valid(dest)); ? dest.IsMaskValid()
: dest.IsValid());
return true; return true;
} }

View File

@ -27,7 +27,7 @@
#include "gerror.h" #include "gerror.h"
struct audio_format; struct AudioFormat;
/** /**
* Parses a string in the form "SAMPLE_RATE:BITS:CHANNELS" into an * Parses a string in the form "SAMPLE_RATE:BITS:CHANNELS" into an
@ -41,7 +41,7 @@ struct audio_format;
* @return true on success * @return true on success
*/ */
bool bool
audio_format_parse(struct audio_format *dest, const char *src, audio_format_parse(AudioFormat &dest, const char *src,
bool mask, GError **error_r); bool mask, GError **error_r);
#endif #endif

View File

@ -18,7 +18,7 @@
*/ */
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include <assert.h> #include <assert.h>
@ -35,11 +35,12 @@ audio_check_sample_rate(unsigned long sample_rate, GError **error_r)
} }
bool bool
audio_check_sample_format(enum sample_format sample_format, GError **error_r) audio_check_sample_format(SampleFormat sample_format, GError **error_r)
{ {
if (!audio_valid_sample_format(sample_format)) { if (!audio_valid_sample_format(sample_format)) {
g_set_error(error_r, audio_format_quark(), 0, g_set_error(error_r, audio_format_quark(), 0,
"Invalid sample format: %u", sample_format); "Invalid sample format: %u",
unsigned(sample_format));
return false; return false;
} }
@ -59,15 +60,15 @@ audio_check_channel_count(unsigned channels, GError **error_r)
} }
bool bool
audio_format_init_checked(struct audio_format *af, unsigned long sample_rate, audio_format_init_checked(AudioFormat &af, unsigned long sample_rate,
enum sample_format sample_format, unsigned channels, SampleFormat sample_format, unsigned channels,
GError **error_r) GError **error_r)
{ {
if (audio_check_sample_rate(sample_rate, error_r) && if (audio_check_sample_rate(sample_rate, error_r) &&
audio_check_sample_format(sample_format, error_r) && audio_check_sample_format(sample_format, error_r) &&
audio_check_channel_count(channels, error_r)) { audio_check_channel_count(channels, error_r)) {
audio_format_init(af, sample_rate, sample_format, channels); af = AudioFormat(sample_rate, sample_format, channels);
assert(audio_format_valid(af)); assert(af.IsValid());
return true; return true;
} else } else
return false; return false;

View File

@ -20,7 +20,7 @@
#ifndef MPD_CHECK_AUDIO_FORMAT_HXX #ifndef MPD_CHECK_AUDIO_FORMAT_HXX
#define MPD_CHECK_AUDIO_FORMAT_HXX #define MPD_CHECK_AUDIO_FORMAT_HXX
#include "audio_format.h" #include "AudioFormat.hxx"
#include <glib.h> #include <glib.h>
@ -38,7 +38,7 @@ bool
audio_check_sample_rate(unsigned long sample_rate, GError **error_r); audio_check_sample_rate(unsigned long sample_rate, GError **error_r);
bool bool
audio_check_sample_format(enum sample_format, GError **error_r); audio_check_sample_format(SampleFormat sample_format, GError **error_r);
bool bool
audio_check_channel_count(unsigned sample_format, GError **error_r); audio_check_channel_count(unsigned sample_format, GError **error_r);
@ -47,8 +47,8 @@ audio_check_channel_count(unsigned sample_format, GError **error_r);
* Wrapper for audio_format_init(), which checks all attributes. * Wrapper for audio_format_init(), which checks all attributes.
*/ */
bool bool
audio_format_init_checked(struct audio_format *af, unsigned long sample_rate, audio_format_init_checked(AudioFormat &af, unsigned long sample_rate,
enum sample_format sample_format, unsigned channels, SampleFormat sample_format, unsigned channels,
GError **error_r); GError **error_r);
#endif #endif

View File

@ -20,7 +20,7 @@
#include "config.h" #include "config.h"
#include "CrossFade.hxx" #include "CrossFade.hxx"
#include "MusicChunk.hxx" #include "MusicChunk.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include "Tag.hxx" #include "Tag.hxx"
#include <cmath> #include <cmath>
@ -97,8 +97,8 @@ unsigned cross_fade_calc(float duration, float total_time,
float mixramp_db, float mixramp_delay, float mixramp_db, float mixramp_delay,
float replay_gain_db, float replay_gain_prev_db, float replay_gain_db, float replay_gain_prev_db,
char *mixramp_start, char *mixramp_prev_end, char *mixramp_start, char *mixramp_prev_end,
const struct audio_format *af, const AudioFormat af,
const struct audio_format *old_format, const AudioFormat old_format,
unsigned max_chunks) unsigned max_chunks)
{ {
unsigned int chunks = 0; unsigned int chunks = 0;
@ -107,13 +107,13 @@ unsigned cross_fade_calc(float duration, float total_time,
if (duration < 0 || duration >= total_time || if (duration < 0 || duration >= total_time ||
/* we can't crossfade when the audio formats are different */ /* we can't crossfade when the audio formats are different */
!audio_format_equals(af, old_format)) af != old_format)
return 0; return 0;
assert(duration >= 0); assert(duration >= 0);
assert(audio_format_valid(af)); assert(af.IsValid());
chunks_f = (float)audio_format_time_to_size(af) / (float)CHUNK_SIZE; chunks_f = (float)af.GetTimeToSize() / (float)CHUNK_SIZE;
if (std::isnan(mixramp_delay) || !mixramp_start || !mixramp_prev_end) { if (std::isnan(mixramp_delay) || !mixramp_start || !mixramp_prev_end) {
chunks = (chunks_f * duration + 0.5); chunks = (chunks_f * duration + 0.5);

View File

@ -20,7 +20,7 @@
#ifndef MPD_CROSSFADE_HXX #ifndef MPD_CROSSFADE_HXX
#define MPD_CROSSFADE_HXX #define MPD_CROSSFADE_HXX
struct audio_format; struct AudioFormat;
struct music_chunk; struct music_chunk;
/** /**
@ -44,8 +44,7 @@ unsigned cross_fade_calc(float duration, float total_time,
float mixramp_db, float mixramp_delay, float mixramp_db, float mixramp_delay,
float replay_gain_db, float replay_gain_prev_db, float replay_gain_db, float replay_gain_prev_db,
char *mixramp_start, char *mixramp_prev_end, char *mixramp_start, char *mixramp_prev_end,
const struct audio_format *af, AudioFormat af, AudioFormat old_format,
const struct audio_format *old_format,
unsigned max_chunks); unsigned max_chunks);
#endif #endif

View File

@ -40,7 +40,7 @@
void void
decoder_initialized(struct decoder *decoder, decoder_initialized(struct decoder *decoder,
const struct audio_format *audio_format, const AudioFormat audio_format,
bool seekable, float total_time) bool seekable, float total_time)
{ {
struct decoder_control *dc = decoder->dc; struct decoder_control *dc = decoder->dc;
@ -52,12 +52,11 @@ decoder_initialized(struct decoder *decoder,
assert(decoder->stream_tag == NULL); assert(decoder->stream_tag == NULL);
assert(decoder->decoder_tag == NULL); assert(decoder->decoder_tag == NULL);
assert(!decoder->seeking); assert(!decoder->seeking);
assert(audio_format != NULL); assert(audio_format.IsDefined());
assert(audio_format_defined(audio_format)); assert(audio_format.IsValid());
assert(audio_format_valid(audio_format));
dc->in_audio_format = *audio_format; dc->in_audio_format = audio_format;
getOutputAudioFormat(audio_format, &dc->out_audio_format); dc->out_audio_format = getOutputAudioFormat(audio_format);
dc->seekable = seekable; dc->seekable = seekable;
dc->total_time = total_time; dc->total_time = total_time;
@ -68,13 +67,12 @@ decoder_initialized(struct decoder *decoder,
dc->Unlock(); dc->Unlock();
g_debug("audio_format=%s, seekable=%s", g_debug("audio_format=%s, seekable=%s",
audio_format_to_string(&dc->in_audio_format, &af_string), audio_format_to_string(dc->in_audio_format, &af_string),
seekable ? "true" : "false"); seekable ? "true" : "false");
if (!audio_format_equals(&dc->in_audio_format, if (dc->in_audio_format != dc->out_audio_format)
&dc->out_audio_format))
g_debug("converting to %s", g_debug("converting to %s",
audio_format_to_string(&dc->out_audio_format, audio_format_to_string(dc->out_audio_format,
&af_string)); &af_string));
} }
@ -371,7 +369,7 @@ decoder_data(struct decoder *decoder,
assert(dc->state == DECODE_STATE_DECODE); assert(dc->state == DECODE_STATE_DECODE);
assert(dc->pipe != NULL); assert(dc->pipe != NULL);
assert(length % audio_format_frame_size(&dc->in_audio_format) == 0); assert(length % dc->in_audio_format.GetFrameSize() == 0);
dc->Lock(); dc->Lock();
cmd = decoder_get_virtual_command(decoder); cmd = decoder_get_virtual_command(decoder);
@ -398,10 +396,10 @@ decoder_data(struct decoder *decoder,
return cmd; return cmd;
} }
if (!audio_format_equals(&dc->in_audio_format, &dc->out_audio_format)) { if (dc->in_audio_format != dc->out_audio_format) {
data = decoder->conv_state.Convert(&dc->in_audio_format, data = decoder->conv_state.Convert(dc->in_audio_format,
data, length, data, length,
&dc->out_audio_format, dc->out_audio_format,
&length, &length,
&error); &error);
if (data == NULL) { if (data == NULL) {
@ -457,7 +455,7 @@ decoder_data(struct decoder *decoder,
length -= nbytes; length -= nbytes;
decoder->timestamp += (double)nbytes / decoder->timestamp += (double)nbytes /
audio_format_time_to_size(&dc->out_audio_format); dc->out_audio_format.GetTimeToSize();
if (dc->end_ms > 0 && if (dc->end_ms > 0 &&
decoder->timestamp >= dc->end_ms / 1000.0) decoder->timestamp >= dc->end_ms / 1000.0)

View File

@ -33,7 +33,7 @@
#include "input_stream.h" #include "input_stream.h"
#include "replay_gain_info.h" #include "replay_gain_info.h"
#include "Tag.hxx" #include "Tag.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include "conf.h" #include "conf.h"
/** /**
@ -48,7 +48,7 @@
*/ */
void void
decoder_initialized(struct decoder *decoder, decoder_initialized(struct decoder *decoder,
const struct audio_format *audio_format, AudioFormat audio_format,
bool seekable, float total_time); bool seekable, float total_time);
/** /**

View File

@ -21,7 +21,7 @@
#define MPD_DECODER_CONTROL_HXX #define MPD_DECODER_CONTROL_HXX
#include "DecoderCommand.hxx" #include "DecoderCommand.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include "thread/Mutex.hxx" #include "thread/Mutex.hxx"
#include "thread/Cond.hxx" #include "thread/Cond.hxx"
@ -85,10 +85,10 @@ struct decoder_control {
double seek_where; double seek_where;
/** the format of the song file */ /** the format of the song file */
struct audio_format in_audio_format; AudioFormat in_audio_format;
/** the format being sent to the music pipe */ /** the format being sent to the music pipe */
struct audio_format out_audio_format; AudioFormat out_audio_format;
/** /**
* The song currently being decoded. This attribute is set by * The song currently being decoded. This attribute is set by

View File

@ -26,7 +26,7 @@
#define MPD_ENCODER_API_HXX #define MPD_ENCODER_API_HXX
#include "EncoderPlugin.hxx" #include "EncoderPlugin.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include "Tag.hxx" #include "Tag.hxx"
#include "conf.h" #include "conf.h"

View File

@ -27,7 +27,7 @@
#include <stddef.h> #include <stddef.h>
struct EncoderPlugin; struct EncoderPlugin;
struct audio_format; struct AudioFormat;
struct config_param; struct config_param;
struct Tag; struct Tag;
@ -55,7 +55,7 @@ struct EncoderPlugin {
void (*finish)(Encoder *encoder); void (*finish)(Encoder *encoder);
bool (*open)(Encoder *encoder, bool (*open)(Encoder *encoder,
struct audio_format *audio_format, AudioFormat &audio_format,
GError **error); GError **error);
void (*close)(Encoder *encoder); void (*close)(Encoder *encoder);
@ -122,7 +122,7 @@ encoder_finish(Encoder *encoder)
* @return true on success * @return true on success
*/ */
static inline bool static inline bool
encoder_open(Encoder *encoder, struct audio_format *audio_format, encoder_open(Encoder *encoder, AudioFormat &audio_format,
GError **error) GError **error)
{ {
assert(!encoder->open); assert(!encoder->open);

View File

@ -25,7 +25,7 @@
#ifndef MPD_FILTER_INTERNAL_HXX #ifndef MPD_FILTER_INTERNAL_HXX
#define MPD_FILTER_INTERNAL_HXX #define MPD_FILTER_INTERNAL_HXX
struct audio_format; struct AudioFormat;
class Filter { class Filter {
public: public:
@ -40,10 +40,10 @@ public:
* format * format
* @param error location to store the error occurring, or NULL * @param error location to store the error occurring, or NULL
* to ignore errors. * to ignore errors.
* @return the format of outgoing data * @return the format of outgoing data or
* AudioFormat::Undefined() on error
*/ */
virtual const audio_format *Open(audio_format &af, virtual AudioFormat Open(AudioFormat &af, GError **error_r) = 0;
GError **error_r) = 0;
/** /**
* Closes the filter. After that, you may call Open() again. * Closes the filter. After that, you may call Open() again.

View File

@ -19,7 +19,7 @@
#include "config.h" #include "config.h"
#include "MusicChunk.hxx" #include "MusicChunk.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include "Tag.hxx" #include "Tag.hxx"
#include <assert.h> #include <assert.h>
@ -31,22 +31,21 @@ music_chunk::~music_chunk()
#ifndef NDEBUG #ifndef NDEBUG
bool bool
music_chunk::CheckFormat(const struct audio_format &other_format) const music_chunk::CheckFormat(const AudioFormat other_format) const
{ {
assert(audio_format_valid(&other_format)); assert(other_format.IsValid());
return length == 0 || return length == 0 || audio_format == other_format;
audio_format_equals(&audio_format, &other_format);
} }
#endif #endif
void * void *
music_chunk::Write(const struct audio_format &af, music_chunk::Write(const AudioFormat af,
float data_time, uint16_t _bit_rate, float data_time, uint16_t _bit_rate,
size_t *max_length_r) size_t *max_length_r)
{ {
assert(CheckFormat(af)); assert(CheckFormat(af));
assert(length == 0 || audio_format_valid(&audio_format)); assert(length == 0 || audio_format.IsValid());
if (length == 0) { if (length == 0) {
/* if the chunk is empty, nobody has set bitRate and /* if the chunk is empty, nobody has set bitRate and
@ -56,7 +55,7 @@ music_chunk::Write(const struct audio_format &af,
times = data_time; times = data_time;
} }
const size_t frame_size = audio_format_frame_size(&af); const size_t frame_size = af.GetFrameSize();
size_t num_frames = (sizeof(data) - length) / frame_size; size_t num_frames = (sizeof(data) - length) / frame_size;
if (num_frames == 0) if (num_frames == 0)
return NULL; return NULL;
@ -70,12 +69,12 @@ music_chunk::Write(const struct audio_format &af,
} }
bool bool
music_chunk::Expand(const struct audio_format &af, size_t _length) music_chunk::Expand(const AudioFormat af, size_t _length)
{ {
const size_t frame_size = audio_format_frame_size(&af); const size_t frame_size = af.GetFrameSize();
assert(length + _length <= sizeof(data)); assert(length + _length <= sizeof(data));
assert(audio_format_equals(&audio_format, &af)); assert(audio_format == af);
length += _length; length += _length;

View File

@ -23,7 +23,7 @@
#include "replay_gain_info.h" #include "replay_gain_info.h"
#ifndef NDEBUG #ifndef NDEBUG
#include "audio_format.h" #include "AudioFormat.hxx"
#endif #endif
#include <stdint.h> #include <stdint.h>
@ -33,7 +33,7 @@ enum {
CHUNK_SIZE = 4096, CHUNK_SIZE = 4096,
}; };
struct audio_format; struct AudioFormat;
struct Tag; struct Tag;
/** /**
@ -90,7 +90,7 @@ struct music_chunk {
char data[CHUNK_SIZE]; char data[CHUNK_SIZE];
#ifndef NDEBUG #ifndef NDEBUG
struct audio_format audio_format; AudioFormat audio_format;
#endif #endif
music_chunk() music_chunk()
@ -111,7 +111,7 @@ struct music_chunk {
* specified audio_format. * specified audio_format.
*/ */
gcc_pure gcc_pure
bool CheckFormat(const struct audio_format &audio_format) const; bool CheckFormat(AudioFormat audio_format) const;
#endif #endif
/** /**
@ -128,7 +128,7 @@ struct music_chunk {
* here * here
* @return a writable buffer, or NULL if the chunk is full * @return a writable buffer, or NULL if the chunk is full
*/ */
void *Write(const struct audio_format &af, void *Write(AudioFormat af,
float data_time, uint16_t bit_rate, float data_time, uint16_t bit_rate,
size_t *max_length_r); size_t *max_length_r);
@ -142,7 +142,7 @@ struct music_chunk {
* @param length the number of bytes which were appended * @param length the number of bytes which were appended
* @return true if the chunk is full * @return true if the chunk is full
*/ */
bool Expand(const struct audio_format &af, size_t length); bool Expand(AudioFormat af, size_t length);
}; };
void void

View File

@ -41,13 +41,13 @@ struct music_pipe {
mutable Mutex mutex; mutable Mutex mutex;
#ifndef NDEBUG #ifndef NDEBUG
struct audio_format audio_format; AudioFormat audio_format;
#endif #endif
music_pipe() music_pipe()
:head(nullptr), tail_r(&head), size(0) { :head(nullptr), tail_r(&head), size(0) {
#ifndef NDEBUG #ifndef NDEBUG
audio_format_clear(&audio_format); audio_format.Clear();
#endif #endif
} }
@ -73,13 +73,12 @@ music_pipe_free(struct music_pipe *mp)
bool bool
music_pipe_check_format(const struct music_pipe *pipe, music_pipe_check_format(const struct music_pipe *pipe,
const struct audio_format *audio_format) const AudioFormat audio_format)
{ {
assert(pipe != NULL); assert(pipe != NULL);
assert(audio_format != NULL);
return !audio_format_defined(&pipe->audio_format) || return !pipe->audio_format.IsDefined() ||
audio_format_equals(&pipe->audio_format, audio_format); pipe->audio_format == audio_format;
} }
bool bool
@ -131,7 +130,7 @@ music_pipe_shift(struct music_pipe *mp)
chunk->next = (struct music_chunk *)(void *)0x01010101; chunk->next = (struct music_chunk *)(void *)0x01010101;
if (mp->size == 0) if (mp->size == 0)
audio_format_clear(&mp->audio_format); mp->audio_format.Clear();
#endif #endif
} }
@ -151,16 +150,16 @@ void
music_pipe_push(struct music_pipe *mp, struct music_chunk *chunk) music_pipe_push(struct music_pipe *mp, struct music_chunk *chunk)
{ {
assert(!chunk->IsEmpty()); assert(!chunk->IsEmpty());
assert(chunk->length == 0 || audio_format_valid(&chunk->audio_format)); assert(chunk->length == 0 || chunk->audio_format.IsValid());
const ScopeLock protect(mp->mutex); const ScopeLock protect(mp->mutex);
assert(mp->size > 0 || !audio_format_defined(&mp->audio_format)); assert(mp->size > 0 || !mp->audio_format.IsDefined());
assert(!audio_format_defined(&mp->audio_format) || assert(!mp->audio_format.IsDefined() ||
chunk->CheckFormat(mp->audio_format)); chunk->CheckFormat(mp->audio_format));
#ifndef NDEBUG #ifndef NDEBUG
if (!audio_format_defined(&mp->audio_format) && chunk->length > 0) if (!mp->audio_format.IsDefined() && chunk->length > 0)
mp->audio_format = chunk->audio_format; mp->audio_format = chunk->audio_format;
#endif #endif

View File

@ -23,7 +23,7 @@
#include "gcc.h" #include "gcc.h"
#ifndef NDEBUG #ifndef NDEBUG
struct audio_format; struct AudioFormat;
#endif #endif
struct music_chunk; struct music_chunk;
@ -56,7 +56,7 @@ music_pipe_free(struct music_pipe *mp);
*/ */
bool bool
music_pipe_check_format(const struct music_pipe *pipe, music_pipe_check_format(const struct music_pipe *pipe,
const struct audio_format *audio_format); AudioFormat audio_format);
/** /**
* Checks if the specified chunk is enqueued in the music pipe. * Checks if the specified chunk is enqueued in the music pipe.

View File

@ -22,7 +22,7 @@
#include "OutputPlugin.hxx" #include "OutputPlugin.hxx"
#include "OutputInternal.hxx" #include "OutputInternal.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include "Tag.hxx" #include "Tag.hxx"
#include "conf.h" #include "conf.h"

View File

@ -36,7 +36,7 @@
#undef G_LOG_DOMAIN #undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "output" #define G_LOG_DOMAIN "output"
static struct audio_format input_audio_format; static AudioFormat input_audio_format;
static struct audio_output **audio_outputs; static struct audio_output **audio_outputs;
static unsigned int num_audio_outputs; static unsigned int num_audio_outputs;
@ -246,12 +246,12 @@ audio_output_all_update(void)
unsigned int i; unsigned int i;
bool ret = false; bool ret = false;
if (!audio_format_defined(&input_audio_format)) if (!input_audio_format.IsDefined())
return false; return false;
for (i = 0; i < num_audio_outputs; ++i) for (i = 0; i < num_audio_outputs; ++i)
ret = audio_output_update(audio_outputs[i], ret = audio_output_update(audio_outputs[i],
&input_audio_format, g_mp) || ret; input_audio_format, g_mp) || ret;
return ret; return ret;
} }
@ -291,14 +291,13 @@ audio_output_all_play(struct music_chunk *chunk, GError **error_r)
} }
bool bool
audio_output_all_open(const struct audio_format *audio_format, audio_output_all_open(const AudioFormat audio_format,
struct music_buffer *buffer, struct music_buffer *buffer,
GError **error_r) GError **error_r)
{ {
bool ret = false, enabled = false; bool ret = false, enabled = false;
unsigned int i; unsigned int i;
assert(audio_format != NULL);
assert(buffer != NULL); assert(buffer != NULL);
assert(g_music_buffer == NULL || g_music_buffer == buffer); assert(g_music_buffer == NULL || g_music_buffer == buffer);
assert((g_mp == NULL) == (g_music_buffer == NULL)); assert((g_mp == NULL) == (g_music_buffer == NULL));
@ -315,10 +314,9 @@ audio_output_all_open(const struct audio_format *audio_format,
/* if the pipe hasn't been cleared, the the audio /* if the pipe hasn't been cleared, the the audio
format must not have changed */ format must not have changed */
assert(music_pipe_empty(g_mp) || assert(music_pipe_empty(g_mp) ||
audio_format_equals(audio_format, audio_format == input_audio_format);
&input_audio_format));
input_audio_format = *audio_format; input_audio_format = audio_format;
audio_output_all_reset_reopen(); audio_output_all_reset_reopen();
audio_output_all_enable_disable(); audio_output_all_enable_disable();
@ -547,7 +545,7 @@ audio_output_all_close(void)
g_music_buffer = NULL; g_music_buffer = NULL;
audio_format_clear(&input_audio_format); input_audio_format.Clear();
audio_output_all_elapsed_time = -1.0; audio_output_all_elapsed_time = -1.0;
} }
@ -570,7 +568,7 @@ audio_output_all_release(void)
g_music_buffer = NULL; g_music_buffer = NULL;
audio_format_clear(&input_audio_format); input_audio_format.Clear();
audio_output_all_elapsed_time = -1.0; audio_output_all_elapsed_time = -1.0;
} }

View File

@ -29,7 +29,7 @@
#include "replay_gain_info.h" #include "replay_gain_info.h"
#include "gerror.h" #include "gerror.h"
struct audio_format; struct AudioFormat;
struct music_buffer; struct music_buffer;
struct music_chunk; struct music_chunk;
struct player_control; struct player_control;
@ -76,14 +76,13 @@ audio_output_all_enable_disable(void);
/** /**
* Opens all audio outputs which are not disabled. * Opens all audio outputs which are not disabled.
* *
* @param audio_format the preferred audio format, or NULL to reuse * @param audio_format the preferred audio format
* the previous format
* @param buffer the #music_buffer where consumed #music_chunk objects * @param buffer the #music_buffer where consumed #music_chunk objects
* should be returned * should be returned
* @return true on success, false on failure * @return true on success, false on failure
*/ */
bool bool
audio_output_all_open(const struct audio_format *audio_format, audio_output_all_open(AudioFormat audio_format,
struct music_buffer *buffer, struct music_buffer *buffer,
GError **error_r); GError **error_r);

View File

@ -139,14 +139,14 @@ audio_output_disable(struct audio_output *ao)
*/ */
static bool static bool
audio_output_open(struct audio_output *ao, audio_output_open(struct audio_output *ao,
const struct audio_format *audio_format, const AudioFormat audio_format,
const struct music_pipe *mp) const struct music_pipe *mp)
{ {
bool open; bool open;
assert(ao != NULL); assert(ao != NULL);
assert(ao->allow_play); assert(ao->allow_play);
assert(audio_format_valid(audio_format)); assert(audio_format.IsValid());
assert(mp != NULL); assert(mp != NULL);
if (ao->fail_timer != NULL) { if (ao->fail_timer != NULL) {
@ -154,8 +154,7 @@ audio_output_open(struct audio_output *ao,
ao->fail_timer = NULL; ao->fail_timer = NULL;
} }
if (ao->open && if (ao->open && audio_format == ao->in_audio_format) {
audio_format_equals(audio_format, &ao->in_audio_format)) {
assert(ao->pipe == mp || assert(ao->pipe == mp ||
(ao->always_on && ao->pause)); (ao->always_on && ao->pause));
@ -176,7 +175,7 @@ audio_output_open(struct audio_output *ao,
return true; return true;
} }
ao->in_audio_format = *audio_format; ao->in_audio_format = audio_format;
ao->chunk = NULL; ao->chunk = NULL;
ao->pipe = mp; ao->pipe = mp;
@ -225,7 +224,7 @@ audio_output_close_locked(struct audio_output *ao)
bool bool
audio_output_update(struct audio_output *ao, audio_output_update(struct audio_output *ao,
const struct audio_format *audio_format, const AudioFormat audio_format,
const struct music_pipe *mp) const struct music_pipe *mp)
{ {
assert(mp != NULL); assert(mp != NULL);

View File

@ -25,7 +25,7 @@
#include <stddef.h> #include <stddef.h>
struct audio_output; struct audio_output;
struct audio_format; struct AudioFormat;
struct config_param; struct config_param;
struct music_pipe; struct music_pipe;
struct player_control; struct player_control;
@ -53,7 +53,7 @@ audio_output_disable(struct audio_output *ao);
*/ */
bool bool
audio_output_update(struct audio_output *ao, audio_output_update(struct audio_output *ao,
const struct audio_format *audio_format, AudioFormat audio_format,
const struct music_pipe *mp); const struct music_pipe *mp);
void void

View File

@ -155,16 +155,16 @@ ao_base_init(struct audio_output *ao,
NULL); NULL);
if (p != NULL) { if (p != NULL) {
bool success = bool success =
audio_format_parse(&ao->config_audio_format, audio_format_parse(ao->config_audio_format,
p, true, error_r); p, true, error_r);
if (!success) if (!success)
return false; return false;
} else } else
audio_format_clear(&ao->config_audio_format); ao->config_audio_format.Clear();
} else { } else {
ao->name = "default detected output"; ao->name = "default detected output";
audio_format_clear(&ao->config_audio_format); ao->config_audio_format.Clear();
} }
ao->plugin = plugin; ao->plugin = plugin;

View File

@ -20,7 +20,7 @@
#ifndef MPD_OUTPUT_INTERNAL_HXX #ifndef MPD_OUTPUT_INTERNAL_HXX
#define MPD_OUTPUT_INTERNAL_HXX #define MPD_OUTPUT_INTERNAL_HXX
#include "audio_format.h" #include "AudioFormat.hxx"
#include "pcm/PcmBuffer.hxx" #include "pcm/PcmBuffer.hxx"
#include "thread/Mutex.hxx" #include "thread/Mutex.hxx"
#include "thread/Cond.hxx" #include "thread/Cond.hxx"
@ -134,13 +134,13 @@ struct audio_output {
/** /**
* The configured audio format. * The configured audio format.
*/ */
struct audio_format config_audio_format; AudioFormat config_audio_format;
/** /**
* The audio_format in which audio data is received from the * The audio_format in which audio data is received from the
* player thread (which in turn receives it from the decoder). * player thread (which in turn receives it from the decoder).
*/ */
struct audio_format in_audio_format; AudioFormat in_audio_format;
/** /**
* The audio_format which is really sent to the device. This * The audio_format which is really sent to the device. This
@ -148,7 +148,7 @@ struct audio_output {
* in_audio_format, but may have been modified by * in_audio_format, but may have been modified by
* plugin->open(). * plugin->open().
*/ */
struct audio_format out_audio_format; AudioFormat out_audio_format;
/** /**
* The buffer used to allocate the cross-fading result. * The buffer used to allocate the cross-fading result.

View File

@ -54,7 +54,7 @@ ao_plugin_disable(struct audio_output *ao)
} }
bool bool
ao_plugin_open(struct audio_output *ao, struct audio_format *audio_format, ao_plugin_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error) GError **error)
{ {
return ao->plugin->open(ao, audio_format, error); return ao->plugin->open(ao, audio_format, error);

View File

@ -26,7 +26,7 @@
#include <stddef.h> #include <stddef.h>
struct config_param; struct config_param;
struct audio_format; struct AudioFormat;
struct Tag; struct Tag;
/** /**
@ -89,7 +89,7 @@ struct audio_output_plugin {
* @param error location to store the error occurring, or NULL * @param error location to store the error occurring, or NULL
* to ignore errors * to ignore errors
*/ */
bool (*open)(struct audio_output *data, struct audio_format *audio_format, bool (*open)(struct audio_output *data, AudioFormat &audio_format,
GError **error); GError **error);
/** /**
@ -181,7 +181,7 @@ void
ao_plugin_disable(struct audio_output *ao); ao_plugin_disable(struct audio_output *ao);
bool bool
ao_plugin_open(struct audio_output *ao, struct audio_format *audio_format, ao_plugin_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error); GError **error);
void void

View File

@ -94,11 +94,11 @@ ao_disable(struct audio_output *ao)
} }
} }
static const struct audio_format * static AudioFormat
ao_filter_open(struct audio_output *ao, audio_format &format, ao_filter_open(struct audio_output *ao, AudioFormat &format,
GError **error_r) GError **error_r)
{ {
assert(audio_format_valid(&format)); assert(format.IsValid());
/* the replay_gain filter cannot fail here */ /* the replay_gain filter cannot fail here */
if (ao->replay_gain_filter != NULL) if (ao->replay_gain_filter != NULL)
@ -106,9 +106,8 @@ ao_filter_open(struct audio_output *ao, audio_format &format,
if (ao->other_replay_gain_filter != NULL) if (ao->other_replay_gain_filter != NULL)
ao->other_replay_gain_filter->Open(format, error_r); ao->other_replay_gain_filter->Open(format, error_r);
const struct audio_format *af const AudioFormat af = ao->filter->Open(format, error_r);
= ao->filter->Open(format, error_r); if (!af.IsDefined()) {
if (af == NULL) {
if (ao->replay_gain_filter != NULL) if (ao->replay_gain_filter != NULL)
ao->replay_gain_filter->Close(); ao->replay_gain_filter->Close();
if (ao->other_replay_gain_filter != NULL) if (ao->other_replay_gain_filter != NULL)
@ -139,7 +138,7 @@ ao_open(struct audio_output *ao)
assert(!ao->open); assert(!ao->open);
assert(ao->pipe != NULL); assert(ao->pipe != NULL);
assert(ao->chunk == NULL); assert(ao->chunk == NULL);
assert(audio_format_valid(&ao->in_audio_format)); assert(ao->in_audio_format.IsValid());
if (ao->fail_timer != NULL) { if (ao->fail_timer != NULL) {
/* this can only happen when this /* this can only happen when this
@ -158,9 +157,9 @@ ao_open(struct audio_output *ao)
/* open the filter */ /* open the filter */
const audio_format *filter_audio_format = const AudioFormat filter_audio_format =
ao_filter_open(ao, ao->in_audio_format, &error); ao_filter_open(ao, ao->in_audio_format, &error);
if (filter_audio_format == NULL) { if (!filter_audio_format.IsDefined()) {
g_warning("Failed to open filter for \"%s\" [%s]: %s", g_warning("Failed to open filter for \"%s\" [%s]: %s",
ao->name, ao->plugin->name, error->message); ao->name, ao->plugin->name, error->message);
g_error_free(error); g_error_free(error);
@ -169,14 +168,13 @@ ao_open(struct audio_output *ao)
return; return;
} }
assert(audio_format_valid(filter_audio_format)); assert(filter_audio_format.IsValid());
ao->out_audio_format = *filter_audio_format; ao->out_audio_format = filter_audio_format;
audio_format_mask_apply(&ao->out_audio_format, ao->out_audio_format.ApplyMask(ao->config_audio_format);
&ao->config_audio_format);
ao->mutex.unlock(); ao->mutex.unlock();
success = ao_plugin_open(ao, &ao->out_audio_format, &error); success = ao_plugin_open(ao, ao->out_audio_format, &error);
ao->mutex.lock(); ao->mutex.lock();
assert(!ao->open); assert(!ao->open);
@ -198,12 +196,11 @@ ao_open(struct audio_output *ao)
g_debug("opened plugin=%s name=\"%s\" " g_debug("opened plugin=%s name=\"%s\" "
"audio_format=%s", "audio_format=%s",
ao->plugin->name, ao->name, ao->plugin->name, ao->name,
audio_format_to_string(&ao->out_audio_format, &af_string)); audio_format_to_string(ao->out_audio_format, &af_string));
if (!audio_format_equals(&ao->in_audio_format, if (ao->in_audio_format != ao->out_audio_format)
&ao->out_audio_format))
g_debug("converting from %s", g_debug("converting from %s",
audio_format_to_string(&ao->in_audio_format, audio_format_to_string(ao->in_audio_format,
&af_string)); &af_string));
} }
@ -235,12 +232,12 @@ ao_close(struct audio_output *ao, bool drain)
static void static void
ao_reopen_filter(struct audio_output *ao) ao_reopen_filter(struct audio_output *ao)
{ {
const struct audio_format *filter_audio_format;
GError *error = NULL; GError *error = NULL;
ao_filter_close(ao); ao_filter_close(ao);
filter_audio_format = ao_filter_open(ao, ao->in_audio_format, &error); const AudioFormat filter_audio_format =
if (filter_audio_format == NULL) { ao_filter_open(ao, ao->in_audio_format, &error);
if (!filter_audio_format.IsDefined()) {
g_warning("Failed to open filter for \"%s\" [%s]: %s", g_warning("Failed to open filter for \"%s\" [%s]: %s",
ao->name, ao->plugin->name, error->message); ao->name, ao->plugin->name, error->message);
g_error_free(error); g_error_free(error);
@ -268,7 +265,7 @@ ao_reopen_filter(struct audio_output *ao)
static void static void
ao_reopen(struct audio_output *ao) ao_reopen(struct audio_output *ao)
{ {
if (!audio_format_fully_defined(&ao->config_audio_format)) { if (!ao->config_audio_format.IsFullyDefined()) {
if (ao->open) { if (ao->open) {
const struct music_pipe *mp = ao->pipe; const struct music_pipe *mp = ao->pipe;
ao_close(ao, true); ao_close(ao, true);
@ -279,8 +276,7 @@ ao_reopen(struct audio_output *ao)
the output's open() method determine the effective the output's open() method determine the effective
out_audio_format */ out_audio_format */
ao->out_audio_format = ao->in_audio_format; ao->out_audio_format = ao->in_audio_format;
audio_format_mask_apply(&ao->out_audio_format, ao->out_audio_format.ApplyMask(ao->config_audio_format);
&ao->config_audio_format);
} }
if (ao->open) if (ao->open)
@ -327,7 +323,7 @@ ao_chunk_data(struct audio_output *ao, const struct music_chunk *chunk,
(void)ao; (void)ao;
assert(length % audio_format_frame_size(&ao->in_audio_format) == 0); assert(length % ao->in_audio_format.GetFrameSize() == 0);
if (length > 0 && replay_gain_filter != NULL) { if (length > 0 && replay_gain_filter != NULL) {
if (chunk->replay_gain_serial != *replay_gain_serial_p) { if (chunk->replay_gain_serial != *replay_gain_serial_p) {
@ -399,10 +395,10 @@ ao_filter_chunk(struct audio_output *ao, const struct music_chunk *chunk,
void *dest = ao->cross_fade_buffer.Get(other_length); void *dest = ao->cross_fade_buffer.Get(other_length);
memcpy(dest, other_data, other_length); memcpy(dest, other_data, other_length);
if (!pcm_mix(dest, data, length, if (!pcm_mix(dest, data, length,
sample_format(ao->in_audio_format.format), ao->in_audio_format.format,
1.0 - chunk->mix_ratio)) { 1.0 - chunk->mix_ratio)) {
g_warning("Cannot cross-fade format %s", g_warning("Cannot cross-fade format %s",
sample_format_to_string(sample_format(ao->in_audio_format.format))); sample_format_to_string(ao->in_audio_format.format));
return NULL; return NULL;
} }
@ -479,7 +475,7 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk)
} }
assert(nbytes <= size); assert(nbytes <= size);
assert(nbytes % audio_format_frame_size(&ao->out_audio_format) == 0); assert(nbytes % ao->out_audio_format.GetFrameSize() == 0);
data += nbytes; data += nbytes;
size -= nbytes; size -= nbytes;

View File

@ -31,7 +31,7 @@
#include "protocol/ArgParser.hxx" #include "protocol/ArgParser.hxx"
extern "C" { extern "C" {
#include "audio_format.h" #include "AudioFormat.hxx"
} }
#include "replay_gain_config.h" #include "replay_gain_config.h"
@ -178,12 +178,12 @@ handle_status(Client *client,
player_status.elapsed_time, player_status.elapsed_time,
player_status.bit_rate); player_status.bit_rate);
if (audio_format_defined(&player_status.audio_format)) { if (player_status.audio_format.IsDefined()) {
struct audio_format_string af_string; struct audio_format_string af_string;
client_printf(client, client_printf(client,
COMMAND_STATUS_AUDIO ": %s\n", COMMAND_STATUS_AUDIO ": %s\n",
audio_format_to_string(&player_status.audio_format, audio_format_to_string(player_status.audio_format,
&af_string)); &af_string));
} }
} }

View File

@ -20,7 +20,7 @@
#ifndef MPD_PLAYER_H #ifndef MPD_PLAYER_H
#define MPD_PLAYER_H #define MPD_PLAYER_H
#include "audio_format.h" #include "AudioFormat.hxx"
#include "thread/Mutex.hxx" #include "thread/Mutex.hxx"
#include "thread/Cond.hxx" #include "thread/Cond.hxx"
@ -85,7 +85,7 @@ enum player_error {
struct player_status { struct player_status {
enum player_state state; enum player_state state;
uint16_t bit_rate; uint16_t bit_rate;
struct audio_format audio_format; AudioFormat audio_format;
float total_time; float total_time;
float elapsed_time; float elapsed_time;
}; };
@ -130,7 +130,7 @@ struct player_control {
GError *error; GError *error;
uint16_t bit_rate; uint16_t bit_rate;
struct audio_format audio_format; AudioFormat audio_format;
float total_time; float total_time;
float elapsed_time; float elapsed_time;

View File

@ -115,7 +115,7 @@ struct player {
/** /**
* The current audio format for the audio outputs. * The current audio format for the audio outputs.
*/ */
struct audio_format play_audio_format; AudioFormat play_audio_format;
/** /**
* The time stamp of the chunk most recently sent to the * The time stamp of the chunk most recently sent to the
@ -279,7 +279,7 @@ player_wait_for_decoder(struct player *player)
/* update player_control's song information */ /* update player_control's song information */
pc->total_time = pc->next_song->GetDuration(); pc->total_time = pc->next_song->GetDuration();
pc->bit_rate = 0; pc->bit_rate = 0;
audio_format_clear(&pc->audio_format); pc->audio_format.Clear();
/* clear the queued song */ /* clear the queued song */
pc->next_song = NULL; pc->next_song = NULL;
@ -323,12 +323,12 @@ player_open_output(struct player *player)
{ {
struct player_control *pc = player->pc; struct player_control *pc = player->pc;
assert(audio_format_defined(&player->play_audio_format)); assert(player->play_audio_format.IsDefined());
assert(pc->state == PLAYER_STATE_PLAY || assert(pc->state == PLAYER_STATE_PLAY ||
pc->state == PLAYER_STATE_PAUSE); pc->state == PLAYER_STATE_PAUSE);
GError *error = NULL; GError *error = NULL;
if (audio_output_all_open(&player->play_audio_format, player_buffer, if (audio_output_all_open(player->play_audio_format, player_buffer,
&error)) { &error)) {
player->output_open = true; player->output_open = true;
player->paused = false; player->paused = false;
@ -439,7 +439,7 @@ static bool
player_send_silence(struct player *player) player_send_silence(struct player *player)
{ {
assert(player->output_open); assert(player->output_open);
assert(audio_format_defined(&player->play_audio_format)); assert(player->play_audio_format.IsDefined());
struct music_chunk *chunk = music_buffer_allocate(player_buffer); struct music_chunk *chunk = music_buffer_allocate(player_buffer);
if (chunk == NULL) { if (chunk == NULL) {
@ -451,8 +451,7 @@ player_send_silence(struct player *player)
chunk->audio_format = player->play_audio_format; chunk->audio_format = player->play_audio_format;
#endif #endif
size_t frame_size = const size_t frame_size = player->play_audio_format.GetFrameSize();
audio_format_frame_size(&player->play_audio_format);
/* this formula ensures that we don't send /* this formula ensures that we don't send
partial frames */ partial frames */
unsigned num_frames = sizeof(chunk->data) / frame_size; unsigned num_frames = sizeof(chunk->data) / frame_size;
@ -597,7 +596,7 @@ static void player_process_command(struct player *player)
pc->Lock(); pc->Lock();
pc->state = PLAYER_STATE_PAUSE; pc->state = PLAYER_STATE_PAUSE;
} else if (!audio_format_defined(&player->play_audio_format)) { } else if (!player->play_audio_format.IsDefined()) {
/* the decoder hasn't provided an audio format /* the decoder hasn't provided an audio format
yet - don't open the audio device yet */ yet - don't open the audio device yet */
pc->Lock(); pc->Lock();
@ -689,10 +688,10 @@ update_song_tag(Song *song, const Tag &new_tag)
static bool static bool
play_chunk(struct player_control *pc, play_chunk(struct player_control *pc,
Song *song, struct music_chunk *chunk, Song *song, struct music_chunk *chunk,
const struct audio_format *format, const AudioFormat format,
GError **error_r) GError **error_r)
{ {
assert(chunk->CheckFormat(*format)); assert(chunk->CheckFormat(format));
if (chunk->tag != NULL) if (chunk->tag != NULL)
update_song_tag(song, *chunk->tag); update_song_tag(song, *chunk->tag);
@ -712,7 +711,7 @@ play_chunk(struct player_control *pc,
return false; return false;
pc->total_play_time += (double)chunk->length / pc->total_play_time += (double)chunk->length /
audio_format_time_to_size(format); format.GetTimeToSize();
return true; return true;
} }
@ -825,7 +824,7 @@ play_next_chunk(struct player *player)
GError *error = NULL; GError *error = NULL;
if (!play_chunk(player->pc, player->song, chunk, if (!play_chunk(player->pc, player->song, chunk,
&player->play_audio_format, &error)) { player->play_audio_format, &error)) {
g_warning("%s", error->message); g_warning("%s", error->message);
music_buffer_return(player_buffer, chunk); music_buffer_return(player_buffer, chunk);
@ -1019,8 +1018,8 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
dc->replay_gain_prev_db, dc->replay_gain_prev_db,
dc->mixramp_start, dc->mixramp_start,
dc->mixramp_prev_end, dc->mixramp_prev_end,
&dc->out_audio_format, dc->out_audio_format,
&player.play_audio_format, player.play_audio_format,
music_buffer_size(player_buffer) - music_buffer_size(player_buffer) -
pc->buffered_before_play); pc->buffered_before_play);
if (player.cross_fade_chunks > 0) { if (player.cross_fade_chunks > 0) {

View File

@ -19,7 +19,7 @@
#include "config.h" #include "config.h"
#include "Timer.hxx" #include "Timer.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include "clock.h" #include "clock.h"
#include <glib.h> #include <glib.h>
@ -28,10 +28,10 @@
#include <limits.h> #include <limits.h>
#include <stddef.h> #include <stddef.h>
Timer::Timer(const struct audio_format &af) Timer::Timer(const AudioFormat af)
: time(0), : time(0),
started(false), started(false),
rate(af.sample_rate * audio_format_frame_size(&af)) rate(af.sample_rate * af.GetFrameSize())
{ {
} }

View File

@ -22,14 +22,14 @@
#include <stdint.h> #include <stdint.h>
struct audio_format; struct AudioFormat;
class Timer { class Timer {
uint64_t time; uint64_t time;
bool started; bool started;
const int rate; const int rate;
public: public:
explicit Timer(const struct audio_format& af); explicit Timer(AudioFormat af);
bool IsStarted() const { return started; } bool IsStarted() const { return started; }

View File

@ -1,316 +0,0 @@
/*
* Copyright (C) 2003-2011 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPD_AUDIO_FORMAT_H
#define MPD_AUDIO_FORMAT_H
#include "gcc.h"
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
enum sample_format {
SAMPLE_FORMAT_UNDEFINED = 0,
SAMPLE_FORMAT_S8,
SAMPLE_FORMAT_S16,
/**
* Signed 24 bit integer samples, packed in 32 bit integers
* (the most significant byte is filled with the sign bit).
*/
SAMPLE_FORMAT_S24_P32,
SAMPLE_FORMAT_S32,
/**
* 32 bit floating point samples in the host's format. The
* range is -1.0f to +1.0f.
*/
SAMPLE_FORMAT_FLOAT,
/**
* Direct Stream Digital. 1-bit samples; each frame has one
* byte (8 samples) per channel.
*/
SAMPLE_FORMAT_DSD,
};
static const unsigned MAX_CHANNELS = 8;
/**
* This structure describes the format of a raw PCM stream.
*/
struct audio_format {
/**
* The sample rate in Hz. A better name for this attribute is
* "frame rate", because technically, you have two samples per
* frame in stereo sound.
*/
uint32_t sample_rate;
/**
* The format samples are stored in. See the #sample_format
* enum for valid values.
*/
uint8_t format;
/**
* The number of channels. Only mono (1) and stereo (2) are
* fully supported currently.
*/
uint8_t channels;
};
/**
* Buffer for audio_format_string().
*/
struct audio_format_string {
char buffer[24];
};
/**
* Clears the #audio_format object, i.e. sets all attributes to an
* undefined (invalid) value.
*/
static inline void audio_format_clear(struct audio_format *af)
{
af->sample_rate = 0;
af->format = SAMPLE_FORMAT_UNDEFINED;
af->channels = 0;
}
/**
* Initializes an #audio_format object, i.e. sets all
* attributes to valid values.
*/
static inline void audio_format_init(struct audio_format *af,
uint32_t sample_rate,
enum sample_format format, uint8_t channels)
{
af->sample_rate = sample_rate;
af->format = (uint8_t)format;
af->channels = channels;
}
/**
* Checks whether the specified #audio_format object has a defined
* value.
*/
static inline bool audio_format_defined(const struct audio_format *af)
{
return af->sample_rate != 0;
}
/**
* Checks whether the specified #audio_format object is full, i.e. all
* attributes are defined. This is more complete than
* audio_format_defined(), but slower.
*/
static inline bool
audio_format_fully_defined(const struct audio_format *af)
{
return af->sample_rate != 0 && af->format != SAMPLE_FORMAT_UNDEFINED &&
af->channels != 0;
}
/**
* Checks whether the specified #audio_format object has at least one
* defined value.
*/
static inline bool
audio_format_mask_defined(const struct audio_format *af)
{
return af->sample_rate != 0 || af->format != SAMPLE_FORMAT_UNDEFINED ||
af->channels != 0;
}
/**
* Checks whether the sample rate is valid.
*
* @param sample_rate the sample rate in Hz
*/
static inline bool
audio_valid_sample_rate(unsigned sample_rate)
{
return sample_rate > 0 && sample_rate < (1 << 30);
}
/**
* Checks whether the sample format is valid.
*
* @param bits the number of significant bits per sample
*/
static inline bool
audio_valid_sample_format(enum sample_format format)
{
switch (format) {
case SAMPLE_FORMAT_S8:
case SAMPLE_FORMAT_S16:
case SAMPLE_FORMAT_S24_P32:
case SAMPLE_FORMAT_S32:
case SAMPLE_FORMAT_FLOAT:
case SAMPLE_FORMAT_DSD:
return true;
case SAMPLE_FORMAT_UNDEFINED:
break;
}
return false;
}
/**
* Checks whether the number of channels is valid.
*/
static inline bool
audio_valid_channel_count(unsigned channels)
{
return channels >= 1 && channels <= MAX_CHANNELS;
}
/**
* Returns false if the format is not valid for playback with MPD.
* This function performs some basic validity checks.
*/
gcc_pure
static inline bool audio_format_valid(const struct audio_format *af)
{
return audio_valid_sample_rate(af->sample_rate) &&
audio_valid_sample_format((enum sample_format)af->format) &&
audio_valid_channel_count(af->channels);
}
/**
* Returns false if the format mask is not valid for playback with
* MPD. This function performs some basic validity checks.
*/
gcc_pure
static inline bool audio_format_mask_valid(const struct audio_format *af)
{
return (af->sample_rate == 0 ||
audio_valid_sample_rate(af->sample_rate)) &&
(af->format == SAMPLE_FORMAT_UNDEFINED ||
audio_valid_sample_format((enum sample_format)af->format)) &&
(af->channels == 0 || audio_valid_channel_count(af->channels));
}
static inline bool audio_format_equals(const struct audio_format *a,
const struct audio_format *b)
{
return a->sample_rate == b->sample_rate &&
a->format == b->format &&
a->channels == b->channels;
}
#ifdef __cplusplus
extern "C" {
#endif
void
audio_format_mask_apply(struct audio_format *af,
const struct audio_format *mask);
gcc_const
static inline unsigned
sample_format_size(enum sample_format format)
{
switch (format) {
case SAMPLE_FORMAT_S8:
return 1;
case SAMPLE_FORMAT_S16:
return 2;
case SAMPLE_FORMAT_S24_P32:
case SAMPLE_FORMAT_S32:
case SAMPLE_FORMAT_FLOAT:
return 4;
case SAMPLE_FORMAT_DSD:
/* each frame has 8 samples per channel */
return 1;
case SAMPLE_FORMAT_UNDEFINED:
return 0;
}
assert(false);
gcc_unreachable();
}
/**
* Returns the size of each (mono) sample in bytes.
*/
gcc_pure
static inline unsigned audio_format_sample_size(const struct audio_format *af)
{
return sample_format_size((enum sample_format)af->format);
}
/**
* Returns the size of each full frame in bytes.
*/
gcc_pure
static inline unsigned
audio_format_frame_size(const struct audio_format *af)
{
return audio_format_sample_size(af) * af->channels;
}
/**
* Returns the floating point factor which converts a time span to a
* storage size in bytes.
*/
gcc_pure
static inline double audio_format_time_to_size(const struct audio_format *af)
{
return af->sample_rate * audio_format_frame_size(af);
}
/**
* Renders a #sample_format enum into a string, e.g. for printing it
* in a log file.
*
* @param format a #sample_format enum value
* @return the string
*/
gcc_pure gcc_malloc
const char *
sample_format_to_string(enum sample_format format);
/**
* Renders the #audio_format object into a string, e.g. for printing
* it in a log file.
*
* @param af the #audio_format object
* @param s a buffer to print into
* @return the string, or NULL if the #audio_format object is invalid
*/
gcc_pure gcc_malloc
const char *
audio_format_to_string(const struct audio_format *af,
struct audio_format_string *s);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -60,11 +60,10 @@ adplug_file_decode(struct decoder *decoder, const char *path_fs)
if (player == nullptr) if (player == nullptr)
return; return;
struct audio_format audio_format; const AudioFormat audio_format(sample_rate, SampleFormat::S16, 2);
audio_format_init(&audio_format, sample_rate, SAMPLE_FORMAT_S16, 2); assert(audio_format.IsValid());
assert(audio_format_valid(&audio_format));
decoder_initialized(decoder, &audio_format, false, decoder_initialized(decoder, audio_format, false,
player->songlength() / 1000.); player->songlength() / 1000.);
int16_t buffer[2048]; int16_t buffer[2048];

View File

@ -114,27 +114,27 @@ setup_virtual_fops(struct input_stream *stream)
return vf; return vf;
} }
static enum sample_format static SampleFormat
audiofile_bits_to_sample_format(int bits) audiofile_bits_to_sample_format(int bits)
{ {
switch (bits) { switch (bits) {
case 8: case 8:
return SAMPLE_FORMAT_S8; return SampleFormat::S8;
case 16: case 16:
return SAMPLE_FORMAT_S16; return SampleFormat::S16;
case 24: case 24:
return SAMPLE_FORMAT_S24_P32; return SampleFormat::S24_P32;
case 32: case 32:
return SAMPLE_FORMAT_S32; return SampleFormat::S32;
} }
return SAMPLE_FORMAT_UNDEFINED; return SampleFormat::UNDEFINED;
} }
static enum sample_format static SampleFormat
audiofile_setup_sample_format(AFfilehandle af_fp) audiofile_setup_sample_format(AFfilehandle af_fp)
{ {
int fs, bits; int fs, bits;
@ -160,7 +160,7 @@ audiofile_stream_decode(struct decoder *decoder, struct input_stream *is)
AFvirtualfile *vf; AFvirtualfile *vf;
int fs, frame_count; int fs, frame_count;
AFfilehandle af_fp; AFfilehandle af_fp;
struct audio_format audio_format; AudioFormat audio_format;
float total_time; float total_time;
uint16_t bit_rate; uint16_t bit_rate;
int ret; int ret;
@ -180,7 +180,7 @@ audiofile_stream_decode(struct decoder *decoder, struct input_stream *is)
return; return;
} }
if (!audio_format_init_checked(&audio_format, if (!audio_format_init_checked(audio_format,
afGetRate(af_fp, AF_DEFAULT_TRACK), afGetRate(af_fp, AF_DEFAULT_TRACK),
audiofile_setup_sample_format(af_fp), audiofile_setup_sample_format(af_fp),
afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK), afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK),
@ -199,7 +199,7 @@ audiofile_stream_decode(struct decoder *decoder, struct input_stream *is)
fs = (int)afGetVirtualFrameSize(af_fp, AF_DEFAULT_TRACK, 1); fs = (int)afGetVirtualFrameSize(af_fp, AF_DEFAULT_TRACK, 1);
decoder_initialized(decoder, &audio_format, true, total_time); decoder_initialized(decoder, audio_format, true, total_time);
do { do {
ret = afReadFrames(af_fp, AF_DEFAULT_TRACK, chunk, ret = afReadFrames(af_fp, AF_DEFAULT_TRACK, chunk,

View File

@ -433,9 +433,9 @@ dsdiff_stream_decode(struct decoder *decoder, struct input_stream *is)
return; return;
GError *error = nullptr; GError *error = nullptr;
struct audio_format audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8, if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8,
SAMPLE_FORMAT_DSD, SampleFormat::DSD,
metadata.channels, &error)) { metadata.channels, &error)) {
g_warning("%s", error->message); g_warning("%s", error->message);
g_error_free(error); g_error_free(error);
@ -448,7 +448,7 @@ dsdiff_stream_decode(struct decoder *decoder, struct input_stream *is)
(float) metadata.sample_rate; (float) metadata.sample_rate;
/* success: file was recognized */ /* success: file was recognized */
decoder_initialized(decoder, &audio_format, false, songtime); decoder_initialized(decoder, audio_format, false, songtime);
/* every iteration of the following loop decodes one "DSD" /* every iteration of the following loop decodes one "DSD"
chunk from a DFF file */ chunk from a DFF file */
@ -487,9 +487,9 @@ dsdiff_scan_stream(struct input_stream *is,
if (!dsdiff_read_metadata(nullptr, is, &metadata, &chunk_header)) if (!dsdiff_read_metadata(nullptr, is, &metadata, &chunk_header))
return false; return false;
struct audio_format audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8, if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8,
SAMPLE_FORMAT_DSD, SampleFormat::DSD,
metadata.channels, nullptr)) metadata.channels, nullptr))
/* refuse to parse files which we cannot play anyway */ /* refuse to parse files which we cannot play anyway */
return false; return false;

View File

@ -285,9 +285,9 @@ dsf_stream_decode(struct decoder *decoder, struct input_stream *is)
return; return;
GError *error = NULL; GError *error = NULL;
struct audio_format audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8, if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8,
SAMPLE_FORMAT_DSD, SampleFormat::DSD,
metadata.channels, &error)) { metadata.channels, &error)) {
g_warning("%s", error->message); g_warning("%s", error->message);
g_error_free(error); g_error_free(error);
@ -299,7 +299,7 @@ dsf_stream_decode(struct decoder *decoder, struct input_stream *is)
(float) metadata.sample_rate; (float) metadata.sample_rate;
/* success: file was recognized */ /* success: file was recognized */
decoder_initialized(decoder, &audio_format, false, songtime); decoder_initialized(decoder, audio_format, false, songtime);
if (!dsf_decode_chunk(decoder, is, metadata.channels, if (!dsf_decode_chunk(decoder, is, metadata.channels,
chunk_size, chunk_size,
@ -317,9 +317,9 @@ dsf_scan_stream(struct input_stream *is,
if (!dsf_read_metadata(NULL, is, &metadata)) if (!dsf_read_metadata(NULL, is, &metadata))
return false; return false;
struct audio_format audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8, if (!audio_format_init_checked(audio_format, metadata.sample_rate / 8,
SAMPLE_FORMAT_DSD, SampleFormat::DSD,
metadata.channels, NULL)) metadata.channels, NULL))
/* refuse to parse files which we cannot play anyway */ /* refuse to parse files which we cannot play anyway */
return false; return false;

View File

@ -248,7 +248,7 @@ faad_song_duration(DecoderBuffer *buffer, struct input_stream *is)
*/ */
static bool static bool
faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer, faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer,
struct audio_format *audio_format, GError **error_r) AudioFormat &audio_format, GError **error_r)
{ {
int32_t nbytes; int32_t nbytes;
uint32_t sample_rate; uint32_t sample_rate;
@ -285,7 +285,7 @@ faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer,
decoder_buffer_consume(buffer, nbytes); decoder_buffer_consume(buffer, nbytes);
return audio_format_init_checked(audio_format, sample_rate, return audio_format_init_checked(audio_format, sample_rate,
SAMPLE_FORMAT_S16, channels, error_r); SampleFormat::S16, channels, error_r);
} }
/** /**
@ -325,7 +325,7 @@ faad_get_file_time_float(struct input_stream *is)
if (length < 0) { if (length < 0) {
bool ret; bool ret;
struct audio_format audio_format; AudioFormat audio_format;
NeAACDecHandle decoder = NeAACDecOpen(); NeAACDecHandle decoder = NeAACDecOpen();
@ -336,7 +336,7 @@ faad_get_file_time_float(struct input_stream *is)
decoder_buffer_fill(buffer); decoder_buffer_fill(buffer);
ret = faad_decoder_init(decoder, buffer, &audio_format, nullptr); ret = faad_decoder_init(decoder, buffer, audio_format, nullptr);
if (ret) if (ret)
length = 0; length = 0;
@ -370,7 +370,7 @@ faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is)
{ {
GError *error = nullptr; GError *error = nullptr;
float total_time = 0; float total_time = 0;
struct audio_format audio_format; AudioFormat audio_format;
bool ret; bool ret;
uint16_t bit_rate = 0; uint16_t bit_rate = 0;
DecoderBuffer *buffer; DecoderBuffer *buffer;
@ -400,7 +400,7 @@ faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is)
/* initialize it */ /* initialize it */
ret = faad_decoder_init(decoder, buffer, &audio_format, &error); ret = faad_decoder_init(decoder, buffer, audio_format, &error);
if (!ret) { if (!ret) {
g_warning("%s", error->message); g_warning("%s", error->message);
g_error_free(error); g_error_free(error);
@ -410,7 +410,7 @@ faad_stream_decode(struct decoder *mpd_decoder, struct input_stream *is)
/* initialize the MPD core */ /* initialize the MPD core */
decoder_initialized(mpd_decoder, &audio_format, false, total_time); decoder_initialized(mpd_decoder, audio_format, false, total_time);
/* the decoder loop */ /* the decoder loop */

View File

@ -52,6 +52,11 @@ extern "C" {
#undef G_LOG_DOMAIN #undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "ffmpeg" #define G_LOG_DOMAIN "ffmpeg"
/* suppress the ffmpeg compatibility macro */
#ifdef SampleFormat
#undef SampleFormat
#endif
static GLogLevelFlags static GLogLevelFlags
level_ffmpeg_to_glib(int level) level_ffmpeg_to_glib(int level)
{ {
@ -297,20 +302,20 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is,
} }
G_GNUC_CONST G_GNUC_CONST
static enum sample_format static SampleFormat
ffmpeg_sample_format(enum AVSampleFormat sample_fmt) ffmpeg_sample_format(enum AVSampleFormat sample_fmt)
{ {
switch (sample_fmt) { switch (sample_fmt) {
case AV_SAMPLE_FMT_S16: case AV_SAMPLE_FMT_S16:
case AV_SAMPLE_FMT_S16P: case AV_SAMPLE_FMT_S16P:
return SAMPLE_FORMAT_S16; return SampleFormat::S16;
case AV_SAMPLE_FMT_S32: case AV_SAMPLE_FMT_S32:
case AV_SAMPLE_FMT_S32P: case AV_SAMPLE_FMT_S32P:
return SAMPLE_FORMAT_S32; return SampleFormat::S32;
case AV_SAMPLE_FMT_FLTP: case AV_SAMPLE_FMT_FLTP:
return SAMPLE_FORMAT_FLOAT; return SampleFormat::FLOAT;
default: default:
break; break;
@ -325,7 +330,7 @@ ffmpeg_sample_format(enum AVSampleFormat sample_fmt)
else else
g_warning("Unsupported libavcodec SampleFormat value: %d", g_warning("Unsupported libavcodec SampleFormat value: %d",
sample_fmt); sample_fmt);
return SAMPLE_FORMAT_UNDEFINED; return SampleFormat::UNDEFINED;
} }
static AVInputFormat * static AVInputFormat *
@ -420,14 +425,14 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
return; return;
} }
const enum sample_format sample_format = const SampleFormat sample_format =
ffmpeg_sample_format(codec_context->sample_fmt); ffmpeg_sample_format(codec_context->sample_fmt);
if (sample_format == SAMPLE_FORMAT_UNDEFINED) if (sample_format == SampleFormat::UNDEFINED)
return; return;
GError *error = NULL; GError *error = NULL;
struct audio_format audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(&audio_format, if (!audio_format_init_checked(audio_format,
codec_context->sample_rate, codec_context->sample_rate,
sample_format, sample_format,
codec_context->channels, &error)) { codec_context->channels, &error)) {
@ -455,7 +460,7 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
? format_context->duration / AV_TIME_BASE ? format_context->duration / AV_TIME_BASE
: 0; : 0;
decoder_initialized(decoder, &audio_format, decoder_initialized(decoder, audio_format,
input->seekable, total_time); input->seekable, total_time);
AVFrame *frame = avcodec_alloc_frame(); AVFrame *frame = avcodec_alloc_frame();

View File

@ -26,6 +26,11 @@ extern "C" {
#include <libavutil/dict.h> #include <libavutil/dict.h>
} }
/* suppress the ffmpeg compatibility macro */
#ifdef SampleFormat
#undef SampleFormat
#endif
struct tag_handler; struct tag_handler;
void void

View File

@ -40,24 +40,24 @@ flac_data::flac_data(struct decoder *_decoder,
{ {
} }
static enum sample_format static SampleFormat
flac_sample_format(unsigned bits_per_sample) flac_sample_format(unsigned bits_per_sample)
{ {
switch (bits_per_sample) { switch (bits_per_sample) {
case 8: case 8:
return SAMPLE_FORMAT_S8; return SampleFormat::S8;
case 16: case 16:
return SAMPLE_FORMAT_S16; return SampleFormat::S16;
case 24: case 24:
return SAMPLE_FORMAT_S24_P32; return SampleFormat::S24_P32;
case 32: case 32:
return SAMPLE_FORMAT_S32; return SampleFormat::S32;
default: default:
return SAMPLE_FORMAT_UNDEFINED; return SampleFormat::UNDEFINED;
} }
} }
@ -69,7 +69,7 @@ flac_got_stream_info(struct flac_data *data,
return; return;
GError *error = nullptr; GError *error = nullptr;
if (!audio_format_init_checked(&data->audio_format, if (!audio_format_init_checked(data->audio_format,
stream_info->sample_rate, stream_info->sample_rate,
flac_sample_format(stream_info->bits_per_sample), flac_sample_format(stream_info->bits_per_sample),
stream_info->channels, &error)) { stream_info->channels, &error)) {
@ -79,7 +79,7 @@ flac_got_stream_info(struct flac_data *data,
return; return;
} }
data->frame_size = audio_format_frame_size(&data->audio_format); data->frame_size = data->audio_format.GetFrameSize();
if (data->total_frames == 0) if (data->total_frames == 0)
data->total_frames = stream_info->total_samples; data->total_frames = stream_info->total_samples;
@ -132,7 +132,7 @@ flac_got_first_frame(struct flac_data *data, const FLAC__FrameHeader *header)
return false; return false;
GError *error = nullptr; GError *error = nullptr;
if (!audio_format_init_checked(&data->audio_format, if (!audio_format_init_checked(data->audio_format,
header->sample_rate, header->sample_rate,
flac_sample_format(header->bits_per_sample), flac_sample_format(header->bits_per_sample),
header->channels, &error)) { header->channels, &error)) {
@ -142,9 +142,9 @@ flac_got_first_frame(struct flac_data *data, const FLAC__FrameHeader *header)
return false; return false;
} }
data->frame_size = audio_format_frame_size(&data->audio_format); data->frame_size = data->audio_format.GetFrameSize();
decoder_initialized(data->decoder, &data->audio_format, decoder_initialized(data->decoder, data->audio_format,
data->input_stream->seekable, data->input_stream->seekable,
(float)data->total_frames / (float)data->total_frames /
(float)data->audio_format.sample_rate); (float)data->audio_format.sample_rate);
@ -170,7 +170,7 @@ flac_common_write(struct flac_data *data, const FLAC__Frame * frame,
buffer = data->buffer.Get(buffer_size); buffer = data->buffer.Get(buffer_size);
flac_convert(buffer, frame->header.channels, flac_convert(buffer, frame->header.channels,
(enum sample_format)data->audio_format.format, buf, data->audio_format.format, buf,
0, frame->header.blocksize); 0, frame->header.blocksize);
if (nbytes > 0) if (nbytes > 0)

View File

@ -56,7 +56,7 @@ struct flac_data : public FlacInput {
* The validated audio format of the FLAC file. This * The validated audio format of the FLAC file. This
* attribute is defined if "initialized" is true. * attribute is defined if "initialized" is true.
*/ */
struct audio_format audio_format; AudioFormat audio_format;
/** /**
* The total number of frames in this song. The decoder * The total number of frames in this song. The decoder

View File

@ -144,7 +144,7 @@ flac_decoder_initialize(struct flac_data *data, FLAC__StreamDecoder *sd,
if (data->initialized) { if (data->initialized) {
/* done */ /* done */
decoder_initialized(data->decoder, &data->audio_format, decoder_initialized(data->decoder, data->audio_format,
data->input_stream->seekable, data->input_stream->seekable,
(float)data->total_frames / (float)data->total_frames /
(float)data->audio_format.sample_rate); (float)data->audio_format.sample_rate);

View File

@ -76,12 +76,12 @@ flac_convert_8(int8_t *dest,
void void
flac_convert(void *dest, flac_convert(void *dest,
unsigned int num_channels, enum sample_format sample_format, unsigned int num_channels, SampleFormat sample_format,
const FLAC__int32 *const buf[], const FLAC__int32 *const buf[],
unsigned int position, unsigned int end) unsigned int position, unsigned int end)
{ {
switch (sample_format) { switch (sample_format) {
case SAMPLE_FORMAT_S16: case SampleFormat::S16:
if (num_channels == 2) if (num_channels == 2)
flac_convert_stereo16((int16_t*)dest, buf, flac_convert_stereo16((int16_t*)dest, buf,
position, end); position, end);
@ -90,20 +90,20 @@ flac_convert(void *dest,
position, end); position, end);
break; break;
case SAMPLE_FORMAT_S24_P32: case SampleFormat::S24_P32:
case SAMPLE_FORMAT_S32: case SampleFormat::S32:
flac_convert_32((int32_t*)dest, num_channels, buf, flac_convert_32((int32_t*)dest, num_channels, buf,
position, end); position, end);
break; break;
case SAMPLE_FORMAT_S8: case SampleFormat::S8:
flac_convert_8((int8_t*)dest, num_channels, buf, flac_convert_8((int8_t*)dest, num_channels, buf,
position, end); position, end);
break; break;
case SAMPLE_FORMAT_FLOAT: case SampleFormat::FLOAT:
case SAMPLE_FORMAT_DSD: case SampleFormat::DSD:
case SAMPLE_FORMAT_UNDEFINED: case SampleFormat::UNDEFINED:
assert(false); assert(false);
gcc_unreachable(); gcc_unreachable();
} }

View File

@ -20,13 +20,13 @@
#ifndef MPD_FLAC_PCM_HXX #ifndef MPD_FLAC_PCM_HXX
#define MPD_FLAC_PCM_HXX #define MPD_FLAC_PCM_HXX
#include "audio_format.h" #include "AudioFormat.hxx"
#include <FLAC/ordinals.h> #include <FLAC/ordinals.h>
void void
flac_convert(void *dest, flac_convert(void *dest,
unsigned int num_channels, enum sample_format sample_format, unsigned int num_channels, SampleFormat sample_format,
const FLAC__int32 *const buf[], const FLAC__int32 *const buf[],
unsigned int position, unsigned int end); unsigned int position, unsigned int end);

View File

@ -166,9 +166,8 @@ fluidsynth_file_decode(struct decoder *decoder, const char *path_fs)
/* initialization complete - announce the audio format to the /* initialization complete - announce the audio format to the
MPD core */ MPD core */
struct audio_format audio_format; const AudioFormat audio_format(sample_rate, SampleFormat::S16, 2);
audio_format_init(&audio_format, sample_rate, SAMPLE_FORMAT_S16, 2); decoder_initialized(decoder, audio_format, false, -1);
decoder_initialized(decoder, &audio_format, false, -1);
while (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING) { while (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING) {
int16_t buffer[2048]; int16_t buffer[2048];

View File

@ -153,9 +153,9 @@ gme_file_decode(struct decoder *decoder, const char *path_fs)
/* initialize the MPD decoder */ /* initialize the MPD decoder */
GError *error = nullptr; GError *error = nullptr;
struct audio_format audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(&audio_format, GME_SAMPLE_RATE, if (!audio_format_init_checked(audio_format, GME_SAMPLE_RATE,
SAMPLE_FORMAT_S16, GME_CHANNELS, SampleFormat::S16, GME_CHANNELS,
&error)) { &error)) {
g_warning("%s", error->message); g_warning("%s", error->message);
g_error_free(error); g_error_free(error);
@ -164,7 +164,7 @@ gme_file_decode(struct decoder *decoder, const char *path_fs)
return; return;
} }
decoder_initialized(decoder, &audio_format, true, song_len); decoder_initialized(decoder, audio_format, true, song_len);
gme_err = gme_start_track(emu, song_num); gme_err = gme_start_track(emu, song_num);
if (gme_err != nullptr) if (gme_err != nullptr)

View File

@ -1124,11 +1124,11 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream)
return; return;
} }
struct audio_format audio_format; AudioFormat audio_format;
GError *error = nullptr; GError *error = nullptr;
if (!audio_format_init_checked(&audio_format, if (!audio_format_init_checked(audio_format,
data.frame.header.samplerate, data.frame.header.samplerate,
SAMPLE_FORMAT_S24_P32, SampleFormat::S24_P32,
MAD_NCHANNELS(&data.frame.header), MAD_NCHANNELS(&data.frame.header),
&error)) { &error)) {
g_warning("%s", error->message); g_warning("%s", error->message);
@ -1138,7 +1138,7 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream)
return; return;
} }
decoder_initialized(decoder, &audio_format, decoder_initialized(decoder, audio_format,
input_stream_is_seekable(input_stream), input_stream_is_seekable(input_stream),
data.total_time); data.total_time);

View File

@ -147,7 +147,6 @@ mikmod_decoder_file_decode(struct decoder *decoder, const char *path_fs)
{ {
char *path2; char *path2;
MODULE *handle; MODULE *handle;
struct audio_format audio_format;
int ret; int ret;
SBYTE buffer[MIKMOD_FRAME_SIZE]; SBYTE buffer[MIKMOD_FRAME_SIZE];
enum decoder_command cmd = DECODE_COMMAND_NONE; enum decoder_command cmd = DECODE_COMMAND_NONE;
@ -164,10 +163,10 @@ mikmod_decoder_file_decode(struct decoder *decoder, const char *path_fs)
/* Prevent module from looping forever */ /* Prevent module from looping forever */
handle->loop = 0; handle->loop = 0;
audio_format_init(&audio_format, mikmod_sample_rate, SAMPLE_FORMAT_S16, 2); const AudioFormat audio_format(mikmod_sample_rate, SampleFormat::S16, 2);
assert(audio_format_valid(&audio_format)); assert(audio_format.IsValid());
decoder_initialized(decoder, &audio_format, false, 0); decoder_initialized(decoder, audio_format, false, 0);
Player_Start(handle); Player_Start(handle);
while (cmd == DECODE_COMMAND_NONE && Player_Active()) { while (cmd == DECODE_COMMAND_NONE && Player_Active()) {

View File

@ -94,7 +94,6 @@ mod_decode(struct decoder *decoder, struct input_stream *is)
ModPlugFile *f; ModPlugFile *f;
ModPlug_Settings settings; ModPlug_Settings settings;
GByteArray *bdatas; GByteArray *bdatas;
struct audio_format audio_format;
int ret; int ret;
char audio_buffer[MODPLUG_FRAME_SIZE]; char audio_buffer[MODPLUG_FRAME_SIZE];
enum decoder_command cmd = DECODE_COMMAND_NONE; enum decoder_command cmd = DECODE_COMMAND_NONE;
@ -122,10 +121,10 @@ mod_decode(struct decoder *decoder, struct input_stream *is)
return; return;
} }
audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2); static constexpr AudioFormat audio_format(44100, SampleFormat::S16, 2);
assert(audio_format_valid(&audio_format)); assert(audio_format.IsValid());
decoder_initialized(decoder, &audio_format, decoder_initialized(decoder, audio_format,
input_stream_is_seekable(is), input_stream_is_seekable(is),
ModPlug_GetLength(f) / 1000.0); ModPlug_GetLength(f) / 1000.0);

View File

@ -154,9 +154,9 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is)
mpc_demux_get_info(demux, &info); mpc_demux_get_info(demux, &info);
GError *error = nullptr; GError *error = nullptr;
struct audio_format audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(&audio_format, info.sample_freq, if (!audio_format_init_checked(audio_format, info.sample_freq,
SAMPLE_FORMAT_S24_P32, SampleFormat::S24_P32,
info.channels, &error)) { info.channels, &error)) {
g_warning("%s", error->message); g_warning("%s", error->message);
g_error_free(error); g_error_free(error);
@ -173,7 +173,7 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is)
decoder_replay_gain(mpd_decoder, &replay_gain_info); decoder_replay_gain(mpd_decoder, &replay_gain_info);
decoder_initialized(mpd_decoder, &audio_format, decoder_initialized(mpd_decoder, audio_format,
input_stream_is_seekable(is), input_stream_is_seekable(is),
mpc_streaminfo_get_length(&info)); mpc_streaminfo_get_length(&info));

View File

@ -56,7 +56,7 @@ mpd_mpg123_finish(void)
*/ */
static bool static bool
mpd_mpg123_open(mpg123_handle *handle, const char *path_fs, mpd_mpg123_open(mpg123_handle *handle, const char *path_fs,
struct audio_format *audio_format) AudioFormat &audio_format)
{ {
GError *gerror = nullptr; GError *gerror = nullptr;
char *path_dup; char *path_dup;
@ -90,7 +90,7 @@ mpd_mpg123_open(mpg123_handle *handle, const char *path_fs,
return false; return false;
} }
if (!audio_format_init_checked(audio_format, rate, SAMPLE_FORMAT_S16, if (!audio_format_init_checked(audio_format, rate, SampleFormat::S16,
channels, &gerror)) { channels, &gerror)) {
g_warning("%s", gerror->message); g_warning("%s", gerror->message);
g_error_free(gerror); g_error_free(gerror);
@ -103,7 +103,6 @@ mpd_mpg123_open(mpg123_handle *handle, const char *path_fs,
static void static void
mpd_mpg123_file_decode(struct decoder *decoder, const char *path_fs) mpd_mpg123_file_decode(struct decoder *decoder, const char *path_fs)
{ {
struct audio_format audio_format;
mpg123_handle *handle; mpg123_handle *handle;
int error; int error;
off_t num_samples; off_t num_samples;
@ -119,7 +118,8 @@ mpd_mpg123_file_decode(struct decoder *decoder, const char *path_fs)
return; return;
} }
if (!mpd_mpg123_open(handle, path_fs, &audio_format)) { AudioFormat audio_format;
if (!mpd_mpg123_open(handle, path_fs, audio_format)) {
mpg123_delete(handle); mpg123_delete(handle);
return; return;
} }
@ -128,7 +128,7 @@ mpd_mpg123_file_decode(struct decoder *decoder, const char *path_fs)
/* tell MPD core we're ready */ /* tell MPD core we're ready */
decoder_initialized(decoder, &audio_format, true, decoder_initialized(decoder, audio_format, true,
(float)num_samples / (float)num_samples /
(float)audio_format.sample_rate); (float)audio_format.sample_rate);
@ -198,7 +198,6 @@ static bool
mpd_mpg123_scan_file(const char *path_fs, mpd_mpg123_scan_file(const char *path_fs,
const struct tag_handler *handler, void *handler_ctx) const struct tag_handler *handler, void *handler_ctx)
{ {
struct audio_format audio_format;
mpg123_handle *handle; mpg123_handle *handle;
int error; int error;
off_t num_samples; off_t num_samples;
@ -210,7 +209,8 @@ mpd_mpg123_scan_file(const char *path_fs,
return false; return false;
} }
if (!mpd_mpg123_open(handle, path_fs, &audio_format)) { AudioFormat audio_format;
if (!mpd_mpg123_open(handle, path_fs, audio_format)) {
mpg123_delete(handle); mpg123_delete(handle);
return false; return false;
} }

View File

@ -202,11 +202,10 @@ MPDOpusDecoder::HandleBOS(const ogg_packet &packet)
return DECODE_COMMAND_STOP; return DECODE_COMMAND_STOP;
} }
struct audio_format audio_format; const AudioFormat audio_format(opus_sample_rate,
audio_format_init(&audio_format, opus_sample_rate, SampleFormat::S16, channels);
SAMPLE_FORMAT_S16, channels); decoder_initialized(decoder, audio_format, false, -1);
decoder_initialized(decoder, &audio_format, false, -1); frame_size = audio_format.GetFrameSize();
frame_size = audio_format_frame_size(&audio_format);
/* allocate an output buffer for 16 bit PCM samples big enough /* allocate an output buffer for 16 bit PCM samples big enough
to hold a quarter second, larger than 120ms required by to hold a quarter second, larger than 120ms required by

View File

@ -36,9 +36,9 @@ extern "C" {
static void static void
pcm_stream_decode(struct decoder *decoder, struct input_stream *is) pcm_stream_decode(struct decoder *decoder, struct input_stream *is)
{ {
static constexpr struct audio_format audio_format = { static constexpr AudioFormat audio_format = {
44100, 44100,
SAMPLE_FORMAT_S16, SampleFormat::S16,
2, 2,
}; };
@ -49,14 +49,14 @@ pcm_stream_decode(struct decoder *decoder, struct input_stream *is)
GError *error = nullptr; GError *error = nullptr;
enum decoder_command cmd; enum decoder_command cmd;
double time_to_size = audio_format_time_to_size(&audio_format); const double time_to_size = audio_format.GetTimeToSize();
float total_time = -1; float total_time = -1;
const goffset size = input_stream_get_size(is); const goffset size = input_stream_get_size(is);
if (size >= 0) if (size >= 0)
total_time = size / time_to_size; total_time = size / time_to_size;
decoder_initialized(decoder, &audio_format, decoder_initialized(decoder, audio_format,
input_stream_is_seekable(is), total_time); input_stream_is_seekable(is), total_time);
do { do {

View File

@ -99,7 +99,7 @@ static SF_VIRTUAL_IO vio = {
* Converts a frame number to a timestamp (in seconds). * Converts a frame number to a timestamp (in seconds).
*/ */
static float static float
frame_to_time(sf_count_t frame, const struct audio_format *audio_format) frame_to_time(sf_count_t frame, const AudioFormat *audio_format)
{ {
return (float)frame / (float)audio_format->sample_rate; return (float)frame / (float)audio_format->sample_rate;
} }
@ -108,7 +108,7 @@ frame_to_time(sf_count_t frame, const struct audio_format *audio_format)
* Converts a timestamp (in seconds) to a frame number. * Converts a timestamp (in seconds) to a frame number.
*/ */
static sf_count_t static sf_count_t
time_to_frame(float t, const struct audio_format *audio_format) time_to_frame(float t, const AudioFormat *audio_format)
{ {
return (sf_count_t)(t * audio_format->sample_rate); return (sf_count_t)(t * audio_format->sample_rate);
} }
@ -119,7 +119,6 @@ sndfile_stream_decode(struct decoder *decoder, struct input_stream *is)
GError *error = nullptr; GError *error = nullptr;
SNDFILE *sf; SNDFILE *sf;
SF_INFO info; SF_INFO info;
struct audio_format audio_format;
size_t frame_size; size_t frame_size;
sf_count_t read_frames, num_frames; sf_count_t read_frames, num_frames;
int buffer[4096]; int buffer[4096];
@ -136,18 +135,19 @@ sndfile_stream_decode(struct decoder *decoder, struct input_stream *is)
/* for now, always read 32 bit samples. Later, we could lower /* for now, always read 32 bit samples. Later, we could lower
MPD's CPU usage by reading 16 bit samples with MPD's CPU usage by reading 16 bit samples with
sf_readf_short() on low-quality source files. */ sf_readf_short() on low-quality source files. */
if (!audio_format_init_checked(&audio_format, info.samplerate, AudioFormat audio_format;
SAMPLE_FORMAT_S32, if (!audio_format_init_checked(audio_format, info.samplerate,
SampleFormat::S32,
info.channels, &error)) { info.channels, &error)) {
g_warning("%s", error->message); g_warning("%s", error->message);
g_error_free(error); g_error_free(error);
return; return;
} }
decoder_initialized(decoder, &audio_format, info.seekable, decoder_initialized(decoder, audio_format, info.seekable,
frame_to_time(info.frames, &audio_format)); frame_to_time(info.frames, &audio_format));
frame_size = audio_format_frame_size(&audio_format); frame_size = audio_format.GetFrameSize();
read_frames = sizeof(buffer) / frame_size; read_frames = sizeof(buffer) / frame_size;
do { do {

View File

@ -202,12 +202,12 @@ vorbis_stream_decode(struct decoder *decoder,
return; return;
} }
struct audio_format audio_format; AudioFormat audio_format;
if (!audio_format_init_checked(&audio_format, vi->rate, if (!audio_format_init_checked(audio_format, vi->rate,
#ifdef HAVE_TREMOR #ifdef HAVE_TREMOR
SAMPLE_FORMAT_S16, SampleFormat::S16,
#else #else
SAMPLE_FORMAT_FLOAT, SampleFormat::FLOAT,
#endif #endif
vi->channels, &error)) { vi->channels, &error)) {
g_warning("%s", error->message); g_warning("%s", error->message);
@ -219,7 +219,7 @@ vorbis_stream_decode(struct decoder *decoder,
if (total_time < 0) if (total_time < 0)
total_time = 0; total_time = 0;
decoder_initialized(decoder, &audio_format, vis.seekable, total_time); decoder_initialized(decoder, audio_format, vis.seekable, total_time);
enum decoder_command cmd = decoder_get_command(decoder); enum decoder_command cmd = decoder_get_command(decoder);

View File

@ -106,27 +106,27 @@ format_samples_float(G_GNUC_UNUSED int bytes_per_sample, void *buffer,
/** /**
* Choose a MPD sample format from libwavpacks' number of bits. * Choose a MPD sample format from libwavpacks' number of bits.
*/ */
static enum sample_format static SampleFormat
wavpack_bits_to_sample_format(bool is_float, int bytes_per_sample) wavpack_bits_to_sample_format(bool is_float, int bytes_per_sample)
{ {
if (is_float) if (is_float)
return SAMPLE_FORMAT_FLOAT; return SampleFormat::FLOAT;
switch (bytes_per_sample) { switch (bytes_per_sample) {
case 1: case 1:
return SAMPLE_FORMAT_S8; return SampleFormat::S8;
case 2: case 2:
return SAMPLE_FORMAT_S16; return SampleFormat::S16;
case 3: case 3:
return SAMPLE_FORMAT_S24_P32; return SampleFormat::S24_P32;
case 4: case 4:
return SAMPLE_FORMAT_S32; return SampleFormat::S32;
default: default:
return SAMPLE_FORMAT_UNDEFINED; return SampleFormat::UNDEFINED;
} }
} }
@ -139,8 +139,8 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek)
{ {
GError *error = NULL; GError *error = NULL;
bool is_float; bool is_float;
enum sample_format sample_format; SampleFormat sample_format;
struct audio_format audio_format; AudioFormat audio_format;
format_samples_t format_samples; format_samples_t format_samples;
float total_time; float total_time;
int bytes_per_sample, output_sample_size; int bytes_per_sample, output_sample_size;
@ -150,7 +150,7 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek)
wavpack_bits_to_sample_format(is_float, wavpack_bits_to_sample_format(is_float,
WavpackGetBytesPerSample(wpc)); WavpackGetBytesPerSample(wpc));
if (!audio_format_init_checked(&audio_format, if (!audio_format_init_checked(audio_format,
WavpackGetSampleRate(wpc), WavpackGetSampleRate(wpc),
sample_format, sample_format,
WavpackGetNumChannels(wpc), &error)) { WavpackGetNumChannels(wpc), &error)) {
@ -168,14 +168,14 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek)
total_time = WavpackGetNumSamples(wpc); total_time = WavpackGetNumSamples(wpc);
total_time /= audio_format.sample_rate; total_time /= audio_format.sample_rate;
bytes_per_sample = WavpackGetBytesPerSample(wpc); bytes_per_sample = WavpackGetBytesPerSample(wpc);
output_sample_size = audio_format_frame_size(&audio_format); output_sample_size = audio_format.GetFrameSize();
/* wavpack gives us all kind of samples in a 32-bit space */ /* wavpack gives us all kind of samples in a 32-bit space */
int32_t chunk[1024]; int32_t chunk[1024];
const uint32_t samples_requested = G_N_ELEMENTS(chunk) / const uint32_t samples_requested = G_N_ELEMENTS(chunk) /
audio_format.channels; audio_format.channels;
decoder_initialized(decoder, &audio_format, can_seek, total_time); decoder_initialized(decoder, audio_format, can_seek, total_time);
enum decoder_command cmd = decoder_get_command(decoder); enum decoder_command cmd = decoder_get_command(decoder);
while (cmd != DECODE_COMMAND_STOP) { while (cmd != DECODE_COMMAND_STOP) {

View File

@ -60,9 +60,9 @@ wildmidi_finish(void)
static void static void
wildmidi_file_decode(struct decoder *decoder, const char *path_fs) wildmidi_file_decode(struct decoder *decoder, const char *path_fs)
{ {
static const struct audio_format audio_format = { static constexpr AudioFormat audio_format = {
WILDMIDI_SAMPLE_RATE, WILDMIDI_SAMPLE_RATE,
SAMPLE_FORMAT_S16, SampleFormat::S16,
2, 2,
}; };
midi *wm; midi *wm;
@ -79,7 +79,7 @@ wildmidi_file_decode(struct decoder *decoder, const char *path_fs)
return; return;
} }
decoder_initialized(decoder, &audio_format, true, decoder_initialized(decoder, audio_format, true,
info->approx_total_samples / WILDMIDI_SAMPLE_RATE); info->approx_total_samples / WILDMIDI_SAMPLE_RATE);
do { do {

View File

@ -285,11 +285,10 @@ sidplay_file_decode(struct decoder *decoder, const char *path_fs)
/* initialize the MPD decoder */ /* initialize the MPD decoder */
struct audio_format audio_format; const AudioFormat audio_format(48000, SampleFormat::S16, channels);
audio_format_init(&audio_format, 48000, SAMPLE_FORMAT_S16, channels); assert(audio_format.IsValid());
assert(audio_format_valid(&audio_format));
decoder_initialized(decoder, &audio_format, true, (float)song_len); decoder_initialized(decoder, audio_format, true, (float)song_len);
/* .. and play */ /* .. and play */

View File

@ -20,7 +20,7 @@
#include "config.h" #include "config.h"
#include "FlacEncoderPlugin.hxx" #include "FlacEncoderPlugin.hxx"
#include "EncoderAPI.hxx" #include "EncoderAPI.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include "pcm/PcmBuffer.hxx" #include "pcm/PcmBuffer.hxx"
#include "util/fifo_buffer.h" #include "util/fifo_buffer.h"
@ -40,7 +40,7 @@ extern "C" {
struct flac_encoder { struct flac_encoder {
Encoder encoder; Encoder encoder;
struct audio_format audio_format; AudioFormat audio_format;
unsigned compression; unsigned compression;
FLAC__StreamEncoder *fse; FLAC__StreamEncoder *fse;
@ -160,31 +160,31 @@ flac_encoder_close(Encoder *_encoder)
} }
static bool static bool
flac_encoder_open(Encoder *_encoder, struct audio_format *audio_format, flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format,
GError **error) GError **error)
{ {
struct flac_encoder *encoder = (struct flac_encoder *)_encoder; struct flac_encoder *encoder = (struct flac_encoder *)_encoder;
unsigned bits_per_sample; unsigned bits_per_sample;
encoder->audio_format = *audio_format; encoder->audio_format = audio_format;
/* FIXME: flac should support 32bit as well */ /* FIXME: flac should support 32bit as well */
switch (audio_format->format) { switch (audio_format.format) {
case SAMPLE_FORMAT_S8: case SampleFormat::S8:
bits_per_sample = 8; bits_per_sample = 8;
break; break;
case SAMPLE_FORMAT_S16: case SampleFormat::S16:
bits_per_sample = 16; bits_per_sample = 16;
break; break;
case SAMPLE_FORMAT_S24_P32: case SampleFormat::S24_P32:
bits_per_sample = 24; bits_per_sample = 24;
break; break;
default: default:
bits_per_sample = 24; bits_per_sample = 24;
audio_format->format = SAMPLE_FORMAT_S24_P32; audio_format.format = SampleFormat::S24_P32;
} }
/* allocate the encoder */ /* allocate the encoder */
@ -263,30 +263,33 @@ flac_encoder_write(Encoder *_encoder,
/* format conversion */ /* format conversion */
num_frames = length / audio_format_frame_size(&encoder->audio_format); num_frames = length / encoder->audio_format.GetFrameSize();
num_samples = num_frames * encoder->audio_format.channels; num_samples = num_frames * encoder->audio_format.channels;
switch (encoder->audio_format.format) { switch (encoder->audio_format.format) {
case SAMPLE_FORMAT_S8: case SampleFormat::S8:
exbuffer = encoder->expand_buffer.Get(length * 4); exbuffer = encoder->expand_buffer.Get(length * 4);
pcm8_to_flac((int32_t *)exbuffer, (const int8_t *)data, pcm8_to_flac((int32_t *)exbuffer, (const int8_t *)data,
num_samples); num_samples);
buffer = exbuffer; buffer = exbuffer;
break; break;
case SAMPLE_FORMAT_S16: case SampleFormat::S16:
exbuffer = encoder->expand_buffer.Get(length * 2); exbuffer = encoder->expand_buffer.Get(length * 2);
pcm16_to_flac((int32_t *)exbuffer, (const int16_t *)data, pcm16_to_flac((int32_t *)exbuffer, (const int16_t *)data,
num_samples); num_samples);
buffer = exbuffer; buffer = exbuffer;
break; break;
case SAMPLE_FORMAT_S24_P32: case SampleFormat::S24_P32:
case SAMPLE_FORMAT_S32: case SampleFormat::S32:
/* nothing need to be done; format is the same for /* nothing need to be done; format is the same for
both mpd and libFLAC */ both mpd and libFLAC */
buffer = data; buffer = data;
break; break;
default:
gcc_unreachable();
} }
/* feed samples to encoder */ /* feed samples to encoder */

View File

@ -20,7 +20,7 @@
#include "config.h" #include "config.h"
#include "LameEncoderPlugin.hxx" #include "LameEncoderPlugin.hxx"
#include "EncoderAPI.hxx" #include "EncoderAPI.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include <lame/lame.h> #include <lame/lame.h>
@ -32,7 +32,7 @@
struct LameEncoder final { struct LameEncoder final {
Encoder encoder; Encoder encoder;
struct audio_format audio_format; AudioFormat audio_format;
float quality; float quality;
int bitrate; int bitrate;
@ -187,15 +187,15 @@ lame_encoder_setup(LameEncoder *encoder, GError **error)
} }
static bool static bool
lame_encoder_open(Encoder *_encoder, struct audio_format *audio_format, lame_encoder_open(Encoder *_encoder, AudioFormat &audio_format,
GError **error) GError **error)
{ {
LameEncoder *encoder = (LameEncoder *)_encoder; LameEncoder *encoder = (LameEncoder *)_encoder;
audio_format->format = SAMPLE_FORMAT_S16; audio_format.format = SampleFormat::S16;
audio_format->channels = 2; audio_format.channels = 2;
encoder->audio_format = *audio_format; encoder->audio_format = audio_format;
encoder->gfp = lame_init(); encoder->gfp = lame_init();
if (encoder->gfp == nullptr) { if (encoder->gfp == nullptr) {
@ -233,7 +233,7 @@ lame_encoder_write(Encoder *_encoder,
assert(encoder->buffer_length == 0); assert(encoder->buffer_length == 0);
const unsigned num_frames = const unsigned num_frames =
length / audio_format_frame_size(&encoder->audio_format); length / encoder->audio_format.GetFrameSize();
float *left = g_new(float, num_frames); float *left = g_new(float, num_frames);
float *right = g_new(float, num_frames); float *right = g_new(float, num_frames);

View File

@ -66,7 +66,7 @@ null_encoder_close(Encoder *_encoder)
static bool static bool
null_encoder_open(Encoder *_encoder, null_encoder_open(Encoder *_encoder,
gcc_unused struct audio_format *audio_format, gcc_unused AudioFormat &audio_format,
gcc_unused GError **error) gcc_unused GError **error)
{ {
NullEncoder *encoder = (NullEncoder *)_encoder; NullEncoder *encoder = (NullEncoder *)_encoder;

View File

@ -21,7 +21,7 @@
#include "OpusEncoderPlugin.hxx" #include "OpusEncoderPlugin.hxx"
#include "OggStream.hxx" #include "OggStream.hxx"
#include "EncoderAPI.hxx" #include "EncoderAPI.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include "mpd_error.h" #include "mpd_error.h"
#include <opus.h> #include <opus.h>
@ -44,7 +44,7 @@ struct opus_encoder {
/* runtime information */ /* runtime information */
struct audio_format audio_format; AudioFormat audio_format;
size_t frame_size; size_t frame_size;
@ -144,37 +144,37 @@ opus_encoder_finish(Encoder *_encoder)
static bool static bool
opus_encoder_open(Encoder *_encoder, opus_encoder_open(Encoder *_encoder,
struct audio_format *audio_format, AudioFormat &audio_format,
GError **error_r) GError **error_r)
{ {
struct opus_encoder *encoder = (struct opus_encoder *)_encoder; struct opus_encoder *encoder = (struct opus_encoder *)_encoder;
/* libopus supports only 48 kHz */ /* libopus supports only 48 kHz */
audio_format->sample_rate = 48000; audio_format.sample_rate = 48000;
if (audio_format->channels > 2) if (audio_format.channels > 2)
audio_format->channels = 1; audio_format.channels = 1;
switch ((enum sample_format)audio_format->format) { switch (audio_format.format) {
case SAMPLE_FORMAT_S16: case SampleFormat::S16:
case SAMPLE_FORMAT_FLOAT: case SampleFormat::FLOAT:
break; break;
case SAMPLE_FORMAT_S8: case SampleFormat::S8:
audio_format->format = SAMPLE_FORMAT_S16; audio_format.format = SampleFormat::S16;
break; break;
default: default:
audio_format->format = SAMPLE_FORMAT_FLOAT; audio_format.format = SampleFormat::FLOAT;
break; break;
} }
encoder->audio_format = *audio_format; encoder->audio_format = audio_format;
encoder->frame_size = audio_format_frame_size(audio_format); encoder->frame_size = audio_format.GetFrameSize();
int error; int error;
encoder->enc = opus_encoder_create(audio_format->sample_rate, encoder->enc = opus_encoder_create(audio_format.sample_rate,
audio_format->channels, audio_format.channels,
OPUS_APPLICATION_AUDIO, OPUS_APPLICATION_AUDIO,
&error); &error);
if (encoder->enc == nullptr) { if (encoder->enc == nullptr) {
@ -190,7 +190,7 @@ opus_encoder_open(Encoder *_encoder,
opus_encoder_ctl(encoder->enc, OPUS_GET_LOOKAHEAD(&encoder->lookahead)); opus_encoder_ctl(encoder->enc, OPUS_GET_LOOKAHEAD(&encoder->lookahead));
encoder->buffer_frames = audio_format->sample_rate / 50; encoder->buffer_frames = audio_format.sample_rate / 50;
encoder->buffer_size = encoder->frame_size * encoder->buffer_frames; encoder->buffer_size = encoder->frame_size * encoder->buffer_frames;
encoder->buffer_position = 0; encoder->buffer_position = 0;
encoder->buffer = (unsigned char *)g_malloc(encoder->buffer_size); encoder->buffer = (unsigned char *)g_malloc(encoder->buffer_size);
@ -218,7 +218,7 @@ opus_encoder_do_encode(struct opus_encoder *encoder, bool eos,
assert(encoder->buffer_position == encoder->buffer_size); assert(encoder->buffer_position == encoder->buffer_size);
opus_int32 result = opus_int32 result =
encoder->audio_format.format == SAMPLE_FORMAT_S16 encoder->audio_format.format == SampleFormat::S16
? opus_encode(encoder->enc, ? opus_encode(encoder->enc,
(const opus_int16 *)encoder->buffer, (const opus_int16 *)encoder->buffer,
encoder->buffer_frames, encoder->buffer_frames,

View File

@ -20,7 +20,7 @@
#include "config.h" #include "config.h"
#include "TwolameEncoderPlugin.hxx" #include "TwolameEncoderPlugin.hxx"
#include "EncoderAPI.hxx" #include "EncoderAPI.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include <twolame.h> #include <twolame.h>
@ -32,7 +32,7 @@
struct TwolameEncoder final { struct TwolameEncoder final {
Encoder encoder; Encoder encoder;
struct audio_format audio_format; AudioFormat audio_format;
float quality; float quality;
int bitrate; int bitrate;
@ -187,15 +187,15 @@ twolame_encoder_setup(TwolameEncoder *encoder, GError **error)
} }
static bool static bool
twolame_encoder_open(Encoder *_encoder, struct audio_format *audio_format, twolame_encoder_open(Encoder *_encoder, AudioFormat &audio_format,
GError **error) GError **error)
{ {
TwolameEncoder *encoder = (TwolameEncoder *)_encoder; TwolameEncoder *encoder = (TwolameEncoder *)_encoder;
audio_format->format = SAMPLE_FORMAT_S16; audio_format.format = SampleFormat::S16;
audio_format->channels = 2; audio_format.channels = 2;
encoder->audio_format = *audio_format; encoder->audio_format = audio_format;
encoder->options = twolame_init(); encoder->options = twolame_init();
if (encoder->options == nullptr) { if (encoder->options == nullptr) {
@ -243,7 +243,7 @@ twolame_encoder_write(Encoder *_encoder,
assert(encoder->buffer_length == 0); assert(encoder->buffer_length == 0);
const unsigned num_frames = const unsigned num_frames =
length / audio_format_frame_size(&encoder->audio_format); length / encoder->audio_format.GetFrameSize();
int bytes_out = twolame_encode_buffer_interleaved(encoder->options, int bytes_out = twolame_encode_buffer_interleaved(encoder->options,
src, num_frames, src, num_frames,

View File

@ -22,7 +22,7 @@
#include "OggStream.hxx" #include "OggStream.hxx"
#include "EncoderAPI.hxx" #include "EncoderAPI.hxx"
#include "Tag.hxx" #include "Tag.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include "mpd_error.h" #include "mpd_error.h"
#include <vorbis/vorbisenc.h> #include <vorbis/vorbisenc.h>
@ -43,7 +43,7 @@ struct vorbis_encoder {
/* runtime information */ /* runtime information */
struct audio_format audio_format; AudioFormat audio_format;
vorbis_dsp_state vd; vorbis_dsp_state vd;
vorbis_block vb; vorbis_block vb;
@ -202,14 +202,14 @@ vorbis_encoder_send_header(struct vorbis_encoder *encoder)
static bool static bool
vorbis_encoder_open(Encoder *_encoder, vorbis_encoder_open(Encoder *_encoder,
struct audio_format *audio_format, AudioFormat &audio_format,
GError **error) GError **error)
{ {
struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
audio_format->format = SAMPLE_FORMAT_FLOAT; audio_format.format = SampleFormat::FLOAT;
encoder->audio_format = *audio_format; encoder->audio_format = audio_format;
if (!vorbis_encoder_reinit(encoder, error)) if (!vorbis_encoder_reinit(encoder, error))
return false; return false;
@ -328,8 +328,7 @@ vorbis_encoder_write(Encoder *_encoder,
{ {
struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
unsigned num_frames = length unsigned num_frames = length / encoder->audio_format.GetFrameSize();
/ audio_format_frame_size(&encoder->audio_format);
/* this is for only 16-bit audio */ /* this is for only 16-bit audio */

View File

@ -100,32 +100,32 @@ wave_encoder_finish(Encoder *_encoder)
static bool static bool
wave_encoder_open(Encoder *_encoder, wave_encoder_open(Encoder *_encoder,
gcc_unused struct audio_format *audio_format, AudioFormat &audio_format,
gcc_unused GError **error) gcc_unused GError **error)
{ {
WaveEncoder *encoder = (WaveEncoder *)_encoder; WaveEncoder *encoder = (WaveEncoder *)_encoder;
assert(audio_format_valid(audio_format)); assert(audio_format.IsValid());
switch (audio_format->format) { switch (audio_format.format) {
case SAMPLE_FORMAT_S8: case SampleFormat::S8:
encoder->bits = 8; encoder->bits = 8;
break; break;
case SAMPLE_FORMAT_S16: case SampleFormat::S16:
encoder->bits = 16; encoder->bits = 16;
break; break;
case SAMPLE_FORMAT_S24_P32: case SampleFormat::S24_P32:
encoder->bits = 24; encoder->bits = 24;
break; break;
case SAMPLE_FORMAT_S32: case SampleFormat::S32:
encoder->bits = 32; encoder->bits = 32;
break; break;
default: default:
audio_format->format = SAMPLE_FORMAT_S16; audio_format.format = SampleFormat::S16;
encoder->bits = 16; encoder->bits = 16;
break; break;
} }
@ -136,10 +136,10 @@ wave_encoder_open(Encoder *_encoder,
/* create PCM wave header in initial buffer */ /* create PCM wave header in initial buffer */
fill_wave_header(header, fill_wave_header(header,
audio_format->channels, audio_format.channels,
encoder->bits, encoder->bits,
audio_format->sample_rate, audio_format.sample_rate,
(encoder->bits / 8) * audio_format->channels ); (encoder->bits / 8) * audio_format.channels);
fifo_buffer_append(encoder->buffer, sizeof(*header)); fifo_buffer_append(encoder->buffer, sizeof(*header));
return true; return true;

View File

@ -23,18 +23,11 @@
#include "FilterPlugin.hxx" #include "FilterPlugin.hxx"
#include "FilterInternal.hxx" #include "FilterInternal.hxx"
#include "FilterRegistry.hxx" #include "FilterRegistry.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include <assert.h> #include <assert.h>
class AutoConvertFilter final : public Filter { class AutoConvertFilter final : public Filter {
/**
* The audio format being fed to the underlying filter. This
* plugin actually doesn't need this variable, we have it here
* just so our open() method doesn't return a stack pointer.
*/
audio_format child_audio_format;
/** /**
* The underlying filter. * The underlying filter.
*/ */
@ -52,46 +45,45 @@ public:
delete filter; delete filter;
} }
virtual const audio_format *Open(audio_format &af, GError **error_r); virtual AudioFormat Open(AudioFormat &af, GError **error_r);
virtual void Close(); virtual void Close();
virtual const void *FilterPCM(const void *src, size_t src_size, virtual const void *FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r, GError **error_r); size_t *dest_size_r, GError **error_r);
}; };
const struct audio_format * AudioFormat
AutoConvertFilter::Open(audio_format &in_audio_format, GError **error_r) AutoConvertFilter::Open(AudioFormat &in_audio_format, GError **error_r)
{ {
assert(audio_format_valid(&in_audio_format)); assert(in_audio_format.IsValid());
/* open the "real" filter */ /* open the "real" filter */
child_audio_format = in_audio_format; const AudioFormat child_audio_format = in_audio_format;
const audio_format *out_audio_format = AudioFormat out_audio_format = filter->Open(in_audio_format, error_r);
filter->Open(child_audio_format, error_r); if (!out_audio_format.IsDefined())
if (out_audio_format == nullptr) return out_audio_format;
return nullptr;
/* need to convert? */ /* need to convert? */
if (!audio_format_equals(&child_audio_format, &in_audio_format)) { if (in_audio_format != child_audio_format) {
/* yes - create a convert_filter */ /* yes - create a convert_filter */
convert = filter_new(&convert_filter_plugin, nullptr, error_r); convert = filter_new(&convert_filter_plugin, nullptr, error_r);
if (convert == nullptr) { if (convert == nullptr) {
filter->Close(); filter->Close();
return nullptr; return AudioFormat::Undefined();
} }
audio_format audio_format2 = in_audio_format; AudioFormat audio_format2 = in_audio_format;
const audio_format *audio_format3 = AudioFormat audio_format3 =
convert->Open(audio_format2, error_r); convert->Open(audio_format2, error_r);
if (audio_format3 == nullptr) { if (!audio_format3.IsDefined()) {
delete convert; delete convert;
filter->Close(); filter->Close();
return nullptr; return AudioFormat::Undefined();
} }
assert(audio_format_equals(&audio_format2, &in_audio_format)); assert(audio_format2 == in_audio_format);
convert_filter_set(convert, child_audio_format); convert_filter_set(convert, child_audio_format);
} else } else

View File

@ -23,7 +23,7 @@
#include "FilterPlugin.hxx" #include "FilterPlugin.hxx"
#include "FilterInternal.hxx" #include "FilterInternal.hxx"
#include "FilterRegistry.hxx" #include "FilterRegistry.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include <glib.h> #include <glib.h>
@ -53,7 +53,7 @@ public:
children.emplace_back(name, filter); children.emplace_back(name, filter);
} }
virtual const audio_format *Open(audio_format &af, GError **error_r); virtual AudioFormat Open(AudioFormat &af, GError **error_r) override;
virtual void Close(); virtual void Close();
virtual const void *FilterPCM(const void *src, size_t src_size, virtual const void *FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r, GError **error_r); size_t *dest_size_r, GError **error_r);
@ -96,43 +96,43 @@ ChainFilter::CloseUntil(const Filter *until)
gcc_unreachable(); gcc_unreachable();
} }
static const struct audio_format * static AudioFormat
chain_open_child(const char *name, Filter *filter, chain_open_child(const char *name, Filter *filter,
const audio_format &prev_audio_format, const AudioFormat &prev_audio_format,
GError **error_r) GError **error_r)
{ {
audio_format conv_audio_format = prev_audio_format; AudioFormat conv_audio_format = prev_audio_format;
const audio_format *next_audio_format = const AudioFormat next_audio_format =
filter->Open(conv_audio_format, error_r); filter->Open(conv_audio_format, error_r);
if (next_audio_format == NULL) if (!next_audio_format.IsDefined())
return NULL; return next_audio_format;
if (!audio_format_equals(&conv_audio_format, &prev_audio_format)) { if (conv_audio_format != prev_audio_format) {
struct audio_format_string s; struct audio_format_string s;
filter->Close(); filter->Close();
g_set_error(error_r, filter_quark(), 0, g_set_error(error_r, filter_quark(), 0,
"Audio format not supported by filter '%s': %s", "Audio format not supported by filter '%s': %s",
name, name,
audio_format_to_string(&prev_audio_format, &s)); audio_format_to_string(prev_audio_format, &s));
return NULL; return AudioFormat::Undefined();
} }
return next_audio_format; return next_audio_format;
} }
const audio_format * AudioFormat
ChainFilter::Open(audio_format &in_audio_format, GError **error_r) ChainFilter::Open(AudioFormat &in_audio_format, GError **error_r)
{ {
const audio_format *audio_format = &in_audio_format; AudioFormat audio_format = in_audio_format;
for (auto &child : children) { for (auto &child : children) {
audio_format = chain_open_child(child.name, child.filter, audio_format = chain_open_child(child.name, child.filter,
*audio_format, error_r); audio_format, error_r);
if (audio_format == NULL) { if (!audio_format.IsDefined()) {
/* rollback, close all children */ /* rollback, close all children */
CloseUntil(child.filter); CloseUntil(child.filter);
return NULL; break;
} }
} }

View File

@ -25,7 +25,7 @@
#include "conf.h" #include "conf.h"
#include "pcm/PcmConvert.hxx" #include "pcm/PcmConvert.hxx"
#include "util/Manual.hxx" #include "util/Manual.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include "poison.h" #include "poison.h"
#include <assert.h> #include <assert.h>
@ -36,27 +36,27 @@ class ConvertFilter final : public Filter {
* The input audio format; PCM data is passed to the filter() * The input audio format; PCM data is passed to the filter()
* method in this format. * method in this format.
*/ */
audio_format in_audio_format; AudioFormat in_audio_format;
/** /**
* The output audio format; the consumer of this plugin * The output audio format; the consumer of this plugin
* expects PCM data in this format. This defaults to * expects PCM data in this format. This defaults to
* #in_audio_format, and can be set with convert_filter_set(). * #in_audio_format, and can be set with convert_filter_set().
*/ */
audio_format out_audio_format; AudioFormat out_audio_format;
Manual<PcmConvert> state; Manual<PcmConvert> state;
public: public:
void Set(const audio_format &_out_audio_format) { void Set(const AudioFormat &_out_audio_format) {
assert(audio_format_valid(&in_audio_format)); assert(in_audio_format.IsValid());
assert(audio_format_valid(&out_audio_format)); assert(out_audio_format.IsValid());
assert(audio_format_valid(&_out_audio_format)); assert(_out_audio_format.IsValid());
out_audio_format = _out_audio_format; out_audio_format = _out_audio_format;
} }
virtual const audio_format *Open(audio_format &af, GError **error_r); virtual AudioFormat Open(AudioFormat &af, GError **error_r) override;
virtual void Close(); virtual void Close();
virtual const void *FilterPCM(const void *src, size_t src_size, virtual const void *FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r, GError **error_r); size_t *dest_size_r, GError **error_r);
@ -69,15 +69,15 @@ convert_filter_init(gcc_unused const struct config_param *param,
return new ConvertFilter(); return new ConvertFilter();
} }
const struct audio_format * AudioFormat
ConvertFilter::Open(audio_format &audio_format, gcc_unused GError **error_r) ConvertFilter::Open(AudioFormat &audio_format, gcc_unused GError **error_r)
{ {
assert(audio_format_valid(&audio_format)); assert(audio_format.IsValid());
in_audio_format = out_audio_format = audio_format; in_audio_format = out_audio_format = audio_format;
state.Construct(); state.Construct();
return &in_audio_format; return in_audio_format;
} }
void void
@ -93,15 +93,15 @@ const void *
ConvertFilter::FilterPCM(const void *src, size_t src_size, ConvertFilter::FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r, GError **error_r) size_t *dest_size_r, GError **error_r)
{ {
if (audio_format_equals(&in_audio_format, &out_audio_format)) { if (in_audio_format == out_audio_format) {
/* optimized special case: no-op */ /* optimized special case: no-op */
*dest_size_r = src_size; *dest_size_r = src_size;
return src; return src;
} }
return state->Convert(&in_audio_format, return state->Convert(in_audio_format,
src, src_size, src, src_size,
&out_audio_format, dest_size_r, out_audio_format, dest_size_r,
error_r); error_r);
} }
@ -111,7 +111,7 @@ const struct filter_plugin convert_filter_plugin = {
}; };
void void
convert_filter_set(Filter *_filter, const audio_format &out_audio_format) convert_filter_set(Filter *_filter, const AudioFormat out_audio_format)
{ {
ConvertFilter *filter = (ConvertFilter *)_filter; ConvertFilter *filter = (ConvertFilter *)_filter;

View File

@ -21,7 +21,7 @@
#define MPD_CONVERT_FILTER_PLUGIN_HXX #define MPD_CONVERT_FILTER_PLUGIN_HXX
class Filter; class Filter;
struct audio_format; struct AudioFormat;
/** /**
* Sets the output audio format for the specified filter. You must * Sets the output audio format for the specified filter. You must
@ -30,6 +30,6 @@ struct audio_format;
* the last in a chain. * the last in a chain.
*/ */
void void
convert_filter_set(Filter *filter, const audio_format &out_audio_format); convert_filter_set(Filter *filter, AudioFormat out_audio_format);
#endif #endif

View File

@ -22,7 +22,7 @@
#include "FilterInternal.hxx" #include "FilterInternal.hxx"
#include "FilterRegistry.hxx" #include "FilterRegistry.hxx"
#include "pcm/PcmBuffer.hxx" #include "pcm/PcmBuffer.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include "AudioCompress/compress.h" #include "AudioCompress/compress.h"
#include <assert.h> #include <assert.h>
@ -34,7 +34,7 @@ class NormalizeFilter final : public Filter {
PcmBuffer buffer; PcmBuffer buffer;
public: public:
virtual const audio_format *Open(audio_format &af, GError **error_r); virtual AudioFormat Open(AudioFormat &af, GError **error_r) override;
virtual void Close(); virtual void Close();
virtual const void *FilterPCM(const void *src, size_t src_size, virtual const void *FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r, GError **error_r); size_t *dest_size_r, GError **error_r);
@ -47,14 +47,14 @@ normalize_filter_init(gcc_unused const struct config_param *param,
return new NormalizeFilter(); return new NormalizeFilter();
} }
const struct audio_format * AudioFormat
NormalizeFilter::Open(audio_format &audio_format, gcc_unused GError **error_r) NormalizeFilter::Open(AudioFormat &audio_format, gcc_unused GError **error_r)
{ {
audio_format.format = SAMPLE_FORMAT_S16; audio_format.format = SampleFormat::S16;
compressor = Compressor_new(0); compressor = Compressor_new(0);
return &audio_format; return audio_format;
} }
void void

View File

@ -28,13 +28,14 @@
#include "FilterPlugin.hxx" #include "FilterPlugin.hxx"
#include "FilterInternal.hxx" #include "FilterInternal.hxx"
#include "FilterRegistry.hxx" #include "FilterRegistry.hxx"
#include "AudioFormat.hxx"
#include "gcc.h" #include "gcc.h"
class NullFilter final : public Filter { class NullFilter final : public Filter {
public: public:
virtual const audio_format *Open(audio_format &af, virtual AudioFormat Open(AudioFormat &af,
gcc_unused GError **error_r) { gcc_unused GError **error_r) {
return &af; return af;
} }
virtual void Close() {} virtual void Close() {}

View File

@ -22,7 +22,7 @@
#include "FilterPlugin.hxx" #include "FilterPlugin.hxx"
#include "FilterInternal.hxx" #include "FilterInternal.hxx"
#include "FilterRegistry.hxx" #include "FilterRegistry.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include "replay_gain_info.h" #include "replay_gain_info.h"
#include "replay_gain_config.h" #include "replay_gain_config.h"
#include "MixerControl.hxx" #include "MixerControl.hxx"
@ -66,7 +66,7 @@ class ReplayGainFilter final : public Filter {
*/ */
unsigned volume; unsigned volume;
struct audio_format format; AudioFormat format;
PcmBuffer buffer; PcmBuffer buffer;
@ -112,7 +112,7 @@ public:
*/ */
void Update(); void Update();
virtual const audio_format *Open(audio_format &af, GError **error_r); virtual AudioFormat Open(AudioFormat &af, GError **error_r) override;
virtual void Close(); virtual void Close();
virtual const void *FilterPCM(const void *src, size_t src_size, virtual const void *FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r, GError **error_r); size_t *dest_size_r, GError **error_r);
@ -159,12 +159,12 @@ replay_gain_filter_init(gcc_unused const struct config_param *param,
return new ReplayGainFilter(); return new ReplayGainFilter();
} }
const audio_format * AudioFormat
ReplayGainFilter::Open(audio_format &af, gcc_unused GError **error_r) ReplayGainFilter::Open(AudioFormat &af, gcc_unused GError **error_r)
{ {
format = af; format = af;
return &format; return format;
} }
void void
@ -196,7 +196,7 @@ ReplayGainFilter::FilterPCM(const void *src, size_t src_size,
memcpy(dest, src, src_size); memcpy(dest, src, src_size);
bool success = pcm_volume(dest, src_size, bool success = pcm_volume(dest, src_size,
sample_format(format.format), format.format,
volume); volume);
if (!success) { if (!success) {
g_set_error(error_r, replay_gain_quark(), 0, g_set_error(error_r, replay_gain_quark(), 0,

View File

@ -42,7 +42,7 @@
#include "config.h" #include "config.h"
#include "conf.h" #include "conf.h"
#include "ConfigQuark.hxx" #include "ConfigQuark.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "FilterPlugin.hxx" #include "FilterPlugin.hxx"
#include "FilterInternal.hxx" #include "FilterInternal.hxx"
@ -79,12 +79,12 @@ class RouteFilter final : public Filter {
/** /**
* The actual input format of our signal, once opened * The actual input format of our signal, once opened
*/ */
struct audio_format input_format; AudioFormat input_format;
/** /**
* The decided upon output format, once opened * The decided upon output format, once opened
*/ */
struct audio_format output_format; AudioFormat output_format;
/** /**
* The size, in bytes, of each multichannel frame in the * The size, in bytes, of each multichannel frame in the
@ -120,7 +120,7 @@ public:
*/ */
bool Configure(const config_param *param, GError **error_r); bool Configure(const config_param *param, GError **error_r);
virtual const audio_format *Open(audio_format &af, GError **error_r); virtual AudioFormat Open(AudioFormat &af, GError **error_r) override;
virtual void Close(); virtual void Close();
virtual const void *FilterPCM(const void *src, size_t src_size, virtual const void *FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r, GError **error_r); size_t *dest_size_r, GError **error_r);
@ -241,12 +241,12 @@ route_filter_init(const config_param *param, GError **error_r)
return filter; return filter;
} }
const struct audio_format * AudioFormat
RouteFilter::Open(audio_format &audio_format, gcc_unused GError **error_r) RouteFilter::Open(AudioFormat &audio_format, gcc_unused GError **error_r)
{ {
// Copy the input format for later reference // Copy the input format for later reference
input_format = audio_format; input_format = audio_format;
input_frame_size = audio_format_frame_size(&input_format); input_frame_size = input_format.GetFrameSize();
// Decide on an output format which has enough channels, // Decide on an output format which has enough channels,
// and is otherwise identical // and is otherwise identical
@ -254,9 +254,9 @@ RouteFilter::Open(audio_format &audio_format, gcc_unused GError **error_r)
output_format.channels = min_output_channels; output_format.channels = min_output_channels;
// Precalculate this simple value, to speed up allocation later // Precalculate this simple value, to speed up allocation later
output_frame_size = audio_format_frame_size(&output_format); output_frame_size = output_format.GetFrameSize();
return &output_format; return output_format;
} }
void void
@ -271,8 +271,7 @@ RouteFilter::FilterPCM(const void *src, size_t src_size,
{ {
size_t number_of_frames = src_size / input_frame_size; size_t number_of_frames = src_size / input_frame_size;
size_t bytes_per_frame_per_channel = const size_t bytes_per_frame_per_channel = input_format.GetSampleSize();
audio_format_sample_size(&input_format);
// A moving pointer that always refers to channel 0 in the input, at the currently handled frame // A moving pointer that always refers to channel 0 in the input, at the currently handled frame
const uint8_t *base_source = (const uint8_t *)src; const uint8_t *base_source = (const uint8_t *)src;

View File

@ -25,7 +25,7 @@
#include "conf.h" #include "conf.h"
#include "pcm/PcmVolume.hxx" #include "pcm/PcmVolume.hxx"
#include "pcm/PcmBuffer.hxx" #include "pcm/PcmBuffer.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
@ -36,7 +36,7 @@ class VolumeFilter final : public Filter {
*/ */
unsigned volume; unsigned volume;
struct audio_format format; AudioFormat format;
PcmBuffer buffer; PcmBuffer buffer;
@ -56,7 +56,7 @@ public:
volume = _volume; volume = _volume;
} }
virtual const audio_format *Open(audio_format &af, GError **error_r); virtual AudioFormat Open(AudioFormat &af, GError **error_r) override;
virtual void Close(); virtual void Close();
virtual const void *FilterPCM(const void *src, size_t src_size, virtual const void *FilterPCM(const void *src, size_t src_size,
size_t *dest_size_r, GError **error_r); size_t *dest_size_r, GError **error_r);
@ -75,12 +75,12 @@ volume_filter_init(gcc_unused const struct config_param *param,
return new VolumeFilter(); return new VolumeFilter();
} }
const struct audio_format * AudioFormat
VolumeFilter::Open(audio_format &audio_format, gcc_unused GError **error_r) VolumeFilter::Open(AudioFormat &audio_format, gcc_unused GError **error_r)
{ {
format = audio_format; format = audio_format;
return &format; return format;
} }
void void
@ -112,7 +112,7 @@ VolumeFilter::FilterPCM(const void *src, size_t src_size,
memcpy(dest, src, src_size); memcpy(dest, src, src_size);
bool success = pcm_volume(dest, src_size, bool success = pcm_volume(dest, src_size,
sample_format(format.format), format.format,
volume); volume);
if (!success) { if (!success) {
g_set_error(error_r, volume_quark(), 0, g_set_error(error_r, volume_quark(), 0,

View File

@ -233,26 +233,26 @@ alsa_test_default_device(void)
} }
static snd_pcm_format_t static snd_pcm_format_t
get_bitformat(enum sample_format sample_format) get_bitformat(SampleFormat sample_format)
{ {
switch (sample_format) { switch (sample_format) {
case SAMPLE_FORMAT_UNDEFINED: case SampleFormat::UNDEFINED:
case SAMPLE_FORMAT_DSD: case SampleFormat::DSD:
return SND_PCM_FORMAT_UNKNOWN; return SND_PCM_FORMAT_UNKNOWN;
case SAMPLE_FORMAT_S8: case SampleFormat::S8:
return SND_PCM_FORMAT_S8; return SND_PCM_FORMAT_S8;
case SAMPLE_FORMAT_S16: case SampleFormat::S16:
return SND_PCM_FORMAT_S16; return SND_PCM_FORMAT_S16;
case SAMPLE_FORMAT_S24_P32: case SampleFormat::S24_P32:
return SND_PCM_FORMAT_S24; return SND_PCM_FORMAT_S24;
case SAMPLE_FORMAT_S32: case SampleFormat::S32:
return SND_PCM_FORMAT_S32; return SND_PCM_FORMAT_S32;
case SAMPLE_FORMAT_FLOAT: case SampleFormat::FLOAT:
return SND_PCM_FORMAT_FLOAT; return SND_PCM_FORMAT_FLOAT;
} }
@ -324,7 +324,7 @@ alsa_try_format_or_packed(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
*/ */
static int static int
alsa_output_try_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, alsa_output_try_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
enum sample_format sample_format, SampleFormat sample_format,
bool *packed_r, bool *reverse_endian_r) bool *packed_r, bool *reverse_endian_r)
{ {
snd_pcm_format_t alsa_format = get_bitformat(sample_format); snd_pcm_format_t alsa_format = get_bitformat(sample_format);
@ -355,36 +355,36 @@ alsa_output_try_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
*/ */
static int static int
alsa_output_setup_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, alsa_output_setup_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
struct audio_format *audio_format, AudioFormat &audio_format,
bool *packed_r, bool *reverse_endian_r) bool *packed_r, bool *reverse_endian_r)
{ {
/* try the input format first */ /* try the input format first */
int err = alsa_output_try_format(pcm, hwparams, int err = alsa_output_try_format(pcm, hwparams,
sample_format(audio_format->format), audio_format.format,
packed_r, reverse_endian_r); packed_r, reverse_endian_r);
/* if unsupported by the hardware, try other formats */ /* if unsupported by the hardware, try other formats */
static const enum sample_format probe_formats[] = { static const SampleFormat probe_formats[] = {
SAMPLE_FORMAT_S24_P32, SampleFormat::S24_P32,
SAMPLE_FORMAT_S32, SampleFormat::S32,
SAMPLE_FORMAT_S16, SampleFormat::S16,
SAMPLE_FORMAT_S8, SampleFormat::S8,
SAMPLE_FORMAT_UNDEFINED, SampleFormat::UNDEFINED,
}; };
for (unsigned i = 0; for (unsigned i = 0;
err == -EINVAL && probe_formats[i] != SAMPLE_FORMAT_UNDEFINED; err == -EINVAL && probe_formats[i] != SampleFormat::UNDEFINED;
++i) { ++i) {
const enum sample_format mpd_format = probe_formats[i]; const SampleFormat mpd_format = probe_formats[i];
if (mpd_format == audio_format->format) if (mpd_format == audio_format.format)
continue; continue;
err = alsa_output_try_format(pcm, hwparams, mpd_format, err = alsa_output_try_format(pcm, hwparams, mpd_format,
packed_r, reverse_endian_r); packed_r, reverse_endian_r);
if (err == 0) if (err == 0)
audio_format->format = mpd_format; audio_format.format = mpd_format;
} }
return err; return err;
@ -395,11 +395,11 @@ alsa_output_setup_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
* the configured settings and the audio format. * the configured settings and the audio format.
*/ */
static bool static bool
alsa_setup(AlsaOutput *ad, struct audio_format *audio_format, alsa_setup(AlsaOutput *ad, AudioFormat &audio_format,
bool *packed_r, bool *reverse_endian_r, GError **error) bool *packed_r, bool *reverse_endian_r, GError **error)
{ {
unsigned int sample_rate = audio_format->sample_rate; unsigned int sample_rate = audio_format.sample_rate;
unsigned int channels = audio_format->channels; unsigned int channels = audio_format.channels;
int err; int err;
const char *cmd = NULL; const char *cmd = NULL;
int retry = MPD_ALSA_RETRY_NR; int retry = MPD_ALSA_RETRY_NR;
@ -443,7 +443,7 @@ configure_hw:
g_set_error(error, alsa_output_quark(), err, g_set_error(error, alsa_output_quark(), err,
"ALSA device \"%s\" does not support format %s: %s", "ALSA device \"%s\" does not support format %s: %s",
alsa_device(ad), alsa_device(ad),
sample_format_to_string(sample_format(audio_format->format)), sample_format_to_string(audio_format.format),
snd_strerror(-err)); snd_strerror(-err));
return false; return false;
} }
@ -458,21 +458,21 @@ configure_hw:
if (err < 0) { if (err < 0) {
g_set_error(error, alsa_output_quark(), err, g_set_error(error, alsa_output_quark(), err,
"ALSA device \"%s\" does not support %i channels: %s", "ALSA device \"%s\" does not support %i channels: %s",
alsa_device(ad), (int)audio_format->channels, alsa_device(ad), (int)audio_format.channels,
snd_strerror(-err)); snd_strerror(-err));
return false; return false;
} }
audio_format->channels = (int8_t)channels; audio_format.channels = (int8_t)channels;
err = snd_pcm_hw_params_set_rate_near(ad->pcm, hwparams, err = snd_pcm_hw_params_set_rate_near(ad->pcm, hwparams,
&sample_rate, NULL); &sample_rate, NULL);
if (err < 0 || sample_rate == 0) { if (err < 0 || sample_rate == 0) {
g_set_error(error, alsa_output_quark(), err, g_set_error(error, alsa_output_quark(), err,
"ALSA device \"%s\" does not support %u Hz audio", "ALSA device \"%s\" does not support %u Hz audio",
alsa_device(ad), audio_format->sample_rate); alsa_device(ad), audio_format.sample_rate);
return false; return false;
} }
audio_format->sample_rate = sample_rate; audio_format.sample_rate = sample_rate;
snd_pcm_uframes_t buffer_size_min, buffer_size_max; snd_pcm_uframes_t buffer_size_min, buffer_size_max;
snd_pcm_hw_params_get_buffer_size_min(hwparams, &buffer_size_min); snd_pcm_hw_params_get_buffer_size_min(hwparams, &buffer_size_min);
@ -603,22 +603,22 @@ error:
} }
static bool static bool
alsa_setup_dsd(AlsaOutput *ad, struct audio_format *audio_format, alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format,
bool *shift8_r, bool *packed_r, bool *reverse_endian_r, bool *shift8_r, bool *packed_r, bool *reverse_endian_r,
GError **error_r) GError **error_r)
{ {
assert(ad->dsd_usb); assert(ad->dsd_usb);
assert(audio_format->format == SAMPLE_FORMAT_DSD); assert(audio_format.format == SampleFormat::DSD);
/* pass 24 bit to alsa_setup() */ /* pass 24 bit to alsa_setup() */
struct audio_format usb_format = *audio_format; AudioFormat usb_format = audio_format;
usb_format.format = SAMPLE_FORMAT_S24_P32; usb_format.format = SampleFormat::S24_P32;
usb_format.sample_rate /= 2; usb_format.sample_rate /= 2;
const struct audio_format check = usb_format; const AudioFormat check = usb_format;
if (!alsa_setup(ad, &usb_format, packed_r, reverse_endian_r, error_r)) if (!alsa_setup(ad, usb_format, packed_r, reverse_endian_r, error_r))
return false; return false;
/* if the device allows only 32 bit, shift all DSD-over-USB /* if the device allows only 32 bit, shift all DSD-over-USB
@ -626,11 +626,11 @@ alsa_setup_dsd(AlsaOutput *ad, struct audio_format *audio_format,
the DSD-over-USB documentation does not specify whether the DSD-over-USB documentation does not specify whether
this is legal, but there is anecdotical evidence that this this is legal, but there is anecdotical evidence that this
is possible (and the only option for some devices) */ is possible (and the only option for some devices) */
*shift8_r = usb_format.format == SAMPLE_FORMAT_S32; *shift8_r = usb_format.format == SampleFormat::S32;
if (usb_format.format == SAMPLE_FORMAT_S32) if (usb_format.format == SampleFormat::S32)
usb_format.format = SAMPLE_FORMAT_S24_P32; usb_format.format = SampleFormat::S24_P32;
if (!audio_format_equals(&usb_format, &check)) { if (usb_format != check) {
/* no bit-perfect playback, which is required /* no bit-perfect playback, which is required
for DSD over USB */ for DSD over USB */
g_set_error(error_r, alsa_output_quark(), 0, g_set_error(error_r, alsa_output_quark(), 0,
@ -644,13 +644,13 @@ alsa_setup_dsd(AlsaOutput *ad, struct audio_format *audio_format,
} }
static bool static bool
alsa_setup_or_dsd(AlsaOutput *ad, struct audio_format *audio_format, alsa_setup_or_dsd(AlsaOutput *ad, AudioFormat &audio_format,
GError **error_r) GError **error_r)
{ {
bool shift8 = false, packed, reverse_endian; bool shift8 = false, packed, reverse_endian;
const bool dsd_usb = ad->dsd_usb && const bool dsd_usb = ad->dsd_usb &&
audio_format->format == SAMPLE_FORMAT_DSD; audio_format.format == SampleFormat::DSD;
const bool success = dsd_usb const bool success = dsd_usb
? alsa_setup_dsd(ad, audio_format, ? alsa_setup_dsd(ad, audio_format,
&shift8, &packed, &reverse_endian, &shift8, &packed, &reverse_endian,
@ -660,14 +660,14 @@ alsa_setup_or_dsd(AlsaOutput *ad, struct audio_format *audio_format,
if (!success) if (!success)
return false; return false;
ad->pcm_export->Open(sample_format(audio_format->format), ad->pcm_export->Open(audio_format.format,
audio_format->channels, audio_format.channels,
dsd_usb, shift8, packed, reverse_endian); dsd_usb, shift8, packed, reverse_endian);
return true; return true;
} }
static bool static bool
alsa_open(struct audio_output *ao, struct audio_format *audio_format, GError **error) alsa_open(struct audio_output *ao, AudioFormat &audio_format, GError **error)
{ {
AlsaOutput *ad = (AlsaOutput *)ao; AlsaOutput *ad = (AlsaOutput *)ao;
@ -688,8 +688,8 @@ alsa_open(struct audio_output *ao, struct audio_format *audio_format, GError **e
return false; return false;
} }
ad->in_frame_size = audio_format_frame_size(audio_format); ad->in_frame_size = audio_format.GetFrameSize();
ad->out_frame_size = ad->pcm_export->GetFrameSize(*audio_format); ad->out_frame_size = ad->pcm_export->GetFrameSize(audio_format);
return true; return true;
} }

View File

@ -200,18 +200,18 @@ ao_output_close(struct audio_output *ao)
} }
static bool static bool
ao_output_open(struct audio_output *ao, struct audio_format *audio_format, ao_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error) GError **error)
{ {
ao_sample_format format = OUR_AO_FORMAT_INITIALIZER; ao_sample_format format = OUR_AO_FORMAT_INITIALIZER;
AoOutput *ad = (AoOutput *)ao; AoOutput *ad = (AoOutput *)ao;
switch (audio_format->format) { switch (audio_format.format) {
case SAMPLE_FORMAT_S8: case SampleFormat::S8:
format.bits = 8; format.bits = 8;
break; break;
case SAMPLE_FORMAT_S16: case SampleFormat::S16:
format.bits = 16; format.bits = 16;
break; break;
@ -219,14 +219,14 @@ ao_output_open(struct audio_output *ao, struct audio_format *audio_format,
/* support for 24 bit samples in libao is currently /* support for 24 bit samples in libao is currently
dubious, and until we have sorted that out, dubious, and until we have sorted that out,
convert everything to 16 bit */ convert everything to 16 bit */
audio_format->format = SAMPLE_FORMAT_S16; audio_format.format = SampleFormat::S16;
format.bits = 16; format.bits = 16;
break; break;
} }
format.rate = audio_format->sample_rate; format.rate = audio_format.sample_rate;
format.byte_format = AO_FMT_NATIVE; format.byte_format = AO_FMT_NATIVE;
format.channels = audio_format->channels; format.channels = audio_format.channels;
ad->device = ao_open_live(ad->driver, &format, ad->options); ad->device = ao_open_live(ad->driver, &format, ad->options);

View File

@ -227,12 +227,12 @@ fifo_output_finish(struct audio_output *ao)
} }
static bool static bool
fifo_output_open(struct audio_output *ao, struct audio_format *audio_format, fifo_output_open(struct audio_output *ao, AudioFormat &audio_format,
G_GNUC_UNUSED GError **error) G_GNUC_UNUSED GError **error)
{ {
FifoOutput *fd = (FifoOutput *)ao; FifoOutput *fd = (FifoOutput *)ao;
fd->timer = new Timer(*audio_format); fd->timer = new Timer(audio_format);
return true; return true;
} }

View File

@ -131,13 +131,13 @@ struct HttpdOutput final : private ServerSocket {
/** /**
* Caller must lock the mutex. * Caller must lock the mutex.
*/ */
bool OpenEncoder(struct audio_format *audio_format, bool OpenEncoder(AudioFormat &audio_format,
GError **error_r); GError **error_r);
/** /**
* Caller must lock the mutex. * Caller must lock the mutex.
*/ */
bool Open(struct audio_format *audio_format, GError **error_r); bool Open(AudioFormat &audio_format, GError **error_r);
/** /**
* Caller must lock the mutex. * Caller must lock the mutex.

View File

@ -291,7 +291,7 @@ httpd_output_disable(struct audio_output *ao)
} }
inline bool inline bool
HttpdOutput::OpenEncoder(struct audio_format *audio_format, GError **error) HttpdOutput::OpenEncoder(AudioFormat &audio_format, GError **error)
{ {
if (!encoder_open(encoder, audio_format, error)) if (!encoder_open(encoder, audio_format, error))
return false; return false;
@ -307,7 +307,7 @@ HttpdOutput::OpenEncoder(struct audio_format *audio_format, GError **error)
} }
inline bool inline bool
HttpdOutput::Open(struct audio_format *audio_format, GError **error_r) HttpdOutput::Open(AudioFormat &audio_format, GError **error_r)
{ {
assert(!open); assert(!open);
assert(clients.empty()); assert(clients.empty());
@ -320,7 +320,7 @@ HttpdOutput::Open(struct audio_format *audio_format, GError **error_r)
/* initialize other attributes */ /* initialize other attributes */
clients_cnt = 0; clients_cnt = 0;
timer = new Timer(*audio_format); timer = new Timer(audio_format);
open = true; open = true;
@ -328,7 +328,7 @@ HttpdOutput::Open(struct audio_format *audio_format, GError **error_r)
} }
static bool static bool
httpd_output_open(struct audio_output *ao, struct audio_format *audio_format, httpd_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error) GError **error)
{ {
HttpdOutput *httpd = Cast(ao); HttpdOutput *httpd = Cast(ao);

View File

@ -67,7 +67,7 @@ struct JackOutput {
size_t ringbuffer_size; size_t ringbuffer_size;
/* the current audio format */ /* the current audio format */
struct audio_format audio_format; AudioFormat audio_format;
/* jack library stuff */ /* jack library stuff */
jack_port_t *ports[MAX_PORTS]; jack_port_t *ports[MAX_PORTS];
@ -203,18 +203,18 @@ mpd_jack_shutdown(void *arg)
} }
static void static void
set_audioformat(JackOutput *jd, struct audio_format *audio_format) set_audioformat(JackOutput *jd, AudioFormat &audio_format)
{ {
audio_format->sample_rate = jack_get_sample_rate(jd->client); audio_format.sample_rate = jack_get_sample_rate(jd->client);
if (jd->num_source_ports == 1) if (jd->num_source_ports == 1)
audio_format->channels = 1; audio_format.channels = 1;
else if (audio_format->channels > jd->num_source_ports) else if (audio_format.channels > jd->num_source_ports)
audio_format->channels = 2; audio_format.channels = 2;
if (audio_format->format != SAMPLE_FORMAT_S16 && if (audio_format.format != SampleFormat::S16 &&
audio_format->format != SAMPLE_FORMAT_S24_P32) audio_format.format != SampleFormat::S24_P32)
audio_format->format = SAMPLE_FORMAT_S24_P32; audio_format.format = SampleFormat::S24_P32;
} }
static void static void
@ -591,7 +591,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r)
} }
static bool static bool
mpd_jack_open(struct audio_output *ao, struct audio_format *audio_format, mpd_jack_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error_r) GError **error_r)
{ {
JackOutput *jd = (JackOutput *)ao; JackOutput *jd = (JackOutput *)ao;
@ -607,7 +607,7 @@ mpd_jack_open(struct audio_output *ao, struct audio_format *audio_format,
return false; return false;
set_audioformat(jd, audio_format); set_audioformat(jd, audio_format);
jd->audio_format = *audio_format; jd->audio_format = audio_format;
if (!mpd_jack_start(jd, error_r)) if (!mpd_jack_start(jd, error_r))
return false; return false;
@ -684,12 +684,12 @@ mpd_jack_write_samples(JackOutput *jd, const void *src,
unsigned num_samples) unsigned num_samples)
{ {
switch (jd->audio_format.format) { switch (jd->audio_format.format) {
case SAMPLE_FORMAT_S16: case SampleFormat::S16:
mpd_jack_write_samples_16(jd, (const int16_t*)src, mpd_jack_write_samples_16(jd, (const int16_t*)src,
num_samples); num_samples);
break; break;
case SAMPLE_FORMAT_S24_P32: case SampleFormat::S24_P32:
mpd_jack_write_samples_24(jd, (const int32_t*)src, mpd_jack_write_samples_24(jd, (const int32_t*)src,
num_samples); num_samples);
break; break;
@ -705,7 +705,7 @@ mpd_jack_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error_r) GError **error_r)
{ {
JackOutput *jd = (JackOutput *)ao; JackOutput *jd = (JackOutput *)ao;
const size_t frame_size = audio_format_frame_size(&jd->audio_format); const size_t frame_size = jd->audio_format.GetFrameSize();
size_t space = 0, space1; size_t space = 0, space1;
jd->pause = false; jd->pause = false;

View File

@ -66,13 +66,13 @@ null_finish(struct audio_output *ao)
} }
static bool static bool
null_open(struct audio_output *ao, struct audio_format *audio_format, null_open(struct audio_output *ao, AudioFormat &audio_format,
gcc_unused GError **error) gcc_unused GError **error)
{ {
NullOutput *nd = (NullOutput *)ao; NullOutput *nd = (NullOutput *)ao;
if (nd->sync) if (nd->sync)
nd->timer = new Timer(*audio_format); nd->timer = new Timer(audio_format);
return true; return true;
} }

View File

@ -316,30 +316,30 @@ osx_output_close(struct audio_output *ao)
} }
static bool static bool
osx_output_open(struct audio_output *ao, struct audio_format *audio_format, GError **error) osx_output_open(struct audio_output *ao, AudioFormat &audio_format, GError **error)
{ {
OSXOutput *od = (OSXOutput *)ao; OSXOutput *od = (OSXOutput *)ao;
AudioStreamBasicDescription stream_description; AudioStreamBasicDescription stream_description;
stream_description.mSampleRate = audio_format->sample_rate; stream_description.mSampleRate = audio_format.sample_rate;
stream_description.mFormatID = kAudioFormatLinearPCM; stream_description.mFormatID = kAudioFormatLinearPCM;
stream_description.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; stream_description.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
switch (audio_format->format) { switch (audio_format.format) {
case SAMPLE_FORMAT_S8: case SampleFormat::S8:
stream_description.mBitsPerChannel = 8; stream_description.mBitsPerChannel = 8;
break; break;
case SAMPLE_FORMAT_S16: case SampleFormat::S16:
stream_description.mBitsPerChannel = 16; stream_description.mBitsPerChannel = 16;
break; break;
case SAMPLE_FORMAT_S32: case SampleFormat::S32:
stream_description.mBitsPerChannel = 32; stream_description.mBitsPerChannel = 32;
break; break;
default: default:
audio_format->format = SAMPLE_FORMAT_S32; audio_format.format = SampleFormat::S32;
stream_description.mBitsPerChannel = 32; stream_description.mBitsPerChannel = 32;
break; break;
} }
@ -348,11 +348,10 @@ osx_output_open(struct audio_output *ao, struct audio_format *audio_format, GErr
stream_description.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; stream_description.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
#endif #endif
stream_description.mBytesPerPacket = stream_description.mBytesPerPacket = audio_format.GetFrameSize();
audio_format_frame_size(audio_format);
stream_description.mFramesPerPacket = 1; stream_description.mFramesPerPacket = 1;
stream_description.mBytesPerFrame = stream_description.mBytesPerPacket; stream_description.mBytesPerFrame = stream_description.mBytesPerPacket;
stream_description.mChannelsPerFrame = audio_format->channels; stream_description.mChannelsPerFrame = audio_format.channels;
ComponentResult result = ComponentResult result =
AudioUnitSetProperty(od->au, kAudioUnitProperty_StreamFormat, AudioUnitSetProperty(od->au, kAudioUnitProperty_StreamFormat,
@ -374,8 +373,8 @@ osx_output_open(struct audio_output *ao, struct audio_format *audio_format, GErr
} }
/* create a buffer of 1s */ /* create a buffer of 1s */
od->buffer = fifo_buffer_new(audio_format->sample_rate * od->buffer = fifo_buffer_new(audio_format.sample_rate *
audio_format_frame_size(audio_format)); audio_format.GetFrameSize());
status = AudioOutputUnitStart(od->au); status = AudioOutputUnitStart(od->au);
if (status != 0) { if (status != 0) {

View File

@ -66,26 +66,26 @@ openal_output_quark(void)
} }
static ALenum static ALenum
openal_audio_format(struct audio_format *audio_format) openal_audio_format(AudioFormat &audio_format)
{ {
/* note: cannot map SAMPLE_FORMAT_S8 to AL_FORMAT_STEREO8 or /* note: cannot map SampleFormat::S8 to AL_FORMAT_STEREO8 or
AL_FORMAT_MONO8 since OpenAL expects unsigned 8 bit AL_FORMAT_MONO8 since OpenAL expects unsigned 8 bit
samples, while MPD uses signed samples */ samples, while MPD uses signed samples */
switch (audio_format->format) { switch (audio_format.format) {
case SAMPLE_FORMAT_S16: case SampleFormat::S16:
if (audio_format->channels == 2) if (audio_format.channels == 2)
return AL_FORMAT_STEREO16; return AL_FORMAT_STEREO16;
if (audio_format->channels == 1) if (audio_format.channels == 1)
return AL_FORMAT_MONO16; return AL_FORMAT_MONO16;
/* fall back to mono */ /* fall back to mono */
audio_format->channels = 1; audio_format.channels = 1;
return openal_audio_format(audio_format); return openal_audio_format(audio_format);
default: default:
/* fall back to 16 bit */ /* fall back to 16 bit */
audio_format->format = SAMPLE_FORMAT_S16; audio_format.format = SampleFormat::S16;
return openal_audio_format(audio_format); return openal_audio_format(audio_format);
} }
} }
@ -169,7 +169,7 @@ openal_finish(struct audio_output *ao)
} }
static bool static bool
openal_open(struct audio_output *ao, struct audio_format *audio_format, openal_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error) GError **error)
{ {
OpenALOutput *od = (OpenALOutput *)ao; OpenALOutput *od = (OpenALOutput *)ao;
@ -199,7 +199,7 @@ openal_open(struct audio_output *ao, struct audio_format *audio_format,
} }
od->filled = 0; od->filled = 0;
od->frequency = audio_format->sample_rate; od->frequency = audio_format.sample_rate;
return true; return true;
} }

View File

@ -70,7 +70,7 @@ struct OssOutput {
* The current input audio format. This is needed to reopen * The current input audio format. This is needed to reopen
* the device after cancel(). * the device after cancel().
*/ */
struct audio_format audio_format; AudioFormat audio_format;
/** /**
* The current OSS audio format. This is needed to reopen the * The current OSS audio format. This is needed to reopen the
@ -308,10 +308,10 @@ oss_try_ioctl(int fd, unsigned long request, int value,
* specified number is not supported. * specified number is not supported.
*/ */
static bool static bool
oss_setup_channels(int fd, struct audio_format *audio_format, GError **error_r) oss_setup_channels(int fd, AudioFormat &audio_format, GError **error_r)
{ {
const char *const msg = "Failed to set channel count"; const char *const msg = "Failed to set channel count";
int channels = audio_format->channels; int channels = audio_format.channels;
enum oss_setup_result result = enum oss_setup_result result =
oss_try_ioctl_r(fd, SNDCTL_DSP_CHANNELS, &channels, msg, error_r); oss_try_ioctl_r(fd, SNDCTL_DSP_CHANNELS, &channels, msg, error_r);
switch (result) { switch (result) {
@ -319,7 +319,7 @@ oss_setup_channels(int fd, struct audio_format *audio_format, GError **error_r)
if (!audio_valid_channel_count(channels)) if (!audio_valid_channel_count(channels))
break; break;
audio_format->channels = channels; audio_format.channels = channels;
return true; return true;
case ERROR: case ERROR:
@ -330,7 +330,7 @@ oss_setup_channels(int fd, struct audio_format *audio_format, GError **error_r)
} }
for (unsigned i = 1; i < 2; ++i) { for (unsigned i = 1; i < 2; ++i) {
if (i == audio_format->channels) if (i == audio_format.channels)
/* don't try that again */ /* don't try that again */
continue; continue;
@ -342,7 +342,7 @@ oss_setup_channels(int fd, struct audio_format *audio_format, GError **error_r)
if (!audio_valid_channel_count(channels)) if (!audio_valid_channel_count(channels))
break; break;
audio_format->channels = channels; audio_format.channels = channels;
return true; return true;
case ERROR: case ERROR:
@ -362,11 +362,11 @@ oss_setup_channels(int fd, struct audio_format *audio_format, GError **error_r)
* specified sample rate is not supported. * specified sample rate is not supported.
*/ */
static bool static bool
oss_setup_sample_rate(int fd, struct audio_format *audio_format, oss_setup_sample_rate(int fd, AudioFormat &audio_format,
GError **error_r) GError **error_r)
{ {
const char *const msg = "Failed to set sample rate"; const char *const msg = "Failed to set sample rate";
int sample_rate = audio_format->sample_rate; int sample_rate = audio_format.sample_rate;
enum oss_setup_result result = enum oss_setup_result result =
oss_try_ioctl_r(fd, SNDCTL_DSP_SPEED, &sample_rate, oss_try_ioctl_r(fd, SNDCTL_DSP_SPEED, &sample_rate,
msg, error_r); msg, error_r);
@ -375,7 +375,7 @@ oss_setup_sample_rate(int fd, struct audio_format *audio_format,
if (!audio_valid_sample_rate(sample_rate)) if (!audio_valid_sample_rate(sample_rate))
break; break;
audio_format->sample_rate = sample_rate; audio_format.sample_rate = sample_rate;
return true; return true;
case ERROR: case ERROR:
@ -388,7 +388,7 @@ oss_setup_sample_rate(int fd, struct audio_format *audio_format,
static const int sample_rates[] = { 48000, 44100, 0 }; static const int sample_rates[] = { 48000, 44100, 0 };
for (unsigned i = 0; sample_rates[i] != 0; ++i) { for (unsigned i = 0; sample_rates[i] != 0; ++i) {
sample_rate = sample_rates[i]; sample_rate = sample_rates[i];
if (sample_rate == (int)audio_format->sample_rate) if (sample_rate == (int)audio_format.sample_rate)
continue; continue;
result = oss_try_ioctl_r(fd, SNDCTL_DSP_SPEED, &sample_rate, result = oss_try_ioctl_r(fd, SNDCTL_DSP_SPEED, &sample_rate,
@ -398,7 +398,7 @@ oss_setup_sample_rate(int fd, struct audio_format *audio_format,
if (!audio_valid_sample_rate(sample_rate)) if (!audio_valid_sample_rate(sample_rate))
break; break;
audio_format->sample_rate = sample_rate; audio_format.sample_rate = sample_rate;
return true; return true;
case ERROR: case ERROR:
@ -418,28 +418,28 @@ oss_setup_sample_rate(int fd, struct audio_format *audio_format,
* AFMT_QUERY if there is no direct counterpart. * AFMT_QUERY if there is no direct counterpart.
*/ */
static int static int
sample_format_to_oss(enum sample_format format) sample_format_to_oss(SampleFormat format)
{ {
switch (format) { switch (format) {
case SAMPLE_FORMAT_UNDEFINED: case SampleFormat::UNDEFINED:
case SAMPLE_FORMAT_FLOAT: case SampleFormat::FLOAT:
case SAMPLE_FORMAT_DSD: case SampleFormat::DSD:
return AFMT_QUERY; return AFMT_QUERY;
case SAMPLE_FORMAT_S8: case SampleFormat::S8:
return AFMT_S8; return AFMT_S8;
case SAMPLE_FORMAT_S16: case SampleFormat::S16:
return AFMT_S16_NE; return AFMT_S16_NE;
case SAMPLE_FORMAT_S24_P32: case SampleFormat::S24_P32:
#ifdef AFMT_S24_NE #ifdef AFMT_S24_NE
return AFMT_S24_NE; return AFMT_S24_NE;
#else #else
return AFMT_QUERY; return AFMT_QUERY;
#endif #endif
case SAMPLE_FORMAT_S32: case SampleFormat::S32:
#ifdef AFMT_S32_NE #ifdef AFMT_S32_NE
return AFMT_S32_NE; return AFMT_S32_NE;
#else #else
@ -452,47 +452,47 @@ sample_format_to_oss(enum sample_format format)
/** /**
* Convert an OSS sample format to its MPD counterpart. Returns * Convert an OSS sample format to its MPD counterpart. Returns
* SAMPLE_FORMAT_UNDEFINED if there is no direct counterpart. * SampleFormat::UNDEFINED if there is no direct counterpart.
*/ */
static enum sample_format static SampleFormat
sample_format_from_oss(int format) sample_format_from_oss(int format)
{ {
switch (format) { switch (format) {
case AFMT_S8: case AFMT_S8:
return SAMPLE_FORMAT_S8; return SampleFormat::S8;
case AFMT_S16_NE: case AFMT_S16_NE:
return SAMPLE_FORMAT_S16; return SampleFormat::S16;
#ifdef AFMT_S24_PACKED #ifdef AFMT_S24_PACKED
case AFMT_S24_PACKED: case AFMT_S24_PACKED:
return SAMPLE_FORMAT_S24_P32; return SampleFormat::S24_P32;
#endif #endif
#ifdef AFMT_S24_NE #ifdef AFMT_S24_NE
case AFMT_S24_NE: case AFMT_S24_NE:
return SAMPLE_FORMAT_S24_P32; return SampleFormat::S24_P32;
#endif #endif
#ifdef AFMT_S32_NE #ifdef AFMT_S32_NE
case AFMT_S32_NE: case AFMT_S32_NE:
return SAMPLE_FORMAT_S32; return SampleFormat::S32;
#endif #endif
default: default:
return SAMPLE_FORMAT_UNDEFINED; return SampleFormat::UNDEFINED;
} }
} }
/** /**
* Probe one sample format. * Probe one sample format.
* *
* @return the selected sample format or SAMPLE_FORMAT_UNDEFINED on * @return the selected sample format or SampleFormat::UNDEFINED on
* error * error
*/ */
static enum oss_setup_result static enum oss_setup_result
oss_probe_sample_format(int fd, enum sample_format sample_format, oss_probe_sample_format(int fd, SampleFormat sample_format,
enum sample_format *sample_format_r, SampleFormat *sample_format_r,
int *oss_format_r, int *oss_format_r,
#ifdef AFMT_S24_PACKED #ifdef AFMT_S24_PACKED
PcmExport &pcm_export, PcmExport &pcm_export,
@ -509,7 +509,7 @@ oss_probe_sample_format(int fd, enum sample_format sample_format,
"Failed to set sample format", error_r); "Failed to set sample format", error_r);
#ifdef AFMT_S24_PACKED #ifdef AFMT_S24_PACKED
if (result == UNSUPPORTED && sample_format == SAMPLE_FORMAT_S24_P32) { if (result == UNSUPPORTED && sample_format == SampleFormat::S24_P32) {
/* if the driver doesn't support padded 24 bit, try /* if the driver doesn't support padded 24 bit, try
packed 24 bit */ packed 24 bit */
oss_format = AFMT_S24_PACKED; oss_format = AFMT_S24_PACKED;
@ -523,7 +523,7 @@ oss_probe_sample_format(int fd, enum sample_format sample_format,
return result; return result;
sample_format = sample_format_from_oss(oss_format); sample_format = sample_format_from_oss(oss_format);
if (sample_format == SAMPLE_FORMAT_UNDEFINED) if (sample_format == SampleFormat::UNDEFINED)
return UNSUPPORTED; return UNSUPPORTED;
*sample_format_r = sample_format; *sample_format_r = sample_format;
@ -544,16 +544,16 @@ oss_probe_sample_format(int fd, enum sample_format sample_format,
* specified format is not supported. * specified format is not supported.
*/ */
static bool static bool
oss_setup_sample_format(int fd, struct audio_format *audio_format, oss_setup_sample_format(int fd, AudioFormat &audio_format,
int *oss_format_r, int *oss_format_r,
#ifdef AFMT_S24_PACKED #ifdef AFMT_S24_PACKED
PcmExport &pcm_export, PcmExport &pcm_export,
#endif #endif
GError **error_r) GError **error_r)
{ {
enum sample_format mpd_format; SampleFormat mpd_format;
enum oss_setup_result result = enum oss_setup_result result =
oss_probe_sample_format(fd, sample_format(audio_format->format), oss_probe_sample_format(fd, audio_format.format,
&mpd_format, oss_format_r, &mpd_format, oss_format_r,
#ifdef AFMT_S24_PACKED #ifdef AFMT_S24_PACKED
pcm_export, pcm_export,
@ -561,7 +561,7 @@ oss_setup_sample_format(int fd, struct audio_format *audio_format,
error_r); error_r);
switch (result) { switch (result) {
case SUCCESS: case SUCCESS:
audio_format->format = mpd_format; audio_format.format = mpd_format;
return true; return true;
case ERROR: case ERROR:
@ -577,17 +577,17 @@ oss_setup_sample_format(int fd, struct audio_format *audio_format,
/* the requested sample format is not available - probe for /* the requested sample format is not available - probe for
other formats supported by MPD */ other formats supported by MPD */
static const enum sample_format sample_formats[] = { static const SampleFormat sample_formats[] = {
SAMPLE_FORMAT_S24_P32, SampleFormat::S24_P32,
SAMPLE_FORMAT_S32, SampleFormat::S32,
SAMPLE_FORMAT_S16, SampleFormat::S16,
SAMPLE_FORMAT_S8, SampleFormat::S8,
SAMPLE_FORMAT_UNDEFINED /* sentinel */ SampleFormat::UNDEFINED /* sentinel */
}; };
for (unsigned i = 0; sample_formats[i] != SAMPLE_FORMAT_UNDEFINED; ++i) { for (unsigned i = 0; sample_formats[i] != SampleFormat::UNDEFINED; ++i) {
mpd_format = sample_formats[i]; mpd_format = sample_formats[i];
if (mpd_format == audio_format->format) if (mpd_format == audio_format.format)
/* don't try that again */ /* don't try that again */
continue; continue;
@ -599,7 +599,7 @@ oss_setup_sample_format(int fd, struct audio_format *audio_format,
error_r); error_r);
switch (result) { switch (result) {
case SUCCESS: case SUCCESS:
audio_format->format = mpd_format; audio_format.format = mpd_format;
return true; return true;
case ERROR: case ERROR:
@ -619,7 +619,7 @@ oss_setup_sample_format(int fd, struct audio_format *audio_format,
* Sets up the OSS device which was opened before. * Sets up the OSS device which was opened before.
*/ */
static bool static bool
oss_setup(OssOutput *od, struct audio_format *audio_format, oss_setup(OssOutput *od, AudioFormat &audio_format,
GError **error_r) GError **error_r)
{ {
return oss_setup_channels(od->fd, audio_format, error_r) && return oss_setup_channels(od->fd, audio_format, error_r) &&
@ -687,7 +687,7 @@ oss_reopen(OssOutput *od, GError **error_r)
} }
static bool static bool
oss_output_open(struct audio_output *ao, struct audio_format *audio_format, oss_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error) GError **error)
{ {
OssOutput *od = (OssOutput *)ao; OssOutput *od = (OssOutput *)ao;
@ -705,7 +705,7 @@ oss_output_open(struct audio_output *ao, struct audio_format *audio_format,
return false; return false;
} }
od->audio_format = *audio_format; od->audio_format = audio_format;
return true; return true;
} }

View File

@ -95,7 +95,7 @@ pipe_output_finish(struct audio_output *ao)
static bool static bool
pipe_output_open(struct audio_output *ao, pipe_output_open(struct audio_output *ao,
G_GNUC_UNUSED struct audio_format *audio_format, G_GNUC_UNUSED AudioFormat &audio_format,
G_GNUC_UNUSED GError **error) G_GNUC_UNUSED GError **error)
{ {
PipeOutput *pd = (PipeOutput *)ao; PipeOutput *pd = (PipeOutput *)ao;

View File

@ -578,7 +578,7 @@ pulse_output_setup_stream(PulseOutput *po, const pa_sample_spec *ss,
} }
static bool static bool
pulse_output_open(struct audio_output *ao, struct audio_format *audio_format, pulse_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error_r) GError **error_r)
{ {
PulseOutput *po = (PulseOutput *)ao; PulseOutput *po = (PulseOutput *)ao;
@ -615,11 +615,11 @@ pulse_output_open(struct audio_output *ao, struct audio_format *audio_format,
/* MPD doesn't support the other pulseaudio sample formats, so /* MPD doesn't support the other pulseaudio sample formats, so
we just force MPD to send us everything as 16 bit */ we just force MPD to send us everything as 16 bit */
audio_format->format = SAMPLE_FORMAT_S16; audio_format.format = SampleFormat::S16;
ss.format = PA_SAMPLE_S16NE; ss.format = PA_SAMPLE_S16NE;
ss.rate = audio_format->sample_rate; ss.rate = audio_format.sample_rate;
ss.channels = audio_format->channels; ss.channels = audio_format.channels;
/* create a stream .. */ /* create a stream .. */

View File

@ -192,7 +192,7 @@ RecorderOutput::EncoderToFile(GError **error_r)
static bool static bool
recorder_output_open(struct audio_output *ao, recorder_output_open(struct audio_output *ao,
struct audio_format *audio_format, AudioFormat &audio_format,
GError **error_r) GError **error_r)
{ {
RecorderOutput *recorder = (RecorderOutput *)ao; RecorderOutput *recorder = (RecorderOutput *)ao;

View File

@ -144,39 +144,41 @@ roar_finish(struct audio_output *ao)
static void static void
roar_use_audio_format(struct roar_audio_info *info, roar_use_audio_format(struct roar_audio_info *info,
struct audio_format *audio_format) AudioFormat &audio_format)
{ {
info->rate = audio_format->sample_rate; info->rate = audio_format.sample_rate;
info->channels = audio_format->channels; info->channels = audio_format.channels;
info->codec = ROAR_CODEC_PCM_S; info->codec = ROAR_CODEC_PCM_S;
switch (audio_format->format) { switch (audio_format.format) {
case SAMPLE_FORMAT_UNDEFINED: case SampleFormat::UNDEFINED:
case SampleFormat::FLOAT:
case SampleFormat::DSD:
info->bits = 16; info->bits = 16;
audio_format->format = SAMPLE_FORMAT_S16; audio_format.format = SampleFormat::S16;
break; break;
case SAMPLE_FORMAT_S8: case SampleFormat::S8:
info->bits = 8; info->bits = 8;
break; break;
case SAMPLE_FORMAT_S16: case SampleFormat::S16:
info->bits = 16; info->bits = 16;
break; break;
case SAMPLE_FORMAT_S24_P32: case SampleFormat::S24_P32:
info->bits = 32; info->bits = 32;
audio_format->format = SAMPLE_FORMAT_S32; audio_format.format = SampleFormat::S32;
break; break;
case SAMPLE_FORMAT_S32: case SampleFormat::S32:
info->bits = 32; info->bits = 32;
break; break;
} }
} }
static bool static bool
roar_open(struct audio_output *ao, struct audio_format *audio_format, GError **error) roar_open(struct audio_output *ao, AudioFormat &audio_format, GError **error)
{ {
RoarOutput *self = (RoarOutput *)ao; RoarOutput *self = (RoarOutput *)ao;
const ScopeLock protect(self->mutex); const ScopeLock protect(self->mutex);

View File

@ -116,9 +116,8 @@ inline bool
ShoutOutput::Configure(const config_param *param, GError **error_r) ShoutOutput::Configure(const config_param *param, GError **error_r)
{ {
const struct audio_format *audio_format = const AudioFormat audio_format = base.config_audio_format;
&base.config_audio_format; if (!audio_format.IsFullyDefined()) {
if (!audio_format_fully_defined(audio_format)) {
g_set_error(error_r, shout_output_quark(), 0, g_set_error(error_r, shout_output_quark(), 0,
"Need full audio format specification"); "Need full audio format specification");
return nullptr; return nullptr;
@ -269,10 +268,10 @@ ShoutOutput::Configure(const config_param *param, GError **error_r)
char temp[11]; char temp[11];
memset(temp, 0, sizeof(temp)); memset(temp, 0, sizeof(temp));
snprintf(temp, sizeof(temp), "%u", audio_format->channels); snprintf(temp, sizeof(temp), "%u", audio_format.channels);
shout_set_audio_info(shout_conn, SHOUT_AI_CHANNELS, temp); shout_set_audio_info(shout_conn, SHOUT_AI_CHANNELS, temp);
snprintf(temp, sizeof(temp), "%u", audio_format->sample_rate); snprintf(temp, sizeof(temp), "%u", audio_format.sample_rate);
shout_set_audio_info(shout_conn, SHOUT_AI_SAMPLERATE, temp); shout_set_audio_info(shout_conn, SHOUT_AI_SAMPLERATE, temp);
@ -428,7 +427,7 @@ shout_connect(ShoutOutput *sd, GError **error)
} }
static bool static bool
my_shout_open_device(struct audio_output *ao, struct audio_format *audio_format, my_shout_open_device(struct audio_output *ao, AudioFormat &audio_format,
GError **error) GError **error)
{ {
ShoutOutput *sd = (ShoutOutput *)ao; ShoutOutput *sd = (ShoutOutput *)ao;

View File

@ -113,7 +113,7 @@ solaris_output_finish(struct audio_output *ao)
} }
static bool static bool
solaris_output_open(struct audio_output *ao, struct audio_format *audio_format, solaris_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error) GError **error)
{ {
SolarisOutput *so = (SolarisOutput *)ao; SolarisOutput *so = (SolarisOutput *)ao;
@ -122,7 +122,7 @@ solaris_output_open(struct audio_output *ao, struct audio_format *audio_format,
/* support only 16 bit mono/stereo for now; nothing else has /* support only 16 bit mono/stereo for now; nothing else has
been tested */ been tested */
audio_format->format = SAMPLE_FORMAT_S16; audio_format.format = SampleFormat::S16;
/* open the device in non-blocking mode */ /* open the device in non-blocking mode */
@ -150,8 +150,8 @@ solaris_output_open(struct audio_output *ao, struct audio_format *audio_format,
return false; return false;
} }
info.play.sample_rate = audio_format->sample_rate; info.play.sample_rate = audio_format.sample_rate;
info.play.channels = audio_format->channels; info.play.channels = audio_format.channels;
info.play.precision = 16; info.play.precision = 16;
info.play.encoding = AUDIO_ENCODING_LINEAR; info.play.encoding = AUDIO_ENCODING_LINEAR;

View File

@ -142,7 +142,7 @@ winmm_output_finish(struct audio_output *ao)
} }
static bool static bool
winmm_output_open(struct audio_output *ao, struct audio_format *audio_format, winmm_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error_r) GError **error_r)
{ {
WinmmOutput *wo = (WinmmOutput *)ao; WinmmOutput *wo = (WinmmOutput *)ao;
@ -154,30 +154,32 @@ winmm_output_open(struct audio_output *ao, struct audio_format *audio_format,
return false; return false;
} }
switch (audio_format->format) { switch (audio_format.format) {
case SAMPLE_FORMAT_S8: case SampleFormat::S8:
case SAMPLE_FORMAT_S16: case SampleFormat::S16:
break; break;
case SAMPLE_FORMAT_S24_P32: case SampleFormat::S24_P32:
case SAMPLE_FORMAT_S32: case SampleFormat::S32:
case SAMPLE_FORMAT_UNDEFINED: case SampleFormat::FLOAT:
case SampleFormat::DSD:
case SampleFormat::UNDEFINED:
/* we havn't tested formats other than S16 */ /* we havn't tested formats other than S16 */
audio_format->format = SAMPLE_FORMAT_S16; audio_format.format = SampleFormat::S16;
break; break;
} }
if (audio_format->channels > 2) if (audio_format.channels > 2)
/* same here: more than stereo was not tested */ /* same here: more than stereo was not tested */
audio_format->channels = 2; audio_format.channels = 2;
WAVEFORMATEX format; WAVEFORMATEX format;
format.wFormatTag = WAVE_FORMAT_PCM; format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = audio_format->channels; format.nChannels = audio_format.channels;
format.nSamplesPerSec = audio_format->sample_rate; format.nSamplesPerSec = audio_format.sample_rate;
format.nBlockAlign = audio_format_frame_size(audio_format); format.nBlockAlign = audio_format.GetFrameSize();
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
format.wBitsPerSample = audio_format_sample_size(audio_format) * 8; format.wBitsPerSample = audio_format.GetSampleSize() * 8;
format.cbSize = 0; format.cbSize = 0;
MMRESULT result = waveOutOpen(&wo->handle, wo->device_id, &format, MMRESULT result = waveOutOpen(&wo->handle, wo->device_id, &format,

View File

@ -22,7 +22,7 @@
#include "PcmChannels.hxx" #include "PcmChannels.hxx"
#include "PcmFormat.hxx" #include "PcmFormat.hxx"
#include "pcm_pack.h" #include "pcm_pack.h"
#include "audio_format.h" #include "AudioFormat.hxx"
#include <glib.h> #include <glib.h>
@ -48,46 +48,46 @@ PcmConvert::Reset()
} }
inline const int16_t * inline const int16_t *
PcmConvert::Convert16(const audio_format *src_format, PcmConvert::Convert16(const AudioFormat src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
const audio_format *dest_format, size_t *dest_size_r, const AudioFormat dest_format, size_t *dest_size_r,
GError **error_r) GError **error_r)
{ {
const int16_t *buf; const int16_t *buf;
size_t len; size_t len;
assert(dest_format->format == SAMPLE_FORMAT_S16); assert(dest_format.format == SampleFormat::S16);
buf = pcm_convert_to_16(format_buffer, dither, buf = pcm_convert_to_16(format_buffer, dither,
sample_format(src_format->format), src_format.format,
src_buffer, src_size, src_buffer, src_size,
&len); &len);
if (buf == NULL) { if (buf == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, g_set_error(error_r, pcm_convert_quark(), 0,
"Conversion from %s to 16 bit is not implemented", "Conversion from %s to 16 bit is not implemented",
sample_format_to_string(sample_format(src_format->format))); sample_format_to_string(src_format.format));
return NULL; return NULL;
} }
if (src_format->channels != dest_format->channels) { if (src_format.channels != dest_format.channels) {
buf = pcm_convert_channels_16(channels_buffer, buf = pcm_convert_channels_16(channels_buffer,
dest_format->channels, dest_format.channels,
src_format->channels, src_format.channels,
buf, len, &len); buf, len, &len);
if (buf == NULL) { if (buf == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, g_set_error(error_r, pcm_convert_quark(), 0,
"Conversion from %u to %u channels " "Conversion from %u to %u channels "
"is not implemented", "is not implemented",
src_format->channels, src_format.channels,
dest_format->channels); dest_format.channels);
return NULL; return NULL;
} }
} }
if (src_format->sample_rate != dest_format->sample_rate) { if (src_format.sample_rate != dest_format.sample_rate) {
buf = resampler.Resample16(dest_format->channels, buf = resampler.Resample16(dest_format.channels,
src_format->sample_rate, buf, len, src_format.sample_rate, buf, len,
dest_format->sample_rate, &len, dest_format.sample_rate, &len,
error_r); error_r);
if (buf == NULL) if (buf == NULL)
return NULL; return NULL;
@ -98,45 +98,45 @@ PcmConvert::Convert16(const audio_format *src_format,
} }
inline const int32_t * inline const int32_t *
PcmConvert::Convert24(const audio_format *src_format, PcmConvert::Convert24(const AudioFormat src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
const audio_format *dest_format, size_t *dest_size_r, const AudioFormat dest_format, size_t *dest_size_r,
GError **error_r) GError **error_r)
{ {
const int32_t *buf; const int32_t *buf;
size_t len; size_t len;
assert(dest_format->format == SAMPLE_FORMAT_S24_P32); assert(dest_format.format == SampleFormat::S24_P32);
buf = pcm_convert_to_24(format_buffer, buf = pcm_convert_to_24(format_buffer,
sample_format(src_format->format), src_format.format,
src_buffer, src_size, &len); src_buffer, src_size, &len);
if (buf == NULL) { if (buf == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, g_set_error(error_r, pcm_convert_quark(), 0,
"Conversion from %s to 24 bit is not implemented", "Conversion from %s to 24 bit is not implemented",
sample_format_to_string(sample_format(src_format->format))); sample_format_to_string(src_format.format));
return NULL; return NULL;
} }
if (src_format->channels != dest_format->channels) { if (src_format.channels != dest_format.channels) {
buf = pcm_convert_channels_24(channels_buffer, buf = pcm_convert_channels_24(channels_buffer,
dest_format->channels, dest_format.channels,
src_format->channels, src_format.channels,
buf, len, &len); buf, len, &len);
if (buf == NULL) { if (buf == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, g_set_error(error_r, pcm_convert_quark(), 0,
"Conversion from %u to %u channels " "Conversion from %u to %u channels "
"is not implemented", "is not implemented",
src_format->channels, src_format.channels,
dest_format->channels); dest_format.channels);
return NULL; return NULL;
} }
} }
if (src_format->sample_rate != dest_format->sample_rate) { if (src_format.sample_rate != dest_format.sample_rate) {
buf = resampler.Resample24(dest_format->channels, buf = resampler.Resample24(dest_format.channels,
src_format->sample_rate, buf, len, src_format.sample_rate, buf, len,
dest_format->sample_rate, &len, dest_format.sample_rate, &len,
error_r); error_r);
if (buf == NULL) if (buf == NULL)
return NULL; return NULL;
@ -147,45 +147,45 @@ PcmConvert::Convert24(const audio_format *src_format,
} }
inline const int32_t * inline const int32_t *
PcmConvert::Convert32(const audio_format *src_format, PcmConvert::Convert32(const AudioFormat src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
const audio_format *dest_format, size_t *dest_size_r, const AudioFormat dest_format, size_t *dest_size_r,
GError **error_r) GError **error_r)
{ {
const int32_t *buf; const int32_t *buf;
size_t len; size_t len;
assert(dest_format->format == SAMPLE_FORMAT_S32); assert(dest_format.format == SampleFormat::S32);
buf = pcm_convert_to_32(format_buffer, buf = pcm_convert_to_32(format_buffer,
sample_format(src_format->format), src_format.format,
src_buffer, src_size, &len); src_buffer, src_size, &len);
if (buf == NULL) { if (buf == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, g_set_error(error_r, pcm_convert_quark(), 0,
"Conversion from %s to 32 bit is not implemented", "Conversion from %s to 32 bit is not implemented",
sample_format_to_string(sample_format(src_format->format))); sample_format_to_string(src_format.format));
return NULL; return NULL;
} }
if (src_format->channels != dest_format->channels) { if (src_format.channels != dest_format.channels) {
buf = pcm_convert_channels_32(channels_buffer, buf = pcm_convert_channels_32(channels_buffer,
dest_format->channels, dest_format.channels,
src_format->channels, src_format.channels,
buf, len, &len); buf, len, &len);
if (buf == NULL) { if (buf == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, g_set_error(error_r, pcm_convert_quark(), 0,
"Conversion from %u to %u channels " "Conversion from %u to %u channels "
"is not implemented", "is not implemented",
src_format->channels, src_format.channels,
dest_format->channels); dest_format.channels);
return NULL; return NULL;
} }
} }
if (src_format->sample_rate != dest_format->sample_rate) { if (src_format.sample_rate != dest_format.sample_rate) {
buf = resampler.Resample32(dest_format->channels, buf = resampler.Resample32(dest_format.channels,
src_format->sample_rate, buf, len, src_format.sample_rate, buf, len,
dest_format->sample_rate, &len, dest_format.sample_rate, &len,
error_r); error_r);
if (buf == NULL) if (buf == NULL)
return buf; return buf;
@ -196,41 +196,41 @@ PcmConvert::Convert32(const audio_format *src_format,
} }
inline const float * inline const float *
PcmConvert::ConvertFloat(const audio_format *src_format, PcmConvert::ConvertFloat(const AudioFormat src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
const audio_format *dest_format, size_t *dest_size_r, const AudioFormat dest_format, size_t *dest_size_r,
GError **error_r) GError **error_r)
{ {
const float *buffer = (const float *)src_buffer; const float *buffer = (const float *)src_buffer;
size_t size = src_size; size_t size = src_size;
assert(dest_format->format == SAMPLE_FORMAT_FLOAT); assert(dest_format.format == SampleFormat::FLOAT);
/* convert to float now */ /* convert to float now */
buffer = pcm_convert_to_float(format_buffer, buffer = pcm_convert_to_float(format_buffer,
sample_format(src_format->format), src_format.format,
buffer, size, &size); buffer, size, &size);
if (buffer == NULL) { if (buffer == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, g_set_error(error_r, pcm_convert_quark(), 0,
"Conversion from %s to float is not implemented", "Conversion from %s to float is not implemented",
sample_format_to_string(sample_format(src_format->format))); sample_format_to_string(src_format.format));
return NULL; return NULL;
} }
/* convert channels */ /* convert channels */
if (src_format->channels != dest_format->channels) { if (src_format.channels != dest_format.channels) {
buffer = pcm_convert_channels_float(channels_buffer, buffer = pcm_convert_channels_float(channels_buffer,
dest_format->channels, dest_format.channels,
src_format->channels, src_format.channels,
buffer, size, &size); buffer, size, &size);
if (buffer == NULL) { if (buffer == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, g_set_error(error_r, pcm_convert_quark(), 0,
"Conversion from %u to %u channels " "Conversion from %u to %u channels "
"is not implemented", "is not implemented",
src_format->channels, src_format.channels,
dest_format->channels); dest_format.channels);
return NULL; return NULL;
} }
} }
@ -238,11 +238,11 @@ PcmConvert::ConvertFloat(const audio_format *src_format,
/* resample with float, because this is the best format for /* resample with float, because this is the best format for
libsamplerate */ libsamplerate */
if (src_format->sample_rate != dest_format->sample_rate) { if (src_format.sample_rate != dest_format.sample_rate) {
buffer = resampler.ResampleFloat(dest_format->channels, buffer = resampler.ResampleFloat(dest_format.channels,
src_format->sample_rate, src_format.sample_rate,
buffer, size, buffer, size,
dest_format->sample_rate, dest_format.sample_rate,
&size, error_r); &size, error_r);
if (buffer == NULL) if (buffer == NULL)
return NULL; return NULL;
@ -253,16 +253,16 @@ PcmConvert::ConvertFloat(const audio_format *src_format,
} }
const void * const void *
PcmConvert::Convert(const audio_format *src_format, PcmConvert::Convert(AudioFormat src_format,
const void *src, size_t src_size, const void *src, size_t src_size,
const audio_format *dest_format, const AudioFormat dest_format,
size_t *dest_size_r, size_t *dest_size_r,
GError **error_r) GError **error_r)
{ {
struct audio_format float_format; AudioFormat float_format;
if (src_format->format == SAMPLE_FORMAT_DSD) { if (src_format.format == SampleFormat::DSD) {
size_t f_size; size_t f_size;
const float *f = dsd.ToFloat(src_format->channels, const float *f = dsd.ToFloat(src_format.channels,
false, (const uint8_t *)src, false, (const uint8_t *)src,
src_size, &f_size); src_size, &f_size);
if (f == NULL) { if (f == NULL) {
@ -271,31 +271,31 @@ PcmConvert::Convert(const audio_format *src_format,
return NULL; return NULL;
} }
float_format = *src_format; float_format = src_format;
float_format.format = SAMPLE_FORMAT_FLOAT; float_format.format = SampleFormat::FLOAT;
src_format = &float_format; src_format = float_format;
src = f; src = f;
src_size = f_size; src_size = f_size;
} }
switch (sample_format(dest_format->format)) { switch (dest_format.format) {
case SAMPLE_FORMAT_S16: case SampleFormat::S16:
return Convert16(src_format, src, src_size, return Convert16(src_format, src, src_size,
dest_format, dest_size_r, dest_format, dest_size_r,
error_r); error_r);
case SAMPLE_FORMAT_S24_P32: case SampleFormat::S24_P32:
return Convert24(src_format, src, src_size, return Convert24(src_format, src, src_size,
dest_format, dest_size_r, dest_format, dest_size_r,
error_r); error_r);
case SAMPLE_FORMAT_S32: case SampleFormat::S32:
return Convert32(src_format, src, src_size, return Convert32(src_format, src, src_size,
dest_format, dest_size_r, dest_format, dest_size_r,
error_r); error_r);
case SAMPLE_FORMAT_FLOAT: case SampleFormat::FLOAT:
return ConvertFloat(src_format, src, src_size, return ConvertFloat(src_format, src, src_size,
dest_format, dest_size_r, dest_format, dest_size_r,
error_r); error_r);
@ -303,7 +303,7 @@ PcmConvert::Convert(const audio_format *src_format,
default: default:
g_set_error(error_r, pcm_convert_quark(), 0, g_set_error(error_r, pcm_convert_quark(), 0,
"PCM conversion to %s is not implemented", "PCM conversion to %s is not implemented",
sample_format_to_string(sample_format(dest_format->format))); sample_format_to_string(dest_format.format));
return NULL; return NULL;
} }
} }

View File

@ -27,7 +27,7 @@
#include <glib.h> #include <glib.h>
struct audio_format; struct AudioFormat;
/** /**
* This object is statically allocated (within another struct), and * This object is statically allocated (within another struct), and
@ -71,34 +71,34 @@ public:
* ignore errors * ignore errors
* @return the destination buffer, or NULL on error * @return the destination buffer, or NULL on error
*/ */
const void *Convert(const audio_format *src_format, const void *Convert(AudioFormat src_format,
const void *src, size_t src_size, const void *src, size_t src_size,
const audio_format *dest_format, AudioFormat dest_format,
size_t *dest_size_r, size_t *dest_size_r,
GError **error_r); GError **error_r);
private: private:
const int16_t *Convert16(const audio_format *src_format, const int16_t *Convert16(AudioFormat src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
const audio_format *dest_format, AudioFormat dest_format,
size_t *dest_size_r, size_t *dest_size_r,
GError **error_r); GError **error_r);
const int32_t *Convert24(const audio_format *src_format, const int32_t *Convert24(AudioFormat src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
const audio_format *dest_format, AudioFormat dest_format,
size_t *dest_size_r, size_t *dest_size_r,
GError **error_r); GError **error_r);
const int32_t *Convert32(const audio_format *src_format, const int32_t *Convert32(AudioFormat src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
const audio_format *dest_format, AudioFormat dest_format,
size_t *dest_size_r, size_t *dest_size_r,
GError **error_r); GError **error_r);
const float *ConvertFloat(const audio_format *src_format, const float *ConvertFloat(AudioFormat src_format,
const void *src_buffer, size_t src_size, const void *src_buffer, size_t src_size,
const audio_format *dest_format, AudioFormat dest_format,
size_t *dest_size_r, size_t *dest_size_r,
GError **error_r); GError **error_r);
}; };

View File

@ -20,7 +20,7 @@
#include "config.h" #include "config.h"
#include "PcmDsdUsb.hxx" #include "PcmDsdUsb.hxx"
#include "PcmBuffer.hxx" #include "PcmBuffer.hxx"
#include "audio_format.h" #include "AudioFormat.hxx"
G_GNUC_CONST G_GNUC_CONST
static inline uint32_t static inline uint32_t

View File

@ -27,21 +27,21 @@ extern "C" {
} }
void void
PcmExport::Open(enum sample_format sample_format, unsigned _channels, PcmExport::Open(SampleFormat sample_format, unsigned _channels,
bool _dsd_usb, bool _shift8, bool _pack, bool _reverse_endian) bool _dsd_usb, bool _shift8, bool _pack, bool _reverse_endian)
{ {
assert(audio_valid_sample_format(sample_format)); assert(audio_valid_sample_format(sample_format));
assert(!_dsd_usb || audio_valid_channel_count(_channels)); assert(!_dsd_usb || audio_valid_channel_count(_channels));
channels = _channels; channels = _channels;
dsd_usb = _dsd_usb && sample_format == SAMPLE_FORMAT_DSD; dsd_usb = _dsd_usb && sample_format == SampleFormat::DSD;
if (dsd_usb) if (dsd_usb)
/* after the conversion to DSD-over-USB, the DSD /* after the conversion to DSD-over-USB, the DSD
samples are stuffed inside fake 24 bit samples */ samples are stuffed inside fake 24 bit samples */
sample_format = SAMPLE_FORMAT_S24_P32; sample_format = SampleFormat::S24_P32;
shift8 = _shift8 && sample_format == SAMPLE_FORMAT_S24_P32; shift8 = _shift8 && sample_format == SampleFormat::S24_P32;
pack24 = _pack && sample_format == SAMPLE_FORMAT_S24_P32; pack24 = _pack && sample_format == SampleFormat::S24_P32;
assert(!shift8 || !pack24); assert(!shift8 || !pack24);
@ -58,7 +58,7 @@ PcmExport::Open(enum sample_format sample_format, unsigned _channels,
} }
size_t size_t
PcmExport::GetFrameSize(const struct audio_format &audio_format) const PcmExport::GetFrameSize(const AudioFormat &audio_format) const
{ {
if (pack24) if (pack24)
/* packed 24 bit samples (3 bytes per sample) */ /* packed 24 bit samples (3 bytes per sample) */
@ -71,7 +71,7 @@ PcmExport::GetFrameSize(const struct audio_format &audio_format) const
bytes per sample) */ bytes per sample) */
return channels * 4; return channels * 4;
return audio_format_frame_size(&audio_format); return audio_format.GetFrameSize();
} }
const void * const void *

Some files were not shown because too many files have changed in this diff Show More