PCM.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:5k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * PCM.c:
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 the VideoLAN team
  5.  * $Id: 82162f3f332ed30671d10d3a2b2a2147b49fe2ef $
  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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, 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. #include <inttypes.h>
  33. #include "fftsg.h"
  34. double **PCMd;    //data structure to store PCM data  PCM[channels][maxsamples]
  35. int maxsamples;   //size of PCM buffer
  36. int start;        //where to add data next
  37. int *ip;          //working space for FFT routines
  38. double *w;        //lookup table for FFT routines
  39. int new;          //how many new samples
  40. //initPCM(int samples)
  41. //
  42. //Initializes the PCM buffer to
  43. // number of samples specified.
  44. void initPCM(int samples)
  45. {
  46.   int i; 
  47.   //Allocate memory for PCM data buffer
  48.   PCMd = (double **)malloc(2 * sizeof(double *));
  49.   PCMd[0] = (double *)malloc(samples * sizeof(double));
  50.   PCMd[1] = (double *)malloc(samples * sizeof(double));
  51.   
  52.   maxsamples=samples;
  53.   new=0;
  54.   //Initialize buffers to 0
  55.   for (i=0;i<samples;i++)
  56.     {
  57.       PCMd[0][i]=0;
  58.       PCMd[1][i]=0;
  59.     }
  60.   start=0;
  61.   //Allocate FFT workspace
  62.   w=  (double *)malloc(maxsamples*sizeof(double));
  63.   ip= (int *)malloc(maxsamples*sizeof(int));
  64.   ip[0]=0;
  65. }
  66. //The only current addPCM function, can support more
  67. //
  68. //Takes in a 2x512 array of PCM samples
  69. //and stores them
  70. void addPCM(int16_t PCMdata[2][512])
  71. {
  72.   int i,j;
  73.   int samples=512;
  74.  for(i=0;i<samples;i++)
  75.    {
  76.      j=i+start;
  77.      PCMd[0][j%maxsamples]=(PCMdata[0][i]/16384.0);
  78.      PCMd[1][j%maxsamples]=(PCMdata[1][i]/16384.0);  
  79.    }
  80.        
  81.  
  82.  // printf("Added %d samples %d %d %fn",samples,start,(start+samples)%maxsamples,PCM[0][start+10]); 
  83.  start+=samples;
  84.  start=start%maxsamples;
  85.  new+=samples;
  86.  if (new>maxsamples) new=maxsamples;
  87. }
  88. //puts sound data requested at provided pointer
  89. //
  90. //samples is number of PCM samples to return
  91. //freq = 0 gives PCM data
  92. //freq = 1 gives FFT data
  93. //smoothing is the smoothing coefficient
  94. //returned values are normalized from -1 to 1
  95. void getPCM(double *PCMdata, int samples, int channel, int freq, double smoothing, int derive)
  96. {
  97.    int i,index;
  98.    
  99.    index=start-1;
  100.    if (index<0) index=maxsamples+index;
  101.    PCMdata[0]=PCMd[channel][index];
  102.    
  103.    for(i=1;i<samples;i++)
  104.      {
  105.        index=start-1-i;
  106.        if (index<0) index=maxsamples+index;
  107.        
  108.        PCMdata[i]=(1-smoothing)*PCMd[channel][index]+smoothing*PCMdata[i-1];
  109.      }
  110.    
  111.    //return derivative of PCM data
  112.    if(derive)
  113.      {
  114.        for(i=0;i<samples-1;i++)
  115.  {    
  116.    PCMdata[i]=PCMdata[i]-PCMdata[i+1];
  117.  }
  118.        PCMdata[samples-1]=0;
  119.      }
  120.    //return frequency data instead of PCM (perform FFT)
  121.    if (freq) rdft(samples, 1, PCMdata, ip, w);
  122.      
  123. }
  124. //getPCMnew
  125. //
  126. //Like getPCM except it returns all new samples in the buffer
  127. //the actual return value is the number of samples, up to maxsamples.
  128. //the passed pointer, PCMData, must bee able to hold up to maxsamples
  129. int getPCMnew(double *PCMdata, int channel, int freq, double smoothing, int derive, int reset)
  130. {
  131.    int i,index;
  132.    
  133.    index=start-1;
  134.    if (index<0) index=maxsamples+index;
  135.    PCMdata[0]=PCMd[channel][index];
  136.    
  137.    for(i=1;i<new;i++)
  138.      {
  139.        index=start-1-i;
  140.        if (index<0) index=maxsamples+index;
  141.        
  142.        PCMdata[i]=(1-smoothing)*PCMd[channel][index]+smoothing*PCMdata[i-1];
  143.      }
  144.    
  145.    //return derivative of PCM data
  146.    if(derive)
  147.      {
  148.        for(i=0;i<new-1;i++)
  149.  {    
  150.    PCMdata[i]=PCMdata[i]-PCMdata[i+1];
  151.  }
  152.        PCMdata[new-1]=0;
  153.      }
  154.    //return frequency data instead of PCM (perform FFT)
  155.    //   if (freq) rdft(samples, 1, PCMdata, ip, w);
  156.    i=new;
  157.    if (reset)  new=0;
  158.    return i;
  159. }
  160. //Free stuff
  161. void freePCM()
  162. {
  163.   free(PCMd[0]);
  164.   free(PCMd[1]);
  165.   free(PCMd);
  166.   free(ip);
  167.   free(w);
  168. }