Added a pitiful attempt at loudness normalization to ORG_DEFAULT.
[cantaveria.git] / seq.c
blob4d7e21511b41c48be22f94d3b0625442568391cd
1 /*
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
24 #include <stdio.h>
25 #include <stdlib.h>
27 #include <seq.h>
28 #include <org.h>
29 #include <list.h>
30 #include <audio.h>
31 #include <util.h>
33 int tick;
34 int terr;
35 int loop_start;
36 int loop_end;
37 int looping;
39 //event lists
40 list* sequence;
41 list* blank_events;
42 list* immediate_events;
44 event* next_event;
49 void seq_init(){
50 printf(" sequencer: ... ");
52 blank_events = empty();
53 immediate_events = empty();
54 sequence = empty();
56 printf("OK\n");
59 int would_loop(){
60 return looping && next_event->tick > loop_end;
63 event* get_event_after(int tick){
64 return NULL;
67 event* get_next_event(){
68 if(would_loop()){
69 return get_event_after(loop_start);
71 else {
72 return next_event;
78 int get_next_tick(){
79 event* e = get_next_event();
80 return e ? e->tick : -1;
83 int distance_to_next(){
84 int next_tick = get_next_tick();
85 if(next_tick < 0) return -1;
87 return would_loop() ?
88 next_tick - loop_start + loop_end - tick :
89 next_tick - tick;
94 /* below are three functions that the synth uses to
95 control the sequencer. it finds control events, advances
96 the event pointer, and finally advances the tick count */
98 //returns samples from now an event will occur
99 //if no event will occur in sbound samples, returns -1
100 int seq_lookahead(int sbound){
101 return sbound;
103 int tbound = sbound*46080/1323000;
104 int T = distance_to_next();
105 if(T < 0) return -1;
106 return T > tbound ?
107 sbound :
108 T*1 + 0;
111 //returns the next event that would play
112 //if there is no such event, returns NULL
113 event* seq_get_event(){
114 return NULL;
115 //needs to handle looping
119 //advance the tick position
120 void seq_advance(int samples){
121 return;
122 // 46080 1/1323000 ticks = 1 sample
123 int N = 46080 * samples;
124 int D = 1323000;
125 terr += N;
126 tick += N/D + terr/D;
127 terr %= D;
128 //needs to handle looping
132 /* IMPORTANT
133 it might well be simpler to implement looping as
134 an event which exists at the loop point after all
135 other events that occur at that time which sends
136 the sequence to a specific tick */
141 /* *** */
142 event* make_event(int type, int chan, int val1, int val2){
143 event* e;
144 if(blank_events->next){
145 e = pop(blank_events);
147 else{
148 e = xmalloc(sizeof(event));
151 e->type = type;
152 e->chan = chan;
153 e->val1= val1;
154 e->val2= val2;
155 e->tick = 0;
156 return e;
159 void recycle_event(event* e){
160 push(blank_events, e);
164 void seq_instant(int type, int chan, int val1, int val2){
165 event* e = make_event(type, chan, val1, val2);
166 audio_lock();
167 append(immediate_events, e);
168 audio_unlock();
172 void seq_play_sound(int id){
173 seq_instant(0x90, 15, id, 0);
178 event* seq_get_immediate(){
179 event* e = pop(immediate_events);
180 if(e != NULL){
181 recycle_event(e);
182 return e;
184 else{
185 return NULL;