forked from len0rd/rockbox
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
This commit is contained in:
parent
d712e252fe
commit
f619f81676
3 changed files with 64 additions and 76 deletions
|
@ -149,9 +149,7 @@ bool lastswap=1;
|
||||||
static inline void synthbuf(void)
|
static inline void synthbuf(void)
|
||||||
{
|
{
|
||||||
int32_t *outptr;
|
int32_t *outptr;
|
||||||
register int i;
|
int i;
|
||||||
int currentSample=0;
|
|
||||||
int synthtemp[2];
|
|
||||||
|
|
||||||
#ifndef SYNC
|
#ifndef SYNC
|
||||||
if(lastswap==swap) return;
|
if(lastswap==swap) return;
|
||||||
|
@ -162,17 +160,18 @@ static inline void synthbuf(void)
|
||||||
outptr=gmbuf;
|
outptr=gmbuf;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(i=0; i<BUF_SIZE; i++)
|
for(i=0; i<BUF_SIZE/numberOfSamples; i++)
|
||||||
{
|
{
|
||||||
synthSample(&synthtemp[0], &synthtemp[1]);
|
synthSamples((int32_t*)outptr, numberOfSamples);
|
||||||
currentSample++;
|
outptr += numberOfSamples;
|
||||||
*outptr=((synthtemp[0]&0xFFFF) << 16) | (synthtemp[1]&0xFFFF);
|
if( tick() == 0 )
|
||||||
outptr++;
|
quit=1;
|
||||||
if(currentSample==numberOfSamples)
|
|
||||||
{
|
|
||||||
if( tick() == 0 ) quit=1;
|
|
||||||
currentSample=0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(BUF_SIZE%numberOfSamples)
|
||||||
|
{
|
||||||
|
synthSamples((int32_t*)outptr, BUF_SIZE%numberOfSamples);
|
||||||
|
outptr += BUF_SIZE%numberOfSamples;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -255,8 +255,7 @@ inline void stopVoice(struct SynthObject * so)
|
||||||
so->decay = 0;
|
so->decay = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int synthVoice(struct SynthObject * so) ICODE_ATTR;
|
static inline int synthVoice(struct SynthObject * so)
|
||||||
int synthVoice(struct SynthObject * so)
|
|
||||||
{
|
{
|
||||||
struct GWaveform * wf;
|
struct GWaveform * wf;
|
||||||
register int s;
|
register int s;
|
||||||
|
@ -404,3 +403,46 @@ int synthVoice(struct SynthObject * so)
|
||||||
return s*so->volscale>>14;
|
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. */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,61 +17,8 @@
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig);
|
int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig);
|
||||||
int synthVoice(struct SynthObject * so);
|
|
||||||
void setPoint(struct SynthObject * so, int pt);
|
void setPoint(struct SynthObject * so, int pt);
|
||||||
|
void synthSamples(int32_t *buf_ptr, unsigned int num_samples);
|
||||||
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. */
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct Event * getEvent(struct Track * tr, int evNum)
|
static inline struct Event * getEvent(struct Track * tr, int evNum)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue