Added more smf decoding code. Do not use.
[orgux.git] / core.c
blobaf47f05a35858a819d8eb246432583037aab8c2c
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 char sequence[SEQUENCE_MAX][5];
60 int seq_en;
61 int seq_ptr;
62 int seq_len;
63 int seq_tick;
64 int seq_samples;
66 int sample_rate;
67 float lp_alpha;
69 int command_queue[512][5]; /* sample type chan val1 val2 */
70 int command_count;
72 int note_on[MAX_NOTES];
73 int note_channel[MAX_NOTES];
74 int note_note[MAX_NOTES];
75 float velocity[MAX_NOTES];
76 int antipop_flag[MAX_NOTES];
77 int antipop_ptr[MAX_NOTES];
78 float wave_ptr[MAX_NOTES];
79 float wave_step[MAX_NOTES];
80 int sample_ptr[MAX_NOTES];
81 float lp_y[MAX_NOTES];
82 int note_max;
85 #define SWAP(X,Y,T) {T tmp = X; X = Y; Y = tmp;}
86 void note_swap(orgux_state* S, int i1, int i2){
88 SWAP(S->note_on[i1], S->note_on[i2], int);
89 SWAP(S->note_channel[i1], S->note_channel[i2], int);
90 SWAP(S->note_note[i1], S->note_note[i2], int);
91 SWAP(S->velocity[i1], S->velocity[i2], float);
92 SWAP(S->antipop_flag[i1], S->antipop_flag[i2], int);
93 SWAP(S->antipop_ptr[i1], S->antipop_ptr[i2], int);
94 SWAP(S->wave_ptr[i1], S->wave_ptr[i2], float);
95 SWAP(S->wave_step[i1], S->wave_step[i2], float);
96 SWAP(S->sample_ptr[i1], S->sample_ptr[i2], int);
100 void orgux_note_on(orgux_state* S, int chan, int note, int velocity){
102 int i=S->note_max;
104 if(i == MAX_NOTES) return;
106 S->note_on[i] = 1;
107 S->note_channel[i] = chan;
108 S->note_note[i] = note;
109 S->velocity[i] = ((float)velocity)/127;
110 S->antipop_flag[i] = -1;
111 S->antipop_ptr[i] = 0;
112 S->wave_ptr[i] = 0.0f;
113 S->sample_ptr[i] = 0;
114 //S->wave_step[i] = (int)((440*pow(2,(note-69)/12.0)*WAVEFORM_LENGTH)/S->sample_rate);
115 S->wave_step[i] = (440*pow(2,(note-69)/12.0)*WAVEFORM_LENGTH)/S->sample_rate;
116 S->note_max++;
118 //printf("note on i=%d\n",i);
119 for(int j=0; j<S->note_max; j++){
120 //printf("[%d %d %d %d]\n",S->note_on[j], S->note_channel[j], S->note_note[j], S->antipop_flag[j]);
125 void orgux_note_off(orgux_state* S, int chan, int note){
127 for(int i=0; i < S->note_max; i++){
128 if(S->note_on[i]==1 && S->note_channel[i]==chan && S->note_note[i]==note && S->antipop_flag[i]<1){
130 S->antipop_flag[i] = 1;
132 //printf("note end\n");
133 for(int j=0; j<S->note_max; j++){
134 //printf("[%d %d %d %d]\n",S->note_on[j], S->note_channel[j], S->note_note[j], S->antipop_flag[j]);
137 break;
143 void orgux_change_volume(orgux_state* S, int chan, int value){
144 //printf("change volume %d %d\n", chan, value);
145 S->volume[chan] = ((float)value)/127;
148 void orgux_change_pan(orgux_state* S, int chan, int value){
149 //printf("change pan %d %d\n", chan, value);
150 float P = (((float)value)/127) * 2 - 1;
152 if(P > 0){
153 S->pan_l[chan] = 1.0f - P;
154 S->pan_r[chan] = 1.0f;
156 else{
157 S->pan_l[chan] = 1.0f;
158 S->pan_r[chan] = P + 1.0f;
162 void orgux_change_instrument(orgux_state* S, int chan, int value){
163 //printf("change instrument %d %d\n", chan, value);
164 S->instrument[chan] = value;
167 void orgux_pitch_bend(orgux_state* S, int chan, int bend){
168 S->bend[chan] = ((((float)bend)/16383) * 2 - 1) * 1;
174 void orgux_process(orgux_state* S, float* lbuf, float* rbuf, int len){
176 int C=0;
178 int swap_ok = 0;
180 if(S->seq_en){//schedule some events
181 for(int i=0; i<len; i++){
182 //add 1 sample to tick counter
183 //if events should happen, schedule
187 for(int i=0; i<len; i++){
189 while(i == S->command_queue[C][0] && C < S->command_count){
190 orgux_control(S, S->command_queue[C][1],
191 S->command_queue[C][2],
192 S->command_queue[C][3],
193 S->command_queue[C][4]);
194 C++;
197 lbuf[i] = 0.0f;
198 rbuf[i] = 0.0f;
200 int jmax = S->note_max;
201 for(int j=0; ;j++){
203 if(j >= jmax) break;
205 if(!S->note_on[j]) continue;
207 if(S->note_channel[j] == 9){
208 int index = S->note_note[j] - SAMPLE_NOTE_ZERO;
209 if(index < 0){index=0;}
210 if(index >= SAMPLE_COUNT){index=SAMPLE_COUNT-1;}
211 float y = samples[index][S->sample_ptr[j]++];
212 if(S->sample_ptr[j] == SAMPLE_LENGTH || S->sample_ptr[j] == sample_len[j]){
213 swap_ok = 1;
216 float V = S->volume[9];
217 float A = S->velocity[j];
218 lbuf[i] += V*A*S->pan_l[9]*y;
219 rbuf[i] += V*A*S->pan_r[9]*y;
221 //lbuf[i] += y;
222 //rbuf[i] += y;
224 if(swap_ok){
225 note_swap(S, j, S->note_max-1);
226 S->note_max--;
227 j--;
228 jmax--;
229 swap_ok = 0;
232 continue;
234 //continue;
236 int I = S->instrument[S->note_channel[j]];
237 /* hard computations */
238 /* float x = S->wave_ptr[j];
239 float x1 = floor(x);
240 float x2 = x1 + 1.0f;
241 int X1 = (int)x1;
242 int X2 = X1 + 1;
243 if(X2 == WAVEFORM_LENGTH) X2 = 0;
244 float y1 = waveform[I][X1];
245 float y2 = waveform[I][X2];
246 float m = (y2-y1)/(x2-x1);
247 float y = m*(x-x1) + y1;
250 float x = S->wave_ptr[j];
251 int X0 = (int)floor(x);
252 float y = waveform_Z[I][X0] + waveform_M[I][X0]*x;
254 //float y = 0;
257 int I = S->instrument[S->note_channel[j]];
258 int X = S->wave_ptr[j];
259 float y = S->waveform[I][X];
262 //float y0 = S->lp_y[j];
263 //y = y0 + S->lp_alpha * (y - y0);
264 //S->lp_y[j] = y;
266 switch(S->antipop_flag[j]){
267 case -1:
268 y *= antipop[S->antipop_ptr[j]];
269 S->antipop_ptr[j]++;
271 if(S->antipop_ptr[j] == ANTIPOP_LENGTH){
272 S->antipop_ptr[j] = ANTIPOP_LENGTH-1;
273 S->antipop_flag[j] = 0;
275 break;
276 case 1:
277 y *= antipop[S->antipop_ptr[j]];
278 S->antipop_ptr[j]--;
279 if(S->antipop_ptr[j] < 0){
280 swap_ok = 1;
282 break;
286 int chan = S->note_channel[j];
287 float volume = S->volume[chan];
288 float velocity = S->velocity[j];
289 lbuf[i] += volume*velocity*S->pan_l[chan]*y;
290 rbuf[i] += volume*velocity*S->pan_r[chan]*y;
292 if(lbuf[i]> 1.0 || lbuf[i] < -1.0){
293 printf("ehh lbuf[%d] = %f\n",i,lbuf[i]);
294 printf("%f %f %f %f %f\n",y,volume, velocity, S->pan_l[chan], S->pan_r[chan]);
297 S->wave_ptr[j] += S->wave_step[j];
298 while(S->wave_ptr[j] >= WAVEFORM_LENGTH){
299 S->wave_ptr[j] -= WAVEFORM_LENGTH;
302 if(swap_ok){ /* kills note */
303 note_swap(S, j, S->note_max-1);
304 S->note_max--;
305 j--;
306 jmax--;
307 swap_ok = 0;
308 //printf("note off\n");
309 for(int z=0; z<S->note_max; z++){
310 //printf("[%d %d %d %d]\n",S->note_on[z], S->note_channel[z], S->note_note[z], S->antipop_flag[z]);
318 S->command_count = 0;
325 void orgux_schedule(orgux_state* S, int sample, unsigned char midi[3]){
326 //orgux_control(S, midi[0]&0xf0, midi[0]&0x0f, midi[1], midi[2]);
328 if(S->command_count == MAX_COMMANDS){
329 return;
332 switch(midi[0]&0xf0){
333 case 0xA0:
334 case 0xD0:
335 return;
338 the queue is sorted by time (sample)
339 soonest times are to the beginning of the queue
340 queue[0] is the first element
341 insert: move all later events right one
344 //printf("schedule %d %x %x %x\n",sample,midi[0],midi[1],midi[2]);
345 int i;
346 for(i=0; i<S->command_count; i++){
348 if(sample < S->command_queue[i][0]){
350 for(int j=S->command_count; j>i; j--){
351 S->command_queue[j][0] = S->command_queue[j-1][0];
352 S->command_queue[j][1] = S->command_queue[j-1][1];
353 S->command_queue[j][2] = S->command_queue[j-1][2];
354 S->command_queue[j][3] = S->command_queue[j-1][3];
355 S->command_queue[j][4] = S->command_queue[j-1][4];
358 S->command_queue[i][0] = sample;
359 S->command_queue[i][1] = midi[0]&0xf0;
360 S->command_queue[i][2] = midi[0]&0x0f;
361 S->command_queue[i][3] = midi[1];
362 S->command_queue[i][4] = midi[2];
364 break;
368 if(i==S->command_count){//end of queue
369 S->command_queue[i][0] = sample;
370 S->command_queue[i][1] = midi[0]&0xf0;
371 S->command_queue[i][2] = midi[0]&0x0f;
372 S->command_queue[i][3] = midi[1];
373 S->command_queue[i][4] = midi[2];
376 S->command_count++;
377 /*for(int i=0; i<S->command_count; i++){
378 printf("%d %d %d %d %d\n",
379 S->command_queue[i][0],
380 S->command_queue[i][1],
381 S->command_queue[i][2],
382 S->command_queue[i][3],
383 S->command_queue[i][4]);
389 void orgux_control(orgux_state* S, int type, int chan, int val1, int val2){
391 int bend = (val1 << 7) + val2;
393 //printf("control %d %d %d %d\n", chan, type, val1, val2);
395 switch(type){
396 case 0x90:
397 orgux_note_on(S, chan, val1, val2);
398 return;
399 case 0x80:
400 orgux_note_off(S, chan, val1);
401 return;
402 case 0xC0:
403 orgux_change_instrument(S, chan, val1);
404 return;
405 case 0xB0:
406 if(val1 == 7){
407 orgux_change_volume(S, chan, val2);
409 else if(val1 == 10){
410 orgux_change_pan(S, chan, val2);
412 return;
413 case 0xE0:
414 orgux_pitch_bend(S, chan, bend);
415 return;
421 orgux_state* orgux_init(int sample_rate){
422 orgux_state* S = malloc(sizeof(orgux_state));
423 if(!S) return NULL;
427 /*precompute waveforms*/
428 if(!precompute_ok){
430 precompute(sample_rate);
431 precompute_ok = 1;
435 /* setup oscillator states */
437 for(int i=0; i<16; i++){
438 S->volume[i] = 1.0f;
439 S->pan_l[i] = 1.0f;
440 S->pan_r[i] = 1.0f;
443 for(int i=0; i<MAX_NOTES; i++){
444 S->wave_ptr[i] = 0.0f;
445 S->antipop_ptr[i] = 0;
446 S->antipop_flag[i] = 0;
447 S->note_on[i] = 0;
448 S->sample_ptr[i] = 0;
449 S->lp_y[i] = 0;
452 S->sample_rate = sample_rate;
454 S->command_count = 0;
455 S->note_max = 0;
457 S->seq_en = 0;
459 //S->lp_alpha = dt/(dt+0.001);
461 return S;
465 void orgux_free(orgux_state* S){
466 free(S);
471 void orgux_seq_append(orgux_state* S, int tick, int type, int chan, int val1, int val2){
472 if(S->seq_len == SEQUENCE_MAX) return;
474 S->sequence[S->seq_len][0] = tick;
475 S->sequence[S->seq_len][1] = type;
476 S->sequence[S->seq_len][2] = chan;
477 S->sequence[S->seq_len][3] = val1;
478 S->sequence[S->seq_len][4] = val2;
479 S->seq_len++;
482 void orgux_seq_sort(orgux_state* S){