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.
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
];
59 char sequence
[SEQUENCE_MAX
][5];
69 int command_queue
[512][5]; /* sample type chan val1 val2 */
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
];
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
){
104 if(i
== MAX_NOTES
) return;
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
;
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]);
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;
153 S
->pan_l
[chan
] = 1.0f
- P
;
154 S
->pan_r
[chan
] = 1.0f
;
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
){
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]);
200 int jmax
= S
->note_max
;
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
]){
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
;
225 note_swap(S
, j
, S
->note_max
-1);
236 int I
= S
->instrument
[S
->note_channel
[j
]];
237 /* hard computations */
238 /* float x = S->wave_ptr[j];
240 float x2 = x1 + 1.0f;
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
;
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);
266 switch(S
->antipop_flag
[j
]){
268 y
*= antipop
[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;
277 y
*= antipop
[S
->antipop_ptr
[j
]];
279 if(S
->antipop_ptr
[j
] < 0){
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);
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
){
332 switch(midi
[0]&0xf0){
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]);
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];
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];
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);
397 orgux_note_on(S
, chan
, val1
, val2
);
400 orgux_note_off(S
, chan
, val1
);
403 orgux_change_instrument(S
, chan
, val1
);
407 orgux_change_volume(S
, chan
, val2
);
410 orgux_change_pan(S
, chan
, val2
);
414 orgux_pitch_bend(S
, chan
, bend
);
421 orgux_state
* orgux_init(int sample_rate
){
422 orgux_state
* S
= malloc(sizeof(orgux_state
));
427 /*precompute waveforms*/
430 precompute(sample_rate
);
435 /* setup oscillator states */
437 for(int i
=0; i
<16; i
++){
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;
448 S
->sample_ptr
[i
] = 0;
452 S
->sample_rate
= sample_rate
;
454 S
->command_count
= 0;
459 //S->lp_alpha = dt/(dt+0.001);
465 void orgux_free(orgux_state
* 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
;
482 void orgux_seq_sort(orgux_state
* S
){