/* * Get Audio routines source file * * Copyright (c) 1999 Albert L Faber * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library 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: get_audio.c,v 1.102 2005/05/25 14:17:51 takehiro Exp $ */ #ifdef HAVE_CONFIG_H # include <config.h> #endif #include <assert.h> #ifdef HAVE_LIMITS_H # include <limits.h> #endif #include <stdio.h> #ifdef STDC_HEADERS # include <stdlib.h> # include <string.h> #else # ifndef HAVE_STRCHR # define strchr index # define strrchr rindex # endif char *strchr(), *strrchr(); # ifndef HAVE_MEMCPY # define memcpy(d, s, n) bcopy ((s), (d), (n)) # define memmove(d, s, n) bcopy ((s), (d), (n)) # endif #endif #define MAX_U_32_NUM 0xFFFFFFFF #include <math.h> #include <sys/stat.h> #ifdef __sun__ /* woraround for SunOS 4.x, it has SEEK_* defined here */ #include <unistd.h> #endif #include "lame.h" #include "main.h" #include "get_audio.h" #include "portableio.h" #include "timestatus.h" #include "lametime.h" #ifdef WITH_DMALLOC #include <dmalloc.h> #endif /* global data for get_audio.c. */ int count_samples_carefully; int pcmbitwidth; int pcmswapbytes = 0; unsigned int num_samples_read; FILE *musicin; #ifdef AMIGA_MPEGA int lame_decode_initfile(const char *fullname, mp3data_struct * const mp3data); #else int lame_decode_initfile(FILE * fd, mp3data_struct * mp3data); #endif /* read mp3 file until mpglib returns one frame of PCM data */ int lame_decode_fromfile(FILE * fd, short int pcm_l[], short int pcm_r[], mp3data_struct * mp3data); static int read_samples_pcm(FILE * musicin, int sample_buffer[2304], int frame_size, int samples_to_read); static int read_samples_mp3(lame_global_flags * const gfp, FILE * const musicin, short int mpg123pcm[2][1152], int num_chan); void CloseSndFile(sound_file_format input, FILE * musicin); FILE *OpenSndFile(lame_global_flags * gfp, char *); /* Replacement for forward fseek(,,SEEK_CUR), because fseek() fails on pipes */ static int fskip(FILE * fp, long offset, int whence) { #ifndef PIPE_BUF char buffer[4096]; #else char buffer[PIPE_BUF]; #endif int read; if (0 == fseek(fp, offset, whence)) return 0; if (whence != SEEK_CUR || offset < 0) { if( silent < 10 ) { fprintf(stderr, "fskip problem: Mostly the return status of functions is not evaluate so it is more secure to polute <stderr>.\n"); } return -1; } while (offset > 0) { read = offset > sizeof(buffer) ? sizeof(buffer) : offset; if ((read = fread(buffer, 1, read, fp)) <= 0) return -1; offset -= read; } return 0; } FILE * init_outfile(char *outPath, int decode) { FILE *outf; #ifdef __riscos__ char *p; #endif /* open the output file */ if (0 == strcmp(outPath, "-")) { lame_set_stream_binary_mode(outf = stdout); } else { if ((outf = fopen(outPath, "wb+")) == NULL) return NULL; #ifdef __riscos__ /* Assign correct file type */ for (p = outPath; *p; p++) /* ugly, ugly to modify a string */ switch (*p) { case '.': *p = '/'; break; case '/': *p = '.'; break; } SetFiletype(outPath, decode ? 0xFB1 /*WAV*/ : 0x1AD /*AMPEG*/); #endif } return outf; } void init_infile(lame_global_flags * gfp, char *inPath) { /* open the input file */ count_samples_carefully = 0; num_samples_read=0; pcmbitwidth=in_bitwidth; pcmswapbytes=swapbytes; musicin = OpenSndFile(gfp, inPath); } void close_infile(void) { CloseSndFile(input_format, musicin); } void SwapBytesInWords(short *ptr, int short_words) { /* Some speedy code */ unsigned long val; unsigned long *p = (unsigned long *) ptr; #ifndef lint # if defined(CHAR_BIT) # if CHAR_BIT != 8 # error CHAR_BIT != 8 # endif # else # error can not determine number of bits in a char # endif #endif /* lint */ assert(sizeof(short) == 2); #if defined(SIZEOF_UNSIGNED_LONG) && SIZEOF_UNSIGNED_LONG == 4 for (; short_words >= 2; short_words -= 2, p++) { val = *p; *p = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0x00FF00FF); } ptr = (short *) p; for (; short_words >= 1; short_words -= 1, ptr++) { val = *ptr; *ptr = ((val << 8) & 0xFF00) | ((val >> 8) & 0x00FF); } #elif defined(SIZEOF_UNSIGNED_LONG) && SIZEOF_UNSIGNED_LONG == 8 for (; short_words >= 4; short_words -= 4, p++) { val = *p; *p = ((val << 8) & 0xFF00FF00FF00FF00) | ((val >> 8) & 0x00FF00FF00FF00FF); } ptr = (short *) p; for (; short_words >= 1; short_words -= 1, ptr++) { val = *ptr; *ptr = ((val << 8) & 0xFF00) | ((val >> 8) & 0x00FF); } #else # ifdef SIZEOF_UNSIGNED_LONG # warning Using unoptimized SwapBytesInWords(). # endif for (; short_words >= 1; short_words -= 1, ptr++) { val = *ptr; *ptr = ((val << 8) & 0xFF00) | ((val >> 8) & 0x00FF); } #endif assert(short_words == 0); } static int get_audio_common( lame_global_flags * const gfp, int buffer[2][1152], short buffer16[2][1152] ); /************************************************************************ * * get_audio() * * PURPOSE: reads a frame of audio data from a file to the buffer, * aligns the data for future processing, and separates the * left and right channels * ************************************************************************/ int get_audio( lame_global_flags * const gfp, int buffer[2][1152] ) { return( get_audio_common( gfp, buffer, NULL ) ); } /* get_audio16 - behave as the original get_audio function, with a limited 16 bit per sample output */ int get_audio16( lame_global_flags * const gfp, short buffer[2][1152] ) { return( get_audio_common( gfp, NULL, buffer ) ); } /************************************************************************ get_audio_common - central functionality of get_audio* in: gfp buffer output to the int buffer or 16-bit buffer out: buffer int output (if buffer != NULL) buffer16 16-bit output (if buffer == NULL) returns: samples read note: either buffer or buffer16 must be allocated upon call */ static int get_audio_common( lame_global_flags * const gfp, int buffer[2][1152], short buffer16[2][1152] ) { int num_channels = lame_get_num_channels( gfp ); int insamp[2 * 1152]; short buf_tmp16[2][1152]; int samples_read; int framesize; int samples_to_read; unsigned int remaining, tmp_num_samples; int i; int *p; /* * NOTE: LAME can now handle arbritray size input data packets, * so there is no reason to read the input data in chuncks of * size "framesize". EXCEPT: the LAME graphical frame analyzer * will get out of sync if we read more than framesize worth of data. */ samples_to_read = framesize = lame_get_framesize(gfp); assert(framesize <= 1152); /* get num_samples */ tmp_num_samples = lame_get_num_samples( gfp ); /* if this flag has been set, then we are carefull to read * exactly num_samples and no more. This is useful for .wav and .aiff * files which have id3 or other tags at the end. Note that if you * are using LIBSNDFILE, this is not necessary */ if (count_samples_carefully) { remaining = tmp_num_samples - Min(tmp_num_samples, num_samples_read); if (remaining < framesize && 0 != tmp_num_samples) /* in case the input is a FIFO (at least it's reproducible with a FIFO) tmp_num_samples may be 0 and therefore remaining would be 0, but we need to read some samples, so don't change samples_to_read to the wrong value in this case */ samples_to_read = remaining; } switch (input_format) { case sf_mp1: case sf_mp2: case sf_mp3: if( buffer != NULL ) samples_read = read_samples_mp3( gfp, musicin, buf_tmp16, num_channels ); else samples_read = read_samples_mp3( gfp, musicin, buffer16, num_channels ); break; default: samples_read = read_samples_pcm(musicin, insamp, num_channels * framesize, num_channels * samples_to_read); p = insamp + samples_read; samples_read /= num_channels; if( buffer != NULL ) { /* output to int buffer */ if( num_channels == 2 ) { for( i = samples_read; --i >= 0; ) { buffer[1][i] = *--p; buffer[0][i] = *--p; } } else if( num_channels == 1 ) { memset( buffer[1], 0, samples_read * sizeof(int) ); for( i = samples_read; --i >= 0; ) { buffer[0][i] = *--p; } } else assert(0); } else { /* convert from int; output to 16-bit buffer */ if( num_channels == 2 ) { for( i = samples_read; --i >= 0; ) { buffer16[1][i] = *--p >> (8 * sizeof(int) - 16); buffer16[0][i] = *--p >> (8 * sizeof(int) - 16); } } else if( num_channels == 1 ) { memset( buffer16[1], 0, samples_read * sizeof(short) ); for( i = samples_read; --i >= 0; ) { buffer16[0][i] = *--p >> (8 * sizeof(int) - 16); } } else assert(0); } } /* LAME mp3 output 16bit - convert to int, if necessary */ if( input_format == sf_mp1 || input_format == sf_mp2 || input_format == sf_mp3) { if( buffer != NULL ) { for( i = samples_read; --i >= 0; ) buffer[0][i] = buf_tmp16[0][i] << (8 * sizeof(int) - 16); if( num_channels == 2 ) { for( i = samples_read; --i >= 0; ) buffer[1][i] = buf_tmp16[1][i] << (8 * sizeof(int) - 16); } else if( num_channels == 1 ) { memset( buffer[1], 0, samples_read * sizeof(int) ); } else assert(0); } } /* if num_samples = MAX_U_32_NUM, then it is considered infinitely long. Don't count the samples */ if ( tmp_num_samples != MAX_U_32_NUM ) num_samples_read += samples_read; return samples_read; } int read_samples_mp3(lame_global_flags * const gfp, FILE * const musicin, short int mpg123pcm[2][1152], int stereo) { int out; #if defined(AMIGA_MPEGA) || defined(HAVE_MPGLIB) static const char type_name[] = "MP3 file"; out = lame_decode_fromfile(musicin, mpg123pcm[0], mpg123pcm[1], &mp3input_data); /* * out < 0: error, probably EOF * out = 0: not possible with lame_decode_fromfile() ??? * out > 0: number of output samples */ if (out < 0) { memset(mpg123pcm, 0, sizeof(**mpg123pcm) * 2 * 1152); return 0; } if ( lame_get_num_channels( gfp ) != mp3input_data.stereo ) if( silent < 10 ) { fprintf(stderr, "Error: number of channels has changed in %s - not supported\n", type_name); } if ( lame_get_in_samplerate( gfp ) != mp3input_data.samplerate ) if( silent < 10 ) { fprintf(stderr, "Error: sample frequency has changed in %s - not supported\n", type_name); } #else out = -1; #endif return out; } int WriteWaveHeader(FILE * const fp, const int pcmbytes, const int freq, const int channels, const int bits) { int bytes = (bits + 7) / 8; /* quick and dirty, but documented */ fwrite("RIFF", 1, 4, fp); /* label */ Write32BitsLowHigh(fp, pcmbytes + 44 - 8); /* length in bytes without header */ fwrite("WAVEfmt ", 2, 4, fp); /* 2 labels */ Write32BitsLowHigh(fp, 2 + 2 + 4 + 4 + 2 + 2); /* length of PCM format declaration area */ Write16BitsLowHigh(fp, 1); /* is PCM? */ Write16BitsLowHigh(fp, channels); /* number of channels */ Write32BitsLowHigh(fp, freq); /* sample frequency in [Hz] */ Write32BitsLowHigh(fp, freq * channels * bytes); /* bytes per second */ Write16BitsLowHigh(fp, channels * bytes); /* bytes per sample time */ Write16BitsLowHigh(fp, bits); /* bits per sample */ fwrite("data", 1, 4, fp); /* label */ Write32BitsLowHigh(fp, pcmbytes); /* length in bytes of raw PCM data */ return ferror(fp) ? -1 : 0; } #if defined(LIBSNDFILE) /* ** Copyright (C) 1999 Albert Faber ** * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library 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. */ void CloseSndFile(sound_file_format input, FILE * musicin) { SNDFILE *gs_pSndFileIn = (SNDFILE *) musicin; if (input == sf_mp1 || input == sf_mp2 || input == sf_mp3) { #ifndef AMIGA_MPEGA if (fclose(musicin) != 0) { if( silent < 10 ) { fprintf(stderr, "Could not close audio input file\n"); } exit(2); } #endif } else { if (gs_pSndFileIn) { if (sf_close(gs_pSndFileIn) != 0) { if( silent < 10 ) { fprintf(stderr, "Could not close sound file \n"); } exit(2); } } } } FILE * OpenSndFile(lame_global_flags * gfp, char *inPath) { char *lpszFileName = inPath; FILE *musicin; SNDFILE *gs_pSndFileIn; SF_INFO gs_wfInfo; if (input_format == sf_mp1 || input_format == sf_mp2 || input_format == sf_mp3) { #ifdef AMIGA_MPEGA if (-1 == lame_decode_initfile(lpszFileName, &mp3input_data)) { if( silent < 10 ) { fprintf(stderr, "Error reading headers in mp3 input file %s.\n", lpszFileName); } exit(1); } #endif #ifdef HAVE_MPGLIB if ((musicin = fopen(lpszFileName, "rb")) == NULL) { if( silent < 10 ) { fprintf(stderr, "Could not find \"%s\".\n", lpszFileName); } exit(1); } if (-1 == lame_decode_initfile(musicin, &mp3input_data)) { if( silent < 10 ) { fprintf(stderr, "Error reading headers in mp3 input file %s.\n", lpszFileName); } exit(1); } #endif if( -1 == lame_set_num_channels( gfp, mp3input_data.stereo ) ) { if( silent < 10 ) { fprintf( stderr, "Unsupported number of channels: %ud\n", mp3input_data.stereo ); } exit( 1 ); } (void) lame_set_in_samplerate( gfp, mp3input_data.samplerate ); (void) lame_set_num_samples( gfp, mp3input_data.nsamp ); } else if (input_format == sf_ogg) { if( silent < 10 ) { fprintf(stderr, "sorry, vorbis support in LAME is deprecated.\n"); } exit(1); } else { /* Try to open the sound file */ /* set some defaults incase input is raw PCM */ gs_wfInfo.seekable = (input_format != sf_raw); /* if user specified -r, set to not seekable */ gs_wfInfo.samplerate = lame_get_in_samplerate( gfp ); gs_wfInfo.pcmbitwidth = in_bitwidth; gs_wfInfo.channels = lame_get_num_channels( gfp ); if (in_bitwidth == 8) { if (in_signed) gs_wfInfo.format = SF_FORMAT_RAW_S8; else gs_wfInfo.format = SF_FORMAT_RAW_U8; } else { if (!in_signed) { fputs("Unsigned input only supported with bitwidth 8\n", stderr); exit(1); } if (in_endian != order_unknown) { if (in_endian == order_littleEndian) gs_wfInfo.format = SF_FORMAT_RAW_LE; else gs_wfInfo.format = SF_FORMAT_RAW_BE; } else { #ifndef WORDS_BIGENDIAN /* little endian */ if (swapbytes) gs_wfInfo.format = SF_FORMAT_RAW_BE; else gs_wfInfo.format = SF_FORMAT_RAW_LE; #else if (swapbytes) gs_wfInfo.format = SF_FORMAT_RAW_LE; else gs_wfInfo.format = SF_FORMAT_RAW_BE; #endif } } gs_pSndFileIn = sf_open_read(lpszFileName, &gs_wfInfo); musicin = (SNDFILE *) gs_pSndFileIn; /* Check result */ if (gs_pSndFileIn == NULL) { sf_perror(gs_pSndFileIn); if( silent < 10 ) { fprintf(stderr, "Could not open sound file \"%s\".\n", lpszFileName); } exit(1); } if ((gs_wfInfo.format == SF_FORMAT_RAW_LE) || (gs_wfInfo.format == SF_FORMAT_RAW_BE) || (gs_wfInfo.format == SF_FORMAT_RAW_S8) || (gs_wfInfo.format == SF_FORMAT_RAW_U8)) input_format = sf_raw; #ifdef _DEBUG_SND_FILE DEBUGF("\n\nSF_INFO structure\n"); DEBUGF("samplerate :%d\n", gs_wfInfo.samplerate); DEBUGF("samples :%d\n", gs_wfInfo.samples); DEBUGF("channels :%d\n", gs_wfInfo.channels); DEBUGF("pcmbitwidth :%d\n", gs_wfInfo.pcmbitwidth); DEBUGF("format :"); /* new formats from sbellon@sbellon.de 1/2000 */ switch (gs_wfInfo.format & SF_FORMAT_TYPEMASK) { case SF_FORMAT_WAV: DEBUGF("Microsoft WAV format (big endian). "); break; case SF_FORMAT_AIFF: DEBUGF("Apple/SGI AIFF format (little endian). "); break; case SF_FORMAT_AU: DEBUGF("Sun/NeXT AU format (big endian). "); break; case SF_FORMAT_AULE: DEBUGF("DEC AU format (little endian). "); break; case SF_FORMAT_RAW: DEBUGF("RAW PCM data. "); break; case SF_FORMAT_PAF: DEBUGF("Ensoniq PARIS file format. "); break; case SF_FORMAT_SVX: DEBUGF("Amiga IFF / SVX8 / SV16 format. "); break; case SF_FORMAT_NIST: DEBUGF("Sphere NIST format. "); break; default: assert(0); break; } switch (gs_wfInfo.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM: DEBUGF("PCM data in 8, 16, 24 or 32 bits."); break; case SF_FORMAT_FLOAT: DEBUGF("32 bit Intel x86 floats."); break; case SF_FORMAT_ULAW: DEBUGF("U-Law encoded."); break; case SF_FORMAT_ALAW: DEBUGF("A-Law encoded."); break; case SF_FORMAT_IMA_ADPCM: DEBUGF("IMA ADPCM."); break; case SF_FORMAT_MS_ADPCM: DEBUGF("Microsoft ADPCM."); break; case SF_FORMAT_PCM_BE: DEBUGF("Big endian PCM data."); break; case SF_FORMAT_PCM_LE: DEBUGF("Little endian PCM data."); break; case SF_FORMAT_PCM_S8: DEBUGF("Signed 8 bit PCM."); break; case SF_FORMAT_PCM_U8: DEBUGF("Unsigned 8 bit PCM."); break; case SF_FORMAT_SVX_FIB: DEBUGF("SVX Fibonacci Delta encoding."); break; case SF_FORMAT_SVX_EXP: DEBUGF("SVX Exponential Delta encoding."); break; default: assert(0); break; } DEBUGF("\n"); DEBUGF("pcmbitwidth :%d\n", gs_wfInfo.pcmbitwidth); DEBUGF("sections :%d\n", gs_wfInfo.sections); DEBUGF("seekable :\n", gs_wfInfo.seekable); #endif (void) lame_set_num_samples( gfp, gs_wfInfo.samples ); if( -1 == lame_set_num_channels( gfp, gs_wfInfo.channels ) ) { if( silent < 10 ) { fprintf( stderr, "Unsupported number of channels: %ud\n", gs_wfInfo.channels ); } exit( 1 ); } (void) lame_set_in_samplerate( gfp, gs_wfInfo.samplerate ); pcmbitwidth = gs_wfInfo.pcmbitwidth; } if (lame_get_num_samples( gfp ) == MAX_U_32_NUM) { /* try to figure out num_samples */ double flen = lame_get_file_size( lpszFileName ); if (flen >= 0) { /* try file size, assume 2 bytes per sample */ if (input_format == sf_mp1 || input_format == sf_mp2 || input_format == sf_mp3) { if (mp3input_data.bitrate>0) { double totalseconds = (flen * 8.0 / (1000.0 * mp3input_data.bitrate)); unsigned long tmp_num_samples = totalseconds * lame_get_in_samplerate( gfp ); (void) lame_set_num_samples( gfp, tmp_num_samples ); mp3input_data.nsamp = tmp_num_samples; } } else { lame_set_num_samples( gfp, flen / (2 * lame_get_num_channels( gfp )) ); } } } return musicin; } /************************************************************************ * * read_samples() * * PURPOSE: reads the PCM samples from a file to the buffer * * SEMANTICS: * Reads #samples_read# number of shorts from #musicin# filepointer * into #sample_buffer[]#. Returns the number of samples read. * ************************************************************************/ static int read_samples_pcm(FILE * const musicin, int sample_buffer[2304], int frame_size /* unused */ , int samples_to_read) { int i; int samples_read; samples_read = sf_read_int((SNDFILE *) musicin, sample_buffer, samples_to_read); switch (pcmbitwidth) { case 8: for (i = 0; i < samples_read; i++) sample_buffer[i] <<= (8 * sizeof(int) - 8); break; case 16: for (i = 0; i < samples_read; i++) sample_buffer[i] <<= (8 * sizeof(int) - 16); break; case 24: for (i = 0; i < samples_read; i++) sample_buffer[i] <<= (8 * sizeof(int) - 24); break; case 32: break; default: if( silent < 10 ) { fprintf(stderr, "Only 8, 16, 24 and 32 bit input files supported \n"); } exit(1); } return samples_read; } #else /* defined(LIBSNDFILE) */ /************************************************************************ ************************************************************************ ************************************************************************ ************************************************************************ ************************************************************************ ************************************************************************ * * OLD ISO/LAME routines follow. Used if you dont have LIBSNDFILE * or for stdin/stdout support * ************************************************************************ ************************************************************************ ************************************************************************ ************************************************************************ ************************************************************************ ************************************************************************/ /************************************************************************ unpack_read_samples - read and unpack signed low-to-high byte or unsigned single byte input. (used for read_samples function) Output integers are stored in the native byte order (little or big endian). -jd in: samples_to_read bytes_per_sample swap_order - set for high-to-low byte order input stream i/o: pcm_in out: sample_buffer (must be allocated up to samples_to_read upon call) returns: number of samples read */ static int unpack_read_samples( const int samples_to_read, const int bytes_per_sample, const int swap_order, int *sample_buffer, FILE *pcm_in ) { int samples_read; int i; int *op; /* output pointer */ unsigned char *ip = (unsigned char *) sample_buffer; /* input pointer */ const int b = sizeof(int) * 8; #define GA_URS_IFLOOP( ga_urs_bps ) \ if( bytes_per_sample == ga_urs_bps ) \ for( i = samples_read * bytes_per_sample; (i -= bytes_per_sample) >=0;) samples_read = fread( sample_buffer, bytes_per_sample, samples_to_read, pcm_in); op = sample_buffer + samples_read; GA_URS_IFLOOP( 1 ) *--op = (ip[i] ^ 0x80)<<(b-8) | 0x7f<<(b-16);/* convert from unsigned*/ if( swap_order == 0 ) { GA_URS_IFLOOP( 2 ) *--op = ip[i]<<(b-16) | ip[i+1]<<(b-8); GA_URS_IFLOOP( 3 ) *--op = ip[i]<<(b-24) | ip[i+1]<<(b-16) | ip[i+2]<<(b-8); GA_URS_IFLOOP( 4 ) *--op = ip[i]<<(b-32) | ip[i+1]<<(b-24) | ip[i+2]<<(b-16) | ip[i+3] << (b-8); } else { GA_URS_IFLOOP( 2 ) *--op = ip[i]<<(b-8) | ip[i+1]<<(b-16); GA_URS_IFLOOP( 3 ) *--op = ip[i]<<(b-8) | ip[i+1]<<(b-16) | ip[i+2]<<(b-24); GA_URS_IFLOOP( 4 ) *--op = ip[i]<<(b-8) | ip[i+1]<<(b-16) | ip[i+2]<<(b-24) | ip[i+3]<<(b-32); } #undef GA_URS_IFLOOP return( samples_read ); } /************************************************************************ * * read_samples() * * PURPOSE: reads the PCM samples from a file to the buffer * * SEMANTICS: * Reads #samples_read# number of shorts from #musicin# filepointer * into #sample_buffer[]#. Returns the number of samples read. * ************************************************************************/ int read_samples_pcm(FILE * musicin, int sample_buffer[2304], int frame_size, int samples_to_read) { int samples_read; int iswav = (input_format == sf_wave); int hi_lo_order; /* byte order of input stream */ if( (32 == pcmbitwidth) || (24 == pcmbitwidth) || (16 == pcmbitwidth) ) { /* assume only recognized wav files are */ /* in little endian byte order */ hi_lo_order = (!iswav == !pcmswapbytes); samples_read = unpack_read_samples(samples_to_read, pcmbitwidth/8, hi_lo_order,sample_buffer, musicin ); } else if( 8 == pcmbitwidth ) { samples_read = unpack_read_samples( samples_to_read, 1, 0, sample_buffer, musicin ); } else { if( silent < 10 ) { fprintf(stderr, "Only 8, 16, 24 and 32 bit input files supported \n"); } exit(1); } if (ferror(musicin)) { if( silent < 10 ) { fprintf(stderr, "Error reading input file\n"); } exit(1); } return samples_read; } /* AIFF Definitions */ #define IFF_ID_FORM 0x464f524d /* "FORM" */ #define IFF_ID_AIFF 0x41494646 /* "AIFF" */ #define IFF_ID_AIFC 0x41494643 /* "AIFC" */ #define IFF_ID_COMM 0x434f4d4d /* "COMM" */ #define IFF_ID_SSND 0x53534e44 /* "SSND" */ #define IFF_ID_MPEG 0x4d504547 /* "MPEG" */ #define IFF_ID_NONE 0x4e4f4e45 /* "NONE" */ /* AIFF-C data format */ #define IFF_ID_2CBE 0x74776f73 /* "twos" */ /* AIFF-C data format */ #define IFF_ID_2CLE 0x736f7774 /* "sowt" */ /* AIFF-C data format */ #define WAV_ID_RIFF 0x52494646 /* "RIFF" */ #define WAV_ID_WAVE 0x57415645 /* "WAVE" */ #define WAV_ID_FMT 0x666d7420 /* "fmt " */ #define WAV_ID_DATA 0x64617461 /* "data" */ /***************************************************************************** * * Read Microsoft Wave headers * * By the time we get here the first 32-bits of the file have already been * read, and we're pretty sure that we're looking at a WAV file. * *****************************************************************************/ static int parse_wave_header(lame_global_flags * gfp, FILE * sf) { int format_tag = 0; int channels = 0; int block_align = 0; int bits_per_sample = 0; int samples_per_sec = 0; int avg_bytes_per_sec = 0; int is_wav = 0; long data_length = 0, file_length, subSize = 0; int loop_sanity = 0; file_length = Read32BitsHighLow(sf); if (Read32BitsHighLow(sf) != WAV_ID_WAVE) return 0; for (loop_sanity = 0; loop_sanity < 20; ++loop_sanity) { int type = Read32BitsHighLow(sf); if (type == WAV_ID_FMT) { subSize = Read32BitsLowHigh(sf); if (subSize < 16) { /*DEBUGF( "'fmt' chunk too short (only %ld bytes)!", subSize); */ return 0; } format_tag = Read16BitsLowHigh(sf); subSize -= 2; channels = Read16BitsLowHigh(sf); subSize -= 2; samples_per_sec = Read32BitsLowHigh(sf); subSize -= 4; avg_bytes_per_sec = Read32BitsLowHigh(sf); subSize -= 4; block_align = Read16BitsLowHigh(sf); subSize -= 2; bits_per_sample = Read16BitsLowHigh(sf); subSize -= 2; /* DEBUGF(" skipping %d bytes\n", subSize); */ if (subSize > 0) { if (fskip(sf, (long) subSize, SEEK_CUR) != 0) return 0; }; } else if (type == WAV_ID_DATA) { subSize = Read32BitsLowHigh(sf); data_length = subSize; is_wav = 1; /* We've found the audio data. Read no further! */ break; } else { subSize = Read32BitsLowHigh(sf); if (fskip(sf, (long) subSize, SEEK_CUR) != 0) return 0; } } if (format_tag != 1) { return 0; /* oh no! non-supported format */ } if (is_wav) { /* make sure the header is sane */ if( -1 == lame_set_num_channels( gfp, channels ) ) { if( silent < 10 ) { fprintf( stderr, "Unsupported number of channels: %ud\n", channels ); } exit( 1 ); } (void) lame_set_in_samplerate( gfp, samples_per_sec ); pcmbitwidth = bits_per_sample; (void) lame_set_num_samples( gfp, data_length / (channels * ((bits_per_sample+7) / 8)) ); } return is_wav; } /************************************************************************ * aiff_check2 * * PURPOSE: Checks AIFF header information to make sure it is valid. * returns 0 on success, 1 on errors ************************************************************************/ int aiff_check2(const char *file_name, IFF_AIFF * const pcm_aiff_data) { if (pcm_aiff_data->sampleType != IFF_ID_SSND) { if( silent < 10 ) { fprintf(stderr, "Sound data is not PCM in '%s'\n", file_name); } return 1; } if (pcm_aiff_data->sampleSize != sizeof(short) * CHAR_BIT) { if( silent < 10 ) { fprintf(stderr, "Sound data is not %i bits in '%s'\n", sizeof(short) * CHAR_BIT, file_name); } return 1; } if (pcm_aiff_data->numChannels != 1 && pcm_aiff_data->numChannels != 2) { if( silent < 10 ) { fprintf(stderr, "Sound data is not mono or stereo in '%s'\n", file_name); } return 1; } if (pcm_aiff_data->blkAlgn.blockSize != 0) { if( silent < 10 ) { fprintf(stderr, "Block size is not 0 bytes in '%s'\n", file_name); } return 1; } /* A bug, since we correctly skip the offset earlier in the code. if (pcm_aiff_data->blkAlgn.offset != 0) { fprintf(stderr, "Block offset is not 0 bytes in '%s'\n", file_name); return 1; } */ return 0; } /***************************************************************************** * * Read Audio Interchange File Format (AIFF) headers. * * By the time we get here the first 32 bits of the file have already been * read, and we're pretty sure that we're looking at an AIFF file. * *****************************************************************************/ static int parse_aiff_header(lame_global_flags * gfp, FILE * sf) { int is_aiff = 0; long chunkSize = 0, subSize = 0, typeID = 0, dataType = 0; IFF_AIFF aiff_info; memset(&aiff_info, 0, sizeof(aiff_info)); chunkSize = Read32BitsHighLow(sf); typeID = Read32BitsHighLow(sf); if ((typeID != IFF_ID_AIFF)&&(typeID != IFF_ID_AIFC)) return 0; while (chunkSize > 0) { int type = Read32BitsHighLow(sf); chunkSize -= 4; /* DEBUGF( "found chunk type %08x '%4.4s'\n", type, (char*)&type); */ /* don't use a switch here to make it easier to use 'break' for SSND */ if (type == IFF_ID_COMM) { subSize = Read32BitsHighLow(sf); chunkSize -= subSize; aiff_info.numChannels = Read16BitsHighLow(sf); subSize -= 2; aiff_info.numSampleFrames = Read32BitsHighLow(sf); subSize -= 4; aiff_info.sampleSize = Read16BitsHighLow(sf); subSize -= 2; aiff_info.sampleRate = ReadIeeeExtendedHighLow(sf); subSize -= 10; if (typeID == IFF_ID_AIFC) { dataType = Read32BitsHighLow(sf); subSize -= 4; if ((dataType != IFF_ID_2CLE) && (dataType != IFF_ID_2CBE) && (dataType != IFF_ID_NONE)) return 0; if (aiff_info.sampleSize == 16) pcmswapbytes = (!swapbytes == (dataType == IFF_ID_2CLE)); } if (fskip(sf, (long) subSize, SEEK_CUR) != 0) return 0; } else if (type == IFF_ID_SSND) { subSize = Read32BitsHighLow(sf); chunkSize -= subSize; aiff_info.blkAlgn.offset = Read32BitsHighLow(sf); subSize -= 4; aiff_info.blkAlgn.blockSize = Read32BitsHighLow(sf); subSize -= 4; if (fskip(sf, (long) aiff_info.blkAlgn.offset, SEEK_CUR) != 0) return 0; aiff_info.sampleType = IFF_ID_SSND; is_aiff = 1; /* We've found the audio data. Read no further! */ break; } else { subSize = Read32BitsHighLow(sf); chunkSize -= subSize; if (fskip(sf, (long) subSize, SEEK_CUR) != 0) return 0; } } /* DEBUGF("Parsed AIFF %d\n", is_aiff); */ if (is_aiff) { /* make sure the header is sane */ if (0 != aiff_check2("name" /*???????????? */ , &aiff_info)) return 0; if( -1 == lame_set_num_channels( gfp, aiff_info.numChannels ) ) { if( silent < 10 ) { fprintf( stderr, "Unsupported number of channels: %ud\n", aiff_info.numChannels ); } exit( 1 ); } (void) lame_set_in_samplerate( gfp, (int)aiff_info.sampleRate ); pcmbitwidth = aiff_info.sampleSize; (void) lame_set_num_samples( gfp, aiff_info.numSampleFrames ); } return is_aiff; } /************************************************************************ * * parse_file_header * * PURPOSE: Read the header from a bytestream. Try to determine whether * it's a WAV file or AIFF without rewinding, since rewind * doesn't work on pipes and there's a good chance we're reading * from stdin (otherwise we'd probably be using libsndfile). * * When this function returns, the file offset will be positioned at the * beginning of the sound data. * ************************************************************************/ void parse_file_header(lame_global_flags * gfp, FILE * sf) { int type = Read32BitsHighLow(sf); /* DEBUGF( "First word of input stream: %08x '%4.4s'\n", type, (char*) &type); */ count_samples_carefully = 0; input_format = sf_raw; if (type == WAV_ID_RIFF) { /* It's probably a WAV file */ if (parse_wave_header(gfp, sf)) { input_format = sf_wave; count_samples_carefully = 1; } else { if( silent < 10 ) { fprintf( stderr, "Warning: corrupt or unsupported WAVE format\n"); } } } else if (type == IFF_ID_FORM) { /* It's probably an AIFF file */ if (parse_aiff_header(gfp, sf)) { input_format = sf_aiff; count_samples_carefully = 1; } } if (input_format == sf_raw) { /* ** Assume it's raw PCM. Since the audio data is assumed to begin ** at byte zero, this will unfortunately require seeking. */ if (fseek(sf, 0L, SEEK_SET) != 0) { /* ignore errors */ } input_format = sf_raw; } } void CloseSndFile(sound_file_format input, FILE * musicin) { if (fclose(musicin) != 0) { if( silent < 10 ) { fprintf(stderr, "Could not close audio input file\n"); } exit(2); } } FILE * OpenSndFile(lame_global_flags * gfp, char *inPath) { FILE *musicin; /* set the defaults from info incase we cannot determine them from file */ lame_set_num_samples( gfp, MAX_U_32_NUM ); if (!strcmp(inPath, "-")) { lame_set_stream_binary_mode(musicin = stdin); /* Read from standard input. */ } else { if ((musicin = fopen(inPath, "rb")) == NULL) { if( silent < 10 ) { fprintf(stderr, "Could not find \"%s\".\n", inPath); } exit(1); } } if (input_format == sf_mp1 || input_format == sf_mp2 || input_format == sf_mp3) { #ifdef AMIGA_MPEGA if (-1 == lame_decode_initfile(inPath, &mp3input_data)) { if( silent < 10 ) { fprintf(stderr, "Error reading headers in mp3 input file %s.\n", inPath); } exit(1); } #endif #ifdef HAVE_MPGLIB if (-1 == lame_decode_initfile(musicin, &mp3input_data)) { if( silent < 10 ) { fprintf(stderr, "Error reading headers in mp3 input file %s.\n", inPath); } exit(1); } #endif if( -1 == lame_set_num_channels( gfp, mp3input_data.stereo ) ) { if( silent < 10 ) { fprintf( stderr, "Unsupported number of channels: %ud\n", mp3input_data.stereo ); } exit( 1 ); } (void) lame_set_in_samplerate( gfp, mp3input_data.samplerate ); (void) lame_set_num_samples( gfp, mp3input_data.nsamp ); } else if (input_format == sf_ogg) { if( silent < 10 ) { fprintf(stderr, "sorry, vorbis support in LAME is deprecated.\n"); } exit(1); } else { if (input_format != sf_raw) { parse_file_header(gfp, musicin); } if (input_format == sf_raw) { /* assume raw PCM */ if( silent < 10 ) { fprintf(stderr, "Assuming raw pcm input file"); if (swapbytes) fprintf(stderr, " : Forcing byte-swapping\n"); else fprintf(stderr, "\n"); } pcmswapbytes = swapbytes; } } if (lame_get_num_samples( gfp ) == MAX_U_32_NUM && musicin != stdin) { double flen = lame_get_file_size(inPath); /* try to figure out num_samples */ if (flen >= 0) { /* try file size, assume 2 bytes per sample */ if (input_format == sf_mp1 || input_format == sf_mp2 || input_format == sf_mp3) { if (mp3input_data.bitrate > 0) { double totalseconds = (flen * 8.0 / (1000.0 * mp3input_data.bitrate)); unsigned long tmp_num_samples = (unsigned long) (totalseconds * lame_get_in_samplerate( gfp )); (void) lame_set_num_samples( gfp, tmp_num_samples ); mp3input_data.nsamp = tmp_num_samples; } } else { (void) lame_set_num_samples( gfp, (unsigned long)(flen / (2 * lame_get_num_channels( gfp ))) ); } } } return musicin; } #endif /* defined(LIBSNDFILE) */ #if defined(HAVE_MPGLIB) static int check_aid(const unsigned char *header) { return 0 == memcmp(header, "AiD\1", 4); } /* * Please check this and don't kill me if there's a bug * This is a (nearly?) complete header analysis for a MPEG-1/2/2.5 Layer I, II or III * data stream */ static int is_syncword_mp123(const void *const headerptr) { const unsigned char *const p = headerptr; static const char abl2[16] = { 0, 7, 7, 7, 0, 7, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8 }; if ((p[0] & 0xFF) != 0xFF) return 0; /* first 8 bits must be '1' */ if ((p[1] & 0xE0) != 0xE0) return 0; /* next 3 bits are also */ if ((p[1] & 0x18) == 0x08) return 0; /* no MPEG-1, -2 or -2.5 */ if ((p[1] & 0x06) == 0x00) return 0; /* no Layer I, II and III */ #ifndef USE_LAYER_1 if ((p[1] & 0x06) == 0x03*2) return 0; /* layer1 is not supported */ #endif #ifndef USE_LAYER_2 if ((p[1] & 0x06) == 0x02*2) return 0; /* layer1 is not supported */ #endif if (!(((p[1] & 0x06) == 0x03*2 && input_format == sf_mp1) || ((p[1] & 0x06) == 0x02*2 && input_format == sf_mp2) || ((p[1] & 0x06) == 0x01*2 && input_format == sf_mp3))) return 0; /* imcompatible layer with input file format */ if ((p[2] & 0xF0) == 0xF0) return 0; /* bad bitrate */ if ((p[2] & 0x0C) == 0x0C) return 0; /* no sample frequency with (32,44.1,48)/(1,2,4) */ if ((p[1] & 0x18) == 0x18 && (p[1] & 0x06) == 0x04 && abl2[p[2] >> 4] & (1 << (p[3] >> 6))) return 0; if ((p[3] & 3) == 2) return 0; /* reserved enphasis mode */ return 1; } int lame_decode_initfile(FILE * fd, mp3data_struct * mp3data) { /* VBRTAGDATA pTagData; */ /* int xing_header,len2,num_frames; */ unsigned char buf[100]; int ret; int len, aid_header; short int pcm_l[1152], pcm_r[1152]; int freeformat = 0; memset(mp3data, 0, sizeof(mp3data_struct)); lame_decode_init(); len = 4; if (fread(buf, 1, len, fd) != len) return -1; /* failed */ if (buf[0] == 'I' && buf[1] == 'D' && buf[2] == '3') { if( silent < 10 ) { fprintf(stderr, "ID3v2 found. " "Be aware that the ID3 tag is currently lost when transcoding.\n"); } len = 6; if (fread(&buf, 1, len, fd) != len) return -1; /* failed */ buf[2] &= 127; buf[3] &= 127; buf[4] &= 127; buf[5] &= 127; len = (((((buf[2] << 7) + buf[3]) << 7) + buf[4]) << 7) + buf[5]; fskip(fd, len, SEEK_CUR); len = 4; if (fread(&buf, 1, len, fd) != len) return -1; /* failed */ } aid_header = check_aid(buf); if (aid_header) { if (fread(&buf, 1, 2, fd) != 2) return -1; /* failed */ aid_header = (unsigned char) buf[0] + 256 * (unsigned char) buf[1]; if( silent < 10 ) { fprintf(stderr, "Album ID found. length=%i \n", aid_header); } /* skip rest of AID, except for 6 bytes we have already read */ fskip(fd, aid_header - 6, SEEK_CUR); /* read 4 more bytes to set up buffer for MP3 header check */ if (fread(&buf, 1, len, fd) != len) return -1; /* failed */ } len = 4; while (!is_syncword_mp123(buf)) { int i; for (i = 0; i < len - 1; i++) buf[i] = buf[i + 1]; if (fread(buf + len - 1, 1, 1, fd) != 1) return -1; /* failed */ } if ((buf[2] & 0xf0)==0) { if( silent < 10 ) { fprintf(stderr,"Input file is freeformat.\n"); } freeformat = 1; } /* now parse the current buffer looking for MP3 headers. */ /* (as of 11/00: mpglib modified so that for the first frame where */ /* headers are parsed, no data will be decoded. */ /* However, for freeformat, we need to decode an entire frame, */ /* so mp3data->bitrate will be 0 until we have decoded the first */ /* frame. Cannot decode first frame here because we are not */ /* yet prepared to handle the output. */ ret = lame_decode1_headersB(buf, len, pcm_l, pcm_r, mp3data,&enc_delay,&enc_padding); if (-1 == ret) return -1; /* repeat until we decode a valid mp3 header. */ while (!mp3data->header_parsed) { len = fread(buf, 1, sizeof(buf), fd); if (len != sizeof(buf)) return -1; ret = lame_decode1_headersB(buf, len, pcm_l, pcm_r, mp3data,&enc_delay,&enc_padding); if (-1 == ret) return -1; } if (mp3data->bitrate==0 && !freeformat) { if( silent < 10 ) { fprintf(stderr, "fail to sync...\n"); } return lame_decode_initfile(fd, mp3data); } if (mp3data->totalframes > 0) { /* mpglib found a Xing VBR header and computed nsamp & totalframes */ } else { /* set as unknown. Later, we will take a guess based on file size * ant bitrate */ mp3data->nsamp = MAX_U_32_NUM; } /* fprintf(stderr,"ret = %i NEED_MORE=%i \n",ret,MP3_NEED_MORE); fprintf(stderr,"stereo = %i \n",mp.fr.stereo); fprintf(stderr,"samp = %i \n",freqs[mp.fr.sampling_frequency]); fprintf(stderr,"framesize = %i \n",framesize); fprintf(stderr,"bitrate = %i \n",mp3data->bitrate); fprintf(stderr,"num frames = %ui \n",num_frames); fprintf(stderr,"num samp = %ui \n",mp3data->nsamp); fprintf(stderr,"mode = %i \n",mp.fr.mode); */ return 0; } /* For lame_decode_fromfile: return code -1 error n number of samples output. either 576 or 1152 depending on MP3 file. For lame_decode1_headers(): return code -1 error 0 ok, but need more data before outputing any samples n number of samples output. either 576 or 1152 depending on MP3 file. */ int lame_decode_fromfile(FILE * fd, short pcm_l[], short pcm_r[], mp3data_struct * mp3data) { int ret = 0, len=0; unsigned char buf[1024]; /* first see if we still have data buffered in the decoder: */ ret = lame_decode1_headers(buf, len, pcm_l, pcm_r, mp3data); if (ret!=0) return ret; /* read until we get a valid output frame */ while (1) { len = fread(buf, 1, 1024, fd); if (len == 0) { /* we are done reading the file, but check for buffered data */ ret = lame_decode1_headers(buf, len, pcm_l, pcm_r, mp3data); if (ret<=0) { lame_decode_exit(); /* release mp3decoder memory */ return -1; /* done with file */ } break; } ret = lame_decode1_headers(buf, len, pcm_l, pcm_r, mp3data); if (ret == -1) { lame_decode_exit(); /* release mp3decoder memory */ return -1; } if (ret >0) break; } return ret; } #endif /* defined(HAVE_MPGLIB) */ /* end of get_audio.c */