1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-12-11 07:06:33 +01:00
Files
audacity/lib-src/sbsms/src/grain.cpp

147 lines
2.4 KiB
C++

#include <math.h>
#include <cstdlib>
#include <cstring>
#include "grain.h"
#include "sbsms.h"
#include "real.h"
#include "utils.h"
#include <map>
using namespace std;
namespace _sbsms_ {
map<int, map<real, real*> > wwMap;
map<int, map<real, audio*> > peakMap;
map<int, fftplan*> fftPlanMap;
map<int, fftplan*> ifftPlanMap;
grain* grain :: create(int N,real pad)
{
grain *g = new grain(N,pad);
return g;
}
void grain :: referenced(grain *g)
{
g->refCount++;
}
void grain :: forget(grain *g)
{
g->refCount--;
if(g->refCount <= 0) {
destroy(g);
}
}
void grain :: destroy(grain *g)
{
free_audio_buf(g->x);
delete g;
}
grain :: grain(int N, real pad)
{
this->N = N;
this->pad = pad;
calc_plans();
calc_windows();
refCount = 0;
x = (audio*) malloc(N*sizeof(audio));
}
void grain :: analyze()
{
for(int k=0;k<N;k++) {
for(int c=0;c<2;c++) {
x[k][c] *= ww[k];
}
}
FFT(fftPlan,x);
}
void grain :: synthesize()
{
IFFT(ifftPlan,x);
real f = pad/(real)N;
for(int k=0;k<N;k++) {
for(int c=0;c<2;c++) {
x[k][c] *= ww[k] * f;
}
}
}
void grain :: calc_plans()
{
fftPlan = fftPlanMap[N];
if(fftPlan == NULL) {
fftPlanMap[N] = (fftPlan = planFFT(N));
}
ifftPlan = ifftPlanMap[N];
if(ifftPlan == NULL) {
ifftPlanMap[N] = (ifftPlan = planIFFT(N));
}
}
void grain :: calc_windows()
{
int N2 = round2int(N/pad);
ww = wwMap[N][pad];
if(ww == NULL) {
wwMap[N][pad] = (ww = (real*)calloc(N,sizeof(real)));
for(int k=0;k<N2;k++) {
ww[k+(N-N2)/2] = 0.5f*(1.0f - cos((real)k/(real)N2*TWOPI));
}
}
peak = peakMap[N][pad];
if(peak == NULL) {
peakMap[N][pad] = (peak = (audio*) calloc(N,sizeof(audio)));
for(int k=0;k<N;k++) {
peak[k][0] = ww[k]/(real)(N2/2);
}
FFT(fftPlan,peak);
}
}
grain* grain :: upsample()
{
grain *g2 = grain::create(2*N,pad);
grain *g = this;
for(int c=0;c<2;c++) {
for(int k=0;k<=N/2;k++)
g2->x[k][c] = g->x[k][c];
for(int k=N/2+1;k<=N/2+N;k++)
g2->x[k][c] = 0;
for(int k=N/2+N+1;k<2*N;k++)
g2->x[k][c] = g->x[k-N][c];
}
return g2;
}
grain* grain :: downsample()
{
grain *g2 = grain::create(N/2,pad);
grain *g = this;
for(int c=0;c<2;c++) {
for(int k=0;k<=N/4-1;k++)
g2->x[k][c] = g->x[k][c];
g2->x[N/4][c] = 0.5f*(g->x[N/4][c] + g->x[N-N/4][c] );
for(int k=N/4+1;k<N/2;k++)
g2->x[k][c] = g->x[k+N/2][c];
}
return g2;
}
}