Better .wav detection

This commit is contained in:
Abramo Bagnara 2000-05-29 18:54:23 +00:00
parent 749b454304
commit 048c2000f8
2 changed files with 92 additions and 62 deletions

View file

@ -377,7 +377,6 @@ int main(int argc, char *argv[])
fprintf(stderr, "Error: wrong extended format '%s'\n", optarg); fprintf(stderr, "Error: wrong extended format '%s'\n", optarg);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
active_format = FORMAT_RAW;
break; break;
case 'm': case 'm':
case 'M': case 'M':
@ -514,26 +513,38 @@ static int test_vocfile(void *buffer)
} }
/* /*
* test, if it's a .WAV file, 0 if ok (and set the speed, stereo etc.) * test, if it's a .WAV file, > 0 if ok (and set the speed, stereo etc.)
* < 0 if not * == 0 if not
* Value returned is bytes to be discarded.
*/ */
static int test_wavefile(void *buffer) static int test_wavefile(void *buffer, size_t size)
{ {
WaveHeader *wp = buffer; WaveHeader *h = buffer;
WaveFmtHeader *f;
WaveChunkHeader *c;
if (wp->main_chunk == WAV_RIFF && wp->chunk_type == WAV_WAVE && if (h->magic != WAV_RIFF || h->type != WAV_WAVE)
wp->sub_chunk == WAV_FMT && wp->data_chunk == WAV_DATA) { return 0;
if (LE_SHORT(wp->format) != WAV_PCM_CODE) { c = (WaveChunkHeader*)((char *)buffer + sizeof(WaveHeader));
while (c->type != WAV_FMT) {
c = (WaveChunkHeader*)((char*)c + sizeof(*c) + c->length);
if ((char *)c + sizeof(*c) > (char*) buffer + size) {
fprintf(stderr, "%s: cannot found WAVE fmt chunk\n", command);
exit(EXIT_FAILURE);
}
}
f = (WaveFmtHeader*) c;
if (LE_SHORT(f->format) != WAV_PCM_CODE) {
fprintf(stderr, "%s: can't play not PCM-coded WAVE-files\n", command); fprintf(stderr, "%s: can't play not PCM-coded WAVE-files\n", command);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (LE_SHORT(wp->modus) < 1 || LE_SHORT(wp->modus) > 32) { if (LE_SHORT(f->modus) < 1) {
fprintf(stderr, "%s: can't play WAVE-files with %d tracks\n", fprintf(stderr, "%s: can't play WAVE-files with %d tracks\n",
command, LE_SHORT(wp->modus)); command, LE_SHORT(f->modus));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
format.channels = LE_SHORT(wp->modus); format.channels = LE_SHORT(f->modus);
switch (LE_SHORT(wp->bit_p_spl)) { switch (LE_SHORT(f->bit_p_spl)) {
case 8: case 8:
format.format = SND_PCM_SFMT_U8; format.format = SND_PCM_SFMT_U8;
break; break;
@ -542,14 +553,21 @@ static int test_wavefile(void *buffer)
break; break;
default: default:
fprintf(stderr, "%s: can't play WAVE-files with sample %d bits wide\n", fprintf(stderr, "%s: can't play WAVE-files with sample %d bits wide\n",
command, LE_SHORT(wp->bit_p_spl)); command, LE_SHORT(f->bit_p_spl));
exit(EXIT_FAILURE);
} }
format.rate = LE_INT(wp->sample_fq); format.rate = LE_INT(f->sample_fq);
count = LE_INT(wp->data_length); while (c->type != WAV_DATA) {
c = (WaveChunkHeader*)((char*)c + sizeof(*c) + c->length);
if ((char *)c + sizeof(*c) > (char*) buffer + size) {
fprintf(stderr, "%s: cannot found WAVE data chunk\n", command);
exit(EXIT_FAILURE);
}
}
count = LE_INT(c->length);
check_new_format(&format); check_new_format(&format);
return 0; return (char *)c + sizeof(*c) - (char *) buffer;
}
return -1;
} }
/* /*
@ -1209,7 +1227,9 @@ static void begin_voc(int fd, size_t cnt)
/* write a WAVE-header */ /* write a WAVE-header */
static void begin_wave(int fd, size_t cnt) static void begin_wave(int fd, size_t cnt)
{ {
WaveHeader wh; WaveHeader h;
WaveFmtHeader f;
WaveChunkHeader c;
int bits; int bits;
bits = 8; bits = 8;
@ -1224,25 +1244,30 @@ static void begin_wave(int fd, size_t cnt)
fprintf(stderr, "%s: Wave doesn't support %s format...\n", command, snd_pcm_get_format_name(format.format)); fprintf(stderr, "%s: Wave doesn't support %s format...\n", command, snd_pcm_get_format_name(format.format));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
wh.main_chunk = WAV_RIFF; h.magic = WAV_RIFF;
wh.length = cnt + sizeof(WaveHeader) - 8; h.length = cnt + sizeof(WaveHeader) + sizeof(WaveFmtHeader) + sizeof(WaveChunkHeader) - 8;
wh.chunk_type = WAV_WAVE; h.type = WAV_WAVE;
wh.sub_chunk = WAV_FMT;
wh.sc_len = 16; f.type = WAV_FMT;
wh.format = WAV_PCM_CODE; f.length = 16;
wh.modus = format.channels; f.format = WAV_PCM_CODE;
wh.sample_fq = format.rate; f.modus = format.channels;
f.sample_fq = format.rate;
#if 0 #if 0
wh.byte_p_spl = (samplesize == 8) ? 1 : 2; f.byte_p_spl = (samplesize == 8) ? 1 : 2;
wh.byte_p_sec = dsp_speed * wh.modus * wh.byte_p_spl; f.byte_p_sec = dsp_speed * f.modus * f.byte_p_spl;
#else #else
wh.byte_p_spl = wh.modus * ((bits + 7) / 8); f.byte_p_spl = f.modus * ((bits + 7) / 8);
wh.byte_p_sec = wh.byte_p_spl * format.rate; f.byte_p_sec = f.byte_p_spl * format.rate;
#endif #endif
wh.bit_p_spl = bits; f.bit_p_spl = bits;
wh.data_chunk = WAV_DATA;
wh.data_length = cnt; c.type = WAV_DATA;
if (write(fd, &wh, sizeof(WaveHeader)) != sizeof(WaveHeader)) { c.length = cnt;
if (write(fd, &h, sizeof(WaveHeader)) != sizeof(WaveHeader) ||
write(fd, &f, sizeof(WaveFmtHeader)) != sizeof(WaveFmtHeader) ||
write(fd, &c, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader)) {
fprintf(stderr, "%s: write error\n", command); fprintf(stderr, "%s: write error\n", command);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -1427,19 +1452,20 @@ static void playback(char *name)
} }
/* read bytes for WAVE-header */ /* read bytes for WAVE-header */
if (read(fd, audiobuf + sizeof(VocHeader), if (read(fd, audiobuf + sizeof(VocHeader),
sizeof(WaveHeader) - sizeof(VocHeader)) != 64 - sizeof(VocHeader)) !=
sizeof(WaveHeader) - sizeof(VocHeader)) { 64 - sizeof(VocHeader)) {
fprintf(stderr, "%s: read error", command); fprintf(stderr, "%s: read error", command);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (test_wavefile(audiobuf) >= 0) { if ((ofs = test_wavefile(audiobuf, 64)) > 0) {
playback_go(fd, 0, count, FORMAT_WAVE, name); memmove(audiobuf, audiobuf + ofs, 64 - ofs);
playback_go(fd, 64 - ofs, count, FORMAT_WAVE, name);
} else { } else {
/* should be raw data */ /* should be raw data */
check_new_format(&rformat); check_new_format(&rformat);
init_raw_data(); init_raw_data();
count = calc_count(); count = calc_count();
playback_go(fd, sizeof(WaveHeader), count, FORMAT_RAW, name); playback_go(fd, 50, count, FORMAT_RAW, name);
} }
__end: __end:
if (fd != 0) if (fd != 0)

View file

@ -64,23 +64,27 @@ typedef struct voc_ext_block {
are in only in this combination, so I combined them in one header; are in only in this combination, so I combined them in one header;
it works on all WAVE-file I have it works on all WAVE-file I have
*/ */
typedef struct wav_header { typedef struct {
u_int main_chunk; /* 'RIFF' */ u_int magic; /* 'RIFF' */
u_int length; /* filelen */ u_int length; /* filelen */
u_int chunk_type; /* 'WAVE' */ u_int type; /* 'WAVE' */
} WaveHeader;
u_int sub_chunk; /* 'fmt ' */ typedef struct {
u_int sc_len; /* length of sub_chunk, =16 */ u_int type; /* 'fmt ' */
u_int length; /* length of chunk */
u_short format; /* should be 1 for PCM-code */ u_short format; /* should be 1 for PCM-code */
u_short modus; /* 1 Mono, 2 Stereo */ u_short modus; /* 1 Mono, 2 Stereo */
u_int sample_fq; /* frequence of sample */ u_int sample_fq; /* frequence of sample */
u_int byte_p_sec; u_int byte_p_sec;
u_short byte_p_spl; /* samplesize; 1 or 2 bytes */ u_short byte_p_spl; /* samplesize; 1 or 2 bytes */
u_short bit_p_spl; /* 8, 12 or 16 bit */ u_short bit_p_spl; /* 8, 12 or 16 bit */
} WaveFmtHeader;
u_int data_chunk; /* 'data' */ typedef struct {
u_int data_length; /* samplecount */ u_int type; /* 'data' */
} WaveHeader; u_int length; /* samplecount */
} WaveChunkHeader;
/* Definitions for Sparc .au header */ /* Definitions for Sparc .au header */