r663: This commit was generated by cvs2svn to compensate for changes in r662,
[cinelerra_cv.git] / toolame-02l / audio_read.c
blob927bff9a6c83fc4d147b2583ef123222831023f1
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "common.h"
5 #include "encoder.h"
6 #include "options.h"
7 #include "portableio.h"
8 #include "audio_read.h"
11 /************************************************************************
13 * read_samples()
15 * PURPOSE: reads the PCM samples from a file to the buffer
17 * SEMANTICS:
18 * Reads #samples_read# number of shorts from #musicin# filepointer
19 * into #sample_buffer[]#. Returns the number of samples read.
21 ************************************************************************/
23 unsigned long
24 read_samples (FILE * musicin, short sample_buffer[2304],
25 unsigned long num_samples, unsigned long frame_size)
27 unsigned long samples_read;
28 static unsigned long samples_to_read;
29 static char init = TRUE;
31 if (init) {
32 samples_to_read = num_samples;
33 init = FALSE;
35 if (samples_to_read >= frame_size)
36 samples_read = frame_size;
37 else
38 samples_read = samples_to_read;
40 * if ((samples_read =
41 * fread (sample_buffer, sizeof (short), (int) samples_read,
42 * musicin)) == 0)
44 if((samples_read = toolame_buffer_read((char*)sample_buffer,
45 sizeof(short),
46 samples_read)) == 0)
47 fprintf (stderr, "Hit end of audio data\n");
49 Samples are big-endian. If this is a little-endian machine
50 we must swap
52 if (NativeByteOrder == order_unknown) {
53 NativeByteOrder = DetermineByteOrder ();
54 if (NativeByteOrder == order_unknown) {
55 fprintf (stderr, "byte order not determined\n");
56 exit (1);
59 if (NativeByteOrder != order_littleEndian || (glopts.byteswap == TRUE))
60 SwapBytesInWords (sample_buffer, samples_read);
62 if (num_samples != MAX_U_32_NUM)
63 samples_to_read -= samples_read;
65 if (samples_read < frame_size && samples_read > 0) {
66 /* fill out frame with zeros */
67 for (; samples_read < frame_size; sample_buffer[samples_read++] = 0);
68 samples_to_read = 0;
69 samples_read = frame_size;
71 return (samples_read);
74 /************************************************************************
76 * get_audio()
78 * PURPOSE: reads a frame of audio data from a file to the buffer,
79 * aligns the data for future processing, and separates the
80 * left and right channels
83 ************************************************************************/
84 unsigned long
85 get_audio (FILE * musicin, short buffer[2][1152], unsigned long num_samples,
86 int nch, frame_header *header)
88 int j;
89 short insamp[2304];
90 unsigned long samples_read;
92 if (nch == 2) { /* stereo */
93 samples_read =
94 read_samples (musicin, insamp, num_samples, (unsigned long) 2304);
95 if (glopts.channelswap == TRUE) {
96 for (j = 0; j < 1152; j++) {
97 buffer[1][j] = insamp[2 * j];
98 buffer[0][j] = insamp[2 * j + 1];
100 } else {
101 for (j = 0; j < 1152; j++) {
102 buffer[0][j] = insamp[2 * j];
103 buffer[1][j] = insamp[2 * j + 1];
106 } else if (glopts.downmix == TRUE) {
107 samples_read =
108 read_samples (musicin, insamp, num_samples, (unsigned long) 2304);
109 for (j = 0; j < 1152; j++) {
110 buffer[0][j] = 0.5 * (insamp[2 * j] + insamp[2 * j + 1]);
112 } else { /* mono */
113 samples_read =
114 read_samples (musicin, insamp, num_samples, (unsigned long) 1152);
115 for (j = 0; j < 1152; j++) {
116 buffer[0][j] = insamp[j];
117 /* buffer[1][j] = 0; don't bother zeroing this buffer. MFC Nov 99 */
120 return (samples_read);
124 /*****************************************************************************
126 * Routines to determine byte order and swap bytes
128 *****************************************************************************/
130 enum byte_order DetermineByteOrder (void)
132 char s[sizeof (long) + 1];
133 union {
134 long longval;
135 char charval[sizeof (long)];
136 } probe;
137 probe.longval = 0x41424344L; /* ABCD in ASCII */
138 strncpy (s, probe.charval, sizeof (long));
139 s[sizeof (long)] = '\0';
140 /* fprintf( stderr, "byte order is %s\n", s ); */
141 if (strcmp (s, "ABCD") == 0)
142 return order_bigEndian;
143 else if (strcmp (s, "DCBA") == 0)
144 return order_littleEndian;
145 else
146 return order_unknown;
149 void SwapBytesInWords (short *loc, int words)
151 int i;
152 short thisval;
153 char *dst, *src;
154 src = (char *) &thisval;
155 for (i = 0; i < words; i++) {
156 thisval = *loc;
157 dst = (char *) loc++;
158 dst[0] = src[1];
159 dst[1] = src[0];
163 /*****************************************************************************
165 * Read Audio Interchange File Format (AIFF) headers.
167 *****************************************************************************/
169 int aiff_read_headers (FILE * file_ptr, IFF_AIFF * aiff_ptr)
171 int chunkSize, subSize, sound_position;
173 if (fseek (file_ptr, 0, SEEK_SET) != 0)
174 return -1;
176 if (Read32BitsHighLow (file_ptr) != IFF_ID_FORM)
177 return -1;
179 chunkSize = Read32BitsHighLow (file_ptr);
181 if (Read32BitsHighLow (file_ptr) != IFF_ID_AIFF)
182 return -1;
184 sound_position = 0;
185 while (chunkSize > 0) {
186 chunkSize -= 4;
187 switch (Read32BitsHighLow (file_ptr)) {
189 case IFF_ID_COMM:
190 chunkSize -= subSize = Read32BitsHighLow (file_ptr);
191 aiff_ptr->numChannels = Read16BitsHighLow (file_ptr);
192 subSize -= 2;
193 aiff_ptr->numSampleFrames = Read32BitsHighLow (file_ptr);
194 subSize -= 4;
195 aiff_ptr->sampleSize = Read16BitsHighLow (file_ptr);
196 subSize -= 2;
197 aiff_ptr->sampleRate = ReadIeeeExtendedHighLow (file_ptr);
198 subSize -= 10;
199 while (subSize > 0) {
200 getc (file_ptr);
201 subSize -= 1;
203 break;
205 case IFF_ID_SSND:
206 chunkSize -= subSize = Read32BitsHighLow (file_ptr);
207 aiff_ptr->blkAlgn.offset = Read32BitsHighLow (file_ptr);
208 subSize -= 4;
209 aiff_ptr->blkAlgn.blockSize = Read32BitsHighLow (file_ptr);
210 subSize -= 4;
211 sound_position = ftell (file_ptr) + aiff_ptr->blkAlgn.offset;
212 if (fseek (file_ptr, (long) subSize, SEEK_CUR) != 0)
213 return -1;
214 aiff_ptr->sampleType = IFF_ID_SSND;
215 break;
217 default:
218 chunkSize -= subSize = Read32BitsHighLow (file_ptr);
219 while (subSize > 0) {
220 getc (file_ptr);
221 subSize -= 1;
223 break;
226 return sound_position;
229 /*****************************************************************************
231 * Seek past some Audio Interchange File Format (AIFF) headers to sound data.
233 *****************************************************************************/
235 int aiff_seek_to_sound_data (FILE * file_ptr)
237 if (fseek
238 (file_ptr, AIFF_FORM_HEADER_SIZE + AIFF_SSND_HEADER_SIZE,
239 SEEK_SET) != 0)
240 return (-1);
241 return (0);
244 /************************************************************
245 * parse_input_file()
246 * Determine the type of sound file. (stdin, wav, aiff, raw pcm)
247 * Determine Sampling Frequency
248 * number of samples
249 * whether the new sample is stereo or mono.
251 * If file is coming from /dev/stdin assume it is raw PCM. (it's what I use. YMMV)
253 * This is just a hacked together function. The aiff parsing comes from the ISO code.
254 * The WAV code comes from Nick Burch
255 * The ugly /dev/stdin hack comes from me.
256 * MFC Dec 99
257 **************************************************************/
258 void
259 parse_input_file (FILE * musicin, char inPath[MAX_NAME_SIZE], frame_header *header,
260 unsigned long *num_samples)
263 IFF_AIFF pcm_aiff_data;
264 long soundPosition;
266 unsigned char wave_header_buffer[40]; //HH fixed
267 int wave_header_read = 0;
268 int wave_header_stereo = -1;
269 int wave_header_16bit = -1;
270 unsigned long samplerate;
272 /*************************** STDIN ********************************/
273 /* check if we're reading from stdin. Assume it's a raw PCM file. */
274 /* Of course, you could be piping a WAV file into stdin. Not done in this code */
275 /* this code is probably very dodgy and was written to suit my needs. MFC Dec 99 */
277 * if ((strcmp (inPath, "/dev/stdin") == 0)) {
278 * fprintf (stderr, "Reading from stdin\n");
279 * fprintf (stderr, "Remember to set samplerate with '-s'.\n");
280 * *num_samples = MAX_U_32_NUM;
281 * return;
284 *num_samples = MAX_U_32_NUM;
285 return;
287 /**************************** AIFF ********************************/
288 if ((soundPosition = aiff_read_headers (musicin, &pcm_aiff_data)) != -1) {
289 fprintf (stderr, ">>> Using Audio IFF sound file headers\n");
290 aiff_check (inPath, &pcm_aiff_data, &header->version);
291 if (fseek (musicin, soundPosition, SEEK_SET) != 0) {
292 fprintf (stderr, "Could not seek to PCM sound data in \"%s\".\n",
293 inPath);
294 exit (1);
296 fprintf (stderr, "Parsing AIFF audio file \n");
297 header->sampling_frequency =
298 toolame_SmpFrqIndex ((long) pcm_aiff_data.sampleRate, &header->version);
299 fprintf (stderr, ">>> %f Hz sampling frequency selected\n",
300 pcm_aiff_data.sampleRate);
302 /* Determine number of samples in sound file */
303 *num_samples = pcm_aiff_data.numChannels * pcm_aiff_data.numSampleFrames;
305 if (pcm_aiff_data.numChannels == 1) {
306 header->mode = MPG_MD_MONO;
307 header->mode_ext = 0;
309 return;
312 /**************************** WAVE *********************************/
313 /* Nick Burch <The_Leveller@newmail.net> */
314 /*********************************/
315 /* Wave File Headers: (Dec) */
316 /* 8-11 = "WAVE" */
317 /* 22 = Stereo / Mono */
318 /* 01 = mono, 02 = stereo */
319 /* 24 = Sampling Frequency */
320 /* 32 = Data Rate */
321 /* 01 = x1 (8bit Mono) */
322 /* 02 = x2 (8bit Stereo or */
323 /* 16bit Mono) */
324 /* 04 = x4 (16bit Stereo) */
325 /*********************************/
327 fseek (musicin, 0, SEEK_SET);
328 fread (wave_header_buffer, 1, 40, musicin);
330 if (wave_header_buffer[8] == 'W' && wave_header_buffer[9] == 'A'
331 && wave_header_buffer[10] == 'V' && wave_header_buffer[11] == 'E') {
332 fprintf (stderr, "Parsing Wave File Header\n");
333 if (NativeByteOrder == order_unknown) {
334 NativeByteOrder = DetermineByteOrder ();
335 if (NativeByteOrder == order_unknown) {
336 fprintf (stderr, "byte order not determined\n");
337 exit (1);
340 if (NativeByteOrder == order_littleEndian) {
341 samplerate = *(unsigned long *) (&wave_header_buffer[24]);
342 } else {
343 samplerate = wave_header_buffer[27] +
344 (wave_header_buffer[26] << 8) +
345 (wave_header_buffer[25] << 16) + (wave_header_buffer[24] << 24);
347 /* Wave File */
348 wave_header_read = 1;
349 switch (samplerate) {
350 case 44100:
351 case 48000:
352 case 32000:
353 case 24000:
354 case 22050:
355 case 16000:
356 fprintf (stderr, ">>> %ld Hz sampling freq selected\n", samplerate);
357 break;
358 default:
359 /* Unknown Unsupported Frequency */
360 fprintf (stderr, ">>> Unknown samp freq %ld Hz in Wave Header\n",
361 samplerate);
362 fprintf (stderr, ">>> Default 44.1 kHz samp freq selected\n");
363 samplerate = 44100;
366 if ((header->sampling_frequency =
367 toolame_SmpFrqIndex ((long) samplerate, &header->version)) < 0) {
368 fprintf (stderr, "invalid sample rate\n");
369 exit (0);
372 if ((long) wave_header_buffer[22] == 1) {
373 fprintf (stderr, ">>> Input Wave File is Mono\n");
374 wave_header_stereo = 0;
375 header->mode = MPG_MD_MONO;
376 header->mode_ext = 0;
378 if ((long) wave_header_buffer[22] == 2) {
379 fprintf (stderr, ">>> Input Wave File is Stereo\n");
380 wave_header_stereo = 1;
382 if ((long) wave_header_buffer[32] == 1) {
383 fprintf (stderr, ">>> Input Wave File is 8 Bit\n");
384 wave_header_16bit = 0;
385 fprintf (stderr, "Input File must be 16 Bit! Please Re-sample");
386 exit (1);
388 if ((long) wave_header_buffer[32] == 2) {
389 if (wave_header_stereo == 1) {
390 fprintf (stderr, ">>> Input Wave File is 8 Bit\n");
391 wave_header_16bit = 0;
392 fprintf (stderr, "Input File must be 16 Bit! Please Re-sample");
393 exit (1);
394 } else {
395 /* fprintf(stderr, ">>> Input Wave File is 16 Bit\n" ); */
396 wave_header_16bit = 1;
399 if ((long) wave_header_buffer[32] == 4) {
400 /* fprintf(stderr, ">>> Input Wave File is 16 Bit\n" ); */
401 wave_header_16bit = 1;
403 /* should probably use the wave header to determine size here FIXME MFC Feb 2003 */
404 *num_samples = MAX_U_32_NUM;
405 if (fseek (musicin, 44, SEEK_SET) != 0) { /* there's a way of calculating the size of the
406 wave header. i'll just jump 44 to start with */
407 fprintf (stderr, "Could not seek to PCM sound data in \"%s\".\n",
408 inPath);
409 exit (1);
411 return;
414 /*************************** PCM **************************/
415 fprintf (stderr, "No header found. Assuming Raw PCM sound file\n");
416 /* Raw PCM. No header. Reset the input file to read from the start */
417 fseek (musicin, 0, SEEK_SET);
418 /* Assume it is a huge sound file since there's no real info available */
419 /* FIXME: Could always fstat the file? Probably not worth it. MFC Feb 2003 */
420 *num_samples = MAX_U_32_NUM;
425 /************************************************************************
427 * aiff_check
429 * PURPOSE: Checks AIFF header information to make sure it is valid.
430 * Exits if not.
432 ************************************************************************/
434 void aiff_check (char *file_name, IFF_AIFF * pcm_aiff_data, int *version)
436 if (pcm_aiff_data->sampleType != IFF_ID_SSND) {
437 fprintf (stderr, "Sound data is not PCM in \"%s\".\n", file_name);
438 exit (1);
441 if (toolame_SmpFrqIndex ((long) pcm_aiff_data->sampleRate, version) < 0) {
442 fprintf (stderr, "in \"%s\".\n", file_name);
443 exit (1);
446 if (pcm_aiff_data->sampleSize != sizeof (short) * BITS_IN_A_BYTE) {
447 fprintf (stderr, "Sound data is not %d bits in \"%s\".\n",
448 sizeof (short) * BITS_IN_A_BYTE, file_name);
449 exit (1);
452 if (pcm_aiff_data->numChannels != MONO
453 && pcm_aiff_data->numChannels != STEREO) {
454 fprintf (stderr, "Sound data is not mono or stereo in \"%s\".\n",
455 file_name);
456 exit (1);
459 if (pcm_aiff_data->blkAlgn.blockSize != 0) {
460 fprintf (stderr, "Block size is not %d bytes in \"%s\".\n", 0, file_name);
461 exit (1);
464 if (pcm_aiff_data->blkAlgn.offset != 0) {
465 fprintf (stderr, "Block offset is not %d bytes in \"%s\".\n", 0,
466 file_name);
467 exit (1);