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