2 Cantaveria - action adventure platform game
3 Copyright (C) 2009 2010 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
18 The Free Software Foundation, Inc.
19 51 Franklin Street, Fifth Floor
20 Boston, MA 02110-1301, USA
22 evanrinehart@gmail.com
26 the synth module exports a mixer callback for the audio output.
27 it uses support from orc (instruments) and seq (sequencer) to
29 * generate N samples of stereo output
48 ticks - 384 per beat (tpb)
49 beats - 120 per minute (bpm)
50 samples - 22050 per second (srate)
52 control happens on tick boundaries
53 control must take effect on nearest sample boundary
55 samples per tick = (srate*60) / (bpm*tpb)
56 which in the above example = 28 and 32760/46080
63 control_callback control
;
64 cleanup_callback cleanup
;
70 int serr
= 0; // 1/1000 of a sample
73 int terr
= 0; // 1/(bpm*tpb) of a sample
74 int terrd
= 46080; //bpm * tpb
88 void dummy_mix(void* v
, float f
[], int i
){}
89 void dummy_control(void* v
, int a
, int b
, int c
, int d
){}
90 void dummy_cleanup(void* v
){}
92 channel
make_dummy_channel(){
98 ch
.cleanup
= dummy_cleanup
;
99 ch
.control
= dummy_control
;
104 channel
make_channel_from_instrument(enum instrument_name name
){
105 channel ch
= make_dummy_channel();
106 instrument ins
= orc_load(name
);
108 ch
.control
= ins
.control
;
109 ch
.cleanup
= ins
.cleanup
;
116 void set_music_volume(int percent
){
128 void fadeout(int seconds
){
134 void mix(channel
* ch
, float in
[], float left
[], float right
[], int count
){
136 for(i
=0; i
<count
; i
++){
137 left
[i
] += in
[i
] * ch
->L
* ch
->V
;
138 right
[i
] += in
[i
] * ch
->R
* ch
->V
;
142 void zero(float buf
[], int count
){
144 for(i
=0; i
<count
; i
++){
149 void reduce(float buf
[], int count
, float factor
){
151 for(i
=0; i
<count
; i
++){
156 void clip(float buf
[], int count
){
160 for(i
=0; i
<count
; i
++){
161 avg
+= buf
[i
]*buf
[i
];
166 else if(buf
[i
] < -1.0) buf
[i
] = -1.0;
170 error_msg("synth: clipping distortion due to output overload\n");
173 avg
/= count
?count
:1;
177 void generate(float left
[], float right
[], int count
){
185 channel
* ch
= &(channels
[i
]);
187 ch
->mix(ch
->data
, buf
, count
);
188 mix(ch
, buf
, left
, right
, count
);
190 reduce(left
, count
, 16.0f
/V
);
191 reduce(right
, count
, 16.0f
/V
);
196 void control(event
* e
){
197 if(e
== NULL
) return;
202 int val
= (e
->val2
<< 7) | e
->val1
;
203 channel
* ch
= &(channels
[chan
]);
206 case EVX_MUSICVOLUME
: set_music_volume(val1
); break;
207 case EVX_MUSICCUT
: cut_music(); break;
208 case EVX_FADECLEAR
: fade_clear(); break;
209 case EVX_FADEOUT
: fadeout(val1
); break;
210 default: ch
->control(ch
->data
, type
, val1
, val2
, val
); break;
214 void immediate_control(){
215 event
* e
= seq_get_immediate();
218 e
= seq_get_immediate();
222 void synth_generate(float left
[], float right
[], int samples
){
224 int remaining
= samples
;
230 while(remaining
> 0){
231 e
= seq_advance(remaining
, &used
);
232 generate(left
+i
, right
+i
, used
);
236 if(e
== NULL
&& used
== 0){
237 error_msg("synth: sequencer failed to advance or provide a control event.");
247 orc_init(SAMPLE_RATE
);
250 channels
[i
] = make_dummy_channel();
253 //channels[0] = make_channel_from_instrument(ORC_KARPLUS);
254 //channels[1] = make_channel_from_instrument(ORC_KARPLUS);
255 //channels[2] = make_channel_from_instrument(ORC_KARPLUS);
256 //channels[3] = make_channel_from_instrument(ORC_KARPLUS);
257 channels
[0] = make_channel_from_instrument(ORC_DEFAULT
);
258 channels
[1] = make_channel_from_instrument(ORC_DEFAULT
);
259 channels
[2] = make_channel_from_instrument(ORC_DEFAULT
);
260 channels
[3] = make_channel_from_instrument(ORC_DEFAULT
);