File: luamoog.csd

package info (click to toggle)
csound 1%3A6.18.1%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 63,220 kB
  • sloc: ansic: 192,643; cpp: 14,149; javascript: 9,654; objc: 9,181; python: 3,376; java: 3,337; sh: 1,840; yacc: 1,255; xml: 985; perl: 635; lisp: 411; tcl: 341; lex: 217; makefile: 128
file content (267 lines) | stat: -rw-r--r-- 8,233 bytes parent folder | download | duplicates (3)
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
<CsoundSynthesizer>
<CsOptions>
-odac -m3
</CsOptions>
<CsInstruments>
sr =    48000
ksmps =   100
nchnls =    1

    gibegan     rtclock

    lua_opdef   "moogladder", {{
local ffi = require("ffi")
local math = require("math")
local string = require("string")
local csoundApi = ffi.load("csoundandroid")
ffi.cdef[[
    int csoundGetKsmps(void *);
    float csoundGetSr(void *);
    struct moogladder_t {
      float *out;
      float *inp;
      float *freq;
      float *res;
      float *istor;
      float sr;
      float ksmps;
      float thermal;
      float f;
      float fc;
      float fc2;
      float fc3;
      float fcr;
      float acr;
      float tune;
      float res4;
      float input;
      float i;
      float j;
      float k;
      float kk;
      float stg[6];
      float delay[6];
      float tanhstg[6];
    };
]]

local moogladder_ct = ffi.typeof('struct moogladder_t *')

function moogladder_init(csound, opcode, carguments)
    local p = ffi.cast(moogladder_ct, carguments)
    p.sr = csoundApi.csoundGetSr(csound)
    p.ksmps = csoundApi.csoundGetKsmps(csound)
    if p.istor[0] == 0 then
        for i = 0, 5 do
            p.delay[i] = 0.0
        end
        for i = 0, 3 do
            p.tanhstg[i] = 0.0
        end
    end
    return 0
end

function moogladder_kontrol(csound, opcode, carguments)
    local p = ffi.cast(moogladder_ct, carguments)
    -- transistor thermal voltage
    p.thermal = 1.0 / 40000.0
    if p.res[0] < 0.0 then
        p.res[0] = 0.0
    end
    -- sr is half the actual filter sampling rate
    p.fc = p.freq[0] / p.sr
    p.f = p.fc / 2.0
    p.fc2 = p.fc * p.fc
    p.fc3 = p.fc2 * p.fc
    -- frequency & amplitude correction
    p.fcr = 1.873 * p.fc3 + 0.4955 * p.fc2 - 0.6490 * p.fc + 0.9988
    p.acr = -3.9364 * p.fc2 + 1.8409 * p.fc + 0.9968
    -- filter tuning
    p.tune = (1.0 - math.exp(-(2.0 * math.pi * p.f * p.fcr))) / p.thermal
    p.res4 = 4.0 * p.res[0] * p.acr
    -- Nested 'for' loops crash, not sure why.
    -- Local loop variables also are problematic.
    -- Lower-level loop constructs don't crash.
    p.i = 0
    while p.i < p.ksmps do
        p.j = 0
        while p.j < 2 do
            p.k = 0
            while p.k < 4 do
                if p.k == 0 then
                    p.input = p.inp[p.i] - p.res4 * p.delay[5]
                    p.stg[p.k] = p.delay[p.k] + p.tune * (math.tanh(p.input * p.thermal) - p.tanhstg[p.k])
                else
                    p.input = p.stg[p.k - 1]
                    p.tanhstg[p.k - 1] = math.tanh(p.input * p.thermal)
                    if p.k < 3 then
                        p.kk = p.tanhstg[p.k]
                    else
                        p.kk = math.tanh(p.delay[p.k] * p.thermal)
                    end
                    p.stg[p.k] = p.delay[p.k] + p.tune * (p.tanhstg[p.k - 1] - p.kk)
                end
                p.delay[p.k] = p.stg[p.k]
                p.k = p.k + 1
            end
            -- 1/2-sample delay for phase compensation
            p.delay[5] = (p.stg[3] + p.delay[4]) * 0.5
            p.delay[4] = p.stg[3]
            p.j = p.j + 1
        end
        p.out[p.i] = p.delay[5]
        p.i = p.i + 1
    end
    return 0
end
}}

/*
Moogladder - An improved implementation of the Moog ladder filter

DESCRIPTION
This is an new digital implementation of the Moog ladder filter based on the work of Antti Huovilainen,
described in the paper \"Non-Linear Digital Implementation of the Moog Ladder Filter\" (Proceedings of DaFX04, Univ of Napoli).
This implementation is probably a more accurate digital representation of the original analogue filter.
This is version 2 (revised 14/DEC/04), with improved amplitude/resonance scaling and frequency correction using a couple of polynomials,as suggested by Antti.

SYNTAX
ar  Moogladder  asig, kcf, kres

PERFORMANCE
asig - input signal
kcf - cutoff frequency (Hz)
kres - resonance (0 - 1).

CREDITS
Victor Lazzarini
*/

                    opcode  moogladderu, a, akk
asig, kcf, kres     xin
                    setksmps    1
ipi                 =           4 * taninv(1)
/* filter delays */
az1                 init        0
az2                 init        0
az3                 init        0
az4                 init        0
az5                 init        0
ay4                 init        0
amf                 init        0
                    if          kres > 1 then
kres                =           1
                    elseif      kres < 0 then
kres                =           0
                    endif
/* twice the \'thermal voltage of a transistor\' */
i2v                 =           40000
/* sr is half the actual filter sampling rate  */
kfc                 =           kcf/sr
kf                  =           kcf/(sr*2)
/* frequency & amplitude correction  */
kfcr                =           1.8730 * (kfc^3) + 0.4955 * (kfc^2) - 0.6490 * kfc + 0.9988
kacr                =           -3.9364 * (kfc^2) + 1.8409 * kfc + 0.9968;
/* filter tuning  */
k2vg                =           i2v * (1 - exp(-2 * ipi * kfcr * kf))
/* cascade of 4 1st order sections         */
ay1                 =           az1 + k2vg * (tanh((asig - 4 * kres * amf * kacr) / i2v) - tanh(az1 / i2v))
az1                 =           ay1
ay2                 =           az2 + k2vg * (tanh(ay1 / i2v) - tanh(az2 / i2v ))
az2                 =           ay2
ay3                 =           az3 + k2vg * (tanh(ay2 / i2v) - tanh(az3 / i2v))
az3                 =           ay3
ay4                 =           az4 + k2vg * (tanh(ay3 / i2v) - tanh(az4 / i2v))
az4                 =           ay4
/* 1/2-sample delay for phase compensation  */
amf                 =           (ay4 + az5) *0.5
az5                 =           ay4
/* oversampling  */
ay1                 =           az1 + k2vg * (tanh((asig - 4 * kres * amf * kacr) / i2v) - tanh(az1 / i2v))
az1                 =           ay1
ay2                 =           az2 + k2vg * (tanh(ay1 / i2v) - tanh(az2 / i2v ))
az2                 =           ay2
ay3                 =           az3 + k2vg * (tanh(ay2 / i2v) - tanh(az3 / i2v))
az3                 =           ay3
ay4                 =           az4 + k2vg * (tanh(ay3 / i2v) - tanh(az4 / i2v))
az4                 =           ay4
amf                 =           (ay4 + az5) * 0.5
az5                 =           ay4
                    xout        amf
                    endop

instr 1
                prints      "No filter.\n"
	kfe         expseg      500, p3*0.9, 1800, p3*0.1, 3000
    kenv        linen       10000, 0.05, p3, 0.05
    asig        buzz        kenv, 100, sr/(200), 1
    ; afil      moogladder  asig, kfe, 1
                out         asig
endin

instr 2
                prints      "Native moogladder.\n"
	kfe         expseg      500, p3*0.9, 1800, p3*0.1, 3000
    kenv        linen       10000, 0.05, p3, 0.05
    asig        buzz        kenv, 100, sr/(200), 1
    afil        moogladder  asig, kfe, 1
                out         afil
endin

instr 3
                prints      "UDO moogladder.\n"
	kfe         expseg      500, p3*0.9, 1800, p3*0.1, 3000
    kenv        linen       10000, 0.05, p3, 0.05
    asig        buzz        kenv, 100, sr/(200), 1
    afil        moogladderu asig, kfe, 1
                out         afil
endin

instr 4
                prints      "Lua moogladder.\n"
    kres        init        1
    istor       init        0
	kfe         expseg      500, p3*0.9, 1800, p3*0.1, 3000
    kenv        linen       10000, 0.05, p3, 0.05
    asig        buzz        kenv, 100, sr/(200), 1
    afil        init        0
                lua_ikopcall    "moogladder", afil, asig, kfe, kres, istor
                out         afil
endin

instr 5
    giended     rtclock
    ielapsed    =           giended - gibegan
                print       ielapsed
    gibegan     rtclock
endin

</CsInstruments>

<CsScore>
f 1     0 65536 10 1
i 5.1   0   1
i 4     1   20
i 5.2   21  1
i 4     22  20
i 5.3   42  1
i 2     43  20
i 5.4   63  1
i 2     64  20
i 5.5   84  1
i 3     85  20
i 5.6   105 1
i 3     106 20
i 5.7   126 1
i 1     127 20
i 5.8   147 1
i 1     148 20
i 5.9   168 1
i 4     169 20
i 4     170 20
i 4     171 20
e
</CsScore>

</CsoundSynthesizer>