PCM.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:5k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * PCM.c:
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 VideoLAN
  5.  * $Id: PCM.c 8205 2004-07-17 13:55:48Z asmax $
  6.  *
  7.  * Authors: Cyril Deguet <asmax@videolan.org>
  8.  *          code from projectM http://xmms-projectm.sourceforge.net
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. //PCM.c - Sound data handler
  25. //
  26. //by Peter Sperl
  27. //
  28. //Takes sound data from wherever and hands it back out.
  29. //Returns PCM Data or spectrum data, or the derivative of the PCM data
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. double **PCMd;    //data structure to store PCM data  PCM[channels][maxsamples]
  33. int maxsamples;   //size of PCM buffer
  34. int start;        //where to add data next
  35. int *ip;          //working space for FFT routines
  36. double *w;        //lookup table for FFT routines
  37. int new;          //how many new samples
  38. //initPCM(int samples)
  39. //
  40. //Initializes the PCM buffer to
  41. // number of samples specified.
  42. void initPCM(int samples)
  43. {
  44.   int i; 
  45.   //Allocate memory for PCM data buffer
  46.   PCMd = (double **)malloc(2 * sizeof(double *));
  47.   PCMd[0] = (double *)malloc(samples * sizeof(double));
  48.   PCMd[1] = (double *)malloc(samples * sizeof(double));
  49.   
  50.   maxsamples=samples;
  51.   new=0;
  52.   //Initialize buffers to 0
  53.   for (i=0;i<samples;i++)
  54.     {
  55.       PCMd[0][i]=0;
  56.       PCMd[1][i]=0;
  57.     }
  58.   start=0;
  59.   //Allocate FFT workspace
  60.   w=  (double *)malloc(maxsamples*sizeof(double));
  61.   ip= (int *)malloc(maxsamples*sizeof(int));
  62.   ip[0]=0;
  63. }
  64. //The only current addPCM function, can support more
  65. //
  66. //Takes in a 2x512 array of PCM samples
  67. //and stores them
  68. void addPCM(int16_t PCMdata[2][512])
  69. {
  70.   int i,j;
  71.   int samples=512;
  72.  for(i=0;i<samples;i++)
  73.    {
  74.      j=i+start;
  75.      PCMd[0][j%maxsamples]=(PCMdata[0][i]/16384.0);
  76.      PCMd[1][j%maxsamples]=(PCMdata[1][i]/16384.0);  
  77.    }
  78.        
  79.  
  80.  // printf("Added %d samples %d %d %fn",samples,start,(start+samples)%maxsamples,PCM[0][start+10]); 
  81.  start+=samples;
  82.  start=start%maxsamples;
  83.  new+=samples;
  84.  if (new>maxsamples) new=maxsamples;
  85. }
  86. //puts sound data requested at provided pointer
  87. //
  88. //samples is number of PCM samples to return
  89. //freq = 0 gives PCM data
  90. //freq = 1 gives FFT data
  91. //smoothing is the smoothing coefficient
  92. //returned values are normalized from -1 to 1
  93. void getPCM(double *PCMdata, int samples, int channel, int freq, double smoothing, int derive)
  94. {
  95.    int i,index;
  96.    
  97.    index=start-1;
  98.    if (index<0) index=maxsamples+index;
  99.    PCMdata[0]=PCMd[channel][index];
  100.    
  101.    for(i=1;i<samples;i++)
  102.      {
  103.        index=start-1-i;
  104.        if (index<0) index=maxsamples+index;
  105.        
  106.        PCMdata[i]=(1-smoothing)*PCMd[channel][index]+smoothing*PCMdata[i-1];
  107.      }
  108.    
  109.    //return derivative of PCM data
  110.    if(derive)
  111.      {
  112.        for(i=0;i<samples-1;i++)
  113.  {    
  114.    PCMdata[i]=PCMdata[i]-PCMdata[i+1];
  115.  }
  116.        PCMdata[samples-1]=0;
  117.      }
  118.    //return frequency data instead of PCM (perform FFT)
  119.    if (freq) rdft(samples, 1, PCMdata, ip, w);
  120.      
  121. }
  122. //getPCMnew
  123. //
  124. //Like getPCM except it returns all new samples in the buffer
  125. //the actual return value is the number of samples, up to maxsamples.
  126. //the passed pointer, PCMData, must bee able to hold up to maxsamples
  127. int getPCMnew(double *PCMdata, int channel, int freq, double smoothing, int derive, int reset)
  128. {
  129.    int i,index;
  130.    
  131.    index=start-1;
  132.    if (index<0) index=maxsamples+index;
  133.    PCMdata[0]=PCMd[channel][index];
  134.    
  135.    for(i=1;i<new;i++)
  136.      {
  137.        index=start-1-i;
  138.        if (index<0) index=maxsamples+index;
  139.        
  140.        PCMdata[i]=(1-smoothing)*PCMd[channel][index]+smoothing*PCMdata[i-1];
  141.      }
  142.    
  143.    //return derivative of PCM data
  144.    if(derive)
  145.      {
  146.        for(i=0;i<new-1;i++)
  147.  {    
  148.    PCMdata[i]=PCMdata[i]-PCMdata[i+1];
  149.  }
  150.        PCMdata[new-1]=0;
  151.      }
  152.    //return frequency data instead of PCM (perform FFT)
  153.    //   if (freq) rdft(samples, 1, PCMdata, ip, w);
  154.    i=new;
  155.    if (reset)  new=0;
  156.    return i;
  157. }
  158. //Free stuff
  159. void freePCM()
  160. {
  161.   free(PCMd[0]);
  162.   free(PCMd[1]);
  163.   free(PCMd);
  164.   free(ip);
  165.   free(w);
  166. }