aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/decoder/wavpack_plugin.c93
1 files changed, 46 insertions, 47 deletions
diff --git a/src/decoder/wavpack_plugin.c b/src/decoder/wavpack_plugin.c
index 675143753..568fd32f5 100644
--- a/src/decoder/wavpack_plugin.c
+++ b/src/decoder/wavpack_plugin.c
@@ -49,74 +49,69 @@ static struct {
/*
* This function has been borrowed from the tiny player found on
* wavpack.com. Modifications were required because mpd only handles
- * max 16 bit samples.
+ * max 24-bit samples.
*/
static void
format_samples_int(int bytes_per_sample, void *buffer, uint32_t samcnt)
{
- int32_t temp;
- uchar *dst = (uchar *)buffer;
- int32_t *src = (int32_t *)buffer;
+ int32_t *src = buffer;
switch (bytes_per_sample) {
- case 1:
+ case 1: {
+ uchar *dst = buffer;
+ /*
+ * The asserts like the following one are because we do the
+ * formatting of samples within a single buffer. The size
+ * of the output samples never can be greater than the size
+ * of the input ones. Otherwise we would have an overflow.
+ */
+ assert(sizeof(uchar) <= sizeof(uint32_t));
+
+ /* pass through and align 8-bit samples */
while (samcnt--) {
*dst++ = *src++;
}
break;
- case 2:
+ }
+ case 2: {
+ uint16_t *dst = buffer;
+ assert(sizeof(uint16_t) <= sizeof(uint32_t));
+
+ /* pass through and align 16-bit samples */
while (samcnt--) {
- temp = *src++;
-#ifdef WORDS_BIGENDIAN
- *dst++ = (uchar)(temp >> 8);
- *dst++ = (uchar)(temp);
-#else
- *dst++ = (uchar)(temp);
- *dst++ = (uchar)(temp >> 8);
-#endif
+ *dst++ = *src++;
}
break;
+ }
case 3:
- /* downscale to 16 bits */
- while (samcnt--) {
- temp = *src++;
-#ifdef WORDS_BIGENDIAN
- *dst++ = (uchar)(temp >> 16);
- *dst++ = (uchar)(temp >> 8);
-#else
- *dst++ = (uchar)(temp >> 8);
- *dst++ = (uchar)(temp >> 16);
-#endif
- }
+ /* do nothing */
break;
- case 4:
- /* downscale to 16 bits */
+ case 4: {
+ uint32_t *dst = buffer;
+ assert(sizeof(uint32_t) <= sizeof(uint32_t));
+
+ /* downsample to 24-bit */
while (samcnt--) {
- temp = *src++;
-#ifdef WORDS_BIGENDIAN
- *dst++ = (uchar)(temp >> 24);
- *dst++ = (uchar)(temp >> 16);
-#else
- *dst++ = (uchar)(temp >> 16);
- *dst++ = (uchar)(temp >> 24);
-#endif
+ *dst++ = *src++ >> 8;
}
break;
}
+ }
}
/*
- * This function converts floating point sample data to 16 bit integer.
+ * This function converts floating point sample data to 24-bit integer.
*/
static void
format_samples_float(mpd_unused int bytes_per_sample, void *buffer,
uint32_t samcnt)
{
- int16_t *dst = (int16_t *)buffer;
- float *src = (float *)buffer;
+ int32_t *dst = buffer;
+ float *src = buffer;
+ assert(sizeof(int32_t) <= sizeof(float));
while (samcnt--) {
- *dst++ = (int16_t)(*src++);
+ *dst++ = (int32_t)(*src++ + 0.5f);
}
}
@@ -142,8 +137,11 @@ wavpack_decode(struct decoder * decoder, WavpackContext *wpc, bool canseek,
audio_format.channels = WavpackGetReducedChannels(wpc);
audio_format.bits = WavpackGetBitsPerSample(wpc);
- if (audio_format.bits > 16) {
- audio_format.bits = 16;
+ /* 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 ((WavpackGetMode(wpc) & MODE_FLOAT) == MODE_FLOAT) {
@@ -153,19 +151,20 @@ wavpack_decode(struct decoder * decoder, WavpackContext *wpc, bool canseek,
}
/*
if ((WavpackGetMode(wpc) & MODE_WVC) == MODE_WVC)
- ERROR("decoding WITH wvc!!!\n");
+ printf("decoding WITH wvc!!!\n");
else
- ERROR("decoding without wvc\n");
+ printf("decoding without wvc\n");
*/
allsamples = WavpackGetNumSamples(wpc);
bytes_per_sample = WavpackGetBytesPerSample(wpc);
outsamplesize = bytes_per_sample;
- if (outsamplesize > 2) {
- outsamplesize = 2;
+ if (outsamplesize == 3) {
+ outsamplesize = 4;
}
outsamplesize *= audio_format.channels;
+ /* wavpack gives us all kind of samples in a 32-bit space */
samplesreq = sizeof(chunk) / (4 * audio_format.channels);
decoder_initialized(decoder, &audio_format, canseek,
@@ -535,7 +534,7 @@ wavpack_streamdecode(struct decoder * decoder, struct input_stream *is)
wavpack_input_init(&isp, decoder, is);
wpc = WavpackOpenFileInputEx(&mpd_is_reader, &isp, &isp_wvc, error,
- open_flags, 15);
+ open_flags, 23);
if (wpc == NULL) {
g_warning("failed to open WavPack stream: %s\n", error);
@@ -564,7 +563,7 @@ wavpack_filedecode(struct decoder *decoder, const char *fname)
wpc = WavpackOpenFileInput(fname, error,
OPEN_TAGS | OPEN_WVC |
- OPEN_2CH_MAX | OPEN_NORMALIZE, 15);
+ OPEN_2CH_MAX | OPEN_NORMALIZE, 23);
if (wpc == NULL) {
g_warning("failed to open WavPack file \"%s\": %s\n",
fname, error);