]> git.sesse.net Git - vlc/blob - modules/visualization/galaktos/PCM.c
int16_t needs <inttypes.h>. Should fix FreeBSD unhapiness with addPCM().
[vlc] / modules / visualization / galaktos / PCM.c
1 /*****************************************************************************
2  * PCM.c:
3  *****************************************************************************
4  * Copyright (C) 2004 the VideoLAN team
5  * $Id$
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
25
26 //PCM.c - Sound data handler
27 //
28 //by Peter Sperl
29 //
30 //Takes sound data from wherever and hands it back out.
31 //Returns PCM Data or spectrum data, or the derivative of the PCM data
32
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <inttypes.h>
36
37 double **PCMd;    //data structure to store PCM data  PCM[channels][maxsamples]
38 int maxsamples;   //size of PCM buffer
39 int start;        //where to add data next
40
41 int *ip;          //working space for FFT routines
42 double *w;        //lookup table for FFT routines
43 int new;          //how many new samples
44
45
46 //initPCM(int samples)
47 //
48 //Initializes the PCM buffer to
49 // number of samples specified.
50
51 void initPCM(int samples)
52 {
53   int i; 
54
55   //Allocate memory for PCM data buffer
56   PCMd = (double **)malloc(2 * sizeof(double *));
57   PCMd[0] = (double *)malloc(samples * sizeof(double));
58   PCMd[1] = (double *)malloc(samples * sizeof(double));
59   
60   maxsamples=samples;
61   new=0;
62
63   //Initialize buffers to 0
64   for (i=0;i<samples;i++)
65     {
66       PCMd[0][i]=0;
67       PCMd[1][i]=0;
68     }
69
70   start=0;
71
72   //Allocate FFT workspace
73   w=  (double *)malloc(maxsamples*sizeof(double));
74   ip= (int *)malloc(maxsamples*sizeof(int));
75   ip[0]=0;
76 }
77
78 //The only current addPCM function, can support more
79 //
80 //Takes in a 2x512 array of PCM samples
81 //and stores them
82
83 void addPCM(int16_t PCMdata[2][512])
84 {
85   int i,j;
86   int samples=512;
87
88          for(i=0;i<samples;i++)
89            {
90              j=i+start;
91              PCMd[0][j%maxsamples]=(PCMdata[0][i]/16384.0);
92              PCMd[1][j%maxsamples]=(PCMdata[1][i]/16384.0);  
93            }
94        
95  
96          // printf("Added %d samples %d %d %f\n",samples,start,(start+samples)%maxsamples,PCM[0][start+10]); 
97
98  start+=samples;
99  start=start%maxsamples;
100
101  new+=samples;
102  if (new>maxsamples) new=maxsamples;
103 }
104
105
106 //puts sound data requested at provided pointer
107 //
108 //samples is number of PCM samples to return
109 //freq = 0 gives PCM data
110 //freq = 1 gives FFT data
111 //smoothing is the smoothing coefficient
112
113 //returned values are normalized from -1 to 1
114
115 void getPCM(double *PCMdata, int samples, int channel, int freq, double smoothing, int derive)
116 {
117    int i,index;
118    
119    index=start-1;
120
121    if (index<0) index=maxsamples+index;
122
123    PCMdata[0]=PCMd[channel][index];
124    
125    for(i=1;i<samples;i++)
126      {
127        index=start-1-i;
128        if (index<0) index=maxsamples+index;
129        
130        PCMdata[i]=(1-smoothing)*PCMd[channel][index]+smoothing*PCMdata[i-1];
131      }
132    
133    //return derivative of PCM data
134    if(derive)
135      {
136        for(i=0;i<samples-1;i++)
137          {         
138            PCMdata[i]=PCMdata[i]-PCMdata[i+1];
139          }
140        PCMdata[samples-1]=0;
141      }
142
143    //return frequency data instead of PCM (perform FFT)
144    if (freq) rdft(samples, 1, PCMdata, ip, w);
145
146
147      
148 }
149
150 //getPCMnew
151 //
152 //Like getPCM except it returns all new samples in the buffer
153 //the actual return value is the number of samples, up to maxsamples.
154 //the passed pointer, PCMData, must bee able to hold up to maxsamples
155
156 int getPCMnew(double *PCMdata, int channel, int freq, double smoothing, int derive, int reset)
157 {
158    int i,index;
159    
160    index=start-1;
161
162    if (index<0) index=maxsamples+index;
163
164    PCMdata[0]=PCMd[channel][index];
165    
166    for(i=1;i<new;i++)
167      {
168        index=start-1-i;
169        if (index<0) index=maxsamples+index;
170        
171        PCMdata[i]=(1-smoothing)*PCMd[channel][index]+smoothing*PCMdata[i-1];
172      }
173    
174    //return derivative of PCM data
175    if(derive)
176      {
177        for(i=0;i<new-1;i++)
178          {         
179            PCMdata[i]=PCMdata[i]-PCMdata[i+1];
180          }
181        PCMdata[new-1]=0;
182      }
183
184    //return frequency data instead of PCM (perform FFT)
185    //   if (freq) rdft(samples, 1, PCMdata, ip, w);
186    i=new;
187    if (reset)  new=0;
188
189    return i;
190 }
191
192 //Free stuff
193 void freePCM()
194 {
195   free(PCMd[0]);
196   free(PCMd[1]);
197   free(PCMd);
198   free(ip);
199   free(w);
200 }