2 Routines for handling .wav files
4 Part of the swftools package.
6 Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
8 This file is distributed under the GPL, see file COPYING for details */
19 int getWAVBlock(FILE*fi, struct WAVBlock*block)
23 if(fread(block->id,1,4,fi)<4)
27 block->size = b[0]|b[1]<<8|b[2]<<16|b[3]<<24;
28 printf("Chunk: [%c%c%c%c] (%d bytes)\n",
29 block->id[0],block->id[1],
30 block->id[2],block->id[3],
35 int readWAV(char* filename, struct WAV*wav)
37 FILE*fi = fopen(filename, "rb");
40 struct WAVBlock block;
44 fseek(fi, 0, SEEK_END);
46 fseek(fi, 0, SEEK_SET);
48 printf("Filesize: %d\n", filesize);
50 if(!getWAVBlock (fi, &block))
52 if(strncmp(block.id,"RIFF",4)) {
53 fprintf(stderr, "readWAV: not a wav file\n");
56 if(block.size + 8 < filesize)
57 fprintf(stderr, "readWAV: warning - more tags (%d extra bytes)\n",
58 filesize - block.size - 8);
59 if(block.size + 8 > filesize)
60 fprintf(stderr, "readWAV: warning - short file (%d bytes missing)\n",
61 block.size + 8 - filesize);
62 if(fread(b, 1, 4, fi) < 4) {
65 if(strncmp(b, "WAVE", 4)) {
66 fprintf(stderr, "readWAV: not a WAV file (2)\n");
72 getWAVBlock(fi, &block);
74 if(!strncmp(block.id, "fmt ", 4)) {
75 if(fread(&b, 1, 16, fi)<16)
77 wav->tag = b[0]|b[1]<<8;
78 wav->channels = b[2]|b[3]<<8;
79 wav->sampsPerSec = b[4]|b[5]<<8|b[6]<<16|b[7]<<24;
80 wav->bytesPerSec = b[8]|b[9]<<8|b[10]<<16|b[11]<<24;
81 wav->align = b[12]|b[13]<<8;
82 wav->bps = b[14]|b[15]<<8;
83 } else if (!strncmp(block.id, "LIST", 4)) {
84 // subchunk ICMT (comment) may exist
85 } else if (!strncmp(block.id, "data", 4)) {
86 wav->data = malloc(block.size);
88 fprintf(stderr, "Out of memory (%d bytes needed)", block.size);
91 if(fread(wav->data, 1, block.size, fi) < block.size)
93 wav->size = block.size;
96 fseek(fi, pos, SEEK_SET);
98 while (pos < filesize);
103 int writeWAV(char*filename, struct WAV*wav)
105 FILE*fi = fopen(filename, "wb");
106 char*b="RIFFWAVEfmt \x10\0\0\0data";
108 unsigned long int w32;
112 w32=(/*fmt*/8+0x10+/*data*/8+wav->size);
118 fwrite(&b[4], 12, 1, fi);
121 c[2] = wav->channels;
122 c[3] = wav->channels>>8;
123 c[4] = wav->sampsPerSec;
124 c[5] = wav->sampsPerSec>>8;
125 c[6] = wav->sampsPerSec>>16;
126 c[7] = wav->sampsPerSec>>24;
127 c[8] = wav->bytesPerSec;
128 c[9] = wav->bytesPerSec>>8;
129 c[10] = wav->bytesPerSec>>16;
130 c[11] = wav->bytesPerSec>>24;
132 c[13] = wav->align>>8;
135 fwrite(c, 16, 1, fi);
136 fwrite(&b[16], 4, 1, fi);
139 c[2] = wav->size>>16;
140 c[3] = wav->size>>24;
142 printf("writing %d converted bytes\n", wav->size);
143 fwrite(wav->data,wav->size,1,fi);
148 void printWAVInfo(struct WAV*wav)
150 printf("tag:%04x channels:%d samples/sec:%d bytes/sec:%d align:%d bits/sample:%d size:%d\n",
151 wav->tag, wav->channels, wav->sampsPerSec, wav->bytesPerSec,
152 wav->align, wav->bps, wav->size);
155 int convertWAV2mono(struct WAV*src, struct WAV*dest, int rate)
157 int samplelen=src->size/src->align;
162 int channels=src->channels;
166 dest->sampsPerSec = rate;
170 dest->tag = src->tag;
171 dest->bytesPerSec = dest->sampsPerSec*dest->align;
173 ratio = (double)dest->sampsPerSec/(double)src->sampsPerSec;
174 fill = (int)(ratio+1)*2;
176 dest->data = (unsigned char*)malloc((int)(samplelen*ratio*2)+128);
179 dest->size = (int)(samplelen*ratio)*2;
183 for(i=0; i<src->size; i+=channels) {
184 int pos2 = ((int)pos)*2;
185 dest->data[pos2] = 0;
186 dest->data[pos2+1] = src->data[i]+128;
190 for(i=0; i<src->size; i+=channels) {
192 int pos2 = ((int)pos)*2;
193 for(j=0;j<fill;j+=2) {
194 dest->data[pos2+j+0] = 0;
195 dest->data[pos2+j+1] = src->data[i]+128;
200 } else if(bps == 16) {
202 for(i=0; i<src->size/2; i+=channels) {
203 int pos2 = ((int)pos)*2;
204 dest->data[pos2+0]=src->data[i*2];
205 dest->data[pos2+1]=src->data[i*2+1];
209 for(i=0; i<src->size/2; i+=channels) {
211 int pos2 = ((int)pos)*2;
212 for(j=0;j<fill;j+=2) {
213 dest->data[pos2+j+0] = src->data[i*2];
214 dest->data[pos2+j+1] = src->data[i*2+1];
219 } else if(bps == 32) {
221 for(i=0; i<src->size/4; i+=channels) {
222 int pos2 = ((int)pos)*2;
223 dest->data[pos2+0]=src->data[i*4+2];
224 dest->data[pos2+1]=src->data[i*4+3];
228 for(i=0; i<src->size/4; i+=channels) {
230 int pos2 = ((int)pos)*2;
231 for(j=0;j<fill;j+=2) {
232 dest->data[pos2+j+0] = src->data[i*4+2];
233 dest->data[pos2+j+1] = src->data[i*4+3];