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
];
62 int command_queue
[512][5]; /* sample type chan val1 val2 */
65 int note_on
[MAX_NOTES
];
66 int note_channel
[MAX_NOTES
];
67 int note_note
[MAX_NOTES
];
68 float velocity
[MAX_NOTES
];
69 int antipop_flag
[MAX_NOTES
];
70 int antipop_ptr
[MAX_NOTES
];
71 float wave_ptr
[MAX_NOTES
];
72 float wave_step
[MAX_NOTES
];
73 int sample_ptr
[MAX_NOTES
];
74 float lp_y
[MAX_NOTES
];
78 #define SWAP(X,Y,T) {T tmp = X; X = Y; Y = tmp;}
79 void note_swap(orgux_state
* S
, int i1
, int i2
){
81 SWAP(S
->note_on
[i1
], S
->note_on
[i2
], int);
82 SWAP(S
->note_channel
[i1
], S
->note_channel
[i2
], int);
83 SWAP(S
->note_note
[i1
], S
->note_note
[i2
], int);
84 SWAP(S
->velocity
[i1
], S
->velocity
[i2
], float);
85 SWAP(S
->antipop_flag
[i1
], S
->antipop_flag
[i2
], int);
86 SWAP(S
->antipop_ptr
[i1
], S
->antipop_ptr
[i2
], int);
87 SWAP(S
->wave_ptr
[i1
], S
->wave_ptr
[i2
], float);
88 SWAP(S
->wave_step
[i1
], S
->wave_step
[i2
], float);
89 SWAP(S
->sample_ptr
[i1
], S
->sample_ptr
[i2
], int);
93 void orgux_note_on(orgux_state
* S
, int chan
, int note
, int velocity
){
97 if(i
== MAX_NOTES
) return;
100 S
->note_channel
[i
] = chan
;
101 S
->note_note
[i
] = note
;
102 S
->velocity
[i
] = ((float)velocity
)/127;
103 S
->antipop_flag
[i
] = -1;
104 S
->antipop_ptr
[i
] = 0;
105 S
->wave_ptr
[i
] = 0.0f
;
106 S
->sample_ptr
[i
] = 0;
107 //S->wave_step[i] = (int)((440*pow(2,(note-69)/12.0)*WAVEFORM_LENGTH)/S->sample_rate);
108 S
->wave_step
[i
] = (440*pow(2,(note
-69)/12.0)*WAVEFORM_LENGTH
)/S
->sample_rate
;
111 //printf("note on i=%d\n",i);
112 for(int j
=0; j
<S
->note_max
; j
++){
113 //printf("[%d %d %d %d]\n",S->note_on[j], S->note_channel[j], S->note_note[j], S->antipop_flag[j]);
118 void orgux_note_off(orgux_state
* S
, int chan
, int note
){
120 for(int i
=0; i
< S
->note_max
; i
++){
121 if(S
->note_on
[i
]==1 && S
->note_channel
[i
]==chan
&& S
->note_note
[i
]==note
&& S
->antipop_flag
[i
]<1){
123 S
->antipop_flag
[i
] = 1;
125 //printf("note end\n");
126 for(int j
=0; j
<S
->note_max
; j
++){
127 //printf("[%d %d %d %d]\n",S->note_on[j], S->note_channel[j], S->note_note[j], S->antipop_flag[j]);
136 void orgux_change_volume(orgux_state
* S
, int chan
, int value
){
137 //printf("change volume %d %d\n", chan, value);
138 S
->volume
[chan
] = ((float)value
)/127;
141 void orgux_change_pan(orgux_state
* S
, int chan
, int value
){
142 //printf("change pan %d %d\n", chan, value);
143 float P
= (((float)value
)/127) * 2 - 1;
146 S
->pan_l
[chan
] = 1.0f
- P
;
147 S
->pan_r
[chan
] = 1.0f
;
150 S
->pan_l
[chan
] = 1.0f
;
151 S
->pan_r
[chan
] = P
+ 1.0f
;
155 void orgux_change_instrument(orgux_state
* S
, int chan
, int value
){
156 //printf("change instrument %d %d\n", chan, value);
157 S
->instrument
[chan
] = value
;
160 void orgux_pitch_bend(orgux_state
* S
, int chan
, int bend
){
161 S
->bend
[chan
] = ((((float)bend
)/16383) * 2 - 1) * 1;
167 void orgux_process(orgux_state
* S
, float* lbuf
, float* rbuf
, int len
){
172 for(int i
=0; i
<len
; i
++){
174 while(i
== S
->command_queue
[C
][0] && C
< S
->command_count
){
175 orgux_control(S
, S
->command_queue
[C
][1],
176 S
->command_queue
[C
][2],
177 S
->command_queue
[C
][3],
178 S
->command_queue
[C
][4]);
185 int jmax
= S
->note_max
;
190 if(!S
->note_on
[j
]) continue;
192 if(S
->note_channel
[j
] == 9){
193 int index
= S
->note_note
[j
] - SAMPLE_NOTE_ZERO
;
194 if(index
< 0){index
=0;}
195 if(index
>= SAMPLE_COUNT
){index
=SAMPLE_COUNT
-1;}
196 float y
= samples
[index
][S
->sample_ptr
[j
]++];
197 if(S
->sample_ptr
[j
] == SAMPLE_LENGTH
|| S
->sample_ptr
[j
] == sample_len
[j
]){
201 float V
= S
->volume
[9];
202 float A
= S
->velocity
[j
];
203 lbuf
[i
] += V
*A
*S
->pan_l
[9]*y
;
204 rbuf
[i
] += V
*A
*S
->pan_r
[9]*y
;
210 note_swap(S
, j
, S
->note_max
-1);
221 int I
= S
->instrument
[S
->note_channel
[j
]];
222 /* hard computations */
223 /* float x = S->wave_ptr[j];
225 float x2 = x1 + 1.0f;
228 if(X2 == WAVEFORM_LENGTH) X2 = 0;
229 float y1 = waveform[I][X1];
230 float y2 = waveform[I][X2];
231 float m = (y2-y1)/(x2-x1);
232 float y = m*(x-x1) + y1;
235 float x
= S
->wave_ptr
[j
];
236 int X0
= (int)floor(x
);
237 float y
= waveform_Z
[I
][X0
] + waveform_M
[I
][X0
]*x
;
242 int I = S->instrument[S->note_channel[j]];
243 int X = S->wave_ptr[j];
244 float y = S->waveform[I][X];
247 //float y0 = S->lp_y[j];
248 //y = y0 + S->lp_alpha * (y - y0);
251 switch(S
->antipop_flag
[j
]){
253 y
*= antipop
[S
->antipop_ptr
[j
]];
256 if(S
->antipop_ptr
[j
] == ANTIPOP_LENGTH
){
257 S
->antipop_ptr
[j
] = ANTIPOP_LENGTH
-1;
258 S
->antipop_flag
[j
] = 0;
262 y
*= antipop
[S
->antipop_ptr
[j
]];
264 if(S
->antipop_ptr
[j
] < 0){
271 int chan
= S
->note_channel
[j
];
272 float volume
= S
->volume
[chan
];
273 float velocity
= S
->velocity
[j
];
274 lbuf
[i
] += volume
*velocity
*S
->pan_l
[chan
]*y
;
275 rbuf
[i
] += volume
*velocity
*S
->pan_r
[chan
]*y
;
277 if(lbuf
[i
]> 1.0 || lbuf
[i
] < -1.0){
278 printf("ehh lbuf[%d] = %f\n",i
,lbuf
[i
]);
279 printf("%f %f %f %f %f\n",y
,volume
, velocity
, S
->pan_l
[chan
], S
->pan_r
[chan
]);
282 S
->wave_ptr
[j
] += S
->wave_step
[j
];
283 while(S
->wave_ptr
[j
] >= WAVEFORM_LENGTH
){
284 S
->wave_ptr
[j
] -= WAVEFORM_LENGTH
;
287 if(swap_ok
){ /* kills note */
288 note_swap(S
, j
, S
->note_max
-1);
293 //printf("note off\n");
294 for(int z
=0; z
<S
->note_max
; z
++){
295 //printf("[%d %d %d %d]\n",S->note_on[z], S->note_channel[z], S->note_note[z], S->antipop_flag[z]);
303 S
->command_count
= 0;
310 void orgux_schedule(orgux_state
* S
, int sample
, unsigned char midi
[3]){
311 //orgux_control(S, midi[0]&0xf0, midi[0]&0x0f, midi[1], midi[2]);
313 if(S
->command_count
== MAX_COMMANDS
){
317 switch(midi
[0]&0xf0){
323 the queue is sorted by time (sample)
324 soonest times are to the beginning of the queue
325 queue[0] is the first element
326 insert: move all later events right one
329 //printf("schedule %d %x %x %x\n",sample,midi[0],midi[1],midi[2]);
331 for(i
=0; i
<S
->command_count
; i
++){
333 if(sample
< S
->command_queue
[i
][0]){
335 for(int j
=S
->command_count
; j
>i
; j
--){
336 S
->command_queue
[j
][0] = S
->command_queue
[j
-1][0];
337 S
->command_queue
[j
][1] = S
->command_queue
[j
-1][1];
338 S
->command_queue
[j
][2] = S
->command_queue
[j
-1][2];
339 S
->command_queue
[j
][3] = S
->command_queue
[j
-1][3];
340 S
->command_queue
[j
][4] = S
->command_queue
[j
-1][4];
343 S
->command_queue
[i
][0] = sample
;
344 S
->command_queue
[i
][1] = midi
[0]&0xf0;
345 S
->command_queue
[i
][2] = midi
[0]&0x0f;
346 S
->command_queue
[i
][3] = midi
[1];
347 S
->command_queue
[i
][4] = midi
[2];
353 if(i
==S
->command_count
){//end of queue
354 S
->command_queue
[i
][0] = sample
;
355 S
->command_queue
[i
][1] = midi
[0]&0xf0;
356 S
->command_queue
[i
][2] = midi
[0]&0x0f;
357 S
->command_queue
[i
][3] = midi
[1];
358 S
->command_queue
[i
][4] = midi
[2];
362 /*for(int i=0; i<S->command_count; i++){
363 printf("%d %d %d %d %d\n",
364 S->command_queue[i][0],
365 S->command_queue[i][1],
366 S->command_queue[i][2],
367 S->command_queue[i][3],
368 S->command_queue[i][4]);
374 void orgux_control(orgux_state
* S
, int type
, int chan
, int val1
, int val2
){
376 int bend
= (val1
<< 7) + val2
;
378 //printf("control %d %d %d %d\n", chan, type, val1, val2);
382 orgux_note_on(S
, chan
, val1
, val2
);
385 orgux_note_off(S
, chan
, val1
);
388 orgux_change_instrument(S
, chan
, val1
);
392 orgux_change_volume(S
, chan
, val2
);
395 orgux_change_pan(S
, chan
, val2
);
399 orgux_pitch_bend(S
, chan
, bend
);
406 orgux_state
* orgux_init(int sample_rate
){
407 orgux_state
* S
= malloc(sizeof(orgux_state
));
412 /*precompute waveforms*/
415 precompute(sample_rate
);
420 /* setup oscillator states */
422 for(int i
=0; i
<16; i
++){
428 for(int i
=0; i
<MAX_NOTES
; i
++){
429 S
->wave_ptr
[i
] = 0.0f
;
430 S
->antipop_ptr
[i
] = 0;
431 S
->antipop_flag
[i
] = 0;
433 S
->sample_ptr
[i
] = 0;
437 S
->sample_rate
= sample_rate
;
439 S
->command_count
= 0;
442 //S->lp_alpha = dt/(dt+0.001);
448 void orgux_free(orgux_state
* S
){