Enabled alternative bases.
[orgux.git] / core.c
blobc921989d3bd528de5ba92d74c2a2583739c60087
1 /*
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.
20 #include <stdio.h>
21 #include <math.h>
22 #include <stdlib.h>
24 #define PI 3.141592653589
25 #define PI2 PI*2
27 #include "orgux.h"
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
40 #define MAX_NOTES 128
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[]){
53 float X = x*k;
54 float Xw = X - WAVEFORM_LENGTH*floor(X/WAVEFORM_LENGTH);
55 int X0 = floor(Xw);
56 int X1 = X0+1;
57 if(X1 == WAVEFORM_LENGTH) X1 = 0;
59 float y1 = wave[X1];
60 float y0 = wave[X0];
61 float m = (y1-y0)/(X1-X0);
63 return m*(x-X0)+y0;
67 struct orgux_state{
68 float volume[16];
69 float pan_l[16];
70 float pan_r[16];
71 float bend[16];
72 int instrument[16];
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];
91 int sample_rate;
92 float lp_alpha;
94 int command_queue[512][5]; /* sample type chan val1 val2 */
95 int command_count;
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];
107 int note_max;
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){
114 S->note_on[i] = 1;
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){
125 S->note_max++;
127 break;
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;
143 //S->note_count++;
144 break;
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;
159 if(P > 0){
160 S->pan_l[chan] = 1.0f - P;
161 S->pan_r[chan] = 1.0f;
163 else{
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){
180 int C=0;
182 /* determine on notes, dont search each time */
183 int note_ons[MAX_NOTES];
184 int N = 0;
185 for(int i=0; i<S->note_max; i++){
186 if(S->note_on[i]){
187 note_ons[N] = i;
188 N++;
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]);
199 C++;
202 lbuf[i] = 0.0f;
203 rbuf[i] = 0.0f;
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){
211 S->sample_on[j] = 0;
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){
233 S->note_on[j] = 0;
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;
241 continue;
243 //continue;
244 /* hard computations */
245 float x = S->wave_ptr[j];
246 float x1 = floor(x);
247 float x2 = x1 + 1.0f;
248 int X1 = (int)x1;
249 int X2 = X1 + 1;
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;
257 //float y = 0;
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);
267 //S->lp_y[j] = y;
269 switch(S->antipop_flag[j]){
270 case -1:
271 y *= S->antipop[S->antipop_ptr[j]];
272 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;
278 break;
279 case 1:
280 y *= S->antipop[S->antipop_ptr[j]];
281 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;
285 S->note_on[j] = 0;
286 if(j+1==S->note_max){
287 S->note_max--;
290 break;
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){
325 return;
328 switch(midi[0]&0xf0){
329 case 0xA0:
330 case 0xD0:
331 return;
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]);
341 int i;
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];
360 break;
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];
372 S->command_count++;
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);
392 switch(type){
393 case 0x90:
394 orgux_note_on(S, chan, val1, val2);
395 return;
396 case 0x80:
397 orgux_note_off(S, chan, val1);
398 return;
399 case 0xC0:
400 orgux_change_instrument(S, chan, val1);
401 return;
402 case 0xB0:
403 if(val1 == 7){
404 orgux_change_volume(S, chan, val2);
406 else if(val1 == 10){
407 orgux_change_pan(S, chan, val2);
409 return;
410 case 0xE0:
411 printf("pitch bend %d\n",bend);
412 orgux_pitch_bend(S, chan, bend);
413 return;
419 orgux_state* orgux_init(int sample_rate){
420 orgux_state* S = malloc(sizeof(orgux_state));
421 if(!S) return NULL;
423 float dt = 1.0/sample_rate;
429 /*precompute square, saw, and triangle wave*/
430 if(!precompute_ok){
431 for(int i=0; i<WAVEFORM_LENGTH; i++){
432 square_wave[i] = 0;
433 triangle_wave[i] = 0;
434 saw_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++){
446 S->volume[i] = 1.0f;
447 S->pan_l[i] = 1.0f;
448 S->pan_r[i] = 1.0f;
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;
455 S->note_on[i] = 0;
456 S->sample_ptr[i] = 0;
457 S->lp_y[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;
468 S->note_max = 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++){
476 int max = 0;
477 float N = 0;
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;
488 N = 0;
489 for(int k=0; k<HARMONIC_COUNT; k++){
490 float M = ((float)instr_config[i][k])/max;
491 M = M*M;
492 N += M;
494 float y;
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; }
511 printf("\n");
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;
521 //generate samples
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;
556 if(f < 0) f = 0;
558 if(A_r < 1){A_r = 1;}
559 double A = A_i - i/A_r;
560 if(A < 0) A = 0;
562 double E = 1;
563 if(i < 64){
564 E = -cos((i/64.0) * PI2 / 2)/2+0.5;
567 S->samples[j][i] = E*A*sin(i*f*K);
571 float y_l;
572 float y_h0=0;
573 float y_h1=0;
576 notes
578 cool hit
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);
600 //y_l0 = y;
602 float temp = y;
603 y = alpha2*(y - y_h0 + y_h1);
604 y_h0 = temp;
605 y_h1 = y;
607 float A = 0.2 - (i/10000.0);
608 if(A<0) A = 0;
610 double E = 1;
611 if(i < 64){
612 E = -cos((i/64.0) * PI2 / 2)/2+0.5;
615 S->samples[15][i] = A*E*y;
619 return S;
623 void orgux_free(orgux_state* S){
624 free(S);