2
* Copyright (C) 2003-2010 The Music Player Daemon Project
3
* http://www.musicpd.org
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License along
16
* with this program; if not, write to the Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
#include "decoder_api.h"
22
#include "audio_check.h"
26
#include <wavpack/wavpack.h>
35
#define G_LOG_DOMAIN "wavpack"
37
/* pick 1020 since its devisible for 8,16,24, and 32-bit audio */
38
#define CHUNK_SIZE 1020
46
{ "artist", TAG_ARTIST },
47
{ "album", TAG_ALBUM },
48
{ "title", TAG_TITLE },
49
{ "track", TAG_TRACK },
51
{ "genre", TAG_GENRE },
53
{ "composer", TAG_COMPOSER },
54
{ "performer", TAG_PERFORMER },
55
{ "comment", TAG_COMMENT },
59
/** A pointer type for format converter function. */
60
typedef void (*format_samples_t)(
62
void *buffer, uint32_t count
66
* This function has been borrowed from the tiny player found on
67
* wavpack.com. Modifications were required because mpd only handles
71
format_samples_int(int bytes_per_sample, void *buffer, uint32_t count)
73
int32_t *src = buffer;
75
switch (bytes_per_sample) {
79
* The asserts like the following one are because we do the
80
* formatting of samples within a single buffer. The size
81
* of the output samples never can be greater than the size
82
* of the input ones. Otherwise we would have an overflow.
84
assert_static(sizeof(*dst) <= sizeof(*src));
86
/* pass through and align 8-bit samples */
93
uint16_t *dst = buffer;
94
assert_static(sizeof(*dst) <= sizeof(*src));
96
/* pass through and align 16-bit samples */
111
* This function converts floating point sample data to 24-bit integer.
114
format_samples_float(G_GNUC_UNUSED int bytes_per_sample, void *buffer,
117
int32_t *dst = buffer;
119
assert_static(sizeof(*dst) <= sizeof(*src));
122
*dst++ = (int32_t)(*src++ + 0.5f);
127
* Choose a MPD sample format from libwavpacks' number of bits.
129
static enum sample_format
130
wavpack_bits_to_sample_format(bool is_float, int bytes_per_sample)
133
return SAMPLE_FORMAT_S24_P32;
135
switch (bytes_per_sample) {
137
return SAMPLE_FORMAT_S8;
140
return SAMPLE_FORMAT_S16;
143
return SAMPLE_FORMAT_S24_P32;
146
return SAMPLE_FORMAT_S32;
149
return SAMPLE_FORMAT_UNDEFINED;
154
* This does the main decoding thing.
155
* Requires an already opened WavpackContext.
158
wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek)
160
GError *error = NULL;
162
enum sample_format sample_format;
163
struct audio_format audio_format;
164
format_samples_t format_samples;
165
char chunk[CHUNK_SIZE];
166
int samples_requested, samples_got;
168
int bytes_per_sample, output_sample_size;
170
is_float = (WavpackGetMode(wpc) & MODE_FLOAT) != 0;
172
wavpack_bits_to_sample_format(is_float,
173
WavpackGetBytesPerSample(wpc));
175
if (!audio_format_init_checked(&audio_format,
176
WavpackGetSampleRate(wpc),
178
WavpackGetNumChannels(wpc), &error)) {
179
g_warning("%s", error->message);
184
if ((WavpackGetMode(wpc) & MODE_FLOAT) == MODE_FLOAT) {
185
format_samples = format_samples_float;
187
format_samples = format_samples_int;
190
total_time = WavpackGetNumSamples(wpc);
191
total_time /= audio_format.sample_rate;
192
bytes_per_sample = WavpackGetBytesPerSample(wpc);
193
output_sample_size = audio_format_frame_size(&audio_format);
195
/* wavpack gives us all kind of samples in a 32-bit space */
196
samples_requested = sizeof(chunk) / (4 * audio_format.channels);
198
decoder_initialized(decoder, &audio_format, can_seek, total_time);
201
if (decoder_get_command(decoder) == DECODE_COMMAND_SEEK) {
203
unsigned where = decoder_seek_where(decoder) *
204
audio_format.sample_rate;
206
if (WavpackSeekSample(wpc, where)) {
207
decoder_command_finished(decoder);
209
decoder_seek_error(decoder);
212
decoder_seek_error(decoder);
216
if (decoder_get_command(decoder) == DECODE_COMMAND_STOP) {
220
samples_got = WavpackUnpackSamples(
221
wpc, (int32_t *)chunk, samples_requested
223
if (samples_got > 0) {
224
int bitrate = (int)(WavpackGetInstantBitrate(wpc) /
228
bytes_per_sample, chunk,
229
samples_got * audio_format.channels
233
decoder, NULL, chunk,
234
samples_got * output_sample_size,
238
} while (samples_got > 0);
242
* Locate and parse a floating point tag. Returns true if it was
246
wavpack_tag_float(WavpackContext *wpc, const char *key, float *value_r)
251
ret = WavpackGetTagItem(wpc, key, buffer, sizeof(buffer));
255
*value_r = atof(buffer);
260
wavpack_replaygain(struct replay_gain_info *replay_gain_info,
265
replay_gain_info_init(replay_gain_info);
267
found |= wavpack_tag_float(
268
wpc, "replaygain_track_gain",
269
&replay_gain_info->tuples[REPLAY_GAIN_TRACK].gain
271
found |= wavpack_tag_float(
272
wpc, "replaygain_track_peak",
273
&replay_gain_info->tuples[REPLAY_GAIN_TRACK].peak
275
found |= wavpack_tag_float(
276
wpc, "replaygain_album_gain",
277
&replay_gain_info->tuples[REPLAY_GAIN_ALBUM].gain
279
found |= wavpack_tag_float(
280
wpc, "replaygain_album_peak",
281
&replay_gain_info->tuples[REPLAY_GAIN_ALBUM].peak
288
* Reads metainfo from the specified file.
291
wavpack_tagdup(const char *fname)
295
char error[ERRORLEN];
297
int size, allocated_size;
299
wpc = WavpackOpenFileInput(fname, error, OPEN_TAGS, 0);
302
"failed to open WavPack file \"%s\": %s\n",
309
tag->time = WavpackGetNumSamples(wpc);
310
tag->time /= WavpackGetSampleRate(wpc);
315
for (unsigned i = 0; i < G_N_ELEMENTS(tagtypes); ++i) {
316
size = WavpackGetTagItem(wpc, tagtypes[i].name, NULL, 0);
322
allocated_size = size;
323
} else if (size > allocated_size) {
324
char *t = (char *)g_realloc(s, size);
325
allocated_size = size;
329
WavpackGetTagItem(wpc, tagtypes[i].name, s, size);
330
tag_add_item(tag, tagtypes[i].type, s);
336
WavpackCloseFile(wpc);
342
* mpd input_stream <=> WavpackStreamReader wrapper callbacks
345
/* This struct is needed for per-stream last_byte storage. */
346
struct wavpack_input {
347
struct decoder *decoder;
348
struct input_stream *is;
349
/* Needed for push_back_byte() */
354
* Little wrapper for struct wavpack_input to cast from void *.
356
static struct wavpack_input *
364
wavpack_input_read_bytes(void *id, void *data, int32_t bcount)
366
uint8_t *buf = (uint8_t *)data;
369
if (wpin(id)->last_byte != EOF) {
370
*buf++ = wpin(id)->last_byte;
371
wpin(id)->last_byte = EOF;
376
/* wavpack fails if we return a partial read, so we just wait
377
until the buffer is full */
379
size_t nbytes = decoder_read(
380
wpin(id)->decoder, wpin(id)->is, buf, bcount
383
/* EOF, error or a decoder command */
396
wavpack_input_get_pos(void *id)
398
return wpin(id)->is->offset;
402
wavpack_input_set_pos_abs(void *id, uint32_t pos)
404
return input_stream_seek(wpin(id)->is, pos, SEEK_SET, NULL) ? 0 : -1;
408
wavpack_input_set_pos_rel(void *id, int32_t delta, int mode)
410
return input_stream_seek(wpin(id)->is, delta, mode, NULL) ? 0 : -1;
414
wavpack_input_push_back_byte(void *id, int c)
416
if (wpin(id)->last_byte == EOF) {
417
wpin(id)->last_byte = c;
425
wavpack_input_get_length(void *id)
427
if (wpin(id)->is->size < 0)
430
return wpin(id)->is->size;
434
wavpack_input_can_seek(void *id)
436
return wpin(id)->is->seekable;
439
static WavpackStreamReader mpd_is_reader = {
440
.read_bytes = wavpack_input_read_bytes,
441
.get_pos = wavpack_input_get_pos,
442
.set_pos_abs = wavpack_input_set_pos_abs,
443
.set_pos_rel = wavpack_input_set_pos_rel,
444
.push_back_byte = wavpack_input_push_back_byte,
445
.get_length = wavpack_input_get_length,
446
.can_seek = wavpack_input_can_seek,
447
.write_bytes = NULL /* no need to write edited tags */
451
wavpack_input_init(struct wavpack_input *isp, struct decoder *decoder,
452
struct input_stream *is)
454
isp->decoder = decoder;
456
isp->last_byte = EOF;
459
static struct input_stream *
460
wavpack_open_wvc(struct decoder *decoder, const char *uri,
461
struct wavpack_input *wpi)
463
struct input_stream *is_wvc;
464
char *wvc_url = NULL;
469
* As we use dc->utf8url, this function will be bad for
470
* single files. utf8url is not absolute file path :/
475
wvc_url = g_strconcat(uri, "c", NULL);
476
is_wvc = input_stream_open(wvc_url, NULL);
483
* And we try to buffer in order to get know
484
* about a possible 404 error.
486
nbytes = decoder_read(
487
decoder, is_wvc, &first_byte, sizeof(first_byte)
490
input_stream_close(is_wvc);
495
wavpack_input_init(wpi, decoder, is_wvc);
496
wpi->last_byte = first_byte;
504
wavpack_streamdecode(struct decoder * decoder, struct input_stream *is)
506
char error[ERRORLEN];
508
struct input_stream *is_wvc;
509
int open_flags = OPEN_NORMALIZE;
510
struct wavpack_input isp, isp_wvc;
511
bool can_seek = is->seekable;
513
is_wvc = wavpack_open_wvc(decoder, is->uri, &isp_wvc);
514
if (is_wvc != NULL) {
515
open_flags |= OPEN_WVC;
516
can_seek &= is_wvc->seekable;
520
open_flags |= OPEN_STREAMING;
523
wavpack_input_init(&isp, decoder, is);
524
wpc = WavpackOpenFileInputEx(
525
&mpd_is_reader, &isp,
526
open_flags & OPEN_WVC ? &isp_wvc : NULL,
527
error, open_flags, 23
531
g_warning("failed to open WavPack stream: %s\n", error);
535
wavpack_decode(decoder, wpc, can_seek);
537
WavpackCloseFile(wpc);
538
if (open_flags & OPEN_WVC) {
539
input_stream_close(is_wvc);
547
wavpack_filedecode(struct decoder *decoder, const char *fname)
549
char error[ERRORLEN];
552
wpc = WavpackOpenFileInput(
554
OPEN_TAGS | OPEN_WVC | OPEN_NORMALIZE, 23
558
"failed to open WavPack file \"%s\": %s\n",
564
struct replay_gain_info replay_gain_info;
565
if (wavpack_replaygain(&replay_gain_info, wpc))
566
decoder_replay_gain(decoder, &replay_gain_info);
568
wavpack_decode(decoder, wpc, true);
570
WavpackCloseFile(wpc);
573
static char const *const wavpack_suffixes[] = {
578
static char const *const wavpack_mime_types[] = {
583
const struct decoder_plugin wavpack_decoder_plugin = {
585
.stream_decode = wavpack_streamdecode,
586
.file_decode = wavpack_filedecode,
587
.tag_dup = wavpack_tagdup,
588
.suffixes = wavpack_suffixes,
589
.mime_types = wavpack_mime_types