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

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /**********************************************************************
  2. MPEG-4 Audio VM
  3. Audio i/o module
  4. This software module was originally developed by
  5. Heiko Purnhagen (University of Hannover / ACTS-MoMuSys)
  6. and edited by
  7. in the course of development of the MPEG-2 NBC/MPEG-4 Audio standard
  8. ISO/IEC 13818-7, 14496-1,2 and 3. This software module is an
  9. implementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio tools
  10. as specified by the MPEG-2 NBC/MPEG-4 Audio standard. ISO/IEC gives
  11. users of the MPEG-2 NBC/MPEG-4 Audio standards free license to this
  12. software module or modifications thereof for use in hardware or
  13. software products claiming conformance to the MPEG-2 NBC/ MPEG-4 Audio
  14. standards. Those intending to use this software module in hardware or
  15. software products are advised that this use may infringe existing
  16. patents. The original developer of this software module and his/her
  17. company, the subsequent editors and their companies, and ISO/IEC have
  18. no liability for use of this software module or modifications thereof
  19. in an implementation. Copyright is not released for non MPEG-2
  20. NBC/MPEG-4 Audio conforming products. The original developer retains
  21. full right to use the code for his/her own purpose, assign or donate
  22. the code to a third party and to inhibit third party from using the
  23. code for non MPEG-2 NBC/MPEG-4 Audio conforming products. This
  24. copyright notice must be included in all copies or derivative works.
  25. Copyright (c) 1996, 1999.
  26. Source file: audio.c
  27. $Id: audio.c,v 1.3 2002/07/08 15:02:34 mvillari Exp $
  28. Required libraries:
  29. libtsp.a AFsp audio file library
  30. Required modules:
  31. common.o common module
  32. austream.o audio i/o streams (.au format)
  33. Authors:
  34. HP    Heiko Purnhagen, Uni Hannover <purnhage@tnt.uni-hannover.de>
  35. BT    Bodo Teichmann, FhG/IIS <tmn@iis.fhg.de>
  36. Changes:
  37. 21-jan-97   HP    born (using AFsp-V2R2)
  38. 27-jan-97   HP    set unavailable samples to 0 in AudioReadData()
  39. 03-feb-97   HP    fix bug AudioInit formatString=NULL
  40. 19-feb-97   HP    made internal data structures invisible
  41. 21-feb-97   BT    raw: big-endian
  42. 12-sep-97   HP    fixed numSample bug for mch files in AudioOpenRead()
  43. 30-dec-98   HP    uses austream for stdin/stdout, evaluates USE_AFSP
  44. 07-jan-99   HP    AFsp-v4r1 (AFsp-V3R2 still supported)
  45. 11-jan-99   HP    clipping & seeking for austream module
  46. 17-jan-99   HP    fixed quantisation to 16 bit
  47. 26-jan-99   HP    improved output file format evaluation
  48. 17-may-99   HP    improved output file format detection
  49. **********************************************************************/
  50. #include <stdio.h>
  51. #include <stdlib.h>
  52. #include <string.h>
  53. #include <ctype.h>
  54. #ifdef USE_AFSP
  55. #include <libtsp.h> /* AFsp audio file library */
  56. #include <libtsp/AFpar.h> /* AFsp audio file library - definitions */
  57. #endif
  58. #include "audio.h" /* audio i/o module */
  59. #include "common_m4a.h" /* common module */
  60. #include "austream.h" /* audio i/o streams (.au format) */
  61. #include "bitstream.h"
  62. /* ---------- declarations ---------- */
  63. #define SAMPLE_BUF_SIZE 16384 /* local sample buffer size */
  64. #define min(a,b) ((a) < (b) ? (a) : (b))
  65. #define max(a,b) ((a) > (b) ? (a) : (b))
  66. #ifdef USE_AFSP
  67. #ifdef FW_SUN
  68. /* only AFsp-V3R2 available: map AFsp-V3R2 to AFsp-v4r1 */
  69. #define AFsetNHpar AFsetNH
  70. #define FTW_AU (FW_SUN/256)
  71. #define FTW_WAVE (FW_WAVE/256)
  72. #define FTW_AIFF_C (FW_AIFF_C/256)
  73. #define FTW_NH_EB (FW_NH_EB/256)
  74. #endif
  75. #endif
  76. /* ---------- declarations (structures) ---------- */
  77. struct AudioFileStruct /* audio file handle */
  78. {
  79. #ifdef USE_AFSP
  80.   AFILE *file; /* AFILE handle */
  81. #else
  82.   int *file;
  83. #endif
  84.   AuStream *stream; /* AuStream handle */
  85. /*   NULL if AFsp used */
  86.   int numChannel; /* number of channels */
  87.   long currentSample; /* number of samples read/written */
  88. /* (samples per channel!) */
  89.   int write; /* 0=read  1=write */
  90.   long numClip; /* number of samples clipped */
  91. };
  92. /* ---------- variables ---------- */
  93. static int AUdebugLevel = 0; /* debug level */
  94. /* ---------- local functions ---------- */
  95. int isfmtstr (char *filename, char *fmtstr)
  96. /* isfmtstr returns true if filename has extension fmtstr */
  97. {
  98.   int i;
  99.   i = strlen(filename)-strlen(fmtstr);
  100.   if (i<0)
  101.     return 0;
  102.   filename += i;
  103.   while (*filename) {
  104.     if (tolower(*filename) != *fmtstr)
  105.       return 0;
  106.     filename++;
  107.     fmtstr++;
  108.   }
  109.   return 1;
  110. }
  111. /* ---------- functions ---------- */
  112. /* AudioInit() */
  113. /* Init audio i/o module. */
  114. /* formatString options: see AFsp documentation */
  115. void AudioInit (
  116.   char *formatString, /* in: file format for headerless files */
  117.   int debugLevel) /* in: debug level */
  118. /*     0=off  1=basic  2=full */
  119. {
  120.   AUdebugLevel = debugLevel;
  121.   if (AUdebugLevel >= 1) {
  122.     printf("AudioInit: formatString="%s"n",
  123.    (formatString!=NULL)?formatString:"(null)");
  124.     printf("AudioInit: debugLevel=%dn",AUdebugLevel);
  125. #ifdef USE_AFSP
  126.     printf("AudioInit: all AFsp file formats supportedn");
  127. #else
  128.     printf("AudioInit: only 16 bit .au format supportedn");
  129. #endif
  130.   }
  131. #ifdef USE_AFSP
  132.   if (formatString!=NULL)
  133.     AFsetNHpar(formatString);   /* headerless file support */
  134. #endif
  135. }
  136. /* AudioOpenRead() */
  137. /* Open audio file for reading. */
  138. AudioFile *AudioOpenRead (
  139.   char *fileName, /* in: file name */
  140. /*     "-": stdin (only 16 bit .au) */
  141.   int *numChannel, /* out: number of channels */
  142.   float *fSample, /* out: sampling frequency [Hz] */
  143.   long *numSample) /* out: number of samples in file */
  144. /*      (samples per channel!) */
  145. /*      or 0 if not available */
  146. /* returns: */
  147. /*  audio file (handle) */
  148. /*  or NULL if error */
  149. {
  150.   AudioFile *file;
  151. #ifdef USE_AFSP
  152.   AFILE *af;
  153. #else
  154.   int *af;
  155. #endif
  156.   AuStream *as;
  157.   long ns;
  158.   long nc;
  159.   int nci;
  160.   float fs;
  161.   if (AUdebugLevel >= 1)
  162.     printf("AudioOpenRead: fileName="%s"n",fileName);
  163.   if ((file=(AudioFile*)malloc(sizeof(AudioFile))) == NULL)
  164.     CommonExit(1,"AudioOpenRead: memory allocation error");
  165. #ifdef USE_AFSP
  166.   if (strcmp(fileName,"-")) {
  167.     af = AFopenRead(fileName,&ns,&nc,&fs,
  168.     AUdebugLevel?stdout:(FILE*)NULL);
  169.     as = NULL;
  170.   }
  171.   else {
  172. #endif
  173.     af = NULL;
  174.     as = AuOpenRead(fileName,&nci,&fs,&ns);
  175.     nc = nci;
  176.     ns = max(0,ns);
  177. #ifdef USE_AFSP
  178.   }
  179. #endif
  180.   if (as==NULL && af==NULL) {
  181.     CommonWarning("AudioOpenRead: error opening audio file %s",fileName);
  182.    FREE(file);
  183.     return (AudioFile*)NULL;
  184.   }
  185.   file->file = af;
  186.   file->stream = as;
  187.   file->numChannel = nc;
  188.   file->currentSample = 0;
  189.   file->write = 0;
  190.   file->numClip = 0;
  191.   *numChannel = nc;
  192.   *fSample = fs;
  193.   *numSample = ns/nc;
  194.   if (AUdebugLevel >= 1)
  195.     printf("AudioOpenRead: numChannel=%d  fSample=%.1f  numSample=%ldn",
  196.    *numChannel,*fSample,*numSample);
  197.   return file;
  198. }
  199. /* AudioOpenWrite() */
  200. /* Open audio file for writing. */
  201. /* Sample format: 16 bit twos complement, uniform quantisation */
  202. /* Supported file formats: (matching substring of format) */
  203. /*  au, snd:  Sun (AFsp) audio file */
  204. /*  wav:      RIFF WAVE file */
  205. /*  aif:      AIFF-C audio file */
  206. /*  raw:      headerless (raw) audio file (native byte order) */
  207. AudioFile *AudioOpenWrite (
  208.   char *fileName, /* in: file name */
  209. /*     "-": stdout (only 16 bit .au) */
  210.   char *format, /* in: file format (ignored if stdout) */
  211. /*     (au, snd, wav, aif, raw) */
  212.   int numChannel, /* in: number of channels */
  213.   float fSample) /* in: sampling frequency [Hz] */
  214. /* returns: */
  215. /*  audio file (handle) */
  216. /*  or NULL if error */
  217. {
  218.   AudioFile *file;
  219. #ifdef USE_AFSP
  220.   AFILE *af;
  221.   int fmt;
  222.   int fmti;
  223.   struct {
  224.     char *str;
  225.     int fmt;
  226.   } fmtstr[] = {
  227.     {"au",FTW_AU*256},
  228.     {"snd",FTW_AU*256},
  229.     {"wav",FTW_WAVE*256},
  230.     {"wave",FTW_WAVE*256},
  231.     {"aif",FTW_AIFF_C*256},
  232.     {"aiff",FTW_AIFF_C*256},
  233.     {"aifc",FTW_AIFF_C*256},
  234.     {"raw",FTW_NH_EB*256}, /* no header big-endian */
  235.     {NULL,-1}
  236.   };
  237. #else
  238.   int *af;
  239.   int fmti;
  240.   struct {
  241.     char *str;
  242.     int fmt;
  243.   } fmtstr[] = {
  244.     {"au",1},
  245.     {"snd",1},
  246.     {NULL,-1}
  247.   };
  248. #endif
  249.   AuStream *as;
  250.   if (AUdebugLevel >= 1) {
  251.     printf("AudioOpenWrite: fileName="%s"  format="%s"n",fileName,format);
  252.     printf("AudioOpenWrite: numChannel=%d  fSample=%.1fn",
  253.    numChannel,fSample);
  254.   }
  255.   if (strcmp(fileName,"-")) {
  256. #ifdef USE_AFSP
  257.     fmti = 0;
  258.     while (fmtstr[fmti].str && !isfmtstr(format,fmtstr[fmti].str))
  259.       fmti++;
  260.     if (fmtstr[fmti].str)
  261.       fmt = FD_INT16 + fmtstr[fmti].fmt;
  262.     else {
  263. #else
  264.     fmti = 0;
  265.     while (fmtstr[fmti].str && !isfmtstr(format,fmtstr[fmti].str))
  266.       fmti++;
  267.     if (!fmtstr[fmti].str) {
  268. #endif
  269.       CommonWarning("AudioOpenWrite: unkown audio file format "%s"",
  270.     format);
  271.       return (AudioFile*)NULL;
  272.     }
  273.   }
  274.   if ((file=(AudioFile*)malloc(sizeof(AudioFile))) == NULL)
  275.     CommonExit(1,"AudioOpenWrite: memory allocation error");
  276. #ifdef USE_AFSP
  277.   if (strcmp(fileName,"-")) {
  278.     af = AFopenWrite(fileName,fmt,numChannel,fSample,
  279.      AUdebugLevel?stdout:(FILE*)NULL);
  280.     as = NULL;
  281.   }
  282.   else {
  283. #endif
  284.     af = NULL;
  285.     as = AuOpenWrite(fileName,numChannel,fSample);
  286. #ifdef USE_AFSP
  287.   }
  288. #endif
  289.   if (as==NULL && af==NULL) {
  290.     CommonWarning("AudioOpenWrite: error opening audio file %s",fileName);
  291.    FREE(file);
  292.     return (AudioFile*)NULL;
  293.   }
  294.   file->file = af;
  295.   file->stream = as;
  296.   file->numChannel = numChannel;
  297.   file->currentSample = 0;
  298.   file->write = 1;
  299.   file->numClip = 0;
  300.   return file;
  301. }
  302. /* AudioReadData() */
  303. /* Read data from audio file. */
  304. /* Requested samples that could not be read from the file are set to 0. */
  305. long AudioReadData (
  306.   AudioFile *file, /* in: audio file (handle) */
  307.   float **data, /* out: data[channel][sample] */
  308. /*      (range [-32768 .. 32767]) */
  309.   long numSample) /* in: number of samples to be read */
  310. /*     (samples per channel!) */
  311. /* returns: */
  312. /*  number of samples read */
  313. {
  314.   long tot,cur,num,tmp;
  315.   long i;
  316.   long numRead;
  317. #ifdef USE_AFSP
  318.   float buf[SAMPLE_BUF_SIZE];
  319. #endif
  320.   short bufs[SAMPLE_BUF_SIZE];
  321.   if (AUdebugLevel >= 2)
  322.     printf("AudioReadData: numSample=%ld (currentSample=%ld)n",
  323.    numSample,file->currentSample);
  324.   if (file->write != 0)
  325.     CommonExit(1,"AudioReadData: audio file not in read mode");
  326.   /* set initial unavailable samples to 0 */
  327.   tot = file->numChannel*numSample;
  328.   cur = 0;
  329.   if (file->stream && file->currentSample < 0) {
  330.     cur = min(-file->numChannel*file->currentSample,tot);
  331.     for (i=0; i<cur; i++)
  332.       data[i%file->numChannel][i/file->numChannel] = 0;
  333.   }
  334.   /* read samples from file */
  335.   while (cur < tot) {
  336.     num = min(tot-cur,SAMPLE_BUF_SIZE);
  337. #ifdef USE_AFSP
  338.     if (file->file) {
  339.       tmp = AFreadData(file->file,
  340.        file->numChannel*file->currentSample+cur,buf,num);
  341.       for (i=0; i<tmp; i++)
  342. data[(cur+i)%file->numChannel][(cur+i)/file->numChannel] = buf[i];
  343.     }
  344. #endif
  345.     if (file->stream) {
  346.       tmp = AuReadData(file->stream,bufs,num);
  347.       for (i=0; i<tmp; i++)
  348. data[(cur+i)%file->numChannel][(cur+i)/file->numChannel] = bufs[i];
  349.     }
  350.     cur += tmp;
  351.     if (tmp < num)
  352.       break;
  353.   }
  354.   numRead = cur/file->numChannel;
  355.   file->currentSample += numRead;
  356.   /* set remaining unavailable samples to 0 */
  357.   for (i=cur; i<tot; i++)
  358.     data[i%file->numChannel][i/file->numChannel] = 0;
  359.   return numRead;
  360. }
  361. /* AudioWriteData() */
  362. /* Write data to audio file. */
  363. void AudioWriteData (
  364.   AudioFile *file, /* in: audio file (handle) */
  365.   float **data, /* in: data[channel][sample] */
  366. /*     (range [-32768 .. 32767]) */
  367.   long numSample) /* in: number of samples to be written */
  368. /*     (samples per channel!) */
  369. {
  370.   long tot,cur,num;
  371.   long i;
  372.   long numClip,tmp;
  373. #ifdef USE_AFSP
  374.   float buf[SAMPLE_BUF_SIZE];
  375. #endif
  376.   short bufs[SAMPLE_BUF_SIZE];
  377.   if (AUdebugLevel >= 2)
  378.     printf("AudioWriteData: numSample=%ld (currentSample=%ld)n",
  379.    numSample,file->currentSample);
  380.   if (file->write != 1)
  381.     CommonExit(1,"AudioWriteData: audio file not in write mode");
  382.   tot = file->numChannel*numSample;
  383.   cur = max(0,-file->numChannel*file->currentSample);
  384.   while (cur < tot) {
  385.     num = min(tot-cur,SAMPLE_BUF_SIZE);
  386. #ifdef USE_AFSP
  387.     if (file->file) {
  388.       for (i=0; i<num; i++)
  389. buf[i] = data[(cur+i)%file->numChannel][(cur+i)/file->numChannel];
  390.       AFwriteData(file->file,buf,num);
  391.     }
  392. #endif
  393.     if (file->stream) {
  394.       numClip = 0;
  395.       for (i=0; i<num; i++) {
  396. tmp = ((long)(data[(cur+i)%file->numChannel]
  397.       [(cur+i)/file->numChannel]+32768.5))-32768;
  398. if (tmp>32767) {
  399.   tmp = 32767;
  400.   numClip++;
  401. }
  402. if (tmp<-32768) {
  403.     tmp = -32768;
  404.     numClip++;
  405. }
  406. bufs[i] = (short)tmp;
  407.       }
  408.       if (numClip && !file->numClip)
  409. CommonWarning("AudioWriteData: output samples clipped");
  410.       file->numClip += numClip;
  411.       AuWriteData(file->stream,bufs,num);
  412.     }
  413.     cur += num;
  414.   }
  415.   file->currentSample += tot/file->numChannel;
  416. }
  417. /* AudioSeek() */
  418. /* Set position in audio file to curSample. */
  419. /* (Beginning of file: curSample=0) */
  420. /* NOTE: It is not possible to seek backwards in a output file if */
  421. /*       any samples were already written to the file. */
  422. void AudioSeek (
  423.   AudioFile *file, /* in: audio file (handle) */
  424.   long curSample) /* in: new position [samples] */
  425. /*     (samples per channel!) */
  426. {
  427.   long tot,cur,num,tmp;
  428. #ifdef USE_AFSP
  429.   float buf[SAMPLE_BUF_SIZE];
  430. #endif
  431.   short bufs[SAMPLE_BUF_SIZE];
  432.   if (AUdebugLevel >= 1)
  433.     printf("AudioSeek: curSample=%ld (currentSample=%ld)n",
  434.    curSample,file->currentSample);
  435.   if (file->write==0) {
  436.     if (file->stream) {
  437.       if (file->currentSample <= 0) {
  438. /* nothing read from stream yet */
  439. if (curSample <= 0)
  440.   file->currentSample = curSample;
  441. else
  442.   file->currentSample = 0;
  443.       }
  444.       if (curSample < file->currentSample)
  445. CommonWarning("AudioSeek: can not seek backward in input stream");
  446.       else {
  447. /* read samples to skip */
  448. tot = file->numChannel*(curSample-file->currentSample);
  449. cur = 0;
  450. while (cur < tot) {
  451.   num = min(tot-cur,SAMPLE_BUF_SIZE);
  452.   tmp = AuReadData(file->stream,bufs,num);
  453.   cur += tmp;
  454.   if (tmp < num)
  455.     break;
  456. }
  457. file->currentSample = curSample;
  458.       }
  459.     }
  460.     else
  461.       file->currentSample = curSample;
  462.   }
  463.   else {
  464.     if (file->currentSample <= 0) {
  465.       /* nothing written to file yet */
  466.       if (curSample <= 0)
  467. file->currentSample = curSample;
  468.       else
  469. file->currentSample = 0;
  470.     }
  471.     if (curSample < file->currentSample)
  472.       CommonExit(1,"AudioSeek: error seeking backwards in output file");
  473.     if (curSample > file->currentSample) {
  474.       /* seek forward, fill skipped region with silence */
  475. #ifdef USE_AFSP
  476.       memset(buf,0,SAMPLE_BUF_SIZE*sizeof(float));
  477. #endif
  478.       memset(bufs,0,SAMPLE_BUF_SIZE*sizeof(short));
  479.       tot = file->numChannel*(curSample-file->currentSample);
  480.       cur = 0;
  481.       while (cur < tot) {
  482. num = min(tot-cur,SAMPLE_BUF_SIZE);
  483. #ifdef USE_AFSP
  484. if (file->file)
  485.   AFwriteData(file->file,buf,num);
  486. #endif
  487. if (file->stream)
  488.   AuWriteData(file->stream,bufs,num);
  489. cur += num;
  490.       }
  491.       file->currentSample = curSample;
  492.     }
  493.   }
  494. }
  495. /* AudioClose() */
  496. /* Close audio file.*/
  497. void AudioClose (
  498.   AudioFile *file) /* in: audio file (handle) */
  499. {
  500.   if (AUdebugLevel >= 1)
  501.     printf("AudioClose: (currentSample=%ld)n",file->currentSample);
  502.   if (file->numClip)
  503.     CommonWarning("AudioClose: %ld samples clipped",file->numClip);
  504. #ifdef USE_AFSP
  505.   if (file->file)
  506.     AFclose(file->file);
  507. #endif
  508.   if (file->stream)
  509.     AuClose(file->stream);
  510.  FREE(file);
  511. }
  512. /* end of audio.c */