1 #include <math.h>
2 #include <cstdlib>
3 #include <cstring>
4 #include "grain.h"
5 #include "sbsms.h"
6 #include "real.h"
7 #include "utils.h"
8 
9 #include <map>
10 using namespace std;
11 
12 namespace _sbsms_ {
13 
GrainAllocator(int N,int N2,int type)14 GrainAllocator :: GrainAllocator(int N, int N2, int type)
15 {
16   this->N = N;
17   this->N2 = N2;
18   this->type = type;
19 
20   switch(N) {
21   case 128:
22     fftPlan = &fft128;
23     ifftPlan = &ifft128;
24     break;
25   case 256:
26     fftPlan = &fft256;
27     ifftPlan = &ifft256;
28     break;
29   case 384:
30     fftPlan = &fft384;
31     //ifftPlan = &ifft384;
32     break;
33   case 512:
34     fftPlan = &fft512;
35     //ifftPlan = &ifft512;
36     break;
37   default:
38     abort();
39     break;
40   }
41 
42   int k1 = (N-N2)/2;
43 
44   w = (float*)calloc(N,sizeof(float));
45   for(int k=0;k<N2;k++) {
46     if(type == hann) {
47       w[k+k1] = 0.5f*(1.0f - cos((float)k/(float)N2*TWOPI));
48     } else if(type == hannpoisson) {
49       w[k+k1] = 0.5f*(1.0f - cos((float)k/(float)N2*TWOPI)) * exp(-2.0f*fabs((float)(k-N2/2))/(float)N2);
50     }
51   }
52 
53   W = (audio*) calloc(N,sizeof(audio));
54   for(int k=0;k<N;k++) {
55     W[k][0] = w[k] * 2.638502561913447f/(float)N2;
56   }
57 
58   fftPlan(W);
59 }
60 
~GrainAllocator()61 GrainAllocator :: ~GrainAllocator()
62 {
63   free(w);
64   free(W);
65 }
66 
create()67 grain* GrainAllocator :: create()
68 {
69   grain *g = new grain(N,N2);
70   g->refCount = 0;
71   g->fftPlan = fftPlan;
72   g->ifftPlan = ifftPlan;
73   g->w = w;
74   return g;
75 }
76 
reference(grain * g)77 void GrainAllocator :: reference(grain *g)
78 {
79   g->refCount++;
80 }
81 
forget(grain * g)82 void GrainAllocator :: forget(grain *g)
83 {
84   g->refCount--;
85   if(g->refCount <= 0) {
86     delete g;
87   }
88 }
89 
grain(int N,int N2)90 grain :: grain(int N, int N2)
91 {
92   this->N = N;
93   this->synthScale = 1.0f / (float)N2;
94   x = (audio*) calloc(N,sizeof(audio));
95 }
96 
~grain()97 grain :: ~grain()
98 {
99   free(x);
100 }
101 
analyze()102 void grain :: analyze()
103 {
104   float *x = (float*)this->x;
105   float *end = x + (N<<1);
106   float *w = this->w;
107   while(x != end) {
108     *(x++) *= *w;
109     *(x++) *= *(w++);
110   }
111 
112   fftPlan(this->x);
113 }
114 
synthesize()115 void grain :: synthesize()
116 {
117   ifftPlan(x);
118   for(int k=0;k<N;k++) {
119     for(int c=0;c<2;c++) {
120       x[k][c] *= w[k] * synthScale;
121     }
122   }
123 }
124 
downsample(grain * g2)125 void grain :: downsample(grain *g2)
126 {
127   grain *g = this;
128 
129   int N2 = N/2;
130   int N4 = N/4;
131   for(int c=0;c<2;c++) {
132     for(int k=0;k<N4;k++) {
133       g2->x[k][c] = 0.5f * g->x[k][c];
134     }
135     g2->x[N4][c] = 0.25f * (g->x[N4][c] + g->x[N-N4][c]);
136     for(int k=N4+1;k<N2;k++) {
137       g2->x[k][c] = 0.5f * g->x[k+N2][c];
138     }
139   }
140 }
141 
142 }
143