/src/libsndfile/src/wavlike.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | ** Copyright (C) 1999-2020 Erik de Castro Lopo <erikd@mega-nerd.com> |
3 | | ** Copyright (C) 2004-2005 David Viens <davidv@plogue.com> |
4 | | ** |
5 | | ** This program is free software; you can redistribute it and/or modify |
6 | | ** it under the terms of the GNU Lesser General Public License as published by |
7 | | ** the Free Software Foundation; either version 2.1 of the License, or |
8 | | ** (at your option) any later version. |
9 | | ** |
10 | | ** This program is distributed in the hope that it will be useful, |
11 | | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | ** GNU Lesser General Public License for more details. |
14 | | ** |
15 | | ** You should have received a copy of the GNU Lesser General Public License |
16 | | ** along with this program; if not, write to the Free Software |
17 | | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
18 | | */ |
19 | | |
20 | | #include "sfconfig.h" |
21 | | |
22 | | #include <stdio.h> |
23 | | #include <string.h> |
24 | | #include <ctype.h> |
25 | | #include <time.h> |
26 | | |
27 | | #include "sndfile.h" |
28 | | #include "sfendian.h" |
29 | | #include "common.h" |
30 | | #include "wavlike.h" |
31 | | |
32 | | |
33 | 1.72k | #define WAV_BEXT_MIN_CHUNK_SIZE 602 |
34 | 173 | #define WAV_BEXT_MAX_CHUNK_SIZE (10 * 1024) |
35 | | |
36 | 6.10k | #define WAV_CART_MIN_CHUNK_SIZE 2048 |
37 | 203 | #define WAV_CART_MAX_CHUNK_SIZE 0xffffffff |
38 | | |
39 | | |
40 | | static int exif_subchunk_parse (SF_PRIVATE *psf, uint32_t length) ; |
41 | | |
42 | | |
43 | | /* Known WAVEFORMATEXTENSIBLE GUIDS. */ |
44 | | static const EXT_SUBFORMAT MSGUID_SUBTYPE_PCM = |
45 | | { 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } |
46 | | } ; |
47 | | |
48 | | static const EXT_SUBFORMAT MSGUID_SUBTYPE_MS_ADPCM = |
49 | | { 0x00000002, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } |
50 | | } ; |
51 | | |
52 | | static const EXT_SUBFORMAT MSGUID_SUBTYPE_IEEE_FLOAT = |
53 | | { 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } |
54 | | } ; |
55 | | |
56 | | static const EXT_SUBFORMAT MSGUID_SUBTYPE_ALAW = |
57 | | { 0x00000006, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } |
58 | | } ; |
59 | | |
60 | | static const EXT_SUBFORMAT MSGUID_SUBTYPE_MULAW = |
61 | | { 0x00000007, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } |
62 | | } ; |
63 | | |
64 | | /* |
65 | | ** the next two are from |
66 | | ** http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html |
67 | | */ |
68 | | |
69 | | static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM = |
70 | | { 0x00000001, 0x0721, 0x11d3, { 0x86, 0x44, 0xc8, 0xc1, 0xca, 0x00, 0x00, 0x00 } |
71 | | } ; |
72 | | |
73 | | static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT = |
74 | | { 0x00000003, 0x0721, 0x11d3, { 0x86, 0x44, 0xc8, 0xc1, 0xca, 0x00, 0x00, 0x00 } |
75 | | } ; |
76 | | |
77 | | |
78 | | #if 0 |
79 | | /* maybe interesting one day to read the following through sf_read_raw */ |
80 | | /* http://www.bath.ac.uk/~masrwd/pvocex/pvocex.html */ |
81 | | static const EXT_SUBFORMAT MSGUID_SUBTYPE_PVOCEX = |
82 | | { 0x8312b9c2, 0x2e6e, 0x11d4, { 0xa8, 0x24, 0xde, 0x5b, 0x96, 0xc3, 0xab, 0x21 } |
83 | | } ; |
84 | | #endif |
85 | | |
86 | | /* This stores which bit in dwChannelMask maps to which channel */ |
87 | | static const struct chanmap_s |
88 | | { int id ; |
89 | | const char * name ; |
90 | | } channel_mask_bits [] = |
91 | | { /* WAVEFORMATEXTENSIBLE doesn't distinguish FRONT_LEFT from LEFT */ |
92 | | { SF_CHANNEL_MAP_LEFT, "L" }, |
93 | | { SF_CHANNEL_MAP_RIGHT, "R" }, |
94 | | { SF_CHANNEL_MAP_CENTER, "C" }, |
95 | | { SF_CHANNEL_MAP_LFE, "LFE" }, |
96 | | { SF_CHANNEL_MAP_REAR_LEFT, "Ls" }, |
97 | | { SF_CHANNEL_MAP_REAR_RIGHT, "Rs" }, |
98 | | { SF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER, "Lc" }, |
99 | | { SF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER, "Rc" }, |
100 | | { SF_CHANNEL_MAP_REAR_CENTER, "Cs" }, |
101 | | { SF_CHANNEL_MAP_SIDE_LEFT, "Sl" }, |
102 | | { SF_CHANNEL_MAP_SIDE_RIGHT, "Sr" }, |
103 | | { SF_CHANNEL_MAP_TOP_CENTER, "Tc" }, |
104 | | { SF_CHANNEL_MAP_TOP_FRONT_LEFT, "Tfl" }, |
105 | | { SF_CHANNEL_MAP_TOP_FRONT_CENTER, "Tfc" }, |
106 | | { SF_CHANNEL_MAP_TOP_FRONT_RIGHT, "Tfr" }, |
107 | | { SF_CHANNEL_MAP_TOP_REAR_LEFT, "Trl" }, |
108 | | { SF_CHANNEL_MAP_TOP_REAR_CENTER, "Trc" }, |
109 | | { SF_CHANNEL_MAP_TOP_REAR_RIGHT, "Trr" }, |
110 | | } ; |
111 | | |
112 | | /*------------------------------------------------------------------------------ |
113 | | * Private static functions. |
114 | | */ |
115 | | |
116 | | static int |
117 | | wavex_guid_equal (const EXT_SUBFORMAT * first, const EXT_SUBFORMAT * second) |
118 | 125k | { return !memcmp (first, second, sizeof (EXT_SUBFORMAT)) ; |
119 | 125k | } /* wavex_guid_equal */ |
120 | | |
121 | | |
122 | | |
123 | | int |
124 | | wavlike_read_fmt_chunk (SF_PRIVATE *psf, int fmtsize) |
125 | 160k | { WAVLIKE_PRIVATE * wpriv ; |
126 | 160k | WAV_FMT *wav_fmt ; |
127 | 160k | int bytesread, k, bytespersec = 0 ; |
128 | | |
129 | 160k | if ((wpriv = psf->container_data) == NULL) |
130 | 0 | return SFE_INTERNAL ; |
131 | 160k | wav_fmt = &wpriv->wav_fmt ; |
132 | | |
133 | 160k | memset (wav_fmt, 0, sizeof (WAV_FMT)) ; |
134 | | |
135 | 160k | if (fmtsize < 16) |
136 | 65 | return SFE_WAV_FMT_SHORT ; |
137 | | |
138 | | /* assume psf->rwf_endian is already properly set */ |
139 | | |
140 | | /* Read the minimal WAV file header here. */ |
141 | 160k | bytesread = psf_binheader_readf (psf, "224422", |
142 | 160k | &(wav_fmt->format), &(wav_fmt->min.channels), |
143 | 160k | &(wav_fmt->min.samplerate), &(wav_fmt->min.bytespersec), |
144 | 160k | &(wav_fmt->min.blockalign), &(wav_fmt->min.bitwidth)) ; |
145 | | |
146 | 160k | psf_log_printf (psf, " Format : 0x%X => %s\n", wav_fmt->format, wavlike_format_str (wav_fmt->format)) ; |
147 | 160k | psf_log_printf (psf, " Channels : %d\n", wav_fmt->min.channels) ; |
148 | 160k | psf_log_printf (psf, " Sample Rate : %d\n", wav_fmt->min.samplerate) ; |
149 | | |
150 | 160k | if (wav_fmt->format == WAVE_FORMAT_PCM && wav_fmt->min.blockalign == 0 |
151 | 160k | && wav_fmt->min.bitwidth > 0 && wav_fmt->min.channels > 0) |
152 | 5.72k | { wav_fmt->min.blockalign = wav_fmt->min.bitwidth / 8 + (wav_fmt->min.bitwidth % 8 > 0 ? 1 : 0) ; |
153 | 5.72k | wav_fmt->min.blockalign *= wav_fmt->min.channels ; |
154 | 5.72k | psf_log_printf (psf, " Block Align : 0 (should be %d)\n", wav_fmt->min.blockalign) ; |
155 | 5.72k | } |
156 | 154k | else |
157 | 154k | psf_log_printf (psf, " Block Align : %d\n", wav_fmt->min.blockalign) ; |
158 | | |
159 | 160k | if (wav_fmt->format == WAVE_FORMAT_PCM && wav_fmt->min.bitwidth == 24 && |
160 | 160k | wav_fmt->min.blockalign == 4 * wav_fmt->min.channels) |
161 | 4.10k | { psf_log_printf (psf, " Bit Width : 24\n") ; |
162 | | |
163 | 4.10k | psf_log_printf (psf, "\n" |
164 | 4.10k | " Ambiguous information in 'fmt ' chunk. Possible file types:\n" |
165 | 4.10k | " 0) Invalid IEEE float file generated by Syntrillium's Cooledit!\n" |
166 | 4.10k | " 1) File generated by ALSA's arecord containing 24 bit samples in 32 bit containers.\n" |
167 | 4.10k | " 2) 24 bit file with incorrect Block Align value.\n" |
168 | 4.10k | "\n") ; |
169 | | |
170 | 4.10k | wpriv->fmt_is_broken = 1 ; |
171 | 4.10k | } |
172 | 156k | else if (wav_fmt->min.bitwidth == 0) |
173 | 30.3k | { switch (wav_fmt->format) |
174 | 30.3k | { case WAVE_FORMAT_GSM610 : |
175 | 2.74k | case WAVE_FORMAT_IPP_ITU_G_723_1 : |
176 | 6.96k | case WAVE_FORMAT_MPEGLAYER3 : |
177 | 6.96k | psf_log_printf (psf, " Bit Width : %d\n", wav_fmt->min.bitwidth) ; |
178 | 6.96k | break ; |
179 | 23.3k | default : |
180 | 23.3k | psf_log_printf (psf, " Bit Width : %d (should not be 0)\n", wav_fmt->min.bitwidth) ; |
181 | 30.3k | } |
182 | 30.3k | } |
183 | 126k | else |
184 | 126k | { switch (wav_fmt->format) |
185 | 126k | { case WAVE_FORMAT_GSM610 : |
186 | 6.94k | case WAVE_FORMAT_IPP_ITU_G_723_1 : |
187 | 12.4k | case WAVE_FORMAT_MPEGLAYER3 : |
188 | 12.4k | psf_log_printf (psf, " Bit Width : %d (should be 0)\n", wav_fmt->min.bitwidth) ; |
189 | 12.4k | break ; |
190 | 113k | default : |
191 | 113k | psf_log_printf (psf, " Bit Width : %d\n", wav_fmt->min.bitwidth) ; |
192 | 126k | } |
193 | 160k | } ; |
194 | | |
195 | 160k | psf->sf.samplerate = wav_fmt->min.samplerate ; |
196 | 160k | psf->sf.frames = 0 ; /* Correct this when reading data chunk. */ |
197 | 160k | psf->sf.channels = wav_fmt->min.channels ; |
198 | | |
199 | 160k | switch (wav_fmt->format) |
200 | 160k | { case WAVE_FORMAT_PCM : |
201 | 53.7k | case WAVE_FORMAT_IEEE_FLOAT : |
202 | 53.7k | bytespersec = wav_fmt->min.samplerate * wav_fmt->min.blockalign ; |
203 | 53.7k | if (wav_fmt->min.bytespersec != (unsigned) bytespersec) |
204 | 47.9k | psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->min.bytespersec, bytespersec) ; |
205 | 5.88k | else |
206 | 5.88k | psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->min.bytespersec) ; |
207 | | |
208 | 53.7k | psf->bytewidth = BITWIDTH2BYTES (wav_fmt->min.bitwidth) ; |
209 | 53.7k | break ; |
210 | | |
211 | 9.36k | case WAVE_FORMAT_ALAW : |
212 | 15.0k | case WAVE_FORMAT_MULAW : |
213 | 15.0k | if (wav_fmt->min.bytespersec != wav_fmt->min.samplerate * wav_fmt->min.blockalign) |
214 | 10.7k | psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->min.bytespersec, wav_fmt->min.samplerate * wav_fmt->min.blockalign) ; |
215 | 4.38k | else |
216 | 4.38k | psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->min.bytespersec) ; |
217 | | |
218 | 15.0k | psf->bytewidth = 1 ; |
219 | 15.0k | if (fmtsize >= 18) |
220 | 9.09k | { bytesread += psf_binheader_readf (psf, "2", &(wav_fmt->size20.extrabytes)) ; |
221 | 9.09k | psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->size20.extrabytes) ; |
222 | 9.09k | } ; |
223 | 15.0k | break ; |
224 | | |
225 | 5.17k | case WAVE_FORMAT_IMA_ADPCM : |
226 | 5.17k | if (wav_fmt->min.bitwidth != 4) |
227 | 17 | return SFE_WAV_ADPCM_NOT4BIT ; |
228 | 5.16k | if (wav_fmt->min.channels < 1 || wav_fmt->min.channels > 2) |
229 | 2 | return SFE_WAV_ADPCM_CHANNELS ; |
230 | | |
231 | 5.16k | bytesread += psf_binheader_readf (psf, "22", &(wav_fmt->ima.extrabytes), &(wav_fmt->ima.samplesperblock)) ; |
232 | 5.16k | psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->ima.extrabytes) ; |
233 | 5.16k | if (wav_fmt->ima.samplesperblock < 1) |
234 | 1 | { psf_log_printf (psf, " Samples/Block : %d (should be > 0)\n", wav_fmt->ima.samplesperblock) ; |
235 | 1 | return SFE_WAV_ADPCM_SAMPLES ; |
236 | 1 | } |
237 | 5.15k | else |
238 | 5.15k | psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->ima.samplesperblock) ; |
239 | | |
240 | 5.15k | bytespersec = (wav_fmt->ima.samplerate * wav_fmt->ima.blockalign) / wav_fmt->ima.samplesperblock ; |
241 | 5.15k | if (wav_fmt->ima.bytespersec != (unsigned) bytespersec) |
242 | 2.32k | psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->ima.bytespersec, bytespersec) ; |
243 | 2.83k | else |
244 | 2.83k | psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->ima.bytespersec) ; |
245 | | |
246 | 5.15k | break ; |
247 | | |
248 | 13.6k | case WAVE_FORMAT_MS_ADPCM : |
249 | 13.6k | if (wav_fmt->msadpcm.bitwidth != 4) |
250 | 6 | return SFE_WAV_ADPCM_NOT4BIT ; |
251 | 13.6k | if (wav_fmt->msadpcm.channels < 1 || wav_fmt->msadpcm.channels > 2) |
252 | 13 | return SFE_WAV_ADPCM_CHANNELS ; |
253 | | |
254 | 13.6k | bytesread += psf_binheader_readf (psf, "222", &(wav_fmt->msadpcm.extrabytes), |
255 | 13.6k | &(wav_fmt->msadpcm.samplesperblock), &(wav_fmt->msadpcm.numcoeffs)) ; |
256 | | |
257 | 13.6k | psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->msadpcm.extrabytes) ; |
258 | 13.6k | if (wav_fmt->ima.samplesperblock < 1) |
259 | 2 | { psf_log_printf (psf, " Samples/Block : %d (should be > 0)\n", wav_fmt->ima.samplesperblock) ; |
260 | 2 | return SFE_WAV_ADPCM_SAMPLES ; |
261 | 2 | } |
262 | 13.6k | else |
263 | 13.6k | psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->ima.samplesperblock) ; |
264 | | |
265 | 13.6k | bytespersec = (wav_fmt->min.samplerate * wav_fmt->min.blockalign) / wav_fmt->msadpcm.samplesperblock ; |
266 | 13.6k | if (wav_fmt->min.bytespersec == (unsigned) bytespersec) |
267 | 3.45k | psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->min.bytespersec) ; |
268 | 10.2k | else if (wav_fmt->min.bytespersec == (wav_fmt->min.samplerate / wav_fmt->msadpcm.samplesperblock) * wav_fmt->min.blockalign) |
269 | 4.89k | psf_log_printf (psf, " Bytes/sec : %d (should be %d (MS BUG!))\n", wav_fmt->min.bytespersec, bytespersec) ; |
270 | 5.31k | else |
271 | 5.31k | psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->min.bytespersec, bytespersec) ; |
272 | | |
273 | 13.6k | if (wav_fmt->msadpcm.numcoeffs > ARRAY_LEN (wav_fmt->msadpcm.coeffs)) |
274 | 3.20k | { psf_log_printf (psf, " No. of Coeffs : %d (should be <= %d)\n", wav_fmt->msadpcm.numcoeffs, ARRAY_LEN (wav_fmt->msadpcm.coeffs)) ; |
275 | 3.20k | wav_fmt->msadpcm.numcoeffs = ARRAY_LEN (wav_fmt->msadpcm.coeffs) ; |
276 | 3.20k | } |
277 | 10.4k | else |
278 | 10.4k | psf_log_printf (psf, " No. of Coeffs : %d\n", wav_fmt->msadpcm.numcoeffs) ; |
279 | | |
280 | 13.6k | psf_log_printf (psf, " Index Coeffs1 Coeffs2\n") ; |
281 | 41.5k | for (k = 0 ; k < wav_fmt->msadpcm.numcoeffs ; k++) |
282 | 27.9k | { char buffer [128] ; |
283 | | |
284 | 27.9k | bytesread += |
285 | 27.9k | psf_binheader_readf (psf, "22", &(wav_fmt->msadpcm.coeffs [k].coeff1), &(wav_fmt->msadpcm.coeffs [k].coeff2)) ; |
286 | 27.9k | snprintf (buffer, sizeof (buffer), " %2d %7d %7d\n", k, wav_fmt->msadpcm.coeffs [k].coeff1, wav_fmt->msadpcm.coeffs [k].coeff2) ; |
287 | 27.9k | psf_log_printf (psf, buffer) ; |
288 | 27.9k | } ; |
289 | 13.6k | break ; |
290 | | |
291 | 9.68k | case WAVE_FORMAT_GSM610 : |
292 | 9.68k | if (wav_fmt->gsm610.channels != 1 || wav_fmt->gsm610.blockalign != 65) |
293 | 16 | return SFE_WAV_GSM610_FORMAT ; |
294 | | |
295 | 9.66k | bytesread += |
296 | 9.66k | psf_binheader_readf (psf, "22", &(wav_fmt->gsm610.extrabytes), &(wav_fmt->gsm610.samplesperblock)) ; |
297 | | |
298 | 9.66k | if (wav_fmt->gsm610.samplesperblock != 320) |
299 | 2 | return SFE_WAV_GSM610_FORMAT ; |
300 | | |
301 | 9.66k | bytespersec = (wav_fmt->gsm610.samplerate * wav_fmt->gsm610.blockalign) / wav_fmt->gsm610.samplesperblock ; |
302 | 9.66k | if (wav_fmt->gsm610.bytespersec != (unsigned) bytespersec) |
303 | 7.52k | psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->gsm610.bytespersec, bytespersec) ; |
304 | 2.14k | else |
305 | 2.14k | psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->gsm610.bytespersec) ; |
306 | | |
307 | 9.66k | psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->gsm610.extrabytes) ; |
308 | 9.66k | psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->gsm610.samplesperblock) ; |
309 | 9.66k | break ; |
310 | | |
311 | 9.71k | case WAVE_FORMAT_MPEGLAYER3 : |
312 | 9.71k | bytesread += psf_binheader_readf (psf, "24222", &(wav_fmt->mpeg3.extrabytes), |
313 | 9.71k | &(wav_fmt->mpeg3.id), &(wav_fmt->mpeg3.flags), &(wav_fmt->mpeg3.blocksize), |
314 | 9.71k | &(wav_fmt->mpeg3.samplesperblock), &(wav_fmt->mpeg3.codecdelay)) ; |
315 | | |
316 | 9.71k | psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->mpeg3.bytespersec) ; |
317 | 9.71k | psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->mpeg3.extrabytes) ; |
318 | 9.71k | if (wav_fmt->mpeg3.id != 1) |
319 | 7.09k | psf_log_printf (psf, " ID : %d (unknown, should be 1)\n", wav_fmt->mpeg3.id) ; |
320 | 2.61k | else |
321 | 2.61k | psf_log_printf (psf, " ID : MPEGLAYER3_ID_MPEG\n") ; |
322 | 9.71k | psf_log_printf (psf, " Flags : 0x%08x\n", wav_fmt->mpeg3.flags) ; |
323 | 9.71k | psf_log_printf (psf, " Block Size : %d\n", wav_fmt->mpeg3.blocksize) ; |
324 | 9.71k | psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->mpeg3.samplesperblock) ; |
325 | 9.71k | psf_log_printf (psf, " Codec Delay : %d samples\n", wav_fmt->mpeg3.codecdelay) ; |
326 | 9.71k | break ; |
327 | | |
328 | 30.4k | case WAVE_FORMAT_EXTENSIBLE : |
329 | 30.4k | if (wav_fmt->ext.bytespersec != wav_fmt->ext.samplerate * wav_fmt->ext.blockalign) |
330 | 23.8k | psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->ext.bytespersec, wav_fmt->ext.samplerate * wav_fmt->ext.blockalign) ; |
331 | 6.63k | else |
332 | 6.63k | psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->ext.bytespersec) ; |
333 | | |
334 | 30.4k | bytesread += |
335 | 30.4k | psf_binheader_readf (psf, "224", &(wav_fmt->ext.extrabytes), &(wav_fmt->ext.validbits), |
336 | 30.4k | &(wav_fmt->ext.channelmask)) ; |
337 | | |
338 | 30.4k | psf_log_printf (psf, " Valid Bits : %d\n", wav_fmt->ext.validbits) ; |
339 | | |
340 | 30.4k | if (wav_fmt->ext.channelmask == 0) |
341 | 6.13k | psf_log_printf (psf, " Channel Mask : 0x0 (should not be zero)\n") ; |
342 | 24.3k | else |
343 | 24.3k | { char buffer [512] ; |
344 | 24.3k | unsigned bit ; |
345 | | |
346 | 24.3k | wpriv->wavex_channelmask = wav_fmt->ext.channelmask ; |
347 | | |
348 | | /* It's probably wise to ignore the channel mask if it is all zero */ |
349 | 24.3k | free (psf->channel_map) ; |
350 | | |
351 | 24.3k | if ((psf->channel_map = calloc (psf->sf.channels, sizeof (psf->channel_map [0]))) == NULL) |
352 | 0 | return SFE_MALLOC_FAILED ; |
353 | | |
354 | | /* Terminate the buffer we're going to append_snprintf into. */ |
355 | 24.3k | buffer [0] = 0 ; |
356 | | |
357 | 243k | for (bit = k = 0 ; bit < ARRAY_LEN (channel_mask_bits) && k < psf->sf.channels ; bit++) |
358 | 219k | { |
359 | 219k | if (wav_fmt->ext.channelmask & (1 << bit)) |
360 | 64.0k | { if (k > psf->sf.channels) |
361 | 0 | { psf_log_printf (psf, "*** More channel map bits than there are channels.\n") ; |
362 | 0 | break ; |
363 | 64.0k | } ; |
364 | | |
365 | 64.0k | psf->channel_map [k++] = channel_mask_bits [bit].id ; |
366 | 64.0k | append_snprintf (buffer, sizeof (buffer), "%s, ", channel_mask_bits [bit].name) ; |
367 | 219k | } ; |
368 | 219k | } ; |
369 | | |
370 | | /* Remove trailing ", ". */ |
371 | 24.3k | bit = strlen (buffer) ; |
372 | 24.3k | if (bit >= 2) |
373 | 14.4k | { buffer [--bit] = 0 ; |
374 | 14.4k | buffer [--bit] = 0 ; |
375 | 14.4k | } ; |
376 | | |
377 | 24.3k | if (k != psf->sf.channels) |
378 | 10.1k | { psf_log_printf (psf, " Channel Mask : 0x%X\n", wav_fmt->ext.channelmask) ; |
379 | 10.1k | psf_log_printf (psf, "*** Less channel map bits than there are channels.\n") ; |
380 | 10.1k | } |
381 | 14.1k | else |
382 | 14.1k | psf_log_printf (psf, " Channel Mask : 0x%X (%s)\n", wav_fmt->ext.channelmask, buffer) ; |
383 | 30.4k | } ; |
384 | | |
385 | 30.4k | bytesread += psf_binheader_readf (psf, "422", &(wav_fmt->ext.esf.esf_field1), &(wav_fmt->ext.esf.esf_field2), &(wav_fmt->ext.esf.esf_field3)) ; |
386 | | |
387 | | /* compare the esf_fields with each known GUID? and print? */ |
388 | 30.4k | psf_log_printf (psf, " Subformat\n") ; |
389 | 30.4k | psf_log_printf (psf, " esf_field1 : 0x%X\n", wav_fmt->ext.esf.esf_field1) ; |
390 | 30.4k | psf_log_printf (psf, " esf_field2 : 0x%X\n", wav_fmt->ext.esf.esf_field2) ; |
391 | 30.4k | psf_log_printf (psf, " esf_field3 : 0x%X\n", wav_fmt->ext.esf.esf_field3) ; |
392 | 30.4k | psf_log_printf (psf, " esf_field4 : ") ; |
393 | 274k | for (k = 0 ; k < 8 ; k++) |
394 | 243k | { bytesread += psf_binheader_readf (psf, "1", &(wav_fmt->ext.esf.esf_field4 [k])) ; |
395 | 243k | psf_log_printf (psf, "0x%X ", wav_fmt->ext.esf.esf_field4 [k] & 0xFF) ; |
396 | 243k | } ; |
397 | 30.4k | psf_log_printf (psf, "\n") ; |
398 | 30.4k | psf->bytewidth = BITWIDTH2BYTES (wav_fmt->ext.bitwidth) ; |
399 | | |
400 | | /* Compare GUIDs for known ones. */ |
401 | 30.4k | if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_PCM)) |
402 | 6.05k | { psf->sf.format = SF_FORMAT_WAVEX | u_bitwidth_to_subformat (psf->bytewidth * 8) ; |
403 | 6.05k | psf_log_printf (psf, " format : pcm\n") ; |
404 | 6.05k | } |
405 | 24.4k | else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_MS_ADPCM)) |
406 | 2.88k | { psf->sf.format = (SF_FORMAT_WAVEX | SF_FORMAT_MS_ADPCM) ; |
407 | 2.88k | psf_log_printf (psf, " format : ms adpcm\n") ; |
408 | 2.88k | } |
409 | 21.5k | else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_IEEE_FLOAT)) |
410 | 3.42k | { psf->sf.format = SF_FORMAT_WAVEX | ((psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT) ; |
411 | 3.42k | psf_log_printf (psf, " format : IEEE float\n") ; |
412 | 3.42k | } |
413 | 18.1k | else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_ALAW)) |
414 | 3.82k | { psf->sf.format = (SF_FORMAT_WAVEX | SF_FORMAT_ALAW) ; |
415 | 3.82k | psf_log_printf (psf, " format : A-law\n") ; |
416 | 3.82k | } |
417 | 14.2k | else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_MULAW)) |
418 | 3.41k | { psf->sf.format = (SF_FORMAT_WAVEX | SF_FORMAT_ULAW) ; |
419 | 3.41k | psf_log_printf (psf, " format : u-law\n") ; |
420 | 3.41k | } |
421 | 10.8k | else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM)) |
422 | 5.29k | { psf->sf.format = SF_FORMAT_WAVEX | u_bitwidth_to_subformat (psf->bytewidth * 8) ; |
423 | 5.29k | psf_log_printf (psf, " format : pcm (Ambisonic B)\n") ; |
424 | 5.29k | wpriv->wavex_ambisonic = SF_AMBISONIC_B_FORMAT ; |
425 | 5.29k | } |
426 | 5.56k | else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT)) |
427 | 5.30k | { psf->sf.format = SF_FORMAT_WAVEX | ((psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT) ; |
428 | 5.30k | psf_log_printf (psf, " format : IEEE float (Ambisonic B)\n") ; |
429 | 5.30k | wpriv->wavex_ambisonic = SF_AMBISONIC_B_FORMAT ; |
430 | 5.30k | } |
431 | 259 | else |
432 | 259 | return SFE_UNIMPLEMENTED ; |
433 | | |
434 | 30.2k | break ; |
435 | | |
436 | 30.2k | case WAVE_FORMAT_G721_ADPCM : |
437 | 13.0k | psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->g72x.bytespersec) ; |
438 | 13.0k | if (fmtsize >= 20) |
439 | 8.10k | { bytesread += psf_binheader_readf (psf, "22", &(wav_fmt->g72x.extrabytes), &(wav_fmt->g72x.auxblocksize)) ; |
440 | 8.10k | if (wav_fmt->g72x.extrabytes == 0) |
441 | 3.13k | psf_log_printf (psf, " Extra Bytes : %d (should be 2)\n", wav_fmt->g72x.extrabytes) ; |
442 | 4.96k | else |
443 | 4.96k | psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->g72x.extrabytes) ; |
444 | 8.10k | psf_log_printf (psf, " Aux Blk Size : %d\n", wav_fmt->g72x.auxblocksize) ; |
445 | 8.10k | } |
446 | 4.95k | else if (fmtsize == 18) |
447 | 2.63k | { bytesread += psf_binheader_readf (psf, "2", &(wav_fmt->g72x.extrabytes)) ; |
448 | 2.63k | psf_log_printf (psf, " Extra Bytes : %d%s\n", wav_fmt->g72x.extrabytes, wav_fmt->g72x.extrabytes != 0 ? " (should be 0)" : "") ; |
449 | 2.63k | } |
450 | 2.32k | else |
451 | 2.32k | psf_log_printf (psf, "*** 'fmt ' chunk should be bigger than this!\n") ; |
452 | 13.0k | break ; |
453 | | |
454 | 9.88k | case WAVE_FORMAT_NMS_VBXADPCM : |
455 | 9.88k | if (wav_fmt->min.channels != 1 || wav_fmt->min.bitwidth < 2 || wav_fmt->min.bitwidth * 20 + 2 != wav_fmt->min.blockalign) |
456 | 20 | return SFE_WAV_NMS_FORMAT ; |
457 | | |
458 | 9.86k | bytespersec = (wav_fmt->min.samplerate * wav_fmt->min.blockalign) / 160 ; |
459 | 9.86k | if (wav_fmt->min.bytespersec == (unsigned) bytespersec) |
460 | 3.29k | psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->min.bytespersec) ; |
461 | 6.56k | else |
462 | 6.56k | psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->min.bytespersec, bytespersec) ; |
463 | 9.86k | if (fmtsize >= 18) |
464 | 5.41k | { bytesread += psf_binheader_readf (psf, "2", &(wav_fmt->size20.extrabytes)) ; |
465 | 5.41k | psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->size20.extrabytes) ; |
466 | 5.41k | } ; |
467 | 9.86k | break ; |
468 | | |
469 | 92 | default : |
470 | 92 | psf_log_printf (psf, "*** No 'fmt ' chunk dumper for this format!\n") ; |
471 | 92 | return SFE_WAV_BAD_FMT ; |
472 | 160k | } ; |
473 | | |
474 | 160k | if (bytesread > fmtsize) |
475 | 16 | { psf_log_printf (psf, "*** wavlike_read_fmt_chunk (bytesread > fmtsize)\n") ; |
476 | 16 | return SFE_WAV_BAD_FMT ; |
477 | 16 | } |
478 | 160k | else |
479 | 160k | psf_binheader_readf (psf, "j", fmtsize - bytesread) ; |
480 | | |
481 | 160k | psf->blockwidth = wav_fmt->min.channels * psf->bytewidth ; |
482 | | |
483 | 160k | return 0 ; |
484 | 160k | } /* wavlike_read_fmt_chunk */ |
485 | | |
486 | | void |
487 | | wavlike_write_guid (SF_PRIVATE *psf, const EXT_SUBFORMAT * subformat) |
488 | 0 | { |
489 | 0 | psf_binheader_writef (psf, "422b", BHW4 (subformat->esf_field1), |
490 | 0 | BHW2 (subformat->esf_field2), BHW2 (subformat->esf_field3), |
491 | 0 | BHWv (subformat->esf_field4), BHWz (8)) ; |
492 | 0 | } /* wavlike_write_guid */ |
493 | | |
494 | | |
495 | | int |
496 | | wavlike_gen_channel_mask (const int *chan_map, int channels) |
497 | 0 | { int chan, mask = 0, bit = -1, last_bit = -1 ; |
498 | |
|
499 | 0 | if (chan_map == NULL) |
500 | 0 | return 0 ; |
501 | | |
502 | 0 | for (chan = 0 ; chan < channels ; chan ++) |
503 | 0 | { int k ; |
504 | |
|
505 | 0 | for (k = bit + 1 ; k < ARRAY_LEN (channel_mask_bits) ; k++) |
506 | 0 | if (chan_map [chan] == channel_mask_bits [k].id) |
507 | 0 | { bit = k ; |
508 | 0 | break ; |
509 | 0 | } ; |
510 | | |
511 | | /* Check for bad sequence. */ |
512 | 0 | if (bit <= last_bit) |
513 | 0 | return 0 ; |
514 | | |
515 | 0 | mask += 1 << bit ; |
516 | 0 | last_bit = bit ; |
517 | 0 | } ; |
518 | |
|
519 | 0 | return mask ; |
520 | 0 | } /* wavlike_gen_channel_mask */ |
521 | | |
522 | | void |
523 | | wavlike_analyze (SF_PRIVATE *psf) |
524 | 52 | { unsigned char buffer [4096] ; |
525 | 52 | AUDIO_DETECT ad ; |
526 | 52 | int format = 0 ; |
527 | | |
528 | 52 | if (psf->is_pipe) |
529 | 0 | { psf_log_printf (psf, "*** Error : Reading from a pipe. Can't analyze data section to figure out real data format.\n\n") ; |
530 | 0 | return ; |
531 | 52 | } ; |
532 | | |
533 | 52 | psf_log_printf (psf, "---------------------------------------------------\n" |
534 | 52 | "Format is known to be broken. Using detection code.\n") ; |
535 | | |
536 | | /* Code goes here. */ |
537 | 52 | ad.endianness = SF_ENDIAN_LITTLE ; |
538 | 52 | ad.channels = psf->sf.channels ; |
539 | | |
540 | 52 | psf_fseek (psf, 3 * 4 * 50, SEEK_SET) ; |
541 | | |
542 | 2.20k | while (psf_fread (buffer, 1, sizeof (buffer), psf) == sizeof (buffer)) |
543 | 2.16k | { format = audio_detect (psf, &ad, buffer, sizeof (buffer)) ; |
544 | 2.16k | if (format != 0) |
545 | 15 | break ; |
546 | 2.16k | } ; |
547 | | |
548 | | /* Seek to start of DATA section. */ |
549 | 52 | psf_fseek (psf, psf->dataoffset, SEEK_SET) ; |
550 | | |
551 | 52 | if (format == 0) |
552 | 37 | { psf_log_printf (psf, "wavlike_analyze : detection failed.\n") ; |
553 | 37 | return ; |
554 | 37 | } ; |
555 | | |
556 | 15 | switch (format) |
557 | 15 | { case SF_FORMAT_PCM_32 : |
558 | 15 | case SF_FORMAT_FLOAT : |
559 | 15 | psf_log_printf (psf, "wavlike_analyze : found format : 0x%X\n", format) ; |
560 | 15 | psf->sf.format = (psf->sf.format & ~SF_FORMAT_SUBMASK) + format ; |
561 | 15 | psf->bytewidth = 4 ; |
562 | 15 | psf->blockwidth = psf->sf.channels * psf->bytewidth ; |
563 | 15 | break ; |
564 | | |
565 | 0 | case SF_FORMAT_PCM_24 : |
566 | 0 | psf_log_printf (psf, "wavlike_analyze : found format : 0x%X\n", format) ; |
567 | 0 | psf->sf.format = (psf->sf.format & ~SF_FORMAT_SUBMASK) + format ; |
568 | 0 | psf->bytewidth = 3 ; |
569 | 0 | psf->blockwidth = psf->sf.channels * psf->bytewidth ; |
570 | 0 | break ; |
571 | | |
572 | 0 | default : |
573 | 0 | psf_log_printf (psf, "wavlike_analyze : unhandled format : 0x%X\n", format) ; |
574 | 0 | break ; |
575 | 15 | } ; |
576 | | |
577 | 15 | return ; |
578 | 15 | } /* wavlike_analyze */ |
579 | | |
580 | | /*============================================================================== |
581 | | */ |
582 | | |
583 | | typedef struct |
584 | | { int ID ; |
585 | | const char *name ; |
586 | | } WAV_FORMAT_DESC ; |
587 | | |
588 | | #define STR(x) #x |
589 | | #define FORMAT_TYPE(x) { x, STR (x) } |
590 | | |
591 | | static WAV_FORMAT_DESC wave_descs [] = |
592 | | { FORMAT_TYPE (WAVE_FORMAT_PCM), |
593 | | FORMAT_TYPE (WAVE_FORMAT_MS_ADPCM), |
594 | | FORMAT_TYPE (WAVE_FORMAT_IEEE_FLOAT), |
595 | | FORMAT_TYPE (WAVE_FORMAT_VSELP), |
596 | | FORMAT_TYPE (WAVE_FORMAT_IBM_CVSD), |
597 | | FORMAT_TYPE (WAVE_FORMAT_ALAW), |
598 | | FORMAT_TYPE (WAVE_FORMAT_MULAW), |
599 | | FORMAT_TYPE (WAVE_FORMAT_OKI_ADPCM), |
600 | | FORMAT_TYPE (WAVE_FORMAT_IMA_ADPCM), |
601 | | FORMAT_TYPE (WAVE_FORMAT_MEDIASPACE_ADPCM), |
602 | | FORMAT_TYPE (WAVE_FORMAT_SIERRA_ADPCM), |
603 | | FORMAT_TYPE (WAVE_FORMAT_G723_ADPCM), |
604 | | FORMAT_TYPE (WAVE_FORMAT_DIGISTD), |
605 | | FORMAT_TYPE (WAVE_FORMAT_DIGIFIX), |
606 | | FORMAT_TYPE (WAVE_FORMAT_DIALOGIC_OKI_ADPCM), |
607 | | FORMAT_TYPE (WAVE_FORMAT_MEDIAVISION_ADPCM), |
608 | | FORMAT_TYPE (WAVE_FORMAT_CU_CODEC), |
609 | | FORMAT_TYPE (WAVE_FORMAT_YAMAHA_ADPCM), |
610 | | FORMAT_TYPE (WAVE_FORMAT_SONARC), |
611 | | FORMAT_TYPE (WAVE_FORMAT_DSPGROUP_TRUESPEECH), |
612 | | FORMAT_TYPE (WAVE_FORMAT_ECHOSC1), |
613 | | FORMAT_TYPE (WAVE_FORMAT_AUDIOFILE_AF36), |
614 | | FORMAT_TYPE (WAVE_FORMAT_APTX), |
615 | | FORMAT_TYPE (WAVE_FORMAT_AUDIOFILE_AF10), |
616 | | FORMAT_TYPE (WAVE_FORMAT_PROSODY_1612), |
617 | | FORMAT_TYPE (WAVE_FORMAT_LRC), |
618 | | FORMAT_TYPE (WAVE_FORMAT_DOLBY_AC2), |
619 | | FORMAT_TYPE (WAVE_FORMAT_GSM610), |
620 | | FORMAT_TYPE (WAVE_FORMAT_MSNAUDIO), |
621 | | FORMAT_TYPE (WAVE_FORMAT_ANTEX_ADPCME), |
622 | | FORMAT_TYPE (WAVE_FORMAT_CONTROL_RES_VQLPC), |
623 | | FORMAT_TYPE (WAVE_FORMAT_DIGIREAL), |
624 | | FORMAT_TYPE (WAVE_FORMAT_DIGIADPCM), |
625 | | FORMAT_TYPE (WAVE_FORMAT_CONTROL_RES_CR10), |
626 | | FORMAT_TYPE (WAVE_FORMAT_NMS_VBXADPCM), |
627 | | FORMAT_TYPE (WAVE_FORMAT_ROLAND_RDAC), |
628 | | FORMAT_TYPE (WAVE_FORMAT_ECHOSC3), |
629 | | FORMAT_TYPE (WAVE_FORMAT_ROCKWELL_ADPCM), |
630 | | FORMAT_TYPE (WAVE_FORMAT_ROCKWELL_DIGITALK), |
631 | | FORMAT_TYPE (WAVE_FORMAT_XEBEC), |
632 | | FORMAT_TYPE (WAVE_FORMAT_G721_ADPCM), |
633 | | FORMAT_TYPE (WAVE_FORMAT_G728_CELP), |
634 | | FORMAT_TYPE (WAVE_FORMAT_MSG723), |
635 | | FORMAT_TYPE (WAVE_FORMAT_MPEG), |
636 | | FORMAT_TYPE (WAVE_FORMAT_RT24), |
637 | | FORMAT_TYPE (WAVE_FORMAT_PAC), |
638 | | FORMAT_TYPE (WAVE_FORMAT_MPEGLAYER3), |
639 | | FORMAT_TYPE (WAVE_FORMAT_LUCENT_G723), |
640 | | FORMAT_TYPE (WAVE_FORMAT_CIRRUS), |
641 | | FORMAT_TYPE (WAVE_FORMAT_ESPCM), |
642 | | FORMAT_TYPE (WAVE_FORMAT_VOXWARE), |
643 | | FORMAT_TYPE (WAVE_FORMAT_CANOPUS_ATRAC), |
644 | | FORMAT_TYPE (WAVE_FORMAT_G726_ADPCM), |
645 | | FORMAT_TYPE (WAVE_FORMAT_G722_ADPCM), |
646 | | FORMAT_TYPE (WAVE_FORMAT_DSAT), |
647 | | FORMAT_TYPE (WAVE_FORMAT_DSAT_DISPLAY), |
648 | | FORMAT_TYPE (WAVE_FORMAT_VOXWARE_BYTE_ALIGNED), |
649 | | FORMAT_TYPE (WAVE_FORMAT_VOXWARE_AC8), |
650 | | FORMAT_TYPE (WAVE_FORMAT_VOXWARE_AC10), |
651 | | FORMAT_TYPE (WAVE_FORMAT_VOXWARE_AC16), |
652 | | FORMAT_TYPE (WAVE_FORMAT_VOXWARE_AC20), |
653 | | FORMAT_TYPE (WAVE_FORMAT_VOXWARE_RT24), |
654 | | FORMAT_TYPE (WAVE_FORMAT_VOXWARE_RT29), |
655 | | FORMAT_TYPE (WAVE_FORMAT_VOXWARE_RT29HW), |
656 | | FORMAT_TYPE (WAVE_FORMAT_VOXWARE_VR12), |
657 | | FORMAT_TYPE (WAVE_FORMAT_VOXWARE_VR18), |
658 | | FORMAT_TYPE (WAVE_FORMAT_VOXWARE_TQ40), |
659 | | FORMAT_TYPE (WAVE_FORMAT_SOFTSOUND), |
660 | | FORMAT_TYPE (WAVE_FORMAT_VOXARE_TQ60), |
661 | | FORMAT_TYPE (WAVE_FORMAT_MSRT24), |
662 | | FORMAT_TYPE (WAVE_FORMAT_G729A), |
663 | | FORMAT_TYPE (WAVE_FORMAT_MVI_MV12), |
664 | | FORMAT_TYPE (WAVE_FORMAT_DF_G726), |
665 | | FORMAT_TYPE (WAVE_FORMAT_DF_GSM610), |
666 | | FORMAT_TYPE (WAVE_FORMAT_ONLIVE), |
667 | | FORMAT_TYPE (WAVE_FORMAT_SBC24), |
668 | | FORMAT_TYPE (WAVE_FORMAT_DOLBY_AC3_SPDIF), |
669 | | FORMAT_TYPE (WAVE_FORMAT_ZYXEL_ADPCM), |
670 | | FORMAT_TYPE (WAVE_FORMAT_PHILIPS_LPCBB), |
671 | | FORMAT_TYPE (WAVE_FORMAT_PACKED), |
672 | | FORMAT_TYPE (WAVE_FORMAT_RHETOREX_ADPCM), |
673 | | FORMAT_TYPE (IBM_FORMAT_MULAW), |
674 | | FORMAT_TYPE (IBM_FORMAT_ALAW), |
675 | | FORMAT_TYPE (IBM_FORMAT_ADPCM), |
676 | | FORMAT_TYPE (WAVE_FORMAT_VIVO_G723), |
677 | | FORMAT_TYPE (WAVE_FORMAT_VIVO_SIREN), |
678 | | FORMAT_TYPE (WAVE_FORMAT_DIGITAL_G723), |
679 | | FORMAT_TYPE (WAVE_FORMAT_CREATIVE_ADPCM), |
680 | | FORMAT_TYPE (WAVE_FORMAT_CREATIVE_FASTSPEECH8), |
681 | | FORMAT_TYPE (WAVE_FORMAT_CREATIVE_FASTSPEECH10), |
682 | | FORMAT_TYPE (WAVE_FORMAT_QUARTERDECK), |
683 | | FORMAT_TYPE (WAVE_FORMAT_FM_TOWNS_SND), |
684 | | FORMAT_TYPE (WAVE_FORMAT_BZV_DIGITAL), |
685 | | FORMAT_TYPE (WAVE_FORMAT_VME_VMPCM), |
686 | | FORMAT_TYPE (WAVE_FORMAT_OLIGSM), |
687 | | FORMAT_TYPE (WAVE_FORMAT_OLIADPCM), |
688 | | FORMAT_TYPE (WAVE_FORMAT_OLICELP), |
689 | | FORMAT_TYPE (WAVE_FORMAT_OLISBC), |
690 | | FORMAT_TYPE (WAVE_FORMAT_OLIOPR), |
691 | | FORMAT_TYPE (WAVE_FORMAT_LH_CODEC), |
692 | | FORMAT_TYPE (WAVE_FORMAT_NORRIS), |
693 | | FORMAT_TYPE (WAVE_FORMAT_SOUNDSPACE_MUSICOMPRESS), |
694 | | FORMAT_TYPE (WAVE_FORMAT_DVM), |
695 | | FORMAT_TYPE (WAVE_FORMAT_INTERWAV_VSC112), |
696 | | FORMAT_TYPE (WAVE_FORMAT_IPP_ITU_G_723_1), |
697 | | FORMAT_TYPE (WAVE_FORMAT_EXTENSIBLE), |
698 | | } ; |
699 | | |
700 | | char const* |
701 | | wavlike_format_str (int k) |
702 | 160k | { int lower, upper, mid ; |
703 | | |
704 | 160k | lower = -1 ; |
705 | 160k | upper = sizeof (wave_descs) / sizeof (WAV_FORMAT_DESC) ; |
706 | | |
707 | | /* binary search */ |
708 | 160k | if ((wave_descs [0].ID <= k) && (k <= wave_descs [upper - 1].ID)) |
709 | 160k | { |
710 | 968k | while (lower + 1 < upper) |
711 | 968k | { mid = (upper + lower) / 2 ; |
712 | | |
713 | 968k | if (k == wave_descs [mid].ID) |
714 | 160k | return wave_descs [mid].name ; |
715 | 807k | if (k < wave_descs [mid].ID) |
716 | 492k | upper = mid ; |
717 | 315k | else |
718 | 315k | lower = mid ; |
719 | 807k | } ; |
720 | 83 | } ; |
721 | | |
722 | 83 | return "Unknown format" ; |
723 | 160k | } /* wavlike_format_str */ |
724 | | |
725 | | int |
726 | | wavlike_srate2blocksize (int srate_chan_product) |
727 | 0 | { if (srate_chan_product < 12000) |
728 | 0 | return 256 ; |
729 | 0 | if (srate_chan_product < 23000) |
730 | 0 | return 512 ; |
731 | 0 | if (srate_chan_product < 44000) |
732 | 0 | return 1024 ; |
733 | 0 | return 2048 ; |
734 | 0 | } /* srate2blocksize */ |
735 | | |
736 | | int |
737 | | wavlike_read_bext_chunk (SF_PRIVATE *psf, uint32_t chunksize) |
738 | 827 | { |
739 | 827 | SF_BROADCAST_INFO_16K * b ; |
740 | 827 | uint32_t bytes = 0 ; |
741 | | |
742 | 827 | if (chunksize < WAV_BEXT_MIN_CHUNK_SIZE) |
743 | 688 | { psf_log_printf (psf, "bext : %u (should be >= %d)\n", chunksize, WAV_BEXT_MIN_CHUNK_SIZE) ; |
744 | 688 | psf_binheader_readf (psf, "j", chunksize) ; |
745 | 688 | return 0 ; |
746 | 688 | } ; |
747 | | |
748 | 139 | if (chunksize > WAV_BEXT_MAX_CHUNK_SIZE) |
749 | 34 | { psf_log_printf (psf, "bext : %u (should be < %d)\n", chunksize, WAV_BEXT_MAX_CHUNK_SIZE) ; |
750 | 34 | psf_binheader_readf (psf, "j", chunksize) ; |
751 | 34 | return 0 ; |
752 | 105 | } ; |
753 | | |
754 | 105 | if (chunksize >= sizeof (SF_BROADCAST_INFO_16K)) |
755 | 0 | { psf_log_printf (psf, "bext : %u too big to be handled\n", chunksize) ; |
756 | 0 | psf_binheader_readf (psf, "j", chunksize) ; |
757 | 0 | return 0 ; |
758 | 105 | } ; |
759 | | |
760 | 105 | psf_log_printf (psf, "bext : %u\n", chunksize) ; |
761 | | |
762 | 105 | if (!psf->broadcast_16k) |
763 | 17 | { psf->broadcast_16k = broadcast_var_alloc () ; |
764 | 17 | if (!psf->broadcast_16k) |
765 | 0 | { psf->error = SFE_MALLOC_FAILED ; |
766 | 0 | return psf->error ; |
767 | 0 | } |
768 | 17 | } |
769 | 88 | else |
770 | 88 | { psf_log_printf (psf, "bext : found more than one bext chunk, using last one.\n") ; |
771 | 88 | memset (psf->broadcast_16k, 0, sizeof (SF_BROADCAST_INFO_16K)) ; |
772 | 88 | } |
773 | | |
774 | 105 | b = psf->broadcast_16k ; |
775 | | |
776 | 105 | bytes += psf_binheader_readf (psf, "b", b->description, sizeof (b->description)) ; |
777 | 105 | bytes += psf_binheader_readf (psf, "b", b->originator, sizeof (b->originator)) ; |
778 | 105 | bytes += psf_binheader_readf (psf, "b", b->originator_reference, sizeof (b->originator_reference)) ; |
779 | 105 | bytes += psf_binheader_readf (psf, "b", b->origination_date, sizeof (b->origination_date)) ; |
780 | 105 | bytes += psf_binheader_readf (psf, "b", b->origination_time, sizeof (b->origination_time)) ; |
781 | 105 | bytes += psf_binheader_readf (psf, "442", &b->time_reference_low, &b->time_reference_high, &b->version) ; |
782 | 105 | bytes += psf_binheader_readf (psf, "b", &b->umid, sizeof (b->umid)) ; |
783 | 105 | bytes += psf_binheader_readf (psf, "22", &b->loudness_value, &b->loudness_range) ; |
784 | 105 | bytes += psf_binheader_readf (psf, "222", &b->max_true_peak_level, &b->max_momentary_loudness, &b->max_shortterm_loudness) ; |
785 | 105 | bytes += psf_binheader_readf (psf, "j", 180) ; |
786 | | |
787 | 105 | if (chunksize > WAV_BEXT_MIN_CHUNK_SIZE) |
788 | 104 | { /* File has coding history data. */ |
789 | | |
790 | 104 | b->coding_history_size = chunksize - WAV_BEXT_MIN_CHUNK_SIZE ; |
791 | | |
792 | | /* We do not parse the coding history */ |
793 | 104 | bytes += psf_binheader_readf (psf, "b", BHWv (b->coding_history), BHWz (b->coding_history_size)) ; |
794 | 104 | } ; |
795 | | |
796 | 105 | if (bytes < chunksize) |
797 | 14 | psf_binheader_readf (psf, "j", BHWj (chunksize - bytes)) ; |
798 | | |
799 | 105 | return 0 ; |
800 | 105 | } /* wavlike_read_bext_chunk */ |
801 | | |
802 | | int |
803 | | wavlike_write_bext_chunk (SF_PRIVATE *psf) |
804 | 0 | { SF_BROADCAST_INFO_16K *b ; |
805 | |
|
806 | 0 | if (psf->broadcast_16k == NULL) |
807 | 0 | return -1 ; |
808 | | |
809 | 0 | b = psf->broadcast_16k ; |
810 | |
|
811 | 0 | psf_binheader_writef (psf, "m4", BHWm (bext_MARKER), BHW4 (WAV_BEXT_MIN_CHUNK_SIZE + b->coding_history_size)) ; |
812 | | |
813 | | /* |
814 | | ** Note that it is very important that the field widths of the SF_BROADCAST_INFO |
815 | | ** struct match those of the bext chunk fields. |
816 | | */ |
817 | |
|
818 | 0 | psf_binheader_writef (psf, "b", BHWv (b->description), BHWz (sizeof (b->description))) ; |
819 | 0 | psf_binheader_writef (psf, "b", BHWv (b->originator), BHWz (sizeof (b->originator))) ; |
820 | 0 | psf_binheader_writef (psf, "b", BHWv (b->originator_reference), BHWz (sizeof (b->originator_reference))) ; |
821 | 0 | psf_binheader_writef (psf, "b", BHWv (b->origination_date), BHWz (sizeof (b->origination_date))) ; |
822 | 0 | psf_binheader_writef (psf, "b", BHWv (b->origination_time), BHWz (sizeof (b->origination_time))) ; |
823 | 0 | psf_binheader_writef (psf, "442", BHW4 (b->time_reference_low), BHW4 (b->time_reference_high), BHW2 (b->version)) ; |
824 | 0 | psf_binheader_writef (psf, "b", BHWv (b->umid), BHWz (sizeof (b->umid))) ; |
825 | 0 | psf_binheader_writef (psf, "22", BHW2 (b->loudness_value), BHW2 (b->loudness_range)) ; |
826 | 0 | psf_binheader_writef (psf, "222", BHW2 (b->max_true_peak_level), BHW2 (b->max_momentary_loudness), BHW2 (b->max_shortterm_loudness)) ; |
827 | 0 | psf_binheader_writef (psf, "z", BHWz (180)) ; |
828 | |
|
829 | 0 | if (b->coding_history_size > 0) |
830 | 0 | psf_binheader_writef (psf, "b", BHWv (b->coding_history), BHWz (b->coding_history_size)) ; |
831 | |
|
832 | 0 | return 0 ; |
833 | 0 | } /* wavlike_write_bext_chunk */ |
834 | | |
835 | | int |
836 | | wavlike_read_cart_chunk (SF_PRIVATE *psf, uint32_t chunksize) |
837 | 3.01k | { SF_CART_INFO_16K *c ; |
838 | 3.01k | uint32_t bytes = 0 ; |
839 | 3.01k | int k ; |
840 | | |
841 | 3.01k | if (chunksize < WAV_CART_MIN_CHUNK_SIZE) |
842 | 2.81k | { psf_log_printf (psf, "cart : %u (should be >= %d)\n", chunksize, WAV_CART_MIN_CHUNK_SIZE) ; |
843 | 2.81k | psf_binheader_readf (psf, "j", chunksize) ; |
844 | 2.81k | return 0 ; |
845 | 2.81k | } ; |
846 | 203 | if (chunksize > WAV_CART_MAX_CHUNK_SIZE) |
847 | 0 | { psf_log_printf (psf, "cart : %u (should be < %d)\n", chunksize, WAV_CART_MAX_CHUNK_SIZE) ; |
848 | 0 | psf_binheader_readf (psf, "j", chunksize) ; |
849 | 0 | return 0 ; |
850 | 203 | } ; |
851 | | |
852 | | /* |
853 | | ** SF_CART_INFO_16K has an extra field 'tag_text_size' that isn't part |
854 | | ** of the chunk, so don't include it in the size check. |
855 | | */ |
856 | 203 | if (chunksize >= sizeof (SF_CART_INFO_16K) - 4) |
857 | 40 | { psf_log_printf (psf, "cart : %u too big to be handled\n", chunksize) ; |
858 | 40 | psf_binheader_readf (psf, "j", chunksize) ; |
859 | 40 | return 0 ; |
860 | 163 | } ; |
861 | | |
862 | 163 | psf_log_printf (psf, "cart : %u\n", chunksize) ; |
863 | | |
864 | 163 | if (psf->cart_16k) |
865 | 130 | { psf_log_printf (psf, " Found more than one cart chunk, using last one.\n") ; |
866 | 130 | free (psf->cart_16k) ; |
867 | 130 | psf->cart_16k = NULL ; |
868 | 130 | } ; |
869 | | |
870 | 163 | if ((psf->cart_16k = cart_var_alloc ()) == NULL) |
871 | 0 | { psf->error = SFE_MALLOC_FAILED ; |
872 | 0 | return psf->error ; |
873 | 163 | } ; |
874 | | |
875 | 163 | c = psf->cart_16k ; |
876 | 163 | bytes += psf_binheader_readf (psf, "b", c->version, sizeof (c->version)) ; |
877 | 163 | bytes += psf_binheader_readf (psf, "b", c->title, sizeof (c->title)) ; |
878 | 163 | bytes += psf_binheader_readf (psf, "b", c->artist, sizeof (c->artist)) ; |
879 | 163 | bytes += psf_binheader_readf (psf, "b", c->cut_id, sizeof (c->cut_id)) ; |
880 | 163 | bytes += psf_binheader_readf (psf, "b", c->client_id, sizeof (c->client_id)) ; |
881 | 163 | bytes += psf_binheader_readf (psf, "b", c->category, sizeof (c->category)) ; |
882 | 163 | bytes += psf_binheader_readf (psf, "b", c->classification, sizeof (c->classification)) ; |
883 | 163 | bytes += psf_binheader_readf (psf, "b", c->out_cue, sizeof (c->out_cue)) ; |
884 | 163 | bytes += psf_binheader_readf (psf, "b", c->start_date, sizeof (c->start_date)) ; |
885 | 163 | bytes += psf_binheader_readf (psf, "b", c->start_time, sizeof (c->start_time)) ; |
886 | 163 | bytes += psf_binheader_readf (psf, "b", c->end_date, sizeof (c->end_date)) ; |
887 | 163 | bytes += psf_binheader_readf (psf, "b", c->end_time, sizeof (c->end_time)) ; |
888 | 163 | bytes += psf_binheader_readf (psf, "b", c->producer_app_id, sizeof (c->producer_app_id)) ; |
889 | 163 | bytes += psf_binheader_readf (psf, "b", c->producer_app_version, sizeof (c->producer_app_version)) ; |
890 | 163 | bytes += psf_binheader_readf (psf, "b", c->user_def, sizeof (c->user_def)) ; |
891 | 163 | bytes += psf_binheader_readf (psf, "e4", &c->level_reference, sizeof (c->level_reference)) ; |
892 | | |
893 | 1.46k | for (k = 0 ; k < ARRAY_LEN (c->post_timers) ; k++) |
894 | 1.30k | bytes += psf_binheader_readf (psf, "b4", &c->post_timers [k].usage, make_size_t (4), &c->post_timers [k].value) ; |
895 | | |
896 | 163 | bytes += psf_binheader_readf (psf, "b", c->reserved, sizeof (c->reserved)) ; |
897 | 163 | bytes += psf_binheader_readf (psf, "b", c->url, sizeof (c->url)) ; |
898 | | |
899 | 163 | if (chunksize > WAV_CART_MIN_CHUNK_SIZE) |
900 | 110 | { /* File has tag text. */ |
901 | 110 | c->tag_text_size = chunksize - WAV_CART_MIN_CHUNK_SIZE ; |
902 | 110 | bytes += psf_binheader_readf (psf, "b", c->tag_text, make_size_t (c->tag_text_size)) ; |
903 | 110 | } ; |
904 | | |
905 | 163 | if (bytes < chunksize) |
906 | 30 | psf_log_printf (psf, " %d trailing bytes in cart chunk.\n", chunksize - bytes) ; |
907 | | |
908 | 163 | return 0 ; |
909 | 163 | } /* wavlike_read_cart_chunk */ |
910 | | |
911 | | int |
912 | | wavlike_write_cart_chunk (SF_PRIVATE *psf) |
913 | 0 | { SF_CART_INFO_16K *c ; |
914 | 0 | int k ; |
915 | |
|
916 | 0 | if (psf->cart_16k == NULL) |
917 | 0 | return -1 ; |
918 | | |
919 | 0 | c = psf->cart_16k ; |
920 | 0 | psf_binheader_writef (psf, "m4", BHWm (cart_MARKER), BHW4 (WAV_CART_MIN_CHUNK_SIZE + c->tag_text_size)) ; |
921 | | /* |
922 | | ** Note that it is very important that the field widths of the SF_CART_INFO |
923 | | ** struct match those of the cart chunk fields. |
924 | | */ |
925 | 0 | psf_binheader_writef (psf, "b", BHWv (c->version), BHWz (sizeof (c->version))) ; |
926 | 0 | psf_binheader_writef (psf, "b", BHWv (c->title), BHWz (sizeof (c->title))) ; |
927 | 0 | psf_binheader_writef (psf, "b", BHWv (c->artist), BHWz (sizeof (c->artist))) ; |
928 | 0 | psf_binheader_writef (psf, "b", BHWv (c->cut_id), BHWz (sizeof (c->cut_id))) ; |
929 | 0 | psf_binheader_writef (psf, "b", BHWv (c->client_id), BHWz (sizeof (c->client_id))) ; |
930 | 0 | psf_binheader_writef (psf, "b", BHWv (c->category), BHWz (sizeof (c->category))) ; |
931 | 0 | psf_binheader_writef (psf, "b", BHWv (c->classification), BHWz (sizeof (c->classification))) ; |
932 | 0 | psf_binheader_writef (psf, "b", BHWv (c->out_cue), BHWz (sizeof (c->out_cue))) ; |
933 | 0 | psf_binheader_writef (psf, "b", BHWv (c->start_date), BHWz (sizeof (c->start_date))) ; |
934 | 0 | psf_binheader_writef (psf, "b", BHWv (c->start_time), BHWz (sizeof (c->start_time))) ; |
935 | 0 | psf_binheader_writef (psf, "b", BHWv (c->end_date), BHWz (sizeof (c->end_date))) ; |
936 | 0 | psf_binheader_writef (psf, "b", BHWv (c->end_time), BHWz (sizeof (c->end_time))) ; |
937 | 0 | psf_binheader_writef (psf, "b", BHWv (c->producer_app_id), BHWz (sizeof (c->producer_app_id))) ; |
938 | 0 | psf_binheader_writef (psf, "b", BHWv (c->producer_app_version), BHWz (sizeof (c->producer_app_version))) ; |
939 | 0 | psf_binheader_writef (psf, "b", BHWv (c->user_def), BHWz (sizeof (c->user_def))) ; |
940 | 0 | psf_binheader_writef (psf, "e4", BHW4 (c->level_reference)) ; |
941 | |
|
942 | 0 | for (k = 0 ; k < ARRAY_LEN (c->post_timers) ; k++) |
943 | 0 | psf_binheader_writef (psf, "b4", BHWv (c->post_timers [k].usage), BHWz (4), BHW4 (c->post_timers [k].value)) ; |
944 | |
|
945 | 0 | psf_binheader_writef (psf, "z", BHWz (sizeof (c->reserved))) ; // just write zeros, we don't have any other use for it |
946 | 0 | psf_binheader_writef (psf, "b", BHWv (c->url), BHWz (sizeof (c->url))) ; |
947 | |
|
948 | 0 | if (c->tag_text_size > 0) |
949 | 0 | psf_binheader_writef (psf, "b", BHWv (c->tag_text), BHWz (c->tag_text_size)) ; |
950 | |
|
951 | 0 | return 0 ; |
952 | 0 | } /* wavlike_write_cart_chunk */ |
953 | | |
954 | | int |
955 | | wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length) |
956 | 86.4k | { sf_count_t current_pos ; |
957 | 86.4k | char buffer [2048] ; |
958 | 86.4k | uint32_t chunk_size, bytesread = 0 ; |
959 | | |
960 | 86.4k | current_pos = psf_fseek (psf, 0, SEEK_CUR) ; |
961 | | |
962 | 86.4k | if (chunk_length <= 8) |
963 | 1.24k | { /* This case is for broken files generated by PEAK. */ |
964 | 1.24k | psf_log_printf (psf, "%M : %u (weird length)\n", chunk, chunk_length) ; |
965 | 1.24k | psf_binheader_readf (psf, "mj", &chunk, chunk_length - 4) ; |
966 | 1.24k | psf_log_printf (psf, " %M\n", chunk) ; |
967 | 1.24k | return 0 ; |
968 | 85.1k | } ; |
969 | | |
970 | 85.1k | if (current_pos + chunk_length > psf->filelength) |
971 | 26.8k | { psf_log_printf (psf, "%M : %u (should be %d)\n", chunk, chunk_length, (int) (psf->filelength - current_pos)) ; |
972 | 26.8k | chunk_length = psf->filelength - current_pos ; |
973 | 26.8k | } |
974 | 58.3k | else |
975 | 58.3k | psf_log_printf (psf, "%M : %u\n", chunk, chunk_length) ; |
976 | | |
977 | 180k | while (bytesread < chunk_length) |
978 | 167k | { uint32_t thisread ; |
979 | | |
980 | 167k | if ((thisread = psf_binheader_readf (psf, "m", &chunk)) == 0) |
981 | 135 | break ; |
982 | 167k | bytesread += thisread ; |
983 | | |
984 | 167k | switch (chunk) |
985 | 167k | { case adtl_MARKER : |
986 | 647 | case INFO_MARKER : |
987 | | /* These markers don't contain anything, not even a chunk length. */ |
988 | 647 | psf_log_printf (psf, " %M\n", chunk) ; |
989 | 647 | continue ; |
990 | | |
991 | 26.5k | case exif_MARKER : |
992 | 26.5k | psf_log_printf (psf, " %M\n", chunk) ; |
993 | 26.5k | if (chunk_length > bytesread) |
994 | 26.3k | bytesread += exif_subchunk_parse (psf, chunk_length - bytesread) ; |
995 | 26.5k | continue ; |
996 | | |
997 | 9.17k | case data_MARKER : |
998 | 9.17k | psf_log_printf (psf, " %M inside a LIST block??? Backing out.\n", chunk) ; |
999 | | /* Jump back four bytes and return to caller. */ |
1000 | 9.17k | psf_binheader_readf (psf, "j", -4) ; |
1001 | 9.17k | return 0 ; |
1002 | | |
1003 | 5.15k | case 0 : |
1004 | | /* |
1005 | | ** Four zero bytes where a marker was expected. Assume this means |
1006 | | ** the rest of the chunk is garbage. |
1007 | | */ |
1008 | 5.15k | psf_log_printf (psf, " *** Found weird-ass zero marker. Jumping to end of chunk.\n") ; |
1009 | 5.15k | goto cleanup_subchunk_parse ; |
1010 | | |
1011 | 125k | default : |
1012 | 125k | break ; |
1013 | 167k | } ; |
1014 | | |
1015 | 125k | switch (chunk) |
1016 | 125k | { case ISFT_MARKER : |
1017 | 2.69k | case ICOP_MARKER : |
1018 | 7.20k | case IARL_MARKER : |
1019 | 17.7k | case IART_MARKER : |
1020 | 26.3k | case ICMT_MARKER : |
1021 | 26.4k | case ICRD_MARKER : |
1022 | 28.6k | case IENG_MARKER : |
1023 | 31.5k | case IGNR_MARKER : |
1024 | 31.5k | case INAM_MARKER : |
1025 | 34.5k | case IPRD_MARKER : |
1026 | 34.6k | case ISBJ_MARKER : |
1027 | 34.7k | case ISRC_MARKER : |
1028 | 36.4k | case IAUT_MARKER : |
1029 | 36.4k | case ITRK_MARKER : |
1030 | 36.4k | bytesread += psf_binheader_readf (psf, "4", &chunk_size) ; |
1031 | 36.4k | chunk_size += (chunk_size & 1) ; |
1032 | 36.4k | if (chunk_size >= SIGNED_SIZEOF (buffer) || bytesread + chunk_size > chunk_length) |
1033 | 15.4k | { psf_log_printf (psf, " *** %M : %u (too big)\n", chunk, chunk_size) ; |
1034 | 15.4k | goto cleanup_subchunk_parse ; |
1035 | 20.9k | } ; |
1036 | | |
1037 | 20.9k | bytesread += psf_binheader_readf (psf, "b", buffer, chunk_size) ; |
1038 | 20.9k | buffer [chunk_size] = 0 ; |
1039 | 20.9k | psf_log_printf (psf, " %M : %s\n", chunk, buffer) ; |
1040 | 20.9k | break ; |
1041 | | |
1042 | 19.7k | case labl_MARKER : |
1043 | 19.7k | { int mark_id ; |
1044 | | |
1045 | 19.7k | bytesread += psf_binheader_readf (psf, "44", &chunk_size, &mark_id) ; |
1046 | 19.7k | chunk_size -= 4 ; |
1047 | 19.7k | chunk_size += (chunk_size & 1) ; |
1048 | 19.7k | if (chunk_size < 1 || chunk_size >= SIGNED_SIZEOF (buffer) || bytesread + chunk_size > chunk_length) |
1049 | 10.6k | { psf_log_printf (psf, " *** %M : %u (too big)\n", chunk, chunk_size) ; |
1050 | 10.6k | goto cleanup_subchunk_parse ; |
1051 | 10.6k | } ; |
1052 | | |
1053 | 9.13k | bytesread += psf_binheader_readf (psf, "b", buffer, chunk_size) ; |
1054 | 9.13k | buffer [chunk_size] = 0 ; |
1055 | | |
1056 | 9.13k | if (mark_id < 10) /* avoid swamping log buffer with labels */ |
1057 | 3.09k | psf_log_printf (psf, " %M : %u : %s\n", chunk, mark_id, buffer) ; |
1058 | 6.04k | else if (mark_id == 10) |
1059 | 3.62k | psf_log_printf (psf, " (Skipping)\n") ; |
1060 | | |
1061 | 9.13k | if (psf->cues) |
1062 | 491 | { unsigned int i = 0 ; |
1063 | | |
1064 | | /* find id to store label */ |
1065 | 902 | while (i < psf->cues->cue_count && psf->cues->cue_points [i].indx != mark_id) |
1066 | 411 | i++ ; |
1067 | | |
1068 | 491 | if (i < psf->cues->cue_count) |
1069 | 195 | memcpy (psf->cues->cue_points [i].name, buffer, sizeof (psf->cues->cue_points [i].name)) ; |
1070 | 491 | } ; |
1071 | 9.13k | } ; |
1072 | 9.13k | break ; |
1073 | | |
1074 | 7.56k | case DISP_MARKER : |
1075 | 7.56k | case ltxt_MARKER : |
1076 | 7.99k | case note_MARKER : |
1077 | 7.99k | bytesread += psf_binheader_readf (psf, "4", &chunk_size) ; |
1078 | 7.99k | chunk_size += (chunk_size & 1) ; |
1079 | 7.99k | if (chunk_size >= SIGNED_SIZEOF (buffer) || bytesread + chunk_size > chunk_length) |
1080 | 5.81k | { psf_log_printf (psf, " *** %M : %u (too big)\n", chunk, chunk_size) ; |
1081 | 5.81k | goto cleanup_subchunk_parse ; |
1082 | 5.81k | } ; |
1083 | | |
1084 | 2.18k | psf_log_printf (psf, " %M : %u\n", chunk, chunk_size) ; |
1085 | 2.18k | goto cleanup_subchunk_parse ; |
1086 | | |
1087 | 61.5k | default : |
1088 | 61.5k | bytesread += psf_binheader_readf (psf, "4", &chunk_size) ; |
1089 | 61.5k | chunk_size += (chunk_size & 1) ; |
1090 | 61.5k | if (bytesread + chunk_size > chunk_length) |
1091 | 23.6k | { psf_log_printf (psf, " *** %M : %u (too big)\n", chunk, chunk_size) ; |
1092 | 23.6k | goto cleanup_subchunk_parse ; |
1093 | 23.6k | } |
1094 | 37.9k | else |
1095 | 37.9k | { psf_log_printf (psf, " %M : %u\n", chunk, chunk_size) ; |
1096 | 37.9k | bytesread += psf_binheader_readf (psf, "j", chunk_size) ; |
1097 | 37.9k | } ; |
1098 | 37.9k | break ; |
1099 | 125k | } ; |
1100 | | |
1101 | 68.0k | switch (chunk) |
1102 | 68.0k | { case ISFT_MARKER : |
1103 | 1.11k | psf_store_string (psf, SF_STR_SOFTWARE, buffer) ; |
1104 | 1.11k | break ; |
1105 | 1.56k | case ICOP_MARKER : |
1106 | 1.56k | psf_store_string (psf, SF_STR_COPYRIGHT, buffer) ; |
1107 | 1.56k | break ; |
1108 | 14 | case INAM_MARKER : |
1109 | 14 | psf_store_string (psf, SF_STR_TITLE, buffer) ; |
1110 | 14 | break ; |
1111 | 4.40k | case IART_MARKER : |
1112 | 4.40k | psf_store_string (psf, SF_STR_ARTIST, buffer) ; |
1113 | 4.40k | break ; |
1114 | 5.51k | case ICMT_MARKER : |
1115 | 5.51k | psf_store_string (psf, SF_STR_COMMENT, buffer) ; |
1116 | 5.51k | break ; |
1117 | 132 | case ICRD_MARKER : |
1118 | 132 | psf_store_string (psf, SF_STR_DATE, buffer) ; |
1119 | 132 | break ; |
1120 | 2.82k | case IGNR_MARKER : |
1121 | 2.82k | psf_store_string (psf, SF_STR_GENRE, buffer) ; |
1122 | 2.82k | break ; |
1123 | 2.74k | case IPRD_MARKER : |
1124 | 2.74k | psf_store_string (psf, SF_STR_ALBUM, buffer) ; |
1125 | 2.74k | break ; |
1126 | 11 | case ITRK_MARKER : |
1127 | 11 | psf_store_string (psf, SF_STR_TRACKNUMBER, buffer) ; |
1128 | 11 | break ; |
1129 | 68.0k | } ; |
1130 | 68.0k | } ; |
1131 | | |
1132 | 76.0k | cleanup_subchunk_parse : |
1133 | | |
1134 | 76.0k | if (chunk_length > bytesread) |
1135 | 52.9k | bytesread += psf_binheader_readf (psf, "j", chunk_length - bytesread) ; |
1136 | | |
1137 | 76.0k | return 0 ; |
1138 | 13.1k | } /* wavlike_subchunk_parse */ |
1139 | | |
1140 | | void |
1141 | | wavlike_write_strings (SF_PRIVATE *psf, int location) |
1142 | 0 | { int k, prev_head_index, saved_head_index ; |
1143 | |
|
1144 | 0 | if (psf_location_string_count (psf, location) == 0) |
1145 | 0 | return ; |
1146 | | |
1147 | 0 | prev_head_index = psf->header.indx + 4 ; |
1148 | |
|
1149 | 0 | psf_binheader_writef (psf, "m4m", BHWm (LIST_MARKER), BHW4 (0xBADBAD), BHWm (INFO_MARKER)) ; |
1150 | |
|
1151 | 0 | for (k = 0 ; k < SF_MAX_STRINGS ; k++) |
1152 | 0 | { if (psf->strings.data [k].type == 0) |
1153 | 0 | break ; |
1154 | 0 | if (psf->strings.data [k].type < 0 || psf->strings.data [k].flags != location) |
1155 | 0 | continue ; |
1156 | | |
1157 | 0 | switch (psf->strings.data [k].type) |
1158 | 0 | { case SF_STR_SOFTWARE : |
1159 | 0 | psf_binheader_writef (psf, "ms", BHWm (ISFT_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ; |
1160 | 0 | break ; |
1161 | | |
1162 | 0 | case SF_STR_TITLE : |
1163 | 0 | psf_binheader_writef (psf, "ms", BHWm (INAM_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ; |
1164 | 0 | break ; |
1165 | | |
1166 | 0 | case SF_STR_COPYRIGHT : |
1167 | 0 | psf_binheader_writef (psf, "ms", BHWm (ICOP_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ; |
1168 | 0 | break ; |
1169 | | |
1170 | 0 | case SF_STR_ARTIST : |
1171 | 0 | psf_binheader_writef (psf, "ms", BHWm (IART_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ; |
1172 | 0 | break ; |
1173 | | |
1174 | 0 | case SF_STR_COMMENT : |
1175 | 0 | psf_binheader_writef (psf, "ms", BHWm (ICMT_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ; |
1176 | 0 | break ; |
1177 | | |
1178 | 0 | case SF_STR_DATE : |
1179 | 0 | psf_binheader_writef (psf, "ms", BHWm (ICRD_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ; |
1180 | 0 | break ; |
1181 | | |
1182 | 0 | case SF_STR_GENRE : |
1183 | 0 | psf_binheader_writef (psf, "ms", BHWm (IGNR_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ; |
1184 | 0 | break ; |
1185 | | |
1186 | 0 | case SF_STR_ALBUM : |
1187 | 0 | psf_binheader_writef (psf, "ms", BHWm (IPRD_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ; |
1188 | 0 | break ; |
1189 | | |
1190 | 0 | case SF_STR_TRACKNUMBER : |
1191 | 0 | psf_binheader_writef (psf, "ms", BHWm (ITRK_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ; |
1192 | 0 | break ; |
1193 | | |
1194 | 0 | default : |
1195 | 0 | break ; |
1196 | 0 | } ; |
1197 | 0 | } ; |
1198 | |
|
1199 | 0 | saved_head_index = psf->header.indx ; |
1200 | 0 | psf->header.indx = prev_head_index ; |
1201 | 0 | psf_binheader_writef (psf, "4", BHW4 (saved_head_index - prev_head_index - 4)) ; |
1202 | 0 | psf->header.indx = saved_head_index ; |
1203 | |
|
1204 | 0 | } /* wavlike_write_strings */ |
1205 | | |
1206 | | int |
1207 | | wavlike_read_peak_chunk (SF_PRIVATE * psf, size_t chunk_size) |
1208 | 8.36k | { char buffer [256] ; |
1209 | 8.36k | uint32_t uk ; |
1210 | | |
1211 | 8.36k | if (chunk_size != WAVLIKE_PEAK_CHUNK_SIZE (psf->sf.channels)) |
1212 | 8 | { psf_binheader_readf (psf, "j", chunk_size) ; |
1213 | 8 | psf_log_printf (psf, "*** File PEAK chunk size doesn't fit with number of channels (%d).\n", psf->sf.channels) ; |
1214 | 8 | return SFE_WAV_BAD_PEAK ; |
1215 | 8.35k | } ; |
1216 | | |
1217 | 8.35k | if (psf->peak_info) |
1218 | 8.29k | { psf_log_printf (psf, "*** Found existing peak info, using last one.\n") ; |
1219 | 8.29k | free (psf->peak_info) ; |
1220 | 8.29k | psf->peak_info = NULL ; |
1221 | 8.29k | } ; |
1222 | 8.35k | if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) |
1223 | 0 | return SFE_MALLOC_FAILED ; |
1224 | | |
1225 | | /* read in rest of PEAK chunk. */ |
1226 | 8.35k | psf_binheader_readf (psf, "44", & (psf->peak_info->version), & (psf->peak_info->timestamp)) ; |
1227 | | |
1228 | 8.35k | if (psf->peak_info->version != 1) |
1229 | 6.16k | psf_log_printf (psf, " version : %d *** (should be version 1)\n", psf->peak_info->version) ; |
1230 | 2.19k | else |
1231 | 2.19k | psf_log_printf (psf, " version : %d\n", psf->peak_info->version) ; |
1232 | | |
1233 | 8.35k | psf_log_printf (psf, " time stamp : %d\n", psf->peak_info->timestamp) ; |
1234 | 8.35k | psf_log_printf (psf, " Ch Position Value\n") ; |
1235 | | |
1236 | 152k | for (uk = 0 ; uk < (uint32_t) psf->sf.channels ; uk++) |
1237 | 143k | { float value ; |
1238 | 143k | uint32_t position ; |
1239 | | |
1240 | 143k | psf_binheader_readf (psf, "f4", &value, &position) ; |
1241 | 143k | psf->peak_info->peaks [uk].value = value ; |
1242 | 143k | psf->peak_info->peaks [uk].position = position ; |
1243 | | |
1244 | 143k | snprintf (buffer, sizeof (buffer), " %2d %-12" PRId64 " %g\n", |
1245 | 143k | uk, psf->peak_info->peaks [uk].position, psf->peak_info->peaks [uk].value) ; |
1246 | 143k | buffer [sizeof (buffer) - 1] = 0 ; |
1247 | 143k | psf_log_printf (psf, "%s", buffer) ; |
1248 | 143k | } ; |
1249 | | |
1250 | 8.35k | return 0 ; |
1251 | 8.35k | } /* wavlike_read_peak_chunk */ |
1252 | | |
1253 | | void |
1254 | | wavlike_write_peak_chunk (SF_PRIVATE * psf) |
1255 | 0 | { int k ; |
1256 | |
|
1257 | 0 | if (psf->peak_info == NULL) |
1258 | 0 | return ; |
1259 | | |
1260 | 0 | psf_binheader_writef (psf, "m4", BHWm (PEAK_MARKER), BHW4 (WAVLIKE_PEAK_CHUNK_SIZE (psf->sf.channels))) ; |
1261 | 0 | psf_binheader_writef (psf, "44", BHW4 (1), BHW4 (time (NULL))) ; |
1262 | 0 | for (k = 0 ; k < psf->sf.channels ; k++) |
1263 | 0 | psf_binheader_writef (psf, "ft8", BHWf (psf->peak_info->peaks [k].value), BHW8 (psf->peak_info->peaks [k].position)) ; |
1264 | 0 | } /* wavlike_write_peak_chunk */ |
1265 | | |
1266 | | /*============================================================================== |
1267 | | */ |
1268 | | |
1269 | | static int |
1270 | | exif_fill_and_sink (SF_PRIVATE *psf, char* buf, size_t bufsz, size_t toread) |
1271 | 25.1k | { |
1272 | 25.1k | size_t bytesread = 0 ; |
1273 | | |
1274 | 25.1k | buf [0] = 0 ; |
1275 | 25.1k | bufsz -= 1 ; |
1276 | 25.1k | if (toread < bufsz) |
1277 | 25.1k | bufsz = toread ; |
1278 | 25.1k | bytesread = psf_binheader_readf (psf, "b", buf, bufsz) ; |
1279 | 25.1k | buf [bufsz] = 0 ; |
1280 | | |
1281 | 25.1k | if (bytesread == bufsz && toread > bufsz) |
1282 | 0 | bytesread += psf_binheader_readf (psf, "j", toread - bufsz) ; |
1283 | | |
1284 | 25.1k | return bytesread ; |
1285 | 25.1k | } /* exif_fill_and_sink */ |
1286 | | |
1287 | | /* |
1288 | | ** Exif specification for audio files, at JEITA CP-3451 Exif 2.2 section 5 |
1289 | | ** (Exif Audio File Specification) http://www.exif.org/Exif2-2.PDF |
1290 | | */ |
1291 | | static int |
1292 | | exif_subchunk_parse (SF_PRIVATE *psf, uint32_t length) |
1293 | 26.3k | { uint32_t marker, dword = 0, vmajor = -1, vminor = -1, bytesread = 0 ; |
1294 | 26.3k | char buf [4096] ; |
1295 | 26.3k | int thisread ; |
1296 | | |
1297 | 282k | while (bytesread < length) |
1298 | 278k | { |
1299 | 278k | if ((thisread = psf_binheader_readf (psf, "m", &marker)) == 0) |
1300 | 39 | break ; |
1301 | 278k | bytesread += thisread ; |
1302 | | |
1303 | 278k | switch (marker) |
1304 | 278k | { |
1305 | 23.9k | case 0 : /* camera padding? */ |
1306 | 23.9k | break ; |
1307 | | |
1308 | 718 | case ever_MARKER : |
1309 | 718 | bytesread += psf_binheader_readf (psf, "j4", 4, &dword) ; |
1310 | 718 | vmajor = 10 * (((dword >> 24) & 0xff) - '0') + (((dword >> 16) & 0xff) - '0') ; |
1311 | 718 | vminor = 10 * (((dword >> 8) & 0xff) - '0') + ((dword & 0xff) - '0') ; |
1312 | 718 | psf_log_printf (psf, " EXIF Version : %u.%02u\n", vmajor, vminor) ; |
1313 | 718 | break ; |
1314 | | |
1315 | 1.41k | case olym_MARKER : |
1316 | 1.41k | bytesread += psf_binheader_readf (psf, "4", &dword) ; |
1317 | 1.41k | psf_log_printf (psf, "%M : %u\n", marker, dword) ; |
1318 | 1.41k | if (dword > length || bytesread + dword > length) |
1319 | 909 | break ; |
1320 | 503 | dword += (dword & 1) ; |
1321 | 503 | bytesread += psf_binheader_readf (psf, "j", dword) ; |
1322 | 503 | break ; |
1323 | | |
1324 | 870 | case emnt_MARKER : /* design information: null-terminated string */ |
1325 | 44.4k | case emdl_MARKER : /* model name ; null-terminated string */ |
1326 | 44.6k | case ecor_MARKER : /* manufacturer: null-terminated string */ |
1327 | 44.8k | case etim_MARKER : /* creation time: null-terminated string in the format "hour:minute:second.subsecond" */ |
1328 | 45.1k | case erel_MARKER : /* relation info: null-terminated string (filename) */ |
1329 | 45.5k | case eucm_MARKER : /* user comment: 4-byte size follows, then possibly unicode data */ |
1330 | 45.5k | bytesread += psf_binheader_readf (psf, "4", &dword) ; |
1331 | 45.5k | bytesread += sizeof (dword) ; |
1332 | 45.5k | dword += (dword & 1) ; |
1333 | | |
1334 | 45.5k | if (dword >= sizeof (buf)) |
1335 | 20.3k | { psf_log_printf (psf, "*** Marker '%M' is too big %u\n\n", marker, dword) ; |
1336 | 20.3k | return bytesread ; |
1337 | 25.1k | } ; |
1338 | | |
1339 | 25.1k | bytesread += exif_fill_and_sink (psf, buf, sizeof (buf), dword) ; |
1340 | | |
1341 | | /* BAD - don't know what's going on here -- maybe a bug in the camera */ |
1342 | | /* field should be NULL-terminated but there's no room for it with the reported number */ |
1343 | | /* example output: emdl : 8 (EX-Z1050) */ |
1344 | 25.1k | if (marker == emdl_MARKER && dword == strlen (buf) /* should be >= strlen+1*/) |
1345 | 5.81k | { psf_log_printf (psf, " *** field size too small for string (sinking 2 bytes)\n") ; |
1346 | 5.81k | bytesread += psf_binheader_readf (psf, "j", 2) ; |
1347 | 5.81k | } ; |
1348 | | |
1349 | 25.1k | psf_log_printf (psf, " %M : %u (%s)\n", marker, dword, buf) ; |
1350 | 25.1k | if (dword > length) |
1351 | 1.82k | return bytesread ; |
1352 | 23.3k | break ; |
1353 | | |
1354 | 206k | default : |
1355 | 206k | psf_log_printf (psf, " *** %M (%u): -- ignored --\n", marker, marker) ; |
1356 | 206k | break ; |
1357 | 278k | } ; |
1358 | 256k | } ; |
1359 | | |
1360 | 4.14k | return bytesread ; |
1361 | 26.3k | } /* exif_subchunk_parse */ |
1362 | | |
1363 | | void |
1364 | | wavlike_write_custom_chunks (SF_PRIVATE * psf) |
1365 | 0 | { uint32_t k ; |
1366 | |
|
1367 | 0 | for (k = 0 ; k < psf->wchunks.used ; k++) |
1368 | 0 | psf_binheader_writef (psf, "m4b", BHWm (psf->wchunks.chunks [k].mark32), BHW4 (psf->wchunks.chunks [k].len), |
1369 | 0 | BHWv (psf->wchunks.chunks [k].data), BHWz (psf->wchunks.chunks [k].len)) ; |
1370 | |
|
1371 | 0 | } /* wavlike_write_custom_chunks */ |