diff options
author | Stepan Moskovchenko <stevenm@rockbox.org> | 2006-05-03 19:32:22 +0000 |
---|---|---|
committer | Stepan Moskovchenko <stevenm@rockbox.org> | 2006-05-03 19:32:22 +0000 |
commit | 28b5afd05a075cce1f46e5cc85c7e2caae3fc6ee (patch) | |
tree | d7285c0d7afb20145a0a9918b17827ed59a1cc9b /apps/plugins | |
parent | 7f1d21480127c9246d2aa7a329f74fd8754b1e42 (diff) | |
download | rockbox-28b5afd05a075cce1f46e5cc85c7e2caae3fc6ee.tar.gz rockbox-28b5afd05a075cce1f46e5cc85c7e2caae3fc6ee.zip |
Optimize synth code by pre-computing the volume scaling for each note.
Scaling is now calculated once per MIDI event at the most, instead of
once per sample. Increase voice ramping speed, increase number of
active voices a little.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9870 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
-rw-r--r-- | apps/plugins/midi/midiutil.c | 1 | ||||
-rw-r--r-- | apps/plugins/midi/sequencer.c | 47 | ||||
-rw-r--r-- | apps/plugins/midi/synth.c | 12 | ||||
-rw-r--r-- | apps/plugins/midiplay.c | 2 |
4 files changed, 35 insertions, 27 deletions
diff --git a/apps/plugins/midi/midiutil.c b/apps/plugins/midi/midiutil.c index daadae8a4f..08e6dbac65 100644 --- a/apps/plugins/midi/midiutil.c +++ b/apps/plugins/midi/midiutil.c | |||
@@ -127,6 +127,7 @@ struct SynthObject | |||
127 | int note, vol, ch, isUsed; | 127 | int note, vol, ch, isUsed; |
128 | int curRate, curOffset, targetOffset; | 128 | int curRate, curOffset, targetOffset; |
129 | int curPoint; | 129 | int curPoint; |
130 | signed short int volscale; | ||
130 | }; | 131 | }; |
131 | 132 | ||
132 | struct SynthObject voices[MAX_VOICES] IBSS_ATTR; | 133 | struct SynthObject voices[MAX_VOICES] IBSS_ATTR; |
diff --git a/apps/plugins/midi/sequencer.c b/apps/plugins/midi/sequencer.c index b6fb592294..ebd5b76405 100644 --- a/apps/plugins/midi/sequencer.c +++ b/apps/plugins/midi/sequencer.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * | 16 | * |
17 | ****************************************************************************/ | 17 | ****************************************************************************/ |
18 | 18 | ||
19 | void setVolScale(int a); | ||
19 | 20 | ||
20 | extern struct plugin_api * rb; | 21 | extern struct plugin_api * rb; |
21 | 22 | ||
@@ -24,8 +25,14 @@ long tempo=375000; | |||
24 | 25 | ||
25 | inline void setVol(int ch, int vol) | 26 | inline void setVol(int ch, int vol) |
26 | { | 27 | { |
27 | // printf("\nvolume[%d] %d ==> %d", ch, chVol[ch], vol); | 28 | int a=0; |
28 | chVol[ch]=vol; | 29 | chVol[ch]=vol; |
30 | |||
31 | /* If channel volume changes, we need to recalculate the volume scale */ | ||
32 | /* factor for all voices active on this channel */ | ||
33 | for(a=0; a<MAX_VOICES; a++) | ||
34 | if(voices[a].ch == ch) | ||
35 | setVolScale(a); | ||
29 | } | 36 | } |
30 | 37 | ||
31 | inline void setPan(int ch, int pan) | 38 | inline void setPan(int ch, int pan) |
@@ -111,25 +118,13 @@ long pitchTbl[] ICONST_ATTR={ | |||
111 | 72901,72934,72967,72999,73032,73065,73098,73131,73164,73197,73230,73264, | 118 | 72901,72934,72967,72999,73032,73065,73098,73131,73164,73197,73230,73264, |
112 | 73297,73330,73363,73396,73429,73462,73495,73528 | 119 | 73297,73330,73363,73396,73429,73462,73495,73528 |
113 | }; | 120 | }; |
114 | /* | ||
115 | void findDelta(struct SynthObject * so, int ch, int note) | ||
116 | { | ||
117 | |||
118 | struct GWaveform * wf = patchSet[chPat[ch]]->waveforms[patchSet[chPat[ch]]->noteTable[note]]; | ||
119 | so->wf=wf; // \|/ was 10 | ||
120 | so->delta = (((gustable[note]<<10) / (wf->rootFreq)) * wf->sampRate / (SAMPLE_RATE)); | ||
121 | so->delta = (so->delta * pitchTbl[chPW[ch]])>> 16; | ||
122 | } | ||
123 | */ | ||
124 | |||
125 | 121 | ||
126 | void findDelta(struct SynthObject * so, int ch, int note) | 122 | void findDelta(struct SynthObject * so, int ch, int note) |
127 | { | 123 | { |
128 | 124 | ||
129 | struct GWaveform * wf = patchSet[chPat[ch]]->waveforms[patchSet[chPat[ch]]->noteTable[note]]; | 125 | struct GWaveform * wf = patchSet[chPat[ch]]->waveforms[patchSet[chPat[ch]]->noteTable[note]]; |
130 | so->wf=wf; // \|/ was 10 | 126 | so->wf=wf; |
131 | 127 | unsigned long delta= 0; /* More percision- extra bit - not so off-key as before */ | |
132 | unsigned long delta= 0 ; | ||
133 | 128 | ||
134 | delta = (((gustable[note]<<FRACTSIZE) / (wf->rootFreq)) * wf->sampRate / (SAMPLE_RATE)); | 129 | delta = (((gustable[note]<<FRACTSIZE) / (wf->rootFreq)) * wf->sampRate / (SAMPLE_RATE)); |
135 | delta = (delta * pitchTbl[chPW[ch]])>> 16; | 130 | delta = (delta * pitchTbl[chPW[ch]])>> 16; |
@@ -139,7 +134,6 @@ void findDelta(struct SynthObject * so, int ch, int note) | |||
139 | 134 | ||
140 | inline void setPW(int ch, int msb, int lsb) | 135 | inline void setPW(int ch, int msb, int lsb) |
141 | { | 136 | { |
142 | // printf("\npitchw[%d] %d ==> %d", ch, chPW[ch], msb); | ||
143 | chPW[ch] = msb<<2|lsb>>5; | 137 | chPW[ch] = msb<<2|lsb>>5; |
144 | 138 | ||
145 | int a=0; | 139 | int a=0; |
@@ -152,16 +146,26 @@ inline void setPW(int ch, int msb, int lsb) | |||
152 | } | 146 | } |
153 | } | 147 | } |
154 | 148 | ||
149 | |||
150 | /* Sets the volume scaling by channel volume and note volume */ | ||
151 | /* This way we can do the multiplication/indexing once per */ | ||
152 | /* MIDI event at the most, instead of once per sample. */ | ||
153 | void setVolScale(int a) | ||
154 | { | ||
155 | struct SynthObject * so = &voices[a]; | ||
156 | so->volscale = ((signed short int)so->vol*(signed short int)chVol[so->ch]); | ||
157 | } | ||
158 | |||
155 | void pressNote(int ch, int note, int vol) | 159 | void pressNote(int ch, int note, int vol) |
156 | { | 160 | { |
157 | static int lastKill = 0; | 161 | static int lastKill = 0; |
158 | //Silences all channels but one, for easy debugging, for me. | 162 | /* Silences all channels but one, for easy debugging, for me. */ |
159 | /* | 163 | /* |
160 | if(ch == 0) return; | 164 | if(ch == 0) return; |
161 | if(ch == 1) return; | 165 | if(ch == 1) return; |
162 | if(ch == 2) return; | 166 | if(ch == 2) return; |
163 | if(ch == 3) return; | 167 | if(ch == 3) return; |
164 | // if(ch == 4) return; | 168 | if(ch == 4) return; |
165 | if(ch == 5) return; | 169 | if(ch == 5) return; |
166 | if(ch == 6) return; | 170 | if(ch == 6) return; |
167 | if(ch == 7) return; | 171 | if(ch == 7) return; |
@@ -203,6 +207,7 @@ void pressNote(int ch, int note, int vol) | |||
203 | voices[a].state=STATE_ATTACK; | 207 | voices[a].state=STATE_ATTACK; |
204 | voices[a].decay=255; | 208 | voices[a].decay=255; |
205 | 209 | ||
210 | setVolScale(a); | ||
206 | 211 | ||
207 | voices[a].loopState=STATE_NONLOOPING; | 212 | voices[a].loopState=STATE_NONLOOPING; |
208 | voices[a].loopDir = LOOPDIR_FORWARD; | 213 | voices[a].loopDir = LOOPDIR_FORWARD; |
@@ -304,9 +309,7 @@ void sendEvent(struct Event * ev) | |||
304 | 309 | ||
305 | if((ev->status & 0xF0) == MIDI_PRGM) | 310 | if((ev->status & 0xF0) == MIDI_PRGM) |
306 | { | 311 | { |
307 | if((ev->status & 0x0F) == 9) | 312 | if((ev->status & 0x0F) != 9) |
308 | printf("\nNOT PATCHING: Someone tried patching Channel 9 onto something?"); | ||
309 | else | ||
310 | setPatch(ev->status & 0x0F, ev->d1); | 313 | setPatch(ev->status & 0x0F, ev->d1); |
311 | } | 314 | } |
312 | } | 315 | } |
@@ -351,7 +354,7 @@ int tick(void) | |||
351 | if(e->d1 == 0x51) | 354 | if(e->d1 == 0x51) |
352 | { | 355 | { |
353 | tempo = (((short)e->evData[0])<<16)|(((short)e->evData[1])<<8)|(e->evData[2]); | 356 | tempo = (((short)e->evData[0])<<16)|(((short)e->evData[1])<<8)|(e->evData[2]); |
354 | printf("\nMeta-Event: Tempo Set = %d", tempo); | 357 | /* printf("\nMeta-Event: Tempo Set = %d", tempo); */ |
355 | bpm=mf->div*1000000/tempo; | 358 | bpm=mf->div*1000000/tempo; |
356 | numberOfSamples=SAMPLE_RATE/bpm; | 359 | numberOfSamples=SAMPLE_RATE/bpm; |
357 | 360 | ||
diff --git a/apps/plugins/midi/synth.c b/apps/plugins/midi/synth.c index a364889ea0..2b70074158 100644 --- a/apps/plugins/midi/synth.c +++ b/apps/plugins/midi/synth.c | |||
@@ -255,7 +255,6 @@ inline void stopVoice(struct SynthObject * so) | |||
255 | 255 | ||
256 | } | 256 | } |
257 | 257 | ||
258 | |||
259 | signed short int synthVoice(struct SynthObject * so) | 258 | signed short int synthVoice(struct SynthObject * so) |
260 | { | 259 | { |
261 | struct GWaveform * wf; | 260 | struct GWaveform * wf; |
@@ -362,16 +361,21 @@ signed short int synthVoice(struct SynthObject * so) | |||
362 | 361 | ||
363 | if(so->state == STATE_RAMPDOWN) | 362 | if(so->state == STATE_RAMPDOWN) |
364 | { | 363 | { |
365 | so->decay--; | 364 | so->decay-=5; |
366 | if(so->decay == 0) | 365 | if(so->decay < 5) |
367 | so->isUsed=0; | 366 | so->isUsed=0; |
368 | s = (s * so->decay) >> 8; | 367 | s = (s * so->decay) >> 8; |
369 | } | 368 | } |
370 | 369 | ||
371 | return s*((signed short int)so->vol*(signed short int)chVol[so->ch])>>14; | 370 | /* Scaling by channel volume and note volume is done in sequencer.c */ |
371 | /* That saves us some multiplication and pointer operations */ | ||
372 | return s*so->volscale>>14; | ||
372 | } | 373 | } |
373 | 374 | ||
374 | 375 | ||
376 | |||
377 | |||
378 | |||
375 | inline void synthSample(int * mixL, int * mixR) | 379 | inline void synthSample(int * mixL, int * mixR) |
376 | { | 380 | { |
377 | register int dL=0; | 381 | register int dL=0; |
diff --git a/apps/plugins/midiplay.c b/apps/plugins/midiplay.c index 8c15af3f2b..d420508473 100644 --- a/apps/plugins/midiplay.c +++ b/apps/plugins/midiplay.c | |||
@@ -22,7 +22,7 @@ PLUGIN_HEADER | |||
22 | 22 | ||
23 | #define FRACTSIZE 10 | 23 | #define FRACTSIZE 10 |
24 | #define SAMPLE_RATE 22050 // 44100 22050 11025 | 24 | #define SAMPLE_RATE 22050 // 44100 22050 11025 |
25 | #define MAX_VOICES 12 // Note: 24 midi channels is the minimum general midi | 25 | #define MAX_VOICES 13 // Note: 24 midi channels is the minimum general midi |
26 | // spec implementation | 26 | // spec implementation |
27 | #define BUF_SIZE 512 | 27 | #define BUF_SIZE 512 |
28 | #define NBUF 2 | 28 | #define NBUF 2 |