movenc: Make tkhd "enabled" flag QuickTime compatible
[libav.git] / tests / audiogen.c
CommitLineData
51133a7d 1/*
58c42af7
DB
2 * Generate a synthetic stereo sound.
3 * NOTE: No floats are used to guarantee bitexact output.
eebfba2e
DB
4 *
5 * Copyright (c) 2002 Fabrice Bellard
6 *
2912e87a 7 * This file is part of Libav.
eebfba2e 8 *
2912e87a 9 * Libav is free software; you can redistribute it and/or
eebfba2e
DB
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
2912e87a 14 * Libav is distributed in the hope that it will be useful,
eebfba2e
DB
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
2912e87a 20 * License along with Libav; if not, write to the Free Software
eebfba2e 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
51133a7d 22 */
eebfba2e 23
51133a7d 24#include <stdlib.h>
010943c6 25#include <stdint.h>
51133a7d 26#include <stdio.h>
010943c6 27#include <string.h>
51133a7d 28
6c834328 29#define MAX_CHANNELS 8
51133a7d
FB
30
31static unsigned int myrnd(unsigned int *seed_ptr, int n)
32{
33 unsigned int seed, val;
34
35 seed = *seed_ptr;
36 seed = (seed * 314159) + 1;
37 if (n == 256) {
38 val = seed >> 24;
39 } else {
40 val = seed % n;
41 }
42 *seed_ptr = seed;
43 return val;
44}
45
46#define FRAC_BITS 16
47#define FRAC_ONE (1 << FRAC_BITS)
48
49#define COS_TABLE_BITS 7
50
03039f4c 51/* integer cosine */
51133a7d 52static const unsigned short cos_table[(1 << COS_TABLE_BITS) + 2] = {
b481bbc3
GN
53 0x8000, 0x7ffe, 0x7ff6, 0x7fea, 0x7fd9, 0x7fc2, 0x7fa7, 0x7f87,
54 0x7f62, 0x7f38, 0x7f0a, 0x7ed6, 0x7e9d, 0x7e60, 0x7e1e, 0x7dd6,
55 0x7d8a, 0x7d3a, 0x7ce4, 0x7c89, 0x7c2a, 0x7bc6, 0x7b5d, 0x7aef,
56 0x7a7d, 0x7a06, 0x798a, 0x790a, 0x7885, 0x77fb, 0x776c, 0x76d9,
57 0x7642, 0x75a6, 0x7505, 0x7460, 0x73b6, 0x7308, 0x7255, 0x719e,
58 0x70e3, 0x7023, 0x6f5f, 0x6e97, 0x6dca, 0x6cf9, 0x6c24, 0x6b4b,
59 0x6a6e, 0x698c, 0x68a7, 0x67bd, 0x66d0, 0x65de, 0x64e9, 0x63ef,
60 0x62f2, 0x61f1, 0x60ec, 0x5fe4, 0x5ed7, 0x5dc8, 0x5cb4, 0x5b9d,
61 0x5a82, 0x5964, 0x5843, 0x571e, 0x55f6, 0x54ca, 0x539b, 0x5269,
62 0x5134, 0x4ffb, 0x4ec0, 0x4d81, 0x4c40, 0x4afb, 0x49b4, 0x486a,
63 0x471d, 0x45cd, 0x447b, 0x4326, 0x41ce, 0x4074, 0x3f17, 0x3db8,
64 0x3c57, 0x3af3, 0x398d, 0x3825, 0x36ba, 0x354e, 0x33df, 0x326e,
65 0x30fc, 0x2f87, 0x2e11, 0x2c99, 0x2b1f, 0x29a4, 0x2827, 0x26a8,
66 0x2528, 0x23a7, 0x2224, 0x209f, 0x1f1a, 0x1d93, 0x1c0c, 0x1a83,
67 0x18f9, 0x176e, 0x15e2, 0x1455, 0x12c8, 0x113a, 0x0fab, 0x0e1c,
68 0x0c8c, 0x0afb, 0x096b, 0x07d9, 0x0648, 0x04b6, 0x0324, 0x0192,
69 0x0000, 0x0000,
51133a7d
FB
70};
71
72#define CSHIFT (FRAC_BITS - COS_TABLE_BITS - 2)
73
74static int int_cos(int a)
75{
76 int neg, v, f;
77 const unsigned short *p;
78
79 a = a & (FRAC_ONE - 1); /* modulo 2 * pi */
80 if (a >= (FRAC_ONE / 2))
81 a = FRAC_ONE - a;
82 neg = 0;
83 if (a > (FRAC_ONE / 4)) {
84 neg = -1;
b481bbc3 85 a = (FRAC_ONE / 2) - a;
51133a7d
FB
86 }
87 p = cos_table + (a >> CSHIFT);
88 /* linear interpolation */
89 f = a & ((1 << CSHIFT) - 1);
90 v = p[0] + (((p[1] - p[0]) * f + (1 << (CSHIFT - 1))) >> CSHIFT);
91 v = (v ^ neg) - neg;
92 v = v << (FRAC_BITS - 15);
93 return v;
94}
95
96FILE *outfile;
97
010943c6 98static void put16(int16_t v)
51133a7d 99{
010943c6 100 fputc( v & 0xff, outfile);
51133a7d
FB
101 fputc((v >> 8) & 0xff, outfile);
102}
103
010943c6
JR
104static void put32(uint32_t v)
105{
106 fputc( v & 0xff, outfile);
107 fputc((v >> 8) & 0xff, outfile);
108 fputc((v >> 16) & 0xff, outfile);
109 fputc((v >> 24) & 0xff, outfile);
110}
111
112#define HEADER_SIZE 46
113#define FMT_SIZE 18
114#define SAMPLE_SIZE 2
115#define WFORMAT_PCM 0x0001
116
117static void put_wav_header(int sample_rate, int channels, int nb_samples)
118{
119 int block_align = SAMPLE_SIZE * channels;
120 int data_size = block_align * nb_samples;
121
122 fputs("RIFF", outfile);
123 put32(HEADER_SIZE + data_size);
124 fputs("WAVEfmt ", outfile);
125 put32(FMT_SIZE);
126 put16(WFORMAT_PCM);
127 put16(channels);
128 put32(sample_rate);
129 put32(block_align * sample_rate);
130 put16(block_align);
131 put16(SAMPLE_SIZE * 8);
132 put16(0);
133 fputs("data", outfile);
134 put32(data_size);
135}
136
51133a7d
FB
137int main(int argc, char **argv)
138{
139 int i, a, v, j, f, amp, ampa;
140 unsigned int seed = 1;
6c834328
JR
141 int tabf1[MAX_CHANNELS], tabf2[MAX_CHANNELS];
142 int taba[MAX_CHANNELS];
143 int sample_rate = 44100;
144 int nb_channels = 2;
010943c6 145 char *ext;
6c834328 146
67ef5f4e
AK
147 if (argc < 2 || argc > 5) {
148 printf("usage: %s file [<sample rate> [<channels>] [<random seed>]]\n"
6c834328 149 "generate a test raw 16 bit audio stream\n"
010943c6 150 "If the file extension is .wav a WAVE header will be added.\n"
6c834328 151 "default: 44100 Hz stereo\n", argv[0]);
51133a7d
FB
152 exit(1);
153 }
115329f1 154
6c834328
JR
155 if (argc > 2) {
156 sample_rate = atoi(argv[2]);
157 if (sample_rate <= 0) {
158 fprintf(stderr, "invalid sample rate: %d\n", sample_rate);
159 return 1;
160 }
161 }
162
163 if (argc > 3) {
164 nb_channels = atoi(argv[3]);
165 if (nb_channels < 1 || nb_channels > MAX_CHANNELS) {
166 fprintf(stderr, "invalid number of channels: %d\n", nb_channels);
167 return 1;
168 }
169 }
170
67ef5f4e
AK
171 if (argc > 4)
172 seed = atoi(argv[4]);
173
baf23f0c 174 outfile = fopen(argv[1], "wb");
51133a7d
FB
175 if (!outfile) {
176 perror(argv[1]);
177 return 1;
178 }
179
010943c6
JR
180 if ((ext = strrchr(argv[1], '.')) != NULL && !strcmp(ext, ".wav"))
181 put_wav_header(sample_rate, nb_channels, 6 * sample_rate);
182
03039f4c 183 /* 1 second of single freq sine at 1000 Hz */
51133a7d 184 a = 0;
b481bbc3 185 for (i = 0; i < 1 * sample_rate; i++) {
51133a7d 186 v = (int_cos(a) * 10000) >> FRAC_BITS;
b481bbc3 187 for (j = 0; j < nb_channels; j++)
010943c6 188 put16(v);
6c834328 189 a += (1000 * FRAC_ONE) / sample_rate;
51133a7d
FB
190 }
191
511cf612 192 /* 1 second of varying frequency between 100 and 10000 Hz */
51133a7d 193 a = 0;
b481bbc3 194 for (i = 0; i < 1 * sample_rate; i++) {
51133a7d 195 v = (int_cos(a) * 10000) >> FRAC_BITS;
b481bbc3 196 for (j = 0; j < nb_channels; j++)
010943c6 197 put16(v);
b481bbc3 198 f = 100 + (((10000 - 100) * i) / sample_rate);
6c834328 199 a += (f * FRAC_ONE) / sample_rate;
51133a7d 200 }
115329f1 201
51133a7d 202 /* 0.5 second of low amplitude white noise */
b481bbc3 203 for (i = 0; i < sample_rate / 2; i++) {
51133a7d 204 v = myrnd(&seed, 20000) - 10000;
b481bbc3 205 for (j = 0; j < nb_channels; j++)
010943c6 206 put16(v);
51133a7d
FB
207 }
208
209 /* 0.5 second of high amplitude white noise */
b481bbc3 210 for (i = 0; i < sample_rate / 2; i++) {
51133a7d 211 v = myrnd(&seed, 65535) - 32768;
b481bbc3 212 for (j = 0; j < nb_channels; j++)
010943c6 213 put16(v);
51133a7d
FB
214 }
215
6c834328 216 /* 1 second of unrelated ramps for each channel */
b481bbc3
GN
217 for (j = 0; j < nb_channels; j++) {
218 taba[j] = 0;
51133a7d
FB
219 tabf1[j] = 100 + myrnd(&seed, 5000);
220 tabf2[j] = 100 + myrnd(&seed, 5000);
221 }
b481bbc3
GN
222 for (i = 0; i < 1 * sample_rate; i++) {
223 for (j = 0; j < nb_channels; j++) {
51133a7d 224 v = (int_cos(taba[j]) * 10000) >> FRAC_BITS;
010943c6 225 put16(v);
b481bbc3 226 f = tabf1[j] + (((tabf2[j] - tabf1[j]) * i) / sample_rate);
6c834328 227 taba[j] += (f * FRAC_ONE) / sample_rate;
51133a7d
FB
228 }
229 }
115329f1 230
6c834328 231 /* 2 seconds of 500 Hz with varying volume */
b481bbc3 232 a = 0;
51133a7d 233 ampa = 0;
b481bbc3
GN
234 for (i = 0; i < 2 * sample_rate; i++) {
235 for (j = 0; j < nb_channels; j++) {
51133a7d
FB
236 amp = ((FRAC_ONE + int_cos(ampa)) * 5000) >> FRAC_BITS;
237 if (j & 1)
238 amp = 10000 - amp;
239 v = (int_cos(a) * amp) >> FRAC_BITS;
010943c6 240 put16(v);
b481bbc3 241 a += (500 * FRAC_ONE) / sample_rate;
6c834328 242 ampa += (2 * FRAC_ONE) / sample_rate;
51133a7d
FB
243 }
244 }
245
246 fclose(outfile);
247 return 0;
248}