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
37 ticks - 384 per beat (tpb)
38 beats - 120 per minute (bpm)
39 samples - 22050 per second (srate)
41 control happens on tick boundaries
42 control must take effect on nearest sample boundary
44 samples per tick = (srate*60) / (bpm*tpb)
45 which in the above example = 28 and 32760/46080
52 control_callback control
;
53 cleanup_callback cleanup
;
59 int serr
= 0; // 1/1000 of a sample
62 int terr
= 0; // 1/(bpm*tpb) of a sample
63 int terrd
= 46080; //bpm * tpb
77 void dummy_mix(void* v
, float f
[], int i
){}
78 void dummy_control(void* v
, int a
, int b
, int c
, int d
){}
79 void dummy_cleanup(void* v
){}
81 channel
make_dummy_channel(){
87 ch
.cleanup
= dummy_cleanup
;
88 ch
.control
= dummy_control
;
93 channel
make_channel_from_instrument(enum instrument_name name
){
94 channel ch
= make_dummy_channel();
95 instrument ins
= load_instrument(name
);
97 ch
.control
= ins
.control
;
98 ch
.cleanup
= ins
.cleanup
;
105 void mix(channel
* ch
, float in
[], float left
[], float right
[], int count
){
107 for(i
=0; i
<count
; i
++){
108 left
[i
] += in
[i
] * ch
->L
* ch
->V
;
109 right
[i
] += in
[i
] * ch
->R
* ch
->V
;
113 void zero(float buf
[], int count
){
115 for(i
=0; i
<count
; i
++){
120 void reduce(float buf
[], int count
, float factor
){
122 for(i
=0; i
<count
; i
++){
127 void clip(float buf
[], int count
){
131 for(i
=0; i
<count
; i
++){
132 avg
+= buf
[i
]*buf
[i
];
137 else if(buf
[i
] < -1.0) buf
[i
] = -1.0;
141 printf("synth: out of range output was clipped in this buffer\n");
144 avg
/= count
?count
:1;
148 void generate(float left
[], float right
[], int count
){
156 channel
* ch
= &(channels
[i
]);
158 ch
->mix(ch
->data
, buf
, count
);
159 mix(ch
, buf
, left
, right
, count
);
161 reduce(left
, count
, 16.0f
/V
);
162 reduce(right
, count
, 16.0f
/V
);
167 void control(event
* e
){
168 if(e
== NULL
) return;
173 int val
= (e
->val2
<< 7) | e
->val1
;
174 channel
* ch
= &(channels
[chan
]);
175 ch
->control(ch
->data
, type
, val1
, val2
, val
);
178 void immediate_control(){
179 event
* e
= seq_get_immediate();
182 e
= seq_get_immediate();
186 void synth_generate(float left
[], float right
[], int samples
){
188 int remaining
= samples
;
194 while(remaining
> 0){
195 e
= seq_advance(remaining
, &used
);
196 generate(left
+i
, right
+i
, used
);
200 if(e
== NULL
&& remaining
> 0){
201 printf("synth: sequencer error. no event was returned, but unable to advance beyond %d samples (out of %d)\n", i
, samples
);
202 printf("synth: i will continue, but this caused a tick/sample drift of %d samples\n", remaining
);
211 printf(" synth: ... ");
214 channels
[i
] = make_dummy_channel();
217 channels
[0] = make_channel_from_instrument(ORG_DEFAULT
);
218 channels
[1] = make_channel_from_instrument(ORG_DEFAULT
);
219 channels
[2] = make_channel_from_instrument(ORG_DEFAULT
);
220 channels
[3] = make_channel_from_instrument(ORG_DEFAULT
);
223 //srate = sample_rate;