-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathoscmorph.c
90 lines (76 loc) · 2.02 KB
/
oscmorph.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <stdlib.h>
#include <math.h>
#include "soundpipe.h"
int sp_oscmorph_create(sp_oscmorph **p)
{
*p = malloc(sizeof(sp_oscmorph));
return SP_OK;
}
int sp_oscmorph_destroy(sp_oscmorph **p)
{
free(*p);
return SP_OK;
}
int sp_oscmorph_init(sp_data *sp, sp_oscmorph *osc, sp_ftbl **ft, int nft, SPFLOAT iphs)
{
int i;
osc->freq = 440.0;
osc->amp = 0.2;
osc->tbl = ft;
osc->iphs = fabs(iphs);
osc->inc = 0;
osc->lphs = ((int32_t)(osc->iphs * SP_FT_MAXLEN)) & SP_FT_PHMASK;
osc->wtpos = 0.0;
osc->nft = nft;
uint32_t prev = (uint32_t)ft[0]->size;
for(i = 0; i < nft; i++) {
if(prev != ft[i]->size) {
fprintf(stderr, "sp_oscmorph: size mismatch\n");
return SP_NOT_OK;
}
prev = (uint32_t)ft[i]->size;
}
return SP_OK;
}
int sp_oscmorph_compute(sp_data *sp, sp_oscmorph *osc, SPFLOAT *in, SPFLOAT *out)
{
sp_ftbl *ftp1;
SPFLOAT amp, cps, fract, v1, v2;
SPFLOAT *ft1, *ft2;
int32_t phs, lobits, pos;
SPFLOAT sicvt = osc->tbl[0]->sicvt;
/* Use only the fractional part of the position or 1 */
if (osc->wtpos > 1.0) {
osc->wtpos -= (int)osc->wtpos;
}
SPFLOAT findex = osc->wtpos * (osc->nft - 1);
int index = floor(findex);
SPFLOAT wtfrac = findex - index;
lobits = osc->tbl[0]->lobits;
amp = osc->amp;
cps = osc->freq;
phs = osc->lphs;
ftp1 = osc->tbl[index];
ft1 = osc->tbl[index]->tbl;
if(index >= osc->nft - 1) {
ft2 = ft1;
} else {
ft2 = osc->tbl[index + 1]->tbl;
}
osc->inc = (int32_t)lrintf(cps * sicvt);
fract = ((phs) & ftp1->lomask) * ftp1->lodiv;
pos = phs >> lobits;
v1 = (1 - wtfrac) *
*(ft1 + pos) +
wtfrac *
*(ft2 + pos);
v2 = (1 - wtfrac) *
*(ft1 + ((pos + 1) % ftp1->size))+
wtfrac *
*(ft2 + ((pos + 1) % ftp1->size));
*out = (v1 + (v2 - v1) * fract) * amp;
phs += osc->inc;
phs &= SP_FT_PHMASK;
osc->lphs = phs;
return SP_OK;
}