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 int sequence
[SEQUENCE_MAX
];
60 unsigned char seq_events
[SEQUENCE_MAX
][3];
72 int command_queue
[512][5]; /* sample type chan val1 val2 */
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
];
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
){
107 if(i
== MAX_NOTES
) return;
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
;
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]);
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;
156 S
->pan_l
[chan
] = 1.0f
- P
;
157 S
->pan_r
[chan
] = 1.0f
;
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
){
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){
192 int target_sample = samples_per_tick*(S->sequence[N] - cur_tick);
193 orgux_schedule(S, target_sample, S->seq_events[N]);
195 if(S->seq_ptr == S->seq_len){
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]);
218 int jmax
= S
->note_max
;
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
]){
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
;
243 note_swap(S
, j
, S
->note_max
-1);
254 int I
= S
->instrument
[S
->note_channel
[j
]];
255 /* hard computations */
256 /* float x = S->wave_ptr[j];
258 float x2 = x1 + 1.0f;
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
;
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);
284 switch(S
->antipop_flag
[j
]){
286 y
*= antipop
[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;
295 y
*= antipop
[S
->antipop_ptr
[j
]];
297 if(S
->antipop_ptr
[j
] < 0){
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);
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
){
350 switch(midi
[0]&0xf0){
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]);
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];
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];
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);
415 orgux_note_on(S
, chan
, val1
, val2
);
418 orgux_note_off(S
, chan
, val1
);
421 orgux_change_instrument(S
, chan
, val1
);
425 orgux_change_volume(S
, chan
, val2
);
428 orgux_change_pan(S
, chan
, val2
);
432 orgux_pitch_bend(S
, chan
, bend
);
439 orgux_state
* orgux_init(int sample_rate
){
440 orgux_state
* S
= malloc(sizeof(orgux_state
));
445 /*precompute waveforms*/
448 precompute(sample_rate
);
453 /* setup oscillator states */
455 for(int i
=0; i
<16; i
++){
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;
466 S
->sample_ptr
[i
] = 0;
470 S
->sample_rate
= sample_rate
;
472 S
->command_count
= 0;
477 //S->lp_alpha = dt/(dt+0.001);
483 void orgux_free(orgux_state
* 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
;
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
){