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