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 samples
[SAMPLE_COUNT
][SAMPLE_LENGTH
];
46 float antipop
[ANTIPOP_LENGTH
];
58 int command_queue
[512][5]; /* sample type chan val1 val2 */
61 int note_on
[MAX_NOTES
];
62 int note_channel
[MAX_NOTES
];
63 int note_note
[MAX_NOTES
];
64 float velocity
[MAX_NOTES
];
65 int antipop_flag
[MAX_NOTES
];
66 int antipop_ptr
[MAX_NOTES
];
67 float wave_ptr
[MAX_NOTES
];
68 float wave_step
[MAX_NOTES
];
69 int sample_ptr
[MAX_NOTES
];
70 float lp_y
[MAX_NOTES
];
74 void orgux_note_on(orgux_state
* S
, int chan
, int note
, int velocity
){
76 for(int i
=0; i
< MAX_NOTES
; i
++){
77 if(S
->note_on
[i
] == 0){
79 S
->note_channel
[i
] = chan
;
80 S
->note_note
[i
] = note
;
81 S
->velocity
[i
] = ((float)velocity
)/127;
82 S
->antipop_flag
[i
] = -1;
83 S
->antipop_ptr
[i
] = 0;
84 S
->wave_ptr
[i
] = 0.0f
;
86 //S->wave_step[i] = (int)((440*pow(2,(note-69)/12.0)*WAVEFORM_LENGTH)/S->sample_rate);
87 S
->wave_step
[i
] = (440*pow(2,(note
-69)/12.0)*WAVEFORM_LENGTH
)/S
->sample_rate
;
97 void orgux_note_off(orgux_state
* S
, int chan
, int note
){
99 for(int i
=0; i
< S
->note_max
; i
++){
100 if(S
->note_on
[i
]==1 && S
->note_channel
[i
]==chan
&& S
->note_note
[i
]==note
&& S
->antipop_flag
[i
]<1){
102 //S->note_on[i][1] = chan;
103 //S->note_on[i][2] = note;
104 S
->antipop_flag
[i
] = 1;
105 //S->wave_ptr[i] = 0.0f;
106 //S->wave_step[i] = (440*pow(2,(note-57)/12.0)*WAVEFORM_LENGTH)/S->sample_rate;
114 void orgux_change_volume(orgux_state
* S
, int chan
, int value
){
115 //printf("change volume %d %d\n", chan, value);
116 S
->volume
[chan
] = ((float)value
)/127;
119 void orgux_change_pan(orgux_state
* S
, int chan
, int value
){
120 //printf("change pan %d %d\n", chan, value);
121 float P
= (((float)value
)/127) * 2 - 1;
124 S
->pan_l
[chan
] = 1.0f
- P
;
125 S
->pan_r
[chan
] = 1.0f
;
128 S
->pan_l
[chan
] = 1.0f
;
129 S
->pan_r
[chan
] = P
+ 1.0f
;
133 void orgux_change_instrument(orgux_state
* S
, int chan
, int value
){
134 //printf("change instrument %d %d\n", chan, value);
135 S
->instrument
[chan
] = value
;
138 void orgux_pitch_bend(orgux_state
* S
, int chan
, int bend
){
139 S
->bend
[chan
] = ((((float)bend
)/16383) * 2 - 1) * 1;
143 void orgux_process(orgux_state
* S
, float* lbuf
, float* rbuf
, int len
){
146 /* determine on notes, dont search each time */
147 int note_ons
[MAX_NOTES
];
149 for(int i
=0; i
<S
->note_max
; i
++){
156 for(int i
=0; i
<len
; i
++){
158 while(i
== S
->command_queue
[C
][0] && C
< S
->command_count
){
159 orgux_control(S
, S
->command_queue
[C
][1],
160 S
->command_queue
[C
][2],
161 S
->command_queue
[C
][3],
162 S
->command_queue
[C
][4]);
170 //render playing samples
171 /*for(int j = 0; j<SAMPLE_COUNT; j++){
172 if(!S->sample_on[j]) continue;
173 float y = S->samples[j][S->sample_ptr[j]++];
174 if(S->sample_ptr[j] == SAMPLE_LENGTH){
177 float V = S->volume[9];
178 float A = S->sample_velocity[j];
179 lbuf[i] += V*A*S->pan_l[9]*y;
180 rbuf[i] += V*A*S->pan_r[9]*y;
184 int jmax
= S
->note_max
;
185 for(int j
=0; j
< jmax
; j
++){
186 //for(int n=0; n < N; n++){
187 //int j = note_ons[n];
189 if(!S
->note_on
[j
]) continue;
191 if(S
->note_channel
[j
] == 9){
192 int index
= S
->note_note
[j
] - SAMPLE_NOTE_ZERO
;
193 if(index
< 0){index
=0;}
194 if(index
>= SAMPLE_COUNT
){index
=SAMPLE_COUNT
-1;}
195 float y
= samples
[index
][S
->sample_ptr
[j
]++];
196 if(S
->sample_ptr
[j
] == SAMPLE_LENGTH
){
200 float V
= S
->volume
[9];
201 float A
= S
->velocity
[j
];
202 lbuf
[i
] += V
*A
*S
->pan_l
[9]*y
;
203 rbuf
[i
] += V
*A
*S
->pan_r
[9]*y
;
208 /* hard computations */
209 float x
= S
->wave_ptr
[j
];
211 float x2
= x1
+ 1.0f
;
214 if(X2
== WAVEFORM_LENGTH
) X2
= 0;
215 int I
= S
->instrument
[S
->note_channel
[j
]];
216 float y1
= waveform
[I
][X1
];
217 float y2
= waveform
[I
][X2
];
218 float m
= (y2
-y1
)/(x2
-x1
);
219 float y
= m
*(x
-x1
) + y1
;
224 int I = S->instrument[S->note_channel[j]];
225 int X = S->wave_ptr[j];
226 float y = S->waveform[I][X];
229 //float y0 = S->lp_y[j];
230 //y = y0 + S->lp_alpha * (y - y0);
233 switch(S
->antipop_flag
[j
]){
235 y
*= antipop
[S
->antipop_ptr
[j
]];
238 if(S
->antipop_ptr
[j
] == ANTIPOP_LENGTH
){
239 S
->antipop_ptr
[j
] = ANTIPOP_LENGTH
-1;
240 S
->antipop_flag
[j
] = 0;
244 y
*= antipop
[S
->antipop_ptr
[j
]];
246 if(S
->antipop_ptr
[j
] < 0){
247 //printf("note dead! j = %d, max = %d\n",j, S->note_max);
248 S
->antipop_flag
[j
] = 0;
250 if(j
+1==S
->note_max
){
258 int chan
= S
->note_channel
[j
];
259 float volume
= S
->volume
[chan
];
260 float velocity
= S
->velocity
[j
];
261 lbuf
[i
] += volume
*velocity
*S
->pan_l
[chan
]*y
;
262 rbuf
[i
] += volume
*velocity
*S
->pan_r
[chan
]*y
;
264 if(lbuf
[i
]> 1.0 || lbuf
[i
] < -1.0){
265 printf("ehh lbuf[%d] = %f\n",i
,lbuf
[i
]);
266 printf("%f %f %f %f %f\n",y
,volume
, velocity
, S
->pan_l
[chan
], S
->pan_r
[chan
]);
269 S
->wave_ptr
[j
] += S
->wave_step
[j
];
270 while(S
->wave_ptr
[j
] >= WAVEFORM_LENGTH
){
271 S
->wave_ptr
[j
] -= WAVEFORM_LENGTH
;
278 S
->command_count
= 0;
285 void orgux_schedule(orgux_state
* S
, int sample
, unsigned char midi
[3]){
286 //orgux_control(S, midi[0]&0xf0, midi[0]&0x0f, midi[1], midi[2]);
288 if(S
->command_count
== MAX_COMMANDS
){
292 switch(midi
[0]&0xf0){
298 the queue is sorted by time (sample)
299 soonest times are to the beginning of the queue
300 queue[0] is the first element
301 insert: move all later events right one
304 //printf("schedule %d %x %x %x\n",sample,midi[0],midi[1],midi[2]);
306 for(i
=0; i
<S
->command_count
; i
++){
308 if(sample
< S
->command_queue
[i
][0]){
310 for(int j
=S
->command_count
; j
>i
; j
--){
311 S
->command_queue
[j
][0] = S
->command_queue
[j
-1][0];
312 S
->command_queue
[j
][1] = S
->command_queue
[j
-1][1];
313 S
->command_queue
[j
][2] = S
->command_queue
[j
-1][2];
314 S
->command_queue
[j
][3] = S
->command_queue
[j
-1][3];
315 S
->command_queue
[j
][4] = S
->command_queue
[j
-1][4];
318 S
->command_queue
[i
][0] = sample
;
319 S
->command_queue
[i
][1] = midi
[0]&0xf0;
320 S
->command_queue
[i
][2] = midi
[0]&0x0f;
321 S
->command_queue
[i
][3] = midi
[1];
322 S
->command_queue
[i
][4] = midi
[2];
328 if(i
==S
->command_count
){//end of queue
329 S
->command_queue
[i
][0] = sample
;
330 S
->command_queue
[i
][1] = midi
[0]&0xf0;
331 S
->command_queue
[i
][2] = midi
[0]&0x0f;
332 S
->command_queue
[i
][3] = midi
[1];
333 S
->command_queue
[i
][4] = midi
[2];
338 for(int i
=0; i
<S
->command_count
; i
++){
339 /*printf("%d %d %d %d %d\n",
340 S->command_queue[i][0],
341 S->command_queue[i][1],
342 S->command_queue[i][2],
343 S->command_queue[i][3],
344 S->command_queue[i][4]);
350 void orgux_control(orgux_state
* S
, int type
, int chan
, int val1
, int val2
){
352 int bend
= (val1
<< 7) + val2
;
354 //printf("control %d %d %d %d\n", chan, type, val1, val2);
358 orgux_note_on(S
, chan
, val1
, val2
);
361 orgux_note_off(S
, chan
, val1
);
364 orgux_change_instrument(S
, chan
, val1
);
368 orgux_change_volume(S
, chan
, val2
);
371 orgux_change_pan(S
, chan
, val2
);
375 printf("pitch bend %d\n",bend
);
376 orgux_pitch_bend(S
, chan
, bend
);
383 orgux_state
* orgux_init(int sample_rate
){
384 orgux_state
* S
= malloc(sizeof(orgux_state
));
389 /*precompute waveforms*/
392 precompute(sample_rate
);
397 /* setup oscillator states */
399 for(int i
=0; i
<16; i
++){
405 for(int i
=0; i
<MAX_NOTES
; i
++){
406 S
->wave_ptr
[i
] = 0.0f
;
407 S
->antipop_ptr
[i
] = 0;
408 S
->antipop_flag
[i
] = 0;
410 S
->sample_ptr
[i
] = 0;
414 S
->sample_rate
= sample_rate
;
416 S
->command_count
= 0;
419 //S->lp_alpha = dt/(dt+0.001);
425 void orgux_free(orgux_state
* S
){