From c412d6251e9cd3abe735b7622af4003502e54f72 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 10 Nov 2009 17:11:34 +0100 Subject: audio_format: changed "bits" to "enum sample_format" This patch prepares support for floating point samples (and probably other formats). It changes the meaning of the "bits" attribute from a bit count to a symbolic value. --- src/decoder/_flac_common.c | 27 +++++++++++++++++++-- src/decoder/_flac_common.h | 2 ++ src/decoder/audiofile_plugin.c | 26 +++++++++++++++++--- src/decoder/faad_plugin.c | 2 +- src/decoder/ffmpeg_plugin.c | 30 +++++++++++++++++------ src/decoder/flac_pcm.c | 16 ++++++++---- src/decoder/flac_pcm.h | 4 ++- src/decoder/fluidsynth_plugin.c | 2 +- src/decoder/mad_plugin.c | 3 ++- src/decoder/mikmod_plugin.c | 2 +- src/decoder/modplug_plugin.c | 2 +- src/decoder/mp4ff_plugin.c | 3 ++- src/decoder/mpcdec_plugin.c | 3 ++- src/decoder/mpg123_decoder_plugin.c | 2 +- src/decoder/sidplay_plugin.cxx | 2 +- src/decoder/sndfile_decoder_plugin.c | 3 ++- src/decoder/vorbis_plugin.c | 3 ++- src/decoder/wavpack_plugin.c | 47 +++++++++++++++++++++++++++--------- src/decoder/wildmidi_plugin.c | 2 +- 19 files changed, 138 insertions(+), 43 deletions(-) (limited to 'src/decoder') 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; -- cgit v1.2.3