get_audio.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:26k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. #include "util.h"
  2. #include "get_audio.h"
  3. #ifdef HAVEGTK
  4. #include "gtkanal.h"
  5. #include <gtk/gtk.h>
  6. #endif
  7. #if (defined LIBSNDFILE || defined LAMESNDFILE)
  8. #ifdef _WIN32
  9. /* needed to set stdin to binary on windoze machines */
  10. #include <io.h>
  11. #endif
  12. static FILE *musicin=NULL;  /* input file pointer */
  13. static unsigned long num_samples;
  14. static int samp_freq;
  15. static int input_bitrate;
  16. static int num_channels;
  17. static int count_samples_carefully;
  18. int read_samples_pcm(lame_global_flags *gfp,short sample_buffer[2304],int frame_size, int samples_to_read);
  19. int read_samples_mp3(lame_global_flags *gfp,FILE *musicin,short int mpg123pcm[2][1152],int num_chan);
  20. void lame_init_infile(lame_global_flags *gfp)
  21. {
  22.   /* open the input file */
  23.   count_samples_carefully=0;
  24.   OpenSndFile(gfp,gfp->inPath,gfp->in_samplerate,gfp->num_channels);  
  25.   /* if GetSndSampleRate is non zero, use it to overwrite the default */
  26.   if (GetSndSampleRate()) gfp->in_samplerate=GetSndSampleRate();
  27.   if (GetSndChannels()) gfp->num_channels=GetSndChannels();
  28.   gfp->num_samples = GetSndSamples();
  29. }
  30. void lame_close_infile(lame_global_flags *gfp)
  31. {
  32.   CloseSndFile(gfp);
  33. }
  34. /************************************************************************
  35. *
  36. * lame_readframe()
  37. *
  38. * PURPOSE:  reads a frame of audio data from a file to the buffer,
  39. *   aligns the data for future processing, and separates the
  40. *   left and right channels
  41. *
  42. *
  43. ************************************************************************/
  44. int lame_readframe(lame_global_flags *gfp,short int Buffer[2][1152])
  45. {
  46.   int iread;
  47.   /* note: if input is gfp->stereo and output is mono, get_audio() 
  48.    * will return  .5*(L+R) in channel 0,  and nothing in channel 1. */
  49.   iread = get_audio(gfp,Buffer,gfp->stereo);
  50.   
  51.   /* check to see if we overestimated/underestimated totalframes */
  52.   if (iread==0)  gfp->totalframes = Min(gfp->totalframes,gfp->frameNum+2);
  53.   if (gfp->frameNum > (gfp->totalframes-1)) gfp->totalframes = gfp->frameNum;
  54.   return iread;
  55. }
  56. /************************************************************************
  57. *
  58. * get_audio()
  59. *
  60. * PURPOSE:  reads a frame of audio data from a file to the buffer,
  61. *   aligns the data for future processing, and separates the
  62. *   left and right channels
  63. *
  64. *
  65. ************************************************************************/
  66. int get_audio(lame_global_flags *gfp,short buffer[2][1152],int stereo)
  67. {
  68.   int j;
  69.   short insamp[2304];
  70.   int samples_read;
  71.   int framesize,samples_to_read;
  72.   static unsigned long num_samples_read;
  73.   unsigned long remaining;
  74.   int num_channels = gfp->num_channels;
  75.   if (gfp->frameNum==0) {
  76.     num_samples_read=0;
  77.     num_samples= GetSndSamples();
  78.   }
  79.   framesize = gfp->mode_gr*576;
  80.   samples_to_read = framesize;
  81.   if (count_samples_carefully) { 
  82.     /* if this flag has been set, then we are carefull to read 
  83.      * exactly num_samples and no more.  This is usefull for .wav and .aiff
  84.      * files which have id3 or other tags at the end.  Note that if you
  85.      * are using LIBSNDFILE, this is not necessary */
  86.     remaining=num_samples-Min(num_samples,num_samples_read);
  87.     if (remaining < (unsigned long)framesize) 
  88.       samples_to_read = remaining;
  89.   }
  90.   if (gfp->input_format==sf_mp3) {
  91.     /* decode an mp3 file for the input */
  92.     samples_read=read_samples_mp3(gfp,musicin,buffer,num_channels);
  93.   }else{
  94.     samples_read = read_samples_pcm(gfp,insamp,num_channels*framesize,num_channels*samples_to_read);
  95.     samples_read /=num_channels;
  96.     for(j=0;j<framesize;j++) {
  97.       buffer[0][j] = insamp[num_channels*j];
  98.       if (num_channels==2) buffer[1][j] = insamp[2*j+1];
  99.       else buffer[1][j]=0;
  100.     }
  101.   }
  102.   /* dont count things in this case to avoid overflows */
  103.   if (num_samples!=MAX_U_32_NUM) num_samples_read += samples_read;
  104.   return(samples_read);
  105. }
  106.   
  107.   
  108. int GetSndBitrate(void)
  109. {
  110. return input_bitrate;
  111. }
  112. int read_samples_mp3(lame_global_flags *gfp,FILE *musicin,short int mpg123pcm[2][1152],int stereo)
  113. {
  114. #if (defined  AMIGA_MPEGA || defined HAVEMPGLIB) 
  115.   int j,out=0;
  116. #ifdef HAVEGTK
  117.   static int framesize=0;
  118.   int ch;
  119. #endif
  120.   out=lame_decode_fromfile(musicin,mpg123pcm[0],mpg123pcm[1]);
  121.   /* out = -1:  error, probably EOF */
  122.   /* out = 0:   not possible with lame_decode_fromfile() */
  123.   /* out = number of output samples */
  124.   if (out==-1) {
  125.     for ( j = 0; j < 1152; j++ ) {
  126.       mpg123pcm[0][j] = 0;
  127.       mpg123pcm[1][j] = 0;
  128.     }
  129.   }
  130. #ifdef HAVEGTK
  131.   if (gfp->gtkflag) {
  132.     framesize=1152;
  133.     if (out==576) framesize=576;
  134.     
  135.     /* add a delay of framesize-DECDELAY, which will make the total delay
  136.      * exactly one frame, so we can sync MP3 output with WAV input */
  137.     
  138.     for ( ch = 0; ch < stereo; ch++ ) {
  139.       for ( j = 0; j < framesize-DECDELAY; j++ )
  140. pinfo->pcmdata2[ch][j] = pinfo->pcmdata2[ch][j+framesize];
  141.       for ( j = 0; j < framesize; j++ ) 
  142. pinfo->pcmdata2[ch][j+framesize-DECDELAY] = mpg123pcm[ch][j];
  143.     }
  144.   
  145.   pinfo->frameNum123 = gfp->frameNum-1;
  146.   pinfo->frameNum = gfp->frameNum;
  147.   }
  148. #endif
  149.   if (out==-1) return 0;
  150.   else return out;
  151. #else
  152.   fprintf(stderr,"Error: libmp3lame was not compiled with I/O support n");
  153.   exit(1);
  154. #endif
  155. }
  156. #endif  /* LAMESNDFILE or LIBSNDFILE */
  157. #ifdef LIBSNDFILE 
  158. /*
  159. ** Copyright (C) 1999 Albert Faber
  160. **  
  161.  * This library is free software; you can redistribute it and/or
  162.  * modify it under the terms of the GNU Library General Public
  163.  * License as published by the Free Software Foundation; either
  164.  * version 2 of the License, or (at your option) any later version.
  165.  *
  166.  * This library is distributed in the hope that it will be useful,
  167.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  168.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  169.  * Library General Public License for more details.
  170.  *
  171.  * You should have received a copy of the GNU Library General Public
  172.  * License along with this library; if not, write to the
  173.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  174.  * Boston, MA 02111-1307, USA.
  175.  */
  176. #include <stdio.h>
  177. /* External references */
  178. static SNDFILE* gs_pSndFileIn=NULL;
  179. static SF_INFO gs_wfInfo;
  180. unsigned long GetSndSamples(void)
  181. {
  182.        return gs_wfInfo.samples;
  183. }
  184. int GetSndSampleRate(void)
  185. {
  186. return gs_wfInfo.samplerate;
  187. }
  188. int GetSndChannels(void)
  189. {
  190. return gs_wfInfo.channels;
  191. }
  192. void CloseSndFile(lame_global_flags *gfp)
  193. {
  194.   if (gfp->input_format==sf_mp3) {
  195. #ifndef AMIGA_MPEGA
  196.     if (fclose(musicin) != 0){
  197.       fprintf(stderr, "Could not close audio input filen");
  198.       exit(2);
  199.     }
  200. #endif
  201.   }else{
  202. if (gs_pSndFileIn)
  203. {
  204. if (sf_close(gs_pSndFileIn) !=0)
  205. {
  206. fprintf(stderr, "Could not close sound file n");
  207. exit(2);
  208. }
  209. }
  210.   }
  211. }
  212. FILE * OpenSndFile(lame_global_flags *gfp,const char* lpszFileName, int default_samp,
  213. int default_channels)
  214. {
  215.   input_bitrate=0;
  216.   if (gfp->input_format==sf_mp3) {
  217. #ifdef AMIGA_MPEGA
  218.     if (-1==lame_decode_initfile(lpszFileName,&num_channels,&samp_freq,&input_bitrate,&num_samples)) {
  219.       fprintf(stderr,"Error reading headers in mp3 input file %s.n", lpszFileName);
  220.       exit(1);
  221.     }
  222. #endif
  223. #ifdef HAVEMPGLIB
  224.     if ((musicin = fopen(lpszFileName, "rb")) == NULL) {
  225.       fprintf(stderr, "Could not find "%s".n", lpszFileName);
  226.       exit(1);
  227.     }
  228.     if (-1==lame_decode_initfile(musicin,&num_channels,&samp_freq,&input_bitrate,&num_samples)) {
  229.       fprintf(stderr,"Error reading headers in mp3 input file %s.n", lpszFileName);
  230.       exit(1);
  231.     }
  232. #endif
  233.     gs_wfInfo.samples=num_samples;
  234.     gs_wfInfo.channels=num_channels;
  235.     gs_wfInfo.samplerate=samp_freq;
  236.   } else {
  237.     /* Try to open the sound file */
  238.     /* set some defaults incase input is raw PCM */
  239.     gs_wfInfo.seekable=(gfp->input_format!=sf_raw);  /* if user specified -r, set to not seekable */
  240.     gs_wfInfo.samplerate=default_samp;
  241.     gs_wfInfo.pcmbitwidth=16;
  242.     gs_wfInfo.channels=default_channels;
  243.     if (DetermineByteOrder()==order_littleEndian) {
  244.       if (gfp->swapbytes) gs_wfInfo.format=SF_FORMAT_RAW_BE;
  245.       else gs_wfInfo.format=SF_FORMAT_RAW_LE;
  246.     } else {
  247.       if (gfp->swapbytes) gs_wfInfo.format=SF_FORMAT_RAW_LE;
  248.       else gs_wfInfo.format=SF_FORMAT_RAW_BE;
  249.     }
  250.     gs_pSndFileIn=sf_open_read(lpszFileName,&gs_wfInfo);
  251.         /* Check result */
  252. if (gs_pSndFileIn==NULL)
  253. {
  254.         sf_perror(gs_pSndFileIn);
  255. fprintf(stderr, "Could not open sound file "%s".n", lpszFileName);
  256. exit(1);
  257. }
  258.     if ((gs_wfInfo.format==SF_FORMAT_RAW_LE) || 
  259. (gs_wfInfo.format==SF_FORMAT_RAW_BE)) 
  260.       gfp->input_format=sf_raw;
  261. #ifdef _DEBUG_SND_FILE
  262. printf("nnSF_INFO structuren");
  263. printf("samplerate        :%dn",gs_wfInfo.samplerate);
  264. printf("samples           :%dn",gs_wfInfo.samples);
  265. printf("channels          :%dn",gs_wfInfo.channels);
  266. printf("pcmbitwidth       :%dn",gs_wfInfo.pcmbitwidth);
  267. printf("format            :");
  268. /* new formats from sbellon@sbellon.de  1/2000 */
  269.         if ((gs_wfInfo.format&SF_FORMAT_TYPEMASK)==SF_FORMAT_WAV)
  270.   printf("Microsoft WAV format (big endian). ");
  271. if ((gs_wfInfo.format&SF_FORMAT_TYPEMASK)==SF_FORMAT_AIFF)
  272.   printf("Apple/SGI AIFF format (little endian). ");
  273. if ((gs_wfInfo.format&SF_FORMAT_TYPEMASK)==SF_FORMAT_AU)
  274.   printf("Sun/NeXT AU format (big endian). ");
  275. if ((gs_wfInfo.format&SF_FORMAT_TYPEMASK)==SF_FORMAT_AULE)
  276.   printf("DEC AU format (little endian). ");
  277. if ((gs_wfInfo.format&SF_FORMAT_TYPEMASK)==SF_FORMAT_RAW)
  278.   printf("RAW PCM data. ");
  279. if ((gs_wfInfo.format&SF_FORMAT_TYPEMASK)==SF_FORMAT_PAF)
  280.   printf("Ensoniq PARIS file format. ");
  281. if ((gs_wfInfo.format&SF_FORMAT_TYPEMASK)==SF_FORMAT_SVX)
  282.   printf("Amiga IFF / SVX8 / SV16 format. ");
  283. if ((gs_wfInfo.format&SF_FORMAT_TYPEMASK)==SF_FORMAT_NIST)
  284.   printf("Sphere NIST format. ");
  285. if ((gs_wfInfo.format&SF_FORMAT_SUBMASK)==SF_FORMAT_PCM)
  286.   printf("PCM data in 8, 16, 24 or 32 bits.");
  287. if ((gs_wfInfo.format&SF_FORMAT_SUBMASK)==SF_FORMAT_FLOAT)
  288.   printf("32 bit Intel x86 floats.");
  289. if ((gs_wfInfo.format&SF_FORMAT_SUBMASK)==SF_FORMAT_ULAW)
  290.   printf("U-Law encoded.");
  291. if ((gs_wfInfo.format&SF_FORMAT_SUBMASK)==SF_FORMAT_ALAW)
  292.   printf("A-Law encoded.");
  293. if ((gs_wfInfo.format&SF_FORMAT_SUBMASK)==SF_FORMAT_IMA_ADPCM)
  294.   printf("IMA ADPCM.");
  295. if ((gs_wfInfo.format&SF_FORMAT_SUBMASK)==SF_FORMAT_MS_ADPCM)
  296.   printf("Microsoft ADPCM.");
  297. if ((gs_wfInfo.format&SF_FORMAT_SUBMASK)==SF_FORMAT_PCM_BE)
  298.   printf("Big endian PCM data.");
  299. if ((gs_wfInfo.format&SF_FORMAT_SUBMASK)==SF_FORMAT_PCM_LE)
  300.   printf("Little endian PCM data.");
  301. if ((gs_wfInfo.format&SF_FORMAT_SUBMASK)==SF_FORMAT_PCM_S8)
  302.   printf("Signed 8 bit PCM.");
  303. if ((gs_wfInfo.format&SF_FORMAT_SUBMASK)==SF_FORMAT_PCM_U8)
  304.   printf("Unsigned 8 bit PCM.");
  305. if ((gs_wfInfo.format&SF_FORMAT_SUBMASK)==SF_FORMAT_SVX_FIB)
  306.   printf("SVX Fibonacci Delta encoding.");
  307. if ((gs_wfInfo.format&SF_FORMAT_SUBMASK)==SF_FORMAT_SVX_EXP)
  308.   printf("SVX Exponential Delta encoding.");
  309. printf("n");
  310. printf("pcmbitwidth       :%dn",gs_wfInfo.pcmbitwidth);
  311. printf("sections          :%dn",gs_wfInfo.sections);
  312. printf("seekable          :n",gs_wfInfo.seekable);
  313. #endif
  314.   }
  315.   if (gs_wfInfo.samples==MAX_U_32_NUM) {
  316.     struct stat sb;
  317.     /* try to figure out num_samples */
  318.     if (0==stat(lpszFileName,&sb)) {
  319.       /* try file size, assume 2 bytes per sample */
  320.       if (gfp->input_format == sf_mp3) {
  321. FLOAT totalseconds = (sb.st_size*8.0/(1000.0*GetSndBitrate()));
  322. gs_wfInfo.samples= totalseconds*GetSndSampleRate();
  323.       }else{
  324. gs_wfInfo.samples = sb.st_size/(2*GetSndChannels());
  325.       }
  326.     }
  327.   }
  328.   return musicin;    
  329. }
  330. /************************************************************************
  331. *
  332. * read_samples()
  333. *
  334. * PURPOSE:  reads the PCM samples from a file to the buffer
  335. *
  336. *  SEMANTICS:
  337. * Reads #samples_read# number of shorts from #musicin# filepointer
  338. * into #sample_buffer[]#.  Returns the number of samples read.
  339. *
  340. ************************************************************************/
  341. int read_samples_pcm(lame_global_flags *gfp,short sample_buffer[2304],int frame_size,int samples_to_read)
  342. {
  343.     int  samples_read;
  344.     int rcode;
  345.     samples_read=sf_read_short(gs_pSndFileIn,sample_buffer,samples_to_read);
  346.     
  347.     rcode = samples_read;
  348.     if (samples_read < frame_size)
  349.       {
  350. /*fprintf(stderr,"Insufficient PCM input for one frame - fillout with zerosn"); 
  351. */
  352. if (samples_read<0) samples_read=0;
  353. for (; samples_read < frame_size; sample_buffer[samples_read++] = 0);
  354.       }
  355. if (8==gs_wfInfo.pcmbitwidth)
  356.   for (; samples_read >= 0; sample_buffer[samples_read] = sample_buffer[samples_read--] * 256);
  357.     return(rcode);
  358. }
  359. #endif /* ifdef LIBSNDFILE */
  360. #ifdef LAMESNDFILE 
  361. /************************************************************************
  362.  ************************************************************************
  363.  ************************************************************************
  364.  ************************************************************************
  365.  ************************************************************************
  366.  ************************************************************************
  367.  *
  368.  * OLD ISO/LAME routines follow.  Used if you dont have LIBSNDFILE
  369.  * or for stdin/stdout support
  370.  *
  371.  ************************************************************************
  372.  ************************************************************************
  373.  ************************************************************************
  374.  ************************************************************************
  375.  ************************************************************************
  376.  ************************************************************************/
  377. /* Replacement for forward fseek(,,SEEK_CUR), because fseek() fails on pipes */
  378. int fskip(FILE *sf,long num_bytes,int dummy)
  379. {
  380.   char data[1024];
  381.   int nskip = 0;
  382.   while (num_bytes > 0) {
  383.     nskip = (num_bytes>1024) ? 1024 : num_bytes;
  384.     num_bytes -= fread(data,(size_t)1,(size_t)nskip,sf);
  385.   }
  386.   /* return 0 if last read was successful */
  387.   return num_bytes;
  388. }
  389. void CloseSndFile(lame_global_flags *gfp)
  390. {
  391.   if (fclose(musicin) != 0){
  392.     fprintf(stderr, "Could not close audio input filen");
  393.     exit(2);
  394.   }
  395. }
  396. unsigned long GetSndSamples(void)
  397. {
  398.        return num_samples;
  399. }
  400. int GetSndSampleRate(void)
  401. {
  402. return samp_freq;
  403. }
  404. int GetSndChannels(void)
  405. {
  406. return num_channels;
  407. }
  408. FILE * OpenSndFile(lame_global_flags *gfp,const char* inPath, int default_samp,
  409. int default_channels)
  410. {
  411.   struct stat sb;
  412.   void parse_file_header(lame_global_flags *gfp,FILE *sf);
  413.   /* set the defaults from info incase we cannot determine them from file */
  414.   num_samples=MAX_U_32_NUM;
  415.   samp_freq=default_samp;
  416.   num_channels = default_channels;
  417.   
  418.   if (!strcmp(inPath, "-")) {
  419.     /* Read from standard input. */
  420. #ifdef __EMX__
  421.     _fsetmode(stdin,"b");
  422. #elif (defined  __BORLANDC__)
  423.     setmode(_fileno(stdin), O_BINARY);
  424. #elif (defined  __CYGWIN__)
  425.     setmode(fileno(stdin), _O_BINARY);
  426. #elif (defined _WIN32)
  427.     _setmode(_fileno(stdin), _O_BINARY);
  428. #endif
  429.     musicin = stdin;
  430.   } else {
  431.     if ((musicin = fopen(inPath, "rb")) == NULL) {
  432.       fprintf(stderr, "Could not find "%s".n", inPath);
  433.       exit(1);
  434.     }
  435.   }
  436.   
  437.   input_bitrate=0;
  438.   if (gfp->input_format==sf_mp3) {
  439. #ifdef AMIGA_MPEGA
  440.     if (-1==lame_decode_initfile(inPath,&num_channels,&samp_freq,&input_bitrate,&num_samples)) {
  441.       fprintf(stderr,"Error reading headers in mp3 input file %s.n", inPath);
  442.       exit(1);
  443.     }
  444. #endif
  445. #ifdef HAVEMPGLIB
  446.     if (-1==lame_decode_initfile(musicin,&num_channels,&samp_freq,&input_bitrate,&num_samples)) {
  447.       fprintf(stderr,"Error reading headers in mp3 input file %s.n", inPath);
  448.       exit(1);
  449.     }
  450. #endif
  451.  }else{
  452.    if (gfp->input_format != sf_raw) {
  453.      parse_file_header(gfp,musicin);
  454.    }
  455.    
  456.    if (gfp->input_format==sf_raw) {
  457.      /* assume raw PCM */
  458.      fprintf(stderr, "Assuming raw pcm input file");
  459.      if (gfp->swapbytes==TRUE)
  460.        fprintf(stderr, " : Forcing byte-swappingn");
  461.      else
  462.        fprintf(stderr, "n");
  463.    }
  464.  }
  465.     
  466.   if (num_samples==MAX_U_32_NUM && musicin != stdin) {
  467.     /* try to figure out num_samples */
  468.     if (0==stat(inPath,&sb)) {  
  469.       /* try file size, assume 2 bytes per sample */
  470.       if (gfp->input_format == sf_mp3) {
  471. FLOAT totalseconds = (sb.st_size*8.0/(1000.0*GetSndBitrate()));
  472. num_samples= totalseconds*GetSndSampleRate();
  473.       }else{
  474. num_samples = sb.st_size/(2*GetSndChannels());
  475.       }
  476.     }
  477.   }
  478.   return musicin;
  479. }
  480.   
  481.   
  482. /************************************************************************
  483. *
  484. * read_samples()
  485. *
  486. * PURPOSE:  reads the PCM samples from a file to the buffer
  487. *
  488. *  SEMANTICS:
  489. * Reads #samples_read# number of shorts from #musicin# filepointer
  490. * into #sample_buffer[]#.  Returns the number of samples read.
  491. *
  492. ************************************************************************/
  493. int read_samples_pcm(lame_global_flags *gfp,short sample_buffer[2304], int frame_size,int samples_to_read)
  494. {
  495.     int samples_read;
  496.     int rcode;
  497.     int iswav=(gfp->input_format==sf_wave);
  498.     samples_read = fread(sample_buffer, sizeof(short), samples_to_read, musicin);
  499.     if (ferror(musicin)) {
  500.       fprintf(stderr, "Error reading input filen");
  501.       exit(2);
  502.     }
  503.     /*
  504.        Samples are big-endian. If this is a little-endian machine
  505.        we must swap
  506.      */
  507.     if ( NativeByteOrder == order_unknown )
  508.       {
  509. NativeByteOrder = DetermineByteOrder();
  510. if ( NativeByteOrder == order_unknown )
  511.   {
  512.     fprintf( stderr, "byte order not determinedn" );
  513.     exit( 1 );
  514.   }
  515.       }
  516.     /* intel=littleEndian */
  517.     if (!iswav && ( NativeByteOrder == order_littleEndian ))
  518.       SwapBytesInWords( sample_buffer, samples_read );
  519.     if (iswav && ( NativeByteOrder == order_bigEndian ))
  520.       SwapBytesInWords( sample_buffer, samples_read );
  521.     if (gfp->swapbytes==TRUE)
  522.       SwapBytesInWords( sample_buffer, samples_read );
  523.     rcode=samples_read;
  524.     if (samples_read < frame_size) {
  525.       if (samples_read<0) samples_read=0;
  526.       /*fprintf(stderr,"Insufficient PCM input for one frame - fillout with zerosn");
  527.       */
  528.       for (; samples_read < frame_size; sample_buffer[samples_read++] = 0);
  529.     }
  530.     return(rcode);
  531. }
  532. #define WAV_ID_RIFF 0x52494646 /* "RIFF" */
  533. #define WAV_ID_WAVE 0x57415645 /* "WAVE" */
  534. #define WAV_ID_FMT  0x666d7420 /* "fmt " */
  535. #define WAV_ID_DATA 0x64617461 /* "data" */
  536. typedef struct fmt_chunk_data_struct {
  537. short format_tag;  /* Format category */
  538. u_short channels;  /* Number of channels */
  539. u_long samples_per_sec;  /* Sampling rate */
  540. u_long avg_bytes_per_sec;  /* For buffer estimation */
  541. u_short block_align;  /* Data block size */
  542. u_short bits_per_sample;  /* for PCM data, anyway... */
  543. } fmt_chunk_data;
  544. /************************************************************************
  545. *
  546. * wave_check
  547. *
  548. * PURPOSE: Checks Wave header information to make sure it is valid.
  549. * Exits if not.
  550. *
  551. ************************************************************************/
  552. static void
  553. wave_check(char *file_name, fmt_chunk_data *wave_info)
  554. {
  555. if (wave_info->bits_per_sample != 16) {
  556. fprintf(stderr, "%d-bit sample-size is not supported!n",
  557. wave_info->bits_per_sample);
  558. exit(1);
  559. }
  560. }
  561. /*****************************************************************************
  562.  *
  563.  * Read Microsoft Wave headers
  564.  *
  565.  * By the time we get here the first 32-bits of the file have already been
  566.  * read, and we're pretty sure that we're looking at a WAV file.
  567.  *
  568.  *****************************************************************************/
  569. static int
  570. parse_wave_header(FILE *sf)
  571. {
  572. fmt_chunk_data wave_info;
  573. int is_wav = 0;
  574. long data_length = 0, file_length, subSize = 0;
  575. int loop_sanity = 0;
  576. memset(&wave_info, 0, sizeof(wave_info));
  577. file_length = Read32BitsHighLow(sf);
  578. if (Read32BitsHighLow(sf) != WAV_ID_WAVE)
  579. return 0;
  580. for (loop_sanity = 0; loop_sanity < 20; ++loop_sanity) {
  581. u_int type = Read32BitsHighLow(sf);
  582. if (type == WAV_ID_FMT) {
  583. subSize = Read32BitsLowHigh(sf);
  584. if (subSize < 16) {
  585.   /*fprintf(stderr,
  586.     "'fmt' chunk too short (only %ld bytes)!", subSize);  */
  587. return 0;
  588. }
  589. wave_info.format_tag = Read16BitsLowHigh(sf);
  590. subSize -= 2;
  591. wave_info.channels = Read16BitsLowHigh(sf);
  592. subSize -= 2;
  593. wave_info.samples_per_sec = Read32BitsLowHigh(sf);
  594. subSize -= 4;
  595. wave_info.avg_bytes_per_sec = Read32BitsLowHigh(sf);
  596. subSize -= 4;
  597. wave_info.block_align = Read16BitsLowHigh(sf);
  598. subSize -= 2;
  599. wave_info.bits_per_sample = Read16BitsLowHigh(sf);
  600. subSize -= 2;
  601. /* fprintf(stderr, "   skipping %d bytesn", subSize); */
  602. if (subSize > 0) {
  603. if (fskip(sf, (long)subSize, SEEK_CUR) != 0 )
  604. return 0;
  605. };
  606. } else if (type == WAV_ID_DATA) {
  607. subSize = Read32BitsLowHigh(sf);
  608. data_length = subSize;
  609. is_wav = 1;
  610. /* We've found the audio data. Read no further! */
  611. break;
  612. } else {
  613. subSize = Read32BitsLowHigh(sf);
  614. if (fskip(sf, (long) subSize, SEEK_CUR) != 0 ) return 0;
  615. }
  616. }
  617. if (is_wav) {
  618. /* make sure the header is sane */
  619. wave_check("name", &wave_info);
  620. num_channels  = wave_info.channels;
  621. samp_freq     = wave_info.samples_per_sec;
  622. num_samples   = data_length / (wave_info.channels * wave_info.bits_per_sample / 8);
  623. }
  624. return is_wav;
  625. }
  626. /************************************************************************
  627. *
  628. * aiff_check
  629. *
  630. * PURPOSE: Checks AIFF header information to make sure it is valid.
  631. * Exits if not.
  632. *
  633. ************************************************************************/
  634. static void
  635. aiff_check2(const char *file_name, IFF_AIFF *pcm_aiff_data)
  636. {
  637. if (pcm_aiff_data->sampleType != IFF_ID_SSND) {
  638.    fprintf(stderr, "Sound data is not PCM in "%s".n", file_name);
  639.    exit(1);
  640. }
  641. if (pcm_aiff_data->sampleSize != sizeof(short) * BITS_IN_A_BYTE) {
  642. fprintf(stderr, "Sound data is not %d bits in "%s".n",
  643. (unsigned int) sizeof(short) * BITS_IN_A_BYTE, file_name);
  644. exit(1);
  645. }
  646. if (pcm_aiff_data->numChannels != 1 &&
  647. pcm_aiff_data->numChannels != 2) {
  648.    fprintf(stderr, "Sound data is not mono or stereo in "%s".n",
  649.    file_name);
  650.    exit(1);
  651. }
  652. if (pcm_aiff_data->blkAlgn.blockSize != 0) {
  653.    fprintf(stderr, "Block size is not %d bytes in "%s".n",
  654.    0, file_name);
  655.    exit(1);
  656. }
  657. if (pcm_aiff_data->blkAlgn.offset != 0) {
  658.    fprintf(stderr, "Block offset is not %d bytes in "%s".n",
  659.    0, file_name);
  660.    exit(1);
  661. }
  662. }
  663. /*****************************************************************************
  664.  *
  665.  * Read Audio Interchange File Format (AIFF) headers.
  666.  *
  667.  * By the time we get here the first 32-bits of the file have already been
  668.  * read, and we're pretty sure that we're looking at an AIFF file.
  669.  *
  670.  *****************************************************************************/
  671. static int
  672. parse_aiff_header(FILE *sf)
  673. {
  674. int is_aiff = 0;
  675. long chunkSize = 0, subSize = 0;
  676. IFF_AIFF aiff_info;
  677. memset(&aiff_info, 0, sizeof(aiff_info));
  678. chunkSize = Read32BitsHighLow(sf);
  679. if ( Read32BitsHighLow(sf) != IFF_ID_AIFF )
  680. return 0;
  681. while ( chunkSize > 0 )
  682. {
  683. u_int type = 0;
  684. chunkSize -= 4;
  685. type = Read32BitsHighLow(sf);
  686. /* fprintf(stderr,
  687. "found chunk type %08x '%4.4s'n", type, (char*)&type); */
  688. /* don't use a switch here to make it easier to use 'break' for SSND */
  689. if (type == IFF_ID_COMM) {
  690. subSize = Read32BitsHighLow(sf);
  691. chunkSize -= subSize;
  692. aiff_info.numChannels   = Read16BitsHighLow(sf);
  693. subSize -= 2;
  694. aiff_info.numSampleFrames = Read32BitsHighLow(sf);
  695. subSize -= 4;
  696. aiff_info.sampleSize   = Read16BitsHighLow(sf);
  697. subSize -= 2;
  698. aiff_info.sampleRate   = ReadIeeeExtendedHighLow(sf);
  699. subSize -= 10;
  700. if (fskip(sf, (long) subSize, SEEK_CUR) != 0 )
  701. return 0;
  702. } else if (type == IFF_ID_SSND) {
  703. subSize = Read32BitsHighLow(sf);
  704. chunkSize -= subSize;
  705. aiff_info.blkAlgn.offset = Read32BitsHighLow(sf);
  706. subSize -= 4;
  707. aiff_info.blkAlgn.blockSize = Read32BitsHighLow(sf);
  708. subSize -= 4;
  709. if (fskip(sf, aiff_info.blkAlgn.offset, SEEK_CUR) != 0 )
  710. return 0;
  711. aiff_info.sampleType = IFF_ID_SSND;
  712. is_aiff = 1;
  713. /* We've found the audio data. Read no further! */
  714. break;
  715. } else {
  716. subSize = Read32BitsHighLow(sf);
  717. chunkSize -= subSize;
  718. if (fskip(sf, (long) subSize, SEEK_CUR) != 0 )
  719. return 0;
  720. }
  721. }
  722. /* fprintf(stderr, "Parsed AIFF %dn", is_aiff); */
  723. if (is_aiff) {
  724. /* make sure the header is sane */
  725. aiff_check2("name", &aiff_info);
  726. num_channels  = aiff_info.numChannels;
  727. samp_freq     = aiff_info.sampleRate;
  728. num_samples   = aiff_info.numSampleFrames;
  729. }
  730. return is_aiff;
  731. }
  732. /************************************************************************
  733. *
  734. * parse_file_header
  735. *
  736. * PURPOSE: Read the header from a bytestream.  Try to determine whether
  737. *    it's a WAV file or AIFF without rewinding, since rewind
  738. *    doesn't work on pipes and there's a good chance we're reading
  739. *    from stdin (otherwise we'd probably be using libsndfile).
  740. *
  741. * When this function returns, the file offset will be positioned at the
  742. * beginning of the sound data.
  743. *
  744. ************************************************************************/
  745. void parse_file_header(lame_global_flags *gfp,FILE *sf)
  746. {
  747. u_int type = 0;
  748. type = Read32BitsHighLow(sf);
  749. /* fprintf(stderr,
  750. "First word of input stream: %08x '%4.4s'n", type, (char*) &type); */
  751. count_samples_carefully=0;
  752. gfp->input_format = sf_raw;
  753. if (type == WAV_ID_RIFF) {
  754. /* It's probably a WAV file */
  755. if (parse_wave_header(sf)) {
  756. gfp->input_format = sf_wave;
  757. count_samples_carefully=1;
  758. }
  759. } else if (type == IFF_ID_FORM) {
  760. /* It's probably an AIFF file */
  761. if (parse_aiff_header(sf)) {
  762. gfp->input_format = sf_aiff;
  763. count_samples_carefully=1;
  764. }
  765. }
  766. if (gfp->input_format==sf_raw) {
  767.   /*
  768.   ** Assume it's raw PCM.  Since the audio data is assumed to begin
  769.   ** at byte zero, this will unfortunately require seeking.
  770.   */
  771.   if (fseek(sf, 0L, SEEK_SET) != 0) {
  772.     /* ignore errors */
  773.   }
  774.   gfp->input_format = sf_raw;
  775. }
  776. }
  777. #endif  /* LAMESNDFILE */