forked from len0rd/rockbox
Some shifting optimizations. Working code. 50% realtime.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6323 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
c3d0a229cc
commit
1f5fb99819
6 changed files with 238 additions and 201 deletions
|
@ -66,18 +66,64 @@ struct GWaveform * loadWaveform(int file)
|
||||||
wav->res=readData(file, 36);
|
wav->res=readData(file, 36);
|
||||||
wav->data=readData(file, wav->wavSize);
|
wav->data=readData(file, wav->wavSize);
|
||||||
|
|
||||||
|
wav->numSamples = wav->wavSize / 2;
|
||||||
int a=0;
|
int a=0;
|
||||||
|
|
||||||
|
return wav;
|
||||||
|
if(wav->mode & 1 == 0) //Whoops, 8 bit
|
||||||
|
{
|
||||||
|
wav->numSamples = wav->wavSize;
|
||||||
|
|
||||||
|
//Allocate a block for the rest of it
|
||||||
|
//It should end up right after the previous one.
|
||||||
|
wav->wavSize = wav->wavSize * 2;
|
||||||
|
void * foo = allocate(wav->wavSize);
|
||||||
|
|
||||||
|
|
||||||
|
for(a=0; a<1000; a++)
|
||||||
|
printf("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||||
|
|
||||||
|
|
||||||
|
for(a=wav->wavSize-1; a>0; a-=2)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
// int b1=wf->data[s]+((wf->mode & 2) << 6);
|
||||||
|
// return b1<<8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
//#if !defined(SIMULATOR)
|
||||||
|
for(a=0; a<wav->wavSize; a+=2)
|
||||||
|
{
|
||||||
|
unsigned char tmp;
|
||||||
|
tmp = wav->data[2*a];
|
||||||
|
wav->data[2*a] = wav->data[2*a+1];
|
||||||
|
wav->data[2*a+1] = tmp;
|
||||||
|
}
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
if(wav->mode & 2)
|
||||||
|
{
|
||||||
|
for(a=0; a<wav->wavSize/2; a++)
|
||||||
|
{
|
||||||
|
((short *) wav->data)[a] = ((short *) wav->data)[a] - 32767;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//If we have a 16 bit waveform
|
//If we have a 16 bit waveform
|
||||||
if(wav->mode & 1 && (wav->mode & 2))
|
/* if(wav->mode & 1 && (wav->mode & 2))
|
||||||
{
|
{
|
||||||
for(a=0; a<wav->wavSize; a+=2) //Convert it to
|
for(a=0; a<wav->wavSize; a+=2) //Convert it to
|
||||||
{
|
{
|
||||||
//wav->data[a]=wav->data[a]; //+((wav->mode & 2) << 6);
|
wav->data[a]=wav->data[a]+(1 << 7);
|
||||||
wav->data[a|1]=wav->data[(a)|1]+(1 << 7);
|
wav->data[a|1]=wav->data[(a)|1]+(1 << 7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return wav;
|
return wav;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ struct GWaveform
|
||||||
unsigned char * name;
|
unsigned char * name;
|
||||||
unsigned char fractions;
|
unsigned char fractions;
|
||||||
unsigned int wavSize;
|
unsigned int wavSize;
|
||||||
|
unsigned int numSamples;
|
||||||
unsigned int startLoop;
|
unsigned int startLoop;
|
||||||
unsigned int endLoop;
|
unsigned int endLoop;
|
||||||
unsigned int sampRate;
|
unsigned int sampRate;
|
||||||
|
|
|
@ -63,33 +63,26 @@
|
||||||
extern struct plugin_api * rb;
|
extern struct plugin_api * rb;
|
||||||
|
|
||||||
|
|
||||||
|
int chVol[16] IDATA_ATTR; //Channel volume
|
||||||
|
int chPanLeft[16] IDATA_ATTR; //Channel panning
|
||||||
|
int chPanRight[16] IDATA_ATTR;
|
||||||
|
int chPat[16]; //Channel patch
|
||||||
|
int chPW[16]; //Channel pitch wheel, MSB only
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
unsigned char chVol[16]; //Channel volume
|
unsigned char chVol[16]; //Channel volume
|
||||||
unsigned char chPanLeft[16]; //Channel panning
|
unsigned char chPanLeft[16]; //Channel panning
|
||||||
unsigned char chPanRight[16];
|
unsigned char chPanRight[16];
|
||||||
unsigned char chPat[16]; //Channel patch
|
unsigned char chPat[16]; //Channel patch
|
||||||
unsigned char chPW[16]; //Channel pitch wheel, MSB only
|
unsigned char chPW[16]; //Channel pitch wheel, MSB only
|
||||||
|
*/
|
||||||
|
|
||||||
struct GPatch * gusload(char *);
|
struct GPatch * gusload(char *);
|
||||||
struct GPatch * patchSet[128];
|
struct GPatch * patchSet[128];
|
||||||
struct GPatch * drumSet[128];
|
struct GPatch * drumSet[128];
|
||||||
struct SynthObject voices[MAX_VOICES];
|
|
||||||
|
|
||||||
|
|
||||||
|
//char myarray[80] IDATA_ATTR;
|
||||||
struct SynthObject
|
|
||||||
{
|
|
||||||
int tmp;
|
|
||||||
struct GWaveform * wf;
|
|
||||||
unsigned int delta;
|
|
||||||
unsigned int decay;
|
|
||||||
unsigned int cp;
|
|
||||||
unsigned char state, pstate, loopState, loopDir;
|
|
||||||
unsigned char note, vol, ch, isUsed;
|
|
||||||
int curRate, curOffset, targetOffset;
|
|
||||||
int curPoint;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct Event
|
struct Event
|
||||||
{
|
{
|
||||||
|
@ -120,6 +113,34 @@ struct MIDIfile
|
||||||
unsigned char patches[128];
|
unsigned char patches[128];
|
||||||
int numPatches;
|
int numPatches;
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
|
struct SynthObject
|
||||||
|
{
|
||||||
|
// int tmp;
|
||||||
|
struct GWaveform * wf;
|
||||||
|
unsigned int delta;
|
||||||
|
unsigned int decay;
|
||||||
|
unsigned int cp;
|
||||||
|
unsigned char state, loopState, loopDir;
|
||||||
|
unsigned char note, vol, ch, isUsed;
|
||||||
|
int curRate, curOffset, targetOffset;
|
||||||
|
unsigned int curPoint;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
struct SynthObject
|
||||||
|
{
|
||||||
|
// int tmp;
|
||||||
|
struct GWaveform * wf;
|
||||||
|
int delta;
|
||||||
|
int decay;
|
||||||
|
int cp;
|
||||||
|
int state, loopState, loopDir;
|
||||||
|
int note, vol, ch, isUsed;
|
||||||
|
int curRate, curOffset, targetOffset;
|
||||||
|
int curPoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SynthObject voices[MAX_VOICES] IDATA_ATTR;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,13 +154,16 @@ int readVarData(int file);
|
||||||
int midimain(void * filename);
|
int midimain(void * filename);
|
||||||
|
|
||||||
|
|
||||||
//Rick's code
|
|
||||||
void *alloc(int size)
|
void *alloc(int size)
|
||||||
{
|
{
|
||||||
static char *offset = NULL;
|
static char *offset = NULL;
|
||||||
static int totalSize = 0;
|
static int totalSize = 0;
|
||||||
char *ret;
|
char *ret;
|
||||||
|
|
||||||
|
int remainder = size % 4;
|
||||||
|
|
||||||
|
size = size + 4-remainder;
|
||||||
|
|
||||||
if (offset == NULL)
|
if (offset == NULL)
|
||||||
{
|
{
|
||||||
offset = rb->plugin_get_audio_buffer(&totalSize);
|
offset = rb->plugin_get_audio_buffer(&totalSize);
|
||||||
|
@ -157,40 +181,34 @@ void *alloc(int size)
|
||||||
totalSize -= size + 4;
|
totalSize -= size + 4;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Rick's code
|
||||||
/*
|
/*
|
||||||
void *ralloc(char *offset, int len)
|
void *alloc(int size)
|
||||||
{
|
{
|
||||||
int size;
|
static char *offset = NULL;
|
||||||
|
static int totalSize = 0;
|
||||||
char *ret;
|
char *ret;
|
||||||
|
|
||||||
|
|
||||||
if (offset == NULL)
|
if (offset == NULL)
|
||||||
{
|
{
|
||||||
return alloc(len);
|
offset = rb->plugin_get_audio_buffer(&totalSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
size = *((unsigned int *)offset - 4);
|
if (size + 4 > totalSize)
|
||||||
|
|
||||||
if (size >= 0x02000000)
|
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = alloc(len);
|
ret = offset + 4;
|
||||||
|
*((unsigned int *)offset) = size;
|
||||||
if (len < size)
|
|
||||||
{
|
|
||||||
rb->memcpy(ret, offset, len);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rb->memcpy(ret, offset, size);
|
|
||||||
rb->memset(ret, 0, len - size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
offset += size + 4;
|
||||||
|
totalSize -= size + 4;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}*/
|
||||||
*/
|
|
||||||
|
|
||||||
void * allocate(int size)
|
void * allocate(int size)
|
||||||
{
|
{
|
||||||
return alloc(size);
|
return alloc(size);
|
||||||
|
@ -222,44 +240,6 @@ int eof(int fd)
|
||||||
|
|
||||||
void printf(char *fmt, ...) {fmt=fmt; }
|
void printf(char *fmt, ...) {fmt=fmt; }
|
||||||
|
|
||||||
/*
|
|
||||||
void *audio_bufferbase;
|
|
||||||
void *audio_bufferpointer;
|
|
||||||
unsigned int audio_buffer_free;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void *my_malloc(int size)
|
|
||||||
{
|
|
||||||
|
|
||||||
void *alloc;
|
|
||||||
|
|
||||||
if (!audio_bufferbase)
|
|
||||||
{
|
|
||||||
audio_bufferbase = audio_bufferpointer
|
|
||||||
= rb->plugin_get_audio_buffer(&audio_buffer_free);
|
|
||||||
#if MEM <= 8 && !defined(SIMULATOR)
|
|
||||||
|
|
||||||
if ((unsigned)(ovl_start_addr - (unsigned char *)audio_bufferbase)
|
|
||||||
< audio_buffer_free)
|
|
||||||
audio_buffer_free = ovl_start_addr - (unsigned char *)audio_bufferbase;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (size + 4 > audio_buffer_free)
|
|
||||||
return 0;
|
|
||||||
alloc = audio_bufferpointer;
|
|
||||||
audio_bufferpointer += size + 4;
|
|
||||||
audio_buffer_free -= size + 4;
|
|
||||||
return alloc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setmallocpos(void *pointer)
|
|
||||||
{
|
|
||||||
audio_bufferpointer = pointer;
|
|
||||||
audio_buffer_free = audio_bufferpointer - audio_bufferbase;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
void exit(int code)
|
void exit(int code)
|
||||||
{
|
{
|
||||||
code = code; //Stub function, kill warning for now
|
code = code; //Stub function, kill warning for now
|
||||||
|
|
|
@ -88,9 +88,30 @@ void setPW(int ch, int msb)
|
||||||
|
|
||||||
void pressNote(int ch, int note, int vol)
|
void pressNote(int ch, int note, int vol)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
if(ch == 0) return;
|
||||||
|
// if(ch == 1) return;
|
||||||
|
if(ch == 2) return;
|
||||||
|
if(ch == 3) return;
|
||||||
|
if(ch == 4) return;
|
||||||
|
if(ch == 5) return;
|
||||||
|
if(ch == 6) return;
|
||||||
|
if(ch == 7) return;
|
||||||
|
if(ch == 8) return;
|
||||||
|
if(ch == 9) return;
|
||||||
|
if(ch == 10) return;
|
||||||
|
if(ch == 11) return;
|
||||||
|
if(ch == 12) return;
|
||||||
|
if(ch == 13) return;
|
||||||
|
if(ch == 14) return;
|
||||||
|
if(ch == 15) return;
|
||||||
|
*/
|
||||||
int a=0;
|
int a=0;
|
||||||
for(a=0; a<MAX_VOICES; a++)
|
for(a=0; a<MAX_VOICES; a++)
|
||||||
{
|
{
|
||||||
|
if(voices[a].ch == ch && voices[a].note == note)
|
||||||
|
break;
|
||||||
|
|
||||||
if(voices[a].isUsed==0)
|
if(voices[a].isUsed==0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +128,7 @@ void pressNote(int ch, int note, int vol)
|
||||||
voices[a].vol=vol;
|
voices[a].vol=vol;
|
||||||
voices[a].cp=0;
|
voices[a].cp=0;
|
||||||
voices[a].state=STATE_ATTACK;
|
voices[a].state=STATE_ATTACK;
|
||||||
voices[a].pstate=STATE_ATTACK;
|
// voices[a].pstate=STATE_ATTACK;
|
||||||
voices[a].decay=255;
|
voices[a].decay=255;
|
||||||
|
|
||||||
|
|
||||||
|
@ -170,15 +191,12 @@ void releaseNote(int ch, int note)
|
||||||
{
|
{
|
||||||
if(voices[a].ch == ch && voices[a].note == note)
|
if(voices[a].ch == ch && voices[a].note == note)
|
||||||
{
|
{
|
||||||
//voices[a].isUsed=0;
|
|
||||||
if((voices[a].wf->mode & 28))
|
if((voices[a].wf->mode & 28))
|
||||||
{
|
{
|
||||||
voices[a].tmp=40;
|
// voices[a].tmp=40;
|
||||||
// voices[a].state = STATE_RELEASE; //Ramp down
|
// voices[a].state = STATE_RELEASE; //Ramp down
|
||||||
|
|
||||||
// voices[a].state = STATE_RAMPDOWN; //Ramp down
|
// voices[a].state = STATE_RAMPDOWN; //Ramp down
|
||||||
|
|
||||||
// voices[a].isUsed = 0;
|
|
||||||
setPoint(&voices[a], 3);
|
setPoint(&voices[a], 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,6 +299,9 @@ int tick(struct MIDIfile * mf)
|
||||||
{
|
{
|
||||||
tempo = (((short)e->evData[0])<<16)|(((short)e->evData[1])<<8)|(e->evData[2]);
|
tempo = (((short)e->evData[0])<<16)|(((short)e->evData[1])<<8)|(e->evData[2]);
|
||||||
printf("\nMeta-Event: Tempo Set = %d", tempo);
|
printf("\nMeta-Event: Tempo Set = %d", tempo);
|
||||||
|
bpm=mf->div*1000000/tempo;
|
||||||
|
numberOfSamples=SAMPLE_RATE/bpm;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tr->delta = 0;
|
tr->delta = 0;
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern struct plugin_api * rb;
|
extern struct plugin_api * rb;
|
||||||
|
|
||||||
struct Event * getEvent(struct Track * tr, int evNum)
|
struct Event * getEvent(struct Track * tr, int evNum)
|
||||||
|
@ -178,7 +176,20 @@ int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
inline signed short int getSample(struct GWaveform * wf, unsigned int s)
|
int currentVoice IDATA_ATTR;
|
||||||
|
struct SynthObject * so IDATA_ATTR;
|
||||||
|
struct GWaveform * wf IDATA_ATTR;
|
||||||
|
int s IDATA_ATTR;
|
||||||
|
short s1 IDATA_ATTR;
|
||||||
|
short s2 IDATA_ATTR;
|
||||||
|
short sample IDATA_ATTR; //For synthSample
|
||||||
|
unsigned int cpShifted IDATA_ATTR;
|
||||||
|
|
||||||
|
unsigned char b1 IDATA_ATTR;
|
||||||
|
unsigned char b2 IDATA_ATTR;
|
||||||
|
|
||||||
|
|
||||||
|
inline int getSample(int s)
|
||||||
{
|
{
|
||||||
|
|
||||||
//16 bit samples
|
//16 bit samples
|
||||||
|
@ -186,24 +197,23 @@ inline signed short int getSample(struct GWaveform * wf, unsigned int s)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(s<<1 >= wf->wavSize)
|
if(s<<1 >= wf->wavSize)
|
||||||
|
{
|
||||||
|
printf("\n!!!!! %d \t %d", s<<1, wf->wavSize);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
// signed short a = ((short *)wf->data)[s];
|
||||||
/*
|
|
||||||
* Probably put the signed/unsigned and and 8-16 bit conversion
|
|
||||||
* into the patch loader and have it run there, once.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
//Sign conversion moved into guspat.c
|
//Sign conversion moved into guspat.c
|
||||||
unsigned char b1=wf->data[s<<1]; //+((wf->mode & 2) << 6);
|
b1=wf->data[s<<1]+((wf->mode & 2) << 6);
|
||||||
unsigned char b2=wf->data[(s<<1)|1]; //+((wf->mode & 2) << 6);
|
b2=wf->data[(s<<1)|1]+((wf->mode & 2) << 6);
|
||||||
return (b1 | (b2<<8)) ;
|
return (b1 | (b2<<8)) ;
|
||||||
|
|
||||||
|
//Get rid of this sometime
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ //8-bit samples
|
{ //8-bit samples
|
||||||
//Do we even have anything 8-bit in our set?
|
//Do we even have anything 8-bit in our set?
|
||||||
unsigned char b1=wf->data[s]+((wf->mode & 2) << 6);
|
int b1=wf->data[s]+((wf->mode & 2) << 6);
|
||||||
return b1<<8;
|
return b1<<8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,6 +261,12 @@ inline void setPoint(struct SynthObject * so, int pt)
|
||||||
*/
|
*/
|
||||||
so->curRate = r<<10;
|
so->curRate = r<<10;
|
||||||
|
|
||||||
|
//Do this here because the patches assume a 44100 sampling rate
|
||||||
|
//We've halved our sampling rate, ergo the ADSR code will be
|
||||||
|
//called half the time. Ergo, double the rate to keep stuff
|
||||||
|
//sounding right.
|
||||||
|
so->curRate = so->curRate << 1;
|
||||||
|
|
||||||
|
|
||||||
so->targetOffset = so->wf->envOffset[pt]<<(20);
|
so->targetOffset = so->wf->envOffset[pt]<<(20);
|
||||||
if(pt==0)
|
if(pt==0)
|
||||||
|
@ -258,8 +274,6 @@ inline void setPoint(struct SynthObject * so, int pt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
long msi=0;
|
|
||||||
|
|
||||||
inline void stopVoice(struct SynthObject * so)
|
inline void stopVoice(struct SynthObject * so)
|
||||||
{
|
{
|
||||||
if(so->state == STATE_RAMPDOWN)
|
if(so->state == STATE_RAMPDOWN)
|
||||||
|
@ -269,51 +283,37 @@ inline void stopVoice(struct SynthObject * so)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int rampDown = 0;
|
|
||||||
|
|
||||||
inline signed short int synthVoice(int v)
|
inline signed short int synthVoice()
|
||||||
{
|
{
|
||||||
//Probably can combine these 2 lines into one..
|
so = &voices[currentVoice];
|
||||||
//But for now, this looks more readable
|
wf = so->wf;
|
||||||
// struct GPatch * pat = patchSet[chPat[voices[v].ch]];
|
|
||||||
// struct GWaveform * wf = pat->waveforms[pat->noteTable[voices[v].note]];
|
|
||||||
struct SynthObject * so = &voices[v];
|
|
||||||
struct GWaveform * wf = so->wf;
|
|
||||||
|
|
||||||
signed int s;
|
|
||||||
|
|
||||||
if(so->state != STATE_RAMPDOWN)
|
if(so->state != STATE_RAMPDOWN)
|
||||||
{
|
{
|
||||||
if(so->loopDir==LOOPDIR_FORWARD)
|
so->cp += so->delta;
|
||||||
{
|
|
||||||
so->cp += so->delta;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
so->cp -= so->delta;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (so->cp>>9 >= (wf->wavSize)) && (so->state != STATE_RAMPDOWN))
|
cpShifted = so->cp >> 10;
|
||||||
|
|
||||||
|
if( (cpShifted >= (wf->wavSize>>1)) && (so->state != STATE_RAMPDOWN))
|
||||||
stopVoice(so);
|
stopVoice(so);
|
||||||
|
|
||||||
/*
|
s2 = getSample((cpShifted)+1);
|
||||||
//Original, working, no interpolation
|
|
||||||
s=getSample(wf, (so->cp>>10));
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
if((wf->mode & (LOOP_REVERSE|LOOP_PINGPONG)) && so->loopState == STATE_LOOPING && (cpShifted <= (wf->startLoop>>1)))
|
||||||
|
|
||||||
int s2=getSample(wf, (so->cp>>10)+1);
|
|
||||||
|
|
||||||
if((wf->mode & (LOOP_REVERSE|LOOP_PINGPONG)) && so->loopState == STATE_LOOPING && (so->cp>>10 <= (wf->startLoop>>1)))
|
|
||||||
{
|
{
|
||||||
if(wf->mode & LOOP_REVERSE)
|
if(wf->mode & LOOP_REVERSE)
|
||||||
{
|
{
|
||||||
so->cp = (wf->endLoop)<<9;
|
so->cp = (wf->endLoop)<<9;
|
||||||
s2=getSample(wf, (so->cp>>10));
|
cpShifted = so->cp >> 10;
|
||||||
|
s2=getSample((cpShifted));
|
||||||
} else
|
} else
|
||||||
|
{
|
||||||
|
so->delta = -so->delta;
|
||||||
so->loopDir = LOOPDIR_FORWARD;
|
so->loopDir = LOOPDIR_FORWARD;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((wf->mode & 28) && (so->cp>>10 >= wf->endLoop>>1))
|
if((wf->mode & 28) && (so->cp>>10 >= wf->endLoop>>1))
|
||||||
|
@ -322,14 +322,21 @@ inline signed short int synthVoice(int v)
|
||||||
if((wf->mode & (24)) == 0)
|
if((wf->mode & (24)) == 0)
|
||||||
{
|
{
|
||||||
so->cp = (wf->startLoop)<<9;
|
so->cp = (wf->startLoop)<<9;
|
||||||
s2=getSample(wf, (so->cp>>10));
|
cpShifted = so->cp >> 10;
|
||||||
|
s2=getSample((cpShifted));
|
||||||
} else
|
} else
|
||||||
|
{
|
||||||
|
so->delta = -so->delta;
|
||||||
so->loopDir = LOOPDIR_REVERSE;
|
so->loopDir = LOOPDIR_REVERSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Better, working, linear interpolation
|
//Better, working, linear interpolation
|
||||||
int s1=getSample(wf, (so->cp>>10));
|
s1=getSample((cpShifted));
|
||||||
s = s1 + ((long)((s2 - s1) * (so->cp & 1023))>>10);
|
s = s1 + ((signed)((s2 - s1) * (so->cp & 1023))>>10);
|
||||||
|
|
||||||
|
|
||||||
|
//ADSR COMMENT WOULD GO FROM HERE.........
|
||||||
|
|
||||||
if(so->curRate == 0)
|
if(so->curRate == 0)
|
||||||
stopVoice(so);
|
stopVoice(so);
|
||||||
|
@ -366,8 +373,9 @@ inline signed short int synthVoice(int v)
|
||||||
so->isUsed=0; //This is OK
|
so->isUsed=0; //This is OK
|
||||||
|
|
||||||
|
|
||||||
s = s * (so->curOffset >> 22);
|
s = (s * (so->curOffset >> 22) >> 6);
|
||||||
s = s>>6;
|
|
||||||
|
// ............. TO HERE
|
||||||
|
|
||||||
|
|
||||||
if(so->state == STATE_RAMPDOWN)
|
if(so->state == STATE_RAMPDOWN)
|
||||||
|
@ -377,64 +385,28 @@ inline signed short int synthVoice(int v)
|
||||||
so->isUsed=0;
|
so->isUsed=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s = s * so->decay; s = s >> 9;
|
s = s * so->decay; s = s >> 10;
|
||||||
|
|
||||||
return s*((signed short int)so->vol*(signed short int)chVol[so->ch])>>14;
|
return s*((signed short int)so->vol*(signed short int)chVol[so->ch])>>14;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int mhL[16];
|
|
||||||
int mhR[16];
|
|
||||||
int mp=0; //Mix position, for circular array
|
|
||||||
// Was stuff for Ghetto Lowpass Filter, now deprecated.
|
|
||||||
|
|
||||||
|
|
||||||
inline void synthSample(int * mixL, int * mixR)
|
inline void synthSample(int * mixL, int * mixR)
|
||||||
{
|
{
|
||||||
int a=0;
|
// signed int leftMix=0, rightMix=0,
|
||||||
signed long int leftMix=0, rightMix=0, sample=0;
|
*mixL = 0;
|
||||||
for(a=0; a<MAX_VOICES; a++)
|
*mixR = 0;
|
||||||
|
for(currentVoice=0; currentVoice<MAX_VOICES; currentVoice++)
|
||||||
{
|
{
|
||||||
if(voices[a].isUsed==1)
|
if(voices[currentVoice].isUsed==1)
|
||||||
{
|
{
|
||||||
sample = synthVoice(a);
|
sample = synthVoice(currentVoice);
|
||||||
|
*mixL += (sample*chPanLeft[voices[currentVoice].ch])>>7;
|
||||||
leftMix += (sample*chPanLeft[voices[a].ch])>>7;
|
*mixR += (sample*chPanRight[voices[currentVoice].ch])>>7;
|
||||||
rightMix += (sample*chPanRight[voices[a].ch])>>7;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Automatic Gain Control, anyone?
|
//TODO: Automatic Gain Control, anyone?
|
||||||
//Or, should this be implemented on the DSP's output volume instead?
|
//Or, should this be implemented on the DSP's output volume instead?
|
||||||
*mixL = leftMix;
|
|
||||||
*mixR = rightMix;
|
|
||||||
|
|
||||||
return; //No more ghetto lowpass filter.. linear intrpolation works well.
|
return; //No more ghetto lowpass filter.. linear intrpolation works well.
|
||||||
|
|
||||||
|
|
||||||
// HACK HACK HACK
|
|
||||||
// This is the infamous Ghetto Lowpass Filter
|
|
||||||
// Now that I have linear interpolation, it should not be needed anymore.
|
|
||||||
/*
|
|
||||||
mp++;
|
|
||||||
if(mp==4)
|
|
||||||
mp=0;
|
|
||||||
|
|
||||||
mhL[mp]=leftMix;
|
|
||||||
mhR[mp]=rightMix;
|
|
||||||
|
|
||||||
*mixL = 0;
|
|
||||||
*mixR = 0;
|
|
||||||
|
|
||||||
|
|
||||||
for(a=0; a<4; a++)
|
|
||||||
{
|
|
||||||
*mixL += mhL[a];
|
|
||||||
*mixR += mhR[a];
|
|
||||||
}
|
|
||||||
*mixL = *mixL>>4;
|
|
||||||
*mixR = *mixR>>4;
|
|
||||||
*/
|
|
||||||
// END HACK END HACK END HACK
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define SAMPLE_RATE 48000
|
#define SAMPLE_RATE 22050
|
||||||
#define MAX_VOICES 100
|
#define MAX_VOICES 100
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,6 +37,12 @@
|
||||||
|
|
||||||
|
|
||||||
#include "../../plugin.h"
|
#include "../../plugin.h"
|
||||||
|
|
||||||
|
#include "lib/xxx2wav.h"
|
||||||
|
|
||||||
|
int numberOfSamples IDATA_ATTR;
|
||||||
|
long bpm;
|
||||||
|
|
||||||
#include "midi/midiutil.c"
|
#include "midi/midiutil.c"
|
||||||
#include "midi/guspat.h"
|
#include "midi/guspat.h"
|
||||||
#include "midi/guspat.c"
|
#include "midi/guspat.c"
|
||||||
|
@ -46,7 +52,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "lib/xxx2wav.h"
|
|
||||||
|
|
||||||
int fd=-1; //File descriptor where the output is written
|
int fd=-1; //File descriptor where the output is written
|
||||||
|
|
||||||
|
@ -58,6 +63,7 @@ struct plugin_api * rb;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
||||||
{
|
{
|
||||||
TEST_PLUGIN_API(api);
|
TEST_PLUGIN_API(api);
|
||||||
|
@ -80,6 +86,14 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
||||||
return PLUGIN_OK;
|
return PLUGIN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signed char outputBuffer[3000] IDATA_ATTR; //signed char.. gonna run out of iram ... !
|
||||||
|
|
||||||
|
|
||||||
|
int currentSample IDATA_ATTR;
|
||||||
|
int outputBufferPosition IDATA_ATTR;
|
||||||
|
int outputSampleOne IDATA_ATTR;
|
||||||
|
int outputSampleTwo IDATA_ATTR;
|
||||||
|
|
||||||
|
|
||||||
int midimain(void * filename)
|
int midimain(void * filename)
|
||||||
{
|
{
|
||||||
|
@ -89,9 +103,6 @@ int midimain(void * filename)
|
||||||
rb->splash(HZ/5, true, "LOADING MIDI");
|
rb->splash(HZ/5, true, "LOADING MIDI");
|
||||||
|
|
||||||
struct MIDIfile * mf = loadFile(filename);
|
struct MIDIfile * mf = loadFile(filename);
|
||||||
long bpm, nsmp, l;
|
|
||||||
|
|
||||||
int bp=0;
|
|
||||||
|
|
||||||
rb->splash(HZ/5, true, "LOADING PATCHES");
|
rb->splash(HZ/5, true, "LOADING PATCHES");
|
||||||
if (initSynth(mf, "/.rockbox/patchset/patchset.cfg", "/.rockbox/patchset/drums.cfg") == -1)
|
if (initSynth(mf, "/.rockbox/patchset/patchset.cfg", "/.rockbox/patchset/drums.cfg") == -1)
|
||||||
|
@ -125,7 +136,7 @@ int midimain(void * filename)
|
||||||
samp=arg;
|
samp=arg;
|
||||||
#else
|
#else
|
||||||
file_info_struct file_info;
|
file_info_struct file_info;
|
||||||
file_info.samplerate = 48000;
|
file_info.samplerate = SAMPLE_RATE;
|
||||||
file_info.infile = fd;
|
file_info.infile = fd;
|
||||||
file_info.channels = 2;
|
file_info.channels = 2;
|
||||||
file_info.bitspersample = 16;
|
file_info.bitspersample = 16;
|
||||||
|
@ -134,12 +145,11 @@ int midimain(void * filename)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
rb->splash(HZ/5, true, " START PLAYING ");
|
rb->splash(HZ/5, true, " Starting Playback ");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
signed char buf[3000];
|
|
||||||
|
|
||||||
// tick() will do one MIDI clock tick. Then, there's a loop here that
|
// tick() will do one MIDI clock tick. Then, there's a loop here that
|
||||||
// will generate the right number of samples per MIDI tick. The whole
|
// will generate the right number of samples per MIDI tick. The whole
|
||||||
|
@ -152,49 +162,56 @@ int midimain(void * filename)
|
||||||
|
|
||||||
printf("\nOkay, starting sequencing");
|
printf("\nOkay, starting sequencing");
|
||||||
|
|
||||||
|
|
||||||
|
currentSample=0; //Sample counting variable
|
||||||
|
outputBufferPosition = 0;
|
||||||
|
|
||||||
|
|
||||||
|
bpm=mf->div*1000000/tempo;
|
||||||
|
numberOfSamples=SAMPLE_RATE/bpm;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Tick() will return 0 if there are no more events left to play
|
//Tick() will return 0 if there are no more events left to play
|
||||||
while(tick(mf))
|
while(tick(mf))
|
||||||
{
|
{
|
||||||
|
|
||||||
//Some annoying math to compute the number of samples
|
//Some annoying math to compute the number of samples
|
||||||
//to syntehsize per each MIDI tick.
|
//to syntehsize per each MIDI tick.
|
||||||
bpm=mf->div*1000000/tempo;
|
|
||||||
nsmp=SAMPLE_RATE/bpm;
|
|
||||||
|
|
||||||
//Yes we need to do this math each time because the tempo
|
//Yes we need to do this math each time because the tempo
|
||||||
//could have changed.
|
//could have changed.
|
||||||
|
|
||||||
// On second thought, this can be moved to the event that
|
// On second thought, this can be moved to the event that
|
||||||
//recalculates the tempo, to save a little bit of CPU time.
|
//recalculates the tempo, to save a little bit of CPU time.
|
||||||
for(l=0; l<nsmp; l++)
|
for(currentSample=0; currentSample<numberOfSamples; currentSample++)
|
||||||
{
|
{
|
||||||
int s1, s2;
|
|
||||||
|
|
||||||
synthSample(&s1, &s2);
|
synthSample(&outputSampleOne, &outputSampleTwo);
|
||||||
|
|
||||||
|
|
||||||
//16-bit audio because, well, it's better
|
//16-bit audio because, well, it's better
|
||||||
// But really because ALSA's OSS emulation sounds extremely
|
// But really because ALSA's OSS emulation sounds extremely
|
||||||
//noisy and distorted when in 8-bit mode. I still do not know
|
//noisy and distorted when in 8-bit mode. I still do not know
|
||||||
//why this happens.
|
//why this happens.
|
||||||
buf[bp]=s1&0XFF; // Low byte first
|
outputBuffer[outputBufferPosition]=outputSampleOne&0XFF; // Low byte first
|
||||||
bp++;
|
outputBufferPosition++;
|
||||||
buf[bp]=s1>>8; //High byte second
|
outputBuffer[outputBufferPosition]=outputSampleOne>>8; //High byte second
|
||||||
bp++;
|
outputBufferPosition++;
|
||||||
|
|
||||||
buf[bp]=s2&0XFF; // Low byte first
|
outputBuffer[outputBufferPosition]=outputSampleTwo&0XFF; // Low byte first
|
||||||
bp++;
|
outputBufferPosition++;
|
||||||
buf[bp]=s2>>8; //High byte second
|
outputBuffer[outputBufferPosition]=outputSampleTwo>>8; //High byte second
|
||||||
bp++;
|
outputBufferPosition++;
|
||||||
|
|
||||||
|
|
||||||
//As soon as we produce 2000 bytes of sound,
|
//As soon as we produce 2000 bytes of sound,
|
||||||
//write it to the sound card. Why 2000? I have
|
//write it to the sound card. Why 2000? I have
|
||||||
//no idea. It's 1 AM and I am dead tired.
|
//no idea. It's 1 AM and I am dead tired.
|
||||||
if(bp>=2000)
|
if(outputBufferPosition>=2000)
|
||||||
{
|
{
|
||||||
rb->write(fd, buf, 2000);
|
rb->write(fd, outputBuffer, 2000);
|
||||||
bp=0;
|
outputBufferPosition=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue