More work on loading and playing midi files.
[orgux.git] / core.c
blobad941ab275014fb7094d81ef7fd98c64be98a129
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>
26 #include "orgux.h"
28 #include "constants.h"
29 #include "instruments.h"
35 extern void precompute(int sample_rate);
36 int precompute_ok = 0;
40 float square_wave[WAVEFORM_LENGTH];
41 float saw_wave[WAVEFORM_LENGTH];
42 float triangle_wave[WAVEFORM_LENGTH];
44 float waveform[128][WAVEFORM_LENGTH];
45 float waveform_M[128][WAVEFORM_LENGTH];
46 float waveform_Z[128][WAVEFORM_LENGTH];
48 float samples[SAMPLE_COUNT][SAMPLE_LENGTH];
49 int sample_len[SAMPLE_COUNT];
50 float antipop[ANTIPOP_LENGTH];
52 struct orgux_state{
53 float volume[16];
54 float pan_l[16];
55 float pan_r[16];
56 float bend[16];
57 int instrument[16];
59 int sequence[SEQUENCE_MAX];
60 unsigned char seq_events[SEQUENCE_MAX][3];
61 int seq_en;
62 int seq_ptr;
63 int seq_len;
64 int seq_tick;
65 int seq_samples;
66 int loop_start;
67 int loop_end;
69 int sample_rate;
70 float lp_alpha;
72 int command_queue[512][5]; /* sample type chan val1 val2 */
73 int command_count;
75 int note_on[MAX_NOTES];
76 int note_channel[MAX_NOTES];
77 int note_note[MAX_NOTES];
78 float velocity[MAX_NOTES];
79 int antipop_flag[MAX_NOTES];
80 int antipop_ptr[MAX_NOTES];
81 float wave_ptr[MAX_NOTES];
82 float wave_step[MAX_NOTES];
83 int sample_ptr[MAX_NOTES];
84 float lp_y[MAX_NOTES];
85 int note_max;
88 #define SWAP(X,Y,T) {T tmp = X; X = Y; Y = tmp;}
89 void note_swap(orgux_state* S, int i1, int i2){
91 SWAP(S->note_on[i1], S->note_on[i2], int);
92 SWAP(S->note_channel[i1], S->note_channel[i2], int);
93 SWAP(S->note_note[i1], S->note_note[i2], int);
94 SWAP(S->velocity[i1], S->velocity[i2], float);
95 SWAP(S->antipop_flag[i1], S->antipop_flag[i2], int);
96 SWAP(S->antipop_ptr[i1], S->antipop_ptr[i2], int);
97 SWAP(S->wave_ptr[i1], S->wave_ptr[i2], float);
98 SWAP(S->wave_step[i1], S->wave_step[i2], float);
99 SWAP(S->sample_ptr[i1], S->sample_ptr[i2], int);
103 void orgux_note_on(orgux_state* S, int chan, int note, int velocity){
105 int i=S->note_max;
107 if(i == MAX_NOTES) return;
109 S->note_on[i] = 1;
110 S->note_channel[i] = chan;
111 S->note_note[i] = note;
112 S->velocity[i] = ((float)velocity)/127;
113 S->antipop_flag[i] = -1;
114 S->antipop_ptr[i] = 0;
115 S->wave_ptr[i] = 0.0f;
116 S->sample_ptr[i] = 0;
117 //S->wave_step[i] = (int)((440*pow(2,(note-69)/12.0)*WAVEFORM_LENGTH)/S->sample_rate);
118 S->wave_step[i] = (440*pow(2,(note-69)/12.0)*WAVEFORM_LENGTH)/S->sample_rate;
119 S->note_max++;
121 //printf("note on i=%d\n",i);
122 for(int j=0; j<S->note_max; j++){
123 //printf("[%d %d %d %d]\n",S->note_on[j], S->note_channel[j], S->note_note[j], S->antipop_flag[j]);
128 void orgux_note_off(orgux_state* S, int chan, int note){
130 for(int i=0; i < S->note_max; i++){
131 if(S->note_on[i]==1 && S->note_channel[i]==chan && S->note_note[i]==note && S->antipop_flag[i]<1){
133 S->antipop_flag[i] = 1;
135 //printf("note end\n");
136 for(int j=0; j<S->note_max; j++){
137 //printf("[%d %d %d %d]\n",S->note_on[j], S->note_channel[j], S->note_note[j], S->antipop_flag[j]);
140 break;
146 void orgux_change_volume(orgux_state* S, int chan, int value){
147 //printf("change volume %d %d\n", chan, value);
148 S->volume[chan] = ((float)value)/127;
151 void orgux_change_pan(orgux_state* S, int chan, int value){
152 //printf("change pan %d %d\n", chan, value);
153 float P = (((float)value)/127) * 2 - 1;
155 if(P > 0){
156 S->pan_l[chan] = 1.0f - P;
157 S->pan_r[chan] = 1.0f;
159 else{
160 S->pan_l[chan] = 1.0f;
161 S->pan_r[chan] = P + 1.0f;
165 void orgux_change_instrument(orgux_state* S, int chan, int value){
166 //printf("change instrument %d %d\n", chan, value);
167 S->instrument[chan] = value;
170 void orgux_pitch_bend(orgux_state* S, int chan, int bend){
171 S->bend[chan] = ((((float)bend)/16383) * 2 - 1) * 1;
177 void orgux_process(orgux_state* S, float* lbuf, float* rbuf, int len){
179 int C=0;
181 int swap_ok = 0;
183 if(S->seq_en){//schedule some events
185 double ticks_per_period = len*ticks_per_sample;
186 double next_tick = cur_tick + ticks_per_period;
188 double samples_per_tick = 1;
190 while(S->sequence[S->seq_ptr] <= next_tick){
191 int N = S->seq_ptr;
192 int target_sample = samples_per_tick*(S->sequence[N] - cur_tick);
193 orgux_schedule(S, target_sample, S->seq_events[N]);
194 S->seq_ptr++;
195 if(S->seq_ptr == S->seq_len){
196 S->seq_en = 0;
197 break;
201 cur_tick = next_tick;
205 for(int i=0; i<len; i++){
207 while(i == S->command_queue[C][0] && C < S->command_count){
208 orgux_control(S, S->command_queue[C][1],
209 S->command_queue[C][2],
210 S->command_queue[C][3],
211 S->command_queue[C][4]);
212 C++;
215 lbuf[i] = 0.0f;
216 rbuf[i] = 0.0f;
218 int jmax = S->note_max;
219 for(int j=0; ;j++){
221 if(j >= jmax) break;
223 if(!S->note_on[j]) continue;
225 if(S->note_channel[j] == 9){
226 int index = S->note_note[j] - SAMPLE_NOTE_ZERO;
227 if(index < 0){index=0;}
228 if(index >= SAMPLE_COUNT){index=SAMPLE_COUNT-1;}
229 float y = samples[index][S->sample_ptr[j]++];
230 if(S->sample_ptr[j] == SAMPLE_LENGTH || S->sample_ptr[j] == sample_len[j]){
231 swap_ok = 1;
234 float V = S->volume[9];
235 float A = S->velocity[j];
236 lbuf[i] += V*A*S->pan_l[9]*y;
237 rbuf[i] += V*A*S->pan_r[9]*y;
239 //lbuf[i] += y;
240 //rbuf[i] += y;
242 if(swap_ok){
243 note_swap(S, j, S->note_max-1);
244 S->note_max--;
245 j--;
246 jmax--;
247 swap_ok = 0;
250 continue;
252 //continue;
254 int I = S->instrument[S->note_channel[j]];
255 /* hard computations */
256 /* float x = S->wave_ptr[j];
257 float x1 = floor(x);
258 float x2 = x1 + 1.0f;
259 int X1 = (int)x1;
260 int X2 = X1 + 1;
261 if(X2 == WAVEFORM_LENGTH) X2 = 0;
262 float y1 = waveform[I][X1];
263 float y2 = waveform[I][X2];
264 float m = (y2-y1)/(x2-x1);
265 float y = m*(x-x1) + y1;
268 float x = S->wave_ptr[j];
269 int X0 = (int)floor(x);
270 float y = waveform_Z[I][X0] + waveform_M[I][X0]*x;
272 //float y = 0;
275 int I = S->instrument[S->note_channel[j]];
276 int X = S->wave_ptr[j];
277 float y = S->waveform[I][X];
280 //float y0 = S->lp_y[j];
281 //y = y0 + S->lp_alpha * (y - y0);
282 //S->lp_y[j] = y;
284 switch(S->antipop_flag[j]){
285 case -1:
286 y *= antipop[S->antipop_ptr[j]];
287 S->antipop_ptr[j]++;
289 if(S->antipop_ptr[j] == ANTIPOP_LENGTH){
290 S->antipop_ptr[j] = ANTIPOP_LENGTH-1;
291 S->antipop_flag[j] = 0;
293 break;
294 case 1:
295 y *= antipop[S->antipop_ptr[j]];
296 S->antipop_ptr[j]--;
297 if(S->antipop_ptr[j] < 0){
298 swap_ok = 1;
300 break;
304 int chan = S->note_channel[j];
305 float volume = S->volume[chan];
306 float velocity = S->velocity[j];
307 lbuf[i] += volume*velocity*S->pan_l[chan]*y;
308 rbuf[i] += volume*velocity*S->pan_r[chan]*y;
310 if(lbuf[i]> 1.0 || lbuf[i] < -1.0){
311 printf("ehh lbuf[%d] = %f\n",i,lbuf[i]);
312 printf("%f %f %f %f %f\n",y,volume, velocity, S->pan_l[chan], S->pan_r[chan]);
315 S->wave_ptr[j] += S->wave_step[j];
316 while(S->wave_ptr[j] >= WAVEFORM_LENGTH){
317 S->wave_ptr[j] -= WAVEFORM_LENGTH;
320 if(swap_ok){ /* kills note */
321 note_swap(S, j, S->note_max-1);
322 S->note_max--;
323 j--;
324 jmax--;
325 swap_ok = 0;
326 //printf("note off\n");
327 for(int z=0; z<S->note_max; z++){
328 //printf("[%d %d %d %d]\n",S->note_on[z], S->note_channel[z], S->note_note[z], S->antipop_flag[z]);
336 S->command_count = 0;
343 void orgux_schedule(orgux_state* S, int sample, unsigned char midi[3]){
344 //orgux_control(S, midi[0]&0xf0, midi[0]&0x0f, midi[1], midi[2]);
346 if(S->command_count == MAX_COMMANDS){
347 return;
350 switch(midi[0]&0xf0){
351 case 0xA0:
352 case 0xD0:
353 return;
356 the queue is sorted by time (sample)
357 soonest times are to the beginning of the queue
358 queue[0] is the first element
359 insert: move all later events right one
362 //printf("schedule %d %x %x %x\n",sample,midi[0],midi[1],midi[2]);
363 int i;
364 for(i=0; i<S->command_count; i++){
366 if(sample < S->command_queue[i][0]){
368 for(int j=S->command_count; j>i; j--){
369 S->command_queue[j][0] = S->command_queue[j-1][0];
370 S->command_queue[j][1] = S->command_queue[j-1][1];
371 S->command_queue[j][2] = S->command_queue[j-1][2];
372 S->command_queue[j][3] = S->command_queue[j-1][3];
373 S->command_queue[j][4] = S->command_queue[j-1][4];
376 S->command_queue[i][0] = sample;
377 S->command_queue[i][1] = midi[0]&0xf0;
378 S->command_queue[i][2] = midi[0]&0x0f;
379 S->command_queue[i][3] = midi[1];
380 S->command_queue[i][4] = midi[2];
382 break;
386 if(i==S->command_count){//end of queue
387 S->command_queue[i][0] = sample;
388 S->command_queue[i][1] = midi[0]&0xf0;
389 S->command_queue[i][2] = midi[0]&0x0f;
390 S->command_queue[i][3] = midi[1];
391 S->command_queue[i][4] = midi[2];
394 S->command_count++;
395 /*for(int i=0; i<S->command_count; i++){
396 printf("%d %d %d %d %d\n",
397 S->command_queue[i][0],
398 S->command_queue[i][1],
399 S->command_queue[i][2],
400 S->command_queue[i][3],
401 S->command_queue[i][4]);
407 void orgux_control(orgux_state* S, int type, int chan, int val1, int val2){
409 int bend = (val1 << 7) + val2;
411 //printf("control %d %d %d %d\n", chan, type, val1, val2);
413 switch(type){
414 case 0x90:
415 orgux_note_on(S, chan, val1, val2);
416 return;
417 case 0x80:
418 orgux_note_off(S, chan, val1);
419 return;
420 case 0xC0:
421 orgux_change_instrument(S, chan, val1);
422 return;
423 case 0xB0:
424 if(val1 == 7){
425 orgux_change_volume(S, chan, val2);
427 else if(val1 == 10){
428 orgux_change_pan(S, chan, val2);
430 return;
431 case 0xE0:
432 orgux_pitch_bend(S, chan, bend);
433 return;
439 orgux_state* orgux_init(int sample_rate){
440 orgux_state* S = malloc(sizeof(orgux_state));
441 if(!S) return NULL;
445 /*precompute waveforms*/
446 if(!precompute_ok){
448 precompute(sample_rate);
449 precompute_ok = 1;
453 /* setup oscillator states */
455 for(int i=0; i<16; i++){
456 S->volume[i] = 1.0f;
457 S->pan_l[i] = 1.0f;
458 S->pan_r[i] = 1.0f;
461 for(int i=0; i<MAX_NOTES; i++){
462 S->wave_ptr[i] = 0.0f;
463 S->antipop_ptr[i] = 0;
464 S->antipop_flag[i] = 0;
465 S->note_on[i] = 0;
466 S->sample_ptr[i] = 0;
467 S->lp_y[i] = 0;
470 S->sample_rate = sample_rate;
472 S->command_count = 0;
473 S->note_max = 0;
475 S->seq_en = 0;
477 //S->lp_alpha = dt/(dt+0.001);
479 return S;
483 void orgux_free(orgux_state* S){
484 free(S);
489 void orgux_seq_append(orgux_state* S, int tick, int type, int chan, int val1, int val2){
490 if(S->seq_len == SEQUENCE_MAX) return;
492 S->sequence[S->seq_len] = tick;
493 S->seq_events[S->seq_len][0] = type | chan;
494 S->seq_events[S->seq_len][1] = val1;
495 S->seq_events[S->seq_len][2] = val2;
496 S->seq_len++;
499 void orgux_seq_sort(orgux_state* S){
501 for(int i=0; i<S->seq_len; i++){
502 printf("%d: %d %x %d %d\n",i, S->sequence[i], S->seq_events[i][0], S->seq_events[i][1], S->seq_events[i][2]);
507 void orgux_play(orgux_state* S, int yesno){
508 S->seq_en = yesno;