summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 1f64e9140b..edcbe3e53b 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -99,7 +99,7 @@ nim.c
99 99
100#if CONFIG_CODEC == SWCODEC /* software codec platforms */ 100#if CONFIG_CODEC == SWCODEC /* software codec platforms */
101mp3_encoder.c 101mp3_encoder.c
102midi2wav.c 102midiplay.c
103wav2wv.c 103wav2wv.c
104#else /* hardware codec platforms */ 104#else /* hardware codec platforms */
105#ifndef HAVE_MMC /* not for Ondio, has no remote control pin */ 105#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 6f1866cd58..4b5e7a6a28 100644
--- a/apps/plugins/midi/guspat.c
+++ b/apps/plugins/midi/guspat.c
@@ -31,11 +31,11 @@ unsigned int readDWord(int file)
31 31
32struct GWaveform * loadWaveform(int file) 32struct GWaveform * loadWaveform(int file)
33{ 33{
34 struct GWaveform * wav = (struct GWaveform *)allocate(sizeof(struct GWaveform)); 34 struct GWaveform * wav = (struct GWaveform *)malloc(sizeof(struct GWaveform));
35 rb->memset(wav, 0, sizeof(struct GWaveform)); 35 rb->memset(wav, 0, sizeof(struct GWaveform));
36 36
37 wav->name=readData(file, 7); 37 wav->name=readData(file, 7);
38 printf("\nWAVE NAME = [%s]", wav->name); 38/* printf("\nWAVE NAME = [%s]", wav->name); */
39 wav->fractions=readChar(file); 39 wav->fractions=readChar(file);
40 wav->wavSize=readDWord(file); 40 wav->wavSize=readDWord(file);
41 wav->startLoop=readDWord(file); 41 wav->startLoop=readDWord(file);
@@ -62,7 +62,7 @@ struct GWaveform * loadWaveform(int file)
62 62
63 wav->scaleFreq=readWord(file); 63 wav->scaleFreq=readWord(file);
64 wav->scaleFactor=readWord(file); 64 wav->scaleFactor=readWord(file);
65 printf("\nScaleFreq = %d ScaleFactor = %d RootFreq = %d", wav->scaleFreq, wav->scaleFactor, wav->rootFreq); 65/* printf("\nScaleFreq = %d ScaleFactor = %d RootFreq = %d", wav->scaleFreq, wav->scaleFactor, wav->rootFreq); */
66 wav->res=readData(file, 36); 66 wav->res=readData(file, 36);
67 wav->data=readData(file, wav->wavSize); 67 wav->data=readData(file, wav->wavSize);
68 68
@@ -137,7 +137,7 @@ int selectWaveform(struct GPatch * pat, int midiNote)
137 137
138struct GPatch * gusload(char * filename) 138struct GPatch * gusload(char * filename)
139{ 139{
140 struct GPatch * gp = (struct GPatch *)allocate(sizeof(struct GPatch)); 140 struct GPatch * gp = (struct GPatch *)malloc(sizeof(struct GPatch));
141 rb->memset(gp, 0, sizeof(struct GPatch)); 141 rb->memset(gp, 0, sizeof(struct GPatch));
142 142
143 int file = rb->open(filename, O_RDONLY); 143 int file = rb->open(filename, O_RDONLY);
@@ -175,15 +175,15 @@ struct GPatch * gusload(char * filename)
175 gp->layerRes=readData(file,40); 175 gp->layerRes=readData(file,40);
176 176
177 177
178 printf("\nFILE: %s", filename); 178/* printf("\nFILE: %s", filename); */
179 printf("\nlayerSamples=%d", gp->numWaves); 179/* printf("\nlayerSamples=%d", gp->numWaves); */
180 180
181 int a=0; 181 int a=0;
182 for(a=0; a<gp->numWaves; a++) 182 for(a=0; a<gp->numWaves; a++)
183 gp->waveforms[a] = loadWaveform(file); 183 gp->waveforms[a] = loadWaveform(file);
184 184
185 185
186 printf("\nPrecomputing note table"); 186/* printf("\nPrecomputing note table"); */
187 187
188 for(a=0; a<128; a++) 188 for(a=0; a<128; a++)
189 { 189 {
diff --git a/apps/plugins/midi/midifile.c b/apps/plugins/midi/midifile.c
index 412cc6104d..61168f9d39 100644
--- a/apps/plugins/midi/midifile.c
+++ b/apps/plugins/midi/midifile.c
@@ -26,7 +26,7 @@ void bail(const char *);
26 26
27struct MIDIfile * loadFile(char * filename) 27struct MIDIfile * loadFile(char * filename)
28{ 28{
29 struct MIDIfile * mf; 29 struct MIDIfile * mfload;
30 int file = rb->open (filename, O_RDONLY); 30 int file = rb->open (filename, O_RDONLY);
31 31
32 if(file==-1) 32 if(file==-1)
@@ -34,15 +34,15 @@ struct MIDIfile * loadFile(char * filename)
34 bail("Could not open file\n"); 34 bail("Could not open file\n");
35 } 35 }
36 36
37 mf = (struct MIDIfile*)allocate(sizeof(struct MIDIfile)); 37 mfload = (struct MIDIfile*)malloc(sizeof(struct MIDIfile));
38 38
39 if(mf==NULL) 39 if(mfload==NULL)
40 { 40 {
41 rb->close(file); 41 rb->close(file);
42 bail("Could not allocate memory for MIDIfile struct\n"); 42 bail("Could not allocate memory for MIDIfile struct\n");
43 } 43 }
44 44
45 rb->memset(mf, 0, sizeof(struct MIDIfile)); 45 rb->memset(mfload, 0, sizeof(struct MIDIfile));
46 46
47 if(readID(file) != ID_MTHD) 47 if(readID(file) != ID_MTHD)
48 { 48 {
@@ -62,32 +62,32 @@ struct MIDIfile * loadFile(char * filename)
62 bail("MIDI file type not supported"); 62 bail("MIDI file type not supported");
63 } 63 }
64 64
65 mf->numTracks = readTwoBytes(file); 65 mfload->numTracks = readTwoBytes(file);
66 mf->div = readTwoBytes(file); 66 mfload->div = readTwoBytes(file);
67 67
68 int track=0; 68 int track=0;
69 69
70 printf("\nnumTracks=%d div=%d\nBegin reading track data\n", mf->numTracks, mf->div); 70 printf("\nnumTracks=%d div=%d\nBegin reading track data\n", mfload->numTracks, mfload->div);
71 71
72 72
73 while(! eof(file) && track < mf->numTracks) 73 while(! eof(file) && track < mfload->numTracks)
74 { 74 {
75 unsigned char id = readID(file); 75 unsigned char id = readID(file);
76 76
77 77
78 if(id == ID_EOF) 78 if(id == ID_EOF)
79 { 79 {
80 if(mf->numTracks != track) 80 if(mfload->numTracks != track)
81 { 81 {
82 printf("\nError: file claims to have %d tracks.\n I only see %d here.\n", mf->numTracks, track); 82 printf("\nError: file claims to have %d tracks.\n I only see %d here.\n", mfload->numTracks, track);
83 mf->numTracks = track; 83 mfload->numTracks = track;
84 } 84 }
85 return mf; 85 return mfload;
86 } 86 }
87 87
88 if(id == ID_MTRK) 88 if(id == ID_MTRK)
89 { 89 {
90 mf->tracks[track] = readTrack(file); 90 mfload->tracks[track] = readTrack(file);
91 //exit(0); 91 //exit(0);
92 track++; 92 track++;
93 } else 93 } else
@@ -98,16 +98,16 @@ struct MIDIfile * loadFile(char * filename)
98 readChar(file); 98 readChar(file);
99 } 99 }
100 } 100 }
101 return mf; 101 return mfload;
102 102
103} 103}
104 104
105 105
106int rStatus = 0;
107
108/* Returns 0 if done, 1 if keep going */ 106/* Returns 0 if done, 1 if keep going */
109int readEvent(int file, void * dest) 107int readEvent(int file, void * dest)
110{ 108{
109
110 static int rStatus = 0;
111 struct Event dummy; 111 struct Event dummy;
112 struct Event * ev = (struct Event *) dest; 112 struct Event * ev = (struct Event *) dest;
113 113
@@ -131,7 +131,7 @@ int readEvent(int file, void * dest)
131 if(dest != NULL) 131 if(dest != NULL)
132 { 132 {
133 ev->evData = readData(file, ev->len); 133 ev->evData = readData(file, ev->len);
134 printf("\nDATA: <%s>", ev->evData); 134/* printf("\nDATA: <%s>", ev->evData); */
135 } 135 }
136 else 136 else
137 { 137 {
@@ -173,11 +173,9 @@ int readEvent(int file, void * dest)
173 return 1; 173 return 1;
174} 174}
175 175
176
177
178struct Track * readTrack(int file) 176struct Track * readTrack(int file)
179{ 177{
180 struct Track * trk = (struct Track *)allocate(sizeof(struct Track)); 178 struct Track * trk = (struct Track *)malloc(sizeof(struct Track));
181 rb->memset(trk, 0, sizeof(struct Track)); 179 rb->memset(trk, 0, sizeof(struct Track));
182 180
183 trk->size = readFourBytes(file); 181 trk->size = readFourBytes(file);
@@ -194,7 +192,7 @@ struct Track * readTrack(int file)
194 rb->lseek(file, pos, SEEK_SET); 192 rb->lseek(file, pos, SEEK_SET);
195 193
196 int trackSize = (numEvents+1) * sizeof(struct Event); 194 int trackSize = (numEvents+1) * sizeof(struct Event);
197 void * dataPtr = allocate(trackSize); 195 void * dataPtr = malloc(trackSize);
198 trk->dataBlock = dataPtr; 196 trk->dataBlock = dataPtr;
199 197
200 numEvents=0; 198 numEvents=0;
diff --git a/apps/plugins/midi/midiutil.c b/apps/plugins/midi/midiutil.c
index d0b968e52c..8e27e739e7 100644
--- a/apps/plugins/midi/midiutil.c
+++ b/apps/plugins/midi/midiutil.c
@@ -63,11 +63,11 @@
63extern struct plugin_api * rb; 63extern struct plugin_api * rb;
64 64
65 65
66int chVol[16] IDATA_ATTR; /* Channel volume */ 66int chVol[16] IBSS_ATTR; /* Channel volume */
67int chPanLeft[16] IDATA_ATTR; /* Channel panning */ 67int chPanLeft[16] IBSS_ATTR; /* Channel panning */
68int chPanRight[16] IDATA_ATTR; 68int chPanRight[16] IBSS_ATTR;
69int chPat[16]; /* Channel patch */ 69int chPat[16] IBSS_ATTR; /* Channel patch */
70int chPW[16]; /* Channel pitch wheel, MSB only */ 70int chPW[16] IBSS_ATTR; /* Channel pitch wheel, MSB only */
71 71
72 72
73struct GPatch * gusload(char *); 73struct GPatch * gusload(char *);
@@ -128,12 +128,9 @@ struct SynthObject
128 int curPoint; 128 int curPoint;
129}; 129};
130 130
131struct SynthObject voices[MAX_VOICES] IDATA_ATTR; 131struct SynthObject voices[MAX_VOICES] IBSS_ATTR;
132
133
134 132
135void sendEvent(struct Event * ev); 133void sendEvent(struct Event * ev);
136int tick(struct MIDIfile * mf);
137inline void setPoint(struct SynthObject * so, int pt); 134inline void setPoint(struct SynthObject * so, int pt);
138struct Event * getEvent(struct Track * tr, int evNum); 135struct Event * getEvent(struct Track * tr, int evNum);
139int readTwoBytes(int file); 136int readTwoBytes(int file);
@@ -196,8 +193,11 @@ void *alloc(int size)
196 offset += size + 4; 193 offset += size + 4;
197 totalSize -= size + 4; 194 totalSize -= size + 4;
198 return ret; 195 return ret;
199}*/ 196}
200void * allocate(int size) 197*/
198
199#define malloc(n) my_malloc(n)
200void * my_malloc(int size)
201{ 201{
202 return alloc(size); 202 return alloc(size);
203} 203}
@@ -211,7 +211,7 @@ unsigned char readChar(int file)
211 211
212unsigned char * readData(int file, int len) 212unsigned char * readData(int file, int len)
213{ 213{
214 unsigned char * dat = allocate(len); 214 unsigned char * dat = malloc(len);
215 rb->read(file, dat, len); 215 rb->read(file, dat, len);
216 return dat; 216 return dat;
217} 217}
@@ -226,7 +226,29 @@ int eof(int fd)
226 return size+1 == rb->lseek(fd, 0, SEEK_CUR); 226 return size+1 == rb->lseek(fd, 0, SEEK_CUR);
227} 227}
228 228
229void printf(char *fmt, ...) {fmt=fmt; } 229// Here is a hacked up printf command to get the output from the game.
230int printf(const char *fmt, ...)
231{
232 static int p_xtpt;
233 char p_buf[50];
234 bool ok;
235 va_list ap;
236
237 va_start(ap, fmt);
238 ok = rb->vsnprintf(p_buf,sizeof(p_buf), fmt, ap);
239 va_end(ap);
240
241 rb->lcd_putsxy(1,p_xtpt, (unsigned char *)p_buf);
242 rb->lcd_update();
243
244 p_xtpt+=8;
245 if(p_xtpt>LCD_HEIGHT-8)
246 {
247 p_xtpt=0;
248 rb->lcd_clear_display();
249 }
250 return 1;
251}
230 252
231void exit(int code) 253void exit(int code)
232{ 254{
diff --git a/apps/plugins/midi/sequencer.c b/apps/plugins/midi/sequencer.c
index 4ae5a9f5fe..3c026276c2 100644
--- a/apps/plugins/midi/sequencer.c
+++ b/apps/plugins/midi/sequencer.c
@@ -22,22 +22,22 @@ extern struct plugin_api * rb;
22long tempo=375000; 22long tempo=375000;
23 23
24 24
25void setVol(int ch, int vol) 25inline void setVol(int ch, int vol)
26{ 26{
27 printf("\nvolume[%d] %d ==> %d", ch, chVol[ch], vol); 27// printf("\nvolume[%d] %d ==> %d", ch, chVol[ch], vol);
28 chVol[ch]=vol; 28 chVol[ch]=vol;
29} 29}
30 30
31void setPan(int ch, int pan) 31inline void setPan(int ch, int pan)
32{ 32{
33 printf("\npanning[%d] %d ==> %d", ch, chPanRight[ch], pan); 33// printf("\npanning[%d] %d ==> %d", ch, chPanRight[ch], pan);
34 34
35 chPanLeft[ch]=128-pan; 35 chPanLeft[ch]=128-pan;
36 chPanRight[ch]=pan; 36 chPanRight[ch]=pan;
37} 37}
38 38
39 39
40void setPatch(int ch, int pat) 40inline void setPatch(int ch, int pat)
41{ 41{
42 chPat[ch]=pat; 42 chPat[ch]=pat;
43} 43}
@@ -52,18 +52,64 @@ void setPatch(int ch, int pat)
52/* 52/*
53long pitchTbl[]= 53long pitchTbl[]=
54{ 54{
55 58386,58491,58597,58703,58809,58915,59022,59128,59235,59342,59449,59557,59664,59772,59880,59988,60097,60205, 55 58386,58491,58597,58703,58809,58915,59022,59128,59235,59342,59449,59557,
56 60314,60423,60532,60642,60751,60861,60971,61081,61191,61302,61413,61524,61635,61746,61858,61970,62081,62194, 56 59664,59772,59880,59988,60097,60205,60314,60423,60532,60642,60751,60861,
57 62306,62419,62531,62644,62757,62871,62984,63098,63212,63326,63441,63555,63670,63785,63901,64016,64132,64248, 57 60971,61081,61191,61302,61413,61524,61635,61746,61858,61970,62081,62194,
58 64364,64480,64596,64713,64830,64947,65065,65182,65300,65418,65536,65654,65773,65892,66011,66130,66250,66369, 58 62306,62419,62531,62644,62757,62871,62984,63098,63212,63326,63441,63555,
59 66489,66609,66730,66850,66971,67092,67213,67335,67456,67578,67700,67823,67945,68068,68191,68314,68438,68561, 59 63670,63785,63901,64016,64132,64248,64364,64480,64596,64713,64830,64947,
60 68685,68809,68933,69058,69183,69308,69433,69558,69684,69810,69936,70062,70189,70316,70443,70570,70698,70825, 60 65065,65182,65300,65418,65536,65654,65773,65892,66011,66130,66250,66369,
61 70953,71082,71210,71339,71468,71597,71726,71856,71985,72115,72246,72376,72507,72638,72769,72901,73032,73164, 61 66489,66609,66730,66850,66971,67092,67213,67335,67456,67578,67700,67823,
62 73297,73429 62 67945,68068,68191,68314,68438,68561,68685,68809,68933,69058,69183,69308,
63 69433,69558,69684,69810,69936,70062,70189,70316,70443,70570,70698,70825,
64 70953,71082,71210,71339,71468,71597,71726,71856,71985,72115,72246,72376,
65 72507,72638,72769,72901,73032,73164,73297,73429
63}; 66};
64*/ 67*/
65long pitchTbl[]={ 68
6658386,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 69long pitchTbl[] ICONST_ATTR={
70 58386,58412,58439,58465,58491,58518,58544,58571,58597,58624,58650,58676,
71 58703,58729,58756,58782,58809,58836,58862,58889,58915,58942,58968,58995,
72 59022,59048,59075,59102,59128,59155,59182,59208,59235,59262,59289,59315,
73 59342,59369,59396,59423,59449,59476,59503,59530,59557,59584,59611,59638,
74 59664,59691,59718,59745,59772,59799,59826,59853,59880,59907,59934,59961,
75 59988,60015,60043,60070,60097,60124,60151,60178,60205,60233,60260,60287,
76 60314,60341,60369,60396,60423,60450,60478,60505,60532,60560,60587,60614,
77 60642,60669,60696,60724,60751,60779,60806,60833,60861,60888,60916,60943,
78 60971,60998,61026,61054,61081,61109,61136,61164,61191,61219,61247,61274,
79 61302,61330,61357,61385,61413,61440,61468,61496,61524,61551,61579,61607,
80 61635,61663,61690,61718,61746,61774,61802,61830,61858,61886,61914,61942,
81 61970,61997,62025,62053,62081,62109,62138,62166,62194,62222,62250,62278,
82 62306,62334,62362,62390,62419,62447,62475,62503,62531,62560,62588,62616,
83 62644,62673,62701,62729,62757,62786,62814,62843,62871,62899,62928,62956,
84 62984,63013,63041,63070,63098,63127,63155,63184,63212,63241,63269,63298,
85 63326,63355,63384,63412,63441,63470,63498,63527,63555,63584,63613,63642,
86 63670,63699,63728,63757,63785,63814,63843,63872,63901,63929,63958,63987,
87 64016,64045,64074,64103,64132,64161,64190,64219,64248,64277,64306,64335,
88 64364,64393,64422,64451,64480,64509,64538,64567,64596,64626,64655,64684,
89 64713,64742,64772,64801,64830,64859,64889,64918,64947,64976,65006,65035,
90 65065,65094,65123,65153,65182,65211,65241,65270,65300,65329,65359,65388,
91 65418,65447,65477,65506,65536,65566,65595,65625,65654,65684,65714,65743,
92 65773,65803,65832,65862,65892,65922,65951,65981,66011,66041,66071,66100,
93 66130,66160,66190,66220,66250,66280,66309,66339,66369,66399,66429,66459,
94 66489,66519,66549,66579,66609,66639,66670,66700,66730,66760,66790,66820,
95 66850,66880,66911,66941,66971,67001,67032,67062,67092,67122,67153,67183,
96 67213,67244,67274,67304,67335,67365,67395,67426,67456,67487,67517,67548,
97 67578,67609,67639,67670,67700,67731,67761,67792,67823,67853,67884,67915,
98 67945,67976,68007,68037,68068,68099,68129,68160,68191,68222,68252,68283,
99 68314,68345,68376,68407,68438,68468,68499,68530,68561,68592,68623,68654,
100 68685,68716,68747,68778,68809,68840,68871,68902,68933,68965,68996,69027,
101 69058,69089,69120,69152,69183,69214,69245,69276,69308,69339,69370,69402,
102 69433,69464,69496,69527,69558,69590,69621,69653,69684,69716,69747,69778,
103 69810,69841,69873,69905,69936,69968,69999,70031,70062,70094,70126,70157,
104 70189,70221,70252,70284,70316,70348,70379,70411,70443,70475,70507,70538,
105 70570,70602,70634,70666,70698,70730,70762,70793,70825,70857,70889,70921,
106 70953,70985,71017,71049,71082,71114,71146,71178,71210,71242,71274,71306,
107 71339,71371,71403,71435,71468,71500,71532,71564,71597,71629,71661,71694,
108 71726,71758,71791,71823,71856,71888,71920,71953,71985,72018,72050,72083,
109 72115,72148,72181,72213,72246,72278,72311,72344,72376,72409,72442,72474,
110 72507,72540,72573,72605,72638,72671,72704,72736,72769,72802,72835,72868,
111 72901,72934,72967,72999,73032,73065,73098,73131,73164,73197,73230,73264,
112 73297,73330,73363,73396,73429,73462,73495,73528
67}; 113};
68 114
69void findDelta(struct SynthObject * so, int ch, int note) 115void findDelta(struct SynthObject * so, int ch, int note)
@@ -75,9 +121,9 @@ void findDelta(struct SynthObject * so, int ch, int note)
75 so->delta = (so->delta * pitchTbl[chPW[ch]])>> 16; 121 so->delta = (so->delta * pitchTbl[chPW[ch]])>> 16;
76} 122}
77 123
78void setPW(int ch, int msb, int lsb) 124inline void setPW(int ch, int msb, int lsb)
79{ 125{
80 printf("\npitchw[%d] %d ==> %d", ch, chPW[ch], msb); 126// printf("\npitchw[%d] %d ==> %d", ch, chPW[ch], msb);
81 chPW[ch] = msb<<2|lsb>>5; 127 chPW[ch] = msb<<2|lsb>>5;
82 128
83 int a=0; 129 int a=0;
@@ -92,7 +138,7 @@ void setPW(int ch, int msb, int lsb)
92 138
93void pressNote(int ch, int note, int vol) 139void pressNote(int ch, int note, int vol)
94{ 140{
95 141 static int lastKill = 0;
96//Silences all channels but one, for easy debugging, for me. 142//Silences all channels but one, for easy debugging, for me.
97/* 143/*
98 if(ch == 0) return; 144 if(ch == 0) return;
@@ -123,11 +169,16 @@ void pressNote(int ch, int note, int vol)
123 } 169 }
124 if(a==MAX_VOICES-1) 170 if(a==MAX_VOICES-1)
125 { 171 {
126 printf("\nOVERFLOW: Too many voices playing at once. No more left"); 172// printf("\nVoice kill");
127 printf("\nVOICE DUMP: "); 173// printf("\nToo many voices playing at once. No more left");
128 for(a=0; a<48; a++) 174// printf("\nVOICE DUMP: ");
129 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); 175// for(a=0; a<48; a++)
130 return; /* None available */ 176// 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);
177 lastKill++;
178 if(lastKill == MAX_VOICES)
179 lastKill = 0;
180 a = lastKill;
181// return; /* None available */
131 } 182 }
132 voices[a].ch=ch; 183 voices[a].ch=ch;
133 voices[a].note=note; 184 voices[a].note=note;
@@ -163,7 +214,7 @@ void pressNote(int ch, int note, int vol)
163 voices[a].wf=wf; 214 voices[a].wf=wf;
164 voices[a].delta = (((gustable[note]<<10) / wf->rootFreq) * wf->sampRate / SAMPLE_RATE); 215 voices[a].delta = (((gustable[note]<<10) / wf->rootFreq) * wf->sampRate / SAMPLE_RATE);
165 if(wf->mode & 28) 216 if(wf->mode & 28)
166 printf("\nWoah, a drum patch has a loop. Stripping the loop..."); 217// printf("\nWoah, a drum patch has a loop. Stripping the loop...");
167 wf->mode = wf->mode & (255-28); 218 wf->mode = wf->mode & (255-28);
168 219
169 /* Turn it on */ 220 /* Turn it on */
@@ -172,7 +223,7 @@ void pressNote(int ch, int note, int vol)
172 223
173 } else 224 } else
174 { 225 {
175 printf("\nWarning: drum %d does not have a patch defined... Ignoring it", note); 226/* printf("\nWarning: drum %d does not have a patch defined... Ignoring it", note); */
176 } 227 }
177 } 228 }
178} 229}
@@ -244,11 +295,7 @@ void sendEvent(struct Event * ev)
244 } 295 }
245} 296}
246 297
247 298int tick(void)
248
249
250
251int tick(struct MIDIfile * mf)
252{ 299{
253 if(mf==NULL) 300 if(mf==NULL)
254 return 0; 301 return 0;
@@ -280,7 +327,7 @@ int tick(struct MIDIfile * mf)
280 sendEvent(e); 327 sendEvent(e);
281 if(((e->status&0xF0) == MIDI_PRGM)) 328 if(((e->status&0xF0) == MIDI_PRGM))
282 { 329 {
283 printf("\nPatch Event, patch[%d] ==> %d", e->status&0xF, e->d1); 330/* printf("\nPatch Event, patch[%d] ==> %d", e->status&0xF, e->d1); */
284 } 331 }
285 } 332 }
286 else 333 else
diff --git a/apps/plugins/midi/synth.c b/apps/plugins/midi/synth.c
index 42ca9ddaf6..44417b2583 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)
104 104
105 if( (getEvent(mf->tracks[a], ts)->status & 0xF0) == MIDI_PRGM) 105 if( (getEvent(mf->tracks[a], ts)->status & 0xF0) == MIDI_PRGM)
106 { 106 {
107 if(patchUsed[getEvent(mf->tracks[a], ts)->d1]==0) 107/* if(patchUsed[getEvent(mf->tracks[a], ts)->d1]==0)
108 printf("\nI need to load patch %d.", getEvent(mf->tracks[a], ts)->d1); 108 printf("\nI need to load patch %d.", getEvent(mf->tracks[a], ts)->d1);
109*/
109 patchUsed[getEvent(mf->tracks[a], ts)->d1]=1; 110 patchUsed[getEvent(mf->tracks[a], ts)->d1]=1;
110 } 111 }
111 } 112 }
@@ -124,13 +125,14 @@ int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig)
124 /* Scan our config file and load the right patches as needed */ 125 /* Scan our config file and load the right patches as needed */
125 int c = 0; 126 int c = 0;
126 rb->snprintf(name, 40, ""); 127 rb->snprintf(name, 40, "");
128 printf("\nLoading instruments");
127 for(a=0; a<128; a++) 129 for(a=0; a<128; a++)
128 { 130 {
129 while(readChar(file)!=' ' && !eof(file)); 131 while(readChar(file)!=' ' && !eof(file));
130 readTextBlock(file, name); 132 readTextBlock(file, name);
131 133
132 rb->snprintf(fn, 40, "/.rockbox/patchset/%s.pat", name); 134 rb->snprintf(fn, 40, "/.rockbox/patchset/%s.pat", name);
133 printf("\nLOADING: <%s> ", fn); 135/* printf("\nLOADING: <%s> ", fn); */
134 136
135 if(patchUsed[a]==1) 137 if(patchUsed[a]==1)
136 { 138 {
@@ -155,6 +157,7 @@ int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig)
155 /* Scan our config file and load the drum data */ 157 /* Scan our config file and load the drum data */
156 int idx=0; 158 int idx=0;
157 char number[30]; 159 char number[30];
160 printf("\nLoading drums");
158 while(!eof(file)) 161 while(!eof(file))
159 { 162 {
160 readTextBlock(file, number); 163 readTextBlock(file, number);
@@ -168,7 +171,6 @@ int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig)
168 if(drumUsed[idx]==1) 171 if(drumUsed[idx]==1)
169 { 172 {
170 drumSet[idx]=gusload(fn); 173 drumSet[idx]=gusload(fn);
171
172 if(drumSet[idx] == NULL) /* Error loading patch */ 174 if(drumSet[idx] == NULL) /* Error loading patch */
173 return -1; 175 return -1;
174 } 176 }
@@ -180,32 +182,14 @@ int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig)
180 return 0; 182 return 0;
181} 183}
182 184
183 185inline short getSample(int s,struct GWaveform * wf )
184
185int currentVoice IDATA_ATTR;
186struct SynthObject * so IDATA_ATTR;
187struct GWaveform * wf IDATA_ATTR;
188int s IDATA_ATTR;
189short s1 IDATA_ATTR;
190short s2 IDATA_ATTR;
191short sample IDATA_ATTR; /* For synthSample */
192unsigned int cpShifted IDATA_ATTR;
193
194unsigned char b1 IDATA_ATTR;
195unsigned char b2 IDATA_ATTR;
196
197
198inline int getSample(int s)
199{ 186{
200 /* Sign conversion moved to guspat.c */ 187 /* Sign conversion moved to guspat.c */
201 /* 8bit conversion NOT YET IMPLEMENTED in guspat.c */ 188 /* 8bit conversion NOT YET IMPLEMENTED in guspat.c */
202 return ((short *) wf->data)[s]; 189 return ((short *) wf->data)[s];
203} 190}
204 191
205 192void setPoint(struct SynthObject * so, int pt)
206
207
208inline void setPoint(struct SynthObject * so, int pt)
209{ 193{
210 if(so->ch==9) /* Drums, no ADSR */ 194 if(so->ch==9) /* Drums, no ADSR */
211 { 195 {
@@ -227,7 +211,7 @@ inline void setPoint(struct SynthObject * so, int pt)
227 211
228 so->curPoint = pt; 212 so->curPoint = pt;
229 213
230 int r=0; 214 int r;
231 int rate = so->wf->envRate[pt]; 215 int rate = so->wf->envRate[pt];
232 216
233 r=3-((rate>>6) & 0x3); /* Some blatant Timidity code for rate conversion... */ 217 r=3-((rate>>6) & 0x3); /* Some blatant Timidity code for rate conversion... */
@@ -243,15 +227,17 @@ inline void setPoint(struct SynthObject * so, int pt)
243 * default this to 10, and maybe later have an option to set it to 9 227 * default this to 10, and maybe later have an option to set it to 9
244 * for longer decays. 228 * for longer decays.
245 */ 229 */
246 so->curRate = r<<10; 230 so->curRate = r<<11;
247 231
248 /* 232 /*
249 * Do this here because the patches assume a 44100 sampling rate 233 * Do this here because the patches assume a 44100 sampling rate
250 * We've halved our sampling rate, ergo the ADSR code will be 234 * We've halved our sampling rate, ergo the ADSR code will be
251 * called half the time. Ergo, double the rate to keep stuff 235 * called half the time. Ergo, double the rate to keep stuff
252 * sounding right. 236 * sounding right.
237 *
238 * Or just move the 1 up one line to optimize a tiny bit.
253 */ 239 */
254 so->curRate = so->curRate << 1; 240/* so->curRate = so->curRate << 1;*/
255 241
256 242
257 so->targetOffset = so->wf->envOffset[pt]<<(20); 243 so->targetOffset = so->wf->envOffset[pt]<<(20);
@@ -270,9 +256,14 @@ inline void stopVoice(struct SynthObject * so)
270} 256}
271 257
272 258
273inline signed short int synthVoice(void) 259signed short int synthVoice(struct SynthObject * so)
274{ 260{
275 so = &voices[currentVoice]; 261 struct GWaveform * wf;
262 register int s;
263 register unsigned int cpShifted;
264 register short s1;
265 register short s2;
266
276 wf = so->wf; 267 wf = so->wf;
277 268
278 269
@@ -288,7 +279,7 @@ inline signed short int synthVoice(void)
288 stopVoice(so); 279 stopVoice(so);
289 } 280 }
290 281
291 s2 = getSample((cpShifted)+1); 282 s2 = getSample((cpShifted)+1, wf);
292 283
293 /* LOOP_REVERSE|LOOP_PINGPONG = 24 */ 284 /* LOOP_REVERSE|LOOP_PINGPONG = 24 */
294 if((wf->mode & (24)) && so->loopState == STATE_LOOPING && (cpShifted <= (wf->startLoop))) 285 if((wf->mode & (24)) && so->loopState == STATE_LOOPING && (cpShifted <= (wf->startLoop)))
@@ -297,8 +288,9 @@ inline signed short int synthVoice(void)
297 { 288 {
298 so->cp = (wf->endLoop)<<10; //Was 10 289 so->cp = (wf->endLoop)<<10; //Was 10
299 cpShifted = wf->endLoop; 290 cpShifted = wf->endLoop;
300 s2=getSample((cpShifted)); 291 s2=getSample((cpShifted), wf);
301 } else 292 }
293 else
302 { 294 {
303 so->delta = -so->delta; 295 so->delta = -so->delta;
304 so->loopDir = LOOPDIR_FORWARD; 296 so->loopDir = LOOPDIR_FORWARD;
@@ -312,8 +304,9 @@ inline signed short int synthVoice(void)
312 { 304 {
313 so->cp = (wf->startLoop)<<10; //Was 10 305 so->cp = (wf->startLoop)<<10; //Was 10
314 cpShifted = wf->startLoop; 306 cpShifted = wf->startLoop;
315 s2=getSample((cpShifted)); 307 s2=getSample((cpShifted), wf);
316 } else 308 }
309 else
317 { 310 {
318 so->delta = -so->delta; 311 so->delta = -so->delta;
319 so->loopDir = LOOPDIR_REVERSE; 312 so->loopDir = LOOPDIR_REVERSE;
@@ -321,7 +314,7 @@ inline signed short int synthVoice(void)
321 } 314 }
322 315
323 /* Better, working, linear interpolation */ 316 /* Better, working, linear interpolation */
324 s1=getSample((cpShifted)); //\|/ Was 1023)) >> 10 317 s1=getSample((cpShifted), wf); //\|/ Was 1023)) >> 10
325 s = s1 + ((signed)((s2 - s1) * (so->cp & 1023))>>10); //Was 10 318 s = s1 + ((signed)((s2 - s1) * (so->cp & 1023))>>10); //Was 10
326 319
327 320
@@ -381,18 +374,26 @@ inline signed short int synthVoice(void)
381 374
382inline void synthSample(int * mixL, int * mixR) 375inline void synthSample(int * mixL, int * mixR)
383{ 376{
384 *mixL = 0; 377 register int dL=0;
385 *mixR = 0; 378 register int dR=0;
386 for(currentVoice=0; currentVoice<MAX_VOICES; currentVoice++) 379 register short sample=0;
380 register struct SynthObject *voicept=voices;
381 struct SynthObject *lastvoice=&voices[MAX_VOICES];
382
383 while(voicept!=lastvoice)
387 { 384 {
388 if(voices[currentVoice].isUsed==1) 385 if(voicept->isUsed==1)
389 { 386 {
390 sample = synthVoice(); 387 sample = synthVoice(voicept);
391 *mixL += (sample*chPanLeft[voices[currentVoice].ch])>>7; 388 dL += (sample*chPanLeft[voicept->ch])>>7;
392 *mixR += (sample*chPanRight[voices[currentVoice].ch])>>7; 389 dR += (sample*chPanRight[voicept->ch])>>7;
393 } 390 }
391 voicept++;
394 } 392 }
395 393
394 *mixL=dL;
395 *mixR=dR;
396
396 /* TODO: Automatic Gain Control, anyone? */ 397 /* TODO: Automatic Gain Control, anyone? */
397 /* Or, should this be implemented on the DSP's output volume instead? */ 398 /* Or, should this be implemented on the DSP's output volume instead? */
398 399
diff --git a/apps/plugins/midiplay.c b/apps/plugins/midiplay.c
new file mode 100644
index 0000000000..f279e72e4e
--- /dev/null
+++ b/apps/plugins/midiplay.c
@@ -0,0 +1,217 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2005 Karl Kurbjun based on midi2wav by Stepan Moskovchenko
10 *
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
13 *
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
16 *
17 ****************************************************************************/
18
19#include "../../plugin.h"
20
21PLUGIN_HEADER
22
23#define SAMPLE_RATE 22050 // 44100 22050 11025
24#define MAX_VOICES 12 // Note: 24 midi channels is the minimum general midi
25 // spec implementation
26#define BUF_SIZE 512
27#define NBUF 2
28
29#undef SYNC
30struct MIDIfile * mf IBSS_ATTR;
31
32int numberOfSamples IBSS_ATTR;
33long bpm IBSS_ATTR;
34
35#include "midi/midiutil.c"
36#include "midi/guspat.h"
37#include "midi/guspat.c"
38#include "midi/sequencer.c"
39#include "midi/midifile.c"
40#include "midi/synth.c"
41
42short gmbuf[BUF_SIZE*NBUF] IBSS_ATTR;
43
44int quit=0;
45struct plugin_api * rb;
46
47#ifdef USE_IRAM
48extern char iramcopy[];
49extern char iramstart[];
50extern char iramend[];
51extern char iedata[];
52extern char iend[];
53#endif
54
55enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
56{
57 rb = api;
58
59 if(parameter == NULL)
60 {
61 rb->splash(HZ*2, true, " Play .MID file ");
62 return PLUGIN_OK;
63 }
64 rb->lcd_setfont(0);
65
66#ifdef USE_IRAM
67 rb->memcpy(iramstart, iramcopy, iramend-iramstart);
68 rb->memset(iedata, 0, iend - iedata);
69#endif
70
71#if !defined(SIMULATOR) && defined(HAVE_ADJUSTABLE_CPU_FREQ)
72 rb->cpu_boost(true);
73#endif
74
75 printf("\n%s", parameter);
76/* rb->splash(HZ, true, parameter); */
77
78#ifdef RB_PROFILE
79 rb->profile_thread();
80#endif
81
82 if(midimain(parameter) == -1)
83 return PLUGIN_ERROR;
84
85#ifdef RB_PROFILE
86 rb->profstop();
87#endif
88
89#ifndef SIMULATOR
90 rb->pcm_play_stop();
91 rb->pcm_set_frequency(44100); // 44100
92#endif
93
94#if !defined(SIMULATOR) && defined(HAVE_ADJUSTABLE_CPU_FREQ)
95 rb->cpu_boost(false);
96#endif
97
98 rb->splash(HZ, true, "FINISHED PLAYING");
99
100 return PLUGIN_OK;
101}
102
103bool swap=0;
104bool lastswap=1;
105
106inline void synthbuf(void)
107{
108 short *outptr;
109 register int i;
110 static int currentSample=0;
111 int synthtemp[2];
112
113#ifndef SYNC
114 if(lastswap==swap) return;
115 lastswap=swap;
116
117 outptr=(swap ? gmbuf : gmbuf+BUF_SIZE);
118#else
119 outptr=gmbuf;
120#endif
121
122 for(i=0; i<BUF_SIZE/2; i++)
123 {
124 synthSample(&synthtemp[0], &synthtemp[1]);
125 currentSample++;
126 *outptr=synthtemp[0]&0xFFFF;
127 outptr++;
128 *outptr=synthtemp[1]&0xFFFF;
129 outptr++;
130 if(currentSample==numberOfSamples)
131 {
132 if( tick() == 0 ) quit=1;
133 currentSample=0;
134 }
135 }
136}
137
138void get_more(unsigned char** start, size_t* size)
139{
140#ifndef SYNC
141 if(lastswap!=swap)
142 {
143 printf("Buffer miss!"); // Comment out the printf to make missses less noticable.
144/*
145 int a=0;
146 for(a=0; a<MAX_VOICES; a++)
147 {
148 voices[a].isUsed=0;
149 }
150*/
151 }
152
153#else
154 synthbuf(); // For some reason midiplayer crashes when an update is forced
155#endif
156
157 *size = BUF_SIZE*sizeof(short);
158#ifndef SYNC
159 *start = (unsigned char*)((swap ? gmbuf : gmbuf + BUF_SIZE));
160 swap=!swap;
161#else
162 *start = (unsigned char*)(gmbuf);
163#endif
164}
165
166int midimain(void * filename)
167{
168 int button;
169
170/* rb->splash(HZ/5, true, "LOADING MIDI"); */
171 printf("\nLoading file");
172 mf= loadFile(filename);
173
174/* rb->splash(HZ/5, true, "LOADING PATCHES"); */
175 if (initSynth(mf, "/.rockbox/patchset/patchset.cfg", "/.rockbox/patchset/drums.cfg") == -1)
176 return -1;
177
178#ifndef SIMULATOR
179 rb->pcm_play_stop();
180 rb->pcm_set_frequency(SAMPLE_RATE); // 44100 22050 11025
181#endif
182
183 /*
184 * tick() will do one MIDI clock tick. Then, there's a loop here that
185 * will generate the right number of samples per MIDI tick. The whole
186 * MIDI playback is timed in terms of this value.. there are no forced
187 * delays or anything. It just produces enough samples for each tick, and
188 * the playback of these samples is what makes the timings right.
189 *
190 * This seems to work quite well.
191 */
192
193 printf("\nOkay, starting sequencing");
194
195 bpm=mf->div*1000000/tempo;
196 numberOfSamples=SAMPLE_RATE/bpm;
197
198 tick();
199
200 synthbuf();
201#ifndef SIMULATOR
202 rb->pcm_play_data(&get_more, NULL, 0);
203#endif
204
205 button=rb->button_status();
206
207 while(!quit)
208 {
209#ifndef SYNC
210 synthbuf();
211#endif
212 rb->yield();
213 if(rb->button_status()!=button) quit=1;
214 }
215
216 return 0;
217}
diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config
index 6de2bd883a..afab02278b 100644
--- a/apps/plugins/viewers.config
+++ b/apps/plugins/viewers.config
@@ -11,7 +11,7 @@ txt,viewers/sort, 00 00 00 00 00 00
11gb,viewers/rockboy, 0C 2A 59 7A 2E 0C 11gb,viewers/rockboy, 0C 2A 59 7A 2E 0C
12gbc,viewers/rockboy, 0C 2A 59 7A 2E 0C 12gbc,viewers/rockboy, 0C 2A 59 7A 2E 0C
13m3u,viewers/iriverify,00 00 00 00 00 00 13m3u,viewers/iriverify,00 00 00 00 00 00
14mid,viewers/midi2wav, 20 70 70 3F 00 00 14mid,viewers/midiplay, 20 70 70 3F 00 00
15rsp,viewers/searchengine, 0e 11 11 31 7e 60 15rsp,viewers/searchengine, 0e 11 11 31 7e 60
16ss,rocks/sudoku, 55 55 55 55 55 55 16ss,rocks/sudoku, 55 55 55 55 55 55
17wav,viewers/wav2wv, 00 00 00 00 00 00 17wav,viewers/wav2wv, 00 00 00 00 00 00