diff options
Diffstat (limited to 'apps/plugins')
| -rw-r--r-- | apps/plugins/SOURCES | 2 | ||||
| -rw-r--r-- | apps/plugins/midi/guspat.c | 14 | ||||
| -rw-r--r-- | apps/plugins/midi/midifile.c | 40 | ||||
| -rw-r--r-- | apps/plugins/midi/midiutil.c | 48 | ||||
| -rw-r--r-- | apps/plugins/midi/sequencer.c | 109 | ||||
| -rw-r--r-- | apps/plugins/midi/synth.c | 83 | ||||
| -rw-r--r-- | apps/plugins/midiplay.c | 217 | ||||
| -rw-r--r-- | apps/plugins/viewers.config | 2 |
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 |