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
, const char* filename
)
51 FILE*fi
= fopen(filename
, "rb");
54 struct WAVBlock block
;
59 fseek(fi
, 0, SEEK_END
);
61 fseek(fi
, 0, SEEK_SET
);
63 //printf("Filesize: %d\n", filesize);
65 if(!getWAVBlock (fi
, &block
))
70 if(strncmp(block
.id
,"RIFF",4))
72 fprintf(stderr
, "wav_read: not a WAV file\n");
76 if(block
.size
+ 8 < filesize
)
77 fprintf(stderr
, "wav_read: warning - more tags (%lu extra bytes)\n", filesize
- block
.size
- 8);
79 if(block
.size
== filesize
)
80 /* some buggy software doesn't generate the right tag length */
81 block
.size
= filesize
- 8;
83 if(block
.size
+ 8 > filesize
)
84 fprintf(stderr
, "wav_read: warning - short file (%lu bytes missing)\n", block
.size
+ 8 - filesize
);
85 if(fread(b
, 1, 4, fi
) < 4)
90 if(strncmp((const char*)b
, "WAVE", 4))
92 fprintf(stderr
, "wav_read: not a WAV file (2)\n");
99 getWAVBlock(fi
, &block
);
101 if(!strncmp(block
.id
, "fmt ", 4))
103 if(fread(&b
, 1, 16, fi
)<16)
108 wav
->tag
= b
[0]|b
[1]<<8;
109 wav
->channels
= b
[2]|b
[3]<<8;
110 wav
->sampsPerSec
= b
[4]|b
[5]<<8|b
[6]<<16|b
[7]<<24;
111 wav
->bytesPerSec
= b
[8]|b
[9]<<8|b
[10]<<16|b
[11]<<24;
112 wav
->align
= b
[12]|b
[13]<<8;
113 wav
->bps
= b
[14]|b
[15]<<8;
116 if (!strncmp(block
.id
, "LIST", 4))
118 // subchunk ICMT (comment) may exist
121 if (!strncmp(block
.id
, "data", 4))
124 wav
->data
= (unsigned char*)malloc(block
.size
);
127 fprintf(stderr
, "Out of memory (%d bytes needed)", block
.size
);
131 l
= fread(wav
->data
, 1, block
.size
, fi
);
133 fprintf(stderr
, "Error: Couldn't read WAV data block\n");
136 } else if(l
< block
.size
)
138 fprintf(stderr
, "Warning: data block of size %d is only %d bytes (%d bytes missing)\n", block
.size
, l
, block
.size
-l
);
141 wav
->size
= block
.size
;
145 fseek(fi
, pos
, SEEK_SET
);
147 while (pos
< filesize
);
152 int wav_write(struct WAV
*wav
, const char*filename
)
154 FILE*fi
= fopen(filename
, "wb");
155 char*b
="RIFFWAVEfmt \x10\0\0\0data";
157 unsigned long int w32
;
161 w32
=(/*fmt*/8+0x10+/*data*/8+wav
->size
);
167 fwrite(&b
[4], 12, 1, fi
);
170 c
[2] = wav
->channels
;
171 c
[3] = wav
->channels
>>8;
172 c
[4] = wav
->sampsPerSec
;
173 c
[5] = wav
->sampsPerSec
>>8;
174 c
[6] = wav
->sampsPerSec
>>16;
175 c
[7] = wav
->sampsPerSec
>>24;
176 c
[8] = wav
->bytesPerSec
;
177 c
[9] = wav
->bytesPerSec
>>8;
178 c
[10] = wav
->bytesPerSec
>>16;
179 c
[11] = wav
->bytesPerSec
>>24;
181 c
[13] = wav
->align
>>8;
184 fwrite(c
, 16, 1, fi
);
185 fwrite(&b
[16], 4, 1, fi
);
188 c
[2] = wav
->size
>>16;
189 c
[3] = wav
->size
>>24;
191 printf("writing %d converted bytes\n", wav
->size
);
192 fwrite(wav
->data
,wav
->size
,1,fi
);
197 void wav_print(struct WAV
*wav
)
199 printf("tag:%04x channels:%d samples/sec:%lu bytes/sec:%lu align:%d bits/sample:%d size:%d\n",
200 wav
->tag
, wav
->channels
, wav
->sampsPerSec
, wav
->bytesPerSec
,
201 wav
->align
, wav
->bps
, wav
->size
);
204 int wav_convert2mono(struct WAV
*src
, struct WAV
*dest
, int rate
)
206 int samplelen
=src
->size
/src
->align
;
211 int channels
=src
->channels
;
215 dest
->sampsPerSec
= rate
;
219 dest
->tag
= src
->tag
;
220 dest
->bytesPerSec
= dest
->sampsPerSec
*dest
->align
;
222 ratio
= (double)dest
->sampsPerSec
/(double)src
->sampsPerSec
;
223 fill
= (int)(ratio
+1)*2;
225 dest
->data
= (unsigned char*)malloc((int)(samplelen
*ratio
*2)+128);
228 dest
->size
= (int)(samplelen
*ratio
)*2;
232 for(i
=0; i
<src
->size
; i
+=channels
) {
233 int pos2
= ((int)pos
)*2;
234 dest
->data
[pos2
] = 0;
235 dest
->data
[pos2
+1] = src
->data
[i
]+128;
239 for(i
=0; i
<src
->size
; i
+=channels
) {
241 int pos2
= ((int)pos
)*2;
242 for(j
=0;j
<fill
;j
+=2) {
243 dest
->data
[pos2
+j
+0] = 0;
244 dest
->data
[pos2
+j
+1] = src
->data
[i
]+128;
249 } else if(bps
== 16) {
251 for(i
=0; i
<src
->size
/2; i
+=channels
) {
252 int pos2
= ((int)pos
)*2;
253 dest
->data
[pos2
+0]=src
->data
[i
*2];
254 dest
->data
[pos2
+1]=src
->data
[i
*2+1];
258 for(i
=0; i
<src
->size
/2; i
+=channels
) {
260 int pos2
= ((int)pos
)*2;
261 for(j
=0;j
<fill
;j
+=2) {
262 dest
->data
[pos2
+j
+0] = src
->data
[i
*2];
263 dest
->data
[pos2
+j
+1] = src
->data
[i
*2+1];
268 } else if(bps
== 32) {
270 for(i
=0; i
<src
->size
/4; i
+=channels
) {
271 int pos2
= ((int)pos
)*2;
272 dest
->data
[pos2
+0]=src
->data
[i
*4+2];
273 dest
->data
[pos2
+1]=src
->data
[i
*4+3];
277 for(i
=0; i
<src
->size
/4; i
+=channels
) {
279 int pos2
= ((int)pos
)*2;
280 for(j
=0;j
<fill
;j
+=2) {
281 dest
->data
[pos2
+j
+0] = src
->data
[i
*4+2];
282 dest
->data
[pos2
+j
+1] = src
->data
[i
*4+3];
288 fprintf(stderr
, "Unsupported bitspersample value: %d\n", bps
);