2 Routines for handling .wav files
4 Part of the swftools package.
6 Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
32 int getWAVBlock(FILE*fi, struct WAVBlock*block)
36 if(fread(block->id,1,4,fi)<4)
41 block->size = b[0]|b[1]<<8|b[2]<<16|b[3]<<24;
42 /*printf("Chunk: [%c%c%c%c] (%d bytes)\n",
43 block->id[0],block->id[1],
44 block->id[2],block->id[3],
49 int wav_read(struct WAV*wav, char* filename)
51 FILE*fi = fopen(filename, "rb");
54 struct WAVBlock block;
58 fseek(fi, 0, SEEK_END);
60 fseek(fi, 0, SEEK_SET);
62 //printf("Filesize: %d\n", filesize);
64 if(!getWAVBlock (fi, &block))
66 if(strncmp(block.id,"RIFF",4)) {
67 fprintf(stderr, "wav_read: not a WAV file\n");
70 if(block.size + 8 < filesize)
71 fprintf(stderr, "wav_read: warning - more tags (%d extra bytes)\n",
72 filesize - block.size - 8);
74 if(block.size == filesize) {
75 /* some buggy software doesn't generate the right tag length */
76 block.size = filesize - 8;
79 if(block.size + 8 > filesize)
80 fprintf(stderr, "wav_read: warning - short file (%d bytes missing)\n",
81 block.size + 8 - filesize);
82 if(fread(b, 1, 4, fi) < 4) {
85 if(strncmp(b, "WAVE", 4)) {
86 fprintf(stderr, "wav_read: not a WAV file (2)\n");
92 getWAVBlock(fi, &block);
94 if(!strncmp(block.id, "fmt ", 4)) {
95 if(fread(&b, 1, 16, fi)<16)
97 wav->tag = b[0]|b[1]<<8;
98 wav->channels = b[2]|b[3]<<8;
99 wav->sampsPerSec = b[4]|b[5]<<8|b[6]<<16|b[7]<<24;
100 wav->bytesPerSec = b[8]|b[9]<<8|b[10]<<16|b[11]<<24;
101 wav->align = b[12]|b[13]<<8;
102 wav->bps = b[14]|b[15]<<8;
103 } else if (!strncmp(block.id, "LIST", 4)) {
104 // subchunk ICMT (comment) may exist
105 } else if (!strncmp(block.id, "data", 4)) {
107 wav->data = malloc(block.size);
109 fprintf(stderr, "Out of memory (%d bytes needed)", block.size);
112 l = fread(wav->data, 1, block.size, fi);
114 fprintf(stderr, "Error while reading data block of size %d (%d bytes missing)", block.size, block.size-l);
117 wav->size = block.size;
120 fseek(fi, pos, SEEK_SET);
122 while (pos < filesize);
127 int wav_write(struct WAV*wav, char*filename)
129 FILE*fi = fopen(filename, "wb");
130 char*b="RIFFWAVEfmt \x10\0\0\0data";
132 unsigned long int w32;
136 w32=(/*fmt*/8+0x10+/*data*/8+wav->size);
142 fwrite(&b[4], 12, 1, fi);
145 c[2] = wav->channels;
146 c[3] = wav->channels>>8;
147 c[4] = wav->sampsPerSec;
148 c[5] = wav->sampsPerSec>>8;
149 c[6] = wav->sampsPerSec>>16;
150 c[7] = wav->sampsPerSec>>24;
151 c[8] = wav->bytesPerSec;
152 c[9] = wav->bytesPerSec>>8;
153 c[10] = wav->bytesPerSec>>16;
154 c[11] = wav->bytesPerSec>>24;
156 c[13] = wav->align>>8;
159 fwrite(c, 16, 1, fi);
160 fwrite(&b[16], 4, 1, fi);
163 c[2] = wav->size>>16;
164 c[3] = wav->size>>24;
166 printf("writing %d converted bytes\n", wav->size);
167 fwrite(wav->data,wav->size,1,fi);
172 void wav_print(struct WAV*wav)
174 printf("tag:%04x channels:%d samples/sec:%d bytes/sec:%d align:%d bits/sample:%d size:%d\n",
175 wav->tag, wav->channels, wav->sampsPerSec, wav->bytesPerSec,
176 wav->align, wav->bps, wav->size);
179 int wav_convert2mono(struct WAV*src, struct WAV*dest, int rate)
181 int samplelen=src->size/src->align;
186 int channels=src->channels;
190 dest->sampsPerSec = rate;
194 dest->tag = src->tag;
195 dest->bytesPerSec = dest->sampsPerSec*dest->align;
197 ratio = (double)dest->sampsPerSec/(double)src->sampsPerSec;
198 fill = (int)(ratio+1)*2;
200 dest->data = (unsigned char*)malloc((int)(samplelen*ratio*2)+128);
203 dest->size = (int)(samplelen*ratio)*2;
207 for(i=0; i<src->size; i+=channels) {
208 int pos2 = ((int)pos)*2;
209 dest->data[pos2] = 0;
210 dest->data[pos2+1] = src->data[i]+128;
214 for(i=0; i<src->size; i+=channels) {
216 int pos2 = ((int)pos)*2;
217 for(j=0;j<fill;j+=2) {
218 dest->data[pos2+j+0] = 0;
219 dest->data[pos2+j+1] = src->data[i]+128;
224 } else if(bps == 16) {
226 for(i=0; i<src->size/2; i+=channels) {
227 int pos2 = ((int)pos)*2;
228 dest->data[pos2+0]=src->data[i*2];
229 dest->data[pos2+1]=src->data[i*2+1];
233 for(i=0; i<src->size/2; i+=channels) {
235 int pos2 = ((int)pos)*2;
236 for(j=0;j<fill;j+=2) {
237 dest->data[pos2+j+0] = src->data[i*2];
238 dest->data[pos2+j+1] = src->data[i*2+1];
243 } else if(bps == 32) {
245 for(i=0; i<src->size/4; i+=channels) {
246 int pos2 = ((int)pos)*2;
247 dest->data[pos2+0]=src->data[i*4+2];
248 dest->data[pos2+1]=src->data[i*4+3];
252 for(i=0; i<src->size/4; i+=channels) {
254 int pos2 = ((int)pos)*2;
255 for(j=0;j<fill;j+=2) {
256 dest->data[pos2+j+0] = src->data[i*4+2];
257 dest->data[pos2+j+1] = src->data[i*4+3];
263 fprintf(stderr, "Unsupported bitspersample value: %d\n", bps);