1
0
Fork 0
forked from len0rd/rockbox

Fixed warnings, adapted to Rockbox coding style, optimized to 78% realtime.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6329 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Stepan Moskovchenko 2005-04-20 21:07:13 +00:00
parent 74e9d545ef
commit 9ec1ff8cf5
7 changed files with 1056 additions and 1115 deletions

View file

@ -21,197 +21,176 @@ extern struct plugin_api * rb;
unsigned int readWord(int file)
{
return (readChar(file)<<0) | (readChar(file)<<8); // | (readChar(file)<<8) | (readChar(file)<<0);
return (readChar(file)<<0) | (readChar(file)<<8); // | (readChar(file)<<8) | (readChar(file)<<0);
}
unsigned int readDWord(int file)
{
return (readChar(file)<<0) | (readChar(file)<<8) | (readChar(file)<<16) | (readChar(file)<<24);
return (readChar(file)<<0) | (readChar(file)<<8) | (readChar(file)<<16) | (readChar(file)<<24);
}
struct GWaveform * loadWaveform(int file)
{
struct GWaveform * wav = (struct GWaveform *)allocate(sizeof(struct GWaveform));
rb->memset(wav, 0, sizeof(struct GWaveform));
struct GWaveform * wav = (struct GWaveform *)allocate(sizeof(struct GWaveform));
rb->memset(wav, 0, sizeof(struct GWaveform));
wav->name=readData(file, 7);
printf("\nWAVE NAME = [%s]", wav->name);
wav->fractions=readChar(file);
wav->wavSize=readDWord(file);
wav->startLoop=readDWord(file);
wav->endLoop=readDWord(file);
wav->sampRate=readWord(file);
wav->name=readData(file, 7);
printf("\nWAVE NAME = [%s]", wav->name);
wav->fractions=readChar(file);
wav->wavSize=readDWord(file);
wav->startLoop=readDWord(file);
wav->endLoop=readDWord(file);
wav->sampRate=readWord(file);
wav->lowFreq=readDWord(file);
wav->highFreq=readDWord(file);
wav->rootFreq=readDWord(file);
wav->lowFreq=readDWord(file);
wav->highFreq=readDWord(file);
wav->rootFreq=readDWord(file);
wav->tune=readWord(file);
wav->tune=readWord(file);
wav->balance=readChar(file);
wav->envRate=readData(file, 6);
wav->envOffset=readData(file, 6);
wav->balance=readChar(file);
wav->envRate=readData(file, 6);
wav->envOffset=readData(file, 6);
wav->tremSweep=readChar(file);
wav->tremRate==readChar(file);
wav->tremDepth=readChar(file);
wav->vibSweep=readChar(file);
wav->vibRate=readChar(file);
wav->vibDepth=readChar(file);
wav->mode=readChar(file);
wav->tremSweep=readChar(file);
wav->tremRate==readChar(file);
wav->tremDepth=readChar(file);
wav->vibSweep=readChar(file);
wav->vibRate=readChar(file);
wav->vibDepth=readChar(file);
wav->mode=readChar(file);
wav->scaleFreq=readWord(file);
wav->scaleFactor=readWord(file);
printf("\nScaleFreq = %d ScaleFactor = %d RootFreq = %d", wav->scaleFreq, wav->scaleFactor, wav->rootFreq);
wav->res=readData(file, 36);
wav->data=readData(file, wav->wavSize);
wav->scaleFreq=readWord(file);
wav->scaleFactor=readWord(file);
printf("\nScaleFreq = %d ScaleFactor = %d RootFreq = %d", wav->scaleFreq, wav->scaleFactor, wav->rootFreq);
wav->res=readData(file, 36);
wav->data=readData(file, wav->wavSize);
wav->numSamples = wav->wavSize / 2;
int a=0;
wav->numSamples = wav->wavSize / 2;
wav->startLoop = wav->startLoop >> 1;
wav->endLoop = wav->endLoop >> 1;
unsigned int a=0;
return wav;
if(wav->mode & 1 == 0) //Whoops, 8 bit
{
wav->numSamples = wav->wavSize;
/* half baked 8 bit conversion UNFINISHED*/
/*
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);
//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=0; a<1000; a++)
printf("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!");
for(a=wav->wavSize-1; a>0; a-=2)
{
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;
}
}
*/
}
// int b1=wf->data[s]+((wf->mode & 2) << 6);
// return b1<<8;
}
*/
/* Iriver needs byteswapping.. big endian, go figure. Gus files are little endian */
//If we have a 16 bit waveform
/* if(wav->mode & 1 && (wav->mode & 2))
{
for(a=0; a<wav->wavSize; a+=2) //Convert it to
{
wav->data[a]=wav->data[a]+(1 << 7);
wav->data[a|1]=wav->data[(a)|1]+(1 << 7);
}
}
*/
return wav;
#if !defined(SIMULATOR)
for(a=0; a<wav->numSamples; a++)
{
((unsigned short *) wav->data)[a] = SWAB16(((unsigned short *) wav->data)[a]);
}
#endif
/* Convert unsigned to signed by subtracting 32768 */
if(wav->mode & 2)
{
for(a=0; a<wav->numSamples; a++)
((short *) wav->data)[a] = ((unsigned short *) wav->data)[a] - 32768;
}
return wav;
}
int selectWaveform(struct GPatch * pat, int midiNote)
{
int tabFreq = gustable[midiNote]/100; //Comparison
int a=0;
for(a=0; a<pat->numWaveforms; a++)
{
if(pat->waveforms[a]->lowFreq/100 <= tabFreq &&
pat->waveforms[a]->highFreq/100 >= tabFreq)
{
return a;
}
}
return 0;
/* We divide by 100 here because everyone's freq formula is slightly different */
unsigned int tabFreq = gustable[midiNote]/100; /* Comparison */
unsigned int a=0;
for(a=0; a<pat->numWaveforms; a++)
{
if(pat->waveforms[a]->lowFreq/100 <= tabFreq &&
pat->waveforms[a]->highFreq/100 >= tabFreq)
{
return a;
}
}
return 0;
}
struct GPatch * gusload(char * filename)
{
struct GPatch * gp = (struct GPatch *)allocate(sizeof(struct GPatch));
rb->memset(gp, 0, sizeof(struct GPatch));
struct GPatch * gp = (struct GPatch *)allocate(sizeof(struct GPatch));
rb->memset(gp, 0, sizeof(struct GPatch));
int file = rb->open(filename, O_RDONLY);
int file = rb->open(filename, O_RDONLY);
if(file == -1)
{
char message[50];
rb->snprintf(message, 50, "Error opening %s", filename);
rb->splash(HZ*2, true, message);
return NULL;
}
if(file == -1)
{
char message[50];
rb->snprintf(message, 50, "Error opening %s", filename);
rb->splash(HZ*2, true, message);
return NULL;
}
gp->header=readData(file, 12);
gp->gravisid=readData(file, 10);
gp->desc=readData(file, 60);
gp->inst=readChar(file);
gp->voc=readChar(file);
gp->chan=readChar(file);
gp->numWaveforms=readWord(file); //readWord(file);
gp->vol=readWord(file);
gp->datSize=readDWord(file);
gp->res=readData(file, 36);
gp->header=readData(file, 12);
gp->gravisid=readData(file, 10);
gp->desc=readData(file, 60);
gp->inst=readChar(file);
gp->voc=readChar(file);
gp->chan=readChar(file);
gp->numWaveforms=readWord(file);
gp->vol=readWord(file);
gp->datSize=readDWord(file);
gp->res=readData(file, 36);
gp->instrID=readWord(file);
gp->instrName=readData(file,16);
gp->instrSize=readDWord(file);
gp->layers=readChar(file);
gp->instrRes=readData(file,40);
gp->instrID=readWord(file);
gp->instrName=readData(file,16);
gp->instrSize=readDWord(file);
gp->layers=readChar(file);
gp->instrRes=readData(file,40);
gp->layerDup=readChar(file);
gp->layerID=readChar(file);
gp->layerSize=readDWord(file);
gp->numWaves=readChar(file);
gp->layerRes=readData(file,40);
/* printf("\n%s\n%s\n%s", gp->header, gp->gravisid, gp->desc);
printf("\nInst = %d", gp->inst);
printf("\nVoc = %d", gp->voc);
printf("\nChan = %d", gp->chan);
printf("\nWav = %d", gp->numWaveforms);
printf("\nVol = %d", gp->vol);
printf("\nSize = %d", gp->datSize);
printf("\n\ninstrID = %d", gp->instrID);
printf("\ninstrName = %s", gp->instrName);
// printf("\ninstrSize = %d", gp->instrSize);
// printf("\nlayers = %d", gp->layers);
*/
printf("\nFILE: %s", filename);
printf("\nlayerSamples=%d", gp->numWaves);
int a=0;
for(a=0; a<gp->numWaves; a++)
gp->waveforms[a] = loadWaveform(file);
gp->layerDup=readChar(file);
gp->layerID=readChar(file);
gp->layerSize=readDWord(file);
gp->numWaves=readChar(file);
gp->layerRes=readData(file,40);
printf("\nPrecomputing note table");
printf("\nFILE: %s", filename);
printf("\nlayerSamples=%d", gp->numWaves);
for(a=0; a<128; a++)
{
gp->noteTable[a] = selectWaveform(gp, a);
}
rb->close(file);
int a=0;
for(a=0; a<gp->numWaves; a++)
gp->waveforms[a] = loadWaveform(file);
return gp;
printf("\nPrecomputing note table");
for(a=0; a<128; a++)
{
gp->noteTable[a] = selectWaveform(gp, a);
}
rb->close(file);
return gp;
}

View file

@ -16,7 +16,7 @@
*
****************************************************************************/
//This came from one of the Gravis documents
/* This came from one of the Gravis documents */
static const unsigned int gustable[]=
{
8175, 8661, 9177, 9722, 10300, 10913, 11562, 12249, 12978, 13750, 14567, 15433,
@ -33,63 +33,63 @@ static const unsigned int gustable[]=
struct GWaveform
{
unsigned char * name;
unsigned char fractions;
unsigned int wavSize;
unsigned int numSamples;
unsigned int startLoop;
unsigned int endLoop;
unsigned int sampRate;
unsigned int lowFreq;
unsigned int highFreq;
unsigned int rootFreq;
unsigned int tune;
unsigned int balance;
unsigned char * envRate;
unsigned char * envOffset;
unsigned char * name;
unsigned char fractions;
unsigned int wavSize;
unsigned int numSamples;
unsigned int startLoop;
unsigned int endLoop;
unsigned int sampRate;
unsigned int lowFreq;
unsigned int highFreq;
unsigned int rootFreq;
unsigned int tune;
unsigned int balance;
unsigned char * envRate;
unsigned char * envOffset;
unsigned char tremSweep;
unsigned char tremRate;
unsigned char tremDepth;
unsigned char vibSweep;
unsigned char vibRate;
unsigned char vibDepth;
unsigned char mode;
unsigned char tremSweep;
unsigned char tremRate;
unsigned char tremDepth;
unsigned char vibSweep;
unsigned char vibRate;
unsigned char vibDepth;
unsigned char mode;
unsigned int scaleFreq;
unsigned int scaleFactor;
unsigned int scaleFreq;
unsigned int scaleFactor;
unsigned char * res;
signed char * data;
unsigned char * res;
signed char * data;
};
struct GPatch
{
unsigned int patchNumber;
unsigned char * header;
unsigned char * gravisid;
unsigned char * desc;
unsigned char inst, voc, chan;
unsigned int numWaveforms;
unsigned int datSize;
unsigned int vol;
unsigned char * res;
unsigned int patchNumber;
unsigned char * header;
unsigned char * gravisid;
unsigned char * desc;
unsigned char inst, voc, chan;
unsigned int numWaveforms;
unsigned int datSize;
unsigned int vol;
unsigned char * res;
unsigned int instrID;
unsigned char * instrName;
unsigned int instrSize;
unsigned int layers;
unsigned char * instrRes;
unsigned int instrID;
unsigned char * instrName;
unsigned int instrSize;
unsigned int layers;
unsigned char * instrRes;
unsigned char layerDup;
unsigned char layerID;
unsigned int layerSize;
unsigned char numWaves;
unsigned char * layerRes;
unsigned char layerDup;
unsigned char layerID;
unsigned int layerSize;
unsigned char numWaves;
unsigned char * layerRes;
unsigned char noteTable[128];
struct GWaveform * waveforms[255];
unsigned char noteTable[128];
struct GWaveform * waveforms[255];
};

View file

@ -26,233 +26,232 @@ void bail(const char *);
struct MIDIfile * loadFile(char * filename)
{
struct MIDIfile * mf;
int file = rb->open (filename, O_RDONLY);
struct MIDIfile * mf;
int file = rb->open (filename, O_RDONLY);
if(file==0)
{
bail("Could not open file\n");
}
if(file==-1)
{
bail("Could not open file\n");
}
mf = (struct MIDIfile*)allocate(sizeof(struct MIDIfile));
mf = (struct MIDIfile*)allocate(sizeof(struct MIDIfile));
if(mf==NULL)
{
rb->close(file);
bail("Could not allocate memory for MIDIfile struct\n");
}
if(mf==NULL)
{
rb->close(file);
bail("Could not allocate memory for MIDIfile struct\n");
}
rb->memset(mf, 0, sizeof(struct MIDIfile));
rb->memset(mf, 0, sizeof(struct MIDIfile));
if(readID(file) != ID_MTHD)
{
rb->close(file);
bail("Invalid file header chunk.");
}
if(readID(file) != ID_MTHD)
{
rb->close(file);
bail("Invalid file header chunk.");
}
if(readFourBytes(file)!=6)
{
rb->close(file);
bail("Header chunk size invalid.");
}
if(readFourBytes(file)!=6)
{
rb->close(file);
bail("Header chunk size invalid.");
}
if(readTwoBytes(file)==2)
{
rb->close(file);
bail("MIDI file type not supported");
}
if(readTwoBytes(file)==2)
{
rb->close(file);
bail("MIDI file type not supported");
}
mf->numTracks = readTwoBytes(file);
mf->div = readTwoBytes(file);
mf->numTracks = readTwoBytes(file);
mf->div = readTwoBytes(file);
int track=0;
int track=0;
printf("\nnumTracks=%d div=%d\nBegin reading track data\n", mf->numTracks, mf->div);
// return;
printf("\nnumTracks=%d div=%d\nBegin reading track data\n", mf->numTracks, mf->div);
while(! eof(file) && track < mf->numTracks)
{
unsigned char id = readID(file);
while(! eof(file) && track < mf->numTracks)
{
unsigned char id = readID(file);
if(id == ID_EOF)
{
if(mf->numTracks != track)
{
printf("\nError: file claims to have %d tracks.\n I only see %d here.\n", mf->numTracks, track);
mf->numTracks = track;
}
return mf;
}
if(id == ID_EOF)
{
if(mf->numTracks != track)
{
printf("\nError: file claims to have %d tracks.\n I only see %d here.\n", mf->numTracks, track);
mf->numTracks = track;
}
return mf;
}
if(id == ID_MTRK)
{
mf->tracks[track] = readTrack(file);
//exit(0);
track++;
} else
{
printf("\n SKIPPING TRACK");
int len = readFourBytes(file);
while(--len)
readChar(file);
}
}
return mf;
if(id == ID_MTRK)
{
mf->tracks[track] = readTrack(file);
//exit(0);
track++;
} else
{
printf("\n SKIPPING TRACK");
int len = readFourBytes(file);
while(--len)
readChar(file);
}
}
return mf;
}
int rStatus = 0;
//Returns 0 if done, 1 if keep going
/* Returns 0 if done, 1 if keep going */
int readEvent(int file, void * dest)
{
struct Event dummy;
struct Event * ev = (struct Event *) dest;
struct Event dummy;
struct Event * ev = (struct Event *) dest;
if(ev == NULL)
ev = &dummy; //If we are just counting events instead of loading them
if(ev == NULL)
ev = &dummy; /* If we are just counting events instead of loading them */
ev->delta = readVarData(file);
ev->delta = readVarData(file);
int t=readChar(file);
int t=readChar(file);
if((t&0x80) == 0x80) //if not a running status event
{
ev->status = t;
if(t == 0xFF)
{
ev->d1 = readChar(file);
ev->len = readVarData(file);
if((t&0x80) == 0x80) /* if not a running status event */
{
ev->status = t;
if(t == 0xFF)
{
ev->d1 = readChar(file);
ev->len = readVarData(file);
//Allocate and read in the data block
if(dest != NULL)
{
ev->evData = readData(file, ev->len);
printf("\nDATA: <%s>", ev->evData);
}
else
{
//Don't allocate anything, just see how much it would tale
//To make memory usage efficient
/* Allocate and read in the data block */
if(dest != NULL)
{
ev->evData = readData(file, ev->len);
printf("\nDATA: <%s>", ev->evData);
}
else
{
/*
* Don't allocate anything, just see how much it would tale
* To make memory usage efficient
*/
unsigned int a=0;
for(a=0; a<ev->len; a++)
readChar(file); //Skip skip
}
int a=0;
for(a=0; a<ev->len; a++)
readChar(file); //Skip skip
}
if(ev->d1 == 0x2F)
{
return 0; /* Termination meta-event */
}
} else /* If part of a running status event */
{
rStatus = t;
ev->status = t;
ev->d1 = readChar(file);
if(ev->d1 == 0x2F)
{
return 0; //Termination meta-event
}
} else //If part of a running status event
{
rStatus = t;
ev->status = t;
ev->d1 = readChar(file);
if ( ((t & 0xF0) != 0xD0) && ((t & 0xF0) != 0xC0) && ((t & 0xF0) > 0x40) )
{
ev->d2 = readChar(file);
} else
ev->d2 = 127;
}
} else //Running Status
{
ev->status = rStatus;
ev->d1 = t;
if ( ((rStatus & 0xF0) != 0xD0) && ((rStatus & 0xF0) != 0xC0) && ((rStatus & 0xF0) > 0x40) )
{
ev->d2 = readChar(file);
} else
ev->d2 = 127;
}
return 1;
if ( ((t & 0xF0) != 0xD0) && ((t & 0xF0) != 0xC0) && ((t & 0xF0) > 0x40) )
{
ev->d2 = readChar(file);
} else
ev->d2 = 127;
}
} else /* Running Status */
{
ev->status = rStatus;
ev->d1 = t;
if ( ((rStatus & 0xF0) != 0xD0) && ((rStatus & 0xF0) != 0xC0) && ((rStatus & 0xF0) > 0x40) )
{
ev->d2 = readChar(file);
} else
ev->d2 = 127;
}
return 1;
}
struct Track * readTrack(int file)
{
struct Track * trk = (struct Track *)allocate(sizeof(struct Track));
rb->memset(trk, 0, sizeof(struct Track));
struct Track * trk = (struct Track *)allocate(sizeof(struct Track));
rb->memset(trk, 0, sizeof(struct Track));
trk->size = readFourBytes(file);
trk->pos = 0;
trk->delta = 0;
trk->size = readFourBytes(file);
trk->pos = 0;
trk->delta = 0;
int numEvents=0;
int numEvents=0;
int pos = rb->lseek(file, 0, SEEK_CUR);
int pos = rb->lseek(file, 0, SEEK_CUR);
while(readEvent(file, NULL)) //Memory saving technique
numEvents++; //Attempt to read in events, count how many
//THEN allocate memory and read them in
rb->lseek(file, pos, SEEK_SET);
while(readEvent(file, NULL)) /* Memory saving technique */
numEvents++; /* Attempt to read in events, count how many */
/* THEN allocate memory and read them in */
rb->lseek(file, pos, SEEK_SET);
int trackSize = (numEvents+1) * sizeof(struct Event);
void * dataPtr = allocate(trackSize);
trk->dataBlock = dataPtr;
int trackSize = (numEvents+1) * sizeof(struct Event);
void * dataPtr = allocate(trackSize);
trk->dataBlock = dataPtr;
numEvents=0;
numEvents=0;
while(readEvent(file, dataPtr))
{
if(trackSize < dataPtr-trk->dataBlock)
{
printf("\nTrack parser memory out of bounds");
exit(1);
}
dataPtr+=sizeof(struct Event);
numEvents++;
}
trk->numEvents = numEvents;
while(readEvent(file, dataPtr))
{
if(trackSize < dataPtr-trk->dataBlock)
{
printf("\nTrack parser memory out of bounds");
exit(1);
}
dataPtr+=sizeof(struct Event);
numEvents++;
}
trk->numEvents = numEvents;
return trk;
return trk;
}
int readID(int file)
{
char id[5];
id[4]=0;
BYTE a;
char id[5];
id[4]=0;
BYTE a;
for(a=0; a<4; a++)
id[a]=readChar(file);
if(eof(file))
{
printf("\End of file reached.");
return ID_EOF;
}
if(rb->strcmp(id, "MThd")==0)
return ID_MTHD;
if(rb->strcmp(id, "MTrk")==0)
return ID_MTRK;
return ID_UNKNOWN;
for(a=0; a<4; a++)
id[a]=readChar(file);
if(eof(file))
{
printf("\End of file reached.");
return ID_EOF;
}
if(rb->strcmp(id, "MThd")==0)
return ID_MTHD;
if(rb->strcmp(id, "MTrk")==0)
return ID_MTRK;
return ID_UNKNOWN;
}
int readFourBytes(int file)
{
int data=0;
BYTE a=0;
for(a=0; a<4; a++)
data=(data<<8)+readChar(file);
return data;
int data=0;
BYTE a=0;
for(a=0; a<4; a++)
data=(data<<8)+readChar(file);
return data;
}
int readTwoBytes(int file)
{
int data=(readChar(file)<<8)+readChar(file);
return data;
int data=(readChar(file)<<8)+readChar(file);
return data;
}
//This came from the MIDI file format guide
/* This came from the MIDI file format guide */
int readVarData(int file)
{
unsigned int value;
@ -270,37 +269,35 @@ int readVarData(int file)
/*
//This function should not be needed because we
//can just release the whole memory buffer at once
void unloadFile(struct MIDIfile * mf)
{
if(mf == NULL)
return;
int a=0;
//Unload each track
for(a=0; a<mf->numTracks; a++)
{
int b=0;
if(mf == NULL)
return;
int a=0;
//Unload each track
for(a=0; a<mf->numTracks; a++)
{
int b=0;
if(mf->tracks[a] != NULL)
for(b=0; b<mf->tracks[a]->numEvents; b++)
{
if(((struct Event*)((mf->tracks[a]->dataBlock)+b*sizeof(struct Event)))->evData!=NULL)
free(((struct Event*)((mf->tracks[a]->dataBlock)+b*sizeof(struct Event)))->evData);
}
if(mf->tracks[a] != NULL)
for(b=0; b<mf->tracks[a]->numEvents; b++)
{
if(((struct Event*)((mf->tracks[a]->dataBlock)+b*sizeof(struct Event)))->evData!=NULL)
free(((struct Event*)((mf->tracks[a]->dataBlock)+b*sizeof(struct Event)))->evData);
}
if(mf->tracks[a]!=NULL && mf->tracks[a]->dataBlock != NULL)
free(mf->tracks[a]->dataBlock); //Unload the event block
if(mf->tracks[a]!=NULL && mf->tracks[a]->dataBlock != NULL)
free(mf->tracks[a]->dataBlock); //Unload the event block
if(mf->tracks[a]!=NULL)
free(mf->tracks[a]); //Unload the track structure itself
}
free(mf); //Unload the main struct
if(mf->tracks[a]!=NULL)
free(mf->tracks[a]); //Unload the track structure itself
}
free(mf); //Unload the main struct
}
*/
void bail(const char * err)
{
rb->splash(HZ*3, true, err);
exit(0);
rb->splash(HZ*3, true, err);
exit(0);
}

View file

@ -20,39 +20,39 @@
#define BYTE unsigned char
//Data chunk ID types, returned by readID()
#define ID_UNKNOWN -1
#define ID_MTHD 1
#define ID_MTRK 2
#define ID_EOF 3
#define ID_UNKNOWN -1
#define ID_MTHD 1
#define ID_MTRK 2
#define ID_EOF 3
//MIDI Commands
#define MIDI_NOTE_OFF 128
#define MIDI_NOTE_ON 144
#define MIDI_AFTERTOUCH 160
#define MIDI_CONTROL 176
#define MIDI_PRGM 192
#define MIDI_PITCHW 224
#define MIDI_NOTE_OFF 128
#define MIDI_NOTE_ON 144
#define MIDI_AFTERTOUCH 160
#define MIDI_CONTROL 176
#define MIDI_PRGM 192
#define MIDI_PITCHW 224
//MIDI Controllers
#define CTRL_VOLUME 7
#define CTRL_BALANCE 8
#define CTRL_PANNING 10
#define CHANNEL 1
#define CTRL_VOLUME 7
#define CTRL_BALANCE 8
#define CTRL_PANNING 10
#define CHANNEL 1
//Most of these are deprecated.. rampdown is used, maybe one other one too
#define STATE_ATTACK 1
#define STATE_DECAY 2
#define STATE_SUSTAIN 3
#define STATE_RELEASE 4
#define STATE_RAMPDOWN 5
#define STATE_ATTACK 1
#define STATE_DECAY 2
#define STATE_SUSTAIN 3
#define STATE_RELEASE 4
#define STATE_RAMPDOWN 5
//Loop states
#define STATE_LOOPING 7
#define STATE_NONLOOPING 8
#define STATE_NONLOOPING 8
//Various bits in the GUS mode byte
#define LOOP_ENABLED 4
#define LOOP_ENABLED 4
#define LOOP_PINGPONG 8
#define LOOP_REVERSE 16
@ -63,81 +63,69 @@
extern struct plugin_api * rb;
int chVol[16] IDATA_ATTR; //Channel volume
int chPanLeft[16] IDATA_ATTR; //Channel panning
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
int chPat[16]; /* Channel patch */
int chPW[16]; /* Channel pitch wheel, MSB only */
/*
unsigned char chVol[16]; //Channel volume
unsigned char chPanLeft[16]; //Channel panning
unsigned char chPanRight[16];
unsigned char chPat[16]; //Channel patch
unsigned char chPW[16]; //Channel pitch wheel, MSB only
*/
struct GPatch * gusload(char *);
struct GPatch * patchSet[128];
struct GPatch * drumSet[128];
//char myarray[80] IDATA_ATTR;
struct Event
{
unsigned int delta;
unsigned char status, d1, d2;
unsigned int len;
unsigned char * evData;
unsigned int delta;
unsigned char status, d1, d2;
unsigned int len;
unsigned char * evData;
};
struct Track
{
unsigned int size;
unsigned int numEvents;
unsigned int delta; //For sequencing
unsigned int pos; //For sequencing
void * dataBlock;
unsigned int size;
unsigned int numEvents;
unsigned int delta; /* For sequencing */
unsigned int pos; /* For sequencing */
void * dataBlock;
};
struct MIDIfile
{
int Length;
//int Format; //We don't really care what type it is
unsigned short numTracks;
unsigned short div; //Time division, X ticks per millisecond
struct Track * tracks[48];
unsigned char patches[128];
int numPatches;
int Length;
unsigned short numTracks;
unsigned short div; /* Time division, X ticks per millisecond */
struct Track * tracks[48];
unsigned char patches[128];
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 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 GWaveform * wf;
int delta;
int decay;
unsigned int cp;
int state, loopState, loopDir;
int note, vol, ch, isUsed;
int curRate, curOffset, targetOffset;
int curPoint;
};
struct SynthObject voices[MAX_VOICES] IDATA_ATTR;
@ -156,91 +144,91 @@ int midimain(void * filename);
void *alloc(int size)
{
static char *offset = NULL;
static int totalSize = 0;
char *ret;
static char *offset = NULL;
static int totalSize = 0;
char *ret;
int remainder = size % 4;
int remainder = size % 4;
size = size + 4-remainder;
size = size + 4-remainder;
if (offset == NULL)
{
offset = rb->plugin_get_audio_buffer(&totalSize);
}
if (offset == NULL)
{
offset = rb->plugin_get_audio_buffer(&totalSize);
}
if (size + 4 > totalSize)
{
return NULL;
}
if (size + 4 > totalSize)
{
return NULL;
}
ret = offset + 4;
*((unsigned int *)offset) = size;
ret = offset + 4;
*((unsigned int *)offset) = size;
offset += size + 4;
totalSize -= size + 4;
return ret;
offset += size + 4;
totalSize -= size + 4;
return ret;
}
//Rick's code
/* Rick's code */
/*
void *alloc(int size)
{
static char *offset = NULL;
static int totalSize = 0;
char *ret;
static char *offset = NULL;
static int totalSize = 0;
char *ret;
if (offset == NULL)
{
offset = rb->plugin_get_audio_buffer(&totalSize);
}
if (offset == NULL)
{
offset = rb->plugin_get_audio_buffer(&totalSize);
}
if (size + 4 > totalSize)
{
return NULL;
}
if (size + 4 > totalSize)
{
return NULL;
}
ret = offset + 4;
*((unsigned int *)offset) = size;
ret = offset + 4;
*((unsigned int *)offset) = size;
offset += size + 4;
totalSize -= size + 4;
return ret;
offset += size + 4;
totalSize -= size + 4;
return ret;
}*/
void * allocate(int size)
{
return alloc(size);
return alloc(size);
}
unsigned char readChar(int file)
{
char buf[2];
rb->read(file, &buf, 1);
return buf[0];
char buf[2];
rb->read(file, &buf, 1);
return buf[0];
}
unsigned char * readData(int file, int len)
{
unsigned char * dat = allocate(len);
rb->read(file, dat, len);
return dat;
unsigned char * dat = allocate(len);
rb->read(file, dat, len);
return dat;
}
int eof(int fd)
{
int curPos = rb->lseek(fd, 0, SEEK_CUR);
int curPos = rb->lseek(fd, 0, SEEK_CUR);
int size = rb->lseek(fd, 0, SEEK_END);
int size = rb->lseek(fd, 0, SEEK_END);
rb->lseek(fd, curPos, SEEK_SET);
return size+1 == rb->lseek(fd, 0, SEEK_CUR);
rb->lseek(fd, curPos, SEEK_SET);
return size+1 == rb->lseek(fd, 0, SEEK_CUR);
}
void printf(char *fmt, ...) {fmt=fmt; }
void exit(int code)
{
code = code; //Stub function, kill warning for now
code = code; /* Stub function, kill warning for now */
}

View file

@ -24,233 +24,220 @@ long tempo=375000;
void setVol(int ch, int vol)
{
printf("\nvolume[%d] %d ==> %d", ch, chVol[ch], vol);
chVol[ch]=vol;
printf("\nvolume[%d] %d ==> %d", ch, chVol[ch], vol);
chVol[ch]=vol;
}
void setPan(int ch, int pan)
{
printf("\npanning[%d] %d ==> %d", ch, chPanRight[ch], pan);
printf("\npanning[%d] %d ==> %d", ch, chPanRight[ch], pan);
chPanLeft[ch]=128-pan;
chPanRight[ch]=pan;
chPanLeft[ch]=128-pan;
chPanRight[ch]=pan;
}
void setPatch(int ch, int pat)
{
chPat[ch]=pat;
chPat[ch]=pat;
}
/*
Pitch Bend table, Computed by
for i=0:127, fprintf('%d,', round(2^16*2^((i-64)/384))); end
(When typed into Matlab)
16 bit pitch bend table
* Pitch Bend table, Computed by
* for i=0:127, fprintf('%d,', round(2^16*2^((i-64)/384))); end
* (When typed into Matlab)
* 16 bit pitch bend table
*/
long pitchTbl[]=
{
58386,58491,58597,58703,58809,58915,59022,59128,59235,59342,59449,59557,59664,59772,59880,59988,60097,60205,
60314,60423,60532,60642,60751,60861,60971,61081,61191,61302,61413,61524,61635,61746,61858,61970,62081,62194,
62306,62419,62531,62644,62757,62871,62984,63098,63212,63326,63441,63555,63670,63785,63901,64016,64132,64248,
64364,64480,64596,64713,64830,64947,65065,65182,65300,65418,65536,65654,65773,65892,66011,66130,66250,66369,
66489,66609,66730,66850,66971,67092,67213,67335,67456,67578,67700,67823,67945,68068,68191,68314,68438,68561,
68685,68809,68933,69058,69183,69308,69433,69558,69684,69810,69936,70062,70189,70316,70443,70570,70698,70825,
70953,71082,71210,71339,71468,71597,71726,71856,71985,72115,72246,72376,72507,72638,72769,72901,73032,73164,
73297,73429
58386,58491,58597,58703,58809,58915,59022,59128,59235,59342,59449,59557,59664,59772,59880,59988,60097,60205,
60314,60423,60532,60642,60751,60861,60971,61081,61191,61302,61413,61524,61635,61746,61858,61970,62081,62194,
62306,62419,62531,62644,62757,62871,62984,63098,63212,63326,63441,63555,63670,63785,63901,64016,64132,64248,
64364,64480,64596,64713,64830,64947,65065,65182,65300,65418,65536,65654,65773,65892,66011,66130,66250,66369,
66489,66609,66730,66850,66971,67092,67213,67335,67456,67578,67700,67823,67945,68068,68191,68314,68438,68561,
68685,68809,68933,69058,69183,69308,69433,69558,69684,69810,69936,70062,70189,70316,70443,70570,70698,70825,
70953,71082,71210,71339,71468,71597,71726,71856,71985,72115,72246,72376,72507,72638,72769,72901,73032,73164,
73297,73429
};
void findDelta(struct SynthObject * so, int ch, int note)
{
struct GWaveform * wf = patchSet[chPat[ch]]->waveforms[patchSet[chPat[ch]]->noteTable[note]];
so->wf=wf;
so->delta = (((gustable[note]<<10) / wf->rootFreq) * wf->sampRate / SAMPLE_RATE);
so->delta = so->delta * pitchTbl[chPW[ch]] >> 16;
struct GWaveform * wf = patchSet[chPat[ch]]->waveforms[patchSet[chPat[ch]]->noteTable[note]];
so->wf=wf;
so->delta = (((gustable[note]<<10) / (wf->rootFreq)) * wf->sampRate / (SAMPLE_RATE));
so->delta = (so->delta * pitchTbl[chPW[ch]])>> 16;
}
void setPW(int ch, int msb)
{
printf("\npitchw[%d] %d ==> %d", ch, chPW[ch], msb);
chPW[ch] = msb;
printf("\npitchw[%d] %d ==> %d", ch, chPW[ch], msb);
chPW[ch] = msb;
int a=0;
for(a = 0; a<MAX_VOICES; a++)
{
if(voices[a].isUsed==1 && voices[a].ch == ch)
{
findDelta(&voices[a], ch, voices[a].note);
}
}
int a=0;
for(a = 0; a<MAX_VOICES; a++)
{
if(voices[a].isUsed==1 && voices[a].ch == ch)
{
findDelta(&voices[a], ch, voices[a].note);
}
}
}
void pressNote(int ch, int note, int vol)
{
//Silences all channels but one, for easy debugging, for me.
/*
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;
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;
for(a=0; a<MAX_VOICES; a++)
{
if(voices[a].ch == ch && voices[a].note == note)
break;
int a=0;
for(a=0; a<MAX_VOICES; a++)
{
if(voices[a].ch == ch && voices[a].note == note)
break;
if(voices[a].isUsed==0)
break;
}
if(a==MAX_VOICES-1)
{
printf("\nOVERFLOW: Too many voices playing at once. No more left");
printf("\nVOICE DUMP: ");
for(a=0; a<48; a++)
printf("\n#%d Ch=%d Note=%d curRate=%d curOffset=%d curPoint=%d targetOffset=%d", a, voices[a].ch, voices[a].note, voices[a].curRate, voices[a].curOffset, voices[a].curPoint, voices[a].targetOffset);
return; //None avaolable
}
voices[a].ch=ch;
voices[a].note=note;
voices[a].vol=vol;
voices[a].cp=0;
voices[a].state=STATE_ATTACK;
// voices[a].pstate=STATE_ATTACK;
voices[a].decay=255;
if(voices[a].isUsed==0)
break;
}
if(a==MAX_VOICES-1)
{
printf("\nOVERFLOW: Too many voices playing at once. No more left");
printf("\nVOICE DUMP: ");
for(a=0; a<48; a++)
printf("\n#%d Ch=%d Note=%d curRate=%d curOffset=%d curPoint=%d targetOffset=%d", a, voices[a].ch, voices[a].note, voices[a].curRate, voices[a].curOffset, voices[a].curPoint, voices[a].targetOffset);
return; /* None available */
}
voices[a].ch=ch;
voices[a].note=note;
voices[a].vol=vol;
voices[a].cp=0;
voices[a].state=STATE_ATTACK;
voices[a].decay=255;
voices[a].loopState=STATE_NONLOOPING;
voices[a].loopDir = LOOPDIR_FORWARD;
/*
OKAY. Gt = Gus Table value
rf = Root Frequency of wave
SR = sound sampling rate
sr = WAVE sampling rate
*/
voices[a].loopState=STATE_NONLOOPING;
voices[a].loopDir = LOOPDIR_FORWARD;
/*
* OKAY. Gt = Gus Table value
* rf = Root Frequency of wave
* SR = sound sampling rate
* sr = WAVE sampling rate
*/
if(ch!=9)
{
findDelta(&voices[a], ch, note);
/* Turn it on */
voices[a].isUsed=1;
setPoint(&voices[a], 0);
} else
{
if(drumSet[note]!=NULL)
{
if(note<35)
printf("\nNOTE LESS THAN 35, AND A DRUM PATCH EXISTS FOR THIS? WHAT THE HELL?");
/*
unsigned int gt = gustable[note];
unsigned int rf = wf->rootFreq;
unsigned int SR = SAMPLE_RATE;
unsigned int sr = wf->sampRate;
voices[a].delta=((((gt<<10) / rf) * sr / SR));
*/
struct GWaveform * wf = drumSet[note]->waveforms[0];
voices[a].wf=wf;
voices[a].delta = (((gustable[note]<<10) / wf->rootFreq) * wf->sampRate / SAMPLE_RATE);
if(wf->mode & 28)
printf("\nWoah, a drum patch has a loop. Stripping the loop...");
wf->mode = wf->mode & (255-28);
/* Turn it on */
voices[a].isUsed=1;
setPoint(&voices[a], 0);
if(ch!=9)
{
findDelta(&voices[a], ch, note);
//Turn it on
voices[a].isUsed=1;
setPoint(&voices[a], 0);
} else
{
if(drumSet[note]!=NULL)
{
if(note<35)
printf("\nNOTE LESS THAN 35, AND A DRUM PATCH EXISTS FOR THIS? WHAT THE HELL?");
struct GWaveform * wf = drumSet[note]->waveforms[0];
voices[a].wf=wf;
voices[a].delta = (((gustable[note]<<10) / wf->rootFreq) * wf->sampRate / SAMPLE_RATE);
if(wf->mode & 28)
printf("\nWoah, a drum patch has a loop. Stripping the loop...");
wf->mode = wf->mode & (255-28);
//Turn it on
voices[a].isUsed=1;
setPoint(&voices[a], 0);
} else
{
printf("\nWarning: drum %d does not have a patch defined... Ignoring it", note);
}
}
} else
{
printf("\nWarning: drum %d does not have a patch defined... Ignoring it", note);
}
}
}
void releaseNote(int ch, int note)
{
if(ch==9) // && note != 27 && note != 31 && note != 28)
return;
int a=0;
for(a=0; a<MAX_VOICES; a++)
{
if(voices[a].ch == ch && voices[a].note == note)
{
if((voices[a].wf->mode & 28))
{
// voices[a].tmp=40;
// voices[a].state = STATE_RELEASE; //Ramp down
if(ch==9)
return;
// voices[a].state = STATE_RAMPDOWN; //Ramp down
setPoint(&voices[a], 3);
}
}
}
int a=0;
for(a=0; a<MAX_VOICES; a++)
{
if(voices[a].ch == ch && voices[a].note == note)
{
if((voices[a].wf->mode & 28))
{
setPoint(&voices[a], 3);
}
}
}
}
void sendEvent(struct Event * ev)
{
// printf("\nEVENT S=%2x D1=%2x D2=%2x", ev->status, ev->d1, ev->d2);
if( ((ev->status & 0xF0) == MIDI_CONTROL) && (ev->d1 == CTRL_VOLUME) )
{
setVol((ev->status & 0xF), ev->d2);
return;
}
if( ((ev->status & 0xF0) == MIDI_CONTROL) && (ev->d1 == CTRL_VOLUME) )
{
setVol((ev->status & 0xF), ev->d2);
return;
}
if( ((ev->status & 0xF0) == MIDI_CONTROL) && (ev->d1 == CTRL_PANNING))
{
setPan((ev->status & 0xF), ev->d2);
return;
}
if( ((ev->status & 0xF0) == MIDI_CONTROL) && (ev->d1 == CTRL_PANNING))
{
setPan((ev->status & 0xF), ev->d2);
return;
}
if(((ev->status & 0xF0) == MIDI_PITCHW))
{
setPW((ev->status & 0xF), ev->d2);
return;
}
if(((ev->status & 0xF0) == MIDI_PITCHW))
{
setPW((ev->status & 0xF), ev->d2);
return;
}
if(((ev->status & 0xF0) == MIDI_NOTE_ON) && (ev->d2 != 0))
{
pressNote(ev->status & 0x0F, ev->d1, ev->d2);
return;
}
if(((ev->status & 0xF0) == MIDI_NOTE_ON) && (ev->d2 != 0))
{
pressNote(ev->status & 0x0F, ev->d1, ev->d2);
return;
}
if(((ev->status & 0xF0) == MIDI_NOTE_ON) && (ev->d2 == 0)) //Release by vol=0
{
releaseNote(ev->status & 0x0F, ev->d1);
return;
}
if(((ev->status & 0xF0) == MIDI_NOTE_ON) && (ev->d2 == 0)) /* Release by vol=0 */
{
releaseNote(ev->status & 0x0F, ev->d1);
return;
}
if((ev->status & 0xF0) == MIDI_NOTE_OFF)
{
releaseNote(ev->status & 0x0F, ev->d1);
return;
}
if((ev->status & 0xF0) == MIDI_NOTE_OFF)
{
releaseNote(ev->status & 0x0F, ev->d1);
return;
}
if((ev->status & 0xF0) == MIDI_PRGM)
{
if((ev->status & 0x0F) == 9)
printf("\nNOT PATCHING: Someone tried patching Channel 9 onto something?");
else
setPatch(ev->status & 0x0F, ev->d1);
}
if((ev->status & 0xF0) == MIDI_PRGM)
{
if((ev->status & 0x0F) == 9)
printf("\nNOT PATCHING: Someone tried patching Channel 9 onto something?");
else
setPatch(ev->status & 0x0F, ev->d1);
}
}
@ -259,61 +246,60 @@ void sendEvent(struct Event * ev)
int tick(struct MIDIfile * mf)
{
if(mf==NULL)
return 0;
if(mf==NULL)
return 0;
int a=0;
int tracksAdv=0;
for(a=0; a<mf->numTracks; a++)
{
struct Track * tr = mf->tracks[a];
int a=0;
int tracksAdv=0;
for(a=0; a<mf->numTracks; a++)
{
struct Track * tr = mf->tracks[a];
if(tr == NULL)
printf("\nNULL TRACK: %d", a);
if(tr == NULL)
printf("\nNULL TRACK: %d", a);
//BIG DEBUG STATEMENT
//printf("\nTrack %2d, Event = %4d of %4d, Delta = %5d, Next = %4d", a, tr->pos, tr->numEvents, tr->delta, getEvent(tr, tr->pos)->delta);
//BIG DEBUG STATEMENT
//printf("\nTrack %2d, Event = %4d of %4d, Delta = %5d, Next = %4d", a, tr->pos, tr->numEvents, tr->delta, getEvent(tr, tr->pos)->delta);
if(tr != NULL && (tr->pos < tr->numEvents))
{
tr->delta++;
tracksAdv++;
while(getEvent(tr, tr->pos)->delta <= tr->delta)
{
// printf("\nDelta = %d", tr->delta);
struct Event * e = getEvent(tr, tr->pos);
if(tr != NULL && (tr->pos < tr->numEvents))
{
tr->delta++;
tracksAdv++;
while(getEvent(tr, tr->pos)->delta <= tr->delta)
{
struct Event * e = getEvent(tr, tr->pos);
if(e->status != 0xFF)
{
sendEvent(e);
if(((e->status&0xF0) == MIDI_PRGM))
{
printf("\nPatch Event, patch[%d] ==> %d", e->status&0xF, e->d1);
}
}
else
{
if(e->d1 == 0x51)
{
tempo = (((short)e->evData[0])<<16)|(((short)e->evData[1])<<8)|(e->evData[2]);
printf("\nMeta-Event: Tempo Set = %d", tempo);
bpm=mf->div*1000000/tempo;
numberOfSamples=SAMPLE_RATE/bpm;
if(e->status != 0xFF)
{
sendEvent(e);
if(((e->status&0xF0) == MIDI_PRGM))
{
printf("\nPatch Event, patch[%d] ==> %d", e->status&0xF, e->d1);
}
}
else
{
if(e->d1 == 0x51)
{
tempo = (((short)e->evData[0])<<16)|(((short)e->evData[1])<<8)|(e->evData[2]);
printf("\nMeta-Event: Tempo Set = %d", tempo);
bpm=mf->div*1000000/tempo;
numberOfSamples=SAMPLE_RATE/bpm;
}
}
tr->delta = 0;
tr->pos++;
if(tr->pos>=(tr->numEvents-1))
break;
}
}
}
}
}
tr->delta = 0;
tr->pos++;
if(tr->pos>=(tr->numEvents-1))
break;
}
}
}
if(tracksAdv != 0)
return 1;
else
return 0;
if(tracksAdv != 0)
return 1;
else
return 0;
}

View file

@ -20,158 +20,164 @@ extern struct plugin_api * rb;
struct Event * getEvent(struct Track * tr, int evNum)
{
return tr->dataBlock + (evNum*sizeof(struct Event));
return tr->dataBlock + (evNum*sizeof(struct Event));
}
void readTextBlock(int file, char * buf)
{
char c = 0;
do
{
c = readChar(file);
} while(c == '\n' || c == ' ' || c=='\t');
char c = 0;
do
{
c = readChar(file);
} while(c == '\n' || c == ' ' || c=='\t');
rb->lseek(file, -1, SEEK_CUR);
int cp = 0;
do
{
c = readChar(file);
buf[cp] = c;
cp++;
} while (c != '\n' && c != ' ' && c != '\t' && !eof(file));
buf[cp-1]=0;
rb->lseek(file, -1, SEEK_CUR);
rb->lseek(file, -1, SEEK_CUR);
int cp = 0;
do
{
c = readChar(file);
buf[cp] = c;
cp++;
} while (c != '\n' && c != ' ' && c != '\t' && !eof(file));
buf[cp-1]=0;
rb->lseek(file, -1, SEEK_CUR);
}
//Filename is the name of the config file
//The MIDI file should have been loaded at this point
/* Filename is the name of the config file */
/* The MIDI file should have been loaded at this point */
int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig)
{
char patchUsed[128];
char drumUsed[128];
int a=0;
for(a=0; a<MAX_VOICES; a++)
{
voices[a].cp=0;
voices[a].vol=0;
voices[a].ch=0;
voices[a].isUsed=0;
voices[a].note=0;
}
char patchUsed[128];
char drumUsed[128];
int a=0;
for(a=0; a<MAX_VOICES; a++)
{
voices[a].cp=0;
voices[a].vol=0;
voices[a].ch=0;
voices[a].isUsed=0;
voices[a].note=0;
}
for(a=0; a<16; a++)
{
chVol[a]=100; //Default, not quite full blast..
chPanLeft[a]=64; //Center
chPanRight[a]=64; //Center
chPat[a]=0; //Ac Gr Piano
chPW[a]=64; // .. not .. bent ?
}
for(a=0; a<128; a++)
{
patchSet[a]=NULL;
drumSet[a]=NULL;
patchUsed[a]=0;
drumUsed[a]=0;
}
for(a=0; a<16; a++)
{
chVol[a]=100; /* Default, not quite full blast.. */
chPanLeft[a]=64; /* Center */
chPanRight[a]=64; /* Center */
chPat[a]=0; /* Ac Gr Piano */
chPW[a]=64; /* .. not .. bent ? */
}
for(a=0; a<128; a++)
{
patchSet[a]=NULL;
drumSet[a]=NULL;
patchUsed[a]=0;
drumUsed[a]=0;
}
//Always load the piano.
//Some files will assume its loaded without specifically
//issuing a Patch command... then we wonder why we can't hear anything
patchUsed[0]=1;
/*
* Always load the piano.
* Some files will assume its loaded without specifically
* issuing a Patch command... then we wonder why we can't hear anything
*/
patchUsed[0]=1;
//Scan the file to see what needs to be loaded
for(a=0; a<mf->numTracks; a++)
{
int ts=0;
/* Scan the file to see what needs to be loaded */
for(a=0; a<mf->numTracks; a++)
{
unsigned int ts=0;
if(mf->tracks[a] == NULL)
{
printf("\nNULL TRACK !!!");
rb->splash(HZ*2, true, "Null Track in loader.");
return -1;
}
if(mf->tracks[a] == NULL)
{
printf("\nNULL TRACK !!!");
rb->splash(HZ*2, true, "Null Track in loader.");
return -1;
}
for(ts=0; ts<mf->tracks[a]->numEvents; ts++)
{
for(ts=0; ts<mf->tracks[a]->numEvents; ts++)
{
if((getEvent(mf->tracks[a], ts)->status) == (MIDI_NOTE_ON+9))
drumUsed[getEvent(mf->tracks[a], ts)->d1]=1;
if((getEvent(mf->tracks[a], ts)->status) == (MIDI_NOTE_ON+9))
drumUsed[getEvent(mf->tracks[a], ts)->d1]=1;
if( (getEvent(mf->tracks[a], ts)->status & 0xF0) == MIDI_PRGM)
{
if(patchUsed[getEvent(mf->tracks[a], ts)->d1]==0)
printf("\nI need to load patch %d.", getEvent(mf->tracks[a], ts)->d1);
patchUsed[getEvent(mf->tracks[a], ts)->d1]=1;
}
}
}
if( (getEvent(mf->tracks[a], ts)->status & 0xF0) == MIDI_PRGM)
{
if(patchUsed[getEvent(mf->tracks[a], ts)->d1]==0)
printf("\nI need to load patch %d.", getEvent(mf->tracks[a], ts)->d1);
patchUsed[getEvent(mf->tracks[a], ts)->d1]=1;
}
}
}
int file = rb->open(filename, O_RDONLY);
if(file == -1)
{
rb->splash(HZ*2, true, "Bad patch config.\nDid you install the patchset?");
return -1;
}
int file = rb->open(filename, O_RDONLY);
if(file == -1)
{
rb->splash(HZ*2, true, "Bad patch config.\nDid you install the patchset?");
return -1;
}
char name[40];
char fn[40];
char name[40];
char fn[40];
//Scan our config file and load the right patches as needed
int c = 0;
rb->snprintf(name, 40, "");
for(a=0; a<128; a++)
{
while(readChar(file)!=' ' && !eof(file));
readTextBlock(file, name);
/* Scan our config file and load the right patches as needed */
int c = 0;
rb->snprintf(name, 40, "");
for(a=0; a<128; a++)
{
while(readChar(file)!=' ' && !eof(file));
readTextBlock(file, name);
rb->snprintf(fn, 40, "/.rockbox/patchset/%s.pat", name);
printf("\nLOADING: <%s> ", fn);
rb->snprintf(fn, 40, "/.rockbox/patchset/%s.pat", name);
printf("\nLOADING: <%s> ", fn);
if(patchUsed[a]==1)
patchSet[a]=gusload(fn);
if(patchUsed[a]==1)
{
patchSet[a]=gusload(fn);
// if(patchSet[a] == NULL)
// return -1;
if(patchSet[a] == NULL) /* There was an error loading it */
return -1;
}
while((c != '\n'))
c = readChar(file);
}
rb->close(file);
while((c != '\n'))
c = readChar(file);
}
rb->close(file);
file = rb->open(drumConfig, O_RDONLY);
if(file == -1)
{
rb->splash(HZ*2, true, "Bad drum config.\nDid you install the patchset?");
return -1;
}
file = rb->open(drumConfig, O_RDONLY);
if(file == -1)
{
rb->splash(HZ*2, true, "Bad drum config.\nDid you install the patchset?");
return -1;
}
//Scan our config file and load the drum data
int idx=0;
char number[30];
while(!eof(file))
{
readTextBlock(file, number);
readTextBlock(file, name);
rb->snprintf(fn, 40, "/.rockbox/patchset/%s.pat", name);
/* Scan our config file and load the drum data */
int idx=0;
char number[30];
while(!eof(file))
{
readTextBlock(file, number);
readTextBlock(file, name);
rb->snprintf(fn, 40, "/.rockbox/patchset/%s.pat", name);
idx = rb->atoi(number);
if(idx == 0)
break;
idx = rb->atoi(number);
if(idx == 0)
break;
if(drumUsed[idx]==1)
drumSet[idx]=gusload(fn);
if(drumUsed[idx]==1)
{
drumSet[idx]=gusload(fn);
// if(drumSet[idx] == NULL)
// return -1;
if(drumSet[idx] == NULL) /* Error loading patch */
return -1;
}
while((c != '\n') && (c != 255) && (!eof(file)))
c = readChar(file);
}
rb->close(file);
return 0;
while((c != '\n') && (c != 255) && (!eof(file)))
c = readChar(file);
}
rb->close(file);
return 0;
}
@ -182,7 +188,7 @@ struct GWaveform * wf IDATA_ATTR;
int s IDATA_ATTR;
short s1 IDATA_ATTR;
short s2 IDATA_ATTR;
short sample IDATA_ATTR; //For synthSample
short sample IDATA_ATTR; /* For synthSample */
unsigned int cpShifted IDATA_ATTR;
unsigned char b1 IDATA_ATTR;
@ -191,31 +197,9 @@ unsigned char b2 IDATA_ATTR;
inline int getSample(int s)
{
//16 bit samples
if(wf->mode&1)
{
if(s<<1 >= wf->wavSize)
{
printf("\n!!!!! %d \t %d", s<<1, wf->wavSize);
return 0;
}
// signed short a = ((short *)wf->data)[s];
//Sign conversion moved into guspat.c
b1=wf->data[s<<1]+((wf->mode & 2) << 6);
b2=wf->data[(s<<1)|1]+((wf->mode & 2) << 6);
return (b1 | (b2<<8)) ;
//Get rid of this sometime
}
else
{ //8-bit samples
//Do we even have anything 8-bit in our set?
int b1=wf->data[s]+((wf->mode & 2) << 6);
return b1<<8;
}
/* Sign conversion moved to guspat.c */
/* 8bit conversion NOT YET IMPLEMENTED in guspat.c */
return ((short *) wf->data)[s];
}
@ -223,190 +207,194 @@ inline int getSample(int s)
inline void setPoint(struct SynthObject * so, int pt)
{
if(so->ch==9) //Drums, no ADSR
{
so->curOffset = 1<<27;
so->curRate = 1;
return;
}
if(so->ch==9) /* Drums, no ADSR */
{
so->curOffset = 1<<27;
so->curRate = 1;
return;
}
if(so->wf==NULL)
{
printf("\nCrap... null waveform...");
exit(1);
}
if(so->wf->envRate==NULL)
{
printf("\nWaveform has no envelope set");
exit(1);
}
if(so->wf==NULL)
{
printf("\nCrap... null waveform...");
exit(1);
}
if(so->wf->envRate==NULL)
{
printf("\nWaveform has no envelope set");
exit(1);
}
so->curPoint = pt;
so->curPoint = pt;
int r=0;
int rate = so->wf->envRate[pt];
int r=0;
int rate = so->wf->envRate[pt];
r=3-((rate>>6) & 0x3); // Some blatant Timidity code for rate conversion...
r*=3;
r = (rate & 0x3f) << r;
r=3-((rate>>6) & 0x3); /* Some blatant Timidity code for rate conversion... */
r*=3;
r = (rate & 0x3f) << r;
/*
Okay. This is the rate shift. Timidity defaults to 9, and sets
it to 10 if you use the fast decay option. Slow decay sounds better
on some files, except on some other files... you get chords that aren't
done decaying yet.. and they dont harmonize with the next chord and it
sounds like utter crap. Yes, even Timitidy does that. So I'm going to
default this to 10, and maybe later have an option to set it to 9
for longer decays.
*/
so->curRate = r<<10;
/*
* Okay. This is the rate shift. Timidity defaults to 9, and sets
* it to 10 if you use the fast decay option. Slow decay sounds better
* on some files, except on some other files... you get chords that aren't
* done decaying yet.. and they dont harmonize with the next chord and it
* sounds like utter crap. Yes, even Timitidy does that. So I'm going to
* default this to 10, and maybe later have an option to set it to 9
* for longer decays.
*/
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;
/*
* 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);
if(pt==0)
so->curOffset = 0;
so->targetOffset = so->wf->envOffset[pt]<<(20);
if(pt==0)
so->curOffset = 0;
}
inline void stopVoice(struct SynthObject * so)
{
if(so->state == STATE_RAMPDOWN)
return;
so->state = STATE_RAMPDOWN;
so->decay = 255;
if(so->state == STATE_RAMPDOWN)
return;
so->state = STATE_RAMPDOWN;
so->decay = 255;
}
inline signed short int synthVoice()
{
so = &voices[currentVoice];
wf = so->wf;
so = &voices[currentVoice];
wf = so->wf;
if(so->state != STATE_RAMPDOWN)
{
so->cp += so->delta;
}
if(so->state != STATE_RAMPDOWN)
{
so->cp += so->delta;
}
cpShifted = so->cp >> 10;
cpShifted = so->cp >> 10;
if( (cpShifted >= (wf->wavSize>>1)) && (so->state != STATE_RAMPDOWN))
stopVoice(so);
if( (cpShifted > (wf->numSamples) && (so->state != STATE_RAMPDOWN)))
{
stopVoice(so);
}
s2 = getSample((cpShifted)+1);
if((wf->mode & (LOOP_REVERSE|LOOP_PINGPONG)) && so->loopState == STATE_LOOPING && (cpShifted <= (wf->startLoop>>1)))
{
if(wf->mode & LOOP_REVERSE)
{
so->cp = (wf->endLoop)<<9;
cpShifted = so->cp >> 10;
s2=getSample((cpShifted));
} else
{
so->delta = -so->delta;
so->loopDir = LOOPDIR_FORWARD;
}
}
/* LOOP_REVERSE|LOOP_PINGPONG = 24 */
if((wf->mode & (24)) && so->loopState == STATE_LOOPING && (cpShifted <= (wf->startLoop)))
{
if(wf->mode & LOOP_REVERSE)
{
so->cp = (wf->endLoop)<<10;
cpShifted = wf->endLoop;
s2=getSample((cpShifted));
} else
{
so->delta = -so->delta;
so->loopDir = LOOPDIR_FORWARD;
}
}
if((wf->mode & 28) && (so->cp>>10 >= wf->endLoop>>1))
{
so->loopState = STATE_LOOPING;
if((wf->mode & (24)) == 0)
{
so->cp = (wf->startLoop)<<9;
cpShifted = so->cp >> 10;
s2=getSample((cpShifted));
} else
{
so->delta = -so->delta;
so->loopDir = LOOPDIR_REVERSE;
}
}
if((wf->mode & 28) && (cpShifted >= wf->endLoop))
{
so->loopState = STATE_LOOPING;
if((wf->mode & (24)) == 0)
{
so->cp = (wf->startLoop)<<10;
cpShifted = wf->startLoop;
s2=getSample((cpShifted));
} else
{
so->delta = -so->delta;
so->loopDir = LOOPDIR_REVERSE;
}
}
//Better, working, linear interpolation
s1=getSample((cpShifted));
s = s1 + ((signed)((s2 - s1) * (so->cp & 1023))>>10);
/* Better, working, linear interpolation */
s1=getSample((cpShifted));
s = s1 + ((signed)((s2 - s1) * (so->cp & 1023))>>10);
//ADSR COMMENT WOULD GO FROM HERE.........
/* ADSR COMMENT WOULD GO FROM HERE.........*/
if(so->curRate == 0)
stopVoice(so);
if(so->curRate == 0)
stopVoice(so);
if(so->ch != 9) //Stupid ADSR code... and don't do ADSR for drums
{
if(so->curOffset < so->targetOffset)
{
so->curOffset += (so->curRate);
if(so -> curOffset > so->targetOffset && so->curPoint != 2)
{
if(so->curPoint != 5)
setPoint(so, so->curPoint+1);
else
stopVoice(so);
}
} else
{
so->curOffset -= (so->curRate);
if(so -> curOffset < so->targetOffset && so->curPoint != 2)
{
if(so->ch != 9) /* Stupid ADSR code... and don't do ADSR for drums */
{
if(so->curOffset < so->targetOffset)
{
so->curOffset += (so->curRate);
if(so -> curOffset > so->targetOffset && so->curPoint != 2)
{
if(so->curPoint != 5)
setPoint(so, so->curPoint+1);
else
stopVoice(so);
}
} else
{
so->curOffset -= (so->curRate);
if(so -> curOffset < so->targetOffset && so->curPoint != 2)
{
if(so->curPoint != 5)
setPoint(so, so->curPoint+1);
else
stopVoice(so);
if(so->curPoint != 5)
setPoint(so, so->curPoint+1);
else
stopVoice(so);
}
}
}
}
}
}
if(so->curOffset < 0)
so->isUsed=0; //This is OK
if(so->curOffset < 0)
so->isUsed=0; /* This is OK because offset faded it out already */
s = (s * (so->curOffset >> 22) >> 6);
s = (s * (so->curOffset >> 22) >> 8);
// ............. TO HERE
/* ............. TO HERE */
if(so->state == STATE_RAMPDOWN)
{
so->decay--;
if(so->decay == 0)
so->isUsed=0;
}
if(so->state == STATE_RAMPDOWN)
{
so->decay--;
if(so->decay == 0)
so->isUsed=0;
s = (s * so->decay) >> 8;
}
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;
}
inline void synthSample(int * mixL, int * mixR)
{
// signed int leftMix=0, rightMix=0,
*mixL = 0;
*mixR = 0;
for(currentVoice=0; currentVoice<MAX_VOICES; currentVoice++)
{
if(voices[currentVoice].isUsed==1)
{
sample = synthVoice(currentVoice);
*mixL += (sample*chPanLeft[voices[currentVoice].ch])>>7;
*mixR += (sample*chPanRight[voices[currentVoice].ch])>>7;
}
}
*mixL = 0;
*mixR = 0;
for(currentVoice=0; currentVoice<MAX_VOICES; currentVoice++)
{
if(voices[currentVoice].isUsed==1)
{
sample = synthVoice(currentVoice);
*mixL += (sample*chPanLeft[voices[currentVoice].ch])>>7;
*mixR += (sample*chPanRight[voices[currentVoice].ch])>>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 intrpolation works well.
/* TODO: Automatic Gain Control, anyone? */
/* Or, should this be implemented on the DSP's output volume instead? */
return; /* No more ghetto lowpass filter.. linear intrpolation works well. */
}

View file

@ -20,21 +20,22 @@
#define MAX_VOICES 100
//Only define LOCAL_DSP on Simulator or else we're asking for trouble
/* Only define LOCAL_DSP on Simulator or else we're asking for trouble */
#if defined(SIMULATOR)
//Enable this to write to the soundcard via a /dsv/dsp symlink in /
// #define LOCAL_DSP
/*Enable this to write to the soundcard via a /dsv/dsp symlink in */
// #define LOCAL_DSP
#endif
#if defined(LOCAL_DSP)
// This is for writing to the DSP directly from the Simulator
/* This is for writing to the DSP directly from the Simulator */
#include <stdio.h>
#include <stdlib.h>
#include <linux/soundcard.h>
#include <sys/ioctl.h>
#endif
#include "../../firmware/export/system.h"
#include "../../plugin.h"
@ -53,9 +54,9 @@ long bpm;
int fd=-1; //File descriptor where the output is written
int fd=-1; /* File descriptor where the output is written */
extern long tempo; //The sequencer keeps track of this
extern long tempo; /* The sequencer keeps track of this */
struct plugin_api * rb;
@ -66,27 +67,28 @@ struct plugin_api * rb;
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
{
TEST_PLUGIN_API(api);
rb = api;
TEST_PLUGIN_API(api);
(void)parameter;
rb = api;
TEST_PLUGIN_API(api);
rb = api;
TEST_PLUGIN_API(api);
(void)parameter;
rb = api;
if(parameter == NULL)
{
rb->splash(HZ*2, true, " Play .MID file ");
return PLUGIN_OK;
}
rb->splash(HZ, true, parameter);
if(midimain(parameter) == -1)
{
return PLUGIN_ERROR;
}
rb->splash(HZ*3, true, "FINISHED PLAYING");
return PLUGIN_OK;
if(parameter == NULL)
{
rb->splash(HZ*2, true, " Play .MID file ");
return PLUGIN_OK;
}
rb->splash(HZ, true, parameter);
if(midimain(parameter) == -1)
{
return PLUGIN_ERROR;
}
rb->splash(HZ*3, true, "FINISHED PLAYING");
return PLUGIN_OK;
}
signed char outputBuffer[3000] IDATA_ATTR; //signed char.. gonna run out of iram ... !
signed char outputBuffer[3000] IDATA_ATTR; /* signed char.. gonna run out of iram ... ! */
int currentSample IDATA_ATTR;
@ -98,132 +100,133 @@ int outputSampleTwo IDATA_ATTR;
int midimain(void * filename)
{
printf("\nHello.\n");
printf("\nHello.\n");
rb->splash(HZ/5, true, "LOADING MIDI");
rb->splash(HZ/5, true, "LOADING MIDI");
struct MIDIfile * mf = loadFile(filename);
struct MIDIfile * mf = loadFile(filename);
rb->splash(HZ/5, true, "LOADING PATCHES");
if (initSynth(mf, "/.rockbox/patchset/patchset.cfg", "/.rockbox/patchset/drums.cfg") == -1)
{
return -1;
}
rb->splash(HZ/5, true, "LOADING PATCHES");
if (initSynth(mf, "/.rockbox/patchset/patchset.cfg", "/.rockbox/patchset/drums.cfg") == -1)
{
return -1;
}
//This lets you hear the music through the sound card if you are on Simulator
//Make a symlink, archos/dsp.raw and make it point to /dev/dsp or whatever
//your sound device is.
/*
* This lets you hear the music through the sound card if you are on Simulator
* Make a symlink, archos/dsp.raw and make it point to /dev/dsp or whatever
* your sound device is.
*/
#if defined(LOCAL_DSP)
fd=rb->open("/dsp.raw", O_WRONLY);
int arg, status;
int bit, samp, ch;
fd=rb->open("/dsp.raw", O_WRONLY);
int arg, status;
int bit, samp, ch;
arg = 16; // sample size
status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);
status = ioctl(fd, SOUND_PCM_READ_BITS, &arg);
bit=arg;
arg = 16; /* sample size */
status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);
status = ioctl(fd, SOUND_PCM_READ_BITS, &arg);
bit=arg;
arg = 2; //Number of channels, 1=mono
status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg);
status = ioctl(fd, SOUND_PCM_READ_CHANNELS, &arg);
ch=arg;
arg = 2; /* Number of channels, 1=mono */
status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg);
status = ioctl(fd, SOUND_PCM_READ_CHANNELS, &arg);
ch=arg;
arg = SAMPLE_RATE; //Yeah. sampling rate
status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg);
status = ioctl(fd, SOUND_PCM_READ_RATE, &arg);
samp=arg;
arg = SAMPLE_RATE; /* Yeah. sampling rate */
status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg);
status = ioctl(fd, SOUND_PCM_READ_RATE, &arg);
samp=arg;
#else
file_info_struct file_info;
file_info.samplerate = SAMPLE_RATE;
file_info.infile = fd;
file_info.channels = 2;
file_info.bitspersample = 16;
local_init("/miditest.tmp", "/miditest.wav", &file_info, rb);
fd = file_info.outfile;
file_info_struct file_info;
file_info.samplerate = SAMPLE_RATE;
file_info.infile = fd;
file_info.channels = 2;
file_info.bitspersample = 16;
local_init("/miditest.tmp", "/miditest.wav", &file_info, rb);
fd = file_info.outfile;
#endif
rb->splash(HZ/5, true, " Starting Playback ");
rb->splash(HZ/5, true, " I hope this works... ");
/*
* 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
* MIDI playback is timed in terms of this value.. there are no forced
* delays or anything. It just produces enough samples for each tick, and
* the playback of these samples is what makes the timings right.
*
* This seems to work quite well.
*/
// 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
// MIDI playback is timed in terms of this value.. there are no forced
// delays or anything. It just produces enough samples for each tick, and
// the playback of these samples is what makes the timings right.
//
// This seems to work quite well.
printf("\nOkay, starting sequencing");
printf("\nOkay, starting sequencing");
currentSample=0; /* Sample counting variable */
outputBufferPosition = 0;
currentSample=0; //Sample counting variable
outputBufferPosition = 0;
bpm=mf->div*1000000/tempo;
numberOfSamples=SAMPLE_RATE/bpm;
bpm=mf->div*1000000/tempo;
numberOfSamples=SAMPLE_RATE/bpm;
//Tick() will return 0 if there are no more events left to play
while(tick(mf))
{
/* Tick() will return 0 if there are no more events left to play */
while(tick(mf))
{
/*
* Tempo recalculation moved to sequencer.c to be done on a tempo event only
*
*/
for(currentSample=0; currentSample<numberOfSamples; currentSample++)
{
//Some annoying math to compute the number of samples
//to syntehsize per each MIDI tick.
//Yes we need to do this math each time because the tempo
//could have changed.
// On second thought, this can be moved to the event that
//recalculates the tempo, to save a little bit of CPU time.
for(currentSample=0; currentSample<numberOfSamples; currentSample++)
{
synthSample(&outputSampleOne, &outputSampleTwo);
synthSample(&outputSampleOne, &outputSampleTwo);
//16-bit audio because, well, it's better
// But really because ALSA's OSS emulation sounds extremely
//noisy and distorted when in 8-bit mode. I still do not know
//why this happens.
outputBuffer[outputBufferPosition]=outputSampleOne&0XFF; // Low byte first
outputBufferPosition++;
outputBuffer[outputBufferPosition]=outputSampleOne>>8; //High byte second
outputBufferPosition++;
/*
* 16-bit audio because, well, it's better
* But really because ALSA's OSS emulation sounds extremely
* noisy and distorted when in 8-bit mode. I still do not know
* why this happens.
*/
outputBuffer[outputBufferPosition]=outputSampleTwo&0XFF; // Low byte first
outputBufferPosition++;
outputBuffer[outputBufferPosition]=outputSampleTwo>>8; //High byte second
outputBufferPosition++;
outputBuffer[outputBufferPosition]=outputSampleOne&0XFF; // Low byte first
outputBufferPosition++;
outputBuffer[outputBufferPosition]=outputSampleOne>>8; //High byte second
outputBufferPosition++;
outputBuffer[outputBufferPosition]=outputSampleTwo&0XFF; // Low byte first
outputBufferPosition++;
outputBuffer[outputBufferPosition]=outputSampleTwo>>8; //High byte second
outputBufferPosition++;
//As soon as we produce 2000 bytes of sound,
//write it to the sound card. Why 2000? I have
//no idea. It's 1 AM and I am dead tired.
if(outputBufferPosition>=2000)
{
rb->write(fd, outputBuffer, 2000);
outputBufferPosition=0;
}
}
}
/*
* As soon as we produce 2000 bytes of sound,
* write it to the sound card. Why 2000? I have
* no idea. It's 1 AM and I am dead tired.
*/
if(outputBufferPosition>=2000)
{
rb->write(fd, outputBuffer, 2000);
outputBufferPosition=0;
}
}
}
// unloadFile(mf);
printf("\n");
printf("\n");
#if !defined(LOCAL_DSP)
close_wav(&file_info);
close_wav(&file_info);
#else
rb->close(fd);
rb->close(fd);
#endif
return 0;
return 0;
}