summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/SOURCES2
-rw-r--r--apps/plugins/midi/guspat.c14
-rw-r--r--apps/plugins/midi/midifile.c40
-rw-r--r--apps/plugins/midi/midiutil.c48
-rw-r--r--apps/plugins/midi/sequencer.c109
-rw-r--r--apps/plugins/midi/synth.c83
-rw-r--r--apps/plugins/midiplay.c217
-rw-r--r--apps/plugins/viewers.config2
8 files changed, 400 insertions, 115 deletions
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index 1f64e91..edcbe3e 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -99,7 +99,7 @@ nim.c
#if CONFIG_CODEC == SWCODEC /* software codec platforms */
mp3_encoder.c
-midi2wav.c
+midiplay.c
wav2wv.c
#else /* hardware codec platforms */
#ifndef HAVE_MMC /* not for Ondio, has no remote control pin */
diff --git a/apps/plugins/midi/guspat.c b/apps/plugins/midi/guspat.c
index 6f1866c..4b5e7a6 100644
--- a/apps/plugins/midi/guspat.c
+++ b/apps/plugins/midi/guspat.c
@@ -31,11 +31,11 @@ unsigned int readDWord(int file)
struct GWaveform * loadWaveform(int file)
{
- struct GWaveform * wav = (struct GWaveform *)allocate(sizeof(struct GWaveform));
+ struct GWaveform * wav = (struct GWaveform *)malloc(sizeof(struct GWaveform));
rb->memset(wav, 0, sizeof(struct GWaveform));
wav->name=readData(file, 7);
- printf("\nWAVE NAME = [%s]", wav->name);
+/* printf("\nWAVE NAME = [%s]", wav->name); */
wav->fractions=readChar(file);
wav->wavSize=readDWord(file);
wav->startLoop=readDWord(file);
@@ -62,7 +62,7 @@ struct GWaveform * loadWaveform(int file)
wav->scaleFreq=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->data=readData(file, wav->wavSize);
@@ -137,7 +137,7 @@ int selectWaveform(struct GPatch * pat, int midiNote)
struct GPatch * gusload(char * filename)
{
- struct GPatch * gp = (struct GPatch *)allocate(sizeof(struct GPatch));
+ struct GPatch * gp = (struct GPatch *)malloc(sizeof(struct GPatch));
rb->memset(gp, 0, sizeof(struct GPatch));
int file = rb->open(filename, O_RDONLY);
@@ -175,15 +175,15 @@ struct GPatch * gusload(char * filename)
gp->layerRes=readData(file,40);
- printf("\nFILE: %s", filename);
- printf("\nlayerSamples=%d", gp->numWaves);
+/* 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("\nPrecomputing note table"); */
for(a=0; a<128; a++)
{
diff --git a/apps/plugins/midi/midifile.c b/apps/plugins/midi/midifile.c
index 412cc61..61168f9 100644
--- a/apps/plugins/midi/midifile.c
+++ b/apps/plugins/midi/midifile.c
@@ -26,7 +26,7 @@ void bail(const char *);
struct MIDIfile * loadFile(char * filename)
{
- struct MIDIfile * mf;
+ struct MIDIfile * mfload;
int file = rb->open (filename, O_RDONLY);
if(file==-1)
@@ -34,15 +34,15 @@ struct MIDIfile * loadFile(char * filename)
bail("Could not open file\n");
}
- mf = (struct MIDIfile*)allocate(sizeof(struct MIDIfile));
+ mfload = (struct MIDIfile*)malloc(sizeof(struct MIDIfile));
- if(mf==NULL)
+ if(mfload==NULL)
{
rb->close(file);
bail("Could not allocate memory for MIDIfile struct\n");
}
- rb->memset(mf, 0, sizeof(struct MIDIfile));
+ rb->memset(mfload, 0, sizeof(struct MIDIfile));
if(readID(file) != ID_MTHD)
{
@@ -62,32 +62,32 @@ struct MIDIfile * loadFile(char * filename)
bail("MIDI file type not supported");
}
- mf->numTracks = readTwoBytes(file);
- mf->div = readTwoBytes(file);
+ mfload->numTracks = readTwoBytes(file);
+ mfload->div = readTwoBytes(file);
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", mfload->numTracks, mfload->div);
- while(! eof(file) && track < mf->numTracks)
+ while(! eof(file) && track < mfload->numTracks)
{
unsigned char id = readID(file);
if(id == ID_EOF)
{
- if(mf->numTracks != track)
+ if(mfload->numTracks != track)
{
- printf("\nError: file claims to have %d tracks.\n I only see %d here.\n", mf->numTracks, track);
- mf->numTracks = track;
+ printf("\nError: file claims to have %d tracks.\n I only see %d here.\n", mfload->numTracks, track);
+ mfload->numTracks = track;
}
- return mf;
+ return mfload;
}
if(id == ID_MTRK)
{
- mf->tracks[track] = readTrack(file);
+ mfload->tracks[track] = readTrack(file);
//exit(0);
track++;
} else
@@ -98,16 +98,16 @@ struct MIDIfile * loadFile(char * filename)
readChar(file);
}
}
- return mf;
+ return mfload;
}
-int rStatus = 0;
-
/* Returns 0 if done, 1 if keep going */
int readEvent(int file, void * dest)
{
+
+ static int rStatus = 0;
struct Event dummy;
struct Event * ev = (struct Event *) dest;
@@ -131,7 +131,7 @@ int readEvent(int file, void * dest)
if(dest != NULL)
{
ev->evData = readData(file, ev->len);
- printf("\nDATA: <%s>", ev->evData);
+/* printf("\nDATA: <%s>", ev->evData); */
}
else
{
@@ -173,11 +173,9 @@ int readEvent(int file, void * dest)
return 1;
}
-
-
struct Track * readTrack(int file)
{
- struct Track * trk = (struct Track *)allocate(sizeof(struct Track));
+ struct Track * trk = (struct Track *)malloc(sizeof(struct Track));
rb->memset(trk, 0, sizeof(struct Track));
trk->size = readFourBytes(file);
@@ -194,7 +192,7 @@ struct Track * readTrack(int file)
rb->lseek(file, pos, SEEK_SET);
int trackSize = (numEvents+1) * sizeof(struct Event);
- void * dataPtr = allocate(trackSize);
+ void * dataPtr = malloc(trackSize);
trk->dataBlock = dataPtr;
numEvents=0;
diff --git a/apps/plugins/midi/midiutil.c b/apps/plugins/midi/midiutil.c
index d0b968e..8e27e73 100644
--- a/apps/plugins/midi/midiutil.c
+++ b/apps/plugins/midi/midiutil.c
@@ -63,11 +63,11 @@
extern struct plugin_api * rb;
-int chVol[16] IDATA_ATTR; /* Channel volume */
-int chPanLeft[16] IDATA_ATTR; /* Channel panning */
-int chPanRight[16] IDATA_ATTR;
-int chPat[16]; /* Channel patch */
-int chPW[16]; /* Channel pitch wheel, MSB only */
+int chVol[16] IBSS_ATTR; /* Channel volume */
+int chPanLeft[16] IBSS_ATTR; /* Channel panning */
+int chPanRight[16] IBSS_ATTR;
+int chPat[16] IBSS_ATTR; /* Channel patch */
+int chPW[16] IBSS_ATTR; /* Channel pitch wheel, MSB only */
struct GPatch * gusload(char *);
@@ -128,12 +128,9 @@ struct SynthObject
int curPoint;
};
-struct SynthObject voices[MAX_VOICES] IDATA_ATTR;
-
-
+struct SynthObject voices[MAX_VOICES] IBSS_ATTR;
void sendEvent(struct Event * ev);
-int tick(struct MIDIfile * mf);
inline void setPoint(struct SynthObject * so, int pt);
struct Event * getEvent(struct Track * tr, int evNum);
int readTwoBytes(int file);
@@ -196,8 +193,11 @@ void *alloc(int size)
offset += size + 4;
totalSize -= size + 4;
return ret;
-}*/
-void * allocate(int size)
+}
+*/
+
+#define malloc(n) my_malloc(n)
+void * my_malloc(int size)
{
return alloc(size);
}
@@ -211,7 +211,7 @@ unsigned char readChar(int file)
unsigned char * readData(int file, int len)
{
- unsigned char * dat = allocate(len);
+ unsigned char * dat = malloc(len);
rb->read(file, dat, len);
return dat;
}
@@ -226,7 +226,29 @@ int eof(int fd)
return size+1 == rb->lseek(fd, 0, SEEK_CUR);
}
-void printf(char *fmt, ...) {fmt=fmt; }
+// Here is a hacked up printf command to get the output from the game.
+int printf(const char *fmt, ...)
+{
+ static int p_xtpt;
+ char p_buf[50];
+ bool ok;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ok = rb->vsnprintf(p_buf,sizeof(p_buf), fmt, ap);
+ va_end(ap);
+
+ rb->lcd_putsxy(1,p_xtpt, (unsigned char *)p_buf);
+ rb->lcd_update();
+
+ p_xtpt+=8;
+ if(p_xtpt>LCD_HEIGHT-8)
+ {
+ p_xtpt=0;
+ rb->lcd_clear_display();
+ }
+ return 1;
+}
void exit(int code)
{
diff --git a/apps/plugins/midi/sequencer.c b/apps/plugins/midi/sequencer.c
index 4ae5a9f..3c02627 100644
--- a/apps/plugins/midi/sequencer.c
+++ b/apps/plugins/midi/sequencer.c
@@ -22,22 +22,22 @@ extern struct plugin_api * rb;
long tempo=375000;
-void setVol(int ch, int vol)
+inline 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;
}
-void setPan(int ch, int pan)
+inline 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;
}
-void setPatch(int ch, int pat)
+inline void setPatch(int ch, int pat)
{
chPat[ch]=pat;
}
@@ -52,18 +52,64 @@ void setPatch(int ch, int pat)
/*
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
};
*/
-long pitchTbl[]={
-58386,58412,58439,58465,58491,58518,58544,58571,58597,58624,58650,58676,58703,58729,58756,58782,58809,58836,58862,58889,58915,58942,58968,58995,59022,59048,59075,59102,59128,59155,59182,59208,59235,59262,59289,59315,59342,59369,59396,59423,59449,59476,59503,59530,59557,59584,59611,59638,59664,59691,59718,59745,59772,59799,59826,59853,59880,59907,59934,59961,59988,60015,60043,60070,60097,60124,60151,60178,60205,60233,60260,60287,60314,60341,60369,60396,60423,60450,60478,60505,60532,60560,60587,60614,60642,60669,60696,60724,60751,60779,60806,60833,60861,60888,60916,60943,60971,60998,61026,61054,61081,61109,61136,61164,61191,61219,61247,61274,61302,61330,61357,61385,61413,61440,61468,61496,61524,61551,61579,61607,61635,61663,61690,61718,61746,61774,61802,61830,61858,61886,61914,61942,61970,61997,62025,62053,62081,62109,62138,62166,62194,62222,62250,62278,62306,62334,62362,62390,62419,62447,62475,62503,62531,62560,62588,62616,62644,62673,62701,62729,62757,62786,62814,62843,62871,62899,62928,62956,62984,63013,63041,63070,63098,63127,63155,63184,63212,63241,63269,63298,63326,63355,63384,63412,63441,63470,63498,63527,63555,63584,63613,63642,63670,63699,63728,63757,63785,63814,63843,63872,63901,63929,63958,63987,64016,64045,64074,64103,64132,64161,64190,64219,64248,64277,64306,64335,64364,64393,64422,64451,64480,64509,64538,64567,64596,64626,64655,64684,64713,64742,64772,64801,64830,64859,64889,64918,64947,64976,65006,65035,65065,65094,65123,65153,65182,65211,65241,65270,65300,65329,65359,65388,65418,65447,65477,65506,65536,65566,65595,65625,65654,65684,65714,65743,65773,65803,65832,65862,65892,65922,65951,65981,66011,66041,66071,66100,66130,66160,66190,66220,66250,66280,66309,66339,66369,66399,66429,66459,66489,66519,66549,66579,66609,66639,66670,66700,66730,66760,66790,66820,66850,66880,66911,66941,66971,67001,67032,67062,67092,67122,67153,67183,67213,67244,67274,67304,67335,67365,67395,67426,67456,67487,67517,67548,67578,67609,67639,67670,67700,67731,67761,67792,67823,67853,67884,67915,67945,67976,68007,68037,68068,68099,68129,68160,68191,68222,68252,68283,68314,68345,68376,68407,68438,68468,68499,68530,68561,68592,68623,68654,68685,68716,68747,68778,68809,68840,68871,68902,68933,68965,68996,69027,69058,69089,69120,69152,69183,69214,69245,69276,69308,69339,69370,69402,69433,69464,69496,69527,69558,69590,69621,69653,69684,69716,69747,69778,69810,69841,69873,69905,69936,69968,69999,70031,70062,70094,70126,70157,70189,70221,70252,70284,70316,70348,70379,70411,70443,70475,70507,70538,70570,70602,70634,70666,70698,70730,70762,70793,70825,70857,70889,70921,70953,70985,71017,71049,71082,71114,71146,71178,71210,71242,71274,71306,71339,71371,71403,71435,71468,71500,71532,71564,71597,71629,71661,71694,71726,71758,71791,71823,71856,71888,71920,71953,71985,72018,72050,72083,72115,72148,72181,72213,72246,72278,72311,72344,72376,72409,72442,72474,72507,72540,72573,72605,72638,72671,72704,72736,72769,72802,72835,72868,72901,72934,72967,72999,73032,73065,73098,73131,73164,73197,73230,73264,73297,73330,73363,73396,73429,73462,73495,73528
+
+long pitchTbl[] ICONST_ATTR={
+ 58386,58412,58439,58465,58491,58518,58544,58571,58597,58624,58650,58676,
+ 58703,58729,58756,58782,58809,58836,58862,58889,58915,58942,58968,58995,
+ 59022,59048,59075,59102,59128,59155,59182,59208,59235,59262,59289,59315,
+ 59342,59369,59396,59423,59449,59476,59503,59530,59557,59584,59611,59638,
+ 59664,59691,59718,59745,59772,59799,59826,59853,59880,59907,59934,59961,
+ 59988,60015,60043,60070,60097,60124,60151,60178,60205,60233,60260,60287,
+ 60314,60341,60369,60396,60423,60450,60478,60505,60532,60560,60587,60614,
+ 60642,60669,60696,60724,60751,60779,60806,60833,60861,60888,60916,60943,
+ 60971,60998,61026,61054,61081,61109,61136,61164,61191,61219,61247,61274,
+ 61302,61330,61357,61385,61413,61440,61468,61496,61524,61551,61579,61607,
+ 61635,61663,61690,61718,61746,61774,61802,61830,61858,61886,61914,61942,
+ 61970,61997,62025,62053,62081,62109,62138,62166,62194,62222,62250,62278,
+ 62306,62334,62362,62390,62419,62447,62475,62503,62531,62560,62588,62616,
+ 62644,62673,62701,62729,62757,62786,62814,62843,62871,62899,62928,62956,
+ 62984,63013,63041,63070,63098,63127,63155,63184,63212,63241,63269,63298,
+ 63326,63355,63384,63412,63441,63470,63498,63527,63555,63584,63613,63642,
+ 63670,63699,63728,63757,63785,63814,63843,63872,63901,63929,63958,63987,
+ 64016,64045,64074,64103,64132,64161,64190,64219,64248,64277,64306,64335,
+ 64364,64393,64422,64451,64480,64509,64538,64567,64596,64626,64655,64684,
+ 64713,64742,64772,64801,64830,64859,64889,64918,64947,64976,65006,65035,
+ 65065,65094,65123,65153,65182,65211,65241,65270,65300,65329,65359,65388,
+ 65418,65447,65477,65506,65536,65566,65595,65625,65654,65684,65714,65743,
+ 65773,65803,65832,65862,65892,65922,65951,65981,66011,66041,66071,66100,
+ 66130,66160,66190,66220,66250,66280,66309,66339,66369,66399,66429,66459,
+ 66489,66519,66549,66579,66609,66639,66670,66700,66730,66760,66790,66820,
+ 66850,66880,66911,66941,66971,67001,67032,67062,67092,67122,67153,67183,
+ 67213,67244,67274,67304,67335,67365,67395,67426,67456,67487,67517,67548,
+ 67578,67609,67639,67670,67700,67731,67761,67792,67823,67853,67884,67915,
+ 67945,67976,68007,68037,68068,68099,68129,68160,68191,68222,68252,68283,
+ 68314,68345,68376,68407,68438,68468,68499,68530,68561,68592,68623,68654,
+ 68685,68716,68747,68778,68809,68840,68871,68902,68933,68965,68996,69027,
+ 69058,69089,69120,69152,69183,69214,69245,69276,69308,69339,69370,69402,
+ 69433,69464,69496,69527,69558,69590,69621,69653,69684,69716,69747,69778,
+ 69810,69841,69873,69905,69936,69968,69999,70031,70062,70094,70126,70157,
+ 70189,70221,70252,70284,70316,70348,70379,70411,70443,70475,70507,70538,
+ 70570,70602,70634,70666,70698,70730,70762,70793,70825,70857,70889,70921,
+ 70953,70985,71017,71049,71082,71114,71146,71178,71210,71242,71274,71306,
+ 71339,71371,71403,71435,71468,71500,71532,71564,71597,71629,71661,71694,
+ 71726,71758,71791,71823,71856,71888,71920,71953,71985,72018,72050,72083,
+ 72115,72148,72181,72213,72246,72278,72311,72344,72376,72409,72442,72474,
+ 72507,72540,72573,72605,72638,72671,72704,72736,72769,72802,72835,72868,
+ 72901,72934,72967,72999,73032,73065,73098,73131,73164,73197,73230,73264,
+ 73297,73330,73363,73396,73429,73462,73495,73528
};
void findDelta(struct SynthObject * so, int ch, int note)
@@ -75,9 +121,9 @@ void findDelta(struct SynthObject * so, int ch, int note)
so->delta = (so->delta * pitchTbl[chPW[ch]])>> 16;
}
-void setPW(int ch, int msb, int lsb)
+inline void setPW(int ch, int msb, int lsb)
{
- printf("\npitchw[%d] %d ==> %d", ch, chPW[ch], msb);
+// printf("\npitchw[%d] %d ==> %d", ch, chPW[ch], msb);
chPW[ch] = msb<<2|lsb>>5;
int a=0;
@@ -92,7 +138,7 @@ void setPW(int ch, int msb, int lsb)
void pressNote(int ch, int note, int vol)
{
-
+ static int lastKill = 0;
//Silences all channels but one, for easy debugging, for me.
/*
if(ch == 0) return;
@@ -123,11 +169,16 @@ void pressNote(int ch, int note, int vol)
}
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 */
+// printf("\nVoice kill");
+// printf("\nToo 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);
+ lastKill++;
+ if(lastKill == MAX_VOICES)
+ lastKill = 0;
+ a = lastKill;
+// return; /* None available */
}
voices[a].ch=ch;
voices[a].note=note;
@@ -163,7 +214,7 @@ void pressNote(int ch, int note, int vol)
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...");
+// printf("\nWoah, a drum patch has a loop. Stripping the loop...");
wf->mode = wf->mode & (255-28);
/* Turn it on */
@@ -172,7 +223,7 @@ void pressNote(int ch, int note, int vol)
} else
{
- printf("\nWarning: drum %d does not have a patch defined... Ignoring it", note);
+/* printf("\nWarning: drum %d does not have a patch defined... Ignoring it", note); */
}
}
}
@@ -244,11 +295,7 @@ void sendEvent(struct Event * ev)
}
}
-
-
-
-
-int tick(struct MIDIfile * mf)
+int tick(void)
{
if(mf==NULL)
return 0;
@@ -280,7 +327,7 @@ int tick(struct MIDIfile * mf)
sendEvent(e);
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
diff --git a/apps/plugins/midi/synth.c b/apps/plugins/midi/synth.c
index 42ca9dd..44417b2 100644
--- a/apps/plugins/midi/synth.c
+++ b/apps/plugins/midi/synth.c
@@ -104,8 +104,9 @@ int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig)
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);
+*/
patchUsed[getEvent(mf->tracks[a], ts)->d1]=1;
}
}
@@ -124,13 +125,14 @@ int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig)
/* Scan our config file and load the right patches as needed */
int c = 0;
rb->snprintf(name, 40, "");
+ printf("\nLoading instruments");
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);
+/* printf("\nLOADING: <%s> ", fn); */
if(patchUsed[a]==1)
{
@@ -155,6 +157,7 @@ int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig)
/* Scan our config file and load the drum data */
int idx=0;
char number[30];
+ printf("\nLoading drums");
while(!eof(file))
{
readTextBlock(file, number);
@@ -168,7 +171,6 @@ int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig)
if(drumUsed[idx]==1)
{
drumSet[idx]=gusload(fn);
-
if(drumSet[idx] == NULL) /* Error loading patch */
return -1;
}
@@ -180,32 +182,14 @@ int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig)
return 0;
}
-
-
-int currentVoice IDATA_ATTR;
-struct SynthObject * so IDATA_ATTR;
-struct GWaveform * wf IDATA_ATTR;
-int s IDATA_ATTR;
-short s1 IDATA_ATTR;
-short s2 IDATA_ATTR;
-short sample IDATA_ATTR; /* For synthSample */
-unsigned int cpShifted IDATA_ATTR;
-
-unsigned char b1 IDATA_ATTR;
-unsigned char b2 IDATA_ATTR;
-
-
-inline int getSample(int s)
+inline short getSample(int s,struct GWaveform * wf )
{
/* Sign conversion moved to guspat.c */
/* 8bit conversion NOT YET IMPLEMENTED in guspat.c */
return ((short *) wf->data)[s];
}
-
-
-
-inline void setPoint(struct SynthObject * so, int pt)
+void setPoint(struct SynthObject * so, int pt)
{
if(so->ch==9) /* Drums, no ADSR */
{
@@ -227,7 +211,7 @@ inline void setPoint(struct SynthObject * so, int pt)
so->curPoint = pt;
- int r=0;
+ int r;
int rate = so->wf->envRate[pt];
r=3-((rate>>6) & 0x3); /* Some blatant Timidity code for rate conversion... */
@@ -243,15 +227,17 @@ inline void setPoint(struct SynthObject * so, int pt)
* default this to 10, and maybe later have an option to set it to 9
* for longer decays.
*/
- so->curRate = r<<10;
+ so->curRate = r<<11;
/*
* 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.
+ *
+ * Or just move the 1 up one line to optimize a tiny bit.
*/
- so->curRate = so->curRate << 1;
+/* so->curRate = so->curRate << 1;*/
so->targetOffset = so->wf->envOffset[pt]<<(20);
@@ -270,9 +256,14 @@ inline void stopVoice(struct SynthObject * so)
}
-inline signed short int synthVoice(void)
+signed short int synthVoice(struct SynthObject * so)
{
- so = &voices[currentVoice];
+ struct GWaveform * wf;
+ register int s;
+ register unsigned int cpShifted;
+ register short s1;
+ register short s2;
+
wf = so->wf;
@@ -288,7 +279,7 @@ inline signed short int synthVoice(void)
stopVoice(so);
}
- s2 = getSample((cpShifted)+1);
+ s2 = getSample((cpShifted)+1, wf);
/* LOOP_REVERSE|LOOP_PINGPONG = 24 */
if((wf->mode & (24)) && so->loopState == STATE_LOOPING && (cpShifted <= (wf->startLoop)))
@@ -297,8 +288,9 @@ inline signed short int synthVoice(void)
{
so->cp = (wf->endLoop)<<10; //Was 10
cpShifted = wf->endLoop;
- s2=getSample((cpShifted));
- } else
+ s2=getSample((cpShifted), wf);
+ }
+ else
{
so->delta = -so->delta;
so->loopDir = LOOPDIR_FORWARD;
@@ -312,8 +304,9 @@ inline signed short int synthVoice(void)
{
so->cp = (wf->startLoop)<<10; //Was 10
cpShifted = wf->startLoop;
- s2=getSample((cpShifted));
- } else
+ s2=getSample((cpShifted), wf);
+ }
+ else
{
so->delta = -so->delta;
so->loopDir = LOOPDIR_REVERSE;
@@ -321,7 +314,7 @@ inline signed short int synthVoice(void)
}
/* Better, working, linear interpolation */
- s1=getSample((cpShifted)); //\|/ Was 1023)) >> 10
+ s1=getSample((cpShifted), wf); //\|/ Was 1023)) >> 10
s = s1 + ((signed)((s2 - s1) * (so->cp & 1023))>>10); //Was 10
@@ -381,18 +374,26 @@ inline signed short int synthVoice(void)
inline void synthSample(int * mixL, int * mixR)
{
- *mixL = 0;
- *mixR = 0;
- for(currentVoice=0; currentVoice<MAX_VOICES; currentVoice++)
+ register int dL=0;
+ register int dR=0;
+ register short sample=0;
+ register struct SynthObject *voicept=voices;
+ struct SynthObject *lastvoice=&voices[MAX_VOICES];
+
+ while(voicept!=lastvoice)
{
- if(voices[currentVoice].isUsed==1)
+ if(voicept->isUsed==1)
{
- sample = synthVoice();
- *mixL += (sample*chPanLeft[voices[currentVoice].ch])>>7;
- *mixR += (sample*chPanRight[voices[currentVoice].ch])>>7;
+ sample = synthVoice(voicept);
+ dL += (sample*chPanLeft[voicept->ch])>>7;
+ dR += (sample*chPanRight[voicept->ch])>>7;
}
+ voicept++;
}
+ *mixL=dL;
+ *mixR=dR;
+
/* TODO: Automatic Gain Control, anyone? */
/* Or, should this be implemented on the DSP's output volume instead? */
diff --git a/apps/plugins/midiplay.c b/apps/plugins/midiplay.c
new file mode 100644
index 0000000..f279e72
--- /dev/null
+++ b/apps/plugins/midiplay.c
@@ -0,0 +1,217 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * Copyright (C) 2005 Karl Kurbjun based on midi2wav by Stepan Moskovchenko
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "../../plugin.h"
+
+PLUGIN_HEADER
+
+#define SAMPLE_RATE 22050 // 44100 22050 11025
+#define MAX_VOICES 12 // Note: 24 midi channels is the minimum general midi
+ // spec implementation
+#define BUF_SIZE 512
+#define NBUF 2
+
+#undef SYNC
+struct MIDIfile * mf IBSS_ATTR;
+
+int numberOfSamples IBSS_ATTR;
+long bpm IBSS_ATTR;
+
+#include "midi/midiutil.c"
+#include "midi/guspat.h"
+#include "midi/guspat.c"
+#include "midi/sequencer.c"
+#include "midi/midifile.c"
+#include "midi/synth.c"
+
+short gmbuf[BUF_SIZE*NBUF] IBSS_ATTR;
+
+int quit=0;
+struct plugin_api * rb;
+
+#ifdef USE_IRAM
+extern char iramcopy[];
+extern char iramstart[];
+extern char iramend[];
+extern char iedata[];
+extern char iend[];
+#endif
+
+enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
+{
+ rb = api;
+
+ if(parameter == NULL)
+ {
+ rb->splash(HZ*2, true, " Play .MID file ");
+ return PLUGIN_OK;
+ }
+ rb->lcd_setfont(0);
+
+#ifdef USE_IRAM
+ rb->memcpy(iramstart, iramcopy, iramend-iramstart);
+ rb->memset(iedata, 0, iend - iedata);
+#endif
+
+#if !defined(SIMULATOR) && defined(HAVE_ADJUSTABLE_CPU_FREQ)
+ rb->cpu_boost(true);
+#endif
+
+ printf("\n%s", parameter);
+/* rb->splash(HZ, true, parameter); */
+
+#ifdef RB_PROFILE
+ rb->profile_thread();
+#endif
+
+ if(midimain(parameter) == -1)
+ return PLUGIN_ERROR;
+
+#ifdef RB_PROFILE
+ rb->profstop();
+#endif
+
+#ifndef SIMULATOR
+ rb->pcm_play_stop();
+ rb->pcm_set_frequency(44100); // 44100
+#endif
+
+#if !defined(SIMULATOR) && defined(HAVE_ADJUSTABLE_CPU_FREQ)
+ rb->cpu_boost(false);
+#endif
+
+ rb->splash(HZ, true, "FINISHED PLAYING");
+
+ return PLUGIN_OK;
+}
+
+bool swap=0;
+bool lastswap=1;
+
+inline void synthbuf(void)
+{
+ short *outptr;
+ register int i;
+ static int currentSample=0;
+ int synthtemp[2];
+
+#ifndef SYNC
+ if(lastswap==swap) return;
+ lastswap=swap;
+
+ outptr=(swap ? gmbuf : gmbuf+BUF_SIZE);
+#else
+ outptr=gmbuf;
+#endif
+
+ for(i=0; i<BUF_SIZE/2; i++)
+ {
+ synthSample(&synthtemp[0], &synthtemp[1]);
+ currentSample++;
+ *outptr=synthtemp[0]&0xFFFF;
+ outptr++;
+ *outptr=synthtemp[1]&0xFFFF;
+ outptr++;
+ if(currentSample==numberOfSamples)
+ {
+ if( tick() == 0 ) quit=1;
+ currentSample=0;
+ }
+ }
+}
+
+void get_more(unsigned char** start, size_t* size)
+{
+#ifndef SYNC
+ if(lastswap!=swap)
+ {
+ printf("Buffer miss!"); // Comment out the printf to make missses less noticable.
+/*
+ int a=0;
+ for(a=0; a<MAX_VOICES; a++)
+ {
+ voices[a].isUsed=0;
+ }
+*/
+ }
+
+#else
+ synthbuf(); // For some reason midiplayer crashes when an update is forced
+#endif
+
+ *size = BUF_SIZE*sizeof(short);
+#ifndef SYNC
+ *start = (unsigned char*)((swap ? gmbuf : gmbuf + BUF_SIZE));
+ swap=!swap;
+#else
+ *start = (unsigned char*)(gmbuf);
+#endif
+}
+
+int midimain(void * filename)
+{
+ int button;
+
+/* rb->splash(HZ/5, true, "LOADING MIDI"); */
+ printf("\nLoading file");
+ mf= loadFile(filename);
+
+/* rb->splash(HZ/5, true, "LOADING PATCHES"); */
+ if (initSynth(mf, "/.rockbox/patchset/patchset.cfg", "/.rockbox/patchset/drums.cfg") == -1)
+ return -1;
+
+#ifndef SIMULATOR
+ rb->pcm_play_stop();
+ rb->pcm_set_frequency(SAMPLE_RATE); // 44100 22050 11025
+#endif
+
+ /*
+ * 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");
+
+ bpm=mf->div*1000000/tempo;
+ numberOfSamples=SAMPLE_RATE/bpm;
+
+ tick();
+
+ synthbuf();
+#ifndef SIMULATOR
+ rb->pcm_play_data(&get_more, NULL, 0);
+#endif
+
+ button=rb->button_status();
+
+ while(!quit)
+ {
+#ifndef SYNC
+ synthbuf();
+#endif
+ rb->yield();
+ if(rb->button_status()!=button) quit=1;
+ }
+
+ return 0;
+}
diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config
index 6de2bd8..afab022 100644
--- a/apps/plugins/viewers.config
+++ b/apps/plugins/viewers.config
@@ -11,7 +11,7 @@ txt,viewers/sort, 00 00 00 00 00 00
gb,viewers/rockboy, 0C 2A 59 7A 2E 0C
gbc,viewers/rockboy, 0C 2A 59 7A 2E 0C
m3u,viewers/iriverify,00 00 00 00 00 00
-mid,viewers/midi2wav, 20 70 70 3F 00 00
+mid,viewers/midiplay, 20 70 70 3F 00 00
rsp,viewers/searchengine, 0e 11 11 31 7e 60
ss,rocks/sudoku, 55 55 55 55 55 55
wav,viewers/wav2wv, 00 00 00 00 00 00