Fixed a typo and removed an old warning from speexenc. Also, using more useful
[opus.git] / tools / wav_io.c
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
43 int read_wav_header(FILE *file, int *rate, int *channels, int *format, celt_int32_t *size)
44 {
45    char ch[5];
46    celt_int32_t itmp;
47    celt_int16_t stmp;
48    celt_int32_t bpersec;
49    celt_int16_t 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
185 void write_wav_header(FILE *file, int rate, int channels, int format, int size)
186 {
187    char ch[5];
188    celt_int32_t itmp;
189    celt_int16_t 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 }