mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-12-23 02:56:30 +01:00
aplay: Add the support for big-endian WAV format (RIFX)
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
c7b9d3e394
commit
de61ec66fe
2 changed files with 73 additions and 29 deletions
|
@ -892,11 +892,20 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
|
||||||
WaveFmtBody *f;
|
WaveFmtBody *f;
|
||||||
WaveChunkHeader *c;
|
WaveChunkHeader *c;
|
||||||
u_int type, len;
|
u_int type, len;
|
||||||
|
unsigned short format, channels;
|
||||||
|
int big_endian, native_format;
|
||||||
|
|
||||||
if (size < sizeof(WaveHeader))
|
if (size < sizeof(WaveHeader))
|
||||||
return -1;
|
return -1;
|
||||||
if (h->magic != WAV_RIFF || h->type != WAV_WAVE)
|
if (h->magic == WAV_RIFF)
|
||||||
|
big_endian = 0;
|
||||||
|
else if (h->magic == WAV_RIFX)
|
||||||
|
big_endian = 1;
|
||||||
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
if (h->type != WAV_WAVE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (size > sizeof(WaveHeader)) {
|
if (size > sizeof(WaveHeader)) {
|
||||||
check_wavefile_space(buffer, size - sizeof(WaveHeader), blimit);
|
check_wavefile_space(buffer, size - sizeof(WaveHeader), blimit);
|
||||||
memcpy(buffer, _buffer + sizeof(WaveHeader), size - sizeof(WaveHeader));
|
memcpy(buffer, _buffer + sizeof(WaveHeader), size - sizeof(WaveHeader));
|
||||||
|
@ -907,7 +916,7 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
|
||||||
test_wavefile_read(fd, buffer, &size, sizeof(WaveChunkHeader), __LINE__);
|
test_wavefile_read(fd, buffer, &size, sizeof(WaveChunkHeader), __LINE__);
|
||||||
c = (WaveChunkHeader*)buffer;
|
c = (WaveChunkHeader*)buffer;
|
||||||
type = c->type;
|
type = c->type;
|
||||||
len = LE_INT(c->length);
|
len = TO_CPU_INT(c->length, big_endian);
|
||||||
len += len % 2;
|
len += len % 2;
|
||||||
if (size > sizeof(WaveChunkHeader))
|
if (size > sizeof(WaveChunkHeader))
|
||||||
memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));
|
memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));
|
||||||
|
@ -929,7 +938,8 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
|
||||||
check_wavefile_space(buffer, len, blimit);
|
check_wavefile_space(buffer, len, blimit);
|
||||||
test_wavefile_read(fd, buffer, &size, len, __LINE__);
|
test_wavefile_read(fd, buffer, &size, len, __LINE__);
|
||||||
f = (WaveFmtBody*) buffer;
|
f = (WaveFmtBody*) buffer;
|
||||||
if (LE_SHORT(f->format) == WAV_FMT_EXTENSIBLE) {
|
format = TO_CPU_SHORT(f->format, big_endian);
|
||||||
|
if (format == WAV_FMT_EXTENSIBLE) {
|
||||||
WaveFmtExtensibleBody *fe = (WaveFmtExtensibleBody*)buffer;
|
WaveFmtExtensibleBody *fe = (WaveFmtExtensibleBody*)buffer;
|
||||||
if (len < sizeof(WaveFmtExtensibleBody)) {
|
if (len < sizeof(WaveFmtExtensibleBody)) {
|
||||||
error(_("unknown length of extensible 'fmt ' chunk (read %u, should be %u at least)"),
|
error(_("unknown length of extensible 'fmt ' chunk (read %u, should be %u at least)"),
|
||||||
|
@ -940,19 +950,20 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
|
||||||
error(_("wrong format tag in extensible 'fmt ' chunk"));
|
error(_("wrong format tag in extensible 'fmt ' chunk"));
|
||||||
prg_exit(EXIT_FAILURE);
|
prg_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
f->format = fe->guid_format;
|
format = TO_CPU_SHORT(fe->guid_format, big_endian);
|
||||||
}
|
}
|
||||||
if (LE_SHORT(f->format) != WAV_FMT_PCM &&
|
if (format != WAV_FMT_PCM &&
|
||||||
LE_SHORT(f->format) != WAV_FMT_IEEE_FLOAT) {
|
format != WAV_FMT_IEEE_FLOAT) {
|
||||||
error(_("can't play WAVE-file format 0x%04x which is not PCM or FLOAT encoded"), LE_SHORT(f->format));
|
error(_("can't play WAVE-file format 0x%04x which is not PCM or FLOAT encoded"), format);
|
||||||
prg_exit(EXIT_FAILURE);
|
prg_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (LE_SHORT(f->channels) < 1) {
|
channels = TO_CPU_SHORT(f->channels, big_endian);
|
||||||
error(_("can't play WAVE-files with %d tracks"), LE_SHORT(f->channels));
|
if (channels < 1) {
|
||||||
|
error(_("can't play WAVE-files with %d tracks"), channels);
|
||||||
prg_exit(EXIT_FAILURE);
|
prg_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
hwparams.channels = LE_SHORT(f->channels);
|
hwparams.channels = channels;
|
||||||
switch (LE_SHORT(f->bit_p_spl)) {
|
switch (TO_CPU_SHORT(f->bit_p_spl, big_endian)) {
|
||||||
case 8:
|
case 8:
|
||||||
if (hwparams.format != DEFAULT_FORMAT &&
|
if (hwparams.format != DEFAULT_FORMAT &&
|
||||||
hwparams.format != SND_PCM_FORMAT_U8)
|
hwparams.format != SND_PCM_FORMAT_U8)
|
||||||
|
@ -960,43 +971,69 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
|
||||||
hwparams.format = SND_PCM_FORMAT_U8;
|
hwparams.format = SND_PCM_FORMAT_U8;
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
|
if (big_endian)
|
||||||
|
native_format = SND_PCM_FORMAT_S16_BE;
|
||||||
|
else
|
||||||
|
native_format = SND_PCM_FORMAT_S16_LE;
|
||||||
if (hwparams.format != DEFAULT_FORMAT &&
|
if (hwparams.format != DEFAULT_FORMAT &&
|
||||||
hwparams.format != SND_PCM_FORMAT_S16_LE)
|
hwparams.format != native_format)
|
||||||
fprintf(stderr, _("Warning: format is changed to S16_LE\n"));
|
fprintf(stderr, _("Warning: format is changed to %s\n"),
|
||||||
hwparams.format = SND_PCM_FORMAT_S16_LE;
|
snd_pcm_format_name(native_format));
|
||||||
|
hwparams.format = native_format;
|
||||||
break;
|
break;
|
||||||
case 24:
|
case 24:
|
||||||
switch (LE_SHORT(f->byte_p_spl) / hwparams.channels) {
|
switch (TO_CPU_SHORT(f->byte_p_spl, big_endian) / hwparams.channels) {
|
||||||
case 3:
|
case 3:
|
||||||
|
if (big_endian)
|
||||||
|
native_format = SND_PCM_FORMAT_S24_3BE;
|
||||||
|
else
|
||||||
|
native_format = SND_PCM_FORMAT_S24_3LE;
|
||||||
if (hwparams.format != DEFAULT_FORMAT &&
|
if (hwparams.format != DEFAULT_FORMAT &&
|
||||||
hwparams.format != SND_PCM_FORMAT_S24_3LE)
|
hwparams.format != native_format)
|
||||||
fprintf(stderr, _("Warning: format is changed to S24_3LE\n"));
|
fprintf(stderr, _("Warning: format is changed to %s\n"),
|
||||||
hwparams.format = SND_PCM_FORMAT_S24_3LE;
|
snd_pcm_format_name(native_format));
|
||||||
|
hwparams.format = native_format;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
|
if (big_endian)
|
||||||
|
native_format = SND_PCM_FORMAT_S24_BE;
|
||||||
|
else
|
||||||
|
native_format = SND_PCM_FORMAT_S24_LE;
|
||||||
if (hwparams.format != DEFAULT_FORMAT &&
|
if (hwparams.format != DEFAULT_FORMAT &&
|
||||||
hwparams.format != SND_PCM_FORMAT_S24_LE)
|
hwparams.format != native_format)
|
||||||
fprintf(stderr, _("Warning: format is changed to S24_LE\n"));
|
fprintf(stderr, _("Warning: format is changed to %s\n"),
|
||||||
hwparams.format = SND_PCM_FORMAT_S24_LE;
|
snd_pcm_format_name(native_format));
|
||||||
|
hwparams.format = native_format;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error(_(" can't play WAVE-files with sample %d bits in %d bytes wide (%d channels)"),
|
error(_(" can't play WAVE-files with sample %d bits in %d bytes wide (%d channels)"),
|
||||||
LE_SHORT(f->bit_p_spl), LE_SHORT(f->byte_p_spl), hwparams.channels);
|
TO_CPU_SHORT(f->bit_p_spl, big_endian),
|
||||||
|
TO_CPU_SHORT(f->byte_p_spl, big_endian),
|
||||||
|
hwparams.channels);
|
||||||
prg_exit(EXIT_FAILURE);
|
prg_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
if (LE_SHORT(f->format) == WAV_FMT_PCM)
|
if (format == WAV_FMT_PCM) {
|
||||||
hwparams.format = SND_PCM_FORMAT_S32_LE;
|
if (big_endian)
|
||||||
else if (LE_SHORT(f->format) == WAV_FMT_IEEE_FLOAT)
|
native_format = SND_PCM_FORMAT_S32_BE;
|
||||||
hwparams.format = SND_PCM_FORMAT_FLOAT_LE;
|
else
|
||||||
|
native_format = SND_PCM_FORMAT_S32_LE;
|
||||||
|
hwparams.format = native_format;
|
||||||
|
} else if (format == WAV_FMT_IEEE_FLOAT) {
|
||||||
|
if (big_endian)
|
||||||
|
native_format = SND_PCM_FORMAT_FLOAT_BE;
|
||||||
|
else
|
||||||
|
native_format = SND_PCM_FORMAT_FLOAT_LE;
|
||||||
|
hwparams.format = native_format;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error(_(" can't play WAVE-files with sample %d bits wide"),
|
error(_(" can't play WAVE-files with sample %d bits wide"),
|
||||||
LE_SHORT(f->bit_p_spl));
|
TO_CPU_SHORT(f->bit_p_spl, big_endian));
|
||||||
prg_exit(EXIT_FAILURE);
|
prg_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
hwparams.rate = LE_INT(f->sample_fq);
|
hwparams.rate = TO_CPU_INT(f->sample_fq, big_endian);
|
||||||
|
|
||||||
if (size > len)
|
if (size > len)
|
||||||
memmove(buffer, buffer + len, size - len);
|
memmove(buffer, buffer + len, size - len);
|
||||||
|
@ -1009,7 +1046,7 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
|
||||||
test_wavefile_read(fd, buffer, &size, sizeof(WaveChunkHeader), __LINE__);
|
test_wavefile_read(fd, buffer, &size, sizeof(WaveChunkHeader), __LINE__);
|
||||||
c = (WaveChunkHeader*)buffer;
|
c = (WaveChunkHeader*)buffer;
|
||||||
type = c->type;
|
type = c->type;
|
||||||
len = LE_INT(c->length);
|
len = TO_CPU_INT(c->length, big_endian);
|
||||||
if (size > sizeof(WaveChunkHeader))
|
if (size > sizeof(WaveChunkHeader))
|
||||||
memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));
|
memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));
|
||||||
size -= sizeof(WaveChunkHeader);
|
size -= sizeof(WaveChunkHeader);
|
||||||
|
|
|
@ -60,7 +60,14 @@ typedef struct voc_ext_block {
|
||||||
#error "Wrong endian"
|
#error "Wrong endian"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Note: the following macros evaluate the parameter v twice */
|
||||||
|
#define TO_CPU_SHORT(v, be) \
|
||||||
|
((be) ? BE_SHORT(v) : LE_SHORT(v))
|
||||||
|
#define TO_CPU_INT(v, be) \
|
||||||
|
((be) ? BE_INT(v) : LE_INT(v))
|
||||||
|
|
||||||
#define WAV_RIFF COMPOSE_ID('R','I','F','F')
|
#define WAV_RIFF COMPOSE_ID('R','I','F','F')
|
||||||
|
#define WAV_RIFX COMPOSE_ID('R','I','F','X')
|
||||||
#define WAV_WAVE COMPOSE_ID('W','A','V','E')
|
#define WAV_WAVE COMPOSE_ID('W','A','V','E')
|
||||||
#define WAV_FMT COMPOSE_ID('f','m','t',' ')
|
#define WAV_FMT COMPOSE_ID('f','m','t',' ')
|
||||||
#define WAV_DATA COMPOSE_ID('d','a','t','a')
|
#define WAV_DATA COMPOSE_ID('d','a','t','a')
|
||||||
|
|
Loading…
Reference in a new issue