Integrated "ultra-wideband" with encoder/decoder.
[speexdsp.git] / src / 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 #include <stdio.h>
34 #include <string.h>
35 #include "misc.h"
36
37 int read_wav_header(FILE *file, int *rate, int *channels, int *format, int *size)
38 {
39    char ch[5];
40    int itmp;
41    short stmp;
42    int bpersec;
43    short balign;
44
45    ch[4]=0;
46    fread(ch, 1, 4, file);
47    if (strcmp(ch, "RIFF")!=0)
48    {
49       fseek(file, 0, SEEK_SET);
50       return 0;
51    }
52
53    fread(&itmp, 4, 1, file);
54    *size = le_int(itmp-36);
55
56    fread(ch, 1, 4, file);
57    if (strcmp(ch, "WAVE")!=0)
58    {
59       fprintf (stderr, "RIFF file is not a WAVE file\n");
60       return -1;
61    }
62
63    fread(ch, 1, 4, file);
64    if (strcmp(ch, "fmt ")!=0)
65    {
66       fprintf (stderr, "Corrupted WAVE file: no \"fmt \"\n");
67       return -1;
68    }
69    
70    fread(&itmp, 4, 1, file);
71    itmp = le_int(itmp);
72    if (itmp!=16)
73    {
74       fprintf (stderr, "Unsupported WAVE file fmt chunk, not PCM?\n");
75       return -1;
76    }
77
78    fread(&stmp, 2, 1, file);
79    stmp = le_short(stmp);
80    if (stmp!=1)
81    {
82       fprintf (stderr, "Only PCM encoding is supported\n");
83       return -1;
84    }
85
86    fread(&stmp, 2, 1, file);
87    stmp = le_short(stmp);
88    *channels = stmp;
89    
90    if (stmp>1)
91    {
92       fprintf (stderr, "Only mono supported for now\n");
93       return -1;
94    }
95
96    fread(&itmp, 4, 1, file);
97    itmp = le_int(itmp);
98    *rate = itmp;
99    if (*rate != 8000 && *rate != 16000 && *rate != 11025 && *rate != 22050 && *rate != 32000 && *rate != 44100 && *rate != 48000)
100    {
101       fprintf (stderr, "Only 8 kHz (narrowband) and 16 kHz (wideband) supported (plus 11.025 kHz and 22.05 kHz, but your mileage may vary)\n");
102       return -1;
103    }
104
105    fread(&itmp, 4, 1, file);
106    bpersec = le_int(itmp);
107
108    fread(&stmp, 2, 1, file);
109    balign = le_short(stmp);
110
111    fread(&stmp, 2, 1, file);
112    stmp = le_short(stmp);
113    if (stmp!=16 && stmp!=8)
114    {
115       fprintf (stderr, "Only 8/16-bit linear supported\n");
116       return -1;
117    }
118    *format=stmp;
119
120    if (bpersec!=*rate**channels*stmp/8)
121    {
122       fprintf (stderr, "Corrupted header: ByteRate mismatch\n");
123       return -1;
124    }
125
126    if (balign!=*channels*stmp/8)
127    {
128       fprintf (stderr, "Corrupted header: BlockAlign mismatch\n");
129       return -1;
130    }
131
132    fread(ch, 1, 4, file);
133    if (strcmp(ch, "data")!=0)
134    {
135       fprintf (stderr, "Corrupted WAVE file: no \"data\"\n");
136       return -1;
137    }
138
139    /*Ignore this for now*/
140    fread(&itmp, 4, 1, file);
141    itmp = le_int(itmp);
142
143
144    return 1;
145 }
146
147
148
149 void write_wav_header(FILE *file, int rate, int channels, int format, int size)
150 {
151    char ch[5];
152    int itmp;
153    short stmp;
154
155    ch[4]=0;
156
157    fprintf (file, "RIFF");
158
159    itmp = 0x7fffffff;
160    fwrite(&itmp, 4, 1, file);
161
162    fprintf (file, "WAVEfmt ");
163
164    itmp = le_int(16);
165    fwrite(&itmp, 4, 1, file);
166
167    stmp = le_short(1);
168    fwrite(&stmp, 2, 1, file);
169
170    stmp = le_short(channels);
171    fwrite(&stmp, 2, 1, file);
172
173    itmp = le_int(rate);
174    fwrite(&itmp, 4, 1, file);
175
176    itmp = le_int(rate*channels*2);
177    fwrite(&itmp, 4, 1, file);
178
179    stmp = le_short(2*channels);
180    fwrite(&stmp, 2, 1, file);
181
182    stmp = le_short(16);
183    fwrite(&stmp, 2, 1, file);
184
185    fprintf (file, "data");
186
187    itmp = le_int(0x7fffffff);
188    fwrite(&itmp, 4, 1, file);
189
190
191 }