1 /*
2  * Waveset
3  *
4  * This code has been extracted from the Csound opcode "waveset".
5  * It has been modified to work as a Soundpipe module.
6  *
7  * Original Author(s): Trevor Wishart, John ffitch
8  * Year: 2001
9  * Location: Opcodes/pitch.c
10  *
11  */
12 
13 #include <stdlib.h>
14 #include "soundpipe.h"
15 
sp_waveset_create(sp_waveset ** p)16 int sp_waveset_create(sp_waveset **p)
17 {
18     *p = malloc(sizeof(sp_waveset));
19     return SP_OK;
20 }
21 
sp_waveset_destroy(sp_waveset ** p)22 int sp_waveset_destroy(sp_waveset **p)
23 {
24     sp_waveset *pp = *p;
25     sp_auxdata_free(&pp->auxch);
26     free(*p);
27     return SP_OK;
28 }
29 
sp_waveset_init(sp_data * sp,sp_waveset * p,SPFLOAT ilen)30 int sp_waveset_init(sp_data *sp, sp_waveset *p, SPFLOAT ilen)
31 {
32     p->length = 1 + (sp->sr * ilen);
33 
34     sp_auxdata_alloc(&p->auxch, p->length * sizeof(SPFLOAT));
35     p->cnt = 1;
36     p->start = 0;
37     p->current = 0;
38     p->end = 0;
39     p->direction = 1;
40     p->lastsamp = 1.0;
41     p->noinsert = 0;
42     return SP_OK;
43 }
44 
sp_waveset_compute(sp_data * sp,sp_waveset * p,SPFLOAT * in,SPFLOAT * out)45 int sp_waveset_compute(sp_data *sp, sp_waveset *p, SPFLOAT *in, SPFLOAT *out)
46 {
47     int index = p->end;
48     SPFLOAT *insert = (SPFLOAT*)(p->auxch.ptr) + index;
49 
50     if (p->noinsert) goto output;
51     *insert++ = *in;
52     if (++index ==  p->start) {
53         p->noinsert = 1;
54     }
55     if (index==p->length) {
56         index = 0;
57         insert = (SPFLOAT*)(p->auxch.ptr);
58     }
59 
60     output:
61 
62     p->end = index;
63     index = p->current;
64     insert = (SPFLOAT*)(p->auxch.ptr) + index;
65     SPFLOAT samp = *insert++;
66     index++;
67 
68     if (index==p->length) {
69         index = 0;
70         insert = (SPFLOAT*)(p->auxch.ptr);
71         p->noinsert = 0;
72     }
73 
74     if (samp != 0.0 && p->lastsamp*samp < 0.0) {
75         if (p->direction == 1) {
76             p->direction = -1;
77         } else {
78             p->direction = 1;
79             if (++p->cnt > p->rep) {
80                 p->cnt = 1;
81                 p->start = index;
82                 p->noinsert = 0;
83             } else { index = p->start;
84                 insert = (SPFLOAT*)(p->auxch.ptr) + index;
85             }
86         }
87     }
88 
89     if (samp != 0.0) p->lastsamp = samp;
90     *out = samp;
91     p->current = index;
92 
93     return SP_OK;
94 }
95