mp3 lame

The LAME API

This is the simple interface to the encodingpart of libmp3lame.so.
The library also contains routines foradding id3 tags and
mp3decoding
.  These routines are not fully documented,
butyou can figure them out by looking at "include/lame.h" andthe
example frontend encoder/decoder source code infrontend/main.c

All of these steps should be done for everyMP3 to beencoded.


=========================================================================

1.(optional) Get the version number of the encoder, if you areinterested.  
   void get_lame_version(char*strbuf, size_t buflen, const char *prefix);


2. Errormessages.  By default, LAME will write error messages to
stderrusing vfprintf().  For GUI applications, this is often aproblem
and you need to set your own error message handlers:

  lame_set_errorf(gfp,error_handler_function);
  lame_set_debugf(gfp,error_handler_function);
  lame_set_msgf(gfp,error_handler_function);
 
See lame.hfor details.


3. Initialize the encoder.  sets defaultfor all encoder parameters.

   #include "lame.h"
  lame_global_flags *gfp;
   gfp = lame_init();

Thedefault (if you set nothing) is a  J-Stereo, 44.1khz
128kbpsCBR mp3 file at quality 5.  Override various default settings
as necessary, for example:

  lame_set_num_channels(gfp,2);
  lame_set_in_samplerate(gfp,44100);
  lame_set_brate(gfp,128);
   lame_set_mode(gfp,1);
  lame_set_quality(gfp,2);   /* 2=high  5 = medium 7=low */


See lame.h for the complete list of options. Note that there are
some lame_set_*() calls not documented inlame.h.  These functions
are experimental and for testingonly.  They may be removed in
the future.



4.Set more internal configuration based on data provided above,
  as well as checking for problems.  Check that ret_code >=0.

   ret_code = lame_init_params(gfp);



5.Encode some data.  input pcmdata, output (maybe) mp3 frames.
This routine handles allbuffering, resampling and filtering for you.
Therequired mp3buffer_size can be computed from num_samples,
samplerateand encoding rate, but here is a worst case estimate:
mp3buffer_size(in bytes) = 1.25*num_samples + 7200.

num_samples = thenumber of PCM samples in each channel.  It is
not the sum ofthe number of samples in the L and R channels.

The return code= number of bytes output in mp3buffer.  This can be 0.
If itis <0, an error occured.  

   intlame_encode_buffer(lame_global_flags *gfp,
        short int leftpcm[], short int rightpcm[],
        int num_samples,char *mp3buffer,int  mp3buffer_size);


Thereare also routines for various types of input  
(float, long,interleaved, etc).  See lame.h for details.


6.lame_encode_flush will flush the buffers and may return a
finalfew mp3 frames.  mp3buffershould be at least 7200 bytes.
return code = number ofbytes output to mp3buffer.  This can be 0.

intlame_encode_flush(lame_global_flags *,char *mp3buffer, intmp3buffer_size);


7.  Write the Xing VBR/INFO tag tomp3 file.  

void lame_mp3_tags_fid(lame_global_flags*,FILE* fid);

This adds avalid mp3 frame which contains information about the
bitstreamsome players may find usefull.
  It is used for CBR,ABRand
VBR.  The routine will attempt to rewind the outputstream to the
beginning.  If this is not possible, (forexample, you are encoding to
stdout) you should specificallydisable the tag by calling
lame_set_bWriteVbrTag(gfp,0) in step 3above, and call
lame_mp3_tags_fid() with fid=NULL.  If therewind fails and
the tag was not disabled, the first mp3 frame inthe bitstream
will be all 0's.



8. free the internaldata structures.

void lame_close(lame_global_flags *);





#include "lame.h"

#include <stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include <fcntl.h>
#include<errno.h>
//#include <signal.h>
//#include<sys/ioctl.h>
#include <memory.h>
//#include<linux/soundcard.h>
#include <alsa/asoundlib.h>
#include<sys/time.h>

#define TIMES    10       //录音时间,
#defineRATE    41000       //采样频率
#defineBITS    16       //量化位数
#defineCHANNELS 2        //声道数目
#defineINBUFF_SIZE 4096
#define MP3BUFF_SIZE (int) (1.25 * INBUFF_SIZE) +7200

// handle the case of underrun or overrun
int xrun(snd_pcm_t * handle);
// handle the case that device busy
intsuspend (snd_pcm_t * handle);
// set alsa params
int
SetFormat(snd_pcm_t * handle, unsigned int channels, unsigned int rate)
{
 int ret = 0;

  ret =
   snd_pcm_set_params (handle, SND_PCM_FORMAT_S16_LE,
           SND_PCM_ACCESS_RW_INTERLEAVED,channels, rate, 1,
           500000);
  if (ret != 0)
    {
     printf ("Unable to set params,error(%s)\n", snd_strerror(ret));
    }

  return ret;
}

int
main(int argc, char **argv)
{
  int fd_dsp;
  FILE*fd_tmp;
  FILE *fd_mp3;
  lame_global_flags*gfp;
  short *input_buff;
  unsignedchar *mp3_buff;

  int samples;
  intmp3_bytes;
  int write_bytes;
  int num = 0;
 int ch;
  int i = 0;
  int ret = 0;
 snd_pcm_t *handle;

  if (argc != 2)
   {
      fprintf (stderr, "Useage:./mp3_record test.mp3\n");
     return -1;
    }

  if (snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0) !=0)
    {
      printf("Failed to open device\n");
     return -1;
    }
  if (SetFormat (handle,CHANNELS, RATE) != 0)
    {
     printf ("Cannot set sound device in bit 16, channel 2, speed44100.\n");
      return -1;
   }

  if ((fd_mp3 = fopen (argv[1], "w")) ==NULL)
    {
     fprintf (stderr, "Open file error: %s\n", strerror(errno));
      ret = -1;
     goto CLOSE_DSP;
    }
  gfp= lame_init ();
  if (gfp == NULL)
   {
      printf ("lame_initfailed\n");
      ret = -1;
     goto CLOSE_MP3;
    }

 lame_set_in_samplerate (gfp, RATE);
 //lame_set_out_samplerate(gfp, RATE);
  lame_set_num_channels(gfp, CHANNELS);
  //lame_set_brate(gfp, 24);
 //lame_set_VBR_min_bitrate_kbps(gfp, lame_get_brate(gfp));
 //lame_set_quality(gfp,7);
  ret= lame_init_params (gfp);
  if (ret < 0)
   {
      printf ("lame_init_paramsreturned %d\n", ret);
      ret =-1;
      goto CLOSE_LAME;
   }
  ch =lame_get_num_channels (gfp);
  printf ("defaultrate is %d, out rate is %d.\n",
     lame_get_in_samplerate (gfp), lame_get_out_samplerate (gfp));
 printf ("default brate is %d.\n", lame_get_brate (gfp));
 printf ("default samples is %lu.\n", lame_get_num_samples(gfp));
  printf ("default channel is %d.\n",ch);
  printf ("default vbr_mode is %d.\n",lame_get_VBR (gfp));
  printf ("default force_ms is%d.\n", lame_get_force_ms (gfp));
  printf ("defaultmode is %d.\n", lame_get_mode (gfp));
  printf ("defaultcompression_ratio is %f.\n",
     lame_get_compression_ratio (gfp));
  printf ("defaultVBR_mean_bitrate is %d.\n",
     lame_get_VBR_mean_bitrate_kbps (gfp));
  printf ("defaultquality is %d.\n", lame_get_quality (gfp));


 input_buff = (short *) malloc (INBUFF_SIZE * CHANNELS);
 mp3_buff = (unsigned char *) malloc (MP3BUFF_SIZE);
  if(input_buff == NULL || mp3_buff == NULL)
   {
      printf ("Failed tomalloc.\n");
      gotoFREE_BUF;
    }

  if ((TIMES * RATE *BITS * CHANNELS / 8) % (INBUFF_SIZE * CHANNELS) != 0)
   num = (TIMES * RATE * BITS * CHANNELS / 8) / (INBUFF_SIZE * CHANNELS)+ 1;
  else
    num = (TIMES * RATE * BITS* CHANNELS / 8) / (INBUFF_SIZE * CHANNELS);
  for (i = 0; i <num; i++)
    {
     memset (input_buff, 0, INBUFF_SIZE * CHANNELS);
     memset (mp3_buff, 0, MP3BUFF_SIZE);
#if 0
     samples = read (fd_dsp, input_buff, INBUFF_SIZE * 2);
     if (samples < 0)
    {
     perror ("Read sound device failed");
     ret = -1;
      goto FREE_BUF;
   }
      printf ("samples is%d.\n", samples);
#endif

1、读取PCM音频数据
     samples = ret = snd_pcm_readi(handle, input_buff, INBUFF_SIZE / 2);
     if (ret == -EAGAIN || (ret >= 0 && (size_t) ret <INBUFF_SIZE / 2))
    {
     snd_pcm_wait (handle, 1000);
      gotoFREE_BUF;
    }
     else if (ret == -EBADFD)
    {           // PCM is not in the right state
     printf ("PCM is not in the right state!\n ");   // EPIPE means underrun
      gotoFREE_BUF;
    }
     else if (ret == -EPIPE)
    {           // an overrun occurred
     printf ("an overrun occurred. samples = %d\n", samples);
     if (xrun (handle) < 0)
       {
          gotoFREE_BUF;
        }

   }
      else if (ret ==-ESTRPIPE)
    {           // a suspend event occurred
      printf("a suspend event occurred\n");
     if (suspend (handle) < 0)
       {
          gotoFREE_BUF;
        }
   }

      //printf("samplesis %d.\n", samples);



2、编码压缩
     mp3_bytes =
    lame_encode_buffer_interleaved(gfp, input_buff, samples, mp3_buff,
                  MP3BUFF_SIZE);

     //mp3_bytes = lame_encode_buffer(gfp, input_buff, NULL, samples,mp3_buff, MP3BUFF_SIZE);
     //printf("mp3_bytes is %d.\n", mp3_bytes);
     if (mp3_bytes < 0)
    {
     printf ("lame_encode_buffer_interleaved returned %d\n",mp3_bytes);
      ret = -1;
     goto FREE_BUF;
    }

3、写入文件
     write_bytes = fwrite (mp3_buff, 1,mp3_bytes, fd_mp3);
      if(write_bytes < 0)
    {
     perror ("Write sound data file failed\n");
     ret = -1;
      goto FREE_BUF;
   }
      else
   fflush (fd_mp3);
    }

 //刷新缓冲区,拿到余下的数据。
 mp3_bytes = lame_encode_flush (gfp, mp3_buff, sizeof (mp3_buff));
 if (mp3_bytes > 0)
    {
     printf ("Writing %d mp3 bytes.\n", mp3_bytes);
     if (fwrite (mp3_buff, 1, mp3_bytes, fd_mp3) != (unsigned int)mp3_bytes)
    printf ("'Writing mp3 byteserror.\n");
      else
   fflush (fd_mp3);
    }
  else
   printf ("Writing mp3 bytes 0.\n");

FREE_BUF:
 if (mp3_buff != NULL)
    {
     free (mp3_buff);
      mp3_buff =NULL;
    }
  if (input_buff != NULL)
   {
      free (input_buff);
     input_buff = NULL;
    }

CLOSE_LAME:lame_close(gfp);
CLOSE_MP3:fclose (fd_mp3);
CLOSE_DSP:
 snd_pcm_drain (handle);
  snd_pcm_close(handle);

EXIT:return ret;
}

int
xrun (snd_pcm_t* handle)
{
  snd_pcm_status_t *status = NULL;
 int ret;
  int verbose = 0;

 snd_pcm_status_alloca (&status);
  if ((ret =snd_pcm_status (handle, status)) < 0)
   {
      printf ("status error: %d\n", ret);
      return -1;
   }

  if (snd_pcm_status_get_state (status) ==SND_PCM_STATE_XRUN)
    {
     struct timeval now, diff, tstamp;
     gettimeofday (&now, 0);
     snd_pcm_status_get_trigger_tstamp (status, &tstamp);
     timersub (&now, &tstamp, &diff);
     fprintf (stderr, "overrun!!! (at least %.3f ms long)\n",
          diff.tv_sec * 1000 +diff.tv_usec / 1000.0);
      if(verbose)
    {
      printf("Status:\n");
      //snd_pcm_status_dump(status, _log);
    }

     if ((ret = snd_pcm_prepare (handle)) < 0)
    {
     printf ("xrun: prepare error:%d\n", ret);
     return -1;
    }
     return 1;            //ok, data should be accepted again
    }

 if (snd_pcm_status_get_state (status) == SND_PCM_STATE_DRAINING)
   {
      if (verbose)
   {
      printf("Status(DRAINING):\n");
      //snd_pcm_status_dump(status, _log);
    }

     printf ("capture stream format change? attemptingrecover...\n");
      if ((ret =snd_pcm_prepare (handle)) < 0)
    {
     printf ("xrun(DRAINING): prepare error: %d\n",ret);
      return -1;
   }
      return 1;
   }
  if (verbose)
    {
     printf ("Status(R/W):\n");
     // snd_pcm_status_dump(status, _log);
    }
 printf ("read/write error, state = %s\n",
     snd_pcm_state_name (snd_pcm_status_get_state(status)));
  return -1;
}

// handle the case thatdevice busy
int
suspend (snd_pcm_t * handle)
{
  intret;

  while ((ret = snd_pcm_resume (handle)) ==-EAGAIN)    // Resume from suspend.
   sleep (1);            //resume can't be proceed immediately, wait until suspend flag isreleased

  if (ret < 0)
    {               //-ENOSYS hardware doesn't support this feature
     if ((ret = snd_pcm_prepare (handle)) < 0)
    {
     printf ("suspend: prepare error: %d", ret);
     return -1;
    }
   }
  return 1;
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值