-
Notifications
You must be signed in to change notification settings - Fork 39
/
Copy pathdelayN.c
139 lines (112 loc) · 3.29 KB
/
delayN.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
delayN.c
aleph - audio
implement delay line using buffer and tap objects. non-interpolated version.
*/
#include "conversion.h"
#include "delayN.h"
// initialize with pointer to audio buffer
extern void delayN_init(delayN* dl, fract32* data, u32 frames) {
buffer_init(&(dl->buffer), data, frames);
buffer_tapN_init(&(dl->tapRd), &(dl->buffer));
buffer_tapN_init(&(dl->tapWr), &(dl->buffer));
dl->tapWr.idx = 0;
dl->tapRd.idx = 0;
dl->tapWr.loop = frames;
dl->tapRd.loop = frames;
dl->preLevel = 0;
dl->write = 1;
}
extern fract32 delayN_next(delayN* dl, fract32 in) {
fract32 readVal;
// get read value first.
// so, setting loop == delayNtime gives sensible results (???)
readVal = buffer_tapN_read( &(dl->tapRd) );
// figure out what to write
if(dl->preLevel == 0) {
if(dl->write) {
// write and replace
buffer_tapN_write(&(dl->tapWr), in);
}
} else if(dl->preLevel < 0) { // consider <0 to be == 1
if(dl->write) {
// overdub
buffer_tapN_add(&(dl->tapWr), in);
}
} else { // prelevel is non-zero, non-full
if(dl->write) {
// write mix
buffer_tapN_mix(&(dl->tapWr), in, dl->preLevel);
}
}
// advance the read phasor
if(dl->runRd) {
buffer_tapN_next( &(dl->tapRd) );
}
// advance the write phasor
if(dl->runWr) {
buffer_tapN_next( &(dl->tapWr) );
}
return readVal;
}
// set loop endpoint in seconds
extern void delayN_set_loop_sec(delayN* dl, fix16 sec) {
u32 samps = sec_to_frames_trunc(sec);
buffer_tapN_set_loop(&(dl->tapRd), samps - 1);
buffer_tapN_set_loop(&(dl->tapWr), samps - 1);
}
// set loop endpoint in samples
extern void delayN_set_loop_samp(delayN* dl, u32 samps) {
dl->tapRd.loop = samps - 1;
dl->tapWr.loop = samps - 1;
}
// set delayN in seconds
extern void delayN_set_delayN_sec(delayN* dl, fix16 sec) {
u32 samp = sec_to_frames_trunc(sec);
buffer_tapN_sync(&(dl->tapRd), &(dl->tapWr), samp);
}
// set delayN in samples
extern void delayN_set_delayN_samp(delayN* dl, u32 samp) {
buffer_tapN_sync(&(dl->tapRd), &(dl->tapWr), samp);
}
// set erase level
extern void delayN_set_pre(delayN* dl, fract32 pre) {
dl->preLevel = pre;
}
// set write level
extern void delayN_set_write(delayN* dl, u8 write) {
dl->write = write;
}
// set read pos in seconds
extern void delayN_set_pos_read_sec(delayN* dl, fix16 sec) {
u32 samp = sec_to_frames_trunc(sec);
buffer_tapN_set_pos(&(dl->tapRd), samp);
}
extern void delayN_set_pos_read_samp(delayN* dl, u32 samp) {
buffer_tapN_set_pos(&(dl->tapRd), samp);
}
// set write pos in seconds
extern void delayN_set_pos_write_sec(delayN* dl, fix16 sec) {
u32 samp = sec_to_frames_trunc(sec);
buffer_tapN_set_pos(&(dl->tapWr), samp);
}
extern void delayN_set_pos_write_samp(delayN* dl, u32 samp) {
buffer_tapN_set_pos(&(dl->tapWr), samp);
}
// set read run flag
extern void delayN_set_run_read(delayN* dl, u8 val) {
dl->runRd = val;
}
// set write run flag
extern void delayN_set_run_write(delayN* dl, u8 val) {
dl->runWr = val;
}
// set read-head rate multiplier
void delayN_set_mul(delayN* dl, u32 val, u8 id) {
// different terms, dumb...
buffer_tapN_set_inc( &(dl->tapRd[id]), val );
}
// set read-head rate divider
void delayN_set_div(delayN* dl, u32 val, u8 id) {
buffer_tapN_set_div( &(dl->tapRd[id]), val );
}