wavpack: make 24-bit samples available for mpd
This patch makes 24-bit samples available for mpd. I tested with the WavPack Test Suite found on wavpack.com: http://www.rarewares.org/wavpack/test_suite.zip Every test file worked fine.
This commit is contained in:
parent
3e338da871
commit
343a8a20e3
@ -49,74 +49,69 @@ static struct {
|
|||||||
/*
|
/*
|
||||||
* This function has been borrowed from the tiny player found on
|
* This function has been borrowed from the tiny player found on
|
||||||
* wavpack.com. Modifications were required because mpd only handles
|
* wavpack.com. Modifications were required because mpd only handles
|
||||||
* max 16 bit samples.
|
* max 24-bit samples.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
format_samples_int(int bytes_per_sample, void *buffer, uint32_t samcnt)
|
format_samples_int(int bytes_per_sample, void *buffer, uint32_t samcnt)
|
||||||
{
|
{
|
||||||
int32_t temp;
|
int32_t *src = buffer;
|
||||||
uchar *dst = (uchar *)buffer;
|
|
||||||
int32_t *src = (int32_t *)buffer;
|
|
||||||
|
|
||||||
switch (bytes_per_sample) {
|
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--) {
|
while (samcnt--) {
|
||||||
*dst++ = *src++;
|
*dst++ = *src++;
|
||||||
}
|
}
|
||||||
break;
|
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--) {
|
while (samcnt--) {
|
||||||
temp = *src++;
|
*dst++ = *src++;
|
||||||
#ifdef WORDS_BIGENDIAN
|
|
||||||
*dst++ = (uchar)(temp >> 8);
|
|
||||||
*dst++ = (uchar)(temp);
|
|
||||||
#else
|
|
||||||
*dst++ = (uchar)(temp);
|
|
||||||
*dst++ = (uchar)(temp >> 8);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 3:
|
case 3:
|
||||||
/* downscale to 16 bits */
|
/* do nothing */
|
||||||
|
break;
|
||||||
|
case 4: {
|
||||||
|
uint32_t *dst = buffer;
|
||||||
|
assert(sizeof(uint32_t) <= sizeof(uint32_t));
|
||||||
|
|
||||||
|
/* downsample to 24-bit */
|
||||||
while (samcnt--) {
|
while (samcnt--) {
|
||||||
temp = *src++;
|
*dst++ = *src++ >> 8;
|
||||||
#ifdef WORDS_BIGENDIAN
|
|
||||||
*dst++ = (uchar)(temp >> 16);
|
|
||||||
*dst++ = (uchar)(temp >> 8);
|
|
||||||
#else
|
|
||||||
*dst++ = (uchar)(temp >> 8);
|
|
||||||
*dst++ = (uchar)(temp >> 16);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
/* downscale to 16 bits */
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
break;
|
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
|
static void
|
||||||
format_samples_float(mpd_unused int bytes_per_sample, void *buffer,
|
format_samples_float(mpd_unused int bytes_per_sample, void *buffer,
|
||||||
uint32_t samcnt)
|
uint32_t samcnt)
|
||||||
{
|
{
|
||||||
int16_t *dst = (int16_t *)buffer;
|
int32_t *dst = buffer;
|
||||||
float *src = (float *)buffer;
|
float *src = buffer;
|
||||||
|
assert(sizeof(int32_t) <= sizeof(float));
|
||||||
|
|
||||||
while (samcnt--) {
|
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.channels = WavpackGetReducedChannels(wpc);
|
||||||
audio_format.bits = WavpackGetBitsPerSample(wpc);
|
audio_format.bits = WavpackGetBitsPerSample(wpc);
|
||||||
|
|
||||||
if (audio_format.bits > 16) {
|
/* round bitwidth to 8-bit units */
|
||||||
audio_format.bits = 16;
|
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) {
|
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)
|
if ((WavpackGetMode(wpc) & MODE_WVC) == MODE_WVC)
|
||||||
ERROR("decoding WITH wvc!!!\n");
|
printf("decoding WITH wvc!!!\n");
|
||||||
else
|
else
|
||||||
ERROR("decoding without wvc\n");
|
printf("decoding without wvc\n");
|
||||||
*/
|
*/
|
||||||
allsamples = WavpackGetNumSamples(wpc);
|
allsamples = WavpackGetNumSamples(wpc);
|
||||||
bytes_per_sample = WavpackGetBytesPerSample(wpc);
|
bytes_per_sample = WavpackGetBytesPerSample(wpc);
|
||||||
|
|
||||||
outsamplesize = bytes_per_sample;
|
outsamplesize = bytes_per_sample;
|
||||||
if (outsamplesize > 2) {
|
if (outsamplesize == 3) {
|
||||||
outsamplesize = 2;
|
outsamplesize = 4;
|
||||||
}
|
}
|
||||||
outsamplesize *= audio_format.channels;
|
outsamplesize *= audio_format.channels;
|
||||||
|
|
||||||
|
/* wavpack gives us all kind of samples in a 32-bit space */
|
||||||
samplesreq = sizeof(chunk) / (4 * audio_format.channels);
|
samplesreq = sizeof(chunk) / (4 * audio_format.channels);
|
||||||
|
|
||||||
decoder_initialized(decoder, &audio_format, canseek,
|
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);
|
wavpack_input_init(&isp, decoder, is);
|
||||||
wpc = WavpackOpenFileInputEx(&mpd_is_reader, &isp, &isp_wvc, error,
|
wpc = WavpackOpenFileInputEx(&mpd_is_reader, &isp, &isp_wvc, error,
|
||||||
open_flags, 15);
|
open_flags, 23);
|
||||||
|
|
||||||
if (wpc == NULL) {
|
if (wpc == NULL) {
|
||||||
g_warning("failed to open WavPack stream: %s\n", error);
|
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,
|
wpc = WavpackOpenFileInput(fname, error,
|
||||||
OPEN_TAGS | OPEN_WVC |
|
OPEN_TAGS | OPEN_WVC |
|
||||||
OPEN_2CH_MAX | OPEN_NORMALIZE, 15);
|
OPEN_2CH_MAX | OPEN_NORMALIZE, 23);
|
||||||
if (wpc == NULL) {
|
if (wpc == NULL) {
|
||||||
g_warning("failed to open WavPack file \"%s\": %s\n",
|
g_warning("failed to open WavPack file \"%s\": %s\n",
|
||||||
fname, error);
|
fname, error);
|
||||||
|
Loading…
Reference in New Issue
Block a user