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
38 ticks - 384 per beat (tpb)
39 beats - 120 per minute (bpm)
40 samples - 22050 per second (srate)
42 control happens on tick boundaries
43 control must take effect on nearest sample boundary
45 samples per tick = (srate*60) / (bpm*tpb)
46 which in the above example = 28 and 32760/46080
53 control_callback control
;
54 cleanup_callback cleanup
;
60 int serr
= 0; // 1/1000 of a sample
63 int terr
= 0; // 1/(bpm*tpb) of a sample
64 int terrd
= 46080; //bpm * tpb
78 void dummy_mix(void* v
, float f
[], int i
){}
79 void dummy_control(void* v
, int a
, int b
, int c
, int d
){}
80 void dummy_cleanup(void* v
){}
82 channel
make_dummy_channel(){
88 ch
.cleanup
= dummy_cleanup
;
89 ch
.control
= dummy_control
;
94 channel
make_channel_from_instrument(enum instrument_name name
){
95 channel ch
= make_dummy_channel();
96 instrument ins
= load_instrument(name
);
98 ch
.control
= ins
.control
;
99 ch
.cleanup
= ins
.cleanup
;
106 void set_music_volume(int percent
){
118 void fadeout(int seconds
){
124 void mix(channel
* ch
, float in
[], float left
[], float right
[], int count
){
126 for(i
=0; i
<count
; i
++){
127 left
[i
] += in
[i
] * ch
->L
* ch
->V
;
128 right
[i
] += in
[i
] * ch
->R
* ch
->V
;
132 void zero(float buf
[], int count
){
134 for(i
=0; i
<count
; i
++){
139 void reduce(float buf
[], int count
, float factor
){
141 for(i
=0; i
<count
; i
++){
146 void clip(float buf
[], int count
){
150 for(i
=0; i
<count
; i
++){
151 avg
+= buf
[i
]*buf
[i
];
156 else if(buf
[i
] < -1.0) buf
[i
] = -1.0;
160 printf("synth: clipping distortion due to output overload\n");
163 avg
/= count
?count
:1;
167 void generate(float left
[], float right
[], int count
){
175 channel
* ch
= &(channels
[i
]);
177 ch
->mix(ch
->data
, buf
, count
);
178 mix(ch
, buf
, left
, right
, count
);
180 reduce(left
, count
, 16.0f
/V
);
181 reduce(right
, count
, 16.0f
/V
);
186 void control(event
* e
){
187 if(e
== NULL
) return;
192 int val
= (e
->val2
<< 7) | e
->val1
;
193 channel
* ch
= &(channels
[chan
]);
196 case EVX_MUSICVOLUME
: set_music_volume(val1
); break;
197 case EVX_MUSICCUT
: cut_music(); break;
198 case EVX_FADECLEAR
: fade_clear(); break;
199 case EVX_FADEOUT
: fadeout(val1
); break;
200 default: ch
->control(ch
->data
, type
, val1
, val2
, val
); break;
204 void immediate_control(){
205 event
* e
= seq_get_immediate();
208 e
= seq_get_immediate();
212 void synth_generate(float left
[], float right
[], int samples
){
214 int remaining
= samples
;
220 while(remaining
> 0){
221 e
= seq_advance(remaining
, &used
);
222 generate(left
+i
, right
+i
, used
);
226 if(e
== NULL
&& used
== 0){
227 error_msg("synth: sequencer failed to advance or provide a control event.");
236 printf(" synth: ... ");
239 channels
[i
] = make_dummy_channel();
242 //channels[0] = make_channel_from_instrument(ORG_KARPLUS);
243 //channels[1] = make_channel_from_instrument(ORG_KARPLUS);
244 //channels[2] = make_channel_from_instrument(ORG_KARPLUS);
245 //channels[3] = make_channel_from_instrument(ORG_KARPLUS);
246 channels
[0] = make_channel_from_instrument(ORG_DEFAULT
);
247 channels
[1] = make_channel_from_instrument(ORG_DEFAULT
);
248 channels
[2] = make_channel_from_instrument(ORG_DEFAULT
);
249 channels
[3] = make_channel_from_instrument(ORG_DEFAULT
);
252 //srate = sample_rate;