Line | Branch | Exec | Source |
---|---|---|---|
1 | #include <stdlib.h> | ||
2 | #include <math.h> | ||
3 | #include "gwion_util.h" | ||
4 | #include "gwion_ast.h" | ||
5 | #include "gwion_env.h" | ||
6 | #include "vm.h" | ||
7 | #include "gwion.h" | ||
8 | #include "instr.h" | ||
9 | #include "object.h" | ||
10 | #include "operator.h" | ||
11 | #include "import.h" | ||
12 | #include "ugen.h" | ||
13 | #include "gwi.h" | ||
14 | #include "emit.h" | ||
15 | |||
16 | 12 | static DTOR(basic_dtor) { xfree(UGEN(o)->module.gen.data); } | |
17 | |||
18 | 480000 | static TICK(gain_tick) { u->out = (u->in * *(m_float *)u->module.gen.data); } | |
19 | |||
20 | 1 | static CTOR(gain_ctor) { | |
21 | 1 | ugen_ini(shred->info->vm->gwion, UGEN(o), 1, 1); | |
22 | 1 | ugen_gen(shred->info->vm->gwion, UGEN(o), gain_tick, | |
23 | (m_float *)xmalloc(SZ_FLOAT), 0); | ||
24 | 1 | UGEN(o)->module.gen.tick = gain_tick; | |
25 | 1 | *(m_float *)UGEN(o)->module.gen.data = 1; | |
26 | 1 | } | |
27 | |||
28 | 67 | static MFUN(gain_get_gain) { | |
29 | 67 | *(m_float *)RETURN = *(m_float *)UGEN(o)->module.gen.data; | |
30 | 67 | } | |
31 | |||
32 | 67 | static MFUN(gain_set_gain) { | |
33 | 67 | *(m_float *)RETURN = *(m_float *)UGEN(o)->module.gen.data = | |
34 | 67 | *(m_float *)MEM(SZ_INT); | |
35 | 67 | } | |
36 | |||
37 | 638 | static GWION_IMPORT(gain) { | |
38 | 638 | GWI_OB(gwi_class_ini(gwi, "Gain", "UGen")) | |
39 | 638 | gwi_class_xtor(gwi, gain_ctor, basic_dtor); | |
40 | 638 | gwi_func_ini(gwi, "float", "gain"); | |
41 | 638 | GWI_BB(gwi_func_end(gwi, gain_get_gain, ae_flag_none)) | |
42 | 638 | gwi_func_ini(gwi, "float", "gain"); | |
43 | 638 | gwi_func_arg(gwi, "float", "arg0"); | |
44 | 638 | GWI_BB(gwi_func_end(gwi, gain_set_gain, ae_flag_none)) | |
45 | 638 | return gwi_class_end(gwi); | |
46 | } | ||
47 | |||
48 | 18 | static TICK(impulse_tick) { | |
49 | 18 | u->out = *(m_float *)u->module.gen.data; | |
50 | 18 | *(m_float *)u->module.gen.data = 0; | |
51 | 18 | } | |
52 | |||
53 | 7 | static CTOR(impulse_ctor) { | |
54 | 7 | ugen_ini(shred->info->vm->gwion, UGEN(o), 0, 1); | |
55 | 7 | ugen_gen(shred->info->vm->gwion, UGEN(o), impulse_tick, | |
56 | (m_float *)xmalloc(SZ_FLOAT), 0); | ||
57 | 7 | *(m_float *)UGEN(o)->module.gen.data = 0; | |
58 | 7 | } | |
59 | |||
60 | 1 | static MFUN(impulse_get_next) { | |
61 | 1 | *(m_float *)RETURN = *(m_float *)UGEN(o)->module.gen.data; | |
62 | 1 | } | |
63 | |||
64 | 8 | static MFUN(impulse_set_next) { | |
65 | 8 | *(m_float *)RETURN = | |
66 | 8 | (*(m_float *)UGEN(o)->module.gen.data = *(m_float *)MEM(SZ_INT)); | |
67 | 8 | } | |
68 | |||
69 | 638 | static GWION_IMPORT(impulse) { | |
70 | 638 | GWI_OB(gwi_class_ini(gwi, "Impulse", "UGen")) | |
71 | 638 | gwi_class_xtor(gwi, impulse_ctor, basic_dtor); | |
72 | 638 | gwi_func_ini(gwi, "float", "next"); | |
73 | 638 | GWI_BB(gwi_func_end(gwi, impulse_get_next, ae_flag_none)) | |
74 | 638 | gwi_func_ini(gwi, "float", "next"); | |
75 | 638 | gwi_func_arg(gwi, "float", "arg0"); | |
76 | 638 | GWI_BB(gwi_func_end(gwi, impulse_set_next, ae_flag_none)) | |
77 | 638 | return gwi_class_end(gwi); | |
78 | } | ||
79 | |||
80 | 2 | static TICK(fullrect_tick) { u->out = fabs(u->in); } | |
81 | |||
82 | 1 | static CTOR(fullrect_ctor) { | |
83 | 1 | ugen_ini(shred->info->vm->gwion, UGEN(o), 1, 1); | |
84 | 1 | ugen_gen(shred->info->vm->gwion, UGEN(o), fullrect_tick, | |
85 | (m_float *)xmalloc(SZ_FLOAT), 0); | ||
86 | 1 | *(m_float *)UGEN(o)->module.gen.data = 1; | |
87 | 1 | } | |
88 | |||
89 | 638 | static GWION_IMPORT(fullrect) { | |
90 | 638 | GWI_OB(gwi_class_ini(gwi, "FullRect", "UGen")) | |
91 | 638 | gwi_class_xtor(gwi, fullrect_ctor, basic_dtor); | |
92 | 638 | return gwi_class_end(gwi); | |
93 | } | ||
94 | |||
95 | 2 | static TICK(halfrect_tick) { | |
96 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (u->in > 0) |
97 | 1 | u->out = u->in; | |
98 | else | ||
99 | 1 | u->out = 0; | |
100 | 2 | } | |
101 | |||
102 | 1 | static CTOR(halfrect_ctor) { | |
103 | 1 | ugen_ini(shred->info->vm->gwion, UGEN(o), 1, 1); | |
104 | 1 | ugen_gen(shred->info->vm->gwion, UGEN(o), halfrect_tick, | |
105 | (m_float *)xmalloc(SZ_FLOAT), 0); | ||
106 | 1 | *(m_float *)UGEN(o)->module.gen.data = 1; | |
107 | 1 | } | |
108 | |||
109 | 638 | static GWION_IMPORT(halfrect) { | |
110 | 638 | GWI_OB(gwi_class_ini(gwi, "HalfRect", "UGen")) | |
111 | 638 | gwi_class_xtor(gwi, halfrect_ctor, basic_dtor); | |
112 | 638 | return gwi_class_end(gwi); | |
113 | } | ||
114 | |||
115 | 1 | static TICK(step_tick) { u->out = *(m_float *)u->module.gen.data; } | |
116 | |||
117 | 1 | static CTOR(step_ctor) { | |
118 | 1 | ugen_ini(shred->info->vm->gwion, UGEN(o), 0, 1); | |
119 | 1 | ugen_gen(shred->info->vm->gwion, UGEN(o), step_tick, | |
120 | (m_float *)xmalloc(SZ_FLOAT), 0); | ||
121 | 1 | *(m_float *)UGEN(o)->module.gen.data = 0; | |
122 | 1 | } | |
123 | |||
124 | 1 | static MFUN(step_get_next) { | |
125 | 1 | *(m_float *)RETURN = *(m_float *)UGEN(o)->module.gen.data; | |
126 | 1 | } | |
127 | |||
128 | 1 | static MFUN(step_set_next) { | |
129 | 1 | *(m_float *)RETURN = *(m_float *)UGEN(o)->module.gen.data = | |
130 | 1 | *(m_float *)(shred->mem + SZ_INT); | |
131 | 1 | } | |
132 | |||
133 | 638 | static GWION_IMPORT(step) { | |
134 | 638 | GWI_OB(gwi_class_ini(gwi, "Step", "UGen")) | |
135 | 638 | gwi_class_xtor(gwi, step_ctor, basic_dtor); | |
136 | 638 | gwi_func_ini(gwi, "float", "next"); | |
137 | 638 | GWI_BB(gwi_func_end(gwi, step_get_next, ae_flag_none)) | |
138 | 638 | gwi_func_ini(gwi, "float", "next"); | |
139 | 638 | gwi_func_arg(gwi, "float", "arg0"); | |
140 | 638 | GWI_BB(gwi_func_end(gwi, step_set_next, ae_flag_none)) | |
141 | 638 | return gwi_class_end(gwi); | |
142 | } | ||
143 | |||
144 | 4 | static TICK(zerox_tick) { | |
145 |
4/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
|
4 | m_float in = (u->in < 0) ? -1 : (u->in > 0); |
146 | 4 | m_float f = *(m_float *)u->module.gen.data; | |
147 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | u->out = f == in ? 1 : 0; |
148 | 4 | *(m_float *)u->module.gen.data = in; | |
149 | 4 | } | |
150 | |||
151 | 1 | static CTOR(zerox_ctor) { | |
152 | 1 | ugen_ini(shred->info->vm->gwion, UGEN(o), 1, 1); | |
153 | 1 | ugen_gen(shred->info->vm->gwion, UGEN(o), zerox_tick, | |
154 | (m_float *)xmalloc(SZ_FLOAT), 0); | ||
155 | 1 | *(m_float *)UGEN(o)->module.gen.data = 1; | |
156 | 1 | } | |
157 | |||
158 | 638 | static GWION_IMPORT(zerox) { | |
159 | 638 | GWI_OB(gwi_class_ini(gwi, "ZeroX", "UGen")) | |
160 | 638 | gwi_class_xtor(gwi, zerox_ctor, basic_dtor); | |
161 | 638 | return gwi_class_end(gwi); | |
162 | } | ||
163 | |||
164 | struct UUGen_ { | ||
165 | M_Object self; | ||
166 | VM_Code code; | ||
167 | VM_Shred shred; | ||
168 | void (*prep)(struct UUGen_ *, const m_float); | ||
169 | }; | ||
170 | |||
171 | ✗ | ANN static void global_prep(struct UUGen_ *uu, const m_float in) { | |
172 | ✗ | *(m_float *)uu->shred->mem = in; | |
173 | } | ||
174 | |||
175 | ✗ | ANN static void member_prep(struct UUGen_ *uu, const m_float in) { | |
176 | ✗ | *(M_Object *)uu->shred->mem = uu->self; | |
177 | ✗ | *(m_float *)(uu->shred->mem + SZ_INT) = in; | |
178 | } | ||
179 | |||
180 | ✗ | static TICK(id_tick) { u->out = u->in; } | |
181 | |||
182 | ✗ | static TICK(usrugen_tick) { | |
183 | ✗ | struct UUGen_ *uu = u->module.gen.data; | |
184 | ✗ | uu->prep(uu, u->in); | |
185 | ✗ | uu->shred->pc = 0; | |
186 | ✗ | shredule(uu->shred->tick->shreduler, uu->shred, 0); | |
187 | ✗ | vm_run(uu->shred->info->vm); | |
188 | ✗ | uu->shred->reg -= SZ_FLOAT; | |
189 | ✗ | u->out = *(m_float *)(uu->shred->reg); | |
190 | } | ||
191 | |||
192 | ✗ | static CTOR(usrugen_ctor) { | |
193 | ✗ | struct UUGen_ *uu = mp_calloc(shred->info->mp, UUGen); | |
194 | ✗ | uu->self = o; | |
195 | ✗ | ugen_ini(shred->info->vm->gwion, UGEN(o), 1, 1); | |
196 | ✗ | ugen_gen(shred->info->vm->gwion, UGEN(o), id_tick, uu, 0); | |
197 | } | ||
198 | |||
199 | ✗ | static DTOR(usrugen_dtor) { | |
200 | ✗ | struct UUGen_ *uu = UGEN(o)->module.gen.data; | |
201 | ✗ | if (uu->shred) free_vm_shred(uu->shred); | |
202 | ✗ | mp_free(shred->info->mp, UUGen, UGEN(o)->module.gen.data); | |
203 | } | ||
204 | |||
205 | 9 | static OP_CHECK(opck_usrugen) { | |
206 | 9 | Exp_Binary * bin = (Exp_Binary *)data; | |
207 | 9 | const Arg_List arg = bin->lhs->type->info->func->def->base->args; | |
208 |
4/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7 times.
|
9 | if (!arg || arg->len > 1) |
209 | 2 | ERR_N(exp_self(bin)->pos, | |
210 | _("Tick function take one and only one argument")); | ||
211 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
|
7 | if (isa(((Arg*)(arg->ptr))->type, env->gwion->type[et_float]) < 0) |
212 | 1 | ERR_N(exp_self(bin)->pos, | |
213 | _("Tick functions argument must be of type float")); | ||
214 | 6 | if (isa(bin->lhs->type->info->func->def->base->ret_type, | |
215 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
|
6 | env->gwion->type[et_float]) < 0) |
216 | 1 | ERR_N(exp_self(bin)->pos, _("Tick function must return float")); | |
217 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (bin->lhs->type->info->func->value_ref->from->owner_class) |
218 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | CHECK_BN(isa(bin->lhs->type->info->func->value_ref->from->owner_class, |
219 | bin->rhs->type)); | ||
220 | 5 | return bin->rhs->type; | |
221 | } | ||
222 | |||
223 | ✗ | static INSTR(UURet) { shreduler_remove(shred->tick->shreduler, shred, false); } | |
224 | |||
225 | ✗ | ANN static void code_prepare(const VM_Code code) { | |
226 | ✗ | m_bit *byte = code->bytecode; | |
227 | ✗ | for (m_uint i = 0; i < vector_size(&code->instr); ++i) { | |
228 | ✗ | if (*(m_bit *)(byte + i * BYTECODE_SZ) == eFuncReturn) { | |
229 | ✗ | *(m_bit *)(byte + i * BYTECODE_SZ) = eOP_MAX; | |
230 | ✗ | *(f_instr *)(byte + (i * BYTECODE_SZ) + SZ_INT * 2) = UURet; | |
231 | } | ||
232 | } | ||
233 | } | ||
234 | |||
235 | ✗ | static MFUN(default_tick) { | |
236 | ✗ | struct UUGen_ *uu = UGEN(o)->module.gen.data; | |
237 | ✗ | if (uu->shred) { | |
238 | ✗ | free_vm_shred(uu->shred); | |
239 | ✗ | uu->shred = NULL; | |
240 | } | ||
241 | ✗ | UGEN(o)->module.gen.tick = id_tick; | |
242 | } | ||
243 | |||
244 | ✗ | static INSTR(UsrUGenTick) { | |
245 | ✗ | const m_uint offset = !instr->m_val ? SZ_INT : 0; | |
246 | ✗ | shred->reg -= SZ_INT * 2 - offset; | |
247 | ✗ | const M_Object o = *(M_Object *)(shred->reg + SZ_INT - offset); | |
248 | ✗ | struct UUGen_ *uu = UGEN(o)->module.gen.data; | |
249 | ✗ | if (uu->shred) { | |
250 | ✗ | free_vm_shred(uu->shred); | |
251 | ✗ | return; | |
252 | } | ||
253 | ✗ | UGEN(o)->module.gen.tick = usrugen_tick; | |
254 | ✗ | const VM_Code code = *(VM_Code *)(shred->reg - offset); | |
255 | ✗ | if (!code) { | |
256 | ✗ | handle(shred, "NullTickException"); | |
257 | ✗ | return; | |
258 | } | ||
259 | ✗ | uu->shred = new_vm_shred(shred->info->mp, *(VM_Code *)(shred->reg - offset)); | |
260 | ✗ | vmcode_addref(*(VM_Code *)(shred->reg - offset)); | |
261 | ✗ | uu->shred->info->vm = shred->info->vm; | |
262 | ✗ | code_prepare(vmcode_callback(shred->info->mp, uu->shred->code)); | |
263 | ✗ | shreduler_ini(uu->shred->tick->shreduler, uu->shred); | |
264 | ✗ | uu->prep = instr->m_val ? member_prep : global_prep; | |
265 | ✗ | *(M_Object *)(shred->reg - SZ_INT) = o; | |
266 | } | ||
267 | |||
268 | ✗ | static OP_EMIT(opem_usrugen) { | |
269 | ✗ | Exp_Binary *bin = (Exp_Binary *)data; | |
270 | ✗ | const Instr instr = emit_add_instr(emit, UsrUGenTick); | |
271 | ✗ | instr->m_val = !!bin->lhs->type->info->func->value_ref->from->owner_class; | |
272 | ✗ | return GW_OK; | |
273 | } | ||
274 | |||
275 | 638 | static GWION_IMPORT(usrugen) { | |
276 | 638 | GWI_OB(gwi_class_ini(gwi, "UsrUGen", "UGen")) | |
277 | 638 | gwi_class_xtor(gwi, usrugen_ctor, usrugen_dtor); | |
278 | 638 | GWI_BB(gwi_func_ini(gwi, "int", "default_tick")) | |
279 | 638 | GWI_BB(gwi_func_end(gwi, default_tick, 0)) | |
280 | 638 | GWI_BB(gwi_class_end(gwi)) | |
281 | 638 | GWI_BB(gwi_oper_ini(gwi, "function", "UsrUGen", "UsrUGen")) | |
282 | 638 | GWI_BB(gwi_oper_add(gwi, opck_usrugen)) | |
283 | 638 | GWI_BB(gwi_oper_emi(gwi, opem_usrugen)) | |
284 | 638 | GWI_BB(gwi_oper_end(gwi, "~=>", NULL)) | |
285 | 638 | return GW_OK; | |
286 | } | ||
287 | |||
288 | 638 | GWION_IMPORT(modules) { | |
289 | 638 | GWI_BB(gwimport_gain(gwi)) | |
290 | 638 | GWI_BB(gwimport_impulse(gwi)) | |
291 | 638 | GWI_BB(gwimport_fullrect(gwi)) | |
292 | 638 | GWI_BB(gwimport_halfrect(gwi)) | |
293 | 638 | GWI_BB(gwimport_step(gwi)) | |
294 | 638 | GWI_BB(gwimport_zerox(gwi)) | |
295 | 638 | return gwimport_usrugen(gwi); | |
296 | } | ||
297 |