Noble Ape
The Central Directories of the Noble Ape Simulation.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
audio.c
Go to the documentation of this file.
1 /****************************************************************
2 
3  audio.c
4 
5  =============================================================
6 
7  Copyright 1996-2014 Tom Barbalet. All rights reserved.
8 
9  Permission is hereby granted, free of charge, to any person
10  obtaining a copy of this software and associated documentation
11  files (the "Software"), to deal in the Software without
12  restriction, including without limitation the rights to use,
13  copy, modify, merge, publish, distribute, sublicense, and/or
14  sell copies of the Software, and to permit persons to whom the
15  Software is furnished to do so, subject to the following
16  conditions:
17 
18  The above copyright notice and this permission notice shall be
19  included in all copies or substantial portions of the Software.
20 
21  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  OTHER DEALINGS IN THE SOFTWARE.
29 
30  This software and Noble Ape are a continuing work of Tom Barbalet,
31  begun on 13 June 1996. No apes or cats were harmed in the writing
32  of this software.
33 
34  ****************************************************************/
35 
41 #include "noble.h"
42 #include <math.h>
43 #include <stdio.h>
44 
45 static n_double frequency[AUDIO_FFT_MAX_BUFFER];
46 static n_double timedomain[AUDIO_FFT_MAX_BUFFER];
47 static n_double frequencyi[AUDIO_FFT_MAX_BUFFER];
48 static n_double timedomaini[AUDIO_FFT_MAX_BUFFER];
49 
56 static n_uint audio_reverse_bits (n_uint index, n_uint power_sample)
57 {
58  n_uint i = 0;
59  n_uint rev = 0;
60  while(i < power_sample)
61  {
62  rev = (rev << 1) | (index & 1);
63  index >>= 1;
64  i++;
65  }
66  return rev;
67 }
68 
74 void audio_fft(n_byte inverse, n_uint power_sample)
75 {
76  n_uint NumSamples = 1 << power_sample; /* Number of bits needed to store indices */
77  n_uint i;
78  n_uint BlockSize, BlockEnd;
79 
80  n_double *d_in, *d_ini, *d_out, *d_outi;
81 
82  n_double angle_numerator = TWO_PI;
83 
84  if ( inverse )
85  {
86  angle_numerator = -angle_numerator;
87 
88  d_in = frequency;
89  d_ini = frequencyi;
90 
91  d_out = timedomain;
92  d_outi = timedomaini;
93  }
94  else
95  {
96  d_in = timedomain;
97  d_ini = timedomaini;
98 
99  d_out = frequency;
100  d_outi = frequencyi;
101  }
102 
103  /*
104  ** Do simultaneous data copy and bit-reversal ordering into outputs...
105  */
106 
107  i=0;
108  while(i < NumSamples)
109  {
110  n_uint j = audio_reverse_bits (i, power_sample);
111  d_outi[j] = d_in[i];
112  d_out[j] = d_ini[i];
113  i++;
114  }
115 
116  /*
117  ** Do the FFT itself...
118  */
119 
120  BlockEnd = 1;
121  BlockSize = 2;
122  while (BlockSize <= NumSamples)
123  {
124  n_double delta_angle = angle_numerator / (n_double)BlockSize;
125  n_double sm2 = sin ( -2 * delta_angle );
126  n_double sm1 = sin ( -delta_angle );
127  n_double cm2 = cos ( -2 * delta_angle );
128  n_double cm1 = cos ( -delta_angle );
129  n_double w = 2 * cm1;
130 
131  i=0;
132 
133  while( i < NumSamples )
134  {
135  n_uint j=i;
136  n_uint n=0;
137 
138  n_double ar2 = cm2;
139  n_double ar1 = cm1;
140 
141  n_double ai2 = sm2;
142  n_double ai1 = sm1;
143 
144  while(n < BlockEnd)
145  {
146  n_double ar0 = w*ar1 - ar2;
147  n_double ai0 = w*ai1 - ai2;
148 
149  ar2 = ar1;
150  ar1 = ar0;
151 
152  ai2 = ai1;
153  ai1 = ai0;
154 
155  {
156  n_uint k = j + BlockEnd;
157 
158  n_double tr = ar0*d_outi[k] - ai0*d_out[k];
159  n_double ti = ar0*d_out[k] + ai0*d_outi[k];
160 
161  d_outi[k] = d_outi[j] - tr;
162  d_out[k] = d_out[j] - ti;
163 
164  d_outi[j] += tr;
165  d_out[j] += ti;
166  }
167  j++;
168  n++;
169  }
170  i += BlockSize;
171  }
172 
173  BlockEnd = BlockSize;
174  BlockSize <<= 1;
175  }
176  /*
177  ** Need to normalize if inverse transform...
178  */
179  if ( inverse )
180  {
181  n_double denom = (n_double) NumSamples;
182  i = 0;
183  while (i < NumSamples)
184  {
185  d_outi[i] /= denom;
186  d_out[i] /= denom;
187  i++;
188  }
189  }
190 }
191 
197 {
198  n_uint loop = 0;
199  while (loop < length)
200  {
201  frequency[loop] = 0;
202  timedomain[loop] = 0;
203  frequencyi[loop] = 0;
204  timedomaini[loop] = 0;
205  loop++;
206  }
207 }
208 
214 void audio_clear_output(n_audio * audio, n_uint length)
215 {
216  n_uint loop = 0;
217  while (loop < length)
218  {
219  audio[loop] = 0;
220  loop++;
221  }
222 }
223 
229 void audio_equal_output(n_audio * audio, n_uint length)
230 {
231  n_uint loop = 0;
232  while (loop < length)
233  {
234  audio[loop] = (n_audio)timedomain[loop];
235  loop++;
236  }
237 }
238 
244 void audio_multiply_output(n_audio * audio, n_uint length)
245 {
246  n_uint loop = 0;
247  while (loop < length)
248  {
249  audio[loop] *= timedomain[loop];
250  loop++;
251  }
252 }
253 
260 {
261  frequency[entry] = value/1E+00;
262  frequencyi[entry] = 0E+00;
263 
264 }
265 
266 static void audio_aiff_uint(n_byte * buffer, n_uint value)
267 {
268  buffer[0] = (value & 0xff000000) >> 24;
269  buffer[1] = (value & 0x00ff0000) >> 16;
270  buffer[2] = (value & 0x0000ff00) >> 8;
271  buffer[3] = (value & 0x000000ff) >> 0;
272 }
273 
274 void audio_aiff_body(void * fptr, n_audio *samples, n_uint number_samples)
275 {
276  fwrite(samples,number_samples,sizeof(n_audio),(FILE*)fptr);
277 }
278 
279 static void audio_header(n_byte * header)
280 {
281  header[0] = 'F';
282  header[1] = 'O';
283  header[2] = 'R';
284  header[3] = 'M';
285 
286  header[8] = 'A';
287  header[9] = 'I';
288  header[10] = 'F';
289  header[11] = 'F';
290 
291  header[12] = 'C';
292  header[13] = 'O';
293  header[14] = 'M';
294  header[15] = 'M';
295 
296  header[19] = 18;
297 
298  header[21] = 1;
299 
300  header[27] = 16;
301 
302  header[28] = 0x40;
303  header[29] = 0x0e;
304  header[30] = 0xac;
305  header[31] = 0x44;
306 
307  header[38] = 'S';
308  header[39] = 'S';
309  header[40] = 'N';
310  header[41] = 'D';
311 }
312 
313 static n_uint audio_total_size(n_uint total_samples)
314 {
315  return 4 + 8 + 18 + 8 + (sizeof(n_audio) * total_samples) + 8;
316 }
317 
318 static n_uint audio_sound_size(n_uint total_samples)
319 {
320  return (2 * total_samples) + 8;
321 }
322 
323 void audio_aiff_header(void * fptr, n_uint total_samples)
324 {
325  n_byte header[54] = {0};
326  audio_header(header);
327  audio_aiff_uint(&header[4], audio_total_size(total_samples));
328  audio_aiff_uint(&header[22], total_samples);
329  audio_aiff_uint(&header[42], audio_sound_size(total_samples));
330  fwrite(header, 54, 1, (FILE*)fptr);
331 }
332