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)
45 #define SQUARE_BASE 129
46 #define TRIANGLE_BASE 130
50 int precompute_ok
= 0;
51 float square_wave
[WAVEFORM_LENGTH
];
52 float saw_wave
[WAVEFORM_LENGTH
];
53 float triangle_wave
[WAVEFORM_LENGTH
];
55 float linterp(float x
, int k
, float wave
[]){
56 int X0
= (int)floor(x
-floor(x
/WAVEFORM_LENGTH
));
58 if(X1
== WAVEFORM_LENGTH
) X1
= 0;
62 float m
= (y1
-y0
)/(X1
-X0
);
75 //float velocity[16][128];
76 unsigned char onbits
[16][16];
78 float waveform
[128][WAVEFORM_LENGTH
];
79 float antipop
[ANTIPOP_LENGTH
];
80 //float wave_ptr[16][128];
81 //float wave_step[16][128];
83 //int env_ptr[16][128];
84 //int env_flag[16][128];
86 //need to redo the samples
87 float samples
[SAMPLE_COUNT
][SAMPLE_LENGTH
];
88 //int sample_ptr[SAMPLE_COUNT];
89 //int sample_on[SAMPLE_COUNT];
90 //float sample_velocity[SAMPLE_COUNT];
95 int command_queue
[512][5]; /* sample type chan val1 val2 */
98 int note_on
[MAX_NOTES
];
99 int note_channel
[MAX_NOTES
];
100 int note_note
[MAX_NOTES
];
101 float velocity
[MAX_NOTES
];
102 int antipop_flag
[MAX_NOTES
];
103 int antipop_ptr
[MAX_NOTES
];
104 float wave_ptr
[MAX_NOTES
];
105 float wave_step
[MAX_NOTES
];
106 int sample_ptr
[MAX_NOTES
];
107 float lp_y
[MAX_NOTES
];
111 void orgux_note_on(orgux_state
* S
, int chan
, int note
, int velocity
){
113 for(int i
=0; i
< MAX_NOTES
; i
++){
114 if(S
->note_on
[i
] == 0){
116 S
->note_channel
[i
] = chan
;
117 S
->note_note
[i
] = note
;
118 S
->velocity
[i
] = ((float)velocity
)/127;
119 S
->antipop_flag
[i
] = -1;
120 S
->antipop_ptr
[i
] = 0;
121 S
->wave_ptr
[i
] = 0.0f
;
122 S
->sample_ptr
[i
] = 0;
123 //S->wave_step[i] = (int)((440*pow(2,(note-69)/12.0)*WAVEFORM_LENGTH)/S->sample_rate);
124 S
->wave_step
[i
] = (440*pow(2,(note
-69)/12.0)*WAVEFORM_LENGTH
)/S
->sample_rate
;
125 if(i
== S
->note_max
){
134 void orgux_note_off(orgux_state
* S
, int chan
, int note
){
136 for(int i
=0; i
< S
->note_max
; i
++){
137 if(S
->note_on
[i
]==1 && S
->note_channel
[i
]==chan
&& S
->note_note
[i
]==note
&& S
->antipop_flag
[i
]<1){
139 //S->note_on[i][1] = chan;
140 //S->note_on[i][2] = note;
141 S
->antipop_flag
[i
] = 1;
142 //S->wave_ptr[i] = 0.0f;
143 //S->wave_step[i] = (440*pow(2,(note-57)/12.0)*WAVEFORM_LENGTH)/S->sample_rate;
151 void orgux_change_volume(orgux_state
* S
, int chan
, int value
){
152 //printf("change volume %d %d\n", chan, value);
153 S
->volume
[chan
] = ((float)value
)/127;
156 void orgux_change_pan(orgux_state
* S
, int chan
, int value
){
157 //printf("change pan %d %d\n", chan, value);
158 float P
= (((float)value
)/127) * 2 - 1;
161 S
->pan_l
[chan
] = 1.0f
- P
;
162 S
->pan_r
[chan
] = 1.0f
;
165 S
->pan_l
[chan
] = 1.0f
;
166 S
->pan_r
[chan
] = P
+ 1.0f
;
170 void orgux_change_instrument(orgux_state
* S
, int chan
, int value
){
171 //printf("change instrument %d %d\n", chan, value);
172 S
->instrument
[chan
] = value
;
175 void orgux_pitch_bend(orgux_state
* S
, int chan
, int bend
){
176 S
->bend
[chan
] = ((((float)bend
)/16383) * 2 - 1) * 1;
180 void orgux_process(orgux_state
* S
, float* lbuf
, float* rbuf
, int len
){
183 /* determine on notes, dont search each time */
184 int note_ons
[MAX_NOTES
];
186 for(int i
=0; i
<S
->note_max
; i
++){
193 for(int i
=0; i
<len
; i
++){
195 while(i
== S
->command_queue
[C
][0] && C
< S
->command_count
){
196 orgux_control(S
, S
->command_queue
[C
][1],
197 S
->command_queue
[C
][2],
198 S
->command_queue
[C
][3],
199 S
->command_queue
[C
][4]);
207 //render playing samples
208 /*for(int j = 0; j<SAMPLE_COUNT; j++){
209 if(!S->sample_on[j]) continue;
210 float y = S->samples[j][S->sample_ptr[j]++];
211 if(S->sample_ptr[j] == SAMPLE_LENGTH){
214 float V = S->volume[9];
215 float A = S->sample_velocity[j];
216 lbuf[i] += V*A*S->pan_l[9]*y;
217 rbuf[i] += V*A*S->pan_r[9]*y;
221 int jmax
= S
->note_max
;
222 for(int j
=0; j
< jmax
; j
++){
223 //for(int n=0; n < N; n++){
224 //int j = note_ons[n];
226 if(!S
->note_on
[j
]) continue;
228 if(S
->note_channel
[j
] == 9){
229 int index
= S
->note_note
[j
] - SAMPLE_NOTE_ZERO
;
230 if(index
< 0){index
=0;}
231 if(index
>= SAMPLE_COUNT
){index
=SAMPLE_COUNT
-1;}
232 float y
= S
->samples
[index
][S
->sample_ptr
[j
]++];
233 if(S
->sample_ptr
[j
] == SAMPLE_LENGTH
){
237 float V
= S
->volume
[9];
238 float A
= S
->velocity
[j
];
239 lbuf
[i
] += V
*A
*S
->pan_l
[9]*y
;
240 rbuf
[i
] += V
*A
*S
->pan_r
[9]*y
;
245 /* hard computations */
246 float x
= S
->wave_ptr
[j
];
248 float x2
= x1
+ 1.0f
;
251 if(X2
== WAVEFORM_LENGTH
) X2
= 0;
252 int I
= S
->instrument
[S
->note_channel
[j
]];
253 float y1
= S
->waveform
[I
][X1
];
254 float y2
= S
->waveform
[I
][X2
];
255 float m
= (y2
-y1
)/(x2
-x1
);
256 float y
= m
*(x
-x1
) + y1
;
261 int I = S->instrument[S->note_channel[j]];
262 int X = S->wave_ptr[j];
263 float y = S->waveform[I][X];
266 //float y0 = S->lp_y[j];
267 //y = y0 + S->lp_alpha * (y - y0);
270 switch(S
->antipop_flag
[j
]){
272 y
*= S
->antipop
[S
->antipop_ptr
[j
]];
275 if(S
->antipop_ptr
[j
] == ANTIPOP_LENGTH
){
276 S
->antipop_ptr
[j
] = ANTIPOP_LENGTH
-1;
277 S
->antipop_flag
[j
] = 0;
281 y
*= S
->antipop
[S
->antipop_ptr
[j
]];
283 if(S
->antipop_ptr
[j
] < 0){
284 //printf("note dead! j = %d, max = %d\n",j, S->note_max);
285 S
->antipop_flag
[j
] = 0;
287 if(j
+1==S
->note_max
){
295 int chan
= S
->note_channel
[j
];
296 float volume
= S
->volume
[chan
];
297 float velocity
= S
->velocity
[j
];
298 lbuf
[i
] += volume
*velocity
*S
->pan_l
[chan
]*y
;
299 rbuf
[i
] += volume
*velocity
*S
->pan_r
[chan
]*y
;
301 if(lbuf
[i
]> 1.0 || lbuf
[i
] < -1.0){
302 printf("ehh lbuf[%d] = %f\n",i
,lbuf
[i
]);
303 printf("%f %f %f %f %f\n",y
,volume
, velocity
, S
->pan_l
[chan
], S
->pan_r
[chan
]);
306 S
->wave_ptr
[j
] += S
->wave_step
[j
];
307 while(S
->wave_ptr
[j
] >= WAVEFORM_LENGTH
){
308 S
->wave_ptr
[j
] -= WAVEFORM_LENGTH
;
315 S
->command_count
= 0;
322 void orgux_schedule(orgux_state
* S
, int sample
, unsigned char midi
[3]){
323 //orgux_control(S, midi[0]&0xf0, midi[0]&0x0f, midi[1], midi[2]);
325 if(S
->command_count
== MAX_COMMANDS
){
329 switch(midi
[0]&0xf0){
335 the queue is sorted by time (sample)
336 soonest times are to the beginning of the queue
337 queue[0] is the first element
338 insert: move all later events right one
341 //printf("schedule %d %x %x %x\n",sample,midi[0],midi[1],midi[2]);
343 for(i
=0; i
<S
->command_count
; i
++){
345 if(sample
< S
->command_queue
[i
][0]){
347 for(int j
=S
->command_count
; j
>i
; j
--){
348 S
->command_queue
[j
][0] = S
->command_queue
[j
-1][0];
349 S
->command_queue
[j
][1] = S
->command_queue
[j
-1][1];
350 S
->command_queue
[j
][2] = S
->command_queue
[j
-1][2];
351 S
->command_queue
[j
][3] = S
->command_queue
[j
-1][3];
352 S
->command_queue
[j
][4] = S
->command_queue
[j
-1][4];
355 S
->command_queue
[i
][0] = sample
;
356 S
->command_queue
[i
][1] = midi
[0]&0xf0;
357 S
->command_queue
[i
][2] = midi
[0]&0x0f;
358 S
->command_queue
[i
][3] = midi
[1];
359 S
->command_queue
[i
][4] = midi
[2];
365 if(i
==S
->command_count
){//end of queue
366 S
->command_queue
[i
][0] = sample
;
367 S
->command_queue
[i
][1] = midi
[0]&0xf0;
368 S
->command_queue
[i
][2] = midi
[0]&0x0f;
369 S
->command_queue
[i
][3] = midi
[1];
370 S
->command_queue
[i
][4] = midi
[2];
375 for(int i
=0; i
<S
->command_count
; i
++){
376 /*printf("%d %d %d %d %d\n",
377 S->command_queue[i][0],
378 S->command_queue[i][1],
379 S->command_queue[i][2],
380 S->command_queue[i][3],
381 S->command_queue[i][4]);
387 void orgux_control(orgux_state
* S
, int type
, int chan
, int val1
, int val2
){
389 int bend
= (val1
<< 7) + val2
;
391 //printf("control %d %d %d %d\n", chan, type, val1, val2);
395 orgux_note_on(S
, chan
, val1
, val2
);
398 orgux_note_off(S
, chan
, val1
);
401 orgux_change_instrument(S
, chan
, val1
);
405 orgux_change_volume(S
, chan
, val2
);
408 orgux_change_pan(S
, chan
, val2
);
412 printf("pitch bend %d\n",bend
);
413 orgux_pitch_bend(S
, chan
, bend
);
420 orgux_state
* orgux_init(int sample_rate
){
421 orgux_state
* S
= malloc(sizeof(orgux_state
));
424 float dt
= 1.0/sample_rate
;
426 /*precompute square, saw, and triangle wave*/
428 for(int i
=0; i
<WAVEFORM_LENGTH
; i
++){
430 triangle_wave
[i
] = 0;
432 for(int j
=0; j
<7; j
++){
433 square_wave
[i
] += (4/PI
)*sin(i
*(2*j
+1)*PI2
/WAVEFORM_LENGTH
)/(2*j
+1);
434 triangle_wave
[i
] += (8/(PI
*PI
))*(j
&1?1:-1)*sin(i
*(2*j
+1)*PI2
/WAVEFORM_LENGTH
)/((2*j
+1)*(2*j
+1));
435 saw_wave
[i
] += (2/PI
)*sin(i
*j
*PI2
/WAVEFORM_LENGTH
)/j
;
440 /* setup oscillator states */
442 for(int i
=0; i
<16; i
++){
448 for(int i
=0; i
<MAX_NOTES
; i
++){
449 S
->wave_ptr
[i
] = 0.0f
;
450 S
->antipop_ptr
[i
] = 0;
451 S
->antipop_flag
[i
] = 0;
453 S
->sample_ptr
[i
] = 0;
457 //for(int i=0; i<SAMPLE_COUNT; i++){
458 // S->sample_on[i] = 0;
459 // S->sample_ptr[i] = 0;
462 S
->sample_rate
= sample_rate
;
464 S
->command_count
= 0;
467 S
->lp_alpha
= dt
/(dt
+0.001);
469 /* setup wave tables */
471 for(int i
=0; i
<128; i
++){
476 for(int j
=0; j
<BASIS_COUNT
; j
++){
477 if(spectra
[i
][j
] > max
){ max
= spectra
[i
][j
]; }
481 for(int j
=0; j
<WAVEFORM_LENGTH
; j
++){
482 S
->waveform
[i
][j
] = 0.0f
;
484 for(int k
=0; k
<BASIS_COUNT
; k
++){
485 float M
= ((float)spectra
[i
][k
])/max
;
491 case SINE_BASE
: y
= sin(j
*(1<<k
)*PI2
/WAVEFORM_LENGTH
); break;
492 //case SQUARE_BASE: y = ((2*j*(1<<k)/WAVEFORM_LENGTH)&1)?1:-1; break;
493 case SQUARE_BASE
: y
= linterp(j
,k
,square_wave
); break;
494 case TRIANGLE_BASE
: y
= linterp(j
,k
,triangle_wave
); break;
495 case SAW_BASE
: y
= linterp(j
,k
,saw_wave
); break;
496 default: y
= 0;//use previously defined waveform
499 S
->waveform
[i
][j
] += M
* y
;
501 if(N
>0){ S
->waveform
[i
][j
] /= N
*10; }
502 //if(S->waveform[i][j] > max){ max = S->waveform[i][j]; }
504 //printf("max[%d] = %f, %d\n",i,max, N);
507 //generate antipop cosine
508 for(int i
=0; i
<ANTIPOP_LENGTH
; i
++){
509 S
->antipop
[i
] = -cos(i
*PI2
/(2.0*ANTIPOP_LENGTH
))/2.0+0.5;
515 float par
[16][8] = {/**/
516 {50, 500, 0.5, 10000, 0, 0, 0, 0},
517 {200, 200, 0.5, 10000, 0, 0, 0, 0},
518 {100, 500, 0.5, 10000, 0, 0, 0, 0},
519 {100, 1000, 0.5, 10000, 0, 0, 0, 0},
521 {100, 500, 0.5, 3000, 0, 0, 0, 0},
522 {200, 500, 0.5, 3000, 0, 0, 0, 0},
523 {300, 500, 0.5, 3000, 0, 0, 0, 0},
524 {400, 500, 0.5, 3000, 0, 0, 0, 0},
526 {400, 200, 0.5, 3000, 0, 0, 0, 0},
527 {400, 100, 0.5, 3000, 0, 0, 0, 0},
528 {400, 50, 0.5, 3000, 0, 0, 0, 0},
529 {400, 20, 0.5, 3000, 0, 0, 0, 0},
531 {100, 500, 0.5, 10000, 0, 0, 0, 0},
532 {100, 500, 0.5, 10000, 0, 0, 0, 0},
533 {100, 500, 0.5, 10000, 0, 0, 0, 0},
534 {100, 500, 0.5, 10000, 0, 0, 0, 0}
537 double K
= PI2
/ sample_rate
;
539 for(int i
=0; i
<SAMPLE_LENGTH
; i
++){
540 for(int j
=0; j
<SAMPLE_COUNT
; j
++){
541 double F_i
= par
[j
][0];
542 double F_r
= par
[j
][1];
543 double A_i
= par
[j
][2];
544 double A_r
= par
[j
][3];
546 if(F_r
< 1){F_r
= 1;}
547 double f
= F_i
- i
/F_r
;
550 if(A_r
< 1){A_r
= 1;}
551 double A
= A_i
- i
/A_r
;
556 E
= -cos((i
/64.0) * PI2
/ 2)/2+0.5;
559 S
->samples
[j
][i
] = E
*A
*sin(i
*f
*K
);
571 tau2 = 0.0001 / (1 + i/50.0)
572 alpha2 = tau2 / (tau2 + dt)
573 A = 0.2 - (i/10000.0)
581 for(int i
=0; i
<SAMPLE_LENGTH
; i
++){
583 float tau1
= (i
/200.0)*0.0001;
584 float alpha1
= dt
/(tau1
+dt
);
586 float tau2
= 0.0001 / (1 + i
/50.0);
587 float alpha2
= tau2
/(tau2
+dt
);
589 float y
= (RANDF()*2 - 1);
591 //y = y_l0 + alpha1*(y - y_l0);
595 y
= alpha2
*(y
- y_h0
+ y_h1
);
599 float A
= 0.2 - (i
/10000.0);
604 E
= -cos((i
/64.0) * PI2
/ 2)/2+0.5;
607 S
->samples
[15][i
] = A
*E
*y
;
615 void orgux_free(orgux_state
* S
){