1 /* Copyright (C) 2002 Jean-Marc Valin
2 File: wav_io.c
3 Routines to handle wav (RIFF) headers
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 - Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 - Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16 - Neither the name of the Xiph.org Foundation nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
24 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <stdio.h>
38 #include <string.h>
39 #include "celt_types.h"
40 #include "wav_io.h"
41
42
read_wav_header(FILE * file,int * rate,int * channels,int * format,celt_int32 * size)43 int read_wav_header(FILE *file, int *rate, int *channels, int *format, celt_int32 *size)
44 {
45 char ch[5];
46 celt_int32 itmp;
47 celt_int16 stmp;
48 celt_int32 bpersec;
49 celt_int16 balign;
50 int skip_bytes;
51 int i;
52
53 ch[4]=0;
54 #if 0
55 fread(ch, 1, 4, file);
56 if (strcmp(ch, "RIFF")!=0)
57 {
58 fseek(file, 0, SEEK_SET);
59 return 0;
60 }
61
62 fread(&itmp, 4, 1, file);
63 *size = le_int(itmp-36);
64
65 fread(ch, 1, 4, file);
66 if (strcmp(ch, "WAVE")!=0)
67 {
68 fprintf (stderr, "RIFF file is not a WAVE file\n");
69 return -1;
70 }
71 #endif
72 fread(ch, 1, 4, file);
73 while (strcmp(ch, "fmt ")!=0)
74 {
75 fread(&itmp, 4, 1, file);
76 itmp = le_int(itmp);
77 /*fprintf (stderr, "skip=%d\n", itmp);*/
78 /*strange way of seeking, but it works even for pipes*/
79 for (i=0;i<itmp;i++)
80 fgetc(file);
81 /*fseek(file, itmp, SEEK_CUR);*/
82 fread(ch, 1, 4, file);
83 if (feof(file))
84 {
85 fprintf (stderr, "Corrupted WAVE file: no \"fmt \"\n");
86 return -1;
87 }
88 }
89 /*if (strcmp(ch, "fmt ")!=0)
90 {
91 fprintf (stderr, "Corrupted WAVE file: no \"fmt \"\n");
92 return -1;
93 }*/
94
95 fread(&itmp, 4, 1, file);
96 itmp = le_int(itmp);
97 skip_bytes=itmp-16;
98 /*fprintf (stderr, "skip=%d\n", skip_bytes);*/
99
100 fread(&stmp, 2, 1, file);
101 stmp = le_short(stmp);
102 if (stmp!=1)
103 {
104 fprintf (stderr, "Only PCM encoding is supported\n");
105 return -1;
106 }
107
108 fread(&stmp, 2, 1, file);
109 stmp = le_short(stmp);
110 *channels = stmp;
111
112 if (stmp>2)
113 {
114 fprintf (stderr, "Only mono and (intensity) stereo supported\n");
115 return -1;
116 }
117
118 fread(&itmp, 4, 1, file);
119 itmp = le_int(itmp);
120 *rate = itmp;
121
122 fread(&itmp, 4, 1, file);
123 bpersec = le_int(itmp);
124
125 fread(&stmp, 2, 1, file);
126 balign = le_short(stmp);
127
128 fread(&stmp, 2, 1, file);
129 stmp = le_short(stmp);
130 if (stmp!=16 && stmp!=8)
131 {
132 fprintf (stderr, "Only 8/16-bit linear supported\n");
133 return -1;
134 }
135 *format=stmp;
136
137 if (bpersec!=*rate**channels*stmp/8)
138 {
139 fprintf (stderr, "Corrupted header: ByteRate mismatch\n");
140 return -1;
141 }
142
143 if (balign!=*channels*stmp/8)
144 {
145 fprintf (stderr, "Corrupted header: BlockAlign mismatch\n");
146 return -1;
147 }
148
149
150 /*strange way of seeking, but it works even for pipes*/
151 if (skip_bytes>0)
152 for (i=0;i<skip_bytes;i++)
153 fgetc(file);
154
155 /*fseek(file, skip_bytes, SEEK_CUR);*/
156
157 fread(ch, 1, 4, file);
158 while (strcmp(ch, "data")!=0)
159 {
160 fread(&itmp, 4, 1, file);
161 itmp = le_int(itmp);
162 /*strange way of seeking, but it works even for pipes*/
163 for (i=0;i<itmp;i++)
164 fgetc(file);
165 /*fseek(file, itmp, SEEK_CUR);*/
166 fread(ch, 1, 4, file);
167 if (feof(file))
168 {
169 fprintf (stderr, "Corrupted WAVE file: no \"data\"\n");
170 return -1;
171 }
172 }
173
174 /*Ignore this for now*/
175 fread(&itmp, 4, 1, file);
176 itmp = le_int(itmp);
177
178 *size=itmp;
179
180 return 1;
181 }
182
183
184
write_wav_header(FILE * file,int rate,int channels,int format,int size)185 void write_wav_header(FILE *file, int rate, int channels, int format, int size)
186 {
187 char ch[5];
188 celt_int32 itmp;
189 celt_int16 stmp;
190
191 ch[4]=0;
192
193 fprintf (file, "RIFF");
194
195 itmp = 0x7fffffff;
196 fwrite(&itmp, 4, 1, file);
197
198 fprintf (file, "WAVEfmt ");
199
200 itmp = le_int(16);
201 fwrite(&itmp, 4, 1, file);
202
203 stmp = le_short(1);
204 fwrite(&stmp, 2, 1, file);
205
206 stmp = le_short(channels);
207 fwrite(&stmp, 2, 1, file);
208
209 itmp = le_int(rate);
210 fwrite(&itmp, 4, 1, file);
211
212 itmp = le_int(rate*channels*2);
213 fwrite(&itmp, 4, 1, file);
214
215 stmp = le_short(2*channels);
216 fwrite(&stmp, 2, 1, file);
217
218 stmp = le_short(16);
219 fwrite(&stmp, 2, 1, file);
220
221 fprintf (file, "data");
222
223 itmp = le_int(0x7fffffff);
224 fwrite(&itmp, 4, 1, file);
225
226
227 }
228