c84bbb6c409794dbcc05c08417ea268f52758720
[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 #include <assert.h>
23 #include <sys/time.h>
24 #include "FLAC/ordinals.h"
25
26 #ifdef _WIN32
27         static const char *mode = "wb";
28 #else
29         static const char *mode = "w";
30 #endif
31
32 static bool is_big_endian_host;
33
34 static void swap16(int16 *i)
35 {
36         unsigned char *x = (unsigned char *)i, b;
37         if(!is_big_endian_host) {
38                 b = x[0];
39                 x[0] = x[1];
40                 x[1] = b;
41         }
42 }
43
44 /* a mono one-sample 16bps stream */
45 static bool generate_01()
46 {
47         FILE *f;
48         int16 x = -32768;
49
50         if(0 == (f = fopen("test01.raw", mode)))
51                 return false;
52
53         swap16(&x);
54         if(fwrite(&x, sizeof(x), 1, f) < 1)
55                 goto foo;
56
57         fclose(f);
58         return true;
59 foo:
60         fclose(f);
61         return false;
62 }
63
64 /* a stereo one-sample 16bps stream */
65 static bool generate_02()
66 {
67         FILE *f;
68         int16 xl = -32768, xr = 32767;
69
70         if(0 == (f = fopen("test02.raw", mode)))
71                 return false;
72
73         swap16(&xl);
74         swap16(&xr);
75
76         if(fwrite(&xl, sizeof(xl), 1, f) < 1)
77                 goto foo;
78         if(fwrite(&xr, sizeof(xr), 1, f) < 1)
79                 goto foo;
80
81         fclose(f);
82         return true;
83 foo:
84         fclose(f);
85         return false;
86 }
87
88 /* a mono five-sample 16bps stream */
89 static bool generate_03()
90 {
91         FILE *f;
92         int16 x[] = { -25, 0, 25, 50, 100 };
93         unsigned i;
94
95         if(0 == (f = fopen("test03.raw", mode)))
96                 return false;
97
98         for(i = 0; i < 5; i++)
99                 swap16(x+i);
100
101         if(fwrite(&x, sizeof(int16), 5, f) < 5)
102                 goto foo;
103
104         fclose(f);
105         return true;
106 foo:
107         fclose(f);
108         return false;
109 }
110
111 /* a stereo five-sample 16bps stream */
112 static bool generate_04()
113 {
114         FILE *f;
115         int16 x[] = { -25, 500, 0, 400, 25, 300, 50, 200, 100, 100 };
116         unsigned i;
117
118         if(0 == (f = fopen("test04.raw", mode)))
119                 return false;
120
121         for(i = 0; i < 10; i++)
122                 swap16(x+i);
123
124         if(fwrite(&x, sizeof(int16), 10, f) < 10)
125                 goto foo;
126
127         fclose(f);
128         return true;
129 foo:
130         fclose(f);
131         return false;
132 }
133
134 /* a mono full-scale deflection 8bps stream */
135 static bool generate_fsd8(const char *fn, const int pattern[], unsigned reps)
136 {
137         FILE *f;
138         unsigned rep, p;
139
140         assert(pattern != 0);
141
142         if(0 == (f = fopen(fn, mode)))
143                 return false;
144
145         for(rep = 0; rep < reps; rep++) {
146                 for(p = 0; pattern[p]; p++) {
147                         signed char x = pattern[p] > 0? 127 : -128;
148                         if(fwrite(&x, sizeof(x), 1, f) < 1)
149                                 goto foo;
150                 }
151         }
152
153         fclose(f);
154         return true;
155 foo:
156         fclose(f);
157         return false;
158 }
159
160 /* a mono full-scale deflection 16bps stream */
161 static bool generate_fsd16(const char *fn, const int pattern[], unsigned reps)
162 {
163         FILE *f;
164         unsigned rep, p;
165
166         assert(pattern != 0);
167
168         if(0 == (f = fopen(fn, mode)))
169                 return false;
170
171         for(rep = 0; rep < reps; rep++) {
172                 for(p = 0; pattern[p]; p++) {
173                         int16 x = pattern[p] > 0? 32767 : -32768;
174                         swap16(&x);
175                         if(fwrite(&x, sizeof(x), 1, f) < 1)
176                                 goto foo;
177                 }
178         }
179
180         fclose(f);
181         return true;
182 foo:
183         fclose(f);
184         return false;
185 }
186
187 /* a mono sine-wave 16bps stream */
188 static 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)
189 {
190         const signed short full_scale = 32767;
191         const double delta1 = 2.0 * M_PI / ( sample_rate / f1);
192         const double delta2 = 2.0 * M_PI / ( sample_rate / f2);
193         FILE *f;
194         double theta1, theta2;
195         unsigned i;
196
197         if(0 == (f = fopen(fn, mode)))
198                 return false;
199
200         for(i = 0, theta1 = theta2 = 0.0; i < samples; i++, theta1 += delta1, theta2 += delta2) {
201                 double val = (a1*sin(theta1) + a2*sin(theta2))*(double)full_scale;
202                 int16 v = (int16)(val + 0.5);
203                 swap16(&v);
204                 if(fwrite(&v, sizeof(v), 1, f) < 1)
205                         goto foo;
206         }
207
208         fclose(f);
209         return true;
210 foo:
211         fclose(f);
212         return false;
213 }
214
215 /* a stereo sine-wave 16bps stream */
216 static 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)
217 {
218         const signed short full_scale = 32767;
219         const double delta1 = 2.0 * M_PI / ( sample_rate / f1);
220         const double delta2 = 2.0 * M_PI / ( sample_rate / f2);
221         FILE *f;
222         double theta1, theta2;
223         unsigned i;
224
225         if(0 == (f = fopen(fn, mode)))
226                 return false;
227
228         for(i = 0, theta1 = theta2 = 0.0; i < samples; i++, theta1 += delta1, theta2 += delta2) {
229                 double val = (a1*sin(theta1) + a2*sin(theta2))*(double)full_scale;
230                 int16 v = (int16)(val + 0.5);
231                 swap16(&v);
232                 if(fwrite(&v, sizeof(v), 1, f) < 1)
233                         goto foo;
234                 val = -(a1*sin(theta1*fmult) + a2*sin(theta2*fmult))*(double)full_scale;
235                 v = (int16)(val + 0.5);
236                 swap16(&v);
237                 if(fwrite(&v, sizeof(v), 1, f) < 1)
238                         goto foo;
239         }
240
241         fclose(f);
242         return true;
243 foo:
244         fclose(f);
245         return false;
246 }
247
248 static bool generate_noise(const char *fn, unsigned bytes)
249 {
250         FILE *f;
251         struct timeval tv;
252         unsigned b;
253
254         if(gettimeofday(&tv, 0) < 0) {
255                 fprintf(stderr, "WARNING: couldn't seed RNG with time\n");
256                 tv.tv_usec = 4321;
257         }
258         srandom(tv.tv_usec);
259
260         if(0 == (f = fopen(fn, mode)))
261                 return false;
262
263         for(b = 0; b < bytes; b++) {
264                 byte x = (byte)(((unsigned)random()) & 0xff);
265                 if(fwrite(&x, sizeof(x), 1, f) < 1)
266                         goto foo;
267         }
268
269         fclose(f);
270         return true;
271 foo:
272         fclose(f);
273         return false;
274 }
275
276 int main(int argc, char *argv[])
277 {
278         uint32 test = 1;
279
280         int pattern01[] = { 1, -1, 0 };
281         int pattern02[] = { 1, 1, -1, 0 };
282         int pattern03[] = { 1, -1, -1, 0 };
283         int pattern04[] = { 1, -1, 1, -1, 0 };
284         int pattern05[] = { 1, -1, -1, 1, 0 };
285         int pattern06[] = { 1, -1, 1, 1, -1, 0 };
286         int pattern07[] = { 1, -1, -1, 1, -1, 0 };
287
288         (void)argc;
289         (void)argv;
290         is_big_endian_host = (*((byte*)(&test)))? false : true;
291
292         if(!generate_01()) return 1;
293         if(!generate_02()) return 1;
294         if(!generate_03()) return 1;
295         if(!generate_04()) return 1;
296
297         if(!generate_fsd8("fsd8-01.raw", pattern01, 100)) return 1;
298         if(!generate_fsd8("fsd8-02.raw", pattern02, 100)) return 1;
299         if(!generate_fsd8("fsd8-03.raw", pattern03, 100)) return 1;
300         if(!generate_fsd8("fsd8-04.raw", pattern04, 100)) return 1;
301         if(!generate_fsd8("fsd8-05.raw", pattern05, 100)) return 1;
302         if(!generate_fsd8("fsd8-06.raw", pattern06, 100)) return 1;
303         if(!generate_fsd8("fsd8-07.raw", pattern07, 100)) return 1;
304
305         if(!generate_fsd16("fsd16-01.raw", pattern01, 100)) return 1;
306         if(!generate_fsd16("fsd16-02.raw", pattern02, 100)) return 1;
307         if(!generate_fsd16("fsd16-03.raw", pattern03, 100)) return 1;
308         if(!generate_fsd16("fsd16-04.raw", pattern04, 100)) return 1;
309         if(!generate_fsd16("fsd16-05.raw", pattern05, 100)) return 1;
310         if(!generate_fsd16("fsd16-06.raw", pattern06, 100)) return 1;
311         if(!generate_fsd16("fsd16-07.raw", pattern07, 100)) return 1;
312
313         if(!generate_sine16_1("sine-00.raw", 44100.0, 80000, 441.0, 0.50, 441.0, 0.49)) return 1;
314         if(!generate_sine16_1("sine-01.raw", 44100.0, 80000, 441.0, 0.61, 661.5, 0.37)) return 1;
315         if(!generate_sine16_1("sine-02.raw", 44100.0, 80000, 441.0, 0.50, 882.0, 0.49)) return 1;
316         if(!generate_sine16_1("sine-03.raw", 44100.0, 80000, 441.0, 0.50, 4410.0, 0.49)) return 1;
317         if(!generate_sine16_1("sine-04.raw", 44100.0, 50000, 8820.0, 0.70, 4410.0, 0.29)) return 1;
318
319         if(!generate_sine16_2("sine-10.raw", 44100.0, 80000, 441.0, 0.50, 441.0, 0.49, 1.0)) return 1;
320         if(!generate_sine16_2("sine-11.raw", 44100.0, 80000, 441.0, 0.61, 661.5, 0.37, 1.0)) return 1;
321         if(!generate_sine16_2("sine-12.raw", 44100.0, 80000, 441.0, 0.50, 882.0, 0.49, 1.0)) return 1;
322         if(!generate_sine16_2("sine-13.raw", 44100.0, 80000, 441.0, 0.50, 4410.0, 0.49, 1.0)) return 1;
323         if(!generate_sine16_2("sine-14.raw", 44100.0, 50000, 8820.0, 0.70, 4410.0, 0.29, 1.0)) return 1;
324         if(!generate_sine16_2("sine-15.raw", 44100.0, 80000, 441.0, 0.50, 441.0, 0.49, 0.5)) return 1;
325         if(!generate_sine16_2("sine-16.raw", 44100.0, 80000, 441.0, 0.61, 661.5, 0.37, 2.0)) return 1;
326         if(!generate_sine16_2("sine-17.raw", 44100.0, 80000, 441.0, 0.50, 882.0, 0.49, 0.7)) return 1;
327         if(!generate_sine16_2("sine-18.raw", 44100.0, 80000, 441.0, 0.50, 4410.0, 0.49, 1.3)) return 1;
328         if(!generate_sine16_2("sine-19.raw", 44100.0, 50000, 8820.0, 0.70, 4410.0, 0.29, 0.1)) return 1;
329
330         if(!generate_noise("noise.raw", 65536 * 2)) return 1;
331
332         return 0;
333 }