diff options
Diffstat (limited to '')
-rw-r--r-- | src/decoder/wavpack_decoder_plugin.c (renamed from src/decoder/wavpack_plugin.c) | 161 |
1 files changed, 85 insertions, 76 deletions
diff --git a/src/decoder/wavpack_plugin.c b/src/decoder/wavpack_decoder_plugin.c index 7ad3a62b0..380985f85 100644 --- a/src/decoder/wavpack_plugin.c +++ b/src/decoder/wavpack_decoder_plugin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2009 The Music Player Daemon Project + * Copyright (C) 2003-2010 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -17,9 +17,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "../decoder_api.h" -#include "../path.h" -#include "../utils.h" +#include "config.h" +#include "decoder_api.h" +#include "audio_check.h" +#include "path.h" +#include "utils.h" #include <wavpack/wavpack.h> #include <glib.h> @@ -41,17 +43,17 @@ static struct { const char *name; enum tag_type type; } tagtypes[] = { - { "artist", TAG_ITEM_ARTIST }, - { "album", TAG_ITEM_ALBUM }, - { "title", TAG_ITEM_TITLE }, - { "track", TAG_ITEM_TRACK }, - { "name", TAG_ITEM_NAME }, - { "genre", TAG_ITEM_GENRE }, - { "date", TAG_ITEM_DATE }, - { "composer", TAG_ITEM_COMPOSER }, - { "performer", TAG_ITEM_PERFORMER }, - { "comment", TAG_ITEM_COMMENT }, - { "disc", TAG_ITEM_DISC }, + { "artist", TAG_ARTIST }, + { "album", TAG_ALBUM }, + { "title", TAG_TITLE }, + { "track", TAG_TRACK }, + { "name", TAG_NAME }, + { "genre", TAG_GENRE }, + { "date", TAG_DATE }, + { "composer", TAG_COMPOSER }, + { "performer", TAG_PERFORMER }, + { "comment", TAG_COMMENT }, + { "disc", TAG_DISC }, }; /** A pointer type for format converter function. */ @@ -97,19 +99,11 @@ format_samples_int(int bytes_per_sample, void *buffer, uint32_t count) } break; } + case 3: + case 4: /* do nothing */ break; - case 4: { - uint32_t *dst = buffer; - assert_static(sizeof(*dst) <= sizeof(*src)); - - /* downsample to 24-bit */ - while (count--) { - *dst++ = *src++ >> 8; - } - break; - } } } @@ -129,38 +123,61 @@ 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. */ static void -wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, - struct replay_gain_info *replay_gain_info) +wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek) { + GError *error = NULL; + bool is_float; + enum sample_format sample_format; struct audio_format audio_format; format_samples_t format_samples; char chunk[CHUNK_SIZE]; int samples_requested, samples_got; - float total_time, current_time; + float total_time; int bytes_per_sample, output_sample_size; - int position; - - audio_format.sample_rate = WavpackGetSampleRate(wpc); - audio_format.channels = WavpackGetReducedChannels(wpc); - audio_format.bits = WavpackGetBitsPerSample(wpc); - - /* round bitwidth to 8-bit units */ - audio_format.bits = (audio_format.bits + 7) & (~7); - /* mpd handles max 24-bit samples */ - if (audio_format.bits > 24) { - audio_format.bits = 24; - } - if (!audio_format_valid(&audio_format)) { - g_warning("Invalid audio format: %u:%u:%u\n", - audio_format.sample_rate, - audio_format.bits, - audio_format.channels); + 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), + sample_format, + WavpackGetNumChannels(wpc), &error)) { + g_warning("%s", error->message); + g_error_free(error); return; } @@ -180,8 +197,6 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, decoder_initialized(decoder, &audio_format, can_seek, total_time); - position = 0; - do { if (decoder_get_command(decoder) == DECODE_COMMAND_SEEK) { if (can_seek) { @@ -189,7 +204,6 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, audio_format.sample_rate; if (WavpackSeekSample(wpc, where)) { - position = where; decoder_command_finished(decoder); } else { decoder_seek_error(decoder); @@ -209,9 +223,6 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, if (samples_got > 0) { int bitrate = (int)(WavpackGetInstantBitrate(wpc) / 1000 + 0.5); - position += samples_got; - current_time = position; - current_time /= audio_format.sample_rate; format_samples( bytes_per_sample, chunk, @@ -221,8 +232,7 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, decoder_data( decoder, NULL, chunk, samples_got * output_sample_size, - current_time, bitrate, - replay_gain_info + bitrate ); } } while (samples_got > 0); @@ -397,13 +407,13 @@ wavpack_input_get_pos(void *id) static int wavpack_input_set_pos_abs(void *id, uint32_t pos) { - return input_stream_seek(wpin(id)->is, pos, SEEK_SET) ? 0 : -1; + return input_stream_seek(wpin(id)->is, pos, SEEK_SET, NULL) ? 0 : -1; } static int wavpack_input_set_pos_rel(void *id, int32_t delta, int mode) { - return input_stream_seek(wpin(id)->is, delta, mode) ? 0 : -1; + return input_stream_seek(wpin(id)->is, delta, mode, NULL) ? 0 : -1; } static int @@ -452,13 +462,12 @@ wavpack_input_init(struct wavpack_input *isp, struct decoder *decoder, isp->last_byte = EOF; } -static bool -wavpack_open_wvc(struct decoder *decoder, struct input_stream *is_wvc, - struct wavpack_input *wpi) +static struct input_stream * +wavpack_open_wvc(struct decoder *decoder, struct wavpack_input *wpi) { + struct input_stream *is_wvc; char *utf8url; char *wvc_url = NULL; - bool ret; char first_byte; size_t nbytes; @@ -474,12 +483,11 @@ wavpack_open_wvc(struct decoder *decoder, struct input_stream *is_wvc, wvc_url = g_strconcat(utf8url, "c", NULL); g_free(utf8url); - ret = input_stream_open(is_wvc, wvc_url); + is_wvc = input_stream_open(wvc_url, NULL); g_free(wvc_url); - if (!ret) { - return false; - } + if (is_wvc == NULL) + return NULL; /* * And we try to buffer in order to get know @@ -490,13 +498,13 @@ wavpack_open_wvc(struct decoder *decoder, struct input_stream *is_wvc, ); if (nbytes == 0) { input_stream_close(is_wvc); - return false; + return NULL; } /* push it back */ wavpack_input_init(wpi, decoder, is_wvc); wpi->last_byte = first_byte; - return true; + return is_wvc; } /* @@ -507,14 +515,15 @@ wavpack_streamdecode(struct decoder * decoder, struct input_stream *is) { char error[ERRORLEN]; WavpackContext *wpc; - struct input_stream is_wvc; - int open_flags = OPEN_2CH_MAX | OPEN_NORMALIZE; + struct input_stream *is_wvc; + int open_flags = OPEN_NORMALIZE; struct wavpack_input isp, isp_wvc; bool can_seek = is->seekable; - if (wavpack_open_wvc(decoder, &is_wvc, &isp_wvc)) { + is_wvc = wavpack_open_wvc(decoder, &isp_wvc); + if (is_wvc != NULL) { open_flags |= OPEN_WVC; - can_seek &= is_wvc.seekable; + can_seek &= is_wvc->seekable; } if (!can_seek) { @@ -533,11 +542,11 @@ wavpack_streamdecode(struct decoder * decoder, struct input_stream *is) return; } - wavpack_decode(decoder, wpc, can_seek, NULL); + wavpack_decode(decoder, wpc, can_seek); WavpackCloseFile(wpc); if (open_flags & OPEN_WVC) { - input_stream_close(&is_wvc); + input_stream_close(is_wvc); } } @@ -553,7 +562,7 @@ wavpack_filedecode(struct decoder *decoder, const char *fname) wpc = WavpackOpenFileInput( fname, error, - OPEN_TAGS | OPEN_WVC | OPEN_2CH_MAX | OPEN_NORMALIZE, 23 + OPEN_TAGS | OPEN_WVC | OPEN_NORMALIZE, 23 ); if (wpc == NULL) { g_warning( @@ -564,13 +573,13 @@ wavpack_filedecode(struct decoder *decoder, const char *fname) } replay_gain_info = wavpack_replaygain(wpc); - - wavpack_decode(decoder, wpc, true, replay_gain_info); - - if (replay_gain_info) { + if (replay_gain_info != NULL) { + decoder_replay_gain(decoder, replay_gain_info); replay_gain_info_free(replay_gain_info); } + wavpack_decode(decoder, wpc, true); + WavpackCloseFile(wpc); } |