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
diff --git a/apps/plugins/midi/midiplay.c b/apps/plugins/midi/midiplay.c
index c557433..99f0571 100644
--- a/apps/plugins/midi/midiplay.c
+++ b/apps/plugins/midi/midiplay.c
@@ -148,32 +148,31 @@
 
 static inline void synthbuf(void)
 {
-   int32_t *outptr;
-   register int i;
-   int currentSample=0;
-   int synthtemp[2];
+    int32_t *outptr;
+    int i;
 
 #ifndef SYNC
-   if(lastswap==swap) return;
-   lastswap=swap;
+    if(lastswap==swap) return;
+    lastswap=swap;
 
-   outptr=(swap ? gmbuf : gmbuf+BUF_SIZE);
+    outptr=(swap ? gmbuf : gmbuf+BUF_SIZE);
 #else
-   outptr=gmbuf;
+    outptr=gmbuf;
 #endif
 
-   for(i=0; i<BUF_SIZE; i++)
-   {
-      synthSample(&synthtemp[0], &synthtemp[1]);
-      currentSample++;
-      *outptr=((synthtemp[0]&0xFFFF) << 16) | (synthtemp[1]&0xFFFF);
-      outptr++;
-      if(currentSample==numberOfSamples)
-      {
-         if( tick() == 0 ) quit=1;
-         currentSample=0;
-      }
-   }
+    for(i=0; i<BUF_SIZE/numberOfSamples; i++)
+    {
+        synthSamples((int32_t*)outptr, numberOfSamples);
+        outptr += numberOfSamples;
+        if( tick() == 0 )
+            quit=1;
+    }
+
+    if(BUF_SIZE%numberOfSamples)
+    {
+        synthSamples((int32_t*)outptr, BUF_SIZE%numberOfSamples);
+        outptr += BUF_SIZE%numberOfSamples;
+    }
 }
 
 void get_more(unsigned char** start, size_t* size)
diff --git a/apps/plugins/midi/synth.c b/apps/plugins/midi/synth.c
index 327f32e..568c7bb 100644
--- a/apps/plugins/midi/synth.c
+++ b/apps/plugins/midi/synth.c
@@ -255,8 +255,7 @@
     so->decay = 0;
 }
 
-int synthVoice(struct SynthObject * so) ICODE_ATTR;
-int synthVoice(struct SynthObject * so)
+static inline int synthVoice(struct SynthObject * so)
 {
     struct GWaveform * wf;
     register int s;
@@ -404,3 +403,46 @@
     return s*so->volscale>>14;
 }
 
+/* synth num_samples samples and write them to the */
+/* buffer pointed to by buf_ptr                    */
+void synthSamples(int32_t *buf_ptr, unsigned int num_samples) ICODE_ATTR;
+void synthSamples(int32_t *buf_ptr, unsigned int num_samples)
+{
+    int i;
+    register int dL;
+    register int dR;
+    register int sample;
+    register struct SynthObject *voicept;
+    while(num_samples>0)
+    {
+        dL=0;
+        dR=0;
+        voicept=&voices[0];
+
+        for(i=MAX_VOICES; i > 0; i--)
+        {
+            if(voicept->isUsed==1)
+            {
+                sample = synthVoice(voicept);
+                dL += sample;
+                sample *= chPan[voicept->ch];
+                dR += sample;
+            }
+            voicept++;
+        }
+
+        dL = (dL << 7) - dR;
+
+        /* combine the left and right 16 bit samples into 32 bits and write */
+        /* to the buffer, left sample in the high word and right in the low word */
+        *buf_ptr=(((dL&0x7FFF80) << 9) | ((dR&0x7FFF80) >> 7));
+
+        buf_ptr++;
+        num_samples--;
+    }
+    /* TODO: Automatic Gain Control, anyone? */
+    /* Or, should this be implemented on the DSP's output volume instead? */
+
+    return;  /* No more ghetto lowpass filter. Linear interpolation works well. */
+}
+
diff --git a/apps/plugins/midi/synth.h b/apps/plugins/midi/synth.h
index e04f9f4..5f9edf8 100644
--- a/apps/plugins/midi/synth.h
+++ b/apps/plugins/midi/synth.h
@@ -17,61 +17,8 @@
  *
  ****************************************************************************/
 int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig);
-int synthVoice(struct SynthObject * so);
 void setPoint(struct SynthObject * so, int pt);
-
-static inline void synthSample(int * mixL, int * mixR)
-{
-    int i;
-    register int dL=0;
-    register int dR=0;
-    register int sample = 0;
-    register struct SynthObject *voicept=voices;
-
-    for(i=MAX_VOICES/2; i > 0; i--)
-    {
-        if(voicept->isUsed==1)
-        {
-            sample = synthVoice(voicept);
-            dL += sample;
-            sample *= chPan[voicept->ch];
-            dR += sample;
-        }
-        voicept++;
-        if(voicept->isUsed==1)
-        {
-            sample = synthVoice(voicept);
-            dL += sample;
-            sample *= chPan[voicept->ch];
-            dR += sample;
-        }
-        voicept++;
-    }
-
-/* if MAX_VOICES is not even we do this to get the last voice */
-#if MAX_VOICES%2
-    if (MAX_VOICES%2)
-    {
-        if(voicept->isUsed==1)
-        {
-            sample = synthVoice(voicept);
-            dL += sample;
-            sample *= chPan[voicept->ch];
-            dR += sample;
-        }
-    }
-#endif
-
-    dL = (dL << 7) - dR;
-
-    *mixL=dL >> 7;
-    *mixR=dR >> 7;
-
-    /* TODO: Automatic Gain Control, anyone? */
-    /* Or, should this be implemented on the DSP's output volume instead? */
-
-    return;  /* No more ghetto lowpass filter. Linear interpolation works well. */
-}
+void synthSamples(int32_t *buf_ptr, unsigned int num_samples);
 
 static inline struct Event * getEvent(struct Track * tr, int evNum)
 {