commit patch for compiling on mingw32
[flac.git] / src / test_streams / main.c
1 /* test_streams - Simple test pattern generator
2  * Copyright (C) 2000,2001  Josh Coalson
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18
19 #include <math.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #if !defined _MSC_VER && !defined __MINGW32__
23 #include <sys/time.h>
24 #endif
25 #include "FLAC/assert.h"
26 #include "FLAC/ordinals.h"
27
28 #ifndef M_PI
29 /* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */
30 #define M_PI 3.14159265358979323846
31 #endif
32
33 #ifdef _WIN32
34         static const char *mode = "wb";
35 #else
36         static const char *mode = "w";
37 #endif
38
39 static FLAC__bool is_big_endian_host;
40
41 /* some flavors of UNIX #define this */
42 #ifdef swap16
43 #undef swap16
44 #endif
45 static void swap16(FLAC__int16 *i)
46 {
47         unsigned char *x = (unsigned char *)i, b;
48         if(!is_big_endian_host) {
49                 b = x[0];
50                 x[0] = x[1];
51                 x[1] = b;
52         }
53 }
54
55 static void swap24(FLAC__byte *x)
56 {
57         if(is_big_endian_host) {
58                 x[0] = x[1];
59                 x[1] = x[2];
60                 x[2] = x[3];
61         }
62         else {
63                 FLAC__byte b = x[0];
64                 x[0] = x[2];
65                 x[2] = b;
66         }
67 }
68
69 /* a mono one-sample 16bps stream */
70 static FLAC__bool generate_01()
71 {
72         FILE *f;
73         FLAC__int16 x = -32768;
74
75         if(0 == (f = fopen("test01.raw", mode)))
76                 return false;
77
78         swap16(&x);
79         if(fwrite(&x, sizeof(x), 1, f) < 1)
80                 goto foo;
81
82         fclose(f);
83         return true;
84 foo:
85         fclose(f);
86         return false;
87 }
88
89 /* a stereo one-sample 16bps stream */
90 static FLAC__bool generate_02()
91 {
92         FILE *f;
93         FLAC__int16 xl = -32768, xr = 32767;
94
95         if(0 == (f = fopen("test02.raw", mode)))
96                 return false;
97
98         swap16(&xl);
99         swap16(&xr);
100
101         if(fwrite(&xl, sizeof(xl), 1, f) < 1)
102                 goto foo;
103         if(fwrite(&xr, sizeof(xr), 1, f) < 1)
104                 goto foo;
105
106         fclose(f);
107         return true;
108 foo:
109         fclose(f);
110         return false;
111 }
112
113 /* a mono five-sample 16bps stream */
114 static FLAC__bool generate_03()
115 {
116         FILE *f;
117         FLAC__int16 x[] = { -25, 0, 25, 50, 100 };
118         unsigned i;
119
120         if(0 == (f = fopen("test03.raw", mode)))
121                 return false;
122
123         for(i = 0; i < 5; i++)
124                 swap16(x+i);
125
126         if(fwrite(&x, sizeof(FLAC__int16), 5, f) < 5)
127                 goto foo;
128
129         fclose(f);
130         return true;
131 foo:
132         fclose(f);
133         return false;
134 }
135
136 /* a stereo five-sample 16bps stream */
137 static FLAC__bool generate_04()
138 {
139         FILE *f;
140         FLAC__int16 x[] = { -25, 500, 0, 400, 25, 300, 50, 200, 100, 100 };
141         unsigned i;
142
143         if(0 == (f = fopen("test04.raw", mode)))
144                 return false;
145
146         for(i = 0; i < 10; i++)
147                 swap16(x+i);
148
149         if(fwrite(&x, sizeof(FLAC__int16), 10, f) < 10)
150                 goto foo;
151
152         fclose(f);
153         return true;
154 foo:
155         fclose(f);
156         return false;
157 }
158
159 /* a mono full-scale deflection 8bps stream */
160 static FLAC__bool generate_fsd8(const char *fn, const int pattern[], unsigned reps)
161 {
162         FILE *f;
163         unsigned rep, p;
164
165         FLAC__ASSERT(pattern != 0);
166
167         if(0 == (f = fopen(fn, mode)))
168                 return false;
169
170         for(rep = 0; rep < reps; rep++) {
171                 for(p = 0; pattern[p]; p++) {
172                         signed char x = pattern[p] > 0? 127 : -128;
173                         if(fwrite(&x, sizeof(x), 1, f) < 1)
174                                 goto foo;
175                 }
176         }
177
178         fclose(f);
179         return true;
180 foo:
181         fclose(f);
182         return false;
183 }
184
185 /* a mono full-scale deflection 16bps stream */
186 static FLAC__bool generate_fsd16(const char *fn, const int pattern[], unsigned reps)
187 {
188         FILE *f;
189         unsigned rep, p;
190
191         FLAC__ASSERT(pattern != 0);
192
193         if(0 == (f = fopen(fn, mode)))
194                 return false;
195
196         for(rep = 0; rep < reps; rep++) {
197                 for(p = 0; pattern[p]; p++) {
198                         FLAC__int16 x = pattern[p] > 0? 32767 : -32768;
199                         swap16(&x);
200                         if(fwrite(&x, sizeof(x), 1, f) < 1)
201                                 goto foo;
202                 }
203         }
204
205         fclose(f);
206         return true;
207 foo:
208         fclose(f);
209         return false;
210 }
211
212 /* a stereo wasted-bits-per-sample 16bps stream */
213 static FLAC__bool generate_wbps16(const char *fn, unsigned samples)
214 {
215         FILE *f;
216         unsigned sample;
217
218         if(0 == (f = fopen(fn, mode)))
219                 return false;
220
221         for(sample = 0; sample < samples; sample++) {
222                 FLAC__int16 l = (sample % 2000) << 2;
223                 FLAC__int16 r = (sample % 1000) << 3;
224                 swap16(&l);
225                 swap16(&r);
226                 if(fwrite(&l, sizeof(l), 1, f) < 1)
227                         goto foo;
228                 if(fwrite(&r, sizeof(r), 1, f) < 1)
229                         goto foo;
230         }
231
232         fclose(f);
233         return true;
234 foo:
235         fclose(f);
236         return false;
237 }
238
239 /* a mono full-scale deflection 24bps stream */
240 static FLAC__bool generate_fsd24(const char *fn, const int pattern[], unsigned reps)
241 {
242         FILE *f;
243         unsigned rep, p;
244
245         FLAC__ASSERT(pattern != 0);
246
247         if(0 == (f = fopen(fn, mode)))
248                 return false;
249
250         for(rep = 0; rep < reps; rep++) {
251                 for(p = 0; pattern[p]; p++) {
252                         FLAC__int32 x = pattern[p] > 0? 8388607 : -8388608;
253                         FLAC__byte *b = (FLAC__byte*)(&x);
254                         swap24(b);
255                         if(fwrite(b, 3, 1, f) < 1)
256                                 goto foo;
257                 }
258         }
259
260         fclose(f);
261         return true;
262 foo:
263         fclose(f);
264         return false;
265 }
266
267 /* a mono sine-wave 16bps stream */
268 static FLAC__bool generate_sine16_1(const char *fn, const double sample_rate, const unsigned samples, const double f1, const double a1, const double f2, const double a2)
269 {
270         const FLAC__int16 full_scale = 32767;
271         const double delta1 = 2.0 * M_PI / ( sample_rate / f1);
272         const double delta2 = 2.0 * M_PI / ( sample_rate / f2);
273         FILE *f;
274         double theta1, theta2;
275         unsigned i;
276
277         if(0 == (f = fopen(fn, mode)))
278                 return false;
279
280         for(i = 0, theta1 = theta2 = 0.0; i < samples; i++, theta1 += delta1, theta2 += delta2) {
281                 double val = (a1*sin(theta1) + a2*sin(theta2))*(double)full_scale;
282                 FLAC__int16 v = (FLAC__int16)(val + 0.5);
283                 swap16(&v);
284                 if(fwrite(&v, sizeof(v), 1, f) < 1)
285                         goto foo;
286         }
287
288         fclose(f);
289         return true;
290 foo:
291         fclose(f);
292         return false;
293 }
294
295 /* a stereo sine-wave 16bps stream */
296 static FLAC__bool generate_sine16_2(const char *fn, const double sample_rate, const unsigned samples, const double f1, const double a1, const double f2, const double a2, double fmult)
297 {
298         const FLAC__int16 full_scale = 32767;
299         const double delta1 = 2.0 * M_PI / ( sample_rate / f1);
300         const double delta2 = 2.0 * M_PI / ( sample_rate / f2);
301         FILE *f;
302         double theta1, theta2;
303         unsigned i;
304
305         if(0 == (f = fopen(fn, mode)))
306                 return false;
307
308         for(i = 0, theta1 = theta2 = 0.0; i < samples; i++, theta1 += delta1, theta2 += delta2) {
309                 double val = (a1*sin(theta1) + a2*sin(theta2))*(double)full_scale;
310                 FLAC__int16 v = (FLAC__int16)(val + 0.5);
311                 swap16(&v);
312                 if(fwrite(&v, sizeof(v), 1, f) < 1)
313                         goto foo;
314                 val = -(a1*sin(theta1*fmult) + a2*sin(theta2*fmult))*(double)full_scale;
315                 v = (FLAC__int16)(val + 0.5);
316                 swap16(&v);
317                 if(fwrite(&v, sizeof(v), 1, f) < 1)
318                         goto foo;
319         }
320
321         fclose(f);
322         return true;
323 foo:
324         fclose(f);
325         return false;
326 }
327
328 /* a mono sine-wave 24bps stream */
329 static FLAC__bool generate_sine24_1(const char *fn, const double sample_rate, const unsigned samples, const double f1, const double a1, const double f2, const double a2)
330 {
331         const FLAC__int32 full_scale = 0x7fffff;
332         const double delta1 = 2.0 * M_PI / ( sample_rate / f1);
333         const double delta2 = 2.0 * M_PI / ( sample_rate / f2);
334         FILE *f;
335         double theta1, theta2;
336         unsigned i;
337
338         if(0 == (f = fopen(fn, mode)))
339                 return false;
340
341         for(i = 0, theta1 = theta2 = 0.0; i < samples; i++, theta1 += delta1, theta2 += delta2) {
342                 double val = (a1*sin(theta1) + a2*sin(theta2))*(double)full_scale;
343                 FLAC__int32 v = (FLAC__int32)(val + 0.5);
344                 FLAC__byte *b = (FLAC__byte*)(&v);
345                 swap24(b);
346                 if(fwrite(b, 3, 1, f) < 1)
347                         goto foo;
348         }
349
350         fclose(f);
351         return true;
352 foo:
353         fclose(f);
354         return false;
355 }
356
357 /* a stereo sine-wave 24bps stream */
358 static FLAC__bool generate_sine24_2(const char *fn, const double sample_rate, const unsigned samples, const double f1, const double a1, const double f2, const double a2, double fmult)
359 {
360         const FLAC__int32 full_scale = 0x7fffff;
361         const double delta1 = 2.0 * M_PI / ( sample_rate / f1);
362         const double delta2 = 2.0 * M_PI / ( sample_rate / f2);
363         FILE *f;
364         double theta1, theta2;
365         unsigned i;
366
367         if(0 == (f = fopen(fn, mode)))
368                 return false;
369
370         for(i = 0, theta1 = theta2 = 0.0; i < samples; i++, theta1 += delta1, theta2 += delta2) {
371                 double val = (a1*sin(theta1) + a2*sin(theta2))*(double)full_scale;
372                 FLAC__int32 v = (FLAC__int32)(val + 0.5);
373                 FLAC__byte *b = (FLAC__byte*)(&v);
374                 swap24(b);
375                 if(fwrite(b, 3, 1, f) < 1)
376                         goto foo;
377                 val = -(a1*sin(theta1*fmult) + a2*sin(theta2*fmult))*(double)full_scale;
378                 v = (FLAC__int32)(val + 0.5);
379                 swap24(b);
380                 if(fwrite(b, 3, 1, f) < 1)
381                         goto foo;
382         }
383
384         fclose(f);
385         return true;
386 foo:
387         fclose(f);
388         return false;
389 }
390
391 static FLAC__bool generate_noise(const char *fn, unsigned bytes)
392 {
393         FILE *f;
394         unsigned b;
395 #if !defined _MSC_VER && !defined __MINGW32__
396         struct timeval tv;
397
398         if(gettimeofday(&tv, 0) < 0) {
399                 fprintf(stderr, "WARNING: couldn't seed RNG with time\n");
400                 tv.tv_usec = 4321;
401         }
402         srandom(tv.tv_usec);
403 #else
404         /* who has the patience to figure out how to do RNG with VC++? */
405 #endif
406
407         if(0 == (f = fopen(fn, mode)))
408                 return false;
409
410         for(b = 0; b < bytes; b++) {
411 #if !defined _MSC_VER && !defined __MINGW32__
412                 FLAC__byte x = (FLAC__byte)(((unsigned)random()) & 0xff);
413 #else
414                 FLAC__byte x = (FLAC__byte)((((unsigned)generate_noise) >> 8) ^ (b * 17)); /* fake it */
415 #endif
416                 if(fwrite(&x, sizeof(x), 1, f) < 1)
417                         goto foo;
418         }
419
420         fclose(f);
421         return true;
422 foo:
423         fclose(f);
424         return false;
425 }
426
427 static FLAC__bool generate_wackywavs()
428 {
429         FILE *f;
430         FLAC__byte wav[] = {
431                 'R', 'I', 'F', 'F',  76,   0,   0,   0,
432                 'W', 'A', 'V', 'E', 'f', 'a', 'c', 't',
433                   4,   0,   0,  0 , 'b', 'l', 'a', 'h',
434                 'p', 'a', 'd', ' ',   4,   0,   0,   0,
435                 'B', 'L', 'A', 'H', 'f', 'm', 't', ' ',
436                  16,   0,   0,   0,   1,   0,   1,   0,
437                 0x44,0xAC,  0,   0,   0,   0,   0,   0,
438                   2,   0,  16,   0, 'd', 'a', 't', 'a',
439                  16,   0,   0,   0,   0,   0,   1,   0,
440                   4,   0,   9,   0,  16,   0,  25,   0,
441                  36,   0,  49,   0, 'p', 'a', 'd', ' ',
442                   4,   0,   0,   0, 'b', 'l', 'a', 'h'
443         };
444
445         if(0 == (f = fopen("wacky1.wav", mode)))
446                 return false;
447         if(fwrite(wav, 1, 84, f) < 84)
448                 goto foo;
449         fclose(f);
450
451         wav[4] += 12;
452         if(0 == (f = fopen("wacky2.wav", mode)))
453                 return false;
454         if(fwrite(wav, 1, 96, f) < 96)
455                 goto foo;
456         fclose(f);
457
458         return true;
459 foo:
460         fclose(f);
461         return false;
462 }
463
464 int main(int argc, char *argv[])
465 {
466         FLAC__uint32 test = 1;
467
468         int pattern01[] = { 1, -1, 0 };
469         int pattern02[] = { 1, 1, -1, 0 };
470         int pattern03[] = { 1, -1, -1, 0 };
471         int pattern04[] = { 1, -1, 1, -1, 0 };
472         int pattern05[] = { 1, -1, -1, 1, 0 };
473         int pattern06[] = { 1, -1, 1, 1, -1, 0 };
474         int pattern07[] = { 1, -1, -1, 1, -1, 0 };
475
476         (void)argc;
477         (void)argv;
478         is_big_endian_host = (*((FLAC__byte*)(&test)))? false : true;
479
480         if(!generate_01()) return 1;
481         if(!generate_02()) return 1;
482         if(!generate_03()) return 1;
483         if(!generate_04()) return 1;
484
485         if(!generate_fsd8("fsd8-01.raw", pattern01, 100)) return 1;
486         if(!generate_fsd8("fsd8-02.raw", pattern02, 100)) return 1;
487         if(!generate_fsd8("fsd8-03.raw", pattern03, 100)) return 1;
488         if(!generate_fsd8("fsd8-04.raw", pattern04, 100)) return 1;
489         if(!generate_fsd8("fsd8-05.raw", pattern05, 100)) return 1;
490         if(!generate_fsd8("fsd8-06.raw", pattern06, 100)) return 1;
491         if(!generate_fsd8("fsd8-07.raw", pattern07, 100)) return 1;
492
493         if(!generate_fsd16("fsd16-01.raw", pattern01, 100)) return 1;
494         if(!generate_fsd16("fsd16-02.raw", pattern02, 100)) return 1;
495         if(!generate_fsd16("fsd16-03.raw", pattern03, 100)) return 1;
496         if(!generate_fsd16("fsd16-04.raw", pattern04, 100)) return 1;
497         if(!generate_fsd16("fsd16-05.raw", pattern05, 100)) return 1;
498         if(!generate_fsd16("fsd16-06.raw", pattern06, 100)) return 1;
499         if(!generate_fsd16("fsd16-07.raw", pattern07, 100)) return 1;
500
501         if(!generate_fsd24("fsd24-01.raw", pattern01, 100)) return 1;
502         if(!generate_fsd24("fsd24-02.raw", pattern02, 100)) return 1;
503         if(!generate_fsd24("fsd24-03.raw", pattern03, 100)) return 1;
504         if(!generate_fsd24("fsd24-04.raw", pattern04, 100)) return 1;
505         if(!generate_fsd24("fsd24-05.raw", pattern05, 100)) return 1;
506         if(!generate_fsd24("fsd24-06.raw", pattern06, 100)) return 1;
507         if(!generate_fsd24("fsd24-07.raw", pattern07, 100)) return 1;
508
509         if(!generate_wbps16("wbps16-01.raw", 1000)) return 1;
510
511         if(!generate_sine16_1("sine16-00.raw", 44100.0, 80000, 441.0, 0.50, 441.0, 0.49)) return 1;
512         if(!generate_sine16_1("sine16-01.raw", 44100.0, 80000, 441.0, 0.61, 661.5, 0.37)) return 1;
513         if(!generate_sine16_1("sine16-02.raw", 44100.0, 80000, 441.0, 0.50, 882.0, 0.49)) return 1;
514         if(!generate_sine16_1("sine16-03.raw", 44100.0, 80000, 441.0, 0.50, 4410.0, 0.49)) return 1;
515         if(!generate_sine16_1("sine16-04.raw", 44100.0, 50000, 8820.0, 0.70, 4410.0, 0.29)) return 1;
516
517         if(!generate_sine16_2("sine16-10.raw", 44100.0, 80000, 441.0, 0.50, 441.0, 0.49, 1.0)) return 1;
518         if(!generate_sine16_2("sine16-11.raw", 44100.0, 80000, 441.0, 0.61, 661.5, 0.37, 1.0)) return 1;
519         if(!generate_sine16_2("sine16-12.raw", 44100.0, 80000, 441.0, 0.50, 882.0, 0.49, 1.0)) return 1;
520         if(!generate_sine16_2("sine16-13.raw", 44100.0, 80000, 441.0, 0.50, 4410.0, 0.49, 1.0)) return 1;
521         if(!generate_sine16_2("sine16-14.raw", 44100.0, 50000, 8820.0, 0.70, 4410.0, 0.29, 1.0)) return 1;
522         if(!generate_sine16_2("sine16-15.raw", 44100.0, 80000, 441.0, 0.50, 441.0, 0.49, 0.5)) return 1;
523         if(!generate_sine16_2("sine16-16.raw", 44100.0, 80000, 441.0, 0.61, 661.5, 0.37, 2.0)) return 1;
524         if(!generate_sine16_2("sine16-17.raw", 44100.0, 80000, 441.0, 0.50, 882.0, 0.49, 0.7)) return 1;
525         if(!generate_sine16_2("sine16-18.raw", 44100.0, 80000, 441.0, 0.50, 4410.0, 0.49, 1.3)) return 1;
526         if(!generate_sine16_2("sine16-19.raw", 44100.0, 50000, 8820.0, 0.70, 4410.0, 0.29, 0.1)) return 1;
527
528         if(!generate_sine24_1("sine24-00.raw", 44100.0, 80000, 441.0, 0.50, 441.0, 0.49)) return 1;
529         if(!generate_sine24_1("sine24-01.raw", 44100.0, 80000, 441.0, 0.61, 661.5, 0.37)) return 1;
530         if(!generate_sine24_1("sine24-02.raw", 44100.0, 80000, 441.0, 0.50, 882.0, 0.49)) return 1;
531         if(!generate_sine24_1("sine24-03.raw", 44100.0, 80000, 441.0, 0.50, 4410.0, 0.49)) return 1;
532         if(!generate_sine24_1("sine24-04.raw", 44100.0, 50000, 8820.0, 0.70, 4410.0, 0.29)) return 1;
533
534         if(!generate_sine24_2("sine24-10.raw", 44100.0, 80000, 441.0, 0.50, 441.0, 0.49, 1.0)) return 1;
535         if(!generate_sine24_2("sine24-11.raw", 44100.0, 80000, 441.0, 0.61, 661.5, 0.37, 1.0)) return 1;
536         if(!generate_sine24_2("sine24-12.raw", 44100.0, 80000, 441.0, 0.50, 882.0, 0.49, 1.0)) return 1;
537         if(!generate_sine24_2("sine24-13.raw", 44100.0, 80000, 441.0, 0.50, 4410.0, 0.49, 1.0)) return 1;
538         if(!generate_sine24_2("sine24-14.raw", 44100.0, 50000, 8820.0, 0.70, 4410.0, 0.29, 1.0)) return 1;
539         if(!generate_sine24_2("sine24-15.raw", 44100.0, 80000, 441.0, 0.50, 441.0, 0.49, 0.5)) return 1;
540         if(!generate_sine24_2("sine24-16.raw", 44100.0, 80000, 441.0, 0.61, 661.5, 0.37, 2.0)) return 1;
541         if(!generate_sine24_2("sine24-17.raw", 44100.0, 80000, 441.0, 0.50, 882.0, 0.49, 0.7)) return 1;
542         if(!generate_sine24_2("sine24-18.raw", 44100.0, 80000, 441.0, 0.50, 4410.0, 0.49, 1.3)) return 1;
543         if(!generate_sine24_2("sine24-19.raw", 44100.0, 50000, 8820.0, 0.70, 4410.0, 0.29, 0.1)) return 1;
544
545         if(!generate_noise("noise.raw", 65536 * 8 * 3)) return 1;
546         if(!generate_wackywavs()) return 1;
547
548         return 0;
549 }