ref: af78782438bd3dfff481a105e3f86988105b992a
dir: /modules/ftbl.c/
#include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #ifndef NO_LIBSNDFILE #include <sndfile.h> #endif #include "soundpipe.h" #include "kiss_fftr.h" #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #define tpd360 0.0174532925199433 int sp_ftbl_create(sp_data *sp, sp_ftbl **ft, size_t size) { USED(sp); sp_ftbl *ftp; *ft = malloc(sizeof(sp_ftbl)); ftp = *ft; ftp->tbl = calloc(1, sizeof(SPFLOAT) * (size + 1)); ftp->size = size; ftp->del = 1; return SP_OK; } /* like create, but use externally managed memory */ int sp_ftbl_bind(sp_data *sp, sp_ftbl **ft, SPFLOAT *tbl, size_t size) { USED(sp); sp_ftbl *ftp; *ft = malloc(sizeof(sp_ftbl)); ftp = *ft; ftp->tbl = tbl; ftp->size = size; ftp->del = 0; return SP_OK; } int sp_ftbl_destroy(sp_ftbl **ft) { sp_ftbl *ftp = *ft; if (ftp->del) free(ftp->tbl); free(*ft); return SP_OK; } static char * tokenize_(char **next, int *size) { char *token; char *str; char *peak; if (*size <= 0) return NULL; token = *next; str = *next; peak = str + 1; while ((*size)--) { if (*str == ' ') { *str = 0; if (*peak != ' ') break; } str = str + 1; peak = str + 1; } *next = peak; return token; } int sp_gen_vals(sp_data *sp, sp_ftbl *ft, const char *string) { USED(sp); int size; char *str; char *out; char *ptr; int j; size = strlen(string); str = malloc(sizeof(char) * size + 1); strcpy(str, string); ptr = str; j = 0; while (size > 0) { out = tokenize_(&str, &size); if (ft->size < j + 1) { ft->tbl = realloc(ft->tbl, sizeof(SPFLOAT) * (ft->size + 2)); /* zero out new tables */ ft->tbl[ft->size] = 0; ft->tbl[ft->size + 1] = 0; ft->size++; } ft->tbl[j] = atof(out); j++; } free(ptr); return SP_OK; } int sp_gen_sine(sp_data *sp, sp_ftbl *ft) { USED(sp); unsigned long i; SPFLOAT step = 2 * M_PI / ft->size; for (i = 0; i < ft->size; i++) { ft->tbl[i] = sin(i * step); } return SP_OK; } void sp_gen_triangle(sp_data *sp, sp_ftbl *ft) { USED(sp); unsigned int i; unsigned int counter; SPFLOAT incr; int step; incr = 1.0f / (SPFLOAT)ft->size; incr *= 2; step = 1; counter = 0; for (i = 0; i < ft->size; i++) { if (i == ft->size / 2) { step = -1; } ft->tbl[i] = (2.f*(counter * incr) - 1.f); counter += step; } } void sp_gen_composite(sp_data *sp, sp_ftbl *ft, const char *argstring) { SPFLOAT phs, inc, amp, dc, tpdlen; int i, n; sp_ftbl *args; sp_ftbl_create(sp, &args, 1); sp_gen_vals(sp, args, argstring); tpdlen = 2 * M_PI / (SPFLOAT) ft->size; for (n = 0; n < args->size; n += 4) { inc = args->tbl[n] * tpdlen; amp = args->tbl[n + 1]; phs = args->tbl[n + 2] * tpd360; dc = args->tbl[n + 3]; for (i = 0; i <ft->size ; i++) { ft->tbl[i] += (SPFLOAT) (sin(phs) * amp + dc); if ((phs += inc) >= 2 * M_PI) phs -= 2 * M_PI; } } sp_ftbl_destroy(&args); } void sp_gen_sinesum(sp_data *sp, sp_ftbl *ft, const char *argstring) { sp_ftbl *args; int32_t phs; SPFLOAT amp; int32_t flen; SPFLOAT tpdlen; int32_t i, n; sp_ftbl_create(sp, &args, 1); sp_gen_vals(sp, args, argstring); flen = (int32_t)ft->size; tpdlen = 2.0 * M_PI / (SPFLOAT) flen; for (i = (int32_t)args->size; i > 0; i--) { amp = args->tbl[i - 1]; if (amp != 0) { for (phs = 0, n = 0; n < ft->size; n++) { ft->tbl[n] += sin(phs * tpdlen) * amp; phs += i; phs %= flen; } } } sp_ftbl_destroy(&args); } void sp_ftbl_fftcut(sp_ftbl *ft, int cut) { kiss_fftr_cfg fft, ifft; kiss_fft_cpx *tmp; int i; SPFLOAT scale; fft = kiss_fftr_alloc(ft->size, 0, NULL, NULL); ifft = kiss_fftr_alloc(ft->size, 1, NULL, NULL); tmp = malloc(sizeof(kiss_fft_cpx) * ft->size); kiss_fftr(fft, ft->tbl, tmp); for (i = cut; i < (ft->size / 2); i++) { tmp[i].r = 0; tmp[i].i = 0; } kiss_fftri(ifft, tmp, ft->tbl); scale = 1.0 / ft->size; for (i = 0; i < ft->size; i++) { ft->tbl[i] *= scale; } free(tmp); kiss_fftr_free(fft); kiss_fftr_free(ifft); }