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
;
61 int serr
= 0; // 1/1000 of a sample
64 int terr
= 0; // 1/(bpm*tpb) of a sample
65 int terrd
= 46080; //bpm * tpb
74 void set_bpm(int x
){ bpm
= x
; }
80 void dummy_mix(void* v
, float f
[], int i
){}
81 void dummy_control(void* v
, int a
, int b
, int c
, int d
){}
82 void dummy_cleanup(void* v
){}
84 channel
make_dummy_channel(){
90 ch
.cleanup
= dummy_cleanup
;
91 ch
.control
= dummy_control
;
96 channel
make_channel_from_instrument(enum instrument_name name
){
97 channel ch
= make_dummy_channel();
98 instrument ins
= load_instrument(name
);
100 ch
.control
= ins
.control
;
101 ch
.cleanup
= ins
.cleanup
;
108 void mix(channel
* ch
, float in
[], float left
[], float right
[], int count
){
110 for(i
=0; i
<count
; i
++){
111 left
[i
] += in
[i
] * ch
->L
* ch
->V
;
112 right
[i
] += in
[i
] * ch
->R
* ch
->V
;
116 void zero(float buf
[], int count
){
118 for(i
=0; i
<count
; i
++){
123 void reduce(float buf
[], int count
, float factor
){
125 for(i
=0; i
<count
; i
++){
130 void generate(float left
[], float right
[], int count
){
138 channel
* ch
= &(channels
[i
]);
140 ch
->mix(ch
->data
, buf
, count
);
141 mix(ch
, buf
, left
, right
, count
);
143 reduce(left
, count
, 16.0f
/V
);
144 reduce(right
, count
, 16.0f
/V
);
147 void control(event
* e
){
148 if(e
== NULL
) return;
153 int val
= (e
->val2
<< 7) | e
->val1
;
154 channel
* ch
= &(channels
[chan
]);
155 ch
->control(ch
->data
, type
, val1
, val2
, val
);
158 void immediate_control(){
159 event
* e
= seq_get_immediate();
162 e
= seq_get_immediate();
166 void synth_generate(float left
[], float right
[], int samples
){
168 int remaining
= samples
;
174 while(remaining
> 0){
175 e
= seq_advance(remaining
, &used
);
176 generate(left
+i
, right
+i
, used
);
180 if(e
== NULL
&& remaining
> 0){
181 printf("synth: sequencer error. no event was returned, but unable to advance beyond %d samples (out of %d)\n", i
, samples
);
182 printf("synth: i will continue, but this caused a tick/sample drift of %d samples\n", remaining
);
191 printf(" synth: ... ");
193 channels
[0] = make_channel_from_instrument(ORG_DEFAULT
);
194 channels
[1] = make_channel_from_instrument(ORG_KARPLUS
);
196 channels
[i
] = make_dummy_channel();
199 //srate = sample_rate;