mirror of
				https://github.com/cookiengineer/audacity
				synced 2025-11-03 23:53:55 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			250 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 *  TwoLAME: an optimized MPEG Audio Layer Two encoder
 | 
						|
 *
 | 
						|
 *  Copyright (C) 2001-2004 Michael Cheng
 | 
						|
 *  Copyright (C) 2004-2006 The TwoLAME Project
 | 
						|
 *
 | 
						|
 *  This library is free software; you can redistribute it and/or
 | 
						|
 *  modify it under the terms of the GNU Lesser General Public
 | 
						|
 *  License as published by the Free Software Foundation; either
 | 
						|
 *  version 2.1 of the License, or (at your option) any later version.
 | 
						|
 *
 | 
						|
 *  This library is distributed in the hope that it will be useful,
 | 
						|
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
 *  Lesser General Public License for more details.
 | 
						|
 *
 | 
						|
 *  You should have received a copy of the GNU Lesser General Public
 | 
						|
 *  License along with this library; if not, write to the Free Software
 | 
						|
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
						|
 *
 | 
						|
 *  $Id: audio_wave.c,v 1.3 2008-02-01 19:44:37 richardash1981 Exp $
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include "audio_wave.h"
 | 
						|
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
*
 | 
						|
*  Routines to determine byte order (of this machine) and swap bytes
 | 
						|
*
 | 
						|
*****************************************************************************/
 | 
						|
 | 
						|
enum byte_order { order_unknown, order_bigEndian, order_littleEndian };
 | 
						|
 | 
						|
static enum byte_order DetermineByteOrder (void)
 | 
						|
{
 | 
						|
	char s[sizeof (long) + 1];
 | 
						|
	union {
 | 
						|
		long longval;
 | 
						|
		char charval[sizeof (long)];
 | 
						|
	} probe;
 | 
						|
	probe.longval = 0x41424344L;	/* ABCD in ASCII */
 | 
						|
	strncpy (s, probe.charval, sizeof (long));
 | 
						|
	s[sizeof (long)] = '\0';
 | 
						|
	/* fprintf( stderr, "byte order is %s\n", s ); */
 | 
						|
	
 | 
						|
	if (strcmp (s, "ABCD") == 0)
 | 
						|
		return order_bigEndian;
 | 
						|
	else if (strcmp (s, "DCBA") == 0)
 | 
						|
		return order_littleEndian;
 | 
						|
	else
 | 
						|
		return order_unknown;
 | 
						|
}
 | 
						|
 | 
						|
static void SwapBytesInWords (short *loc, int words)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	short thisval;
 | 
						|
	char *dst, *src;
 | 
						|
	src = (char *) &thisval;
 | 
						|
	for (i = 0; i < words; i++) {
 | 
						|
		thisval = *loc;
 | 
						|
		dst = (char *) loc++;
 | 
						|
		dst[0] = src[1];
 | 
						|
		dst[1] = src[0];
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
*
 | 
						|
*  Read in specified number of samples
 | 
						|
*
 | 
						|
*****************************************************************************/
 | 
						|
 | 
						|
int wave_get_samples (wave_info_t *wave_info, short int pcm[], int numSamples)
 | 
						|
{
 | 
						|
	int samples_read;
 | 
						|
	FILE *file = wave_info->soundfile;
 | 
						|
	
 | 
						|
	samples_read = fread (pcm, sizeof(short int), numSamples, file);
 | 
						|
	
 | 
						|
	if (wave_info->byteswap) {
 | 
						|
		SwapBytesInWords (pcm, samples_read);
 | 
						|
	}
 | 
						|
	
 | 
						|
	return (samples_read/wave_info->channels);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
*
 | 
						|
*  parse the wave header.
 | 
						|
*  returns NULL if not open failed
 | 
						|
*  returns a wave_info_t * if wave header successfully parsed.
 | 
						|
*  needs to fill in : samplerate + channels
 | 
						|
*  
 | 
						|
*  POST: wave_info->soundfile is set to be at the start of the
 | 
						|
*        PCM audio data 
 | 
						|
*
 | 
						|
*****************************************************************************/
 | 
						|
 | 
						|
wave_info_t *wave_init (char *inPath)
 | 
						|
{
 | 
						|
	unsigned char wave_header_buffer[40];	//HH fixed
 | 
						|
	int wave_header_read = 0;
 | 
						|
	int wave_header_stereo = -1;
 | 
						|
	int wave_header_16bit = -1;
 | 
						|
	unsigned long samplerate;
 | 
						|
	enum byte_order NativeByteOrder = order_unknown;
 | 
						|
	
 | 
						|
	
 | 
						|
	wave_info_t *wave_info = NULL;
 | 
						|
	FILE *file;
 | 
						|
	
 | 
						|
	if ( (file = fopen(inPath, "rb"))==NULL) {
 | 
						|
		fprintf(stdout,"WAV: cannot open input file: %s\n", inPath);
 | 
						|
		return(NULL);
 | 
						|
	}
 | 
						|
	
 | 
						|
	
 | 
						|
	/************** WAVE ************************/
 | 
						|
	/*   Nick Burch <The_Leveller@newmail.net>  */
 | 
						|
	/********************************************/
 | 
						|
	/* Wave File Headers:   (Dec)				*/
 | 
						|
	/* 8-11 = "WAVE"							*/
 | 
						|
	/* 22 = Stereo / Mono						*/
 | 
						|
	/*		01 = mono, 02 = stereo				*/
 | 
						|
	/* 24 = Sampling Frequency					*/
 | 
						|
	/* 32 = Data Rate							*/
 | 
						|
	/*		01 = x1 (8bit Mono)					*/
 | 
						|
	/*		02 = x2 (8bit Stereo or				*/
 | 
						|
	/*				 16bit Mono)				*/
 | 
						|
	/*		04 = x4 (16bit Stereo)				*/
 | 
						|
	/********************************************/
 | 
						|
	
 | 
						|
	fseek (file, 0, SEEK_SET);
 | 
						|
	fread (wave_header_buffer, 1, 40, file);
 | 
						|
	
 | 
						|
	if (wave_header_buffer[8]  == 'W' && wave_header_buffer[9] == 'A'
 | 
						|
	 && wave_header_buffer[10] == 'V' && wave_header_buffer[11] == 'E') {
 | 
						|
		fprintf (stderr, "Parsing Wave File Header\n");
 | 
						|
		if (NativeByteOrder == order_unknown) {
 | 
						|
			NativeByteOrder = DetermineByteOrder ();
 | 
						|
			if (NativeByteOrder == order_unknown) {
 | 
						|
				fprintf (stderr, "byte order not determined\n");
 | 
						|
				fclose(file); return(NULL);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		
 | 
						|
		if (NativeByteOrder == order_littleEndian) {
 | 
						|
			samplerate = *(unsigned long *) (&wave_header_buffer[24]);
 | 
						|
		} else {
 | 
						|
			samplerate = wave_header_buffer[27] +
 | 
						|
			(wave_header_buffer[26] << 8) +
 | 
						|
			(wave_header_buffer[25] << 16) + (wave_header_buffer[24] << 24);
 | 
						|
		}
 | 
						|
		
 | 
						|
		/* Wave File */
 | 
						|
		wave_header_read = 1;
 | 
						|
		switch (samplerate) {
 | 
						|
			case 44100:
 | 
						|
			case 48000:
 | 
						|
			case 32000:
 | 
						|
			case 24000:
 | 
						|
			case 22050:
 | 
						|
			case 16000:
 | 
						|
				fprintf (stderr, ">>> %ld Hz sampling freq selected\n", samplerate);
 | 
						|
			break;
 | 
						|
			default:
 | 
						|
				/* Unknown Unsupported Frequency */
 | 
						|
				fprintf (stderr, ">>> Unknown samp freq %ld Hz in Wave Header\n",
 | 
						|
				samplerate);
 | 
						|
				fprintf (stderr, ">>> Default 44.1 kHz samp freq selected\n");
 | 
						|
				samplerate = 44100;
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		
 | 
						|
		if ((long) wave_header_buffer[22] == 1) {
 | 
						|
			fprintf (stderr, ">>> Input Wave File is Mono\n");
 | 
						|
			wave_header_stereo = 0;
 | 
						|
		}
 | 
						|
		if ((long) wave_header_buffer[22] == 2) {
 | 
						|
			fprintf (stderr, ">>> Input Wave File is Stereo\n");
 | 
						|
			wave_header_stereo = 1;
 | 
						|
		}
 | 
						|
		if ((long) wave_header_buffer[32] == 1) {
 | 
						|
			fprintf (stderr, ">>> Input Wave File is 8 Bit\n");
 | 
						|
			wave_header_16bit = 0;
 | 
						|
			fprintf (stderr, "Input File must be 16 Bit! Please Re-sample");
 | 
						|
			fclose(file); return(NULL);
 | 
						|
		}
 | 
						|
		if ((long) wave_header_buffer[32] == 2) {
 | 
						|
			if (wave_header_stereo == 1) {
 | 
						|
				fprintf (stderr, ">>> Input Wave File is 8 Bit\n");
 | 
						|
				wave_header_16bit = 0;
 | 
						|
				fprintf (stderr, "Input File must be 16 Bit! Please Re-sample");
 | 
						|
				fclose(file); return(NULL);
 | 
						|
			} else {
 | 
						|
				/* fprintf(stderr,  ">>> Input Wave File is 16 Bit\n" ); */
 | 
						|
				wave_header_16bit = 1;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if ((long) wave_header_buffer[32] == 4) {
 | 
						|
			/* fprintf(stderr,  ">>> Input Wave File is 16 Bit\n" ); */
 | 
						|
			wave_header_16bit = 1;
 | 
						|
		}
 | 
						|
 | 
						|
		/* should probably use the wave header to determine size here FIXME MFC Feb 2003 */
 | 
						|
		if (fseek (file, 44, SEEK_SET) != 0) {
 | 
						|
			/* there's a way of calculating the size of the
 | 
						|
			   wave header. i'll just jump 44 to start with */
 | 
						|
			fprintf (stderr, "Could not seek to PCM sound data in \"%s\".\n", inPath);
 | 
						|
			fclose(file); return(NULL);
 | 
						|
		}
 | 
						|
		
 | 
						|
		// Successfully processed the wave header
 | 
						|
		wave_info = (wave_info_t *)calloc(1, sizeof(wave_info_t));
 | 
						|
		wave_info->soundfile = file;
 | 
						|
		if (wave_header_stereo == 1)
 | 
						|
				wave_info->channels = 2;
 | 
						|
		else	wave_info->channels = 1;
 | 
						|
		wave_info->samplerate = samplerate;
 | 
						|
		
 | 
						|
		// UNKNOWN. But we really should be able to work 
 | 
						|
		// it out. FIX THIS. MFC May03.
 | 
						|
		wave_info->num_samples = -1;
 | 
						|
		
 | 
						|
		// Enable byte swap for big endian machines
 | 
						|
		if (NativeByteOrder == order_bigEndian)
 | 
						|
				wave_info->byteswap = 1;
 | 
						|
		else	wave_info->byteswap = 0;
 | 
						|
			
 | 
						|
		return(wave_info);
 | 
						|
	}
 | 
						|
	
 | 
						|
	// not a wave file
 | 
						|
	fclose(file);  return(NULL);
 | 
						|
}
 | 
						|
 | 
						|
/* vim:ts=4:sw=4:nowrap: */
 |