2 orgux - a just-for-fun real time synth
3 Copyright (C) 2009 Evan Rinehart
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 #define PI 3.141592653589
29 #include "instruments.h"
32 #define SAMPLE_LENGTH 1<<16
33 #define SAMPLE_COUNT 16
34 #define SAMPLE_NOTE_ZERO 60
36 #define ANTIPOP_LENGTH 512
37 #define WAVEFORM_LENGTH (1<<10)
39 #define MAX_COMMANDS 256
42 #define RANDF() (((float)rand())/RAND_MAX)
43 #define RAND_SIGNAL() (RANDF()*2 - 1)
47 int precompute_ok
= 0;
48 float square_wave
[WAVEFORM_LENGTH
];
49 float saw_wave
[WAVEFORM_LENGTH
];
50 float triangle_wave
[WAVEFORM_LENGTH
];
52 float linterp(float x
, int k
, float wave
[]){
54 float Xw
= X
- WAVEFORM_LENGTH
*floor(X
/WAVEFORM_LENGTH
);
57 if(X1
== WAVEFORM_LENGTH
) X1
= 0;
61 float m
= (y1
-y0
)/(X1
-X0
);
74 //float velocity[16][128];
75 unsigned char onbits
[16][16];
77 float waveform
[128][WAVEFORM_LENGTH
];
78 float antipop
[ANTIPOP_LENGTH
];
79 //float wave_ptr[16][128];
80 //float wave_step[16][128];
82 //int env_ptr[16][128];
83 //int env_flag[16][128];
85 //need to redo the samples
86 float samples
[SAMPLE_COUNT
][SAMPLE_LENGTH
];
87 //int sample_ptr[SAMPLE_COUNT];
88 //int sample_on[SAMPLE_COUNT];
89 //float sample_velocity[SAMPLE_COUNT];
94 int command_queue
[512][5]; /* sample type chan val1 val2 */
97 int note_on
[MAX_NOTES
];
98 int note_channel
[MAX_NOTES
];
99 int note_note
[MAX_NOTES
];
100 float velocity
[MAX_NOTES
];
101 int antipop_flag
[MAX_NOTES
];
102 int antipop_ptr
[MAX_NOTES
];
103 float wave_ptr
[MAX_NOTES
];
104 float wave_step
[MAX_NOTES
];
105 int sample_ptr
[MAX_NOTES
];
106 float lp_y
[MAX_NOTES
];
110 void orgux_note_on(orgux_state
* S
, int chan
, int note
, int velocity
){
112 for(int i
=0; i
< MAX_NOTES
; i
++){
113 if(S
->note_on
[i
] == 0){
115 S
->note_channel
[i
] = chan
;
116 S
->note_note
[i
] = note
;
117 S
->velocity
[i
] = ((float)velocity
)/127;
118 S
->antipop_flag
[i
] = -1;
119 S
->antipop_ptr
[i
] = 0;
120 S
->wave_ptr
[i
] = 0.0f
;
121 S
->sample_ptr
[i
] = 0;
122 //S->wave_step[i] = (int)((440*pow(2,(note-69)/12.0)*WAVEFORM_LENGTH)/S->sample_rate);
123 S
->wave_step
[i
] = (440*pow(2,(note
-69)/12.0)*WAVEFORM_LENGTH
)/S
->sample_rate
;
124 if(i
== S
->note_max
){
133 void orgux_note_off(orgux_state
* S
, int chan
, int note
){
135 for(int i
=0; i
< S
->note_max
; i
++){
136 if(S
->note_on
[i
]==1 && S
->note_channel
[i
]==chan
&& S
->note_note
[i
]==note
&& S
->antipop_flag
[i
]<1){
138 //S->note_on[i][1] = chan;
139 //S->note_on[i][2] = note;
140 S
->antipop_flag
[i
] = 1;
141 //S->wave_ptr[i] = 0.0f;
142 //S->wave_step[i] = (440*pow(2,(note-57)/12.0)*WAVEFORM_LENGTH)/S->sample_rate;
150 void orgux_change_volume(orgux_state
* S
, int chan
, int value
){
151 //printf("change volume %d %d\n", chan, value);
152 S
->volume
[chan
] = ((float)value
)/127;
155 void orgux_change_pan(orgux_state
* S
, int chan
, int value
){
156 //printf("change pan %d %d\n", chan, value);
157 float P
= (((float)value
)/127) * 2 - 1;
160 S
->pan_l
[chan
] = 1.0f
- P
;
161 S
->pan_r
[chan
] = 1.0f
;
164 S
->pan_l
[chan
] = 1.0f
;
165 S
->pan_r
[chan
] = P
+ 1.0f
;
169 void orgux_change_instrument(orgux_state
* S
, int chan
, int value
){
170 //printf("change instrument %d %d\n", chan, value);
171 S
->instrument
[chan
] = value
;
174 void orgux_pitch_bend(orgux_state
* S
, int chan
, int bend
){
175 S
->bend
[chan
] = ((((float)bend
)/16383) * 2 - 1) * 1;
179 void orgux_process(orgux_state
* S
, float* lbuf
, float* rbuf
, int len
){
182 /* determine on notes, dont search each time */
183 int note_ons
[MAX_NOTES
];
185 for(int i
=0; i
<S
->note_max
; i
++){
192 for(int i
=0; i
<len
; i
++){
194 while(i
== S
->command_queue
[C
][0] && C
< S
->command_count
){
195 orgux_control(S
, S
->command_queue
[C
][1],
196 S
->command_queue
[C
][2],
197 S
->command_queue
[C
][3],
198 S
->command_queue
[C
][4]);
206 //render playing samples
207 /*for(int j = 0; j<SAMPLE_COUNT; j++){
208 if(!S->sample_on[j]) continue;
209 float y = S->samples[j][S->sample_ptr[j]++];
210 if(S->sample_ptr[j] == SAMPLE_LENGTH){
213 float V = S->volume[9];
214 float A = S->sample_velocity[j];
215 lbuf[i] += V*A*S->pan_l[9]*y;
216 rbuf[i] += V*A*S->pan_r[9]*y;
220 int jmax
= S
->note_max
;
221 for(int j
=0; j
< jmax
; j
++){
222 //for(int n=0; n < N; n++){
223 //int j = note_ons[n];
225 if(!S
->note_on
[j
]) continue;
227 if(S
->note_channel
[j
] == 9){
228 int index
= S
->note_note
[j
] - SAMPLE_NOTE_ZERO
;
229 if(index
< 0){index
=0;}
230 if(index
>= SAMPLE_COUNT
){index
=SAMPLE_COUNT
-1;}
231 float y
= S
->samples
[index
][S
->sample_ptr
[j
]++];
232 if(S
->sample_ptr
[j
] == SAMPLE_LENGTH
){
236 float V
= S
->volume
[9];
237 float A
= S
->velocity
[j
];
238 lbuf
[i
] += V
*A
*S
->pan_l
[9]*y
;
239 rbuf
[i
] += V
*A
*S
->pan_r
[9]*y
;
244 /* hard computations */
245 float x
= S
->wave_ptr
[j
];
247 float x2
= x1
+ 1.0f
;
250 if(X2
== WAVEFORM_LENGTH
) X2
= 0;
251 int I
= S
->instrument
[S
->note_channel
[j
]];
252 float y1
= S
->waveform
[I
][X1
];
253 float y2
= S
->waveform
[I
][X2
];
254 float m
= (y2
-y1
)/(x2
-x1
);
255 float y
= m
*(x
-x1
) + y1
;
260 int I = S->instrument[S->note_channel[j]];
261 int X = S->wave_ptr[j];
262 float y = S->waveform[I][X];
265 //float y0 = S->lp_y[j];
266 //y = y0 + S->lp_alpha * (y - y0);
269 switch(S
->antipop_flag
[j
]){
271 y
*= S
->antipop
[S
->antipop_ptr
[j
]];
274 if(S
->antipop_ptr
[j
] == ANTIPOP_LENGTH
){
275 S
->antipop_ptr
[j
] = ANTIPOP_LENGTH
-1;
276 S
->antipop_flag
[j
] = 0;
280 y
*= S
->antipop
[S
->antipop_ptr
[j
]];
282 if(S
->antipop_ptr
[j
] < 0){
283 //printf("note dead! j = %d, max = %d\n",j, S->note_max);
284 S
->antipop_flag
[j
] = 0;
286 if(j
+1==S
->note_max
){
294 int chan
= S
->note_channel
[j
];
295 float volume
= S
->volume
[chan
];
296 float velocity
= S
->velocity
[j
];
297 lbuf
[i
] += volume
*velocity
*S
->pan_l
[chan
]*y
;
298 rbuf
[i
] += volume
*velocity
*S
->pan_r
[chan
]*y
;
300 if(lbuf
[i
]> 1.0 || lbuf
[i
] < -1.0){
301 printf("ehh lbuf[%d] = %f\n",i
,lbuf
[i
]);
302 printf("%f %f %f %f %f\n",y
,volume
, velocity
, S
->pan_l
[chan
], S
->pan_r
[chan
]);
305 S
->wave_ptr
[j
] += S
->wave_step
[j
];
306 while(S
->wave_ptr
[j
] >= WAVEFORM_LENGTH
){
307 S
->wave_ptr
[j
] -= WAVEFORM_LENGTH
;
314 S
->command_count
= 0;
321 void orgux_schedule(orgux_state
* S
, int sample
, unsigned char midi
[3]){
322 //orgux_control(S, midi[0]&0xf0, midi[0]&0x0f, midi[1], midi[2]);
324 if(S
->command_count
== MAX_COMMANDS
){
328 switch(midi
[0]&0xf0){
334 the queue is sorted by time (sample)
335 soonest times are to the beginning of the queue
336 queue[0] is the first element
337 insert: move all later events right one
340 //printf("schedule %d %x %x %x\n",sample,midi[0],midi[1],midi[2]);
342 for(i
=0; i
<S
->command_count
; i
++){
344 if(sample
< S
->command_queue
[i
][0]){
346 for(int j
=S
->command_count
; j
>i
; j
--){
347 S
->command_queue
[j
][0] = S
->command_queue
[j
-1][0];
348 S
->command_queue
[j
][1] = S
->command_queue
[j
-1][1];
349 S
->command_queue
[j
][2] = S
->command_queue
[j
-1][2];
350 S
->command_queue
[j
][3] = S
->command_queue
[j
-1][3];
351 S
->command_queue
[j
][4] = S
->command_queue
[j
-1][4];
354 S
->command_queue
[i
][0] = sample
;
355 S
->command_queue
[i
][1] = midi
[0]&0xf0;
356 S
->command_queue
[i
][2] = midi
[0]&0x0f;
357 S
->command_queue
[i
][3] = midi
[1];
358 S
->command_queue
[i
][4] = midi
[2];
364 if(i
==S
->command_count
){//end of queue
365 S
->command_queue
[i
][0] = sample
;
366 S
->command_queue
[i
][1] = midi
[0]&0xf0;
367 S
->command_queue
[i
][2] = midi
[0]&0x0f;
368 S
->command_queue
[i
][3] = midi
[1];
369 S
->command_queue
[i
][4] = midi
[2];
374 for(int i
=0; i
<S
->command_count
; i
++){
375 /*printf("%d %d %d %d %d\n",
376 S->command_queue[i][0],
377 S->command_queue[i][1],
378 S->command_queue[i][2],
379 S->command_queue[i][3],
380 S->command_queue[i][4]);
386 void orgux_control(orgux_state
* S
, int type
, int chan
, int val1
, int val2
){
388 int bend
= (val1
<< 7) + val2
;
390 //printf("control %d %d %d %d\n", chan, type, val1, val2);
394 orgux_note_on(S
, chan
, val1
, val2
);
397 orgux_note_off(S
, chan
, val1
);
400 orgux_change_instrument(S
, chan
, val1
);
404 orgux_change_volume(S
, chan
, val2
);
407 orgux_change_pan(S
, chan
, val2
);
411 printf("pitch bend %d\n",bend
);
412 orgux_pitch_bend(S
, chan
, bend
);
419 orgux_state
* orgux_init(int sample_rate
){
420 orgux_state
* S
= malloc(sizeof(orgux_state
));
423 float dt
= 1.0/sample_rate
;
429 /*precompute square, saw, and triangle wave*/
431 for(int i
=0; i
<WAVEFORM_LENGTH
; i
++){
433 triangle_wave
[i
] = 0;
435 for(int j
=0; j
<7; j
++){
436 square_wave
[i
] += (4/PI
)*sin(i
*(2*j
+1)*PI2
/WAVEFORM_LENGTH
)/(2*j
+1);
437 triangle_wave
[i
] += (8/(PI
*PI
))*(j
&1?1:-1)*sin(i
*(2*j
+1)*PI2
/WAVEFORM_LENGTH
)/((2*j
+1)*(2*j
+1));
438 saw_wave
[i
] += (2/PI
)*sin(i
*(j
+1)*PI2
/WAVEFORM_LENGTH
)/(j
+1);
443 /* setup oscillator states */
445 for(int i
=0; i
<16; i
++){
451 for(int i
=0; i
<MAX_NOTES
; i
++){
452 S
->wave_ptr
[i
] = 0.0f
;
453 S
->antipop_ptr
[i
] = 0;
454 S
->antipop_flag
[i
] = 0;
456 S
->sample_ptr
[i
] = 0;
460 //for(int i=0; i<SAMPLE_COUNT; i++){
461 // S->sample_on[i] = 0;
462 // S->sample_ptr[i] = 0;
465 S
->sample_rate
= sample_rate
;
467 S
->command_count
= 0;
470 S
->lp_alpha
= dt
/(dt
+0.001);
472 /* setup wave tables */
473 printf(" 0 1 2 3 4 5 6 7 | basis FM FM_freq LP HP\n");
474 for(int i
=0; i
<128; i
++){
479 printf("instrument[%d] = {",i
);
481 for(int j
=0; j
<HARMONIC_COUNT
; j
++){
482 if(instr_config
[i
][j
] > max
){ max
= instr_config
[i
][j
]; }
486 for(int j
=0; j
<WAVEFORM_LENGTH
; j
++){
487 S
->waveform
[i
][j
] = 0.0f
;
489 for(int k
=0; k
<HARMONIC_COUNT
; k
++){
490 float M
= ((float)instr_config
[i
][k
])/max
;
495 switch(instr_config
[i
][BASE_CONFIG
]){
496 case SINE_BASE
: y
= sin(j
*(1<<k
)*PI2
/WAVEFORM_LENGTH
); break;
497 //case SQUARE_BASE: y = ((2*j*(1<<k)/WAVEFORM_LENGTH)&1)?1:-1; break;
498 case SQUARE_BASE
: y
= linterp(j
,k
+1,square_wave
); break;
499 case TRIANGLE_BASE
: y
= linterp(j
,k
+1,triangle_wave
); break;
500 case SAW_BASE
: y
= linterp(j
,k
+1,saw_wave
); break;
501 //case NOISE_BASE: y = RANDF()*2 - 1; break;
502 case NOISE_BASE
: y
= 0; break;
503 default: y
= 0;//use previously defined waveform
506 S
->waveform
[i
][j
] += M
* y
;
508 if(N
>0){ S
->waveform
[i
][j
] /= N
*10; }
515 //generate antipop cosine
516 for(int i
=0; i
<ANTIPOP_LENGTH
; i
++){
517 S
->antipop
[i
] = -cos(i
*PI2
/(2.0*ANTIPOP_LENGTH
))/2.0+0.5;
523 float par
[16][8] = {/**/
524 {50, 500, 0.5, 10000, 0, 0, 0, 0},
525 {200, 200, 0.5, 10000, 0, 0, 0, 0},
526 {100, 500, 0.5, 10000, 0, 0, 0, 0},
527 {100, 1000, 0.5, 10000, 0, 0, 0, 0},
529 {100, 500, 0.5, 3000, 0, 0, 0, 0},
530 {200, 500, 0.5, 3000, 0, 0, 0, 0},
531 {300, 500, 0.5, 3000, 0, 0, 0, 0},
532 {400, 500, 0.5, 3000, 0, 0, 0, 0},
534 {400, 200, 0.5, 3000, 0, 0, 0, 0},
535 {400, 100, 0.5, 3000, 0, 0, 0, 0},
536 {400, 50, 0.5, 3000, 0, 0, 0, 0},
537 {400, 20, 0.5, 3000, 0, 0, 0, 0},
539 {100, 500, 0.5, 10000, 0, 0, 0, 0},
540 {100, 500, 0.5, 10000, 0, 0, 0, 0},
541 {100, 500, 0.5, 10000, 0, 0, 0, 0},
542 {100, 500, 0.5, 10000, 0, 0, 0, 0}
545 double K
= PI2
/ sample_rate
;
546 printf("generating samples\n");
547 for(int i
=0; i
<SAMPLE_LENGTH
; i
++){
548 for(int j
=0; j
<SAMPLE_COUNT
; j
++){
549 double F_i
= par
[j
][0];
550 double F_r
= par
[j
][1];
551 double A_i
= par
[j
][2];
552 double A_r
= par
[j
][3];
554 if(F_r
< 1){F_r
= 1;}
555 double f
= F_i
- i
/F_r
;
558 if(A_r
< 1){A_r
= 1;}
559 double A
= A_i
- i
/A_r
;
564 E
= -cos((i
/64.0) * PI2
/ 2)/2+0.5;
567 S
->samples
[j
][i
] = E
*A
*sin(i
*f
*K
);
579 tau2 = 0.0001 / (1 + i/50.0)
580 alpha2 = tau2 / (tau2 + dt)
581 A = 0.2 - (i/10000.0)
589 for(int i
=0; i
<SAMPLE_LENGTH
; i
++){
591 float tau1
= (i
/200.0)*0.0001;
592 float alpha1
= dt
/(tau1
+dt
);
594 float tau2
= 0.0001 / (1 + i
/50.0);
595 float alpha2
= tau2
/(tau2
+dt
);
597 float y
= RAND_SIGNAL();
599 //y = y_l0 + alpha1*(y - y_l0);
603 y
= alpha2
*(y
- y_h0
+ y_h1
);
607 float A
= 0.2 - (i
/10000.0);
612 E
= -cos((i
/64.0) * PI2
/ 2)/2+0.5;
615 S
->samples
[15][i
] = A
*E
*y
;
623 void orgux_free(orgux_state
* S
){