summaryrefslogtreecommitdiff
path: root/apps/plugins/midi/sequencer.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/midi/sequencer.c')
-rw-r--r--apps/plugins/midi/sequencer.c298
1 files changed, 298 insertions, 0 deletions
diff --git a/apps/plugins/midi/sequencer.c b/apps/plugins/midi/sequencer.c
new file mode 100644
index 0000000000..fb98fdaf51
--- /dev/null
+++ b/apps/plugins/midi/sequencer.c
@@ -0,0 +1,298 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2005 Stepan Moskovchenko
10 *
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
13 *
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
16 *
17 ****************************************************************************/
18
19
20extern struct plugin_api * rb;
21
22long tempo=375000;
23
24
25void setVol(int ch, int vol)
26{
27 printf("\nvolume[%d] %d ==> %d", ch, chVol[ch], vol);
28 chVol[ch]=vol;
29}
30
31void setPan(int ch, int pan)
32{
33 printf("\npanning[%d] %d ==> %d", ch, chPanRight[ch], pan);
34
35 chPanLeft[ch]=128-pan;
36 chPanRight[ch]=pan;
37}
38
39
40void setPatch(int ch, int pat)
41{
42 chPat[ch]=pat;
43}
44
45
46/*
47 Pitch Bend table, Computed by
48 for i=0:127, fprintf('%d,', round(2^16*2^((i-64)/384))); end
49 (When typed into Matlab)
50 16 bit pitch bend table
51*/
52long pitchTbl[]=
53{
54 58386,58491,58597,58703,58809,58915,59022,59128,59235,59342,59449,59557,59664,59772,59880,59988,60097,60205,
55 60314,60423,60532,60642,60751,60861,60971,61081,61191,61302,61413,61524,61635,61746,61858,61970,62081,62194,
56 62306,62419,62531,62644,62757,62871,62984,63098,63212,63326,63441,63555,63670,63785,63901,64016,64132,64248,
57 64364,64480,64596,64713,64830,64947,65065,65182,65300,65418,65536,65654,65773,65892,66011,66130,66250,66369,
58 66489,66609,66730,66850,66971,67092,67213,67335,67456,67578,67700,67823,67945,68068,68191,68314,68438,68561,
59 68685,68809,68933,69058,69183,69308,69433,69558,69684,69810,69936,70062,70189,70316,70443,70570,70698,70825,
60 70953,71082,71210,71339,71468,71597,71726,71856,71985,72115,72246,72376,72507,72638,72769,72901,73032,73164,
61 73297,73429
62};
63
64
65void findDelta(struct SynthObject * so, int ch, int note)
66{
67
68 struct GWaveform * wf = patchSet[chPat[ch]]->waveforms[patchSet[chPat[ch]]->noteTable[note]];
69 so->wf=wf;
70 so->delta = (((gustable[note]<<10) / wf->rootFreq) * wf->sampRate / SAMPLE_RATE);
71 so->delta = so->delta * pitchTbl[chPW[ch]] >> 16;
72}
73
74void setPW(int ch, int msb)
75{
76 printf("\npitchw[%d] %d ==> %d", ch, chPW[ch], msb);
77 chPW[ch] = msb;
78
79 int a=0;
80 for(a = 0; a<MAX_VOICES; a++)
81 {
82 if(voices[a].isUsed==1 && voices[a].ch == ch)
83 {
84 findDelta(&voices[a], ch, voices[a].note);
85 }
86 }
87}
88
89void pressNote(int ch, int note, int vol)
90{
91 int a=0;
92 for(a=0; a<MAX_VOICES; a++)
93 {
94 if(voices[a].isUsed==0)
95 break;
96 }
97 if(a==MAX_VOICES-1)
98 {
99 printf("\nOVERFLOW: Too many voices playing at once. No more left");
100 printf("\nVOICE DUMP: ");
101 for(a=0; a<48; a++)
102 printf("\n#%d Ch=%d Note=%d curRate=%d curOffset=%d curPoint=%d targetOffset=%d", a, voices[a].ch, voices[a].note, voices[a].curRate, voices[a].curOffset, voices[a].curPoint, voices[a].targetOffset);
103 return; //None avaolable
104 }
105 voices[a].ch=ch;
106 voices[a].note=note;
107 voices[a].vol=vol;
108 voices[a].cp=0;
109 voices[a].state=STATE_ATTACK;
110 voices[a].pstate=STATE_ATTACK;
111 voices[a].decay=255;
112
113
114 voices[a].loopState=STATE_NONLOOPING;
115 voices[a].loopDir = LOOPDIR_FORWARD;
116 /*
117 OKAY. Gt = Gus Table value
118 rf = Root Frequency of wave
119 SR = sound sampling rate
120 sr = WAVE sampling rate
121 */
122
123
124 /*
125 unsigned int gt = gustable[note];
126 unsigned int rf = wf->rootFreq;
127 unsigned int SR = SAMPLE_RATE;
128 unsigned int sr = wf->sampRate;
129 voices[a].delta=((((gt<<10) / rf) * sr / SR));
130 */
131
132
133 if(ch!=9)
134 {
135 findDelta(&voices[a], ch, note);
136 //Turn it on
137 voices[a].isUsed=1;
138 setPoint(&voices[a], 0);
139 } else
140 {
141 if(drumSet[note]!=NULL)
142 {
143 if(note<35)
144 printf("\nNOTE LESS THAN 35, AND A DRUM PATCH EXISTS FOR THIS? WHAT THE HELL?");
145
146 struct GWaveform * wf = drumSet[note]->waveforms[0];
147 voices[a].wf=wf;
148 voices[a].delta = (((gustable[note]<<10) / wf->rootFreq) * wf->sampRate / SAMPLE_RATE);
149 if(wf->mode & 28)
150 printf("\nWoah, a drum patch has a loop. Stripping the loop...");
151 wf->mode = wf->mode & (255-28);
152 //Turn it on
153 voices[a].isUsed=1;
154 setPoint(&voices[a], 0);
155
156 } else
157 {
158 printf("\nWarning: drum %d does not have a patch defined... Ignoring it", note);
159 }
160 }
161}
162
163
164void releaseNote(int ch, int note)
165{
166 if(ch==9) // && note != 27 && note != 31 && note != 28)
167 return;
168 int a=0;
169 for(a=0; a<MAX_VOICES; a++)
170 {
171 if(voices[a].ch == ch && voices[a].note == note)
172 {
173 //voices[a].isUsed=0;
174 if((voices[a].wf->mode & 28))
175 {
176 voices[a].tmp=40;
177// voices[a].state = STATE_RELEASE; //Ramp down
178
179// voices[a].state = STATE_RAMPDOWN; //Ramp down
180
181// voices[a].isUsed = 0;
182 setPoint(&voices[a], 3);
183 }
184 }
185 }
186}
187
188void sendEvent(struct Event * ev)
189{
190// printf("\nEVENT S=%2x D1=%2x D2=%2x", ev->status, ev->d1, ev->d2);
191
192 if( ((ev->status & 0xF0) == MIDI_CONTROL) && (ev->d1 == CTRL_VOLUME) )
193 {
194 setVol((ev->status & 0xF), ev->d2);
195 return;
196 }
197
198 if( ((ev->status & 0xF0) == MIDI_CONTROL) && (ev->d1 == CTRL_PANNING))
199 {
200 setPan((ev->status & 0xF), ev->d2);
201 return;
202 }
203
204 if(((ev->status & 0xF0) == MIDI_PITCHW))
205 {
206 setPW((ev->status & 0xF), ev->d2);
207 return;
208 }
209
210 if(((ev->status & 0xF0) == MIDI_NOTE_ON) && (ev->d2 != 0))
211 {
212 pressNote(ev->status & 0x0F, ev->d1, ev->d2);
213 return;
214 }
215
216 if(((ev->status & 0xF0) == MIDI_NOTE_ON) && (ev->d2 == 0)) //Release by vol=0
217 {
218 releaseNote(ev->status & 0x0F, ev->d1);
219 return;
220 }
221
222
223 if((ev->status & 0xF0) == MIDI_NOTE_OFF)
224 {
225 releaseNote(ev->status & 0x0F, ev->d1);
226 return;
227 }
228
229 if((ev->status & 0xF0) == MIDI_PRGM)
230 {
231 if((ev->status & 0x0F) == 9)
232 printf("\nNOT PATCHING: Someone tried patching Channel 9 onto something?");
233 else
234 setPatch(ev->status & 0x0F, ev->d1);
235 }
236}
237
238
239
240
241
242int tick(struct MIDIfile * mf)
243{
244 if(mf==NULL)
245 return;
246
247 int a=0;
248 int tracksAdv=0;
249 for(a=0; a<mf->numTracks; a++)
250 {
251 struct Track * tr = mf->tracks[a];
252
253 if(tr == NULL)
254 printf("\nNULL TRACK: %d", a);
255
256
257 //BIG DEBUG STATEMENT
258 //printf("\nTrack %2d, Event = %4d of %4d, Delta = %5d, Next = %4d", a, tr->pos, tr->numEvents, tr->delta, getEvent(tr, tr->pos)->delta);
259
260
261 if(tr != NULL && (tr->pos < tr->numEvents))
262 {
263 tr->delta++;
264 tracksAdv++;
265 while(getEvent(tr, tr->pos)->delta <= tr->delta)
266 {
267// printf("\nDelta = %d", tr->delta);
268 struct Event * e = getEvent(tr, tr->pos);
269
270 if(e->status != 0xFF)
271 {
272 sendEvent(e);
273 if(((e->status&0xF0) == MIDI_PRGM))
274 {
275 printf("\nPatch Event, patch[%d] ==> %d", e->status&0xF, e->d1);
276 }
277 }
278 else
279 {
280 if(e->d1 == 0x51)
281 {
282 tempo = (((short)e->evData[0])<<16)|(((short)e->evData[1])<<8)|(e->evData[2]);
283 printf("\nMeta-Event: Tempo Set = %d", tempo);
284 }
285 }
286 tr->delta = 0;
287 tr->pos++;
288 if(tr->pos>=(tr->numEvents-1))
289 break;
290 }
291 }
292 }
293
294 if(tracksAdv != 0)
295 return 1;
296 else
297 return 0;
298}