mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-11-10 03:35:42 +01:00
various bugfixes
- don't parse -X option because such an option doesn't exist - allow argument for --sleep-min option - fix handling of .voc magic string - fix handling of .voc files on big-endian machines - remove superfluous "size" parameter from check_wavefile_space macro - reallocate buffer only if needed in check_wavefile_space - fix playback of >2GB .wav files - skip over padding bytes in .wav files - fix memory leak when playing .voc silence blocks - fix file length when recording >2GB .wav files - fix recording of >4GB files
This commit is contained in:
parent
dfec58eb7e
commit
72ae8b1e79
2 changed files with 35 additions and 33 deletions
|
@ -305,7 +305,7 @@ enum {
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int option_index;
|
int option_index;
|
||||||
char *short_options = "hlLD:qt:c:f:r:d:s:MNF:A:X:R:T:B:vIPC";
|
char *short_options = "hlLD:qt:c:f:r:d:s:MNF:A:R:T:B:vIPC";
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{"help", 0, 0, 'h'},
|
{"help", 0, 0, 'h'},
|
||||||
{"version", 0, 0, OPT_VERSION},
|
{"version", 0, 0, OPT_VERSION},
|
||||||
|
@ -318,7 +318,7 @@ int main(int argc, char *argv[])
|
||||||
{"format", 1, 0, 'f'},
|
{"format", 1, 0, 'f'},
|
||||||
{"rate", 1, 0, 'r'},
|
{"rate", 1, 0, 'r'},
|
||||||
{"duration", 1, 0 ,'d'},
|
{"duration", 1, 0 ,'d'},
|
||||||
{"sleep-min", 0, 0, 's'},
|
{"sleep-min", 1, 0, 's'},
|
||||||
{"mmap", 0, 0, 'M'},
|
{"mmap", 0, 0, 'M'},
|
||||||
{"nonblock", 0, 0, 'N'},
|
{"nonblock", 0, 0, 'N'},
|
||||||
{"period-time", 1, 0, 'F'},
|
{"period-time", 1, 0, 'F'},
|
||||||
|
@ -602,12 +602,12 @@ static int test_vocfile(void *buffer)
|
||||||
{
|
{
|
||||||
VocHeader *vp = buffer;
|
VocHeader *vp = buffer;
|
||||||
|
|
||||||
if (strstr(vp->magic, VOC_MAGIC_STRING)) {
|
if (!memcmp(vp->magic, VOC_MAGIC_STRING, 20)) {
|
||||||
vocminor = vp->version & 0xFF;
|
vocminor = LE_SHORT(vp->version) & 0xFF;
|
||||||
vocmajor = vp->version / 256;
|
vocmajor = LE_SHORT(vp->version) / 256;
|
||||||
if (vp->version != (0x1233 - vp->coded_ver))
|
if (LE_SHORT(vp->version) != (0x1233 - LE_SHORT(vp->coded_ver)))
|
||||||
return -2; /* coded version mismatch */
|
return -2; /* coded version mismatch */
|
||||||
return vp->headerlen - sizeof(VocHeader); /* 0 mostly */
|
return LE_SHORT(vp->headerlen) - sizeof(VocHeader); /* 0 mostly */
|
||||||
}
|
}
|
||||||
return -1; /* magic string fail */
|
return -1; /* magic string fail */
|
||||||
}
|
}
|
||||||
|
@ -627,12 +627,13 @@ size_t test_wavefile_read(int fd, char *buffer, size_t *size, size_t reqsize, in
|
||||||
return *size = reqsize;
|
return *size = reqsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define check_wavefile_space(buffer, size, len, blimit) \
|
#define check_wavefile_space(buffer, len, blimit) \
|
||||||
if (size + len > blimit) \
|
if (len > blimit) { \
|
||||||
blimit = size + len; \
|
blimit = len; \
|
||||||
if ((buffer = realloc(buffer, blimit)) == NULL) { \
|
if ((buffer = realloc(buffer, blimit)) == NULL) { \
|
||||||
error("not enough memory"); \
|
error("not enough memory"); \
|
||||||
exit(EXIT_FAILURE); \
|
exit(EXIT_FAILURE); \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -654,22 +655,23 @@ static ssize_t test_wavefile(int fd, char *_buffer, size_t size)
|
||||||
if (h->magic != WAV_RIFF || h->type != WAV_WAVE)
|
if (h->magic != WAV_RIFF || h->type != WAV_WAVE)
|
||||||
return -1;
|
return -1;
|
||||||
if (size > sizeof(WaveHeader)) {
|
if (size > sizeof(WaveHeader)) {
|
||||||
check_wavefile_space(buffer, size, 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));
|
||||||
}
|
}
|
||||||
size -= sizeof(WaveHeader);
|
size -= sizeof(WaveHeader);
|
||||||
while (1) {
|
while (1) {
|
||||||
check_wavefile_space(buffer, size, sizeof(WaveChunkHeader), blimit);
|
check_wavefile_space(buffer, sizeof(WaveChunkHeader), blimit);
|
||||||
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 = LE_INT(c->length);
|
||||||
|
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));
|
||||||
size -= sizeof(WaveChunkHeader);
|
size -= sizeof(WaveChunkHeader);
|
||||||
if (type == WAV_FMT)
|
if (type == WAV_FMT)
|
||||||
break;
|
break;
|
||||||
check_wavefile_space(buffer, size, len, blimit);
|
check_wavefile_space(buffer, len, blimit);
|
||||||
test_wavefile_read(fd, buffer, &size, len, __LINE__);
|
test_wavefile_read(fd, buffer, &size, len, __LINE__);
|
||||||
if (size > len)
|
if (size > len)
|
||||||
memmove(buffer, buffer + len, size - len);
|
memmove(buffer, buffer + len, size - len);
|
||||||
|
@ -680,7 +682,7 @@ static ssize_t test_wavefile(int fd, char *_buffer, size_t size)
|
||||||
error("unknown length of 'fmt ' chunk (read %u, should be %u at least)", len, (u_int)sizeof(WaveFmtBody));
|
error("unknown length of 'fmt ' chunk (read %u, should be %u at least)", len, (u_int)sizeof(WaveFmtBody));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
check_wavefile_space(buffer, size, 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_PCM_CODE) {
|
if (LE_SHORT(f->format) != WAV_PCM_CODE) {
|
||||||
|
@ -740,7 +742,7 @@ static ssize_t test_wavefile(int fd, char *_buffer, size_t size)
|
||||||
while (1) {
|
while (1) {
|
||||||
u_int type, len;
|
u_int type, len;
|
||||||
|
|
||||||
check_wavefile_space(buffer, size, sizeof(WaveChunkHeader), blimit);
|
check_wavefile_space(buffer, sizeof(WaveChunkHeader), blimit);
|
||||||
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;
|
||||||
|
@ -749,14 +751,15 @@ static ssize_t test_wavefile(int fd, char *_buffer, size_t size)
|
||||||
memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));
|
memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));
|
||||||
size -= sizeof(WaveChunkHeader);
|
size -= sizeof(WaveChunkHeader);
|
||||||
if (type == WAV_DATA) {
|
if (type == WAV_DATA) {
|
||||||
if (len < pbrec_count)
|
if (len < pbrec_count && len < 0x7ffffffe)
|
||||||
pbrec_count = len;
|
pbrec_count = len;
|
||||||
if (size > 0)
|
if (size > 0)
|
||||||
memcpy(_buffer, buffer, size);
|
memcpy(_buffer, buffer, size);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
check_wavefile_space(buffer, size, len, blimit);
|
len += len % 2;
|
||||||
|
check_wavefile_space(buffer, len, blimit);
|
||||||
test_wavefile_read(fd, buffer, &size, len, __LINE__);
|
test_wavefile_read(fd, buffer, &size, len, __LINE__);
|
||||||
if (size > len)
|
if (size > len)
|
||||||
memmove(buffer, buffer + len, size - len);
|
memmove(buffer, buffer + len, size - len);
|
||||||
|
@ -1294,6 +1297,7 @@ static void voc_write_silence(unsigned x)
|
||||||
}
|
}
|
||||||
x -= l;
|
x -= l;
|
||||||
}
|
}
|
||||||
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void voc_pcm_flush(void)
|
static void voc_pcm_flush(void)
|
||||||
|
@ -1562,11 +1566,10 @@ static void begin_voc(int fd, size_t cnt)
|
||||||
VocVoiceData vd;
|
VocVoiceData vd;
|
||||||
VocExtBlock eb;
|
VocExtBlock eb;
|
||||||
|
|
||||||
strncpy(vh.magic, VOC_MAGIC_STRING, 20);
|
memcpy(vh.magic, VOC_MAGIC_STRING, 20);
|
||||||
vh.magic[19] = 0x1A;
|
vh.headerlen = LE_SHORT(sizeof(VocHeader));
|
||||||
vh.headerlen = sizeof(VocHeader);
|
vh.version = LE_SHORT(VOC_ACTUAL_VERSION);
|
||||||
vh.version = VOC_ACTUAL_VERSION;
|
vh.coded_ver = LE_SHORT(0x1233 - VOC_ACTUAL_VERSION);
|
||||||
vh.coded_ver = 0x1233 - VOC_ACTUAL_VERSION;
|
|
||||||
|
|
||||||
if (write(fd, &vh, sizeof(VocHeader)) != sizeof(VocHeader)) {
|
if (write(fd, &vh, sizeof(VocHeader)) != sizeof(VocHeader)) {
|
||||||
error("write error");
|
error("write error");
|
||||||
|
@ -1581,7 +1584,7 @@ static void begin_voc(int fd, size_t cnt)
|
||||||
error("write error");
|
error("write error");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
eb.tc = (u_short) (65536 - 256000000L / (hwparams.rate << 1));
|
eb.tc = LE_SHORT(65536 - 256000000L / (hwparams.rate << 1));
|
||||||
eb.pack = 0;
|
eb.pack = 0;
|
||||||
eb.mode = 1;
|
eb.mode = 1;
|
||||||
if (write(fd, &eb, sizeof(VocExtBlock)) != sizeof(VocExtBlock)) {
|
if (write(fd, &eb, sizeof(VocExtBlock)) != sizeof(VocExtBlock)) {
|
||||||
|
@ -1743,15 +1746,16 @@ static void end_wave(int fd)
|
||||||
{ /* only close output */
|
{ /* only close output */
|
||||||
WaveChunkHeader cd;
|
WaveChunkHeader cd;
|
||||||
off64_t length_seek;
|
off64_t length_seek;
|
||||||
|
off64_t filelen;
|
||||||
u_int rifflen;
|
u_int rifflen;
|
||||||
|
|
||||||
length_seek = sizeof(WaveHeader) +
|
length_seek = sizeof(WaveHeader) +
|
||||||
sizeof(WaveChunkHeader) +
|
sizeof(WaveChunkHeader) +
|
||||||
sizeof(WaveFmtBody);
|
sizeof(WaveFmtBody);
|
||||||
cd.type = WAV_DATA;
|
cd.type = WAV_DATA;
|
||||||
cd.length = fdcount > 0x7fffffff ? 0x7fffffff : LE_INT(fdcount);
|
cd.length = fdcount > 0x7fffffff ? LE_INT(0x7fffffff) : LE_INT(fdcount);
|
||||||
rifflen = fdcount + 2*sizeof(WaveChunkHeader) + sizeof(WaveFmtBody) + 4;
|
filelen = fdcount + 2*sizeof(WaveChunkHeader) + sizeof(WaveFmtBody) + 4;
|
||||||
rifflen = rifflen > 0x7fffffff ? 0x7fffffff : LE_INT(rifflen);
|
rifflen = filelen > 0x7fffffff ? LE_INT(0x7fffffff) : LE_INT(filelen);
|
||||||
if (lseek64(fd, 4, SEEK_SET) == 4)
|
if (lseek64(fd, 4, SEEK_SET) == 4)
|
||||||
write(fd, &rifflen, 4);
|
write(fd, &rifflen, 4);
|
||||||
if (lseek64(fd, length_seek, SEEK_SET) == length_seek)
|
if (lseek64(fd, length_seek, SEEK_SET) == length_seek)
|
||||||
|
@ -1856,9 +1860,7 @@ void capture_go(int fd, off64_t count, int rtype, char *name)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
for (cur = count; cur > 0; cur -= r) {
|
for (cur = count; cur > 0; cur -= r) {
|
||||||
c = cur;
|
c = (cur <= chunk_bytes) ? cur : chunk_bytes;
|
||||||
if (c > chunk_bytes)
|
|
||||||
c = chunk_bytes;
|
|
||||||
c = c * 8 / bits_per_frame;
|
c = c * 8 / bits_per_frame;
|
||||||
if ((size_t)(r = pcm_read(audiobuf, c)) != c)
|
if ((size_t)(r = pcm_read(audiobuf, c)) != c)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
/* Definitions for .VOC files */
|
/* Definitions for .VOC files */
|
||||||
|
|
||||||
#define VOC_MAGIC_STRING "Creative Voice File\0x1A"
|
#define VOC_MAGIC_STRING "Creative Voice File\x1A"
|
||||||
#define VOC_ACTUAL_VERSION 0x010A
|
#define VOC_ACTUAL_VERSION 0x010A
|
||||||
#define VOC_SAMPLESIZE 8
|
#define VOC_SAMPLESIZE 8
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue