diff --git a/Makefile.am b/Makefile.am index 049506980..760e07765 100644 --- a/Makefile.am +++ b/Makefile.am @@ -877,6 +877,7 @@ test_run_normalize_LDADD = \ $(GLIB_LIBS) test_run_convert_SOURCES = test/run_convert.c \ + src/audio_format.c \ src/audio_check.c \ src/audio_parser.c \ src/pcm_channels.c \ diff --git a/src/audio_check.c b/src/audio_check.c index 4046e8862..a843975fa 100644 --- a/src/audio_check.c +++ b/src/audio_check.c @@ -35,7 +35,7 @@ audio_check_sample_rate(unsigned long sample_rate, GError **error_r) } bool -audio_check_sample_format(unsigned sample_format, GError **error_r) +audio_check_sample_format(enum sample_format sample_format, GError **error_r) { if (!audio_valid_sample_format(sample_format)) { g_set_error(error_r, audio_format_quark(), 0, @@ -60,7 +60,7 @@ audio_check_channel_count(unsigned channels, GError **error_r) bool audio_format_init_checked(struct audio_format *af, unsigned long sample_rate, - unsigned sample_format, unsigned channels, + enum sample_format sample_format, unsigned channels, GError **error_r) { if (audio_check_sample_rate(sample_rate, error_r) && diff --git a/src/audio_check.h b/src/audio_check.h index a11fbe3d3..197dedd48 100644 --- a/src/audio_check.h +++ b/src/audio_check.h @@ -20,11 +20,11 @@ #ifndef MPD_AUDIO_CHECK_H #define MPD_AUDIO_CHECK_H +#include "audio_format.h" + #include #include -struct audio_format; - /** * The GLib quark used for errors reported by this library. */ @@ -48,7 +48,7 @@ audio_check_channel_count(unsigned sample_format, GError **error_r); */ bool audio_format_init_checked(struct audio_format *af, unsigned long sample_rate, - unsigned sample_format, unsigned channels, + enum sample_format sample_format, unsigned channels, GError **error_r); #endif diff --git a/src/audio_format.c b/src/audio_format.c index f88735c73..33cd90f58 100644 --- a/src/audio_format.c +++ b/src/audio_format.c @@ -28,6 +28,31 @@ #define REVERSE_ENDIAN_SUFFIX "_be" #endif +const char * +sample_format_to_string(enum sample_format format) +{ + switch (format) { + case SAMPLE_FORMAT_UNDEFINED: + return "?"; + + case SAMPLE_FORMAT_S8: + return "8"; + + case SAMPLE_FORMAT_S16: + return "16"; + + case SAMPLE_FORMAT_S24_P32: + return "24"; + + case SAMPLE_FORMAT_S32: + return "32"; + } + + /* unreachable */ + assert(false); + return "?"; +} + const char * audio_format_to_string(const struct audio_format *af, struct audio_format_string *s) @@ -35,8 +60,8 @@ audio_format_to_string(const struct audio_format *af, assert(af != NULL); assert(s != NULL); - snprintf(s->buffer, sizeof(s->buffer), "%u:%u%s:%u", - af->sample_rate, af->bits, + snprintf(s->buffer, sizeof(s->buffer), "%u:%s%s:%u", + af->sample_rate, sample_format_to_string(af->format), af->reverse_endian ? REVERSE_ENDIAN_SUFFIX : "", af->channels); diff --git a/src/audio_format.h b/src/audio_format.h index 0c1e425a9..6e7d50c46 100644 --- a/src/audio_format.h +++ b/src/audio_format.h @@ -23,6 +23,21 @@ #include #include +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, +}; + /** * This structure describes the format of a raw PCM stream. */ @@ -35,11 +50,10 @@ struct audio_format { uint32_t sample_rate; /** - * The number of significant bits per sample. Samples are - * currently always signed. Supported values are 8, 16, 24, - * 32. 24 bit samples are packed in 32 bit integers. + * The format samples are stored in. See the #sample_format + * enum for valid values. */ - uint8_t bits; + uint8_t format; /** * The number of channels. Only mono (1) and stereo (2) are @@ -69,7 +83,7 @@ struct audio_format_string { static inline void audio_format_clear(struct audio_format *af) { af->sample_rate = 0; - af->bits = 0; + af->format = SAMPLE_FORMAT_UNDEFINED; af->channels = 0; af->reverse_endian = 0; } @@ -80,10 +94,10 @@ static inline void audio_format_clear(struct audio_format *af) */ static inline void audio_format_init(struct audio_format *af, uint32_t sample_rate, - uint8_t bits, uint8_t channels) + enum sample_format format, uint8_t channels) { af->sample_rate = sample_rate; - af->bits = bits; + af->format = (uint8_t)format; af->channels = channels; af->reverse_endian = 0; } @@ -105,7 +119,8 @@ static inline bool audio_format_defined(const struct audio_format *af) static inline bool audio_format_fully_defined(const struct audio_format *af) { - return af->sample_rate != 0 && af->bits != 0 && af->channels != 0; + return af->sample_rate != 0 && af->format != SAMPLE_FORMAT_UNDEFINED && + af->channels != 0; } /** @@ -115,7 +130,8 @@ audio_format_fully_defined(const struct audio_format *af) static inline bool audio_format_mask_defined(const struct audio_format *af) { - return af->sample_rate != 0 || af->bits != 0 || af->channels != 0; + return af->sample_rate != 0 || af->format != SAMPLE_FORMAT_UNDEFINED || + af->channels != 0; } /** @@ -135,9 +151,20 @@ audio_valid_sample_rate(unsigned sample_rate) * @param bits the number of significant bits per sample */ static inline bool -audio_valid_sample_format(unsigned bits) +audio_valid_sample_format(enum sample_format format) { - return bits == 16 || bits == 24 || bits == 32 || bits == 8; + switch (format) { + case SAMPLE_FORMAT_S8: + case SAMPLE_FORMAT_S16: + case SAMPLE_FORMAT_S24_P32: + case SAMPLE_FORMAT_S32: + return true; + + case SAMPLE_FORMAT_UNDEFINED: + break; + } + + return false; } /** @@ -156,7 +183,7 @@ audio_valid_channel_count(unsigned channels) static inline bool audio_format_valid(const struct audio_format *af) { return audio_valid_sample_rate(af->sample_rate) && - audio_valid_sample_format(af->bits) && + audio_valid_sample_format((enum sample_format)af->format) && audio_valid_channel_count(af->channels); } @@ -168,7 +195,8 @@ 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->bits == 0 || audio_valid_sample_format(af->bits)) && + (af->format == SAMPLE_FORMAT_UNDEFINED || + audio_valid_sample_format((enum sample_format)af->format)) && (af->channels == 0 || audio_valid_channel_count(af->channels)); } @@ -176,7 +204,7 @@ static inline bool audio_format_equals(const struct audio_format *a, const struct audio_format *b) { return a->sample_rate == b->sample_rate && - a->bits == b->bits && + a->format == b->format && a->channels == b->channels && a->reverse_endian == b->reverse_endian; } @@ -188,8 +216,8 @@ audio_format_mask_apply(struct audio_format *af, if (mask->sample_rate != 0) af->sample_rate = mask->sample_rate; - if (mask->bits != 0) - af->bits = mask->bits; + if (mask->format != SAMPLE_FORMAT_UNDEFINED) + af->format = mask->format; if (mask->channels != 0) af->channels = mask->channels; @@ -200,12 +228,22 @@ audio_format_mask_apply(struct audio_format *af, */ static inline unsigned audio_format_sample_size(const struct audio_format *af) { - if (af->bits <= 8) + switch (af->format) { + case SAMPLE_FORMAT_S8: return 1; - else if (af->bits <= 16) + + case SAMPLE_FORMAT_S16: return 2; - else + + case SAMPLE_FORMAT_S24_P32: + case SAMPLE_FORMAT_S32: return 4; + + case SAMPLE_FORMAT_UNDEFINED: + break; + } + + return 0; } /** @@ -226,6 +264,16 @@ 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 + */ +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. diff --git a/src/audio_parser.c b/src/audio_parser.c index df87be325..210ea7a62 100644 --- a/src/audio_parser.c +++ b/src/audio_parser.c @@ -27,6 +27,7 @@ #include "audio_format.h" #include "audio_check.h" +#include #include /** @@ -65,14 +66,16 @@ parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r, } static bool -parse_sample_format(const char *src, bool mask, uint8_t *bits_r, +parse_sample_format(const char *src, bool mask, + enum sample_format *sample_format_r, const char **endptr_r, GError **error_r) { unsigned long value; char *endptr; + enum sample_format sample_format; if (mask && *src == '*') { - *bits_r = 0; + *sample_format_r = SAMPLE_FORMAT_UNDEFINED; *endptr_r = src + 1; return true; } @@ -82,10 +85,34 @@ parse_sample_format(const char *src, bool mask, uint8_t *bits_r, g_set_error(error_r, audio_parser_quark(), 0, "Failed to parse the sample format"); return false; - } else if (!audio_check_sample_format(value, error_r)) - return false; + } - *bits_r = value; + switch (value) { + case 8: + sample_format = SAMPLE_FORMAT_S8; + break; + + case 16: + sample_format = SAMPLE_FORMAT_S16; + break; + + case 24: + sample_format = SAMPLE_FORMAT_S24_P32; + break; + + case 32: + sample_format = SAMPLE_FORMAT_S32; + break; + + default: + g_set_error(error_r, audio_parser_quark(), 0, + "Invalid sample format: %lu", value); + return false; + } + + assert(audio_valid_sample_format(sample_format)); + + *sample_format_r = sample_format; *endptr_r = endptr; return true; } @@ -121,7 +148,8 @@ audio_format_parse(struct audio_format *dest, const char *src, bool mask, GError **error_r) { uint32_t rate; - uint8_t bits, channels; + enum sample_format sample_format; + uint8_t channels; audio_format_clear(dest); @@ -138,7 +166,7 @@ audio_format_parse(struct audio_format *dest, const char *src, /* parse sample format */ - if (!parse_sample_format(src, mask, &bits, &src, error_r)) + if (!parse_sample_format(src, mask, &sample_format, &src, error_r)) return false; if (*src++ != ':') { @@ -158,7 +186,7 @@ audio_format_parse(struct audio_format *dest, const char *src, return false; } - audio_format_init(dest, rate, bits, channels); + audio_format_init(dest, rate, sample_format, channels); return true; } diff --git a/src/decoder/_flac_common.c b/src/decoder/_flac_common.c index f12b8bff0..70b2c0202 100644 --- a/src/decoder/_flac_common.c +++ b/src/decoder/_flac_common.c @@ -60,6 +60,27 @@ flac_data_deinit(struct flac_data *data) tag_free(data->tag); } +static enum sample_format +flac_sample_format(const FLAC__StreamMetadata_StreamInfo *si) +{ + switch (si->bits_per_sample) { + case 8: + return SAMPLE_FORMAT_S8; + + case 16: + return SAMPLE_FORMAT_S16; + + case 24: + return SAMPLE_FORMAT_S24_P32; + + case 32: + return SAMPLE_FORMAT_S32; + + default: + return SAMPLE_FORMAT_UNDEFINED; + } +} + bool flac_data_get_audio_format(struct flac_data *data, struct audio_format *audio_format) @@ -71,9 +92,11 @@ flac_data_get_audio_format(struct flac_data *data, return false; } + data->sample_format = flac_sample_format(&data->stream_info); + if (!audio_format_init_checked(audio_format, data->stream_info.sample_rate, - data->stream_info.bits_per_sample, + data->sample_format, data->stream_info.channels, &error)) { g_warning("%s", error->message); g_error_free(error); @@ -144,7 +167,7 @@ flac_common_write(struct flac_data *data, const FLAC__Frame * frame, buffer = pcm_buffer_get(&data->buffer, buffer_size); flac_convert(buffer, frame->header.channels, - frame->header.bits_per_sample, buf, + data->sample_format, buf, 0, frame->header.blocksize); if (data->next_frame >= data->first_frame) diff --git a/src/decoder/_flac_common.h b/src/decoder/_flac_common.h index 1d211fcfb..2f328afa6 100644 --- a/src/decoder/_flac_common.h +++ b/src/decoder/_flac_common.h @@ -38,6 +38,8 @@ struct flac_data { struct pcm_buffer buffer; + enum sample_format sample_format; + /** * The size of one frame in the output buffer. */ diff --git a/src/decoder/audiofile_plugin.c b/src/decoder/audiofile_plugin.c index 5a2096d00..fcb431db7 100644 --- a/src/decoder/audiofile_plugin.c +++ b/src/decoder/audiofile_plugin.c @@ -101,13 +101,33 @@ setup_virtual_fops(struct input_stream *stream) return vf; } -static uint8_t +static enum sample_format +audiofile_bits_to_sample_format(int bits) +{ + switch (bits) { + case 8: + return SAMPLE_FORMAT_S8; + + case 16: + return SAMPLE_FORMAT_S16; + + case 24: + return SAMPLE_FORMAT_S24_P32; + + case 32: + return SAMPLE_FORMAT_S32; + } + + return SAMPLE_FORMAT_UNDEFINED; +} + +static enum sample_format audiofile_setup_sample_format(AFfilehandle af_fp) { int fs, bits; afGetSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits); - if (!audio_valid_sample_format(bits)) { + if (!audio_valid_sample_format(audiofile_bits_to_sample_format(bits))) { g_debug("input file has %d bit samples, converting to 16", bits); bits = 16; @@ -117,7 +137,7 @@ audiofile_setup_sample_format(AFfilehandle af_fp) AF_SAMPFMT_TWOSCOMP, bits); afGetVirtualSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits); - return bits; + return audiofile_bits_to_sample_format(bits); } static void diff --git a/src/decoder/faad_plugin.c b/src/decoder/faad_plugin.c index 55df15555..2a05e33e8 100644 --- a/src/decoder/faad_plugin.c +++ b/src/decoder/faad_plugin.c @@ -283,7 +283,7 @@ faad_decoder_init(faacDecHandle decoder, struct decoder_buffer *buffer, decoder_buffer_consume(buffer, nbytes); return audio_format_init_checked(audio_format, sample_rate, - 16, channels, error_r); + SAMPLE_FORMAT_S16, channels, error_r); } /** diff --git a/src/decoder/ffmpeg_plugin.c b/src/decoder/ffmpeg_plugin.c index 9b025153b..af9320322 100644 --- a/src/decoder/ffmpeg_plugin.c +++ b/src/decoder/ffmpeg_plugin.c @@ -277,6 +277,26 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is, return cmd; } +static enum sample_format +ffmpeg_sample_format(G_GNUC_UNUSED const AVCodecContext *codec_context) +{ +#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(41<<8)+0) + int bits = (uint8_t) av_get_bits_per_sample_format(codec_context->sample_fmt); + + /* XXX implement & test other sample formats */ + + switch (bits) { + case 16: + return SAMPLE_FORMAT_S16; + } + + return SAMPLE_FORMAT_UNDEFINED; +#else + /* XXX fixme 16-bit for older ffmpeg (13 Aug 2007) */ + return SAMPLE_FORMAT_S16; +#endif +} + static bool ffmpeg_decode_internal(struct ffmpeg_context *ctx) { @@ -288,7 +308,6 @@ ffmpeg_decode_internal(struct ffmpeg_context *ctx) struct audio_format audio_format; enum decoder_command cmd; int total_time; - uint8_t bits; total_time = 0; @@ -296,14 +315,9 @@ ffmpeg_decode_internal(struct ffmpeg_context *ctx) codec_context->channels = 2; } -#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(41<<8)+0) - bits = (uint8_t) av_get_bits_per_sample_format(codec_context->sample_fmt); -#else - /* XXX fixme 16-bit for older ffmpeg (13 Aug 2007) */ - bits = (uint8_t) 16; -#endif if (!audio_format_init_checked(&audio_format, - codec_context->sample_rate, bits, + codec_context->sample_rate, + ffmpeg_sample_format(codec_context), codec_context->channels, &error)) { g_warning("%s", error->message); g_error_free(error); diff --git a/src/decoder/flac_pcm.c b/src/decoder/flac_pcm.c index 737d5b043..a8bf6f293 100644 --- a/src/decoder/flac_pcm.c +++ b/src/decoder/flac_pcm.c @@ -20,6 +20,8 @@ #include "config.h" #include "flac_pcm.h" +#include + static void flac_convert_stereo16(int16_t *dest, const FLAC__int32 * const buf[], unsigned int position, unsigned int end) @@ -74,12 +76,12 @@ flac_convert_8(int8_t *dest, void flac_convert(void *dest, - unsigned int num_channels, unsigned sample_format, + unsigned int num_channels, enum sample_format sample_format, const FLAC__int32 *const buf[], unsigned int position, unsigned int end) { switch (sample_format) { - case 16: + case SAMPLE_FORMAT_S16: if (num_channels == 2) flac_convert_stereo16((int16_t*)dest, buf, position, end); @@ -88,15 +90,19 @@ flac_convert(void *dest, position, end); break; - case 24: - case 32: + case SAMPLE_FORMAT_S24_P32: + case SAMPLE_FORMAT_S32: flac_convert_32((int32_t*)dest, num_channels, buf, position, end); break; - case 8: + case SAMPLE_FORMAT_S8: flac_convert_8((int8_t*)dest, num_channels, buf, position, end); break; + + case SAMPLE_FORMAT_UNDEFINED: + /* unreachable */ + assert(false); } } diff --git a/src/decoder/flac_pcm.h b/src/decoder/flac_pcm.h index dca9d6824..4d7a51c4d 100644 --- a/src/decoder/flac_pcm.h +++ b/src/decoder/flac_pcm.h @@ -20,11 +20,13 @@ #ifndef MPD_FLAC_PCM_H #define MPD_FLAC_PCM_H +#include "audio_format.h" + #include void flac_convert(void *dest, - unsigned int num_channels, unsigned sample_format, + unsigned int num_channels, enum sample_format sample_format, const FLAC__int32 *const buf[], unsigned int position, unsigned int end); diff --git a/src/decoder/fluidsynth_plugin.c b/src/decoder/fluidsynth_plugin.c index 3e8a4edc4..1b1e6a531 100644 --- a/src/decoder/fluidsynth_plugin.c +++ b/src/decoder/fluidsynth_plugin.c @@ -88,7 +88,7 @@ fluidsynth_file_decode(struct decoder *decoder, const char *path_fs) { static const struct audio_format audio_format = { .sample_rate = 48000, - .bits = 16, + .format = SAMPLE_FORMAT_S16, .channels = 2, }; char setting_sample_rate[] = "synth.sample-rate"; diff --git a/src/decoder/mad_plugin.c b/src/decoder/mad_plugin.c index da93fe45b..cba40aea0 100644 --- a/src/decoder/mad_plugin.c +++ b/src/decoder/mad_plugin.c @@ -1188,7 +1188,8 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream) } if (!audio_format_init_checked(&audio_format, - data.frame.header.samplerate, 24, + data.frame.header.samplerate, + SAMPLE_FORMAT_S24_P32, MAD_NCHANNELS(&data.frame.header), &error)) { g_warning("%s", error->message); diff --git a/src/decoder/mikmod_plugin.c b/src/decoder/mikmod_plugin.c index 204dd5ce0..1e64aeffd 100644 --- a/src/decoder/mikmod_plugin.c +++ b/src/decoder/mikmod_plugin.c @@ -163,7 +163,7 @@ mikmod_decoder_file_decode(struct decoder *decoder, const char *path_fs) /* Prevent module from looping forever */ handle->loop = 0; - audio_format_init(&audio_format, mikmod_sample_rate, 16, 2); + audio_format_init(&audio_format, mikmod_sample_rate, SAMPLE_FORMAT_S16, 2); assert(audio_format_valid(&audio_format)); decoder_initialized(decoder, &audio_format, false, 0); diff --git a/src/decoder/modplug_plugin.c b/src/decoder/modplug_plugin.c index 6c08c2199..02292992d 100644 --- a/src/decoder/modplug_plugin.c +++ b/src/decoder/modplug_plugin.c @@ -122,7 +122,7 @@ mod_decode(struct decoder *decoder, struct input_stream *is) return; } - audio_format_init(&audio_format, 44100, 16, 2); + audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2); assert(audio_format_valid(&audio_format)); decoder_initialized(decoder, &audio_format, diff --git a/src/decoder/mp4ff_plugin.c b/src/decoder/mp4ff_plugin.c index 70ca4bdc3..8d3a4b9e9 100644 --- a/src/decoder/mp4ff_plugin.c +++ b/src/decoder/mp4ff_plugin.c @@ -132,7 +132,8 @@ mp4_faad_new(mp4ff_t *mp4fh, int *track_r, struct audio_format *audio_format) return NULL; } - if (!audio_format_init_checked(audio_format, sample_rate, 16, channels, + if (!audio_format_init_checked(audio_format, sample_rate, + SAMPLE_FORMAT_S16, channels, &error)) { g_warning("%s", error->message); g_error_free(error); diff --git a/src/decoder/mpcdec_plugin.c b/src/decoder/mpcdec_plugin.c index d985f8459..2f1936e55 100644 --- a/src/decoder/mpcdec_plugin.c +++ b/src/decoder/mpcdec_plugin.c @@ -196,7 +196,8 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is) mpc_demux_get_info(demux, &info); #endif - if (!audio_format_init_checked(&audio_format, info.sample_freq, 24, + if (!audio_format_init_checked(&audio_format, info.sample_freq, + SAMPLE_FORMAT_S24_P32, info.channels, &error)) { g_warning("%s", error->message); g_error_free(error); diff --git a/src/decoder/mpg123_decoder_plugin.c b/src/decoder/mpg123_decoder_plugin.c index 922e56484..62e6b00b0 100644 --- a/src/decoder/mpg123_decoder_plugin.c +++ b/src/decoder/mpg123_decoder_plugin.c @@ -87,7 +87,7 @@ mpd_mpg123_open(mpg123_handle *handle, const char *path_fs, return false; } - if (!audio_format_init_checked(audio_format, rate, 16, + if (!audio_format_init_checked(audio_format, rate, SAMPLE_FORMAT_S16, channels, &gerror)) { g_warning("%s", gerror->message); g_error_free(gerror); diff --git a/src/decoder/sidplay_plugin.cxx b/src/decoder/sidplay_plugin.cxx index b6e557e08..63e46a285 100644 --- a/src/decoder/sidplay_plugin.cxx +++ b/src/decoder/sidplay_plugin.cxx @@ -277,7 +277,7 @@ sidplay_file_decode(struct decoder *decoder, const char *path_fs) /* initialize the MPD decoder */ struct audio_format audio_format; - audio_format_init(&audio_format, 48000, 16, 2); + audio_format_init(&audio_format, 48000, SAMPLE_FORMAT_S16, 2); assert(audio_format_valid(&audio_format)); decoder_initialized(decoder, &audio_format, true, (float)song_len); diff --git a/src/decoder/sndfile_decoder_plugin.c b/src/decoder/sndfile_decoder_plugin.c index 84835c449..fee0f8292 100644 --- a/src/decoder/sndfile_decoder_plugin.c +++ b/src/decoder/sndfile_decoder_plugin.c @@ -130,7 +130,8 @@ sndfile_stream_decode(struct decoder *decoder, struct input_stream *is) /* for now, always read 32 bit samples. Later, we could lower MPD's CPU usage by reading 16 bit samples with sf_readf_short() on low-quality source files. */ - if (!audio_format_init_checked(&audio_format, info.samplerate, 32, + if (!audio_format_init_checked(&audio_format, info.samplerate, + SAMPLE_FORMAT_S32, info.channels, &error)) { g_warning("%s", error->message); g_error_free(error); diff --git a/src/decoder/vorbis_plugin.c b/src/decoder/vorbis_plugin.c index 3a41869a0..cb61e5999 100755 --- a/src/decoder/vorbis_plugin.c +++ b/src/decoder/vorbis_plugin.c @@ -311,7 +311,8 @@ vorbis_stream_decode(struct decoder *decoder, return; } - if (!audio_format_init_checked(&audio_format, vi->rate, 16, + if (!audio_format_init_checked(&audio_format, vi->rate, + SAMPLE_FORMAT_S16, vi->channels, &error)) { g_warning("%s", error->message); g_error_free(error); diff --git a/src/decoder/wavpack_plugin.c b/src/decoder/wavpack_plugin.c index 9b32a79f2..dffa078f9 100644 --- a/src/decoder/wavpack_plugin.c +++ b/src/decoder/wavpack_plugin.c @@ -123,6 +123,33 @@ format_samples_float(G_GNUC_UNUSED int bytes_per_sample, void *buffer, } } +/** + * Choose a MPD sample format from libwavpacks' number of bits. + */ +static enum sample_format +wavpack_bits_to_sample_format(bool is_float, int bytes_per_sample) +{ + if (is_float) + return SAMPLE_FORMAT_S24_P32; + + switch (bytes_per_sample) { + case 1: + return SAMPLE_FORMAT_S8; + + case 2: + return SAMPLE_FORMAT_S16; + + case 3: + return SAMPLE_FORMAT_S24_P32; + + case 4: + return SAMPLE_FORMAT_S32; + + default: + return SAMPLE_FORMAT_UNDEFINED; + } +} + /* * This does the main decoding thing. * Requires an already opened WavpackContext. @@ -132,7 +159,8 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, struct replay_gain_info *replay_gain_info) { GError *error = NULL; - unsigned bits; + bool is_float; + enum sample_format sample_format; struct audio_format audio_format; format_samples_t format_samples; char chunk[CHUNK_SIZE]; @@ -141,19 +169,14 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, int bytes_per_sample, output_sample_size; int position; - bits = WavpackGetBitsPerSample(wpc); - - /* round bitwidth to 8-bit units */ - bits = (bits + 7) & (~7); - /* MPD handles max 32-bit samples */ - if (bits > 32) - bits = 32; - - if ((WavpackGetMode(wpc) & MODE_FLOAT) == MODE_FLOAT) - bits = 24; + is_float = (WavpackGetMode(wpc) & MODE_FLOAT) != 0; + sample_format = + wavpack_bits_to_sample_format(is_float, + WavpackGetBytesPerSample(wpc)); if (!audio_format_init_checked(&audio_format, - WavpackGetSampleRate(wpc), bits, + WavpackGetSampleRate(wpc), + sample_format, WavpackGetNumChannels(wpc), &error)) { g_warning("%s", error->message); g_error_free(error); diff --git a/src/decoder/wildmidi_plugin.c b/src/decoder/wildmidi_plugin.c index 718f24c2e..70b4d5ef9 100644 --- a/src/decoder/wildmidi_plugin.c +++ b/src/decoder/wildmidi_plugin.c @@ -59,7 +59,7 @@ wildmidi_file_decode(struct decoder *decoder, const char *path_fs) { static const struct audio_format audio_format = { .sample_rate = WILDMIDI_SAMPLE_RATE, - .bits = 16, + .format = SAMPLE_FORMAT_S16, .channels = 2, }; midi *wm; diff --git a/src/encoder/flac_encoder.c b/src/encoder/flac_encoder.c index ab7dc0c39..4f80fe568 100644 --- a/src/encoder/flac_encoder.c +++ b/src/encoder/flac_encoder.c @@ -89,7 +89,8 @@ flac_encoder_finish(struct encoder *_encoder) } static bool -flac_encoder_setup(struct flac_encoder *encoder, GError **error) +flac_encoder_setup(struct flac_encoder *encoder, unsigned bits_per_sample, + GError **error) { if ( !FLAC__stream_encoder_set_compression_level(encoder->fse, encoder->compression)) { @@ -106,10 +107,10 @@ flac_encoder_setup(struct flac_encoder *encoder, GError **error) return false; } if ( !FLAC__stream_encoder_set_bits_per_sample(encoder->fse, - encoder->audio_format.bits)) { + bits_per_sample)) { g_set_error(error, flac_encoder_quark(), 0, "error setting flac bit format to %d", - encoder->audio_format.bits); + bits_per_sample); return false; } if ( !FLAC__stream_encoder_set_sample_rate(encoder->fse, @@ -143,13 +144,29 @@ flac_encoder_open(struct encoder *_encoder, struct audio_format *audio_format, GError **error) { struct flac_encoder *encoder = (struct flac_encoder *)_encoder; + unsigned bits_per_sample; FLAC__StreamEncoderInitStatus init_status; encoder->audio_format = *audio_format; /* FIXME: flac should support 32bit as well */ - if (audio_format->bits > 24) - audio_format->bits = 24; + switch (audio_format->format) { + case SAMPLE_FORMAT_S8: + bits_per_sample = 8; + break; + + case SAMPLE_FORMAT_S16: + bits_per_sample = 16; + break; + + case SAMPLE_FORMAT_S24_P32: + bits_per_sample = 24; + break; + + default: + bits_per_sample = 24; + audio_format->format = SAMPLE_FORMAT_S24_P32; + } /* allocate the encoder */ encoder->fse = FLAC__stream_encoder_new(); @@ -159,7 +176,7 @@ flac_encoder_open(struct encoder *_encoder, struct audio_format *audio_format, return false; } - if (!flac_encoder_setup(encoder, error)) { + if (!flac_encoder_setup(encoder, bits_per_sample, error)) { FLAC__stream_encoder_delete(encoder->fse); return false; } @@ -237,20 +254,23 @@ flac_encoder_write(struct encoder *_encoder, num_frames = length / audio_format_frame_size(&encoder->audio_format); num_samples = num_frames * encoder->audio_format.channels; - switch (encoder->audio_format.bits) { - case 8: + switch (encoder->audio_format.format) { + case SAMPLE_FORMAT_S8: exbuffer = pcm_buffer_get(&encoder->expand_buffer, length*4); pcm8_to_flac(exbuffer, data, num_samples); buffer = exbuffer; break; - case 16: + + case SAMPLE_FORMAT_S16: exbuffer = pcm_buffer_get(&encoder->expand_buffer, length*2); pcm16_to_flac(exbuffer, data, num_samples); buffer = exbuffer; break; - case 24: - case 32: /* nothing need to be done - * format is the same for both mpd and libFLAC */ + + case SAMPLE_FORMAT_S24_P32: + case SAMPLE_FORMAT_S32: + /* nothing need to be done; format is the same for + both mpd and libFLAC */ buffer = data; break; } diff --git a/src/encoder/lame_encoder.c b/src/encoder/lame_encoder.c index 812ff39c5..97431a817 100644 --- a/src/encoder/lame_encoder.c +++ b/src/encoder/lame_encoder.c @@ -185,7 +185,7 @@ lame_encoder_open(struct encoder *_encoder, struct audio_format *audio_format, { struct lame_encoder *encoder = (struct lame_encoder *)_encoder; - audio_format->bits = 16; + audio_format->format = SAMPLE_FORMAT_S16; audio_format->channels = 2; encoder->audio_format = *audio_format; diff --git a/src/encoder/twolame_encoder.c b/src/encoder/twolame_encoder.c index cddf5773e..e7af89bf6 100644 --- a/src/encoder/twolame_encoder.c +++ b/src/encoder/twolame_encoder.c @@ -192,7 +192,7 @@ twolame_encoder_open(struct encoder *_encoder, struct audio_format *audio_format { struct twolame_encoder *encoder = (struct twolame_encoder *)_encoder; - audio_format->bits = 16; + audio_format->format = SAMPLE_FORMAT_S16; audio_format->channels = 2; encoder->audio_format = *audio_format; diff --git a/src/encoder/vorbis_encoder.c b/src/encoder/vorbis_encoder.c index 2fa0fd950..d072bcd3f 100644 --- a/src/encoder/vorbis_encoder.c +++ b/src/encoder/vorbis_encoder.c @@ -212,7 +212,7 @@ vorbis_encoder_open(struct encoder *_encoder, struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; bool ret; - audio_format->bits = 16; + audio_format->format = SAMPLE_FORMAT_S16; encoder->audio_format = *audio_format; diff --git a/src/encoder/wave_encoder.c b/src/encoder/wave_encoder.c index e66cc1917..f34ae0241 100644 --- a/src/encoder/wave_encoder.c +++ b/src/encoder/wave_encoder.c @@ -114,16 +114,39 @@ wave_encoder_open(struct encoder *_encoder, struct wave_encoder *encoder = (struct wave_encoder *)_encoder; void *buffer; - encoder->bits = audio_format->bits; + assert(audio_format_valid(audio_format)); + + switch (audio_format->format) { + case SAMPLE_FORMAT_S8: + encoder->bits = 8; + break; + + case SAMPLE_FORMAT_S16: + encoder->bits = 16; + break; + + case SAMPLE_FORMAT_S24_P32: + encoder->bits = 24; + break; + + case SAMPLE_FORMAT_S32: + encoder->bits = 32; + break; + + default: + audio_format->format = SAMPLE_FORMAT_S16; + encoder->bits = 16; + break; + } buffer = pcm_buffer_get(&encoder->buffer, sizeof(struct wave_header) ); /* create PCM wave header in initial buffer */ fill_wave_header((struct wave_header *) buffer, audio_format->channels, - audio_format->bits, + encoder->bits, audio_format->sample_rate, - (audio_format->bits / 8) * audio_format->channels ); + (encoder->bits / 8) * audio_format->channels ); encoder->buffer_length = sizeof(struct wave_header); return true; diff --git a/src/filter/volume_filter_plugin.c b/src/filter/volume_filter_plugin.c index f6639a75f..285a4b7a4 100644 --- a/src/filter/volume_filter_plugin.c +++ b/src/filter/volume_filter_plugin.c @@ -75,8 +75,9 @@ volume_filter_open(struct filter *_filter, { struct volume_filter *filter = (struct volume_filter *)_filter; - if (audio_format->bits != 8 && audio_format->bits != 16 && - audio_format->bits != 24) { + if (audio_format->format != SAMPLE_FORMAT_S8 && + audio_format->format != SAMPLE_FORMAT_S16 && + audio_format->format != SAMPLE_FORMAT_S24_P32) { g_set_error(error_r, volume_quark(), 0, "Unsupported audio format"); return false; diff --git a/src/normalize.c b/src/normalize.c index f9201df64..1c8173def 100644 --- a/src/normalize.c +++ b/src/normalize.c @@ -47,7 +47,8 @@ void finishNormalization(void) void normalizeData(void *buffer, int bufferSize, const struct audio_format *format) { - if ((format->bits != 16) || (format->channels != 2)) return; + if (format->format != SAMPLE_FORMAT_S16 || format->channels != 2) + return; Compressor_Process_int16(compressor, buffer, bufferSize / 2); } diff --git a/src/output/alsa_plugin.c b/src/output/alsa_plugin.c index 2c642015d..b7325de07 100644 --- a/src/output/alsa_plugin.c +++ b/src/output/alsa_plugin.c @@ -185,13 +185,22 @@ alsa_test_default_device(void) static snd_pcm_format_t get_bitformat(const struct audio_format *af) { - switch (af->bits) { - case 8: return SND_PCM_FORMAT_S8; - case 16: return SND_PCM_FORMAT_S16; - case 24: return SND_PCM_FORMAT_S24; - case 32: return SND_PCM_FORMAT_S32; + switch (af->format) { + case SAMPLE_FORMAT_S8: + return SND_PCM_FORMAT_S8; + + case SAMPLE_FORMAT_S16: + return SND_PCM_FORMAT_S16; + + case SAMPLE_FORMAT_S24_P32: + return SND_PCM_FORMAT_S24; + + case SAMPLE_FORMAT_S32: + return SND_PCM_FORMAT_S32; + + default: + return SND_PCM_FORMAT_UNKNOWN; } - return SND_PCM_FORMAT_UNKNOWN; } static snd_pcm_format_t @@ -264,61 +273,67 @@ configure_hw: err = snd_pcm_hw_params_set_format(ad->pcm, hwparams, byteswap_bitformat(bitformat)); if (err == 0) { - g_debug("ALSA device \"%s\": converting %u bit to reverse-endian\n", - alsa_device(ad), audio_format->bits); + g_debug("ALSA device \"%s\": converting format %s to reverse-endian", + alsa_device(ad), + sample_format_to_string(audio_format->format)); audio_format->reverse_endian = 1; } } - if (err == -EINVAL && (audio_format->bits == 24 || - audio_format->bits == 16)) { + if (err == -EINVAL && (audio_format->format == SAMPLE_FORMAT_S24_P32 || + audio_format->format == SAMPLE_FORMAT_S16)) { /* fall back to 32 bit, let pcm_convert.c do the conversion */ err = snd_pcm_hw_params_set_format(ad->pcm, hwparams, SND_PCM_FORMAT_S32); if (err == 0) { - g_debug("ALSA device \"%s\": converting %u bit to 32 bit\n", - alsa_device(ad), audio_format->bits); - audio_format->bits = 32; + g_debug("ALSA device \"%s\": converting format %s to 32 bit\n", + alsa_device(ad), + sample_format_to_string(audio_format->format)); + audio_format->format = SAMPLE_FORMAT_S32; } } - if (err == -EINVAL && (audio_format->bits == 24 || - audio_format->bits == 16)) { + if (err == -EINVAL && (audio_format->format == SAMPLE_FORMAT_S24_P32 || + audio_format->format == SAMPLE_FORMAT_S16)) { /* fall back to 32 bit, let pcm_convert.c do the conversion */ err = snd_pcm_hw_params_set_format(ad->pcm, hwparams, byteswap_bitformat(SND_PCM_FORMAT_S32)); if (err == 0) { - g_debug("ALSA device \"%s\": converting %u bit to 32 bit backward-endian\n", - alsa_device(ad), audio_format->bits); - audio_format->bits = 32; + g_debug("ALSA device \"%s\": converting format %s to 32 bit backward-endian\n", + alsa_device(ad), + sample_format_to_string(audio_format->format)); + audio_format->format = SAMPLE_FORMAT_S32; audio_format->reverse_endian = 1; } } - if (err == -EINVAL && audio_format->bits != 16) { + if (err == -EINVAL && audio_format->format != SAMPLE_FORMAT_S16) { /* fall back to 16 bit, let pcm_convert.c do the conversion */ err = snd_pcm_hw_params_set_format(ad->pcm, hwparams, SND_PCM_FORMAT_S16); if (err == 0) { - g_debug("ALSA device \"%s\": converting %u bit to 16 bit\n", - alsa_device(ad), audio_format->bits); - audio_format->bits = 16; + g_debug("ALSA device \"%s\": converting format %s to 16 bit\n", + alsa_device(ad), + sample_format_to_string(audio_format->format)); + audio_format->format = SAMPLE_FORMAT_S16; } } - if (err == -EINVAL && audio_format->bits != 16) { + if (err == -EINVAL && audio_format->format != SAMPLE_FORMAT_S16) { /* fall back to 16 bit, let pcm_convert.c do the conversion */ err = snd_pcm_hw_params_set_format(ad->pcm, hwparams, byteswap_bitformat(SND_PCM_FORMAT_S16)); if (err == 0) { - g_debug("ALSA device \"%s\": converting %u bit to 16 bit backward-endian\n", - alsa_device(ad), audio_format->bits); - audio_format->bits = 16; + g_debug("ALSA device \"%s\": converting format %s to 16 bit backward-endian\n", + alsa_device(ad), + sample_format_to_string(audio_format->format)); + audio_format->format = SAMPLE_FORMAT_S16; audio_format->reverse_endian = 1; } } if (err < 0) { g_set_error(error, alsa_output_quark(), err, - "ALSA device \"%s\" does not support %u bit audio: %s", - alsa_device(ad), audio_format->bits, + "ALSA device \"%s\" does not support format %s: %s", + alsa_device(ad), + sample_format_to_string(audio_format->format), snd_strerror(-err)); return false; } @@ -449,7 +464,7 @@ alsa_open(void *data, struct audio_format *audio_format, GError **error) /* sample format is not supported by this plugin - fall back to 16 bit samples */ - audio_format->bits = 16; + audio_format->format = SAMPLE_FORMAT_S16; bitformat = SND_PCM_FORMAT_S16; } diff --git a/src/output/ao_plugin.c b/src/output/ao_plugin.c index d69175272..7afca0db2 100644 --- a/src/output/ao_plugin.c +++ b/src/output/ao_plugin.c @@ -170,13 +170,24 @@ ao_output_open(void *data, struct audio_format *audio_format, ao_sample_format format; struct ao_data *ad = (struct ao_data *)data; - /* support for 24 bit samples in libao is currently dubious, - and until we have sorted that out, resample everything to - 16 bit */ - if (audio_format->bits > 16) - audio_format->bits = 16; + switch (audio_format->format) { + case SAMPLE_FORMAT_S8: + format.bits = 8; + break; + + case SAMPLE_FORMAT_S16: + format.bits = 16; + break; + + default: + /* support for 24 bit samples in libao is currently + dubious, and until we have sorted that out, + convert everything to 16 bit */ + audio_format->format = SAMPLE_FORMAT_S16; + format.bits = 16; + break; + } - format.bits = audio_format->bits; format.rate = audio_format->sample_rate; format.byte_format = AO_FMT_NATIVE; format.channels = audio_format->channels; diff --git a/src/output/jack_output_plugin.c b/src/output/jack_output_plugin.c index 7e5a52993..f50bc37d0 100644 --- a/src/output/jack_output_plugin.c +++ b/src/output/jack_output_plugin.c @@ -157,8 +157,9 @@ set_audioformat(struct jack_data *jd, struct audio_format *audio_format) else if (audio_format->channels > jd->num_source_ports) audio_format->channels = 2; - if (audio_format->bits != 16 && audio_format->bits != 24) - audio_format->bits = 24; + if (audio_format->format != SAMPLE_FORMAT_S16 && + audio_format->format != SAMPLE_FORMAT_S24_P32) + audio_format->format = SAMPLE_FORMAT_S24_P32; } static void @@ -606,13 +607,13 @@ static void mpd_jack_write_samples(struct jack_data *jd, const void *src, unsigned num_samples) { - switch (jd->audio_format.bits) { - case 16: + switch (jd->audio_format.format) { + case SAMPLE_FORMAT_S16: mpd_jack_write_samples_16(jd, (const int16_t*)src, num_samples); break; - case 24: + case SAMPLE_FORMAT_S24_P32: mpd_jack_write_samples_24(jd, (const int32_t*)src, num_samples); break; diff --git a/src/output/mvp_plugin.c b/src/output/mvp_plugin.c index 5a9a9b48b..86f147e5a 100644 --- a/src/output/mvp_plugin.c +++ b/src/output/mvp_plugin.c @@ -172,19 +172,19 @@ mvp_set_pcm_params(struct mvp_data *md, struct audio_format *audio_format, } /* 0,1=24bit(24) , 2,3=16bit */ - switch (audio_format->bits) { - case 16: + switch (audio_format->format) { + case SAMPLE_FORMAT_S16: mix[1] = 2; break; - case 24: + case SAMPLE_FORMAT_S24_P32: mix[1] = 0; break; default: - g_debug("unsupported sample format %u - falling back to stereo", - audio_format->bits); - audio_format->bits = 16; + g_debug("unsupported sample format %s - falling back to 16 bit", + sample_format_to_string(audio_format->format)); + audio_format->format = SAMPLE_FORMAT_S16; mix[1] = 2; break; } diff --git a/src/output/openal_plugin.c b/src/output/openal_plugin.c index 8fda110e1..0aded4d9a 100644 --- a/src/output/openal_plugin.c +++ b/src/output/openal_plugin.c @@ -58,25 +58,29 @@ openal_output_quark(void) static ALenum openal_audio_format(struct audio_format *audio_format) { - /* Only 8 and 16 bit samples are supported */ - if (audio_format->bits != 16 && audio_format->bits != 8) - audio_format->bits = 16; - - switch (audio_format->bits) - { - case 16: + switch (audio_format->format) { + case SAMPLE_FORMAT_S16: if (audio_format->channels == 2) return AL_FORMAT_STEREO16; if (audio_format->channels == 1) return AL_FORMAT_MONO16; break; - case 8: + case SAMPLE_FORMAT_S8: if (audio_format->channels == 2) return AL_FORMAT_STEREO8; if (audio_format->channels == 1) return AL_FORMAT_MONO8; break; + + default: + /* fall back to 16 bit */ + audio_format->format = SAMPLE_FORMAT_S16; + if (audio_format->channels == 2) + return AL_FORMAT_STEREO16; + if (audio_format->channels == 1) + return AL_FORMAT_MONO16; + break; } return 0; diff --git a/src/output/oss_plugin.c b/src/output/oss_plugin.c index b02d7d62e..f16374e39 100644 --- a/src/output/oss_plugin.c +++ b/src/output/oss_plugin.c @@ -490,17 +490,18 @@ oss_setup(struct oss_data *od, GError **error) } od->audio_format.sample_rate = tmp; - switch (od->audio_format.bits) { - case 8: + switch (od->audio_format.format) { + case SAMPLE_FORMAT_S8: tmp = AFMT_S8; break; - case 16: + + case SAMPLE_FORMAT_S16: tmp = AFMT_S16_MPD; break; default: /* not supported by OSS - fall back to 16 bit */ - od->audio_format.bits = 16; + od->audio_format.format = SAMPLE_FORMAT_S16; tmp = AFMT_S16_MPD; break; } diff --git a/src/output/osx_plugin.c b/src/output/osx_plugin.c index afcd143b3..22b742ee5 100644 --- a/src/output/osx_plugin.c +++ b/src/output/osx_plugin.c @@ -166,9 +166,6 @@ osx_output_open(void *data, struct audio_format *audio_format, GError **error) OSStatus status; ComponentResult result; - if (audio_format->bits > 16) - audio_format->bits = 16; - desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_DefaultOutput; desc.componentManufacturer = kAudioUnitManufacturer_Apple; @@ -226,7 +223,21 @@ osx_output_open(void *data, struct audio_format *audio_format, GError **error) stream_description.mFramesPerPacket = 1; stream_description.mBytesPerFrame = stream_description.mBytesPerPacket; stream_description.mChannelsPerFrame = audio_format->channels; - stream_description.mBitsPerChannel = audio_format->bits; + + switch (audio_format->format) { + case SAMPLE_FORMAT_S8: + stream_description.mBitsPerChannel = 8; + break; + + case SAMPLE_FORMAT_S16: + stream_description.mBitsPerChannel = 16; + break; + + default: + audio_format->format = SAMPLE_FORMAT_S16; + stream_description.mBitsPerChannel = 16; + break; + } result = AudioUnitSetProperty(od->au, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, diff --git a/src/output/pulse_output_plugin.c b/src/output/pulse_output_plugin.c index 3da1b3593..a64157920 100644 --- a/src/output/pulse_output_plugin.c +++ b/src/output/pulse_output_plugin.c @@ -467,7 +467,7 @@ pulse_output_open(void *data, struct audio_format *audio_format, /* MPD doesn't support the other pulseaudio sample formats, so we just force MPD to send us everything as 16 bit */ - audio_format->bits = 16; + audio_format->format = SAMPLE_FORMAT_S16; ss.format = PA_SAMPLE_S16NE; ss.rate = audio_format->sample_rate; diff --git a/src/output/solaris_output_plugin.c b/src/output/solaris_output_plugin.c index b187630ee..fe84068f1 100644 --- a/src/output/solaris_output_plugin.c +++ b/src/output/solaris_output_plugin.c @@ -89,7 +89,7 @@ solaris_output_open(void *data, struct audio_format *audio_format, /* support only 16 bit mono/stereo for now; nothing else has been tested */ - audio_format->bits = 16; + audio_format->format = SAMPLE_FORMAT_S16; /* open the device in non-blocking mode */ @@ -119,7 +119,7 @@ solaris_output_open(void *data, struct audio_format *audio_format, info.play.sample_rate = audio_format->sample_rate; info.play.channels = audio_format->channels; - info.play.precision = audio_format->bits; + info.play.precision = 16; info.play.encoding = AUDIO_ENCODING_LINEAR; ret = ioctl(so->fd, AUDIO_SETINFO, &info); diff --git a/src/pcm_convert.c b/src/pcm_convert.c index 1d6299964..8d529dd5f 100644 --- a/src/pcm_convert.c +++ b/src/pcm_convert.c @@ -63,15 +63,15 @@ pcm_convert_16(struct pcm_convert_state *state, const int16_t *buf; size_t len; - assert(dest_format->bits == 16); + assert(dest_format->format == SAMPLE_FORMAT_S16); buf = pcm_convert_to_16(&state->format_buffer, &state->dither, - src_format->bits, src_buffer, src_size, + src_format->format, src_buffer, src_size, &len); if (buf == NULL) { g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %u to 16 bit is not implemented", - src_format->bits); + "Conversion from %s to 16 bit is not implemented", + sample_format_to_string(src_format->format)); return NULL; } @@ -119,14 +119,14 @@ pcm_convert_24(struct pcm_convert_state *state, const int32_t *buf; size_t len; - assert(dest_format->bits == 24); + assert(dest_format->format == SAMPLE_FORMAT_S24_P32); - buf = pcm_convert_to_24(&state->format_buffer, src_format->bits, + buf = pcm_convert_to_24(&state->format_buffer, src_format->format, src_buffer, src_size, &len); if (buf == NULL) { g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %u to 24 bit is not implemented", - src_format->bits); + "Conversion from %s to 24 bit is not implemented", + sample_format_to_string(src_format->format)); return NULL; } @@ -174,14 +174,14 @@ pcm_convert_32(struct pcm_convert_state *state, const int32_t *buf; size_t len; - assert(dest_format->bits == 32); + assert(dest_format->format == SAMPLE_FORMAT_S32); - buf = pcm_convert_to_32(&state->format_buffer, src_format->bits, + buf = pcm_convert_to_32(&state->format_buffer, src_format->format, src_buffer, src_size, &len); if (buf == NULL) { g_set_error(error_r, pcm_convert_quark(), 0, - "Conversion from %u to 24 bit is not implemented", - src_format->bits); + "Conversion from %s to 24 bit is not implemented", + sample_format_to_string(src_format->format)); return NULL; } @@ -227,20 +227,20 @@ pcm_convert(struct pcm_convert_state *state, size_t *dest_size_r, GError **error_r) { - switch (dest_format->bits) { - case 16: + switch (dest_format->format) { + case SAMPLE_FORMAT_S16: return pcm_convert_16(state, src_format, src, src_size, dest_format, dest_size_r, error_r); - case 24: + case SAMPLE_FORMAT_S24_P32: return pcm_convert_24(state, src_format, src, src_size, dest_format, dest_size_r, error_r); - case 32: + case SAMPLE_FORMAT_S32: return pcm_convert_32(state, src_format, src, src_size, dest_format, dest_size_r, @@ -248,8 +248,8 @@ pcm_convert(struct pcm_convert_state *state, default: g_set_error(error_r, pcm_convert_quark(), 0, - "PCM conversion to %u bit is not implemented", - dest_format->bits); + "PCM conversion to %s is not implemented", + sample_format_to_string(dest_format->format)); return NULL; } } diff --git a/src/pcm_format.c b/src/pcm_format.c index 8da253db9..b0dad2ba3 100644 --- a/src/pcm_format.c +++ b/src/pcm_format.c @@ -50,14 +50,17 @@ pcm_convert_32_to_16(struct pcm_dither *dither, const int16_t * pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither, - uint8_t bits, const void *src, + enum sample_format src_format, const void *src, size_t src_size, size_t *dest_size_r) { unsigned num_samples; int16_t *dest; - switch (bits) { - case 8: + switch (src_format) { + case SAMPLE_FORMAT_UNDEFINED: + break; + + case SAMPLE_FORMAT_S8: num_samples = src_size; *dest_size_r = src_size * sizeof(*dest); dest = pcm_buffer_get(buffer, *dest_size_r); @@ -67,11 +70,11 @@ pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither, num_samples); return dest; - case 16: + case SAMPLE_FORMAT_S16: *dest_size_r = src_size; return src; - case 24: + case SAMPLE_FORMAT_S24_P32: num_samples = src_size / 4; *dest_size_r = num_samples * sizeof(*dest); dest = pcm_buffer_get(buffer, *dest_size_r); @@ -81,7 +84,7 @@ pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither, num_samples); return dest; - case 32: + case SAMPLE_FORMAT_S32: num_samples = src_size / 4; *dest_size_r = num_samples * sizeof(*dest); dest = pcm_buffer_get(buffer, *dest_size_r); @@ -127,14 +130,17 @@ pcm_convert_32_to_24(int32_t *out, const int16_t *in, const int32_t * pcm_convert_to_24(struct pcm_buffer *buffer, - uint8_t bits, const void *src, + enum sample_format src_format, const void *src, size_t src_size, size_t *dest_size_r) { unsigned num_samples; int32_t *dest; - switch (bits) { - case 8: + switch (src_format) { + case SAMPLE_FORMAT_UNDEFINED: + break; + + case SAMPLE_FORMAT_S8: num_samples = src_size; *dest_size_r = src_size * sizeof(*dest); dest = pcm_buffer_get(buffer, *dest_size_r); @@ -143,7 +149,7 @@ pcm_convert_to_24(struct pcm_buffer *buffer, num_samples); return dest; - case 16: + case SAMPLE_FORMAT_S16: num_samples = src_size / 2; *dest_size_r = num_samples * sizeof(*dest); dest = pcm_buffer_get(buffer, *dest_size_r); @@ -152,11 +158,11 @@ pcm_convert_to_24(struct pcm_buffer *buffer, num_samples); return dest; - case 24: + case SAMPLE_FORMAT_S24_P32: *dest_size_r = src_size; return src; - case 32: + case SAMPLE_FORMAT_S32: num_samples = src_size / 4; *dest_size_r = num_samples * sizeof(*dest); dest = pcm_buffer_get(buffer, *dest_size_r); @@ -201,14 +207,17 @@ pcm_convert_24_to_32(int32_t *out, const int32_t *in, const int32_t * pcm_convert_to_32(struct pcm_buffer *buffer, - uint8_t bits, const void *src, + enum sample_format src_format, const void *src, size_t src_size, size_t *dest_size_r) { unsigned num_samples; int32_t *dest; - switch (bits) { - case 8: + switch (src_format) { + case SAMPLE_FORMAT_UNDEFINED: + break; + + case SAMPLE_FORMAT_S8: num_samples = src_size; *dest_size_r = src_size * sizeof(*dest); dest = pcm_buffer_get(buffer, *dest_size_r); @@ -217,7 +226,7 @@ pcm_convert_to_32(struct pcm_buffer *buffer, num_samples); return dest; - case 16: + case SAMPLE_FORMAT_S16: num_samples = src_size / 2; *dest_size_r = num_samples * sizeof(*dest); dest = pcm_buffer_get(buffer, *dest_size_r); @@ -226,7 +235,7 @@ pcm_convert_to_32(struct pcm_buffer *buffer, num_samples); return dest; - case 24: + case SAMPLE_FORMAT_S24_P32: num_samples = src_size / 4; *dest_size_r = num_samples * sizeof(*dest); dest = pcm_buffer_get(buffer, *dest_size_r); @@ -235,7 +244,7 @@ pcm_convert_to_32(struct pcm_buffer *buffer, num_samples); return dest; - case 32: + case SAMPLE_FORMAT_S32: *dest_size_r = src_size; return src; } diff --git a/src/pcm_format.h b/src/pcm_format.h index 350566827..6ea5573bd 100644 --- a/src/pcm_format.h +++ b/src/pcm_format.h @@ -20,6 +20,8 @@ #ifndef PCM_FORMAT_H #define PCM_FORMAT_H +#include "audio_format.h" + #include #include @@ -40,7 +42,7 @@ struct pcm_dither; */ const int16_t * pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither, - uint8_t bits, const void *src, + enum sample_format src_format, const void *src, size_t src_size, size_t *dest_size_r); /** @@ -55,7 +57,7 @@ pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither, */ const int32_t * pcm_convert_to_24(struct pcm_buffer *buffer, - uint8_t bits, const void *src, + enum sample_format src_format, const void *src, size_t src_size, size_t *dest_size_r); /** @@ -70,7 +72,7 @@ pcm_convert_to_24(struct pcm_buffer *buffer, */ const int32_t * pcm_convert_to_32(struct pcm_buffer *buffer, - uint8_t bits, const void *src, + enum sample_format src_format, const void *src, size_t src_size, size_t *dest_size_r); #endif diff --git a/src/pcm_mix.c b/src/pcm_mix.c index 6e678a912..0f767a1d9 100644 --- a/src/pcm_mix.c +++ b/src/pcm_mix.c @@ -103,18 +103,18 @@ pcm_add(void *buffer1, const void *buffer2, size_t size, int vol1, int vol2, const struct audio_format *format) { - switch (format->bits) { - case 8: + switch (format->format) { + case SAMPLE_FORMAT_S8: pcm_add_8((int8_t *)buffer1, (const int8_t *)buffer2, size, vol1, vol2); break; - case 16: + case SAMPLE_FORMAT_S16: pcm_add_16((int16_t *)buffer1, (const int16_t *)buffer2, size / 2, vol1, vol2); break; - case 24: + case SAMPLE_FORMAT_S24_P32: pcm_add_24((int32_t*)buffer1, (const int32_t*)buffer2, size / 4, vol1, vol2); @@ -127,7 +127,8 @@ pcm_add(void *buffer1, const void *buffer2, size_t size, break; default: - g_error("%u bits not supported by pcm_add!\n", format->bits); + g_error("format %s not supported by pcm_add", + sample_format_to_string(format->format)); } } diff --git a/src/pcm_volume.c b/src/pcm_volume.c index 90ad17d6d..acb6c41a8 100644 --- a/src/pcm_volume.c +++ b/src/pcm_volume.c @@ -150,17 +150,17 @@ pcm_volume(void *buffer, int length, return true; } - switch (format->bits) { - case 8: + switch (format->format) { + case SAMPLE_FORMAT_S8: pcm_volume_change_8((int8_t *)buffer, length, volume); return true; - case 16: + case SAMPLE_FORMAT_S16: pcm_volume_change_16((int16_t *)buffer, length / 2, volume); return true; - case 24: + case SAMPLE_FORMAT_S24_P32: pcm_volume_change_24((int32_t*)buffer, length / 4, volume); return true; diff --git a/test/run_encoder.c b/test/run_encoder.c index aaafd2e8f..bb73e7b6e 100644 --- a/test/run_encoder.c +++ b/test/run_encoder.c @@ -63,7 +63,7 @@ int main(int argc, char **argv) else encoder_name = "vorbis"; - audio_format_init(&audio_format, 44100, 16, 2); + audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2); /* create the encoder */ diff --git a/test/run_filter.c b/test/run_filter.c index 30495b1fd..62cafdbc1 100644 --- a/test/run_filter.c +++ b/test/run_filter.c @@ -85,7 +85,7 @@ int main(int argc, char **argv) return 1; } - audio_format_init(&audio_format, 44100, 16, 2); + audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2); g_thread_init(NULL); diff --git a/test/run_output.c b/test/run_output.c index 1acc7b377..9ae4e4c4b 100644 --- a/test/run_output.c +++ b/test/run_output.c @@ -119,7 +119,7 @@ int main(int argc, char **argv) return 1; } - audio_format_init(&audio_format, 44100, 16, 2); + audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2); g_thread_init(NULL); diff --git a/test/software_volume.c b/test/software_volume.c index 3b4c5f0fb..11345764d 100644 --- a/test/software_volume.c +++ b/test/software_volume.c @@ -55,7 +55,7 @@ int main(int argc, char **argv) return 1; } } else - audio_format_init(&audio_format, 48000, 16, 2); + audio_format_init(&audio_format, 48000, SAMPLE_FORMAT_S16, 2); while ((nbytes = read(0, buffer, sizeof(buffer))) > 0) { if (!pcm_volume(buffer, nbytes, &audio_format,