This repository has been archived by the owner on Jan 27, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 89
/
lfo.cc
97 lines (88 loc) · 2.33 KB
/
lfo.cc
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
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Low frequency oscillator, compatible with DX7
#include "synth.h"
#include "sin.h"
#include "lfo.h"
uint32_t Lfo::unit_;
void Lfo::init(double sample_rate) {
// constant is 1 << 32 / 15.5s / 11
Lfo::unit_ = (int32_t)(N * 25190424 / sample_rate + 0.5);
}
void Lfo::reset(const char params[6]) {
int rate = params[0]; // 0..99
int sr = rate == 0 ? 1 : (165 * rate) >> 6;
sr *= sr < 160 ? 11 : (11 + ((sr - 160) >> 4));
delta_ = unit_ * sr;
int a = 99 - params[1]; // LFO delay
if (a == 99) {
delayinc_ = ~0u;
delayinc2_ = ~0u;
} else {
a = (16 + (a & 15)) << (1 + (a >> 4));
delayinc_ = unit_ * a;
a &= 0xff80;
a = max(0x80, a);
delayinc2_ = unit_ * a;
}
waveform_ = params[5];
sync_ = params[4] != 0;
}
int32_t Lfo::getsample() {
phase_ += delta_;
int32_t x;
switch (waveform_) {
case 0: // triangle
x = phase_ >> 7;
x ^= -(phase_ >> 31);
x &= (1 << 24) - 1;
return x;
case 1: // sawtooth down
return (~phase_ ^ (1U << 31)) >> 8;
case 2: // sawtooth up
return (phase_ ^ (1U << 31)) >> 8;
case 3: // square
return ((~phase_) >> 7) & (1 << 24);
case 4: // sine
return (1 << 23) + (Sin::lookup(phase_ >> 8) >> 1);
case 5: // s&h
if (phase_ < delta_) {
randstate_ = (randstate_ * 179 + 17) & 0xff;
}
x = randstate_ ^ 0x80;
return (x + 1) << 16;
}
return 1 << 23;
}
int32_t Lfo::getdelay() {
uint32_t delta = delaystate_ < (1U << 31) ? delayinc_ : delayinc2_;
uint32_t d = delaystate_ + delta;
if (d < delayinc_) {
return 1 << 24;
}
delaystate_ = d;
if (d < (1U << 31)) {
return 0;
} else {
return (d >> 7) & ((1 << 24) - 1);
}
}
void Lfo::keydown() {
if (sync_) {
phase_ = (1U << 31) - 1;
}
delaystate_ = 0;
}