diff options
author | Stepan Moskovchenko <stevenm@rockbox.org> | 2007-10-15 05:11:37 +0000 |
---|---|---|
committer | Stepan Moskovchenko <stevenm@rockbox.org> | 2007-10-15 05:11:37 +0000 |
commit | 1515ff852224c822a6d3db8c458eab2c9037704f (patch) | |
tree | e427fbec1b397d18abffc12b7fe74e67c2cad807 /apps | |
parent | 99f955088149d5938ce4c9ca5624377f464b1380 (diff) | |
download | rockbox-1515ff852224c822a6d3db8c458eab2c9037704f.tar.gz rockbox-1515ff852224c822a6d3db8c458eab2c9037704f.zip |
MIDI: At long last, though quick and dirty, pitch bend depth! Or, I think it works. Tested on two
files. Let me know if anyone discovers any problems with this. This commit also includes Nils's synth
loop optimization patch. I hope committing it does not cause problems.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15112 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/midi/midiplay.c | 14 | ||||
-rw-r--r-- | apps/plugins/midi/midiutil.c | 1 | ||||
-rw-r--r-- | apps/plugins/midi/midiutil.h | 4 | ||||
-rw-r--r-- | apps/plugins/midi/sequencer.c | 78 | ||||
-rw-r--r-- | apps/plugins/midi/synth.c | 261 |
5 files changed, 218 insertions, 140 deletions
diff --git a/apps/plugins/midi/midiplay.c b/apps/plugins/midi/midiplay.c index 99f05718d6..325d90c375 100644 --- a/apps/plugins/midi/midiplay.c +++ b/apps/plugins/midi/midiplay.c | |||
@@ -93,6 +93,7 @@ int numberOfSamples IBSS_ATTR; | |||
93 | long bpm IBSS_ATTR; | 93 | long bpm IBSS_ATTR; |
94 | 94 | ||
95 | int32_t gmbuf[BUF_SIZE*NBUF]; | 95 | int32_t gmbuf[BUF_SIZE*NBUF]; |
96 | static unsigned int samples_in_buf; | ||
96 | 97 | ||
97 | int quit=0; | 98 | int quit=0; |
98 | struct plugin_api * rb; | 99 | struct plugin_api * rb; |
@@ -160,7 +161,8 @@ static inline void synthbuf(void) | |||
160 | outptr=gmbuf; | 161 | outptr=gmbuf; |
161 | #endif | 162 | #endif |
162 | 163 | ||
163 | for(i=0; i<BUF_SIZE/numberOfSamples; i++) | 164 | /* synth samples for as many whole ticks as we can fit in the buffer */ |
165 | for(i=0; i < BUF_SIZE/numberOfSamples; i++) | ||
164 | { | 166 | { |
165 | synthSamples((int32_t*)outptr, numberOfSamples); | 167 | synthSamples((int32_t*)outptr, numberOfSamples); |
166 | outptr += numberOfSamples; | 168 | outptr += numberOfSamples; |
@@ -168,11 +170,9 @@ static inline void synthbuf(void) | |||
168 | quit=1; | 170 | quit=1; |
169 | } | 171 | } |
170 | 172 | ||
171 | if(BUF_SIZE%numberOfSamples) | 173 | /* how many samples did we write to the buffer? */ |
172 | { | 174 | samples_in_buf = BUF_SIZE-(BUF_SIZE%numberOfSamples); |
173 | synthSamples((int32_t*)outptr, BUF_SIZE%numberOfSamples); | 175 | |
174 | outptr += BUF_SIZE%numberOfSamples; | ||
175 | } | ||
176 | } | 176 | } |
177 | 177 | ||
178 | void get_more(unsigned char** start, size_t* size) | 178 | void get_more(unsigned char** start, size_t* size) |
@@ -187,7 +187,7 @@ void get_more(unsigned char** start, size_t* size) | |||
187 | synthbuf(); // For some reason midiplayer crashes when an update is forced | 187 | synthbuf(); // For some reason midiplayer crashes when an update is forced |
188 | #endif | 188 | #endif |
189 | 189 | ||
190 | *size = sizeof(gmbuf)/NBUF; | 190 | *size = samples_in_buf*sizeof(int32_t); |
191 | #ifndef SYNC | 191 | #ifndef SYNC |
192 | *start = (unsigned char*)((swap ? gmbuf : gmbuf + BUF_SIZE)); | 192 | *start = (unsigned char*)((swap ? gmbuf : gmbuf + BUF_SIZE)); |
193 | swap=!swap; | 193 | swap=!swap; |
diff --git a/apps/plugins/midi/midiutil.c b/apps/plugins/midi/midiutil.c index aba56c5a8c..8cf8ffcde6 100644 --- a/apps/plugins/midi/midiutil.c +++ b/apps/plugins/midi/midiutil.c | |||
@@ -25,6 +25,7 @@ int chVol[16] IBSS_ATTR; /* Channel volume */ | |||
25 | int chPan[16] IBSS_ATTR; /* Channel panning */ | 25 | int chPan[16] IBSS_ATTR; /* Channel panning */ |
26 | int chPat[16] IBSS_ATTR; /* Channel patch */ | 26 | int chPat[16] IBSS_ATTR; /* Channel patch */ |
27 | int chPW[16] IBSS_ATTR; /* Channel pitch wheel, MSB only */ | 27 | int chPW[16] IBSS_ATTR; /* Channel pitch wheel, MSB only */ |
28 | int chPBDepth[16] IBSS_ATTR; /* Channel pitch wheel, MSB only */ | ||
28 | 29 | ||
29 | struct GPatch * gusload(char *); | 30 | struct GPatch * gusload(char *); |
30 | struct GPatch * patchSet[128]; | 31 | struct GPatch * patchSet[128]; |
diff --git a/apps/plugins/midi/midiutil.h b/apps/plugins/midi/midiutil.h index a94c257df0..911774440e 100644 --- a/apps/plugins/midi/midiutil.h +++ b/apps/plugins/midi/midiutil.h | |||
@@ -63,7 +63,8 @@ | |||
63 | #define MIDI_PITCHW 224 | 63 | #define MIDI_PITCHW 224 |
64 | 64 | ||
65 | /* MIDI Controllers */ | 65 | /* MIDI Controllers */ |
66 | #define CTRL_VOLUME 7 | 66 | #define CTRL_PWDEPTH 6 |
67 | #define CTRL_VOLUME 7 | ||
67 | #define CTRL_BALANCE 8 | 68 | #define CTRL_BALANCE 8 |
68 | #define CTRL_PANNING 10 | 69 | #define CTRL_PANNING 10 |
69 | #define CHANNEL 1 | 70 | #define CHANNEL 1 |
@@ -159,6 +160,7 @@ extern int chVol[16]; /* Channel volume */ | |||
159 | extern int chPan[16]; /* Channel panning */ | 160 | extern int chPan[16]; /* Channel panning */ |
160 | extern int chPat[16]; /* Channel patch */ | 161 | extern int chPat[16]; /* Channel patch */ |
161 | extern int chPW[16]; /* Channel pitch wheel, MSB only */ | 162 | extern int chPW[16]; /* Channel pitch wheel, MSB only */ |
163 | extern int chPBDepth[16]; /* Channel pitch bend depth (Controller 6 */ | ||
162 | 164 | ||
163 | extern struct GPatch * gusload(char *); | 165 | extern struct GPatch * gusload(char *); |
164 | extern struct GPatch * patchSet[128]; | 166 | extern struct GPatch * patchSet[128]; |
diff --git a/apps/plugins/midi/sequencer.c b/apps/plugins/midi/sequencer.c index 1a00c078c6..638c9ba43a 100644 --- a/apps/plugins/midi/sequencer.c +++ b/apps/plugins/midi/sequencer.c | |||
@@ -75,7 +75,60 @@ long pitchTbl[]= | |||
75 | }; | 75 | }; |
76 | */ | 76 | */ |
77 | 77 | ||
78 | |||
79 | /* 512 entries here */ | ||
80 | /* | ||
81 | for i=0:512, fprintf('%d,', round(2^16*2^((i-256)/1536))); end | ||
82 | */ | ||
83 | |||
78 | const uint32_t pitchTbl[] ICONST_ATTR={ | 84 | const uint32_t pitchTbl[] ICONST_ATTR={ |
85 | 61858,61872,61886,61900,61914,61928,61942,61956,61970,61983,61997,62011, | ||
86 | 62025,62039,62053,62067,62081,62095,62109,62124,62138,62152,62166,62180, | ||
87 | 62194,62208,62222,62236,62250,62264,62278,62292,62306,62320,62334,62348, | ||
88 | 62362,62376,62390,62404,62419,62433,62447,62461,62475,62489,62503,62517, | ||
89 | 62531,62545,62560,62574,62588,62602,62616,62630,62644,62658,62673,62687, | ||
90 | 62701,62715,62729,62743,62757,62772,62786,62800,62814,62828,62843,62857, | ||
91 | 62871,62885,62899,62913,62928,62942,62956,62970,62984,62999,63013,63027, | ||
92 | 63041,63056,63070,63084,63098,63112,63127,63141,63155,63169,63184,63198, | ||
93 | 63212,63227,63241,63255,63269,63284,63298,63312,63326,63341,63355,63369, | ||
94 | 63384,63398,63412,63427,63441,63455,63470,63484,63498,63512,63527,63541, | ||
95 | 63555,63570,63584,63599,63613,63627,63642,63656,63670,63685,63699,63713, | ||
96 | 63728,63742,63757,63771,63785,63800,63814,63829,63843,63857,63872,63886, | ||
97 | 63901,63915,63929,63944,63958,63973,63987,64002,64016,64030,64045,64059, | ||
98 | 64074,64088,64103,64117,64132,64146,64161,64175,64190,64204,64219,64233, | ||
99 | 64248,64262,64277,64291,64306,64320,64335,64349,64364,64378,64393,64407, | ||
100 | 64422,64436,64451,64465,64480,64494,64509,64524,64538,64553,64567,64582, | ||
101 | 64596,64611,64626,64640,64655,64669,64684,64699,64713,64728,64742,64757, | ||
102 | 64772,64786,64801,64815,64830,64845,64859,64874,64889,64903,64918,64933, | ||
103 | 64947,64962,64976,64991,65006,65020,65035,65050,65065,65079,65094,65109, | ||
104 | 65123,65138,65153,65167,65182,65197,65211,65226,65241,65256,65270,65285, | ||
105 | 65300,65315,65329,65344,65359,65374,65388,65403,65418,65433,65447,65462, | ||
106 | 65477,65492,65506,65521,65536,65551,65566,65580,65595,65610,65625,65640, | ||
107 | 65654,65669,65684,65699,65714,65729,65743,65758,65773,65788,65803,65818, | ||
108 | 65832,65847,65862,65877,65892,65907,65922,65936,65951,65966,65981,65996, | ||
109 | 66011,66026,66041,66056,66071,66085,66100,66115,66130,66145,66160,66175, | ||
110 | 66190,66205,66220,66235,66250,66265,66280,66294,66309,66324,66339,66354, | ||
111 | 66369,66384,66399,66414,66429,66444,66459,66474,66489,66504,66519,66534, | ||
112 | 66549,66564,66579,66594,66609,66624,66639,66654,66670,66685,66700,66715, | ||
113 | 66730,66745,66760,66775,66790,66805,66820,66835,66850,66865,66880,66896, | ||
114 | 66911,66926,66941,66956,66971,66986,67001,67016,67032,67047,67062,67077, | ||
115 | 67092,67107,67122,67137,67153,67168,67183,67198,67213,67228,67244,67259, | ||
116 | 67274,67289,67304,67320,67335,67350,67365,67380,67395,67411,67426,67441, | ||
117 | 67456,67472,67487,67502,67517,67532,67548,67563,67578,67593,67609,67624, | ||
118 | 67639,67655,67670,67685,67700,67716,67731,67746,67761,67777,67792,67807, | ||
119 | 67823,67838,67853,67869,67884,67899,67915,67930,67945,67961,67976,67991, | ||
120 | 68007,68022,68037,68053,68068,68083,68099,68114,68129,68145,68160,68176, | ||
121 | 68191,68206,68222,68237,68252,68268,68283,68299,68314,68330,68345,68360, | ||
122 | 68376,68391,68407,68422,68438,68453,68468,68484,68499,68515,68530,68546, | ||
123 | 68561,68577,68592,68608,68623,68639,68654,68670,68685,68701,68716,68732, | ||
124 | 68747,68763,68778,68794,68809,68825,68840,68856,68871,68887,68902,68918, | ||
125 | 68933,68949,68965,68980,68996,69011,69027,69042,69058,69074,69089,69105, | ||
126 | 69120,69136,69152,69167,69183,69198,69214,69230,69245,69261,69276,69292, | ||
127 | 69308,69323,69339,69355,69370,69386,69402,69417,69433 | ||
128 | |||
129 | }; | ||
130 | |||
131 | /* | ||
79 | 58386,58412,58439,58465,58491,58518,58544,58571,58597,58624,58650,58676, | 132 | 58386,58412,58439,58465,58491,58518,58544,58571,58597,58624,58650,58676, |
80 | 58703,58729,58756,58782,58809,58836,58862,58889,58915,58942,58968,58995, | 133 | 58703,58729,58756,58782,58809,58836,58862,58889,58915,58942,58968,58995, |
81 | 59022,59048,59075,59102,59128,59155,59182,59208,59235,59262,59289,59315, | 134 | 59022,59048,59075,59102,59128,59155,59182,59208,59235,59262,59289,59315, |
@@ -119,7 +172,10 @@ const uint32_t pitchTbl[] ICONST_ATTR={ | |||
119 | 72507,72540,72573,72605,72638,72671,72704,72736,72769,72802,72835,72868, | 172 | 72507,72540,72573,72605,72638,72671,72704,72736,72769,72802,72835,72868, |
120 | 72901,72934,72967,72999,73032,73065,73098,73131,73164,73197,73230,73264, | 173 | 72901,72934,72967,72999,73032,73065,73098,73131,73164,73197,73230,73264, |
121 | 73297,73330,73363,73396,73429,73462,73495,73528 | 174 | 73297,73330,73363,73396,73429,73462,73495,73528 |
122 | }; | 175 | };*/ |
176 | |||
177 | |||
178 | |||
123 | 179 | ||
124 | static void findDelta(struct SynthObject * so, int ch, int note) | 180 | static void findDelta(struct SynthObject * so, int ch, int note) |
125 | { | 181 | { |
@@ -128,8 +184,15 @@ static void findDelta(struct SynthObject * so, int ch, int note) | |||
128 | so->wf=wf; | 184 | so->wf=wf; |
129 | unsigned int delta= 0; | 185 | unsigned int delta= 0; |
130 | 186 | ||
131 | delta = (((gustable[note]<<FRACTSIZE) / (wf->rootFreq)) * wf->sampRate / (SAMPLE_RATE)); | 187 | int totalBend = (chPW[ch]-256) * chPBDepth[ch]; |
132 | delta = (delta * pitchTbl[chPW[ch]])>> 16; | 188 | |
189 | int noteOffset = totalBend >> 8; | ||
190 | |||
191 | int pitchOffset = totalBend - (noteOffset<<8); | ||
192 | |||
193 | |||
194 | delta = (((gustable[note+noteOffset]<<FRACTSIZE) / (wf->rootFreq)) * wf->sampRate / (SAMPLE_RATE)); | ||
195 | delta = (delta * pitchTbl[pitchOffset+256])>> 16; | ||
133 | 196 | ||
134 | so->delta = delta; | 197 | so->delta = delta; |
135 | } | 198 | } |
@@ -280,6 +343,13 @@ static void sendEvent(struct Event * ev) | |||
280 | chPan[status_low]=d2; | 343 | chPan[status_low]=d2; |
281 | return; | 344 | return; |
282 | } | 345 | } |
346 | case CTRL_PWDEPTH: | ||
347 | { | ||
348 | /* TODO: Update all deltas. Is this really needed? */ | ||
349 | chPBDepth[status_low] = d2; | ||
350 | return; | ||
351 | } | ||
352 | |||
283 | } | 353 | } |
284 | break; | 354 | break; |
285 | 355 | ||
@@ -293,7 +363,7 @@ static void sendEvent(struct Event * ev) | |||
293 | case 0: /* Release by vol=0 */ | 363 | case 0: /* Release by vol=0 */ |
294 | releaseNote(status_low, d1); | 364 | releaseNote(status_low, d1); |
295 | return; | 365 | return; |
296 | 366 | ||
297 | default: | 367 | default: |
298 | pressNote(status_low, d1, d2); | 368 | pressNote(status_low, d1, d2); |
299 | return; | 369 | return; |
diff --git a/apps/plugins/midi/synth.c b/apps/plugins/midi/synth.c index 568c7bb1ce..f0fa93d60e 100644 --- a/apps/plugins/midi/synth.c +++ b/apps/plugins/midi/synth.c | |||
@@ -65,6 +65,7 @@ int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig) | |||
65 | chPan[a]=64; /* Center */ | 65 | chPan[a]=64; /* Center */ |
66 | chPat[a]=0; /* Ac Gr Piano */ | 66 | chPat[a]=0; /* Ac Gr Piano */ |
67 | chPW[a]=256; /* .. not .. bent ? */ | 67 | chPW[a]=256; /* .. not .. bent ? */ |
68 | chPBDepth[a]=2; /* Default bend value is 2 */ | ||
68 | } | 69 | } |
69 | for(a=0; a<128; a++) | 70 | for(a=0; a<128; a++) |
70 | { | 71 | { |
@@ -255,191 +256,195 @@ inline void stopVoice(struct SynthObject * so) | |||
255 | so->decay = 0; | 256 | so->decay = 0; |
256 | } | 257 | } |
257 | 258 | ||
258 | static inline int synthVoice(struct SynthObject * so) | 259 | static inline void synthVoice(struct SynthObject * so, int32_t * out, unsigned int samples) |
259 | { | 260 | { |
260 | struct GWaveform * wf; | 261 | struct GWaveform * wf; |
261 | register int s; | 262 | register int s; |
262 | register unsigned int cpShifted; | 263 | register int s1; |
263 | register short s1; | 264 | register int s2; |
264 | register short s2; | 265 | |
266 | register unsigned int cp_temp = so->cp; | ||
265 | 267 | ||
266 | wf = so->wf; | 268 | wf = so->wf; |
267 | 269 | ||
270 | const int mode_mask24 = wf->mode&24; | ||
271 | const int mode_mask28 = wf->mode&28; | ||
272 | const int mode_mask_looprev = wf->mode&LOOP_REVERSE; | ||
268 | 273 | ||
269 | /* Is voice being ramped? */ | 274 | const unsigned int num_samples = (wf->numSamples-1) << FRACTSIZE; |
270 | if(so->state == STATE_RAMPDOWN) | ||
271 | { | ||
272 | if(so->decay != 0) /* Ramp has been started */ | ||
273 | { | ||
274 | so->decay = so->decay / 2; | ||
275 | 275 | ||
276 | if(so->decay < 10 && so->decay > -10) | 276 | const unsigned int end_loop = wf->endLoop << FRACTSIZE; |
277 | so->isUsed = 0; | 277 | const unsigned int start_loop = wf->startLoop << FRACTSIZE; |
278 | const int diff_loop = end_loop-start_loop; | ||
278 | 279 | ||
279 | return so->decay; | 280 | while(samples > 0) |
280 | } | ||
281 | } else /* OK to advance voice */ | ||
282 | { | 281 | { |
283 | so->cp += so->delta; | 282 | samples--; |
284 | } | 283 | /* Is voice being ramped? */ |
285 | 284 | if(so->state == STATE_RAMPDOWN) | |
286 | 285 | { | |
287 | cpShifted = so->cp >> FRACTSIZE; | 286 | if(so->decay != 0) /* Ramp has been started */ |
287 | { | ||
288 | so->decay = so->decay / 2; | ||
288 | 289 | ||
290 | if(so->decay < 10 && so->decay > -10) | ||
291 | so->isUsed = 0; | ||
289 | 292 | ||
293 | s1=so->decay; | ||
294 | s2 = s1*chPan[so->ch]; | ||
295 | s1 = (s1<<7) -s2; | ||
296 | *(out++)+=(((s1&0x7FFF80) << 9) | ((s2&0x7FFF80) >> 7)); | ||
297 | continue; | ||
298 | } | ||
299 | } else /* OK to advance voice */ | ||
300 | { | ||
301 | cp_temp += so->delta; | ||
302 | } | ||
290 | 303 | ||
291 | s2 = getSample((cpShifted)+1, wf); | 304 | s2 = getSample((cp_temp >> FRACTSIZE)+1, wf); |
292 | 305 | ||
293 | /* LOOP_REVERSE|LOOP_PINGPONG = 24 */ | 306 | /* LOOP_REVERSE|LOOP_PINGPONG = 24 */ |
294 | if((wf->mode & (24)) && so->loopState == STATE_LOOPING && (cpShifted < (wf->startLoop))) | 307 | if(mode_mask24 && so->loopState == STATE_LOOPING && (cp_temp < start_loop)) |
295 | { | ||
296 | if(wf->mode & LOOP_REVERSE) | ||
297 | { | ||
298 | cpShifted = wf->endLoop-(wf->startLoop-cpShifted); | ||
299 | so->cp = (cpShifted)<<FRACTSIZE; | ||
300 | s2=getSample((cpShifted), wf); | ||
301 | } | ||
302 | else | ||
303 | { | 308 | { |
304 | so->delta = -so->delta; /* At this point cpShifted is wrong. We need to take a step */ | 309 | if(mode_mask_looprev) |
305 | so->loopDir = LOOPDIR_FORWARD; | 310 | { |
311 | cp_temp += diff_loop; | ||
312 | s2=getSample((cp_temp >> FRACTSIZE), wf); | ||
313 | } | ||
314 | else | ||
315 | { | ||
316 | so->delta = -so->delta; /* At this point cp_temp is wrong. We need to take a step */ | ||
317 | so->loopDir = LOOPDIR_FORWARD; | ||
318 | } | ||
306 | } | 319 | } |
307 | } | ||
308 | 320 | ||
309 | if((wf->mode & 28) && (cpShifted >= wf->endLoop)) | 321 | if(mode_mask28 && (cp_temp >= end_loop)) |
310 | { | ||
311 | so->loopState = STATE_LOOPING; | ||
312 | if((wf->mode & (24)) == 0) | ||
313 | { | 322 | { |
314 | cpShifted = wf->startLoop + (cpShifted-wf->endLoop); | 323 | so->loopState = STATE_LOOPING; |
315 | so->cp = (cpShifted)<<FRACTSIZE; | 324 | if(!mode_mask24) |
316 | s2=getSample((cpShifted), wf); | 325 | { |
326 | cp_temp -= diff_loop; | ||
327 | s2=getSample((cp_temp >> FRACTSIZE), wf); | ||
328 | } | ||
329 | else | ||
330 | { | ||
331 | so->delta = -so->delta; | ||
332 | so->loopDir = LOOPDIR_REVERSE; | ||
333 | } | ||
317 | } | 334 | } |
318 | else | 335 | |
336 | /* Have we overrun? */ | ||
337 | if(cp_temp >= num_samples) | ||
319 | { | 338 | { |
320 | so->delta = -so->delta; | 339 | cp_temp -= so->delta; |
321 | so->loopDir = LOOPDIR_REVERSE; | 340 | s2 = getSample((cp_temp >> FRACTSIZE)+1, wf); |
341 | stopVoice(so); | ||
322 | } | 342 | } |
323 | } | ||
324 | |||
325 | /* Have we overrun? */ | ||
326 | if( (cpShifted >= (wf->numSamples-1))) | ||
327 | { | ||
328 | so->cp -= so->delta; | ||
329 | cpShifted = so->cp >> FRACTSIZE; | ||
330 | s2 = getSample((cpShifted)+1, wf); | ||
331 | stopVoice(so); | ||
332 | } | ||
333 | |||
334 | |||
335 | /* Better, working, linear interpolation */ | ||
336 | s1=getSample((cpShifted), wf); | ||
337 | 343 | ||
338 | s = s1 + ((signed)((s2 - s1) * (so->cp & ((1<<FRACTSIZE)-1)))>>FRACTSIZE); | 344 | /* Better, working, linear interpolation */ |
345 | s1=getSample((cp_temp >> FRACTSIZE), wf); | ||
339 | 346 | ||
347 | s = s1 + ((signed)((s2 - s1) * (cp_temp & ((1<<FRACTSIZE)-1)))>>FRACTSIZE); | ||
340 | 348 | ||
341 | if(so->curRate == 0) | 349 | if(so->curRate == 0) |
342 | { | 350 | { |
343 | stopVoice(so); | 351 | stopVoice(so); |
344 | // so->isUsed = 0; | 352 | // so->isUsed = 0; |
345 | 353 | ||
346 | } | 354 | } |
347 | 355 | ||
348 | if(so->ch != 9 && so->state != STATE_RAMPDOWN) /* Stupid ADSR code... and don't do ADSR for drums */ | 356 | if(so->ch != 9 && so->state != STATE_RAMPDOWN) /* Stupid ADSR code... and don't do ADSR for drums */ |
349 | { | ||
350 | if(so->curOffset < so->targetOffset) | ||
351 | { | 357 | { |
352 | so->curOffset += (so->curRate); | 358 | if(so->curOffset < so->targetOffset) |
353 | if(so -> curOffset > so->targetOffset && so->curPoint != 2) | ||
354 | { | 359 | { |
355 | if(so->curPoint != 5) | 360 | so->curOffset += (so->curRate); |
361 | if(so -> curOffset > so->targetOffset && so->curPoint != 2) | ||
356 | { | 362 | { |
357 | setPoint(so, so->curPoint+1); | 363 | if(so->curPoint != 5) |
364 | { | ||
365 | setPoint(so, so->curPoint+1); | ||
366 | } | ||
367 | else | ||
368 | { | ||
369 | stopVoice(so); | ||
370 | } | ||
358 | } | 371 | } |
359 | else | 372 | } else |
373 | { | ||
374 | so->curOffset -= (so->curRate); | ||
375 | if(so -> curOffset < so->targetOffset && so->curPoint != 2) | ||
360 | { | 376 | { |
361 | stopVoice(so); | 377 | |
378 | if(so->curPoint != 5) | ||
379 | { | ||
380 | setPoint(so, so->curPoint+1); | ||
381 | } | ||
382 | else | ||
383 | { | ||
384 | stopVoice(so); | ||
385 | } | ||
386 | |||
362 | } | 387 | } |
363 | } | 388 | } |
364 | } else | 389 | } |
390 | |||
391 | if(so->curOffset < 0) | ||
365 | { | 392 | { |
366 | so->curOffset -= (so->curRate); | 393 | so->curOffset = so->targetOffset; |
367 | if(so -> curOffset < so->targetOffset && so->curPoint != 2) | 394 | stopVoice(so); |
368 | { | 395 | } |
369 | 396 | ||
370 | if(so->curPoint != 5) | 397 | s = (s * (so->curOffset >> 22) >> 8); |
371 | { | ||
372 | setPoint(so, so->curPoint+1); | ||
373 | } | ||
374 | else | ||
375 | { | ||
376 | stopVoice(so); | ||
377 | } | ||
378 | 398 | ||
379 | } | 399 | /* need to set ramp beginning */ |
400 | if(so->state == STATE_RAMPDOWN && so->decay == 0) | ||
401 | { | ||
402 | so->decay = s*so->volscale>>14; | ||
403 | if(so->decay == 0) | ||
404 | so->decay = 1; /* stupid junk.. */ | ||
380 | } | 405 | } |
381 | } | ||
382 | 406 | ||
383 | if(so->curOffset < 0) | ||
384 | { | ||
385 | so->curOffset = so->targetOffset; | ||
386 | stopVoice(so); | ||
387 | } | ||
388 | 407 | ||
389 | s = (s * (so->curOffset >> 22) >> 8); | 408 | /* Scaling by channel volume and note volume is done in sequencer.c */ |
409 | /* That saves us some multiplication and pointer operations */ | ||
410 | s1=s*so->volscale>>14; | ||
390 | 411 | ||
412 | s2 = s1*chPan[so->ch]; | ||
413 | s1 = (s1<<7) - s2; | ||
414 | *(out++)+=(((s1&0x7FFF80) << 9) | ((s2&0x7FFF80) >> 7)); | ||
391 | 415 | ||
392 | /* need to set ramp beginning */ | ||
393 | if(so->state == STATE_RAMPDOWN && so->decay == 0) | ||
394 | { | ||
395 | so->decay = s*so->volscale>>14; | ||
396 | if(so->decay == 0) | ||
397 | so->decay = 1; /* stupid junk.. */ | ||
398 | } | 416 | } |
399 | 417 | ||
400 | 418 | so->cp=cp_temp; /* store this again */ | |
401 | /* Scaling by channel volume and note volume is done in sequencer.c */ | 419 | return; |
402 | /* That saves us some multiplication and pointer operations */ | ||
403 | return s*so->volscale>>14; | ||
404 | } | 420 | } |
405 | 421 | ||
422 | /* buffer to hold all the samples for the current tick, this is a hack | ||
423 | neccesary for coldfire targets as pcm_play_data uses the dma which cannot | ||
424 | access iram */ | ||
425 | int32_t samp_buf[256] IBSS_ATTR; | ||
426 | |||
406 | /* synth num_samples samples and write them to the */ | 427 | /* synth num_samples samples and write them to the */ |
407 | /* buffer pointed to by buf_ptr */ | 428 | /* buffer pointed to by buf_ptr */ |
408 | void synthSamples(int32_t *buf_ptr, unsigned int num_samples) ICODE_ATTR; | 429 | void synthSamples(int32_t *buf_ptr, unsigned int num_samples) ICODE_ATTR; |
409 | void synthSamples(int32_t *buf_ptr, unsigned int num_samples) | 430 | void synthSamples(int32_t *buf_ptr, unsigned int num_samples) |
410 | { | 431 | { |
411 | int i; | 432 | int i; |
412 | register int dL; | 433 | struct SynthObject *voicept; |
413 | register int dR; | 434 | |
414 | register int sample; | 435 | rb->memset(samp_buf, 0, num_samples*4); |
415 | register struct SynthObject *voicept; | ||
416 | while(num_samples>0) | ||
417 | { | ||
418 | dL=0; | ||
419 | dR=0; | ||
420 | voicept=&voices[0]; | ||
421 | 436 | ||
422 | for(i=MAX_VOICES; i > 0; i--) | 437 | for(i=0; i < MAX_VOICES; i++) |
438 | { | ||
439 | voicept=&voices[i]; | ||
440 | if(voicept->isUsed==1) | ||
423 | { | 441 | { |
424 | if(voicept->isUsed==1) | 442 | synthVoice(voicept, samp_buf, num_samples); |
425 | { | ||
426 | sample = synthVoice(voicept); | ||
427 | dL += sample; | ||
428 | sample *= chPan[voicept->ch]; | ||
429 | dR += sample; | ||
430 | } | ||
431 | voicept++; | ||
432 | } | 443 | } |
444 | } | ||
433 | 445 | ||
434 | dL = (dL << 7) - dR; | 446 | rb->memcpy(buf_ptr, samp_buf, num_samples*4); |
435 | |||
436 | /* combine the left and right 16 bit samples into 32 bits and write */ | ||
437 | /* to the buffer, left sample in the high word and right in the low word */ | ||
438 | *buf_ptr=(((dL&0x7FFF80) << 9) | ((dR&0x7FFF80) >> 7)); | ||
439 | 447 | ||
440 | buf_ptr++; | ||
441 | num_samples--; | ||
442 | } | ||
443 | /* TODO: Automatic Gain Control, anyone? */ | 448 | /* TODO: Automatic Gain Control, anyone? */ |
444 | /* Or, should this be implemented on the DSP's output volume instead? */ | 449 | /* Or, should this be implemented on the DSP's output volume instead? */ |
445 | 450 | ||