diff options
author | Nils Wallménius <nils@rockbox.org> | 2007-10-08 19:28:41 +0000 |
---|---|---|
committer | Nils Wallménius <nils@rockbox.org> | 2007-10-08 19:28:41 +0000 |
commit | f619f8167646632d6eab10f529638eebbdda6af6 (patch) | |
tree | 119a1f4051d59808a25612421f613cb09ee1e9d5 /apps/plugins | |
parent | d712e252fecf814a48814034a55ba60a1b194598 (diff) | |
download | rockbox-f619f8167646632d6eab10f529638eebbdda6af6.tar.gz rockbox-f619f8167646632d6eab10f529638eebbdda6af6.zip |
Change loop structure for sample synthesizing. Gives a nice speedup on both coldfire and arm targets.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15036 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
-rw-r--r-- | apps/plugins/midi/midiplay.c | 39 | ||||
-rw-r--r-- | apps/plugins/midi/synth.c | 46 | ||||
-rw-r--r-- | apps/plugins/midi/synth.h | 55 |
3 files changed, 64 insertions, 76 deletions
diff --git a/apps/plugins/midi/midiplay.c b/apps/plugins/midi/midiplay.c index c557433dce..99f05718d6 100644 --- a/apps/plugins/midi/midiplay.c +++ b/apps/plugins/midi/midiplay.c | |||
@@ -148,32 +148,31 @@ bool lastswap=1; | |||
148 | 148 | ||
149 | static inline void synthbuf(void) | 149 | static inline void synthbuf(void) |
150 | { | 150 | { |
151 | int32_t *outptr; | 151 | int32_t *outptr; |
152 | register int i; | 152 | int i; |
153 | int currentSample=0; | ||
154 | int synthtemp[2]; | ||
155 | 153 | ||
156 | #ifndef SYNC | 154 | #ifndef SYNC |
157 | if(lastswap==swap) return; | 155 | if(lastswap==swap) return; |
158 | lastswap=swap; | 156 | lastswap=swap; |
159 | 157 | ||
160 | outptr=(swap ? gmbuf : gmbuf+BUF_SIZE); | 158 | outptr=(swap ? gmbuf : gmbuf+BUF_SIZE); |
161 | #else | 159 | #else |
162 | outptr=gmbuf; | 160 | outptr=gmbuf; |
163 | #endif | 161 | #endif |
164 | 162 | ||
165 | for(i=0; i<BUF_SIZE; i++) | 163 | for(i=0; i<BUF_SIZE/numberOfSamples; i++) |
166 | { | 164 | { |
167 | synthSample(&synthtemp[0], &synthtemp[1]); | 165 | synthSamples((int32_t*)outptr, numberOfSamples); |
168 | currentSample++; | 166 | outptr += numberOfSamples; |
169 | *outptr=((synthtemp[0]&0xFFFF) << 16) | (synthtemp[1]&0xFFFF); | 167 | if( tick() == 0 ) |
170 | outptr++; | 168 | quit=1; |
171 | if(currentSample==numberOfSamples) | 169 | } |
172 | { | 170 | |
173 | if( tick() == 0 ) quit=1; | 171 | if(BUF_SIZE%numberOfSamples) |
174 | currentSample=0; | 172 | { |
175 | } | 173 | synthSamples((int32_t*)outptr, BUF_SIZE%numberOfSamples); |
176 | } | 174 | outptr += BUF_SIZE%numberOfSamples; |
175 | } | ||
177 | } | 176 | } |
178 | 177 | ||
179 | void get_more(unsigned char** start, size_t* size) | 178 | void get_more(unsigned char** start, size_t* size) |
diff --git a/apps/plugins/midi/synth.c b/apps/plugins/midi/synth.c index 327f32e288..568c7bb1ce 100644 --- a/apps/plugins/midi/synth.c +++ b/apps/plugins/midi/synth.c | |||
@@ -255,8 +255,7 @@ inline void stopVoice(struct SynthObject * so) | |||
255 | so->decay = 0; | 255 | so->decay = 0; |
256 | } | 256 | } |
257 | 257 | ||
258 | int synthVoice(struct SynthObject * so) ICODE_ATTR; | 258 | static inline int synthVoice(struct SynthObject * so) |
259 | int synthVoice(struct SynthObject * so) | ||
260 | { | 259 | { |
261 | struct GWaveform * wf; | 260 | struct GWaveform * wf; |
262 | register int s; | 261 | register int s; |
@@ -404,3 +403,46 @@ int synthVoice(struct SynthObject * so) | |||
404 | return s*so->volscale>>14; | 403 | return s*so->volscale>>14; |
405 | } | 404 | } |
406 | 405 | ||
406 | /* synth num_samples samples and write them to the */ | ||
407 | /* buffer pointed to by buf_ptr */ | ||
408 | void synthSamples(int32_t *buf_ptr, unsigned int num_samples) ICODE_ATTR; | ||
409 | void synthSamples(int32_t *buf_ptr, unsigned int num_samples) | ||
410 | { | ||
411 | int i; | ||
412 | register int dL; | ||
413 | register int dR; | ||
414 | register int sample; | ||
415 | register struct SynthObject *voicept; | ||
416 | while(num_samples>0) | ||
417 | { | ||
418 | dL=0; | ||
419 | dR=0; | ||
420 | voicept=&voices[0]; | ||
421 | |||
422 | for(i=MAX_VOICES; i > 0; i--) | ||
423 | { | ||
424 | if(voicept->isUsed==1) | ||
425 | { | ||
426 | sample = synthVoice(voicept); | ||
427 | dL += sample; | ||
428 | sample *= chPan[voicept->ch]; | ||
429 | dR += sample; | ||
430 | } | ||
431 | voicept++; | ||
432 | } | ||
433 | |||
434 | dL = (dL << 7) - dR; | ||
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 | |||
440 | buf_ptr++; | ||
441 | num_samples--; | ||
442 | } | ||
443 | /* TODO: Automatic Gain Control, anyone? */ | ||
444 | /* Or, should this be implemented on the DSP's output volume instead? */ | ||
445 | |||
446 | return; /* No more ghetto lowpass filter. Linear interpolation works well. */ | ||
447 | } | ||
448 | |||
diff --git a/apps/plugins/midi/synth.h b/apps/plugins/midi/synth.h index e04f9f4bd5..5f9edf89e5 100644 --- a/apps/plugins/midi/synth.h +++ b/apps/plugins/midi/synth.h | |||
@@ -17,61 +17,8 @@ | |||
17 | * | 17 | * |
18 | ****************************************************************************/ | 18 | ****************************************************************************/ |
19 | int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig); | 19 | int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig); |
20 | int synthVoice(struct SynthObject * so); | ||
21 | void setPoint(struct SynthObject * so, int pt); | 20 | void setPoint(struct SynthObject * so, int pt); |
22 | 21 | void synthSamples(int32_t *buf_ptr, unsigned int num_samples); | |
23 | static inline void synthSample(int * mixL, int * mixR) | ||
24 | { | ||
25 | int i; | ||
26 | register int dL=0; | ||
27 | register int dR=0; | ||
28 | register int sample = 0; | ||
29 | register struct SynthObject *voicept=voices; | ||
30 | |||
31 | for(i=MAX_VOICES/2; i > 0; i--) | ||
32 | { | ||
33 | if(voicept->isUsed==1) | ||
34 | { | ||
35 | sample = synthVoice(voicept); | ||
36 | dL += sample; | ||
37 | sample *= chPan[voicept->ch]; | ||
38 | dR += sample; | ||
39 | } | ||
40 | voicept++; | ||
41 | if(voicept->isUsed==1) | ||
42 | { | ||
43 | sample = synthVoice(voicept); | ||
44 | dL += sample; | ||
45 | sample *= chPan[voicept->ch]; | ||
46 | dR += sample; | ||
47 | } | ||
48 | voicept++; | ||
49 | } | ||
50 | |||
51 | /* if MAX_VOICES is not even we do this to get the last voice */ | ||
52 | #if MAX_VOICES%2 | ||
53 | if (MAX_VOICES%2) | ||
54 | { | ||
55 | if(voicept->isUsed==1) | ||
56 | { | ||
57 | sample = synthVoice(voicept); | ||
58 | dL += sample; | ||
59 | sample *= chPan[voicept->ch]; | ||
60 | dR += sample; | ||
61 | } | ||
62 | } | ||
63 | #endif | ||
64 | |||
65 | dL = (dL << 7) - dR; | ||
66 | |||
67 | *mixL=dL >> 7; | ||
68 | *mixR=dR >> 7; | ||
69 | |||
70 | /* TODO: Automatic Gain Control, anyone? */ | ||
71 | /* Or, should this be implemented on the DSP's output volume instead? */ | ||
72 | |||
73 | return; /* No more ghetto lowpass filter. Linear interpolation works well. */ | ||
74 | } | ||
75 | 22 | ||
76 | static inline struct Event * getEvent(struct Track * tr, int evNum) | 23 | static inline struct Event * getEvent(struct Track * tr, int evNum) |
77 | { | 24 | { |