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 */
20 int getWAVBlock(FILE*fi, struct WAVBlock*block)
24 if(fread(block->id,1,4,fi)<4)
28 block->size = b[0]|b[1]<<8|b[2]<<16|b[3]<<24;
29 /*printf("Chunk: [%c%c%c%c] (%d bytes)\n",
30 block->id[0],block->id[1],
31 block->id[2],block->id[3],
36 int readWAV(char* filename, struct WAV*wav)
38 FILE*fi = fopen(filename, "rb");
41 struct WAVBlock block;
45 fseek(fi, 0, SEEK_END);
47 fseek(fi, 0, SEEK_SET);
49 //printf("Filesize: %d\n", filesize);
51 if(!getWAVBlock (fi, &block))
53 if(strncmp(block.id,"RIFF",4)) {
54 fprintf(stderr, "readWAV: not a wav file\n");
57 if(block.size + 8 < filesize)
58 fprintf(stderr, "readWAV: warning - more tags (%d extra bytes)\n",
59 filesize - block.size - 8);
60 if(block.size + 8 > filesize)
61 fprintf(stderr, "readWAV: warning - short file (%d bytes missing)\n",
62 block.size + 8 - filesize);
63 if(fread(b, 1, 4, fi) < 4) {
66 if(strncmp(b, "WAVE", 4)) {
67 fprintf(stderr, "readWAV: not a WAV file (2)\n");
73 getWAVBlock(fi, &block);
75 if(!strncmp(block.id, "fmt ", 4)) {
76 if(fread(&b, 1, 16, fi)<16)
78 wav->tag = b[0]|b[1]<<8;
79 wav->channels = b[2]|b[3]<<8;
80 wav->sampsPerSec = b[4]|b[5]<<8|b[6]<<16|b[7]<<24;
81 wav->bytesPerSec = b[8]|b[9]<<8|b[10]<<16|b[11]<<24;
82 wav->align = b[12]|b[13]<<8;
83 wav->bps = b[14]|b[15]<<8;
84 } else if (!strncmp(block.id, "LIST", 4)) {
85 // subchunk ICMT (comment) may exist
86 } else if (!strncmp(block.id, "data", 4)) {
87 wav->data = malloc(block.size);
89 fprintf(stderr, "Out of memory (%d bytes needed)", block.size);
92 if(fread(wav->data, 1, block.size, fi) < block.size)
94 wav->size = block.size;
97 fseek(fi, pos, SEEK_SET);
99 while (pos < filesize);
104 int writeWAV(char*filename, struct WAV*wav)
106 FILE*fi = fopen(filename, "wb");
107 char*b="RIFFWAVEfmt \x10\0\0\0data";
109 unsigned long int w32;
113 w32=(/*fmt*/8+0x10+/*data*/8+wav->size);
119 fwrite(&b[4], 12, 1, fi);
122 c[2] = wav->channels;
123 c[3] = wav->channels>>8;
124 c[4] = wav->sampsPerSec;
125 c[5] = wav->sampsPerSec>>8;
126 c[6] = wav->sampsPerSec>>16;
127 c[7] = wav->sampsPerSec>>24;
128 c[8] = wav->bytesPerSec;
129 c[9] = wav->bytesPerSec>>8;
130 c[10] = wav->bytesPerSec>>16;
131 c[11] = wav->bytesPerSec>>24;
133 c[13] = wav->align>>8;
136 fwrite(c, 16, 1, fi);
137 fwrite(&b[16], 4, 1, fi);
140 c[2] = wav->size>>16;
141 c[3] = wav->size>>24;
143 printf("writing %d converted bytes\n", wav->size);
144 fwrite(wav->data,wav->size,1,fi);
149 void printWAVInfo(struct WAV*wav)
151 printf("tag:%04x channels:%d samples/sec:%d bytes/sec:%d align:%d bits/sample:%d size:%d\n",
152 wav->tag, wav->channels, wav->sampsPerSec, wav->bytesPerSec,
153 wav->align, wav->bps, wav->size);
156 int convertWAV2mono(struct WAV*src, struct WAV*dest, int rate)
158 int samplelen=src->size/src->align;
163 int channels=src->channels;
167 dest->sampsPerSec = rate;
171 dest->tag = src->tag;
172 dest->bytesPerSec = dest->sampsPerSec*dest->align;
174 ratio = (double)dest->sampsPerSec/(double)src->sampsPerSec;
175 fill = (int)(ratio+1)*2;
177 dest->data = (unsigned char*)malloc((int)(samplelen*ratio*2)+128);
180 dest->size = (int)(samplelen*ratio)*2;
184 for(i=0; i<src->size; i+=channels) {
185 int pos2 = ((int)pos)*2;
186 dest->data[pos2] = 0;
187 dest->data[pos2+1] = src->data[i]+128;
191 for(i=0; i<src->size; i+=channels) {
193 int pos2 = ((int)pos)*2;
194 for(j=0;j<fill;j+=2) {
195 dest->data[pos2+j+0] = 0;
196 dest->data[pos2+j+1] = src->data[i]+128;
201 } else if(bps == 16) {
203 for(i=0; i<src->size/2; i+=channels) {
204 int pos2 = ((int)pos)*2;
205 dest->data[pos2+0]=src->data[i*2];
206 dest->data[pos2+1]=src->data[i*2+1];
210 for(i=0; i<src->size/2; i+=channels) {
212 int pos2 = ((int)pos)*2;
213 for(j=0;j<fill;j+=2) {
214 dest->data[pos2+j+0] = src->data[i*2];
215 dest->data[pos2+j+1] = src->data[i*2+1];
220 } else if(bps == 32) {
222 for(i=0; i<src->size/4; i+=channels) {
223 int pos2 = ((int)pos)*2;
224 dest->data[pos2+0]=src->data[i*4+2];
225 dest->data[pos2+1]=src->data[i*4+3];
229 for(i=0; i<src->size/4; i+=channels) {
231 int pos2 = ((int)pos)*2;
232 for(j=0;j<fill;j+=2) {
233 dest->data[pos2+j+0] = src->data[i*4+2];
234 dest->data[pos2+j+1] = src->data[i*4+3];