ref: f2e11903bc2d80a73e21916e2929a18b6042c5f6
dir: /modules/padsynth.c/
/* Example implementation of the PADsynth basic algorithm By: Nasca O. Paul, Tg. Mures, Romania Ported to pure C by Paul Batchelor This implementation and the algorithm are released under Public Domain Feel free to use it into your projects or your products ;-) This implementation is tested under GCC/Linux, but it's very easy to port to other compiler/OS. */ #include <stdlib.h> #include <math.h> #include "soundpipe.h" #ifndef M_PI #define M_PI 3.14159265358979323846 #endif int sp_gen_padsynth(sp_data *sp, sp_ftbl *ps, sp_ftbl *amps, SPFLOAT f, SPFLOAT bw) { int i, nh; int N = (int) ps->size; int number_harmonics = (int) amps->size; SPFLOAT *A = amps->tbl; SPFLOAT *smp = ps->tbl; SPFLOAT *freq_amp = malloc((N / 2) * sizeof(SPFLOAT)); SPFLOAT *freq_phase = malloc((N / 2) * sizeof(SPFLOAT)); N = (int) ps->size; number_harmonics = (int) amps->size; A = amps->tbl; smp = ps->tbl; freq_amp = malloc((N / 2) * sizeof(SPFLOAT)); freq_phase = malloc((N / 2) * sizeof(SPFLOAT)); for (i = 0; i < N/2; i++) freq_amp[i]=0.0; for (nh=1; nh < number_harmonics; nh++) { SPFLOAT bw_Hz; SPFLOAT bwi; SPFLOAT fi; bw_Hz = (pow(2.0, bw/1200.0) - 1.0) * f * nh; bwi = bw_Hz/(2.0*ps->size); fi = f*nh/ps->size; for (i = 0; i < N/2 ; i++) { SPFLOAT hprofile; hprofile = sp_padsynth_profile((i / (SPFLOAT) N) - fi, bwi); freq_amp[i] += hprofile*A[nh]; } } for (i = 0; i < N/2; i++) { freq_phase[i] = (sp_rand(sp) / (SP_RANDMAX + 1.0)) * 2.0 * M_PI; }; sp_padsynth_ifft(N,freq_amp,freq_phase,smp); sp_padsynth_normalize(N,smp); free(freq_amp); free(freq_phase); return SP_OK; } /* This is the profile of one harmonic In this case is a Gaussian distribution (e^(-x^2)) The amplitude is divided by the bandwidth to ensure that the harmonic keeps the same amplitude regardless of the bandwidth */ SPFLOAT sp_padsynth_profile(SPFLOAT fi, SPFLOAT bwi) { SPFLOAT x =fi/bwi; x *= x; /* * this avoids computing the e^(-x^2) where * it's results are very close to zero */ if (x>14.71280603) return 0.0; return exp(-x)/bwi; } int sp_padsynth_ifft(int N, SPFLOAT *freq_amp, SPFLOAT *freq_phase, SPFLOAT *smp) { int i; FFTwrapper *fft; FFTFREQS fftfreqs; FFTwrapper_create(&fft, N); newFFTFREQS(&fftfreqs,N/2); for (i = 0; i < N/2; i++) { fftfreqs.c[i] = freq_amp[i]*cos(freq_phase[i]); fftfreqs.s[i] = freq_amp[i]*sin(freq_phase[i]); }; freqs2smps(fft, &fftfreqs,smp); deleteFFTFREQS(&fftfreqs); FFTwrapper_destroy(&fft); return SP_OK; } /* Simple normalization function. It normalizes the sound to 1/sqrt(2) */ int sp_padsynth_normalize(int N, SPFLOAT *smp) { int i; SPFLOAT max=0.0; for (i = 0; i < N;i++) { if (fabs(smp[i]) > max) max = fabs(smp[i]); } if (max < 1e-5) max = 1e-5; for (i = 0; i < N; i++) smp[i] /= max*1.4142; return SP_OK; }