diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/midi/guspat.c | 327 | ||||
-rw-r--r-- | apps/plugins/midi/guspat.h | 94 | ||||
-rw-r--r-- | apps/plugins/midi/midifile.c | 427 | ||||
-rw-r--r-- | apps/plugins/midi/midiutil.c | 222 | ||||
-rw-r--r-- | apps/plugins/midi/sequencer.c | 470 | ||||
-rw-r--r-- | apps/plugins/midi/synth.c | 650 | ||||
-rw-r--r-- | apps/plugins/midi2wav.c | 231 |
7 files changed, 1181 insertions, 1240 deletions
diff --git a/apps/plugins/midi/guspat.c b/apps/plugins/midi/guspat.c index 2172072eb1..23b6811542 100644 --- a/apps/plugins/midi/guspat.c +++ b/apps/plugins/midi/guspat.c | |||
@@ -21,197 +21,176 @@ extern struct plugin_api * rb; | |||
21 | 21 | ||
22 | unsigned int readWord(int file) | 22 | unsigned int readWord(int file) |
23 | { | 23 | { |
24 | return (readChar(file)<<0) | (readChar(file)<<8); // | (readChar(file)<<8) | (readChar(file)<<0); | 24 | return (readChar(file)<<0) | (readChar(file)<<8); // | (readChar(file)<<8) | (readChar(file)<<0); |
25 | } | 25 | } |
26 | 26 | ||
27 | unsigned int readDWord(int file) | 27 | unsigned int readDWord(int file) |
28 | { | 28 | { |
29 | return (readChar(file)<<0) | (readChar(file)<<8) | (readChar(file)<<16) | (readChar(file)<<24); | 29 | return (readChar(file)<<0) | (readChar(file)<<8) | (readChar(file)<<16) | (readChar(file)<<24); |
30 | } | 30 | } |
31 | 31 | ||
32 | struct GWaveform * loadWaveform(int file) | 32 | struct GWaveform * loadWaveform(int file) |
33 | { | 33 | { |
34 | struct GWaveform * wav = (struct GWaveform *)allocate(sizeof(struct GWaveform)); | 34 | struct GWaveform * wav = (struct GWaveform *)allocate(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); |
42 | wav->endLoop=readDWord(file); | 42 | wav->endLoop=readDWord(file); |
43 | wav->sampRate=readWord(file); | 43 | wav->sampRate=readWord(file); |
44 | 44 | ||
45 | wav->lowFreq=readDWord(file); | 45 | wav->lowFreq=readDWord(file); |
46 | wav->highFreq=readDWord(file); | 46 | wav->highFreq=readDWord(file); |
47 | wav->rootFreq=readDWord(file); | 47 | wav->rootFreq=readDWord(file); |
48 | 48 | ||
49 | wav->tune=readWord(file); | 49 | wav->tune=readWord(file); |
50 | 50 | ||
51 | wav->balance=readChar(file); | 51 | wav->balance=readChar(file); |
52 | wav->envRate=readData(file, 6); | 52 | wav->envRate=readData(file, 6); |
53 | wav->envOffset=readData(file, 6); | 53 | wav->envOffset=readData(file, 6); |
54 | 54 | ||
55 | wav->tremSweep=readChar(file); | 55 | wav->tremSweep=readChar(file); |
56 | wav->tremRate==readChar(file); | 56 | wav->tremRate==readChar(file); |
57 | wav->tremDepth=readChar(file); | 57 | wav->tremDepth=readChar(file); |
58 | wav->vibSweep=readChar(file); | 58 | wav->vibSweep=readChar(file); |
59 | wav->vibRate=readChar(file); | 59 | wav->vibRate=readChar(file); |
60 | wav->vibDepth=readChar(file); | 60 | wav->vibDepth=readChar(file); |
61 | wav->mode=readChar(file); | 61 | wav->mode=readChar(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 | ||
69 | wav->numSamples = wav->wavSize / 2; | 69 | wav->numSamples = wav->wavSize / 2; |
70 | int a=0; | 70 | wav->startLoop = wav->startLoop >> 1; |
71 | 71 | wav->endLoop = wav->endLoop >> 1; | |
72 | return wav; | 72 | unsigned int a=0; |
73 | if(wav->mode & 1 == 0) //Whoops, 8 bit | 73 | |
74 | { | 74 | /* half baked 8 bit conversion UNFINISHED*/ |
75 | wav->numSamples = wav->wavSize; | 75 | /* |
76 | 76 | if(wav->mode & 1 == 0) //Whoops, 8 bit | |
77 | //Allocate a block for the rest of it | 77 | { |
78 | //It should end up right after the previous one. | 78 | wav->numSamples = wav->wavSize; |
79 | wav->wavSize = wav->wavSize * 2; | 79 | |
80 | void * foo = allocate(wav->wavSize); | 80 | //Allocate a block for the rest of it |
81 | 81 | //It should end up right after the previous one. | |
82 | 82 | wav->wavSize = wav->wavSize * 2; | |
83 | for(a=0; a<1000; a++) | 83 | void * foo = allocate(wav->wavSize); |
84 | printf("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); | 84 | |
85 | 85 | ||
86 | 86 | for(a=0; a<1000; a++) | |
87 | for(a=wav->wavSize-1; a>0; a-=2) | 87 | printf("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!"); |
88 | { | 88 | |
89 | 89 | ||
90 | } | 90 | for(a=wav->wavSize-1; a>0; a-=2) |
91 | // int b1=wf->data[s]+((wf->mode & 2) << 6); | 91 | { |
92 | // return b1<<8; | 92 | |
93 | } | 93 | } |
94 | 94 | // int b1=wf->data[s]+((wf->mode & 2) << 6); | |
95 | /* | 95 | // return b1<<8; |
96 | //#if !defined(SIMULATOR) | 96 | } |
97 | for(a=0; a<wav->wavSize; a+=2) | 97 | */ |
98 | { | 98 | |
99 | unsigned char tmp; | 99 | |
100 | tmp = wav->data[2*a]; | 100 | /* Iriver needs byteswapping.. big endian, go figure. Gus files are little endian */ |
101 | wav->data[2*a] = wav->data[2*a+1]; | 101 | |
102 | wav->data[2*a+1] = tmp; | 102 | #if !defined(SIMULATOR) |
103 | } | 103 | for(a=0; a<wav->numSamples; a++) |
104 | //#endif | 104 | { |
105 | 105 | ((unsigned short *) wav->data)[a] = SWAB16(((unsigned short *) wav->data)[a]); | |
106 | if(wav->mode & 2) | 106 | } |
107 | { | 107 | #endif |
108 | for(a=0; a<wav->wavSize/2; a++) | 108 | |
109 | { | 109 | /* Convert unsigned to signed by subtracting 32768 */ |
110 | ((short *) wav->data)[a] = ((short *) wav->data)[a] - 32767; | 110 | if(wav->mode & 2) |
111 | } | 111 | { |
112 | } | 112 | for(a=0; a<wav->numSamples; a++) |
113 | */ | 113 | ((short *) wav->data)[a] = ((unsigned short *) wav->data)[a] - 32768; |
114 | 114 | ||
115 | 115 | } | |
116 | 116 | ||
117 | //If we have a 16 bit waveform | 117 | return wav; |
118 | /* if(wav->mode & 1 && (wav->mode & 2)) | ||
119 | { | ||
120 | for(a=0; a<wav->wavSize; a+=2) //Convert it to | ||
121 | { | ||
122 | wav->data[a]=wav->data[a]+(1 << 7); | ||
123 | wav->data[a|1]=wav->data[(a)|1]+(1 << 7); | ||
124 | } | ||
125 | } | ||
126 | */ | ||
127 | return wav; | ||
128 | } | 118 | } |
129 | 119 | ||
130 | 120 | ||
131 | 121 | ||
132 | int selectWaveform(struct GPatch * pat, int midiNote) | 122 | int selectWaveform(struct GPatch * pat, int midiNote) |
133 | { | 123 | { |
134 | int tabFreq = gustable[midiNote]/100; //Comparison | 124 | /* We divide by 100 here because everyone's freq formula is slightly different */ |
135 | int a=0; | 125 | unsigned int tabFreq = gustable[midiNote]/100; /* Comparison */ |
136 | for(a=0; a<pat->numWaveforms; a++) | 126 | unsigned int a=0; |
137 | { | 127 | for(a=0; a<pat->numWaveforms; a++) |
138 | if(pat->waveforms[a]->lowFreq/100 <= tabFreq && | 128 | { |
139 | pat->waveforms[a]->highFreq/100 >= tabFreq) | 129 | if(pat->waveforms[a]->lowFreq/100 <= tabFreq && |
140 | { | 130 | pat->waveforms[a]->highFreq/100 >= tabFreq) |
141 | return a; | 131 | { |
142 | } | 132 | return a; |
143 | } | 133 | } |
144 | return 0; | 134 | } |
135 | return 0; | ||
145 | } | 136 | } |
146 | 137 | ||
147 | 138 | ||
148 | struct GPatch * gusload(char * filename) | 139 | struct GPatch * gusload(char * filename) |
149 | { | 140 | { |
150 | struct GPatch * gp = (struct GPatch *)allocate(sizeof(struct GPatch)); | 141 | struct GPatch * gp = (struct GPatch *)allocate(sizeof(struct GPatch)); |
151 | rb->memset(gp, 0, sizeof(struct GPatch)); | 142 | rb->memset(gp, 0, sizeof(struct GPatch)); |
152 | 143 | ||
153 | int file = rb->open(filename, O_RDONLY); | 144 | int file = rb->open(filename, O_RDONLY); |
154 | 145 | ||
155 | if(file == -1) | 146 | if(file == -1) |
156 | { | 147 | { |
157 | char message[50]; | 148 | char message[50]; |
158 | rb->snprintf(message, 50, "Error opening %s", filename); | 149 | rb->snprintf(message, 50, "Error opening %s", filename); |
159 | rb->splash(HZ*2, true, message); | 150 | rb->splash(HZ*2, true, message); |
160 | return NULL; | 151 | return NULL; |
161 | } | 152 | } |
162 | 153 | ||
163 | gp->header=readData(file, 12); | 154 | gp->header=readData(file, 12); |
164 | gp->gravisid=readData(file, 10); | 155 | gp->gravisid=readData(file, 10); |
165 | gp->desc=readData(file, 60); | 156 | gp->desc=readData(file, 60); |
166 | gp->inst=readChar(file); | 157 | gp->inst=readChar(file); |
167 | gp->voc=readChar(file); | 158 | gp->voc=readChar(file); |
168 | gp->chan=readChar(file); | 159 | gp->chan=readChar(file); |
169 | gp->numWaveforms=readWord(file); //readWord(file); | 160 | gp->numWaveforms=readWord(file); |
170 | gp->vol=readWord(file); | 161 | gp->vol=readWord(file); |
171 | gp->datSize=readDWord(file); | 162 | gp->datSize=readDWord(file); |
172 | gp->res=readData(file, 36); | 163 | gp->res=readData(file, 36); |
173 | 164 | ||
174 | gp->instrID=readWord(file); | 165 | gp->instrID=readWord(file); |
175 | gp->instrName=readData(file,16); | 166 | gp->instrName=readData(file,16); |
176 | gp->instrSize=readDWord(file); | 167 | gp->instrSize=readDWord(file); |
177 | gp->layers=readChar(file); | 168 | gp->layers=readChar(file); |
178 | gp->instrRes=readData(file,40); | 169 | gp->instrRes=readData(file,40); |
179 | 170 | ||
180 | 171 | ||
181 | gp->layerDup=readChar(file); | 172 | gp->layerDup=readChar(file); |
182 | gp->layerID=readChar(file); | 173 | gp->layerID=readChar(file); |
183 | gp->layerSize=readDWord(file); | 174 | gp->layerSize=readDWord(file); |
184 | gp->numWaves=readChar(file); | 175 | gp->numWaves=readChar(file); |
185 | gp->layerRes=readData(file,40); | 176 | gp->layerRes=readData(file,40); |
186 | 177 | ||
187 | /* printf("\n%s\n%s\n%s", gp->header, gp->gravisid, gp->desc); | 178 | |
188 | printf("\nInst = %d", gp->inst); | 179 | printf("\nFILE: %s", filename); |
189 | printf("\nVoc = %d", gp->voc); | 180 | printf("\nlayerSamples=%d", gp->numWaves); |
190 | printf("\nChan = %d", gp->chan); | 181 | |
191 | printf("\nWav = %d", gp->numWaveforms); | 182 | int a=0; |
192 | printf("\nVol = %d", gp->vol); | 183 | for(a=0; a<gp->numWaves; a++) |
193 | printf("\nSize = %d", gp->datSize); | 184 | gp->waveforms[a] = loadWaveform(file); |
194 | 185 | ||
195 | printf("\n\ninstrID = %d", gp->instrID); | 186 | |
196 | printf("\ninstrName = %s", gp->instrName); | 187 | printf("\nPrecomputing note table"); |
197 | // printf("\ninstrSize = %d", gp->instrSize); | 188 | |
198 | // printf("\nlayers = %d", gp->layers); | 189 | for(a=0; a<128; a++) |
199 | */ | 190 | { |
200 | printf("\nFILE: %s", filename); | 191 | gp->noteTable[a] = selectWaveform(gp, a); |
201 | printf("\nlayerSamples=%d", gp->numWaves); | 192 | } |
202 | 193 | rb->close(file); | |
203 | int a=0; | 194 | |
204 | for(a=0; a<gp->numWaves; a++) | 195 | return gp; |
205 | gp->waveforms[a] = loadWaveform(file); | ||
206 | |||
207 | |||
208 | printf("\nPrecomputing note table"); | ||
209 | |||
210 | for(a=0; a<128; a++) | ||
211 | { | ||
212 | gp->noteTable[a] = selectWaveform(gp, a); | ||
213 | } | ||
214 | rb->close(file); | ||
215 | |||
216 | return gp; | ||
217 | } | 196 | } |
diff --git a/apps/plugins/midi/guspat.h b/apps/plugins/midi/guspat.h index 6e41a85d23..e35f54b57a 100644 --- a/apps/plugins/midi/guspat.h +++ b/apps/plugins/midi/guspat.h | |||
@@ -16,7 +16,7 @@ | |||
16 | * | 16 | * |
17 | ****************************************************************************/ | 17 | ****************************************************************************/ |
18 | 18 | ||
19 | //This came from one of the Gravis documents | 19 | /* This came from one of the Gravis documents */ |
20 | static const unsigned int gustable[]= | 20 | static const unsigned int gustable[]= |
21 | { | 21 | { |
22 | 8175, 8661, 9177, 9722, 10300, 10913, 11562, 12249, 12978, 13750, 14567, 15433, | 22 | 8175, 8661, 9177, 9722, 10300, 10913, 11562, 12249, 12978, 13750, 14567, 15433, |
@@ -33,63 +33,63 @@ static const unsigned int gustable[]= | |||
33 | 33 | ||
34 | struct GWaveform | 34 | struct GWaveform |
35 | { | 35 | { |
36 | unsigned char * name; | 36 | unsigned char * name; |
37 | unsigned char fractions; | 37 | unsigned char fractions; |
38 | unsigned int wavSize; | 38 | unsigned int wavSize; |
39 | unsigned int numSamples; | 39 | unsigned int numSamples; |
40 | unsigned int startLoop; | 40 | unsigned int startLoop; |
41 | unsigned int endLoop; | 41 | unsigned int endLoop; |
42 | unsigned int sampRate; | 42 | unsigned int sampRate; |
43 | unsigned int lowFreq; | 43 | unsigned int lowFreq; |
44 | unsigned int highFreq; | 44 | unsigned int highFreq; |
45 | unsigned int rootFreq; | 45 | unsigned int rootFreq; |
46 | unsigned int tune; | 46 | unsigned int tune; |
47 | unsigned int balance; | 47 | unsigned int balance; |
48 | unsigned char * envRate; | 48 | unsigned char * envRate; |
49 | unsigned char * envOffset; | 49 | unsigned char * envOffset; |
50 | 50 | ||
51 | unsigned char tremSweep; | 51 | unsigned char tremSweep; |
52 | unsigned char tremRate; | 52 | unsigned char tremRate; |
53 | unsigned char tremDepth; | 53 | unsigned char tremDepth; |
54 | unsigned char vibSweep; | 54 | unsigned char vibSweep; |
55 | unsigned char vibRate; | 55 | unsigned char vibRate; |
56 | unsigned char vibDepth; | 56 | unsigned char vibDepth; |
57 | unsigned char mode; | 57 | unsigned char mode; |
58 | 58 | ||
59 | unsigned int scaleFreq; | 59 | unsigned int scaleFreq; |
60 | unsigned int scaleFactor; | 60 | unsigned int scaleFactor; |
61 | 61 | ||
62 | unsigned char * res; | 62 | unsigned char * res; |
63 | signed char * data; | 63 | signed char * data; |
64 | }; | 64 | }; |
65 | 65 | ||
66 | 66 | ||
67 | struct GPatch | 67 | struct GPatch |
68 | { | 68 | { |
69 | unsigned int patchNumber; | 69 | unsigned int patchNumber; |
70 | unsigned char * header; | 70 | unsigned char * header; |
71 | unsigned char * gravisid; | 71 | unsigned char * gravisid; |
72 | unsigned char * desc; | 72 | unsigned char * desc; |
73 | unsigned char inst, voc, chan; | 73 | unsigned char inst, voc, chan; |
74 | unsigned int numWaveforms; | 74 | unsigned int numWaveforms; |
75 | unsigned int datSize; | 75 | unsigned int datSize; |
76 | unsigned int vol; | 76 | unsigned int vol; |
77 | unsigned char * res; | 77 | unsigned char * res; |
78 | 78 | ||
79 | 79 | ||
80 | unsigned int instrID; | 80 | unsigned int instrID; |
81 | unsigned char * instrName; | 81 | unsigned char * instrName; |
82 | unsigned int instrSize; | 82 | unsigned int instrSize; |
83 | unsigned int layers; | 83 | unsigned int layers; |
84 | unsigned char * instrRes; | 84 | unsigned char * instrRes; |
85 | 85 | ||
86 | unsigned char layerDup; | 86 | unsigned char layerDup; |
87 | unsigned char layerID; | 87 | unsigned char layerID; |
88 | unsigned int layerSize; | 88 | unsigned int layerSize; |
89 | unsigned char numWaves; | 89 | unsigned char numWaves; |
90 | unsigned char * layerRes; | 90 | unsigned char * layerRes; |
91 | 91 | ||
92 | unsigned char noteTable[128]; | 92 | unsigned char noteTable[128]; |
93 | struct GWaveform * waveforms[255]; | 93 | struct GWaveform * waveforms[255]; |
94 | }; | 94 | }; |
95 | 95 | ||
diff --git a/apps/plugins/midi/midifile.c b/apps/plugins/midi/midifile.c index c786b8e5a6..412cc6104d 100644 --- a/apps/plugins/midi/midifile.c +++ b/apps/plugins/midi/midifile.c | |||
@@ -26,233 +26,232 @@ void bail(const char *); | |||
26 | 26 | ||
27 | struct MIDIfile * loadFile(char * filename) | 27 | struct MIDIfile * loadFile(char * filename) |
28 | { | 28 | { |
29 | struct MIDIfile * mf; | 29 | struct MIDIfile * mf; |
30 | int file = rb->open (filename, O_RDONLY); | 30 | int file = rb->open (filename, O_RDONLY); |
31 | 31 | ||
32 | if(file==0) | 32 | if(file==-1) |
33 | { | 33 | { |
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 | mf = (struct MIDIfile*)allocate(sizeof(struct MIDIfile)); |
38 | 38 | ||
39 | if(mf==NULL) | 39 | if(mf==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(mf, 0, sizeof(struct MIDIfile)); |
46 | 46 | ||
47 | if(readID(file) != ID_MTHD) | 47 | if(readID(file) != ID_MTHD) |
48 | { | 48 | { |
49 | rb->close(file); | 49 | rb->close(file); |
50 | bail("Invalid file header chunk."); | 50 | bail("Invalid file header chunk."); |
51 | } | 51 | } |
52 | 52 | ||
53 | if(readFourBytes(file)!=6) | 53 | if(readFourBytes(file)!=6) |
54 | { | 54 | { |
55 | rb->close(file); | 55 | rb->close(file); |
56 | bail("Header chunk size invalid."); | 56 | bail("Header chunk size invalid."); |
57 | } | 57 | } |
58 | 58 | ||
59 | if(readTwoBytes(file)==2) | 59 | if(readTwoBytes(file)==2) |
60 | { | 60 | { |
61 | rb->close(file); | 61 | rb->close(file); |
62 | bail("MIDI file type not supported"); | 62 | bail("MIDI file type not supported"); |
63 | } | 63 | } |
64 | 64 | ||
65 | mf->numTracks = readTwoBytes(file); | 65 | mf->numTracks = readTwoBytes(file); |
66 | mf->div = readTwoBytes(file); | 66 | mf->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", mf->numTracks, mf->div); |
71 | 71 | ||
72 | // return; | 72 | |
73 | 73 | while(! eof(file) && track < mf->numTracks) | |
74 | 74 | { | |
75 | while(! eof(file) && track < mf->numTracks) | 75 | unsigned char id = readID(file); |
76 | { | 76 | |
77 | unsigned char id = readID(file); | 77 | |
78 | 78 | if(id == ID_EOF) | |
79 | 79 | { | |
80 | if(id == ID_EOF) | 80 | if(mf->numTracks != track) |
81 | { | 81 | { |
82 | if(mf->numTracks != track) | 82 | printf("\nError: file claims to have %d tracks.\n I only see %d here.\n", mf->numTracks, track); |
83 | { | 83 | mf->numTracks = track; |
84 | printf("\nError: file claims to have %d tracks.\n I only see %d here.\n", mf->numTracks, track); | 84 | } |
85 | mf->numTracks = track; | 85 | return mf; |
86 | } | 86 | } |
87 | return mf; | 87 | |
88 | } | 88 | if(id == ID_MTRK) |
89 | 89 | { | |
90 | if(id == ID_MTRK) | 90 | mf->tracks[track] = readTrack(file); |
91 | { | 91 | //exit(0); |
92 | mf->tracks[track] = readTrack(file); | 92 | track++; |
93 | //exit(0); | 93 | } else |
94 | track++; | 94 | { |
95 | } else | 95 | printf("\n SKIPPING TRACK"); |
96 | { | 96 | int len = readFourBytes(file); |
97 | printf("\n SKIPPING TRACK"); | 97 | while(--len) |
98 | int len = readFourBytes(file); | 98 | readChar(file); |
99 | while(--len) | 99 | } |
100 | readChar(file); | 100 | } |
101 | } | 101 | return mf; |
102 | } | ||
103 | return mf; | ||
104 | 102 | ||
105 | } | 103 | } |
106 | 104 | ||
107 | 105 | ||
108 | int rStatus = 0; | 106 | int rStatus = 0; |
109 | 107 | ||
110 | //Returns 0 if done, 1 if keep going | 108 | /* Returns 0 if done, 1 if keep going */ |
111 | int readEvent(int file, void * dest) | 109 | int readEvent(int file, void * dest) |
112 | { | 110 | { |
113 | struct Event dummy; | 111 | struct Event dummy; |
114 | struct Event * ev = (struct Event *) dest; | 112 | struct Event * ev = (struct Event *) dest; |
115 | 113 | ||
116 | if(ev == NULL) | 114 | if(ev == NULL) |
117 | ev = &dummy; //If we are just counting events instead of loading them | 115 | ev = &dummy; /* If we are just counting events instead of loading them */ |
118 | 116 | ||
119 | ev->delta = readVarData(file); | 117 | ev->delta = readVarData(file); |
120 | 118 | ||
121 | 119 | ||
122 | int t=readChar(file); | 120 | int t=readChar(file); |
123 | 121 | ||
124 | if((t&0x80) == 0x80) //if not a running status event | 122 | if((t&0x80) == 0x80) /* if not a running status event */ |
125 | { | 123 | { |
126 | ev->status = t; | 124 | ev->status = t; |
127 | if(t == 0xFF) | 125 | if(t == 0xFF) |
128 | { | 126 | { |
129 | ev->d1 = readChar(file); | 127 | ev->d1 = readChar(file); |
130 | ev->len = readVarData(file); | 128 | ev->len = readVarData(file); |
131 | 129 | ||
132 | //Allocate and read in the data block | 130 | /* Allocate and read in the data block */ |
133 | if(dest != NULL) | 131 | if(dest != NULL) |
134 | { | 132 | { |
135 | ev->evData = readData(file, ev->len); | 133 | ev->evData = readData(file, ev->len); |
136 | printf("\nDATA: <%s>", ev->evData); | 134 | printf("\nDATA: <%s>", ev->evData); |
137 | } | 135 | } |
138 | else | 136 | else |
139 | { | 137 | { |
140 | //Don't allocate anything, just see how much it would tale | 138 | /* |
141 | //To make memory usage efficient | 139 | * Don't allocate anything, just see how much it would tale |
142 | 140 | * To make memory usage efficient | |
143 | int a=0; | 141 | */ |
144 | for(a=0; a<ev->len; a++) | 142 | unsigned int a=0; |
145 | readChar(file); //Skip skip | 143 | for(a=0; a<ev->len; a++) |
146 | } | 144 | readChar(file); //Skip skip |
147 | 145 | } | |
148 | if(ev->d1 == 0x2F) | 146 | |
149 | { | 147 | if(ev->d1 == 0x2F) |
150 | return 0; //Termination meta-event | 148 | { |
151 | } | 149 | return 0; /* Termination meta-event */ |
152 | } else //If part of a running status event | 150 | } |
153 | { | 151 | } else /* If part of a running status event */ |
154 | rStatus = t; | 152 | { |
155 | ev->status = t; | 153 | rStatus = t; |
156 | ev->d1 = readChar(file); | 154 | ev->status = t; |
157 | 155 | ev->d1 = readChar(file); | |
158 | if ( ((t & 0xF0) != 0xD0) && ((t & 0xF0) != 0xC0) && ((t & 0xF0) > 0x40) ) | 156 | |
159 | { | 157 | if ( ((t & 0xF0) != 0xD0) && ((t & 0xF0) != 0xC0) && ((t & 0xF0) > 0x40) ) |
160 | ev->d2 = readChar(file); | 158 | { |
161 | } else | 159 | ev->d2 = readChar(file); |
162 | ev->d2 = 127; | 160 | } else |
163 | } | 161 | ev->d2 = 127; |
164 | } else //Running Status | 162 | } |
165 | { | 163 | } else /* Running Status */ |
166 | ev->status = rStatus; | 164 | { |
167 | ev->d1 = t; | 165 | ev->status = rStatus; |
168 | if ( ((rStatus & 0xF0) != 0xD0) && ((rStatus & 0xF0) != 0xC0) && ((rStatus & 0xF0) > 0x40) ) | 166 | ev->d1 = t; |
169 | { | 167 | if ( ((rStatus & 0xF0) != 0xD0) && ((rStatus & 0xF0) != 0xC0) && ((rStatus & 0xF0) > 0x40) ) |
170 | ev->d2 = readChar(file); | 168 | { |
171 | } else | 169 | ev->d2 = readChar(file); |
172 | ev->d2 = 127; | 170 | } else |
173 | } | 171 | ev->d2 = 127; |
174 | return 1; | 172 | } |
173 | return 1; | ||
175 | } | 174 | } |
176 | 175 | ||
177 | 176 | ||
178 | 177 | ||
179 | struct Track * readTrack(int file) | 178 | struct Track * readTrack(int file) |
180 | { | 179 | { |
181 | struct Track * trk = (struct Track *)allocate(sizeof(struct Track)); | 180 | struct Track * trk = (struct Track *)allocate(sizeof(struct Track)); |
182 | rb->memset(trk, 0, sizeof(struct Track)); | 181 | rb->memset(trk, 0, sizeof(struct Track)); |
183 | 182 | ||
184 | trk->size = readFourBytes(file); | 183 | trk->size = readFourBytes(file); |
185 | trk->pos = 0; | 184 | trk->pos = 0; |
186 | trk->delta = 0; | 185 | trk->delta = 0; |
187 | 186 | ||
188 | int numEvents=0; | 187 | int numEvents=0; |
189 | 188 | ||
190 | int pos = rb->lseek(file, 0, SEEK_CUR); | 189 | int pos = rb->lseek(file, 0, SEEK_CUR); |
191 | 190 | ||
192 | while(readEvent(file, NULL)) //Memory saving technique | 191 | while(readEvent(file, NULL)) /* Memory saving technique */ |
193 | numEvents++; //Attempt to read in events, count how many | 192 | numEvents++; /* Attempt to read in events, count how many */ |
194 | //THEN allocate memory and read them in | 193 | /* THEN allocate memory and read them in */ |
195 | rb->lseek(file, pos, SEEK_SET); | 194 | rb->lseek(file, pos, SEEK_SET); |
196 | 195 | ||
197 | int trackSize = (numEvents+1) * sizeof(struct Event); | 196 | int trackSize = (numEvents+1) * sizeof(struct Event); |
198 | void * dataPtr = allocate(trackSize); | 197 | void * dataPtr = allocate(trackSize); |
199 | trk->dataBlock = dataPtr; | 198 | trk->dataBlock = dataPtr; |
200 | 199 | ||
201 | numEvents=0; | 200 | numEvents=0; |
202 | 201 | ||
203 | while(readEvent(file, dataPtr)) | 202 | while(readEvent(file, dataPtr)) |
204 | { | 203 | { |
205 | if(trackSize < dataPtr-trk->dataBlock) | 204 | if(trackSize < dataPtr-trk->dataBlock) |
206 | { | 205 | { |
207 | printf("\nTrack parser memory out of bounds"); | 206 | printf("\nTrack parser memory out of bounds"); |
208 | exit(1); | 207 | exit(1); |
209 | } | 208 | } |
210 | dataPtr+=sizeof(struct Event); | 209 | dataPtr+=sizeof(struct Event); |
211 | numEvents++; | 210 | numEvents++; |
212 | } | 211 | } |
213 | trk->numEvents = numEvents; | 212 | trk->numEvents = numEvents; |
214 | 213 | ||
215 | return trk; | 214 | return trk; |
216 | } | 215 | } |
217 | 216 | ||
218 | 217 | ||
219 | int readID(int file) | 218 | int readID(int file) |
220 | { | 219 | { |
221 | char id[5]; | 220 | char id[5]; |
222 | id[4]=0; | 221 | id[4]=0; |
223 | BYTE a; | 222 | BYTE a; |
224 | 223 | ||
225 | for(a=0; a<4; a++) | 224 | for(a=0; a<4; a++) |
226 | id[a]=readChar(file); | 225 | id[a]=readChar(file); |
227 | if(eof(file)) | 226 | if(eof(file)) |
228 | { | 227 | { |
229 | printf("\End of file reached."); | 228 | printf("\End of file reached."); |
230 | return ID_EOF; | 229 | return ID_EOF; |
231 | } | 230 | } |
232 | if(rb->strcmp(id, "MThd")==0) | 231 | if(rb->strcmp(id, "MThd")==0) |
233 | return ID_MTHD; | 232 | return ID_MTHD; |
234 | if(rb->strcmp(id, "MTrk")==0) | 233 | if(rb->strcmp(id, "MTrk")==0) |
235 | return ID_MTRK; | 234 | return ID_MTRK; |
236 | return ID_UNKNOWN; | 235 | return ID_UNKNOWN; |
237 | } | 236 | } |
238 | 237 | ||
239 | 238 | ||
240 | int readFourBytes(int file) | 239 | int readFourBytes(int file) |
241 | { | 240 | { |
242 | int data=0; | 241 | int data=0; |
243 | BYTE a=0; | 242 | BYTE a=0; |
244 | for(a=0; a<4; a++) | 243 | for(a=0; a<4; a++) |
245 | data=(data<<8)+readChar(file); | 244 | data=(data<<8)+readChar(file); |
246 | return data; | 245 | return data; |
247 | } | 246 | } |
248 | 247 | ||
249 | int readTwoBytes(int file) | 248 | int readTwoBytes(int file) |
250 | { | 249 | { |
251 | int data=(readChar(file)<<8)+readChar(file); | 250 | int data=(readChar(file)<<8)+readChar(file); |
252 | return data; | 251 | return data; |
253 | } | 252 | } |
254 | 253 | ||
255 | //This came from the MIDI file format guide | 254 | /* This came from the MIDI file format guide */ |
256 | int readVarData(int file) | 255 | int readVarData(int file) |
257 | { | 256 | { |
258 | unsigned int value; | 257 | unsigned int value; |
@@ -270,37 +269,35 @@ int readVarData(int file) | |||
270 | 269 | ||
271 | 270 | ||
272 | /* | 271 | /* |
273 | //This function should not be needed because we | ||
274 | //can just release the whole memory buffer at once | ||
275 | void unloadFile(struct MIDIfile * mf) | 272 | void unloadFile(struct MIDIfile * mf) |
276 | { | 273 | { |
277 | if(mf == NULL) | 274 | if(mf == NULL) |
278 | return; | 275 | return; |
279 | int a=0; | 276 | int a=0; |
280 | //Unload each track | 277 | //Unload each track |
281 | for(a=0; a<mf->numTracks; a++) | 278 | for(a=0; a<mf->numTracks; a++) |
282 | { | 279 | { |
283 | int b=0; | 280 | int b=0; |
284 | 281 | ||
285 | if(mf->tracks[a] != NULL) | 282 | if(mf->tracks[a] != NULL) |
286 | for(b=0; b<mf->tracks[a]->numEvents; b++) | 283 | for(b=0; b<mf->tracks[a]->numEvents; b++) |
287 | { | 284 | { |
288 | if(((struct Event*)((mf->tracks[a]->dataBlock)+b*sizeof(struct Event)))->evData!=NULL) | 285 | if(((struct Event*)((mf->tracks[a]->dataBlock)+b*sizeof(struct Event)))->evData!=NULL) |
289 | free(((struct Event*)((mf->tracks[a]->dataBlock)+b*sizeof(struct Event)))->evData); | 286 | free(((struct Event*)((mf->tracks[a]->dataBlock)+b*sizeof(struct Event)))->evData); |
290 | } | 287 | } |
291 | 288 | ||
292 | if(mf->tracks[a]!=NULL && mf->tracks[a]->dataBlock != NULL) | 289 | if(mf->tracks[a]!=NULL && mf->tracks[a]->dataBlock != NULL) |
293 | free(mf->tracks[a]->dataBlock); //Unload the event block | 290 | free(mf->tracks[a]->dataBlock); //Unload the event block |
294 | 291 | ||
295 | if(mf->tracks[a]!=NULL) | 292 | if(mf->tracks[a]!=NULL) |
296 | free(mf->tracks[a]); //Unload the track structure itself | 293 | free(mf->tracks[a]); //Unload the track structure itself |
297 | } | 294 | } |
298 | free(mf); //Unload the main struct | 295 | free(mf); //Unload the main struct |
299 | } | 296 | } |
300 | */ | 297 | */ |
301 | void bail(const char * err) | 298 | void bail(const char * err) |
302 | { | 299 | { |
303 | rb->splash(HZ*3, true, err); | 300 | rb->splash(HZ*3, true, err); |
304 | exit(0); | 301 | exit(0); |
305 | } | 302 | } |
306 | 303 | ||
diff --git a/apps/plugins/midi/midiutil.c b/apps/plugins/midi/midiutil.c index bf25d1d277..d0b968e52c 100644 --- a/apps/plugins/midi/midiutil.c +++ b/apps/plugins/midi/midiutil.c | |||
@@ -20,39 +20,39 @@ | |||
20 | #define BYTE unsigned char | 20 | #define BYTE unsigned char |
21 | 21 | ||
22 | //Data chunk ID types, returned by readID() | 22 | //Data chunk ID types, returned by readID() |
23 | #define ID_UNKNOWN -1 | 23 | #define ID_UNKNOWN -1 |
24 | #define ID_MTHD 1 | 24 | #define ID_MTHD 1 |
25 | #define ID_MTRK 2 | 25 | #define ID_MTRK 2 |
26 | #define ID_EOF 3 | 26 | #define ID_EOF 3 |
27 | 27 | ||
28 | //MIDI Commands | 28 | //MIDI Commands |
29 | #define MIDI_NOTE_OFF 128 | 29 | #define MIDI_NOTE_OFF 128 |
30 | #define MIDI_NOTE_ON 144 | 30 | #define MIDI_NOTE_ON 144 |
31 | #define MIDI_AFTERTOUCH 160 | 31 | #define MIDI_AFTERTOUCH 160 |
32 | #define MIDI_CONTROL 176 | 32 | #define MIDI_CONTROL 176 |
33 | #define MIDI_PRGM 192 | 33 | #define MIDI_PRGM 192 |
34 | #define MIDI_PITCHW 224 | 34 | #define MIDI_PITCHW 224 |
35 | 35 | ||
36 | 36 | ||
37 | //MIDI Controllers | 37 | //MIDI Controllers |
38 | #define CTRL_VOLUME 7 | 38 | #define CTRL_VOLUME 7 |
39 | #define CTRL_BALANCE 8 | 39 | #define CTRL_BALANCE 8 |
40 | #define CTRL_PANNING 10 | 40 | #define CTRL_PANNING 10 |
41 | #define CHANNEL 1 | 41 | #define CHANNEL 1 |
42 | 42 | ||
43 | //Most of these are deprecated.. rampdown is used, maybe one other one too | 43 | //Most of these are deprecated.. rampdown is used, maybe one other one too |
44 | #define STATE_ATTACK 1 | 44 | #define STATE_ATTACK 1 |
45 | #define STATE_DECAY 2 | 45 | #define STATE_DECAY 2 |
46 | #define STATE_SUSTAIN 3 | 46 | #define STATE_SUSTAIN 3 |
47 | #define STATE_RELEASE 4 | 47 | #define STATE_RELEASE 4 |
48 | #define STATE_RAMPDOWN 5 | 48 | #define STATE_RAMPDOWN 5 |
49 | 49 | ||
50 | //Loop states | 50 | //Loop states |
51 | #define STATE_LOOPING 7 | 51 | #define STATE_LOOPING 7 |
52 | #define STATE_NONLOOPING 8 | 52 | #define STATE_NONLOOPING 8 |
53 | 53 | ||
54 | //Various bits in the GUS mode byte | 54 | //Various bits in the GUS mode byte |
55 | #define LOOP_ENABLED 4 | 55 | #define LOOP_ENABLED 4 |
56 | #define LOOP_PINGPONG 8 | 56 | #define LOOP_PINGPONG 8 |
57 | #define LOOP_REVERSE 16 | 57 | #define LOOP_REVERSE 16 |
58 | 58 | ||
@@ -63,81 +63,69 @@ | |||
63 | extern struct plugin_api * rb; | 63 | extern struct plugin_api * rb; |
64 | 64 | ||
65 | 65 | ||
66 | int chVol[16] IDATA_ATTR; //Channel volume | 66 | int chVol[16] IDATA_ATTR; /* Channel volume */ |
67 | int chPanLeft[16] IDATA_ATTR; //Channel panning | 67 | int chPanLeft[16] IDATA_ATTR; /* Channel panning */ |
68 | int chPanRight[16] IDATA_ATTR; | 68 | int chPanRight[16] IDATA_ATTR; |
69 | int chPat[16]; //Channel patch | 69 | int chPat[16]; /* Channel patch */ |
70 | int chPW[16]; //Channel pitch wheel, MSB only | 70 | int chPW[16]; /* Channel pitch wheel, MSB only */ |
71 | 71 | ||
72 | 72 | ||
73 | /* | ||
74 | unsigned char chVol[16]; //Channel volume | ||
75 | unsigned char chPanLeft[16]; //Channel panning | ||
76 | unsigned char chPanRight[16]; | ||
77 | unsigned char chPat[16]; //Channel patch | ||
78 | unsigned char chPW[16]; //Channel pitch wheel, MSB only | ||
79 | */ | ||
80 | struct GPatch * gusload(char *); | 73 | struct GPatch * gusload(char *); |
81 | struct GPatch * patchSet[128]; | 74 | struct GPatch * patchSet[128]; |
82 | struct GPatch * drumSet[128]; | 75 | struct GPatch * drumSet[128]; |
83 | 76 | ||
84 | |||
85 | //char myarray[80] IDATA_ATTR; | ||
86 | |||
87 | struct Event | 77 | struct Event |
88 | { | 78 | { |
89 | unsigned int delta; | 79 | unsigned int delta; |
90 | unsigned char status, d1, d2; | 80 | unsigned char status, d1, d2; |
91 | unsigned int len; | 81 | unsigned int len; |
92 | unsigned char * evData; | 82 | unsigned char * evData; |
93 | }; | 83 | }; |
94 | 84 | ||
95 | struct Track | 85 | struct Track |
96 | { | 86 | { |
97 | unsigned int size; | 87 | unsigned int size; |
98 | unsigned int numEvents; | 88 | unsigned int numEvents; |
99 | unsigned int delta; //For sequencing | 89 | unsigned int delta; /* For sequencing */ |
100 | unsigned int pos; //For sequencing | 90 | unsigned int pos; /* For sequencing */ |
101 | void * dataBlock; | 91 | void * dataBlock; |
102 | }; | 92 | }; |
103 | 93 | ||
104 | 94 | ||
105 | struct MIDIfile | 95 | struct MIDIfile |
106 | { | 96 | { |
107 | int Length; | 97 | int Length; |
108 | 98 | unsigned short numTracks; | |
109 | //int Format; //We don't really care what type it is | 99 | unsigned short div; /* Time division, X ticks per millisecond */ |
110 | unsigned short numTracks; | 100 | struct Track * tracks[48]; |
111 | unsigned short div; //Time division, X ticks per millisecond | 101 | unsigned char patches[128]; |
112 | struct Track * tracks[48]; | 102 | int numPatches; |
113 | unsigned char patches[128]; | ||
114 | int numPatches; | ||
115 | }; | 103 | }; |
104 | |||
116 | /* | 105 | /* |
117 | struct SynthObject | 106 | struct SynthObject |
118 | { | 107 | { |
119 | // int tmp; | 108 | struct GWaveform * wf; |
120 | struct GWaveform * wf; | 109 | unsigned int delta; |
121 | unsigned int delta; | 110 | unsigned int decay; |
122 | unsigned int decay; | 111 | unsigned int cp; |
123 | unsigned int cp; | 112 | unsigned char state, loopState, loopDir; |
124 | unsigned char state, loopState, loopDir; | 113 | unsigned char note, vol, ch, isUsed; |
125 | unsigned char note, vol, ch, isUsed; | 114 | int curRate, curOffset, targetOffset; |
126 | int curRate, curOffset, targetOffset; | 115 | unsigned int curPoint; |
127 | unsigned int curPoint; | ||
128 | }; | 116 | }; |
129 | */ | 117 | */ |
118 | |||
130 | struct SynthObject | 119 | struct SynthObject |
131 | { | 120 | { |
132 | // int tmp; | 121 | struct GWaveform * wf; |
133 | struct GWaveform * wf; | 122 | int delta; |
134 | int delta; | 123 | int decay; |
135 | int decay; | 124 | unsigned int cp; |
136 | int cp; | 125 | int state, loopState, loopDir; |
137 | int state, loopState, loopDir; | 126 | int note, vol, ch, isUsed; |
138 | int note, vol, ch, isUsed; | 127 | int curRate, curOffset, targetOffset; |
139 | int curRate, curOffset, targetOffset; | 128 | int curPoint; |
140 | int curPoint; | ||
141 | }; | 129 | }; |
142 | 130 | ||
143 | struct SynthObject voices[MAX_VOICES] IDATA_ATTR; | 131 | struct SynthObject voices[MAX_VOICES] IDATA_ATTR; |
@@ -156,91 +144,91 @@ int midimain(void * filename); | |||
156 | 144 | ||
157 | void *alloc(int size) | 145 | void *alloc(int size) |
158 | { | 146 | { |
159 | static char *offset = NULL; | 147 | static char *offset = NULL; |
160 | static int totalSize = 0; | 148 | static int totalSize = 0; |
161 | char *ret; | 149 | char *ret; |
162 | 150 | ||
163 | int remainder = size % 4; | 151 | int remainder = size % 4; |
164 | 152 | ||
165 | size = size + 4-remainder; | 153 | size = size + 4-remainder; |
166 | 154 | ||
167 | if (offset == NULL) | 155 | if (offset == NULL) |
168 | { | 156 | { |
169 | offset = rb->plugin_get_audio_buffer(&totalSize); | 157 | offset = rb->plugin_get_audio_buffer(&totalSize); |
170 | } | 158 | } |
171 | 159 | ||
172 | if (size + 4 > totalSize) | 160 | if (size + 4 > totalSize) |
173 | { | 161 | { |
174 | return NULL; | 162 | return NULL; |
175 | } | 163 | } |
176 | 164 | ||
177 | ret = offset + 4; | 165 | ret = offset + 4; |
178 | *((unsigned int *)offset) = size; | 166 | *((unsigned int *)offset) = size; |
179 | 167 | ||
180 | offset += size + 4; | 168 | offset += size + 4; |
181 | totalSize -= size + 4; | 169 | totalSize -= size + 4; |
182 | return ret; | 170 | return ret; |
183 | } | 171 | } |
184 | 172 | ||
185 | 173 | ||
186 | //Rick's code | 174 | /* Rick's code */ |
187 | /* | 175 | /* |
188 | void *alloc(int size) | 176 | void *alloc(int size) |
189 | { | 177 | { |
190 | static char *offset = NULL; | 178 | static char *offset = NULL; |
191 | static int totalSize = 0; | 179 | static int totalSize = 0; |
192 | char *ret; | 180 | char *ret; |
193 | 181 | ||
194 | 182 | ||
195 | if (offset == NULL) | 183 | if (offset == NULL) |
196 | { | 184 | { |
197 | offset = rb->plugin_get_audio_buffer(&totalSize); | 185 | offset = rb->plugin_get_audio_buffer(&totalSize); |
198 | } | 186 | } |
199 | 187 | ||
200 | if (size + 4 > totalSize) | 188 | if (size + 4 > totalSize) |
201 | { | 189 | { |
202 | return NULL; | 190 | return NULL; |
203 | } | 191 | } |
204 | 192 | ||
205 | ret = offset + 4; | 193 | ret = offset + 4; |
206 | *((unsigned int *)offset) = size; | 194 | *((unsigned int *)offset) = size; |
207 | 195 | ||
208 | offset += size + 4; | 196 | offset += size + 4; |
209 | totalSize -= size + 4; | 197 | totalSize -= size + 4; |
210 | return ret; | 198 | return ret; |
211 | }*/ | 199 | }*/ |
212 | void * allocate(int size) | 200 | void * allocate(int size) |
213 | { | 201 | { |
214 | return alloc(size); | 202 | return alloc(size); |
215 | } | 203 | } |
216 | 204 | ||
217 | unsigned char readChar(int file) | 205 | unsigned char readChar(int file) |
218 | { | 206 | { |
219 | char buf[2]; | 207 | char buf[2]; |
220 | rb->read(file, &buf, 1); | 208 | rb->read(file, &buf, 1); |
221 | return buf[0]; | 209 | return buf[0]; |
222 | } | 210 | } |
223 | 211 | ||
224 | unsigned char * readData(int file, int len) | 212 | unsigned char * readData(int file, int len) |
225 | { | 213 | { |
226 | unsigned char * dat = allocate(len); | 214 | unsigned char * dat = allocate(len); |
227 | rb->read(file, dat, len); | 215 | rb->read(file, dat, len); |
228 | return dat; | 216 | return dat; |
229 | } | 217 | } |
230 | 218 | ||
231 | int eof(int fd) | 219 | int eof(int fd) |
232 | { | 220 | { |
233 | int curPos = rb->lseek(fd, 0, SEEK_CUR); | 221 | int curPos = rb->lseek(fd, 0, SEEK_CUR); |
234 | 222 | ||
235 | int size = rb->lseek(fd, 0, SEEK_END); | 223 | int size = rb->lseek(fd, 0, SEEK_END); |
236 | 224 | ||
237 | rb->lseek(fd, curPos, SEEK_SET); | 225 | rb->lseek(fd, curPos, SEEK_SET); |
238 | return size+1 == rb->lseek(fd, 0, SEEK_CUR); | 226 | return size+1 == rb->lseek(fd, 0, SEEK_CUR); |
239 | } | 227 | } |
240 | 228 | ||
241 | void printf(char *fmt, ...) {fmt=fmt; } | 229 | void printf(char *fmt, ...) {fmt=fmt; } |
242 | 230 | ||
243 | void exit(int code) | 231 | void exit(int code) |
244 | { | 232 | { |
245 | code = code; //Stub function, kill warning for now | 233 | code = code; /* Stub function, kill warning for now */ |
246 | } | 234 | } |
diff --git a/apps/plugins/midi/sequencer.c b/apps/plugins/midi/sequencer.c index 836866a5df..4781963645 100644 --- a/apps/plugins/midi/sequencer.c +++ b/apps/plugins/midi/sequencer.c | |||
@@ -24,233 +24,220 @@ long tempo=375000; | |||
24 | 24 | ||
25 | void setVol(int ch, int vol) | 25 | 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 | ||
31 | void setPan(int ch, int pan) | 31 | 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 | ||
40 | void setPatch(int ch, int pat) | 40 | void setPatch(int ch, int pat) |
41 | { | 41 | { |
42 | chPat[ch]=pat; | 42 | chPat[ch]=pat; |
43 | } | 43 | } |
44 | 44 | ||
45 | 45 | ||
46 | /* | 46 | /* |
47 | Pitch Bend table, Computed by | 47 | * Pitch Bend table, Computed by |
48 | for i=0:127, fprintf('%d,', round(2^16*2^((i-64)/384))); end | 48 | * for i=0:127, fprintf('%d,', round(2^16*2^((i-64)/384))); end |
49 | (When typed into Matlab) | 49 | * (When typed into Matlab) |
50 | 16 bit pitch bend table | 50 | * 16 bit pitch bend table |
51 | */ | 51 | */ |
52 | long pitchTbl[]= | 52 | long pitchTbl[]= |
53 | { | 53 | { |
54 | 58386,58491,58597,58703,58809,58915,59022,59128,59235,59342,59449,59557,59664,59772,59880,59988,60097,60205, | 54 | 58386,58491,58597,58703,58809,58915,59022,59128,59235,59342,59449,59557,59664,59772,59880,59988,60097,60205, |
55 | 60314,60423,60532,60642,60751,60861,60971,61081,61191,61302,61413,61524,61635,61746,61858,61970,62081,62194, | 55 | 60314,60423,60532,60642,60751,60861,60971,61081,61191,61302,61413,61524,61635,61746,61858,61970,62081,62194, |
56 | 62306,62419,62531,62644,62757,62871,62984,63098,63212,63326,63441,63555,63670,63785,63901,64016,64132,64248, | 56 | 62306,62419,62531,62644,62757,62871,62984,63098,63212,63326,63441,63555,63670,63785,63901,64016,64132,64248, |
57 | 64364,64480,64596,64713,64830,64947,65065,65182,65300,65418,65536,65654,65773,65892,66011,66130,66250,66369, | 57 | 64364,64480,64596,64713,64830,64947,65065,65182,65300,65418,65536,65654,65773,65892,66011,66130,66250,66369, |
58 | 66489,66609,66730,66850,66971,67092,67213,67335,67456,67578,67700,67823,67945,68068,68191,68314,68438,68561, | 58 | 66489,66609,66730,66850,66971,67092,67213,67335,67456,67578,67700,67823,67945,68068,68191,68314,68438,68561, |
59 | 68685,68809,68933,69058,69183,69308,69433,69558,69684,69810,69936,70062,70189,70316,70443,70570,70698,70825, | 59 | 68685,68809,68933,69058,69183,69308,69433,69558,69684,69810,69936,70062,70189,70316,70443,70570,70698,70825, |
60 | 70953,71082,71210,71339,71468,71597,71726,71856,71985,72115,72246,72376,72507,72638,72769,72901,73032,73164, | 60 | 70953,71082,71210,71339,71468,71597,71726,71856,71985,72115,72246,72376,72507,72638,72769,72901,73032,73164, |
61 | 73297,73429 | 61 | 73297,73429 |
62 | }; | 62 | }; |
63 | 63 | ||
64 | 64 | ||
65 | void findDelta(struct SynthObject * so, int ch, int note) | 65 | void findDelta(struct SynthObject * so, int ch, int note) |
66 | { | 66 | { |
67 | 67 | ||
68 | struct GWaveform * wf = patchSet[chPat[ch]]->waveforms[patchSet[chPat[ch]]->noteTable[note]]; | 68 | struct GWaveform * wf = patchSet[chPat[ch]]->waveforms[patchSet[chPat[ch]]->noteTable[note]]; |
69 | so->wf=wf; | 69 | so->wf=wf; |
70 | so->delta = (((gustable[note]<<10) / wf->rootFreq) * wf->sampRate / SAMPLE_RATE); | 70 | so->delta = (((gustable[note]<<10) / (wf->rootFreq)) * wf->sampRate / (SAMPLE_RATE)); |
71 | so->delta = so->delta * pitchTbl[chPW[ch]] >> 16; | 71 | so->delta = (so->delta * pitchTbl[chPW[ch]])>> 16; |
72 | } | 72 | } |
73 | 73 | ||
74 | void setPW(int ch, int msb) | 74 | void setPW(int ch, int msb) |
75 | { | 75 | { |
76 | printf("\npitchw[%d] %d ==> %d", ch, chPW[ch], msb); | 76 | printf("\npitchw[%d] %d ==> %d", ch, chPW[ch], msb); |
77 | chPW[ch] = msb; | 77 | chPW[ch] = msb; |
78 | 78 | ||
79 | int a=0; | 79 | int a=0; |
80 | for(a = 0; a<MAX_VOICES; a++) | 80 | for(a = 0; a<MAX_VOICES; a++) |
81 | { | 81 | { |
82 | if(voices[a].isUsed==1 && voices[a].ch == ch) | 82 | if(voices[a].isUsed==1 && voices[a].ch == ch) |
83 | { | 83 | { |
84 | findDelta(&voices[a], ch, voices[a].note); | 84 | findDelta(&voices[a], ch, voices[a].note); |
85 | } | 85 | } |
86 | } | 86 | } |
87 | } | 87 | } |
88 | 88 | ||
89 | void pressNote(int ch, int note, int vol) | 89 | void pressNote(int ch, int note, int vol) |
90 | { | 90 | { |
91 | |||
92 | //Silences all channels but one, for easy debugging, for me. | ||
91 | /* | 93 | /* |
92 | if(ch == 0) return; | 94 | if(ch == 0) return; |
93 | // if(ch == 1) return; | 95 | if(ch == 1) return; |
94 | if(ch == 2) return; | 96 | if(ch == 2) return; |
95 | if(ch == 3) return; | 97 | if(ch == 3) return; |
96 | if(ch == 4) return; | 98 | // if(ch == 4) return; |
97 | if(ch == 5) return; | 99 | if(ch == 5) return; |
98 | if(ch == 6) return; | 100 | if(ch == 6) return; |
99 | if(ch == 7) return; | 101 | if(ch == 7) return; |
100 | if(ch == 8) return; | 102 | if(ch == 8) return; |
101 | if(ch == 9) return; | 103 | if(ch == 9) return; |
102 | if(ch == 10) return; | 104 | if(ch == 10) return; |
103 | if(ch == 11) return; | 105 | if(ch == 11) return; |
104 | if(ch == 12) return; | 106 | if(ch == 12) return; |
105 | if(ch == 13) return; | 107 | if(ch == 13) return; |
106 | if(ch == 14) return; | 108 | if(ch == 14) return; |
107 | if(ch == 15) return; | 109 | if(ch == 15) return; |
108 | */ | 110 | */ |
109 | int a=0; | 111 | int a=0; |
110 | for(a=0; a<MAX_VOICES; a++) | 112 | for(a=0; a<MAX_VOICES; a++) |
111 | { | 113 | { |
112 | if(voices[a].ch == ch && voices[a].note == note) | 114 | if(voices[a].ch == ch && voices[a].note == note) |
113 | break; | 115 | break; |
114 | 116 | ||
115 | if(voices[a].isUsed==0) | 117 | if(voices[a].isUsed==0) |
116 | break; | 118 | break; |
117 | } | 119 | } |
118 | if(a==MAX_VOICES-1) | 120 | if(a==MAX_VOICES-1) |
119 | { | 121 | { |
120 | printf("\nOVERFLOW: Too many voices playing at once. No more left"); | 122 | printf("\nOVERFLOW: Too many voices playing at once. No more left"); |
121 | printf("\nVOICE DUMP: "); | 123 | printf("\nVOICE DUMP: "); |
122 | for(a=0; a<48; a++) | 124 | for(a=0; a<48; a++) |
123 | 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); | 125 | 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); |
124 | return; //None avaolable | 126 | return; /* None available */ |
125 | } | 127 | } |
126 | voices[a].ch=ch; | 128 | voices[a].ch=ch; |
127 | voices[a].note=note; | 129 | voices[a].note=note; |
128 | voices[a].vol=vol; | 130 | voices[a].vol=vol; |
129 | voices[a].cp=0; | 131 | voices[a].cp=0; |
130 | voices[a].state=STATE_ATTACK; | 132 | voices[a].state=STATE_ATTACK; |
131 | // voices[a].pstate=STATE_ATTACK; | 133 | voices[a].decay=255; |
132 | voices[a].decay=255; | 134 | |
133 | 135 | ||
134 | 136 | voices[a].loopState=STATE_NONLOOPING; | |
135 | voices[a].loopState=STATE_NONLOOPING; | 137 | voices[a].loopDir = LOOPDIR_FORWARD; |
136 | voices[a].loopDir = LOOPDIR_FORWARD; | 138 | /* |
137 | /* | 139 | * OKAY. Gt = Gus Table value |
138 | OKAY. Gt = Gus Table value | 140 | * rf = Root Frequency of wave |
139 | rf = Root Frequency of wave | 141 | * SR = sound sampling rate |
140 | SR = sound sampling rate | 142 | * sr = WAVE sampling rate |
141 | sr = WAVE sampling rate | 143 | */ |
142 | */ | 144 | |
143 | 145 | if(ch!=9) | |
144 | 146 | { | |
145 | /* | 147 | findDelta(&voices[a], ch, note); |
146 | unsigned int gt = gustable[note]; | 148 | /* Turn it on */ |
147 | unsigned int rf = wf->rootFreq; | 149 | voices[a].isUsed=1; |
148 | unsigned int SR = SAMPLE_RATE; | 150 | setPoint(&voices[a], 0); |
149 | unsigned int sr = wf->sampRate; | 151 | } else |
150 | voices[a].delta=((((gt<<10) / rf) * sr / SR)); | 152 | { |
151 | */ | 153 | if(drumSet[note]!=NULL) |
152 | 154 | { | |
153 | 155 | if(note<35) | |
154 | if(ch!=9) | 156 | printf("\nNOTE LESS THAN 35, AND A DRUM PATCH EXISTS FOR THIS? WHAT THE HELL?"); |
155 | { | 157 | |
156 | findDelta(&voices[a], ch, note); | 158 | struct GWaveform * wf = drumSet[note]->waveforms[0]; |
157 | //Turn it on | 159 | voices[a].wf=wf; |
158 | voices[a].isUsed=1; | 160 | voices[a].delta = (((gustable[note]<<10) / wf->rootFreq) * wf->sampRate / SAMPLE_RATE); |
159 | setPoint(&voices[a], 0); | 161 | if(wf->mode & 28) |
160 | } else | 162 | printf("\nWoah, a drum patch has a loop. Stripping the loop..."); |
161 | { | 163 | wf->mode = wf->mode & (255-28); |
162 | if(drumSet[note]!=NULL) | 164 | |
163 | { | 165 | /* Turn it on */ |
164 | if(note<35) | 166 | voices[a].isUsed=1; |
165 | printf("\nNOTE LESS THAN 35, AND A DRUM PATCH EXISTS FOR THIS? WHAT THE HELL?"); | 167 | setPoint(&voices[a], 0); |
166 | 168 | ||
167 | struct GWaveform * wf = drumSet[note]->waveforms[0]; | 169 | } else |
168 | voices[a].wf=wf; | 170 | { |
169 | voices[a].delta = (((gustable[note]<<10) / wf->rootFreq) * wf->sampRate / SAMPLE_RATE); | 171 | printf("\nWarning: drum %d does not have a patch defined... Ignoring it", note); |
170 | if(wf->mode & 28) | 172 | } |
171 | printf("\nWoah, a drum patch has a loop. Stripping the loop..."); | 173 | } |
172 | wf->mode = wf->mode & (255-28); | ||
173 | //Turn it on | ||
174 | voices[a].isUsed=1; | ||
175 | setPoint(&voices[a], 0); | ||
176 | |||
177 | } else | ||
178 | { | ||
179 | printf("\nWarning: drum %d does not have a patch defined... Ignoring it", note); | ||
180 | } | ||
181 | } | ||
182 | } | 174 | } |
183 | 175 | ||
184 | 176 | ||
185 | void releaseNote(int ch, int note) | 177 | void releaseNote(int ch, int note) |
186 | { | 178 | { |
187 | if(ch==9) // && note != 27 && note != 31 && note != 28) | 179 | if(ch==9) |
188 | return; | 180 | return; |
189 | int a=0; | 181 | |
190 | for(a=0; a<MAX_VOICES; a++) | 182 | int a=0; |
191 | { | 183 | for(a=0; a<MAX_VOICES; a++) |
192 | if(voices[a].ch == ch && voices[a].note == note) | 184 | { |
193 | { | 185 | if(voices[a].ch == ch && voices[a].note == note) |
194 | if((voices[a].wf->mode & 28)) | 186 | { |
195 | { | 187 | if((voices[a].wf->mode & 28)) |
196 | // voices[a].tmp=40; | 188 | { |
197 | // voices[a].state = STATE_RELEASE; //Ramp down | 189 | setPoint(&voices[a], 3); |
198 | 190 | } | |
199 | // voices[a].state = STATE_RAMPDOWN; //Ramp down | 191 | } |
200 | setPoint(&voices[a], 3); | 192 | } |
201 | } | ||
202 | } | ||
203 | } | ||
204 | } | 193 | } |
205 | 194 | ||
206 | void sendEvent(struct Event * ev) | 195 | void sendEvent(struct Event * ev) |
207 | { | 196 | { |
208 | // printf("\nEVENT S=%2x D1=%2x D2=%2x", ev->status, ev->d1, ev->d2); | 197 | if( ((ev->status & 0xF0) == MIDI_CONTROL) && (ev->d1 == CTRL_VOLUME) ) |
209 | 198 | { | |
210 | if( ((ev->status & 0xF0) == MIDI_CONTROL) && (ev->d1 == CTRL_VOLUME) ) | 199 | setVol((ev->status & 0xF), ev->d2); |
211 | { | 200 | return; |
212 | setVol((ev->status & 0xF), ev->d2); | 201 | } |
213 | return; | 202 | |
214 | } | 203 | if( ((ev->status & 0xF0) == MIDI_CONTROL) && (ev->d1 == CTRL_PANNING)) |
215 | 204 | { | |
216 | if( ((ev->status & 0xF0) == MIDI_CONTROL) && (ev->d1 == CTRL_PANNING)) | 205 | setPan((ev->status & 0xF), ev->d2); |
217 | { | 206 | return; |
218 | setPan((ev->status & 0xF), ev->d2); | 207 | } |
219 | return; | 208 | |
220 | } | 209 | if(((ev->status & 0xF0) == MIDI_PITCHW)) |
221 | 210 | { | |
222 | if(((ev->status & 0xF0) == MIDI_PITCHW)) | 211 | setPW((ev->status & 0xF), ev->d2); |
223 | { | 212 | return; |
224 | setPW((ev->status & 0xF), ev->d2); | 213 | } |
225 | return; | 214 | |
226 | } | 215 | if(((ev->status & 0xF0) == MIDI_NOTE_ON) && (ev->d2 != 0)) |
227 | 216 | { | |
228 | if(((ev->status & 0xF0) == MIDI_NOTE_ON) && (ev->d2 != 0)) | 217 | pressNote(ev->status & 0x0F, ev->d1, ev->d2); |
229 | { | 218 | return; |
230 | pressNote(ev->status & 0x0F, ev->d1, ev->d2); | 219 | } |
231 | return; | 220 | |
232 | } | 221 | if(((ev->status & 0xF0) == MIDI_NOTE_ON) && (ev->d2 == 0)) /* Release by vol=0 */ |
233 | 222 | { | |
234 | if(((ev->status & 0xF0) == MIDI_NOTE_ON) && (ev->d2 == 0)) //Release by vol=0 | 223 | releaseNote(ev->status & 0x0F, ev->d1); |
235 | { | 224 | return; |
236 | releaseNote(ev->status & 0x0F, ev->d1); | 225 | } |
237 | return; | 226 | |
238 | } | 227 | |
239 | 228 | if((ev->status & 0xF0) == MIDI_NOTE_OFF) | |
240 | 229 | { | |
241 | if((ev->status & 0xF0) == MIDI_NOTE_OFF) | 230 | releaseNote(ev->status & 0x0F, ev->d1); |
242 | { | 231 | return; |
243 | releaseNote(ev->status & 0x0F, ev->d1); | 232 | } |
244 | return; | 233 | |
245 | } | 234 | if((ev->status & 0xF0) == MIDI_PRGM) |
246 | 235 | { | |
247 | if((ev->status & 0xF0) == MIDI_PRGM) | 236 | if((ev->status & 0x0F) == 9) |
248 | { | 237 | printf("\nNOT PATCHING: Someone tried patching Channel 9 onto something?"); |
249 | if((ev->status & 0x0F) == 9) | 238 | else |
250 | printf("\nNOT PATCHING: Someone tried patching Channel 9 onto something?"); | 239 | setPatch(ev->status & 0x0F, ev->d1); |
251 | else | 240 | } |
252 | setPatch(ev->status & 0x0F, ev->d1); | ||
253 | } | ||
254 | } | 241 | } |
255 | 242 | ||
256 | 243 | ||
@@ -259,61 +246,60 @@ void sendEvent(struct Event * ev) | |||
259 | 246 | ||
260 | int tick(struct MIDIfile * mf) | 247 | int tick(struct MIDIfile * mf) |
261 | { | 248 | { |
262 | if(mf==NULL) | 249 | if(mf==NULL) |
263 | return 0; | 250 | return 0; |
264 | 251 | ||
265 | int a=0; | 252 | int a=0; |
266 | int tracksAdv=0; | 253 | int tracksAdv=0; |
267 | for(a=0; a<mf->numTracks; a++) | 254 | for(a=0; a<mf->numTracks; a++) |
268 | { | 255 | { |
269 | struct Track * tr = mf->tracks[a]; | 256 | struct Track * tr = mf->tracks[a]; |
270 | 257 | ||
271 | if(tr == NULL) | 258 | if(tr == NULL) |
272 | printf("\nNULL TRACK: %d", a); | 259 | printf("\nNULL TRACK: %d", a); |
273 | 260 | ||
274 | 261 | ||
275 | //BIG DEBUG STATEMENT | 262 | //BIG DEBUG STATEMENT |
276 | //printf("\nTrack %2d, Event = %4d of %4d, Delta = %5d, Next = %4d", a, tr->pos, tr->numEvents, tr->delta, getEvent(tr, tr->pos)->delta); | 263 | //printf("\nTrack %2d, Event = %4d of %4d, Delta = %5d, Next = %4d", a, tr->pos, tr->numEvents, tr->delta, getEvent(tr, tr->pos)->delta); |
277 | 264 | ||
278 | 265 | ||
279 | if(tr != NULL && (tr->pos < tr->numEvents)) | 266 | if(tr != NULL && (tr->pos < tr->numEvents)) |
280 | { | 267 | { |
281 | tr->delta++; | 268 | tr->delta++; |
282 | tracksAdv++; | 269 | tracksAdv++; |
283 | while(getEvent(tr, tr->pos)->delta <= tr->delta) | 270 | while(getEvent(tr, tr->pos)->delta <= tr->delta) |
284 | { | 271 | { |
285 | // printf("\nDelta = %d", tr->delta); | 272 | struct Event * e = getEvent(tr, tr->pos); |
286 | struct Event * e = getEvent(tr, tr->pos); | 273 | |
287 | 274 | if(e->status != 0xFF) | |
288 | if(e->status != 0xFF) | 275 | { |
289 | { | 276 | sendEvent(e); |
290 | sendEvent(e); | 277 | if(((e->status&0xF0) == MIDI_PRGM)) |
291 | if(((e->status&0xF0) == MIDI_PRGM)) | 278 | { |
292 | { | 279 | printf("\nPatch Event, patch[%d] ==> %d", e->status&0xF, e->d1); |
293 | printf("\nPatch Event, patch[%d] ==> %d", e->status&0xF, e->d1); | 280 | } |
294 | } | 281 | } |
295 | } | 282 | else |
296 | else | 283 | { |
297 | { | 284 | if(e->d1 == 0x51) |
298 | if(e->d1 == 0x51) | 285 | { |
299 | { | 286 | tempo = (((short)e->evData[0])<<16)|(((short)e->evData[1])<<8)|(e->evData[2]); |
300 | tempo = (((short)e->evData[0])<<16)|(((short)e->evData[1])<<8)|(e->evData[2]); | 287 | printf("\nMeta-Event: Tempo Set = %d", tempo); |
301 | printf("\nMeta-Event: Tempo Set = %d", tempo); | 288 | bpm=mf->div*1000000/tempo; |
302 | bpm=mf->div*1000000/tempo; | 289 | numberOfSamples=SAMPLE_RATE/bpm; |
303 | numberOfSamples=SAMPLE_RATE/bpm; | 290 | |
304 | 291 | } | |
305 | } | 292 | } |
306 | } | 293 | tr->delta = 0; |
307 | tr->delta = 0; | 294 | tr->pos++; |
308 | tr->pos++; | 295 | if(tr->pos>=(tr->numEvents-1)) |
309 | if(tr->pos>=(tr->numEvents-1)) | 296 | break; |
310 | break; | 297 | } |
311 | } | 298 | } |
312 | } | 299 | } |
313 | } | 300 | |
314 | 301 | if(tracksAdv != 0) | |
315 | if(tracksAdv != 0) | 302 | return 1; |
316 | return 1; | 303 | else |
317 | else | 304 | return 0; |
318 | return 0; | ||
319 | } | 305 | } |
diff --git a/apps/plugins/midi/synth.c b/apps/plugins/midi/synth.c index bafaf1c7ca..50becf32a4 100644 --- a/apps/plugins/midi/synth.c +++ b/apps/plugins/midi/synth.c | |||
@@ -20,158 +20,164 @@ extern struct plugin_api * rb; | |||
20 | 20 | ||
21 | struct Event * getEvent(struct Track * tr, int evNum) | 21 | struct Event * getEvent(struct Track * tr, int evNum) |
22 | { | 22 | { |
23 | return tr->dataBlock + (evNum*sizeof(struct Event)); | 23 | return tr->dataBlock + (evNum*sizeof(struct Event)); |
24 | } | 24 | } |
25 | 25 | ||
26 | void readTextBlock(int file, char * buf) | 26 | void readTextBlock(int file, char * buf) |
27 | { | 27 | { |
28 | char c = 0; | 28 | char c = 0; |
29 | do | 29 | do |
30 | { | 30 | { |
31 | c = readChar(file); | 31 | c = readChar(file); |
32 | } while(c == '\n' || c == ' ' || c=='\t'); | 32 | } while(c == '\n' || c == ' ' || c=='\t'); |
33 | 33 | ||
34 | rb->lseek(file, -1, SEEK_CUR); | 34 | rb->lseek(file, -1, SEEK_CUR); |
35 | int cp = 0; | 35 | int cp = 0; |
36 | do | 36 | do |
37 | { | 37 | { |
38 | c = readChar(file); | 38 | c = readChar(file); |
39 | buf[cp] = c; | 39 | buf[cp] = c; |
40 | cp++; | 40 | cp++; |
41 | } while (c != '\n' && c != ' ' && c != '\t' && !eof(file)); | 41 | } while (c != '\n' && c != ' ' && c != '\t' && !eof(file)); |
42 | buf[cp-1]=0; | 42 | buf[cp-1]=0; |
43 | rb->lseek(file, -1, SEEK_CUR); | 43 | rb->lseek(file, -1, SEEK_CUR); |
44 | } | 44 | } |
45 | 45 | ||
46 | 46 | ||
47 | 47 | ||
48 | //Filename is the name of the config file | 48 | /* Filename is the name of the config file */ |
49 | //The MIDI file should have been loaded at this point | 49 | /* The MIDI file should have been loaded at this point */ |
50 | int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig) | 50 | int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig) |
51 | { | 51 | { |
52 | char patchUsed[128]; | 52 | char patchUsed[128]; |
53 | char drumUsed[128]; | 53 | char drumUsed[128]; |
54 | int a=0; | 54 | int a=0; |
55 | for(a=0; a<MAX_VOICES; a++) | 55 | for(a=0; a<MAX_VOICES; a++) |
56 | { | 56 | { |
57 | voices[a].cp=0; | 57 | voices[a].cp=0; |
58 | voices[a].vol=0; | 58 | voices[a].vol=0; |
59 | voices[a].ch=0; | 59 | voices[a].ch=0; |
60 | voices[a].isUsed=0; | 60 | voices[a].isUsed=0; |
61 | voices[a].note=0; | 61 | voices[a].note=0; |
62 | } | 62 | } |
63 | 63 | ||
64 | for(a=0; a<16; a++) | 64 | for(a=0; a<16; a++) |
65 | { | 65 | { |
66 | chVol[a]=100; //Default, not quite full blast.. | 66 | chVol[a]=100; /* Default, not quite full blast.. */ |
67 | chPanLeft[a]=64; //Center | 67 | chPanLeft[a]=64; /* Center */ |
68 | chPanRight[a]=64; //Center | 68 | chPanRight[a]=64; /* Center */ |
69 | chPat[a]=0; //Ac Gr Piano | 69 | chPat[a]=0; /* Ac Gr Piano */ |
70 | chPW[a]=64; // .. not .. bent ? | 70 | chPW[a]=64; /* .. not .. bent ? */ |
71 | } | 71 | } |
72 | for(a=0; a<128; a++) | 72 | for(a=0; a<128; a++) |
73 | { | 73 | { |
74 | patchSet[a]=NULL; | 74 | patchSet[a]=NULL; |
75 | drumSet[a]=NULL; | 75 | drumSet[a]=NULL; |
76 | patchUsed[a]=0; | 76 | patchUsed[a]=0; |
77 | drumUsed[a]=0; | 77 | drumUsed[a]=0; |
78 | } | 78 | } |
79 | 79 | ||
80 | //Always load the piano. | 80 | /* |
81 | //Some files will assume its loaded without specifically | 81 | * Always load the piano. |
82 | //issuing a Patch command... then we wonder why we can't hear anything | 82 | * Some files will assume its loaded without specifically |
83 | patchUsed[0]=1; | 83 | * issuing a Patch command... then we wonder why we can't hear anything |
84 | 84 | */ | |
85 | //Scan the file to see what needs to be loaded | 85 | patchUsed[0]=1; |
86 | for(a=0; a<mf->numTracks; a++) | 86 | |
87 | { | 87 | /* Scan the file to see what needs to be loaded */ |
88 | int ts=0; | 88 | for(a=0; a<mf->numTracks; a++) |
89 | 89 | { | |
90 | if(mf->tracks[a] == NULL) | 90 | unsigned int ts=0; |
91 | { | 91 | |
92 | printf("\nNULL TRACK !!!"); | 92 | if(mf->tracks[a] == NULL) |
93 | rb->splash(HZ*2, true, "Null Track in loader."); | 93 | { |
94 | return -1; | 94 | printf("\nNULL TRACK !!!"); |
95 | } | 95 | rb->splash(HZ*2, true, "Null Track in loader."); |
96 | 96 | return -1; | |
97 | for(ts=0; ts<mf->tracks[a]->numEvents; ts++) | 97 | } |
98 | { | 98 | |
99 | 99 | for(ts=0; ts<mf->tracks[a]->numEvents; ts++) | |
100 | if((getEvent(mf->tracks[a], ts)->status) == (MIDI_NOTE_ON+9)) | 100 | { |
101 | drumUsed[getEvent(mf->tracks[a], ts)->d1]=1; | 101 | |
102 | 102 | if((getEvent(mf->tracks[a], ts)->status) == (MIDI_NOTE_ON+9)) | |
103 | if( (getEvent(mf->tracks[a], ts)->status & 0xF0) == MIDI_PRGM) | 103 | drumUsed[getEvent(mf->tracks[a], ts)->d1]=1; |
104 | { | 104 | |
105 | if(patchUsed[getEvent(mf->tracks[a], ts)->d1]==0) | 105 | if( (getEvent(mf->tracks[a], ts)->status & 0xF0) == MIDI_PRGM) |
106 | printf("\nI need to load patch %d.", getEvent(mf->tracks[a], ts)->d1); | 106 | { |
107 | patchUsed[getEvent(mf->tracks[a], ts)->d1]=1; | 107 | if(patchUsed[getEvent(mf->tracks[a], ts)->d1]==0) |
108 | } | 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 | } | 110 | } |
111 | 111 | } | |
112 | int file = rb->open(filename, O_RDONLY); | 112 | } |
113 | if(file == -1) | 113 | |
114 | { | 114 | int file = rb->open(filename, O_RDONLY); |
115 | rb->splash(HZ*2, true, "Bad patch config.\nDid you install the patchset?"); | 115 | if(file == -1) |
116 | return -1; | 116 | { |
117 | } | 117 | rb->splash(HZ*2, true, "Bad patch config.\nDid you install the patchset?"); |
118 | 118 | return -1; | |
119 | char name[40]; | 119 | } |
120 | char fn[40]; | 120 | |
121 | 121 | char name[40]; | |
122 | //Scan our config file and load the right patches as needed | 122 | char fn[40]; |
123 | int c = 0; | 123 | |
124 | rb->snprintf(name, 40, ""); | 124 | /* Scan our config file and load the right patches as needed */ |
125 | for(a=0; a<128; a++) | 125 | int c = 0; |
126 | { | 126 | rb->snprintf(name, 40, ""); |
127 | while(readChar(file)!=' ' && !eof(file)); | 127 | for(a=0; a<128; a++) |
128 | readTextBlock(file, name); | 128 | { |
129 | 129 | while(readChar(file)!=' ' && !eof(file)); | |
130 | rb->snprintf(fn, 40, "/.rockbox/patchset/%s.pat", name); | 130 | readTextBlock(file, name); |
131 | printf("\nLOADING: <%s> ", fn); | 131 | |
132 | 132 | rb->snprintf(fn, 40, "/.rockbox/patchset/%s.pat", name); | |
133 | if(patchUsed[a]==1) | 133 | printf("\nLOADING: <%s> ", fn); |
134 | patchSet[a]=gusload(fn); | 134 | |
135 | 135 | if(patchUsed[a]==1) | |
136 | // if(patchSet[a] == NULL) | 136 | { |
137 | // return -1; | 137 | patchSet[a]=gusload(fn); |
138 | 138 | ||
139 | while((c != '\n')) | 139 | if(patchSet[a] == NULL) /* There was an error loading it */ |
140 | c = readChar(file); | 140 | return -1; |
141 | } | 141 | } |
142 | rb->close(file); | 142 | |
143 | 143 | while((c != '\n')) | |
144 | file = rb->open(drumConfig, O_RDONLY); | 144 | c = readChar(file); |
145 | if(file == -1) | 145 | } |
146 | { | 146 | rb->close(file); |
147 | rb->splash(HZ*2, true, "Bad drum config.\nDid you install the patchset?"); | 147 | |
148 | return -1; | 148 | file = rb->open(drumConfig, O_RDONLY); |
149 | } | 149 | if(file == -1) |
150 | 150 | { | |
151 | //Scan our config file and load the drum data | 151 | rb->splash(HZ*2, true, "Bad drum config.\nDid you install the patchset?"); |
152 | int idx=0; | 152 | return -1; |
153 | char number[30]; | 153 | } |
154 | while(!eof(file)) | 154 | |
155 | { | 155 | /* Scan our config file and load the drum data */ |
156 | readTextBlock(file, number); | 156 | int idx=0; |
157 | readTextBlock(file, name); | 157 | char number[30]; |
158 | rb->snprintf(fn, 40, "/.rockbox/patchset/%s.pat", name); | 158 | while(!eof(file)) |
159 | 159 | { | |
160 | idx = rb->atoi(number); | 160 | readTextBlock(file, number); |
161 | if(idx == 0) | 161 | readTextBlock(file, name); |
162 | break; | 162 | rb->snprintf(fn, 40, "/.rockbox/patchset/%s.pat", name); |
163 | 163 | ||
164 | if(drumUsed[idx]==1) | 164 | idx = rb->atoi(number); |
165 | drumSet[idx]=gusload(fn); | 165 | if(idx == 0) |
166 | 166 | break; | |
167 | // if(drumSet[idx] == NULL) | 167 | |
168 | // return -1; | 168 | if(drumUsed[idx]==1) |
169 | 169 | { | |
170 | while((c != '\n') && (c != 255) && (!eof(file))) | 170 | drumSet[idx]=gusload(fn); |
171 | c = readChar(file); | 171 | |
172 | } | 172 | if(drumSet[idx] == NULL) /* Error loading patch */ |
173 | rb->close(file); | 173 | return -1; |
174 | return 0; | 174 | } |
175 | |||
176 | while((c != '\n') && (c != 255) && (!eof(file))) | ||
177 | c = readChar(file); | ||
178 | } | ||
179 | rb->close(file); | ||
180 | return 0; | ||
175 | } | 181 | } |
176 | 182 | ||
177 | 183 | ||
@@ -182,7 +188,7 @@ struct GWaveform * wf IDATA_ATTR; | |||
182 | int s IDATA_ATTR; | 188 | int s IDATA_ATTR; |
183 | short s1 IDATA_ATTR; | 189 | short s1 IDATA_ATTR; |
184 | short s2 IDATA_ATTR; | 190 | short s2 IDATA_ATTR; |
185 | short sample IDATA_ATTR; //For synthSample | 191 | short sample IDATA_ATTR; /* For synthSample */ |
186 | unsigned int cpShifted IDATA_ATTR; | 192 | unsigned int cpShifted IDATA_ATTR; |
187 | 193 | ||
188 | unsigned char b1 IDATA_ATTR; | 194 | unsigned char b1 IDATA_ATTR; |
@@ -191,31 +197,9 @@ unsigned char b2 IDATA_ATTR; | |||
191 | 197 | ||
192 | inline int getSample(int s) | 198 | inline int getSample(int s) |
193 | { | 199 | { |
194 | 200 | /* Sign conversion moved to guspat.c */ | |
195 | //16 bit samples | 201 | /* 8bit conversion NOT YET IMPLEMENTED in guspat.c */ |
196 | if(wf->mode&1) | 202 | return ((short *) wf->data)[s]; |
197 | { | ||
198 | |||
199 | if(s<<1 >= wf->wavSize) | ||
200 | { | ||
201 | printf("\n!!!!! %d \t %d", s<<1, wf->wavSize); | ||
202 | return 0; | ||
203 | } | ||
204 | // signed short a = ((short *)wf->data)[s]; | ||
205 | |||
206 | //Sign conversion moved into guspat.c | ||
207 | b1=wf->data[s<<1]+((wf->mode & 2) << 6); | ||
208 | b2=wf->data[(s<<1)|1]+((wf->mode & 2) << 6); | ||
209 | return (b1 | (b2<<8)) ; | ||
210 | |||
211 | //Get rid of this sometime | ||
212 | } | ||
213 | else | ||
214 | { //8-bit samples | ||
215 | //Do we even have anything 8-bit in our set? | ||
216 | int b1=wf->data[s]+((wf->mode & 2) << 6); | ||
217 | return b1<<8; | ||
218 | } | ||
219 | } | 203 | } |
220 | 204 | ||
221 | 205 | ||
@@ -223,190 +207,194 @@ inline int getSample(int s) | |||
223 | 207 | ||
224 | inline void setPoint(struct SynthObject * so, int pt) | 208 | inline void setPoint(struct SynthObject * so, int pt) |
225 | { | 209 | { |
226 | if(so->ch==9) //Drums, no ADSR | 210 | if(so->ch==9) /* Drums, no ADSR */ |
227 | { | 211 | { |
228 | so->curOffset = 1<<27; | 212 | so->curOffset = 1<<27; |
229 | so->curRate = 1; | 213 | so->curRate = 1; |
230 | return; | 214 | return; |
231 | } | 215 | } |
232 | 216 | ||
233 | if(so->wf==NULL) | 217 | if(so->wf==NULL) |
234 | { | 218 | { |
235 | printf("\nCrap... null waveform..."); | 219 | printf("\nCrap... null waveform..."); |
236 | exit(1); | 220 | exit(1); |
237 | } | 221 | } |
238 | if(so->wf->envRate==NULL) | 222 | if(so->wf->envRate==NULL) |
239 | { | 223 | { |
240 | printf("\nWaveform has no envelope set"); | 224 | printf("\nWaveform has no envelope set"); |
241 | exit(1); | 225 | exit(1); |
242 | } | 226 | } |
243 | 227 | ||
244 | so->curPoint = pt; | 228 | so->curPoint = pt; |
245 | 229 | ||
246 | int r=0; | 230 | int r=0; |
247 | int rate = so->wf->envRate[pt]; | 231 | int rate = so->wf->envRate[pt]; |
248 | 232 | ||
249 | r=3-((rate>>6) & 0x3); // Some blatant Timidity code for rate conversion... | 233 | r=3-((rate>>6) & 0x3); /* Some blatant Timidity code for rate conversion... */ |
250 | r*=3; | 234 | r*=3; |
251 | r = (rate & 0x3f) << r; | 235 | r = (rate & 0x3f) << r; |
252 | 236 | ||
253 | /* | 237 | /* |
254 | Okay. This is the rate shift. Timidity defaults to 9, and sets | 238 | * Okay. This is the rate shift. Timidity defaults to 9, and sets |
255 | it to 10 if you use the fast decay option. Slow decay sounds better | 239 | * it to 10 if you use the fast decay option. Slow decay sounds better |
256 | on some files, except on some other files... you get chords that aren't | 240 | * on some files, except on some other files... you get chords that aren't |
257 | done decaying yet.. and they dont harmonize with the next chord and it | 241 | * done decaying yet.. and they dont harmonize with the next chord and it |
258 | sounds like utter crap. Yes, even Timitidy does that. So I'm going to | 242 | * sounds like utter crap. Yes, even Timitidy does that. So I'm going to |
259 | default this to 10, and maybe later have an option to set it to 9 | 243 | * default this to 10, and maybe later have an option to set it to 9 |
260 | for longer decays. | 244 | * for longer decays. |
261 | */ | 245 | */ |
262 | so->curRate = r<<10; | 246 | so->curRate = r<<10; |
263 | 247 | ||
264 | //Do this here because the patches assume a 44100 sampling rate | 248 | /* |
265 | //We've halved our sampling rate, ergo the ADSR code will be | 249 | * Do this here because the patches assume a 44100 sampling rate |
266 | //called half the time. Ergo, double the rate to keep stuff | 250 | * We've halved our sampling rate, ergo the ADSR code will be |
267 | //sounding right. | 251 | * called half the time. Ergo, double the rate to keep stuff |
268 | so->curRate = so->curRate << 1; | 252 | * sounding right. |
269 | 253 | */ | |
270 | 254 | so->curRate = so->curRate << 1; | |
271 | so->targetOffset = so->wf->envOffset[pt]<<(20); | 255 | |
272 | if(pt==0) | 256 | |
273 | so->curOffset = 0; | 257 | so->targetOffset = so->wf->envOffset[pt]<<(20); |
258 | if(pt==0) | ||
259 | so->curOffset = 0; | ||
274 | } | 260 | } |
275 | 261 | ||
276 | 262 | ||
277 | inline void stopVoice(struct SynthObject * so) | 263 | inline void stopVoice(struct SynthObject * so) |
278 | { | 264 | { |
279 | if(so->state == STATE_RAMPDOWN) | 265 | if(so->state == STATE_RAMPDOWN) |
280 | return; | 266 | return; |
281 | so->state = STATE_RAMPDOWN; | 267 | so->state = STATE_RAMPDOWN; |
282 | so->decay = 255; | 268 | so->decay = 255; |
283 | 269 | ||
284 | } | 270 | } |
285 | 271 | ||
286 | 272 | ||
287 | inline signed short int synthVoice() | 273 | inline signed short int synthVoice() |
288 | { | 274 | { |
289 | so = &voices[currentVoice]; | 275 | so = &voices[currentVoice]; |
290 | wf = so->wf; | 276 | wf = so->wf; |
291 | 277 | ||
292 | 278 | ||
293 | if(so->state != STATE_RAMPDOWN) | 279 | if(so->state != STATE_RAMPDOWN) |
294 | { | 280 | { |
295 | so->cp += so->delta; | 281 | so->cp += so->delta; |
296 | } | 282 | } |
297 | 283 | ||
298 | cpShifted = so->cp >> 10; | 284 | cpShifted = so->cp >> 10; |
299 | 285 | ||
300 | if( (cpShifted >= (wf->wavSize>>1)) && (so->state != STATE_RAMPDOWN)) | 286 | if( (cpShifted > (wf->numSamples) && (so->state != STATE_RAMPDOWN))) |
301 | stopVoice(so); | 287 | { |
288 | stopVoice(so); | ||
289 | } | ||
302 | 290 | ||
303 | s2 = getSample((cpShifted)+1); | 291 | s2 = getSample((cpShifted)+1); |
304 | 292 | ||
305 | if((wf->mode & (LOOP_REVERSE|LOOP_PINGPONG)) && so->loopState == STATE_LOOPING && (cpShifted <= (wf->startLoop>>1))) | 293 | /* LOOP_REVERSE|LOOP_PINGPONG = 24 */ |
306 | { | 294 | if((wf->mode & (24)) && so->loopState == STATE_LOOPING && (cpShifted <= (wf->startLoop))) |
307 | if(wf->mode & LOOP_REVERSE) | 295 | { |
308 | { | 296 | if(wf->mode & LOOP_REVERSE) |
309 | so->cp = (wf->endLoop)<<9; | 297 | { |
310 | cpShifted = so->cp >> 10; | 298 | so->cp = (wf->endLoop)<<10; |
311 | s2=getSample((cpShifted)); | 299 | cpShifted = wf->endLoop; |
312 | } else | 300 | s2=getSample((cpShifted)); |
313 | { | 301 | } else |
314 | so->delta = -so->delta; | 302 | { |
315 | so->loopDir = LOOPDIR_FORWARD; | 303 | so->delta = -so->delta; |
316 | } | 304 | so->loopDir = LOOPDIR_FORWARD; |
317 | } | 305 | } |
318 | 306 | } | |
319 | if((wf->mode & 28) && (so->cp>>10 >= wf->endLoop>>1)) | 307 | |
320 | { | 308 | if((wf->mode & 28) && (cpShifted >= wf->endLoop)) |
321 | so->loopState = STATE_LOOPING; | 309 | { |
322 | if((wf->mode & (24)) == 0) | 310 | so->loopState = STATE_LOOPING; |
323 | { | 311 | if((wf->mode & (24)) == 0) |
324 | so->cp = (wf->startLoop)<<9; | 312 | { |
325 | cpShifted = so->cp >> 10; | 313 | so->cp = (wf->startLoop)<<10; |
326 | s2=getSample((cpShifted)); | 314 | cpShifted = wf->startLoop; |
327 | } else | 315 | s2=getSample((cpShifted)); |
328 | { | 316 | } else |
329 | so->delta = -so->delta; | 317 | { |
330 | so->loopDir = LOOPDIR_REVERSE; | 318 | so->delta = -so->delta; |
331 | } | 319 | so->loopDir = LOOPDIR_REVERSE; |
332 | } | 320 | } |
333 | 321 | } | |
334 | //Better, working, linear interpolation | 322 | |
335 | s1=getSample((cpShifted)); | 323 | /* Better, working, linear interpolation */ |
336 | s = s1 + ((signed)((s2 - s1) * (so->cp & 1023))>>10); | 324 | s1=getSample((cpShifted)); |
337 | 325 | s = s1 + ((signed)((s2 - s1) * (so->cp & 1023))>>10); | |
338 | 326 | ||
339 | //ADSR COMMENT WOULD GO FROM HERE......... | 327 | |
340 | 328 | /* ADSR COMMENT WOULD GO FROM HERE.........*/ | |
341 | if(so->curRate == 0) | 329 | |
342 | stopVoice(so); | 330 | if(so->curRate == 0) |
343 | 331 | stopVoice(so); | |
344 | 332 | ||
345 | if(so->ch != 9) //Stupid ADSR code... and don't do ADSR for drums | 333 | |
346 | { | 334 | if(so->ch != 9) /* Stupid ADSR code... and don't do ADSR for drums */ |
347 | if(so->curOffset < so->targetOffset) | 335 | { |
348 | { | 336 | if(so->curOffset < so->targetOffset) |
349 | so->curOffset += (so->curRate); | 337 | { |
350 | if(so -> curOffset > so->targetOffset && so->curPoint != 2) | 338 | so->curOffset += (so->curRate); |
351 | { | 339 | if(so -> curOffset > so->targetOffset && so->curPoint != 2) |
352 | if(so->curPoint != 5) | 340 | { |
353 | setPoint(so, so->curPoint+1); | 341 | if(so->curPoint != 5) |
354 | else | 342 | setPoint(so, so->curPoint+1); |
355 | stopVoice(so); | 343 | else |
356 | } | 344 | stopVoice(so); |
357 | } else | 345 | } |
358 | { | 346 | } else |
359 | so->curOffset -= (so->curRate); | 347 | { |
360 | if(so -> curOffset < so->targetOffset && so->curPoint != 2) | 348 | so->curOffset -= (so->curRate); |
361 | { | 349 | if(so -> curOffset < so->targetOffset && so->curPoint != 2) |
362 | 350 | { | |
363 | if(so->curPoint != 5) | 351 | |
364 | setPoint(so, so->curPoint+1); | 352 | if(so->curPoint != 5) |
365 | else | 353 | setPoint(so, so->curPoint+1); |
366 | stopVoice(so); | 354 | else |
367 | 355 | stopVoice(so); | |
368 | } | 356 | |
369 | } | 357 | } |
370 | } | 358 | } |
371 | 359 | } | |
372 | if(so->curOffset < 0) | 360 | |
373 | so->isUsed=0; //This is OK | 361 | if(so->curOffset < 0) |
374 | 362 | so->isUsed=0; /* This is OK because offset faded it out already */ | |
375 | 363 | ||
376 | s = (s * (so->curOffset >> 22) >> 6); | 364 | |
377 | 365 | s = (s * (so->curOffset >> 22) >> 8); | |
378 | // ............. TO HERE | 366 | |
379 | 367 | /* ............. TO HERE */ | |
380 | 368 | ||
381 | if(so->state == STATE_RAMPDOWN) | 369 | |
382 | { | 370 | if(so->state == STATE_RAMPDOWN) |
383 | so->decay--; | 371 | { |
384 | if(so->decay == 0) | 372 | so->decay--; |
385 | so->isUsed=0; | 373 | if(so->decay == 0) |
386 | } | 374 | so->isUsed=0; |
387 | 375 | s = (s * so->decay) >> 8; | |
388 | s = s * so->decay; s = s >> 10; | 376 | } |
389 | 377 | ||
390 | return s*((signed short int)so->vol*(signed short int)chVol[so->ch])>>14; | 378 | return s*((signed short int)so->vol*(signed short int)chVol[so->ch])>>14; |
391 | } | 379 | } |
392 | 380 | ||
393 | 381 | ||
394 | inline void synthSample(int * mixL, int * mixR) | 382 | inline void synthSample(int * mixL, int * mixR) |
395 | { | 383 | { |
396 | // signed int leftMix=0, rightMix=0, | 384 | *mixL = 0; |
397 | *mixL = 0; | 385 | *mixR = 0; |
398 | *mixR = 0; | 386 | for(currentVoice=0; currentVoice<MAX_VOICES; currentVoice++) |
399 | for(currentVoice=0; currentVoice<MAX_VOICES; currentVoice++) | 387 | { |
400 | { | 388 | if(voices[currentVoice].isUsed==1) |
401 | if(voices[currentVoice].isUsed==1) | 389 | { |
402 | { | 390 | sample = synthVoice(currentVoice); |
403 | sample = synthVoice(currentVoice); | 391 | *mixL += (sample*chPanLeft[voices[currentVoice].ch])>>7; |
404 | *mixL += (sample*chPanLeft[voices[currentVoice].ch])>>7; | 392 | *mixR += (sample*chPanRight[voices[currentVoice].ch])>>7; |
405 | *mixR += (sample*chPanRight[voices[currentVoice].ch])>>7; | 393 | } |
406 | } | 394 | } |
407 | } | 395 | |
408 | 396 | /* TODO: Automatic Gain Control, anyone? */ | |
409 | //TODO: Automatic Gain Control, anyone? | 397 | /* Or, should this be implemented on the DSP's output volume instead? */ |
410 | //Or, should this be implemented on the DSP's output volume instead? | 398 | |
411 | return; //No more ghetto lowpass filter.. linear intrpolation works well. | 399 | return; /* No more ghetto lowpass filter.. linear intrpolation works well. */ |
412 | } | 400 | } |
diff --git a/apps/plugins/midi2wav.c b/apps/plugins/midi2wav.c index 6dc7a626b5..241d56defb 100644 --- a/apps/plugins/midi2wav.c +++ b/apps/plugins/midi2wav.c | |||
@@ -20,21 +20,22 @@ | |||
20 | #define MAX_VOICES 100 | 20 | #define MAX_VOICES 100 |
21 | 21 | ||
22 | 22 | ||
23 | //Only define LOCAL_DSP on Simulator or else we're asking for trouble | 23 | /* Only define LOCAL_DSP on Simulator or else we're asking for trouble */ |
24 | #if defined(SIMULATOR) | 24 | #if defined(SIMULATOR) |
25 | //Enable this to write to the soundcard via a /dsv/dsp symlink in / | 25 | /*Enable this to write to the soundcard via a /dsv/dsp symlink in */ |
26 | // #define LOCAL_DSP | 26 | // #define LOCAL_DSP |
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | 29 | ||
30 | #if defined(LOCAL_DSP) | 30 | #if defined(LOCAL_DSP) |
31 | // This is for writing to the DSP directly from the Simulator | 31 | /* This is for writing to the DSP directly from the Simulator */ |
32 | #include <stdio.h> | 32 | #include <stdio.h> |
33 | #include <stdlib.h> | 33 | #include <stdlib.h> |
34 | #include <linux/soundcard.h> | 34 | #include <linux/soundcard.h> |
35 | #include <sys/ioctl.h> | 35 | #include <sys/ioctl.h> |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | #include "../../firmware/export/system.h" | ||
38 | 39 | ||
39 | #include "../../plugin.h" | 40 | #include "../../plugin.h" |
40 | 41 | ||
@@ -53,9 +54,9 @@ long bpm; | |||
53 | 54 | ||
54 | 55 | ||
55 | 56 | ||
56 | int fd=-1; //File descriptor where the output is written | 57 | int fd=-1; /* File descriptor where the output is written */ |
57 | 58 | ||
58 | extern long tempo; //The sequencer keeps track of this | 59 | extern long tempo; /* The sequencer keeps track of this */ |
59 | 60 | ||
60 | 61 | ||
61 | struct plugin_api * rb; | 62 | struct plugin_api * rb; |
@@ -66,27 +67,28 @@ struct plugin_api * rb; | |||
66 | 67 | ||
67 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | 68 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) |
68 | { | 69 | { |
69 | TEST_PLUGIN_API(api); | 70 | TEST_PLUGIN_API(api); |
70 | rb = api; | 71 | rb = api; |
71 | TEST_PLUGIN_API(api); | 72 | TEST_PLUGIN_API(api); |
72 | (void)parameter; | 73 | (void)parameter; |
73 | rb = api; | 74 | rb = api; |
74 | 75 | ||
75 | if(parameter == NULL) | 76 | if(parameter == NULL) |
76 | { | 77 | { |
77 | rb->splash(HZ*2, true, " Play .MID file "); | 78 | rb->splash(HZ*2, true, " Play .MID file "); |
78 | return PLUGIN_OK; | 79 | return PLUGIN_OK; |
79 | } | 80 | } |
80 | rb->splash(HZ, true, parameter); | 81 | |
81 | if(midimain(parameter) == -1) | 82 | rb->splash(HZ, true, parameter); |
82 | { | 83 | if(midimain(parameter) == -1) |
83 | return PLUGIN_ERROR; | 84 | { |
84 | } | 85 | return PLUGIN_ERROR; |
85 | rb->splash(HZ*3, true, "FINISHED PLAYING"); | 86 | } |
86 | return PLUGIN_OK; | 87 | rb->splash(HZ*3, true, "FINISHED PLAYING"); |
88 | return PLUGIN_OK; | ||
87 | } | 89 | } |
88 | 90 | ||
89 | signed char outputBuffer[3000] IDATA_ATTR; //signed char.. gonna run out of iram ... ! | 91 | signed char outputBuffer[3000] IDATA_ATTR; /* signed char.. gonna run out of iram ... ! */ |
90 | 92 | ||
91 | 93 | ||
92 | int currentSample IDATA_ATTR; | 94 | int currentSample IDATA_ATTR; |
@@ -98,132 +100,133 @@ int outputSampleTwo IDATA_ATTR; | |||
98 | int midimain(void * filename) | 100 | int midimain(void * filename) |
99 | { | 101 | { |
100 | 102 | ||
101 | printf("\nHello.\n"); | 103 | printf("\nHello.\n"); |
102 | 104 | ||
103 | rb->splash(HZ/5, true, "LOADING MIDI"); | 105 | rb->splash(HZ/5, true, "LOADING MIDI"); |
104 | 106 | ||
105 | struct MIDIfile * mf = loadFile(filename); | 107 | struct MIDIfile * mf = loadFile(filename); |
106 | 108 | ||
107 | rb->splash(HZ/5, true, "LOADING PATCHES"); | 109 | rb->splash(HZ/5, true, "LOADING PATCHES"); |
108 | if (initSynth(mf, "/.rockbox/patchset/patchset.cfg", "/.rockbox/patchset/drums.cfg") == -1) | 110 | if (initSynth(mf, "/.rockbox/patchset/patchset.cfg", "/.rockbox/patchset/drums.cfg") == -1) |
109 | { | 111 | { |
110 | return -1; | 112 | return -1; |
111 | } | 113 | } |
112 | 114 | ||
113 | //This lets you hear the music through the sound card if you are on Simulator | 115 | /* |
114 | //Make a symlink, archos/dsp.raw and make it point to /dev/dsp or whatever | 116 | * This lets you hear the music through the sound card if you are on Simulator |
115 | //your sound device is. | 117 | * Make a symlink, archos/dsp.raw and make it point to /dev/dsp or whatever |
118 | * your sound device is. | ||
119 | */ | ||
116 | 120 | ||
117 | #if defined(LOCAL_DSP) | 121 | #if defined(LOCAL_DSP) |
118 | fd=rb->open("/dsp.raw", O_WRONLY); | 122 | fd=rb->open("/dsp.raw", O_WRONLY); |
119 | int arg, status; | 123 | int arg, status; |
120 | int bit, samp, ch; | 124 | int bit, samp, ch; |
121 | 125 | ||
122 | arg = 16; // sample size | 126 | arg = 16; /* sample size */ |
123 | status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg); | 127 | status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg); |
124 | status = ioctl(fd, SOUND_PCM_READ_BITS, &arg); | 128 | status = ioctl(fd, SOUND_PCM_READ_BITS, &arg); |
125 | bit=arg; | 129 | bit=arg; |
126 | 130 | ||
127 | 131 | ||
128 | arg = 2; //Number of channels, 1=mono | 132 | arg = 2; /* Number of channels, 1=mono */ |
129 | status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg); | 133 | status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg); |
130 | status = ioctl(fd, SOUND_PCM_READ_CHANNELS, &arg); | 134 | status = ioctl(fd, SOUND_PCM_READ_CHANNELS, &arg); |
131 | ch=arg; | 135 | ch=arg; |
132 | 136 | ||
133 | arg = SAMPLE_RATE; //Yeah. sampling rate | 137 | arg = SAMPLE_RATE; /* Yeah. sampling rate */ |
134 | status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg); | 138 | status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg); |
135 | status = ioctl(fd, SOUND_PCM_READ_RATE, &arg); | 139 | status = ioctl(fd, SOUND_PCM_READ_RATE, &arg); |
136 | samp=arg; | 140 | samp=arg; |
137 | #else | 141 | #else |
138 | file_info_struct file_info; | 142 | file_info_struct file_info; |
139 | file_info.samplerate = SAMPLE_RATE; | 143 | file_info.samplerate = SAMPLE_RATE; |
140 | file_info.infile = fd; | 144 | file_info.infile = fd; |
141 | file_info.channels = 2; | 145 | file_info.channels = 2; |
142 | file_info.bitspersample = 16; | 146 | file_info.bitspersample = 16; |
143 | local_init("/miditest.tmp", "/miditest.wav", &file_info, rb); | 147 | local_init("/miditest.tmp", "/miditest.wav", &file_info, rb); |
144 | fd = file_info.outfile; | 148 | fd = file_info.outfile; |
145 | #endif | 149 | #endif |
146 | 150 | ||
147 | 151 | ||
148 | rb->splash(HZ/5, true, " Starting Playback "); | 152 | rb->splash(HZ/5, true, " I hope this works... "); |
149 | 153 | ||
150 | 154 | ||
151 | 155 | ||
152 | 156 | ||
157 | /* | ||
158 | * tick() will do one MIDI clock tick. Then, there's a loop here that | ||
159 | * will generate the right number of samples per MIDI tick. The whole | ||
160 | * MIDI playback is timed in terms of this value.. there are no forced | ||
161 | * delays or anything. It just produces enough samples for each tick, and | ||
162 | * the playback of these samples is what makes the timings right. | ||
163 | * | ||
164 | * This seems to work quite well. | ||
165 | */ | ||
153 | 166 | ||
154 | // tick() will do one MIDI clock tick. Then, there's a loop here that | 167 | printf("\nOkay, starting sequencing"); |
155 | // will generate the right number of samples per MIDI tick. The whole | ||
156 | // MIDI playback is timed in terms of this value.. there are no forced | ||
157 | // delays or anything. It just produces enough samples for each tick, and | ||
158 | // the playback of these samples is what makes the timings right. | ||
159 | // | ||
160 | // This seems to work quite well. | ||
161 | 168 | ||
162 | 169 | ||
163 | printf("\nOkay, starting sequencing"); | 170 | currentSample=0; /* Sample counting variable */ |
171 | outputBufferPosition = 0; | ||
164 | 172 | ||
165 | 173 | ||
166 | currentSample=0; //Sample counting variable | 174 | bpm=mf->div*1000000/tempo; |
167 | outputBufferPosition = 0; | 175 | numberOfSamples=SAMPLE_RATE/bpm; |
168 | 176 | ||
169 | 177 | ||
170 | bpm=mf->div*1000000/tempo; | ||
171 | numberOfSamples=SAMPLE_RATE/bpm; | ||
172 | 178 | ||
179 | /* Tick() will return 0 if there are no more events left to play */ | ||
180 | while(tick(mf)) | ||
181 | { | ||
182 | /* | ||
183 | * Tempo recalculation moved to sequencer.c to be done on a tempo event only | ||
184 | * | ||
185 | */ | ||
186 | for(currentSample=0; currentSample<numberOfSamples; currentSample++) | ||
187 | { | ||
173 | 188 | ||
189 | synthSample(&outputSampleOne, &outputSampleTwo); | ||
174 | 190 | ||
175 | //Tick() will return 0 if there are no more events left to play | ||
176 | while(tick(mf)) | ||
177 | { | ||
178 | 191 | ||
179 | //Some annoying math to compute the number of samples | 192 | /* |
180 | //to syntehsize per each MIDI tick. | 193 | * 16-bit audio because, well, it's better |
194 | * But really because ALSA's OSS emulation sounds extremely | ||
195 | * noisy and distorted when in 8-bit mode. I still do not know | ||
196 | * why this happens. | ||
197 | */ | ||
181 | 198 | ||
182 | //Yes we need to do this math each time because the tempo | 199 | outputBuffer[outputBufferPosition]=outputSampleOne&0XFF; // Low byte first |
183 | //could have changed. | 200 | outputBufferPosition++; |
201 | outputBuffer[outputBufferPosition]=outputSampleOne>>8; //High byte second | ||
202 | outputBufferPosition++; | ||
184 | 203 | ||
185 | // On second thought, this can be moved to the event that | 204 | outputBuffer[outputBufferPosition]=outputSampleTwo&0XFF; // Low byte first |
186 | //recalculates the tempo, to save a little bit of CPU time. | 205 | outputBufferPosition++; |
187 | for(currentSample=0; currentSample<numberOfSamples; currentSample++) | 206 | outputBuffer[outputBufferPosition]=outputSampleTwo>>8; //High byte second |
188 | { | 207 | outputBufferPosition++; |
189 | 208 | ||
190 | synthSample(&outputSampleOne, &outputSampleTwo); | ||
191 | 209 | ||
210 | /* | ||
211 | * As soon as we produce 2000 bytes of sound, | ||
212 | * write it to the sound card. Why 2000? I have | ||
213 | * no idea. It's 1 AM and I am dead tired. | ||
214 | */ | ||
215 | if(outputBufferPosition>=2000) | ||
216 | { | ||
217 | rb->write(fd, outputBuffer, 2000); | ||
218 | outputBufferPosition=0; | ||
219 | } | ||
220 | } | ||
221 | } | ||
192 | 222 | ||
193 | //16-bit audio because, well, it's better | 223 | printf("\n"); |
194 | // But really because ALSA's OSS emulation sounds extremely | ||
195 | //noisy and distorted when in 8-bit mode. I still do not know | ||
196 | //why this happens. | ||
197 | outputBuffer[outputBufferPosition]=outputSampleOne&0XFF; // Low byte first | ||
198 | outputBufferPosition++; | ||
199 | outputBuffer[outputBufferPosition]=outputSampleOne>>8; //High byte second | ||
200 | outputBufferPosition++; | ||
201 | |||
202 | outputBuffer[outputBufferPosition]=outputSampleTwo&0XFF; // Low byte first | ||
203 | outputBufferPosition++; | ||
204 | outputBuffer[outputBufferPosition]=outputSampleTwo>>8; //High byte second | ||
205 | outputBufferPosition++; | ||
206 | |||
207 | |||
208 | //As soon as we produce 2000 bytes of sound, | ||
209 | //write it to the sound card. Why 2000? I have | ||
210 | //no idea. It's 1 AM and I am dead tired. | ||
211 | if(outputBufferPosition>=2000) | ||
212 | { | ||
213 | rb->write(fd, outputBuffer, 2000); | ||
214 | outputBufferPosition=0; | ||
215 | } | ||
216 | } | ||
217 | } | ||
218 | |||
219 | // unloadFile(mf); | ||
220 | printf("\n"); | ||
221 | 224 | ||
222 | #if !defined(LOCAL_DSP) | 225 | #if !defined(LOCAL_DSP) |
223 | 226 | ||
224 | close_wav(&file_info); | 227 | close_wav(&file_info); |
225 | #else | 228 | #else |
226 | rb->close(fd); | 229 | rb->close(fd); |
227 | #endif | 230 | #endif |
228 | return 0; | 231 | return 0; |
229 | } | 232 | } |