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) 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) 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 * loadWaveform(int file)
{ {
struct GWaveform * wav = (struct GWaveform *)allocate(sizeof(struct GWaveform)); struct GWaveform * wav = (struct GWaveform *)allocate(sizeof(struct GWaveform));
rb->memset(wav, 0, sizeof(struct GWaveform)); rb->memset(wav, 0, sizeof(struct GWaveform));
wav->name=readData(file, 7); wav->name=readData(file, 7);
printf("\nWAVE NAME = [%s]", wav->name); printf("\nWAVE NAME = [%s]", wav->name);
wav->fractions=readChar(file); wav->fractions=readChar(file);
wav->wavSize=readDWord(file); wav->wavSize=readDWord(file);
wav->startLoop=readDWord(file); wav->startLoop=readDWord(file);
wav->endLoop=readDWord(file); wav->endLoop=readDWord(file);
wav->sampRate=readWord(file); wav->sampRate=readWord(file);
wav->lowFreq=readDWord(file); wav->lowFreq=readDWord(file);
wav->highFreq=readDWord(file); wav->highFreq=readDWord(file);
wav->rootFreq=readDWord(file); wav->rootFreq=readDWord(file);
wav->tune=readWord(file); wav->tune=readWord(file);
wav->balance=readChar(file); wav->balance=readChar(file);
wav->envRate=readData(file, 6); wav->envRate=readData(file, 6);
wav->envOffset=readData(file, 6); wav->envOffset=readData(file, 6);
wav->tremSweep=readChar(file); wav->tremSweep=readChar(file);
wav->tremRate==readChar(file); wav->tremRate==readChar(file);
wav->tremDepth=readChar(file); wav->tremDepth=readChar(file);
wav->vibSweep=readChar(file); wav->vibSweep=readChar(file);
wav->vibRate=readChar(file); wav->vibRate=readChar(file);
wav->vibDepth=readChar(file); wav->vibDepth=readChar(file);
wav->mode=readChar(file); wav->mode=readChar(file);
wav->scaleFreq=readWord(file); wav->scaleFreq=readWord(file);
wav->scaleFactor=readWord(file); wav->scaleFactor=readWord(file);
printf("\nScaleFreq = %d ScaleFactor = %d RootFreq = %d", wav->scaleFreq, wav->scaleFactor, wav->rootFreq); printf("\nScaleFreq = %d ScaleFactor = %d RootFreq = %d", wav->scaleFreq, wav->scaleFactor, wav->rootFreq);
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; wav->numSamples = wav->wavSize / 2;
int a=0; wav->startLoop = wav->startLoop >> 1;
wav->endLoop = wav->endLoop >> 1;
unsigned int a=0;
return wav; /* half baked 8 bit conversion UNFINISHED*/
if(wav->mode & 1 == 0) //Whoops, 8 bit /*
{ if(wav->mode & 1 == 0) //Whoops, 8 bit
wav->numSamples = wav->wavSize; {
wav->numSamples = wav->wavSize;
//Allocate a block for the rest of it //Allocate a block for the rest of it
//It should end up right after the previous one. //It should end up right after the previous one.
wav->wavSize = wav->wavSize * 2; wav->wavSize = wav->wavSize * 2;
void * foo = allocate(wav->wavSize); void * foo = allocate(wav->wavSize);
for(a=0; a<1000; a++) for(a=0; a<1000; a++)
printf("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); 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); // int b1=wf->data[s]+((wf->mode & 2) << 6);
// return b1<<8; // 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;
}
}
*/
/* Iriver needs byteswapping.. big endian, go figure. Gus files are little endian */
//If we have a 16 bit waveform #if !defined(SIMULATOR)
/* if(wav->mode & 1 && (wav->mode & 2)) for(a=0; a<wav->numSamples; a++)
{ {
for(a=0; a<wav->wavSize; a+=2) //Convert it to ((unsigned short *) wav->data)[a] = SWAB16(((unsigned short *) wav->data)[a]);
{ }
wav->data[a]=wav->data[a]+(1 << 7); #endif
wav->data[a|1]=wav->data[(a)|1]+(1 << 7);
} /* Convert unsigned to signed by subtracting 32768 */
} if(wav->mode & 2)
*/ {
return wav; 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 selectWaveform(struct GPatch * pat, int midiNote)
{ {
int tabFreq = gustable[midiNote]/100; //Comparison /* We divide by 100 here because everyone's freq formula is slightly different */
int a=0; unsigned int tabFreq = gustable[midiNote]/100; /* Comparison */
for(a=0; a<pat->numWaveforms; a++) unsigned int a=0;
{ for(a=0; a<pat->numWaveforms; a++)
if(pat->waveforms[a]->lowFreq/100 <= tabFreq && {
pat->waveforms[a]->highFreq/100 >= tabFreq) if(pat->waveforms[a]->lowFreq/100 <= tabFreq &&
{ pat->waveforms[a]->highFreq/100 >= tabFreq)
return a; {
} return a;
} }
return 0; }
return 0;
} }
struct GPatch * gusload(char * filename) struct GPatch * gusload(char * filename)
{ {
struct GPatch * gp = (struct GPatch *)allocate(sizeof(struct GPatch)); struct GPatch * gp = (struct GPatch *)allocate(sizeof(struct GPatch));
rb->memset(gp, 0, 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) if(file == -1)
{ {
char message[50]; char message[50];
rb->snprintf(message, 50, "Error opening %s", filename); rb->snprintf(message, 50, "Error opening %s", filename);
rb->splash(HZ*2, true, message); rb->splash(HZ*2, true, message);
return NULL; return NULL;
} }
gp->header=readData(file, 12); gp->header=readData(file, 12);
gp->gravisid=readData(file, 10); gp->gravisid=readData(file, 10);
gp->desc=readData(file, 60); gp->desc=readData(file, 60);
gp->inst=readChar(file); gp->inst=readChar(file);
gp->voc=readChar(file); gp->voc=readChar(file);
gp->chan=readChar(file); gp->chan=readChar(file);
gp->numWaveforms=readWord(file); //readWord(file); gp->numWaveforms=readWord(file);
gp->vol=readWord(file); gp->vol=readWord(file);
gp->datSize=readDWord(file); gp->datSize=readDWord(file);
gp->res=readData(file, 36); gp->res=readData(file, 36);
gp->instrID=readWord(file); gp->instrID=readWord(file);
gp->instrName=readData(file,16); gp->instrName=readData(file,16);
gp->instrSize=readDWord(file); gp->instrSize=readDWord(file);
gp->layers=readChar(file); gp->layers=readChar(file);
gp->instrRes=readData(file,40); gp->instrRes=readData(file,40);
gp->layerDup=readChar(file); gp->layerDup=readChar(file);
gp->layerID=readChar(file); gp->layerID=readChar(file);
gp->layerSize=readDWord(file); gp->layerSize=readDWord(file);
gp->numWaves=readChar(file); gp->numWaves=readChar(file);
gp->layerRes=readData(file,40); 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);
printf("\nPrecomputing note table"); printf("\nFILE: %s", filename);
printf("\nlayerSamples=%d", gp->numWaves);
for(a=0; a<128; a++) int a=0;
{ for(a=0; a<gp->numWaves; a++)
gp->noteTable[a] = selectWaveform(gp, a); gp->waveforms[a] = loadWaveform(file);
}
rb->close(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[]= static const unsigned int gustable[]=
{ {
8175, 8661, 9177, 9722, 10300, 10913, 11562, 12249, 12978, 13750, 14567, 15433, 8175, 8661, 9177, 9722, 10300, 10913, 11562, 12249, 12978, 13750, 14567, 15433,
@ -33,63 +33,63 @@ static const unsigned int gustable[]=
struct GWaveform 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 numSamples;
unsigned int startLoop; unsigned int startLoop;
unsigned int endLoop; unsigned int endLoop;
unsigned int sampRate; unsigned int sampRate;
unsigned int lowFreq; unsigned int lowFreq;
unsigned int highFreq; unsigned int highFreq;
unsigned int rootFreq; unsigned int rootFreq;
unsigned int tune; unsigned int tune;
unsigned int balance; unsigned int balance;
unsigned char * envRate; unsigned char * envRate;
unsigned char * envOffset; unsigned char * envOffset;
unsigned char tremSweep; unsigned char tremSweep;
unsigned char tremRate; unsigned char tremRate;
unsigned char tremDepth; unsigned char tremDepth;
unsigned char vibSweep; unsigned char vibSweep;
unsigned char vibRate; unsigned char vibRate;
unsigned char vibDepth; unsigned char vibDepth;
unsigned char mode; unsigned char mode;
unsigned int scaleFreq; unsigned int scaleFreq;
unsigned int scaleFactor; unsigned int scaleFactor;
unsigned char * res; unsigned char * res;
signed char * data; signed char * data;
}; };
struct GPatch struct GPatch
{ {
unsigned int patchNumber; unsigned int patchNumber;
unsigned char * header; unsigned char * header;
unsigned char * gravisid; unsigned char * gravisid;
unsigned char * desc; unsigned char * desc;
unsigned char inst, voc, chan; unsigned char inst, voc, chan;
unsigned int numWaveforms; unsigned int numWaveforms;
unsigned int datSize; unsigned int datSize;
unsigned int vol; unsigned int vol;
unsigned char * res; unsigned char * res;
unsigned int instrID; unsigned int instrID;
unsigned char * instrName; unsigned char * instrName;
unsigned int instrSize; unsigned int instrSize;
unsigned int layers; unsigned int layers;
unsigned char * instrRes; unsigned char * instrRes;
unsigned char layerDup; unsigned char layerDup;
unsigned char layerID; unsigned char layerID;
unsigned int layerSize; unsigned int layerSize;
unsigned char numWaves; unsigned char numWaves;
unsigned char * layerRes; unsigned char * layerRes;
unsigned char noteTable[128]; unsigned char noteTable[128];
struct GWaveform * waveforms[255]; struct GWaveform * waveforms[255];
}; };

View file

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

View file

@ -20,39 +20,39 @@
#define BYTE unsigned char #define BYTE unsigned char
//Data chunk ID types, returned by readID() //Data chunk ID types, returned by readID()
#define ID_UNKNOWN -1 #define ID_UNKNOWN -1
#define ID_MTHD 1 #define ID_MTHD 1
#define ID_MTRK 2 #define ID_MTRK 2
#define ID_EOF 3 #define ID_EOF 3
//MIDI Commands //MIDI Commands
#define MIDI_NOTE_OFF 128 #define MIDI_NOTE_OFF 128
#define MIDI_NOTE_ON 144 #define MIDI_NOTE_ON 144
#define MIDI_AFTERTOUCH 160 #define MIDI_AFTERTOUCH 160
#define MIDI_CONTROL 176 #define MIDI_CONTROL 176
#define MIDI_PRGM 192 #define MIDI_PRGM 192
#define MIDI_PITCHW 224 #define MIDI_PITCHW 224
//MIDI Controllers //MIDI Controllers
#define CTRL_VOLUME 7 #define CTRL_VOLUME 7
#define CTRL_BALANCE 8 #define CTRL_BALANCE 8
#define CTRL_PANNING 10 #define CTRL_PANNING 10
#define CHANNEL 1 #define CHANNEL 1
//Most of these are deprecated.. rampdown is used, maybe one other one too //Most of these are deprecated.. rampdown is used, maybe one other one too
#define STATE_ATTACK 1 #define STATE_ATTACK 1
#define STATE_DECAY 2 #define STATE_DECAY 2
#define STATE_SUSTAIN 3 #define STATE_SUSTAIN 3
#define STATE_RELEASE 4 #define STATE_RELEASE 4
#define STATE_RAMPDOWN 5 #define STATE_RAMPDOWN 5
//Loop states //Loop states
#define STATE_LOOPING 7 #define STATE_LOOPING 7
#define STATE_NONLOOPING 8 #define STATE_NONLOOPING 8
//Various bits in the GUS mode byte //Various bits in the GUS mode byte
#define LOOP_ENABLED 4 #define LOOP_ENABLED 4
#define LOOP_PINGPONG 8 #define LOOP_PINGPONG 8
#define LOOP_REVERSE 16 #define LOOP_REVERSE 16
@ -63,81 +63,69 @@
extern struct plugin_api * rb; extern struct plugin_api * rb;
int chVol[16] IDATA_ATTR; //Channel volume int chVol[16] IDATA_ATTR; /* Channel volume */
int chPanLeft[16] IDATA_ATTR; //Channel panning int chPanLeft[16] IDATA_ATTR; /* Channel panning */
int chPanRight[16] IDATA_ATTR; int chPanRight[16] IDATA_ATTR;
int chPat[16]; //Channel patch int chPat[16]; /* Channel patch */
int chPW[16]; //Channel pitch wheel, MSB only 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 * gusload(char *);
struct GPatch * patchSet[128]; struct GPatch * patchSet[128];
struct GPatch * drumSet[128]; struct GPatch * drumSet[128];
//char myarray[80] IDATA_ATTR;
struct Event struct Event
{ {
unsigned int delta; unsigned int delta;
unsigned char status, d1, d2; unsigned char status, d1, d2;
unsigned int len; unsigned int len;
unsigned char * evData; unsigned char * evData;
}; };
struct Track struct Track
{ {
unsigned int size; unsigned int size;
unsigned int numEvents; unsigned int numEvents;
unsigned int delta; //For sequencing unsigned int delta; /* For sequencing */
unsigned int pos; //For sequencing unsigned int pos; /* For sequencing */
void * dataBlock; void * dataBlock;
}; };
struct MIDIfile struct MIDIfile
{ {
int Length; int Length;
unsigned short numTracks;
//int Format; //We don't really care what type it is unsigned short div; /* Time division, X ticks per millisecond */
unsigned short numTracks; struct Track * tracks[48];
unsigned short div; //Time division, X ticks per millisecond unsigned char patches[128];
struct Track * tracks[48]; int numPatches;
unsigned char patches[128];
int numPatches;
}; };
/* /*
struct SynthObject struct SynthObject
{ {
// int tmp; struct GWaveform * wf;
struct GWaveform * wf; unsigned int delta;
unsigned int delta; unsigned int decay;
unsigned int decay; unsigned int cp;
unsigned int cp; unsigned char state, loopState, loopDir;
unsigned char state, loopState, loopDir; unsigned char note, vol, ch, isUsed;
unsigned char note, vol, ch, isUsed; int curRate, curOffset, targetOffset;
int curRate, curOffset, targetOffset; unsigned int curPoint;
unsigned int curPoint;
}; };
*/ */
struct SynthObject struct SynthObject
{ {
// int tmp; struct GWaveform * wf;
struct GWaveform * wf; int delta;
int delta; int decay;
int decay; unsigned int cp;
int cp; int state, loopState, loopDir;
int state, loopState, loopDir; int note, vol, ch, isUsed;
int note, vol, ch, isUsed; int curRate, curOffset, targetOffset;
int curRate, curOffset, targetOffset; int curPoint;
int curPoint;
}; };
struct SynthObject voices[MAX_VOICES] IDATA_ATTR; struct SynthObject voices[MAX_VOICES] IDATA_ATTR;
@ -156,91 +144,91 @@ int midimain(void * filename);
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; int remainder = size % 4;
size = size + 4-remainder; size = size + 4-remainder;
if (offset == NULL) if (offset == NULL)
{ {
offset = rb->plugin_get_audio_buffer(&totalSize); offset = rb->plugin_get_audio_buffer(&totalSize);
} }
if (size + 4 > totalSize) if (size + 4 > totalSize)
{ {
return NULL; return NULL;
} }
ret = offset + 4; ret = offset + 4;
*((unsigned int *)offset) = size; *((unsigned int *)offset) = size;
offset += size + 4; offset += size + 4;
totalSize -= size + 4; totalSize -= size + 4;
return ret; return ret;
} }
//Rick's code /* 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;
if (offset == NULL) if (offset == NULL)
{ {
offset = rb->plugin_get_audio_buffer(&totalSize); offset = rb->plugin_get_audio_buffer(&totalSize);
} }
if (size + 4 > totalSize) if (size + 4 > totalSize)
{ {
return NULL; return NULL;
} }
ret = offset + 4; ret = offset + 4;
*((unsigned int *)offset) = size; *((unsigned int *)offset) = size;
offset += size + 4; offset += size + 4;
totalSize -= size + 4; totalSize -= size + 4;
return ret; return ret;
}*/ }*/
void * allocate(int size) void * allocate(int size)
{ {
return alloc(size); return alloc(size);
} }
unsigned char readChar(int file) unsigned char readChar(int file)
{ {
char buf[2]; char buf[2];
rb->read(file, &buf, 1); rb->read(file, &buf, 1);
return buf[0]; return buf[0];
} }
unsigned char * readData(int file, int len) unsigned char * readData(int file, int len)
{ {
unsigned char * dat = allocate(len); unsigned char * dat = allocate(len);
rb->read(file, dat, len); rb->read(file, dat, len);
return dat; return dat;
} }
int eof(int fd) 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); rb->lseek(fd, curPos, SEEK_SET);
return size+1 == rb->lseek(fd, 0, SEEK_CUR); return size+1 == rb->lseek(fd, 0, SEEK_CUR);
} }
void printf(char *fmt, ...) {fmt=fmt; } void printf(char *fmt, ...) {fmt=fmt; }
void exit(int code) 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) void setVol(int ch, int vol)
{ {
printf("\nvolume[%d] %d ==> %d", ch, chVol[ch], vol); printf("\nvolume[%d] %d ==> %d", ch, chVol[ch], vol);
chVol[ch]=vol; chVol[ch]=vol;
} }
void setPan(int ch, int pan) 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; chPanLeft[ch]=128-pan;
chPanRight[ch]=pan; chPanRight[ch]=pan;
} }
void setPatch(int ch, int pat) void setPatch(int ch, int pat)
{ {
chPat[ch]=pat; chPat[ch]=pat;
} }
/* /*
Pitch Bend table, Computed by * Pitch Bend table, Computed by
for i=0:127, fprintf('%d,', round(2^16*2^((i-64)/384))); end * for i=0:127, fprintf('%d,', round(2^16*2^((i-64)/384))); end
(When typed into Matlab) * (When typed into Matlab)
16 bit pitch bend table * 16 bit pitch bend table
*/ */
long pitchTbl[]= long pitchTbl[]=
{ {
58386,58491,58597,58703,58809,58915,59022,59128,59235,59342,59449,59557,59664,59772,59880,59988,60097,60205, 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, 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, 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, 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, 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, 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, 70953,71082,71210,71339,71468,71597,71726,71856,71985,72115,72246,72376,72507,72638,72769,72901,73032,73164,
73297,73429 73297,73429
}; };
void findDelta(struct SynthObject * so, int ch, int note) void findDelta(struct SynthObject * so, int ch, int note)
{ {
struct GWaveform * wf = patchSet[chPat[ch]]->waveforms[patchSet[chPat[ch]]->noteTable[note]]; struct GWaveform * wf = patchSet[chPat[ch]]->waveforms[patchSet[chPat[ch]]->noteTable[note]];
so->wf=wf; so->wf=wf;
so->delta = (((gustable[note]<<10) / wf->rootFreq) * wf->sampRate / SAMPLE_RATE); so->delta = (((gustable[note]<<10) / (wf->rootFreq)) * wf->sampRate / (SAMPLE_RATE));
so->delta = so->delta * pitchTbl[chPW[ch]] >> 16; so->delta = (so->delta * pitchTbl[chPW[ch]])>> 16;
} }
void setPW(int ch, int msb) void setPW(int ch, int msb)
{ {
printf("\npitchw[%d] %d ==> %d", ch, chPW[ch], msb); printf("\npitchw[%d] %d ==> %d", ch, chPW[ch], msb);
chPW[ch] = msb; chPW[ch] = msb;
int a=0; int a=0;
for(a = 0; a<MAX_VOICES; a++) for(a = 0; a<MAX_VOICES; a++)
{ {
if(voices[a].isUsed==1 && voices[a].ch == ch) if(voices[a].isUsed==1 && voices[a].ch == ch)
{ {
findDelta(&voices[a], ch, voices[a].note); findDelta(&voices[a], ch, voices[a].note);
} }
} }
} }
void pressNote(int ch, int note, int vol) void pressNote(int ch, int note, int vol)
{ {
//Silences all channels but one, for easy debugging, for me.
/* /*
if(ch == 0) return; if(ch == 0) return;
// if(ch == 1) return; if(ch == 1) return;
if(ch == 2) return; if(ch == 2) return;
if(ch == 3) return; if(ch == 3) return;
if(ch == 4) return; // if(ch == 4) return;
if(ch == 5) return; if(ch == 5) return;
if(ch == 6) return; if(ch == 6) return;
if(ch == 7) return; if(ch == 7) return;
if(ch == 8) return; if(ch == 8) return;
if(ch == 9) return; if(ch == 9) return;
if(ch == 10) return; if(ch == 10) return;
if(ch == 11) return; if(ch == 11) return;
if(ch == 12) return; if(ch == 12) return;
if(ch == 13) return; if(ch == 13) return;
if(ch == 14) return; if(ch == 14) return;
if(ch == 15) 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) if(voices[a].ch == ch && voices[a].note == note)
break; break;
if(voices[a].isUsed==0) if(voices[a].isUsed==0)
break; break;
} }
if(a==MAX_VOICES-1) if(a==MAX_VOICES-1)
{ {
printf("\nOVERFLOW: Too many voices playing at once. No more left"); printf("\nOVERFLOW: Too many voices playing at once. No more left");
printf("\nVOICE DUMP: "); printf("\nVOICE DUMP: ");
for(a=0; a<48; a++) 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); 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 return; /* None available */
} }
voices[a].ch=ch; voices[a].ch=ch;
voices[a].note=note; voices[a].note=note;
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].decay=255;
voices[a].decay=255;
voices[a].loopState=STATE_NONLOOPING; voices[a].loopState=STATE_NONLOOPING;
voices[a].loopDir = LOOPDIR_FORWARD; voices[a].loopDir = LOOPDIR_FORWARD;
/* /*
OKAY. Gt = Gus Table value * OKAY. Gt = Gus Table value
rf = Root Frequency of wave * rf = Root Frequency of wave
SR = sound sampling rate * SR = sound sampling rate
sr = WAVE 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?");
/* struct GWaveform * wf = drumSet[note]->waveforms[0];
unsigned int gt = gustable[note]; voices[a].wf=wf;
unsigned int rf = wf->rootFreq; voices[a].delta = (((gustable[note]<<10) / wf->rootFreq) * wf->sampRate / SAMPLE_RATE);
unsigned int SR = SAMPLE_RATE; if(wf->mode & 28)
unsigned int sr = wf->sampRate; printf("\nWoah, a drum patch has a loop. Stripping the loop...");
voices[a].delta=((((gt<<10) / rf) * sr / SR)); wf->mode = wf->mode & (255-28);
*/
/* Turn it on */
voices[a].isUsed=1;
setPoint(&voices[a], 0);
if(ch!=9) } else
{ {
findDelta(&voices[a], ch, note); printf("\nWarning: drum %d does not have a patch defined... Ignoring it", 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);
}
}
} }
void releaseNote(int ch, int note) void releaseNote(int ch, int note)
{ {
if(ch==9) // && note != 27 && note != 31 && note != 28) if(ch==9)
return; 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
// voices[a].state = STATE_RAMPDOWN; //Ramp down int a=0;
setPoint(&voices[a], 3); 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) 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) ) if( ((ev->status & 0xF0) == MIDI_CONTROL) && (ev->d1 == CTRL_PANNING))
{ {
setVol((ev->status & 0xF), ev->d2); setPan((ev->status & 0xF), ev->d2);
return; return;
} }
if( ((ev->status & 0xF0) == MIDI_CONTROL) && (ev->d1 == CTRL_PANNING)) if(((ev->status & 0xF0) == MIDI_PITCHW))
{ {
setPan((ev->status & 0xF), ev->d2); setPW((ev->status & 0xF), ev->d2);
return; return;
} }
if(((ev->status & 0xF0) == MIDI_PITCHW)) if(((ev->status & 0xF0) == MIDI_NOTE_ON) && (ev->d2 != 0))
{ {
setPW((ev->status & 0xF), ev->d2); pressNote(ev->status & 0x0F, ev->d1, ev->d2);
return; return;
} }
if(((ev->status & 0xF0) == MIDI_NOTE_ON) && (ev->d2 != 0)) if(((ev->status & 0xF0) == MIDI_NOTE_ON) && (ev->d2 == 0)) /* Release by vol=0 */
{ {
pressNote(ev->status & 0x0F, ev->d1, ev->d2); releaseNote(ev->status & 0x0F, ev->d1);
return; 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) if((ev->status & 0xF0) == MIDI_NOTE_OFF)
{ {
releaseNote(ev->status & 0x0F, ev->d1); releaseNote(ev->status & 0x0F, ev->d1);
return; return;
} }
if((ev->status & 0xF0) == MIDI_PRGM) if((ev->status & 0xF0) == MIDI_PRGM)
{ {
if((ev->status & 0x0F) == 9) if((ev->status & 0x0F) == 9)
printf("\nNOT PATCHING: Someone tried patching Channel 9 onto something?"); printf("\nNOT PATCHING: Someone tried patching Channel 9 onto something?");
else else
setPatch(ev->status & 0x0F, ev->d1); setPatch(ev->status & 0x0F, ev->d1);
} }
} }
@ -259,61 +246,60 @@ void sendEvent(struct Event * ev)
int tick(struct MIDIfile * mf) int tick(struct MIDIfile * mf)
{ {
if(mf==NULL) if(mf==NULL)
return 0; return 0;
int a=0; int a=0;
int tracksAdv=0; int tracksAdv=0;
for(a=0; a<mf->numTracks; a++) for(a=0; a<mf->numTracks; a++)
{ {
struct Track * tr = mf->tracks[a]; struct Track * tr = mf->tracks[a];
if(tr == NULL) if(tr == NULL)
printf("\nNULL TRACK: %d", a); printf("\nNULL TRACK: %d", a);
//BIG DEBUG STATEMENT //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); //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)) if(tr != NULL && (tr->pos < tr->numEvents))
{ {
tr->delta++; tr->delta++;
tracksAdv++; tracksAdv++;
while(getEvent(tr, tr->pos)->delta <= tr->delta) while(getEvent(tr, tr->pos)->delta <= tr->delta)
{ {
// printf("\nDelta = %d", tr->delta); struct Event * e = getEvent(tr, tr->pos);
struct Event * e = getEvent(tr, tr->pos);
if(e->status != 0xFF) if(e->status != 0xFF)
{ {
sendEvent(e); sendEvent(e);
if(((e->status&0xF0) == MIDI_PRGM)) if(((e->status&0xF0) == MIDI_PRGM))
{ {
printf("\nPatch Event, patch[%d] ==> %d", e->status&0xF, e->d1); printf("\nPatch Event, patch[%d] ==> %d", e->status&0xF, e->d1);
} }
} }
else else
{ {
if(e->d1 == 0x51) if(e->d1 == 0x51)
{ {
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; bpm=mf->div*1000000/tempo;
numberOfSamples=SAMPLE_RATE/bpm; numberOfSamples=SAMPLE_RATE/bpm;
} }
} }
tr->delta = 0; tr->delta = 0;
tr->pos++; tr->pos++;
if(tr->pos>=(tr->numEvents-1)) if(tr->pos>=(tr->numEvents-1))
break; break;
} }
} }
} }
if(tracksAdv != 0) if(tracksAdv != 0)
return 1; return 1;
else else
return 0; return 0;
} }

View file

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

View file

@ -20,21 +20,22 @@
#define MAX_VOICES 100 #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) #if defined(SIMULATOR)
//Enable this to write to the soundcard via a /dsv/dsp symlink in / /*Enable this to write to the soundcard via a /dsv/dsp symlink in */
// #define LOCAL_DSP // #define LOCAL_DSP
#endif #endif
#if defined(LOCAL_DSP) #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 <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <linux/soundcard.h> #include <linux/soundcard.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#endif #endif
#include "../../firmware/export/system.h"
#include "../../plugin.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; struct plugin_api * rb;
@ -66,27 +67,28 @@ 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);
rb = api; rb = api;
TEST_PLUGIN_API(api); TEST_PLUGIN_API(api);
(void)parameter; (void)parameter;
rb = api; rb = api;
if(parameter == NULL) if(parameter == NULL)
{ {
rb->splash(HZ*2, true, " Play .MID file "); rb->splash(HZ*2, true, " Play .MID file ");
return PLUGIN_OK; return PLUGIN_OK;
} }
rb->splash(HZ, true, parameter);
if(midimain(parameter) == -1) rb->splash(HZ, true, parameter);
{ if(midimain(parameter) == -1)
return PLUGIN_ERROR; {
} return PLUGIN_ERROR;
rb->splash(HZ*3, true, "FINISHED PLAYING"); }
return PLUGIN_OK; 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; int currentSample IDATA_ATTR;
@ -98,132 +100,133 @@ int outputSampleTwo IDATA_ATTR;
int midimain(void * filename) 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"); 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)
{ {
return -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 * This lets you hear the music through the sound card if you are on Simulator
//your sound device is. * Make a symlink, archos/dsp.raw and make it point to /dev/dsp or whatever
* your sound device is.
*/
#if defined(LOCAL_DSP) #if defined(LOCAL_DSP)
fd=rb->open("/dsp.raw", O_WRONLY); fd=rb->open("/dsp.raw", O_WRONLY);
int arg, status; int arg, status;
int bit, samp, ch; int bit, samp, ch;
arg = 16; // sample size arg = 16; /* sample size */
status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg); status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);
status = ioctl(fd, SOUND_PCM_READ_BITS, &arg); status = ioctl(fd, SOUND_PCM_READ_BITS, &arg);
bit=arg; bit=arg;
arg = 2; //Number of channels, 1=mono arg = 2; /* Number of channels, 1=mono */
status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg); status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg);
status = ioctl(fd, SOUND_PCM_READ_CHANNELS, &arg); status = ioctl(fd, SOUND_PCM_READ_CHANNELS, &arg);
ch=arg; ch=arg;
arg = SAMPLE_RATE; //Yeah. sampling rate arg = SAMPLE_RATE; /* Yeah. sampling rate */
status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg); status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg);
status = ioctl(fd, SOUND_PCM_READ_RATE, &arg); status = ioctl(fd, SOUND_PCM_READ_RATE, &arg);
samp=arg; samp=arg;
#else #else
file_info_struct file_info; file_info_struct file_info;
file_info.samplerate = SAMPLE_RATE; 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;
local_init("/miditest.tmp", "/miditest.wav", &file_info, rb); local_init("/miditest.tmp", "/miditest.wav", &file_info, rb);
fd = file_info.outfile; fd = file_info.outfile;
#endif #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 printf("\nOkay, starting sequencing");
// 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"); currentSample=0; /* Sample counting variable */
outputBufferPosition = 0;
currentSample=0; //Sample counting variable bpm=mf->div*1000000/tempo;
outputBufferPosition = 0; 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 /* Tick() will return 0 if there are no more events left to play */
while(tick(mf)) 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 synthSample(&outputSampleOne, &outputSampleTwo);
//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);
//16-bit audio because, well, it's better /*
// But really because ALSA's OSS emulation sounds extremely * 16-bit audio because, well, it's better
//noisy and distorted when in 8-bit mode. I still do not know * But really because ALSA's OSS emulation sounds extremely
//why this happens. * noisy and distorted when in 8-bit mode. I still do not know
outputBuffer[outputBufferPosition]=outputSampleOne&0XFF; // Low byte first * why this happens.
outputBufferPosition++; */
outputBuffer[outputBufferPosition]=outputSampleOne>>8; //High byte second
outputBufferPosition++;
outputBuffer[outputBufferPosition]=outputSampleTwo&0XFF; // Low byte first outputBuffer[outputBufferPosition]=outputSampleOne&0XFF; // Low byte first
outputBufferPosition++; outputBufferPosition++;
outputBuffer[outputBufferPosition]=outputSampleTwo>>8; //High byte second outputBuffer[outputBufferPosition]=outputSampleOne>>8; //High byte second
outputBufferPosition++; 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 * As soon as we produce 2000 bytes of sound,
//no idea. It's 1 AM and I am dead tired. * write it to the sound card. Why 2000? I have
if(outputBufferPosition>=2000) * no idea. It's 1 AM and I am dead tired.
{ */
rb->write(fd, outputBuffer, 2000); if(outputBufferPosition>=2000)
outputBufferPosition=0; {
} rb->write(fd, outputBuffer, 2000);
} outputBufferPosition=0;
} }
}
}
// unloadFile(mf); printf("\n");
printf("\n");
#if !defined(LOCAL_DSP) #if !defined(LOCAL_DSP)
close_wav(&file_info); close_wav(&file_info);
#else #else
rb->close(fd); rb->close(fd);
#endif #endif
return 0; return 0;
} }