diff options
-rw-r--r-- | apps/plugins/midi/guspat.c | 52 | ||||
-rw-r--r-- | apps/plugins/midi/guspat.h | 1 | ||||
-rw-r--r-- | apps/plugins/midi/midiutil.c | 132 | ||||
-rw-r--r-- | apps/plugins/midi/sequencer.c | 31 | ||||
-rw-r--r-- | apps/plugins/midi/synth.c | 158 | ||||
-rw-r--r-- | apps/plugins/midi2wav.c | 65 |
6 files changed, 238 insertions, 201 deletions
diff --git a/apps/plugins/midi/guspat.c b/apps/plugins/midi/guspat.c index f674b64caa..2172072eb1 100644 --- a/apps/plugins/midi/guspat.c +++ b/apps/plugins/midi/guspat.c | |||
@@ -66,18 +66,64 @@ struct GWaveform * loadWaveform(int file) | |||
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 | int a=0; | 70 | int a=0; |
70 | 71 | ||
72 | return wav; | ||
73 | if(wav->mode & 1 == 0) //Whoops, 8 bit | ||
74 | { | ||
75 | wav->numSamples = wav->wavSize; | ||
76 | |||
77 | //Allocate a block for the rest of it | ||
78 | //It should end up right after the previous one. | ||
79 | wav->wavSize = wav->wavSize * 2; | ||
80 | void * foo = allocate(wav->wavSize); | ||
81 | |||
82 | |||
83 | for(a=0; a<1000; a++) | ||
84 | printf("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); | ||
85 | |||
86 | |||
87 | for(a=wav->wavSize-1; a>0; a-=2) | ||
88 | { | ||
89 | |||
90 | } | ||
91 | // int b1=wf->data[s]+((wf->mode & 2) << 6); | ||
92 | // return b1<<8; | ||
93 | } | ||
94 | |||
95 | /* | ||
96 | //#if !defined(SIMULATOR) | ||
97 | for(a=0; a<wav->wavSize; a+=2) | ||
98 | { | ||
99 | unsigned char tmp; | ||
100 | tmp = wav->data[2*a]; | ||
101 | wav->data[2*a] = wav->data[2*a+1]; | ||
102 | wav->data[2*a+1] = tmp; | ||
103 | } | ||
104 | //#endif | ||
105 | |||
106 | if(wav->mode & 2) | ||
107 | { | ||
108 | for(a=0; a<wav->wavSize/2; a++) | ||
109 | { | ||
110 | ((short *) wav->data)[a] = ((short *) wav->data)[a] - 32767; | ||
111 | } | ||
112 | } | ||
113 | */ | ||
114 | |||
115 | |||
116 | |||
71 | //If we have a 16 bit waveform | 117 | //If we have a 16 bit waveform |
72 | if(wav->mode & 1 && (wav->mode & 2)) | 118 | /* if(wav->mode & 1 && (wav->mode & 2)) |
73 | { | 119 | { |
74 | for(a=0; a<wav->wavSize; a+=2) //Convert it to | 120 | for(a=0; a<wav->wavSize; a+=2) //Convert it to |
75 | { | 121 | { |
76 | //wav->data[a]=wav->data[a]; //+((wav->mode & 2) << 6); | 122 | wav->data[a]=wav->data[a]+(1 << 7); |
77 | wav->data[a|1]=wav->data[(a)|1]+(1 << 7); | 123 | wav->data[a|1]=wav->data[(a)|1]+(1 << 7); |
78 | } | 124 | } |
79 | } | 125 | } |
80 | 126 | */ | |
81 | return wav; | 127 | return wav; |
82 | } | 128 | } |
83 | 129 | ||
diff --git a/apps/plugins/midi/guspat.h b/apps/plugins/midi/guspat.h index 75bdb2ca01..6e41a85d23 100644 --- a/apps/plugins/midi/guspat.h +++ b/apps/plugins/midi/guspat.h | |||
@@ -36,6 +36,7 @@ struct GWaveform | |||
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 startLoop; | 40 | unsigned int startLoop; |
40 | unsigned int endLoop; | 41 | unsigned int endLoop; |
41 | unsigned int sampRate; | 42 | unsigned int sampRate; |
diff --git a/apps/plugins/midi/midiutil.c b/apps/plugins/midi/midiutil.c index 41a02ae682..bf25d1d277 100644 --- a/apps/plugins/midi/midiutil.c +++ b/apps/plugins/midi/midiutil.c | |||
@@ -63,33 +63,26 @@ | |||
63 | extern struct plugin_api * rb; | 63 | extern struct plugin_api * rb; |
64 | 64 | ||
65 | 65 | ||
66 | int chVol[16] IDATA_ATTR; //Channel volume | ||
67 | int chPanLeft[16] IDATA_ATTR; //Channel panning | ||
68 | int chPanRight[16] IDATA_ATTR; | ||
69 | int chPat[16]; //Channel patch | ||
70 | int chPW[16]; //Channel pitch wheel, MSB only | ||
71 | |||
72 | |||
73 | /* | ||
66 | unsigned char chVol[16]; //Channel volume | 74 | unsigned char chVol[16]; //Channel volume |
67 | unsigned char chPanLeft[16]; //Channel panning | 75 | unsigned char chPanLeft[16]; //Channel panning |
68 | unsigned char chPanRight[16]; | 76 | unsigned char chPanRight[16]; |
69 | unsigned char chPat[16]; //Channel patch | 77 | unsigned char chPat[16]; //Channel patch |
70 | unsigned char chPW[16]; //Channel pitch wheel, MSB only | 78 | unsigned char chPW[16]; //Channel pitch wheel, MSB only |
71 | 79 | */ | |
72 | |||
73 | struct GPatch * gusload(char *); | 80 | struct GPatch * gusload(char *); |
74 | struct GPatch * patchSet[128]; | 81 | struct GPatch * patchSet[128]; |
75 | struct GPatch * drumSet[128]; | 82 | struct GPatch * drumSet[128]; |
76 | struct SynthObject voices[MAX_VOICES]; | ||
77 | 83 | ||
78 | 84 | ||
79 | 85 | //char myarray[80] IDATA_ATTR; | |
80 | struct SynthObject | ||
81 | { | ||
82 | int tmp; | ||
83 | struct GWaveform * wf; | ||
84 | unsigned int delta; | ||
85 | unsigned int decay; | ||
86 | unsigned int cp; | ||
87 | unsigned char state, pstate, loopState, loopDir; | ||
88 | unsigned char note, vol, ch, isUsed; | ||
89 | int curRate, curOffset, targetOffset; | ||
90 | int curPoint; | ||
91 | }; | ||
92 | |||
93 | 86 | ||
94 | struct Event | 87 | struct Event |
95 | { | 88 | { |
@@ -120,6 +113,34 @@ struct MIDIfile | |||
120 | unsigned char patches[128]; | 113 | unsigned char patches[128]; |
121 | int numPatches; | 114 | int numPatches; |
122 | }; | 115 | }; |
116 | /* | ||
117 | struct SynthObject | ||
118 | { | ||
119 | // int tmp; | ||
120 | struct GWaveform * wf; | ||
121 | unsigned int delta; | ||
122 | unsigned int decay; | ||
123 | unsigned int cp; | ||
124 | unsigned char state, loopState, loopDir; | ||
125 | unsigned char note, vol, ch, isUsed; | ||
126 | int curRate, curOffset, targetOffset; | ||
127 | unsigned int curPoint; | ||
128 | }; | ||
129 | */ | ||
130 | struct SynthObject | ||
131 | { | ||
132 | // int tmp; | ||
133 | struct GWaveform * wf; | ||
134 | int delta; | ||
135 | int decay; | ||
136 | int cp; | ||
137 | int state, loopState, loopDir; | ||
138 | int note, vol, ch, isUsed; | ||
139 | int curRate, curOffset, targetOffset; | ||
140 | int curPoint; | ||
141 | }; | ||
142 | |||
143 | struct SynthObject voices[MAX_VOICES] IDATA_ATTR; | ||
123 | 144 | ||
124 | 145 | ||
125 | 146 | ||
@@ -133,13 +154,16 @@ int readVarData(int file); | |||
133 | int midimain(void * filename); | 154 | int midimain(void * filename); |
134 | 155 | ||
135 | 156 | ||
136 | //Rick's code | ||
137 | void *alloc(int size) | 157 | void *alloc(int size) |
138 | { | 158 | { |
139 | static char *offset = NULL; | 159 | static char *offset = NULL; |
140 | static int totalSize = 0; | 160 | static int totalSize = 0; |
141 | char *ret; | 161 | char *ret; |
142 | 162 | ||
163 | int remainder = size % 4; | ||
164 | |||
165 | size = size + 4-remainder; | ||
166 | |||
143 | if (offset == NULL) | 167 | if (offset == NULL) |
144 | { | 168 | { |
145 | offset = rb->plugin_get_audio_buffer(&totalSize); | 169 | offset = rb->plugin_get_audio_buffer(&totalSize); |
@@ -157,40 +181,34 @@ void *alloc(int size) | |||
157 | totalSize -= size + 4; | 181 | totalSize -= size + 4; |
158 | return ret; | 182 | return ret; |
159 | } | 183 | } |
184 | |||
185 | |||
186 | //Rick's code | ||
160 | /* | 187 | /* |
161 | void *ralloc(char *offset, int len) | 188 | void *alloc(int size) |
162 | { | 189 | { |
163 | int size; | 190 | static char *offset = NULL; |
191 | static int totalSize = 0; | ||
164 | char *ret; | 192 | char *ret; |
165 | 193 | ||
194 | |||
166 | if (offset == NULL) | 195 | if (offset == NULL) |
167 | { | 196 | { |
168 | return alloc(len); | 197 | offset = rb->plugin_get_audio_buffer(&totalSize); |
169 | } | 198 | } |
170 | 199 | ||
171 | size = *((unsigned int *)offset - 4); | 200 | if (size + 4 > totalSize) |
172 | |||
173 | if (size >= 0x02000000) | ||
174 | { | 201 | { |
175 | return NULL; | 202 | return NULL; |
176 | } | 203 | } |
177 | 204 | ||
178 | ret = alloc(len); | 205 | ret = offset + 4; |
179 | 206 | *((unsigned int *)offset) = size; | |
180 | if (len < size) | ||
181 | { | ||
182 | rb->memcpy(ret, offset, len); | ||
183 | } | ||
184 | else | ||
185 | { | ||
186 | rb->memcpy(ret, offset, size); | ||
187 | rb->memset(ret, 0, len - size); | ||
188 | } | ||
189 | 207 | ||
208 | offset += size + 4; | ||
209 | totalSize -= size + 4; | ||
190 | return ret; | 210 | return ret; |
191 | } | 211 | }*/ |
192 | */ | ||
193 | |||
194 | void * allocate(int size) | 212 | void * allocate(int size) |
195 | { | 213 | { |
196 | return alloc(size); | 214 | return alloc(size); |
@@ -222,44 +240,6 @@ int eof(int fd) | |||
222 | 240 | ||
223 | void printf(char *fmt, ...) {fmt=fmt; } | 241 | void printf(char *fmt, ...) {fmt=fmt; } |
224 | 242 | ||
225 | /* | ||
226 | void *audio_bufferbase; | ||
227 | void *audio_bufferpointer; | ||
228 | unsigned int audio_buffer_free; | ||
229 | |||
230 | |||
231 | |||
232 | |||
233 | void *my_malloc(int size) | ||
234 | { | ||
235 | |||
236 | void *alloc; | ||
237 | |||
238 | if (!audio_bufferbase) | ||
239 | { | ||
240 | audio_bufferbase = audio_bufferpointer | ||
241 | = rb->plugin_get_audio_buffer(&audio_buffer_free); | ||
242 | #if MEM <= 8 && !defined(SIMULATOR) | ||
243 | |||
244 | if ((unsigned)(ovl_start_addr - (unsigned char *)audio_bufferbase) | ||
245 | < audio_buffer_free) | ||
246 | audio_buffer_free = ovl_start_addr - (unsigned char *)audio_bufferbase; | ||
247 | #endif | ||
248 | } | ||
249 | if (size + 4 > audio_buffer_free) | ||
250 | return 0; | ||
251 | alloc = audio_bufferpointer; | ||
252 | audio_bufferpointer += size + 4; | ||
253 | audio_buffer_free -= size + 4; | ||
254 | return alloc; | ||
255 | } | ||
256 | |||
257 | void setmallocpos(void *pointer) | ||
258 | { | ||
259 | audio_bufferpointer = pointer; | ||
260 | audio_buffer_free = audio_bufferpointer - audio_bufferbase; | ||
261 | } | ||
262 | */ | ||
263 | void exit(int code) | 243 | void exit(int code) |
264 | { | 244 | { |
265 | code = code; //Stub function, kill warning for now | 245 | code = code; //Stub function, kill warning for now |
diff --git a/apps/plugins/midi/sequencer.c b/apps/plugins/midi/sequencer.c index f7c6f30376..836866a5df 100644 --- a/apps/plugins/midi/sequencer.c +++ b/apps/plugins/midi/sequencer.c | |||
@@ -88,9 +88,30 @@ void setPW(int ch, int msb) | |||
88 | 88 | ||
89 | void pressNote(int ch, int note, int vol) | 89 | void pressNote(int ch, int note, int vol) |
90 | { | 90 | { |
91 | /* | ||
92 | if(ch == 0) return; | ||
93 | // if(ch == 1) return; | ||
94 | if(ch == 2) return; | ||
95 | if(ch == 3) return; | ||
96 | if(ch == 4) return; | ||
97 | if(ch == 5) return; | ||
98 | if(ch == 6) return; | ||
99 | if(ch == 7) return; | ||
100 | if(ch == 8) return; | ||
101 | if(ch == 9) return; | ||
102 | if(ch == 10) return; | ||
103 | if(ch == 11) return; | ||
104 | if(ch == 12) return; | ||
105 | if(ch == 13) return; | ||
106 | if(ch == 14) return; | ||
107 | if(ch == 15) return; | ||
108 | */ | ||
91 | int a=0; | 109 | int a=0; |
92 | for(a=0; a<MAX_VOICES; a++) | 110 | for(a=0; a<MAX_VOICES; a++) |
93 | { | 111 | { |
112 | if(voices[a].ch == ch && voices[a].note == note) | ||
113 | break; | ||
114 | |||
94 | if(voices[a].isUsed==0) | 115 | if(voices[a].isUsed==0) |
95 | break; | 116 | break; |
96 | } | 117 | } |
@@ -107,7 +128,7 @@ void pressNote(int ch, int note, int vol) | |||
107 | voices[a].vol=vol; | 128 | voices[a].vol=vol; |
108 | voices[a].cp=0; | 129 | voices[a].cp=0; |
109 | voices[a].state=STATE_ATTACK; | 130 | voices[a].state=STATE_ATTACK; |
110 | voices[a].pstate=STATE_ATTACK; | 131 | // voices[a].pstate=STATE_ATTACK; |
111 | voices[a].decay=255; | 132 | voices[a].decay=255; |
112 | 133 | ||
113 | 134 | ||
@@ -170,15 +191,12 @@ void releaseNote(int ch, int note) | |||
170 | { | 191 | { |
171 | if(voices[a].ch == ch && voices[a].note == note) | 192 | if(voices[a].ch == ch && voices[a].note == note) |
172 | { | 193 | { |
173 | //voices[a].isUsed=0; | ||
174 | if((voices[a].wf->mode & 28)) | 194 | if((voices[a].wf->mode & 28)) |
175 | { | 195 | { |
176 | voices[a].tmp=40; | 196 | // voices[a].tmp=40; |
177 | // voices[a].state = STATE_RELEASE; //Ramp down | 197 | // voices[a].state = STATE_RELEASE; //Ramp down |
178 | 198 | ||
179 | // voices[a].state = STATE_RAMPDOWN; //Ramp down | 199 | // voices[a].state = STATE_RAMPDOWN; //Ramp down |
180 | |||
181 | // voices[a].isUsed = 0; | ||
182 | setPoint(&voices[a], 3); | 200 | setPoint(&voices[a], 3); |
183 | } | 201 | } |
184 | } | 202 | } |
@@ -281,6 +299,9 @@ int tick(struct MIDIfile * mf) | |||
281 | { | 299 | { |
282 | 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]); |
283 | printf("\nMeta-Event: Tempo Set = %d", tempo); | 301 | printf("\nMeta-Event: Tempo Set = %d", tempo); |
302 | bpm=mf->div*1000000/tempo; | ||
303 | numberOfSamples=SAMPLE_RATE/bpm; | ||
304 | |||
284 | } | 305 | } |
285 | } | 306 | } |
286 | tr->delta = 0; | 307 | tr->delta = 0; |
diff --git a/apps/plugins/midi/synth.c b/apps/plugins/midi/synth.c index 99864e557e..bafaf1c7ca 100644 --- a/apps/plugins/midi/synth.c +++ b/apps/plugins/midi/synth.c | |||
@@ -16,8 +16,6 @@ | |||
16 | * | 16 | * |
17 | ****************************************************************************/ | 17 | ****************************************************************************/ |
18 | 18 | ||
19 | |||
20 | |||
21 | extern struct plugin_api * rb; | 19 | extern struct plugin_api * rb; |
22 | 20 | ||
23 | struct Event * getEvent(struct Track * tr, int evNum) | 21 | struct Event * getEvent(struct Track * tr, int evNum) |
@@ -178,7 +176,20 @@ int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig) | |||
178 | 176 | ||
179 | 177 | ||
180 | 178 | ||
181 | inline signed short int getSample(struct GWaveform * wf, unsigned int s) | 179 | int currentVoice IDATA_ATTR; |
180 | struct SynthObject * so IDATA_ATTR; | ||
181 | struct GWaveform * wf IDATA_ATTR; | ||
182 | int s IDATA_ATTR; | ||
183 | short s1 IDATA_ATTR; | ||
184 | short s2 IDATA_ATTR; | ||
185 | short sample IDATA_ATTR; //For synthSample | ||
186 | unsigned int cpShifted IDATA_ATTR; | ||
187 | |||
188 | unsigned char b1 IDATA_ATTR; | ||
189 | unsigned char b2 IDATA_ATTR; | ||
190 | |||
191 | |||
192 | inline int getSample(int s) | ||
182 | { | 193 | { |
183 | 194 | ||
184 | //16 bit samples | 195 | //16 bit samples |
@@ -186,24 +197,23 @@ inline signed short int getSample(struct GWaveform * wf, unsigned int s) | |||
186 | { | 197 | { |
187 | 198 | ||
188 | if(s<<1 >= wf->wavSize) | 199 | if(s<<1 >= wf->wavSize) |
200 | { | ||
201 | printf("\n!!!!! %d \t %d", s<<1, wf->wavSize); | ||
189 | return 0; | 202 | return 0; |
190 | 203 | } | |
191 | 204 | // signed short a = ((short *)wf->data)[s]; | |
192 | /* | ||
193 | * Probably put the signed/unsigned and and 8-16 bit conversion | ||
194 | * into the patch loader and have it run there, once. | ||
195 | */ | ||
196 | |||
197 | 205 | ||
198 | //Sign conversion moved into guspat.c | 206 | //Sign conversion moved into guspat.c |
199 | unsigned char b1=wf->data[s<<1]; //+((wf->mode & 2) << 6); | 207 | b1=wf->data[s<<1]+((wf->mode & 2) << 6); |
200 | unsigned char b2=wf->data[(s<<1)|1]; //+((wf->mode & 2) << 6); | 208 | b2=wf->data[(s<<1)|1]+((wf->mode & 2) << 6); |
201 | return (b1 | (b2<<8)) ; | 209 | return (b1 | (b2<<8)) ; |
210 | |||
211 | //Get rid of this sometime | ||
202 | } | 212 | } |
203 | else | 213 | else |
204 | { //8-bit samples | 214 | { //8-bit samples |
205 | //Do we even have anything 8-bit in our set? | 215 | //Do we even have anything 8-bit in our set? |
206 | unsigned char b1=wf->data[s]+((wf->mode & 2) << 6); | 216 | int b1=wf->data[s]+((wf->mode & 2) << 6); |
207 | return b1<<8; | 217 | return b1<<8; |
208 | } | 218 | } |
209 | } | 219 | } |
@@ -251,6 +261,12 @@ inline void setPoint(struct SynthObject * so, int pt) | |||
251 | */ | 261 | */ |
252 | so->curRate = r<<10; | 262 | so->curRate = r<<10; |
253 | 263 | ||
264 | //Do this here because the patches assume a 44100 sampling rate | ||
265 | //We've halved our sampling rate, ergo the ADSR code will be | ||
266 | //called half the time. Ergo, double the rate to keep stuff | ||
267 | //sounding right. | ||
268 | so->curRate = so->curRate << 1; | ||
269 | |||
254 | 270 | ||
255 | so->targetOffset = so->wf->envOffset[pt]<<(20); | 271 | so->targetOffset = so->wf->envOffset[pt]<<(20); |
256 | if(pt==0) | 272 | if(pt==0) |
@@ -258,8 +274,6 @@ inline void setPoint(struct SynthObject * so, int pt) | |||
258 | } | 274 | } |
259 | 275 | ||
260 | 276 | ||
261 | long msi=0; | ||
262 | |||
263 | inline void stopVoice(struct SynthObject * so) | 277 | inline void stopVoice(struct SynthObject * so) |
264 | { | 278 | { |
265 | if(so->state == STATE_RAMPDOWN) | 279 | if(so->state == STATE_RAMPDOWN) |
@@ -269,51 +283,37 @@ inline void stopVoice(struct SynthObject * so) | |||
269 | 283 | ||
270 | } | 284 | } |
271 | 285 | ||
272 | int rampDown = 0; | ||
273 | 286 | ||
274 | inline signed short int synthVoice(int v) | 287 | inline signed short int synthVoice() |
275 | { | 288 | { |
276 | //Probably can combine these 2 lines into one.. | 289 | so = &voices[currentVoice]; |
277 | //But for now, this looks more readable | 290 | wf = so->wf; |
278 | // struct GPatch * pat = patchSet[chPat[voices[v].ch]]; | ||
279 | // struct GWaveform * wf = pat->waveforms[pat->noteTable[voices[v].note]]; | ||
280 | struct SynthObject * so = &voices[v]; | ||
281 | struct GWaveform * wf = so->wf; | ||
282 | 291 | ||
283 | signed int s; | ||
284 | 292 | ||
285 | if(so->state != STATE_RAMPDOWN) | 293 | if(so->state != STATE_RAMPDOWN) |
286 | { | 294 | { |
287 | if(so->loopDir==LOOPDIR_FORWARD) | 295 | so->cp += so->delta; |
288 | { | ||
289 | so->cp += so->delta; | ||
290 | } | ||
291 | else | ||
292 | { | ||
293 | so->cp -= so->delta; | ||
294 | } | ||
295 | } | 296 | } |
296 | 297 | ||
297 | if( (so->cp>>9 >= (wf->wavSize)) && (so->state != STATE_RAMPDOWN)) | 298 | cpShifted = so->cp >> 10; |
298 | stopVoice(so); | ||
299 | |||
300 | /* | ||
301 | //Original, working, no interpolation | ||
302 | s=getSample(wf, (so->cp>>10)); | ||
303 | */ | ||
304 | |||
305 | 299 | ||
300 | if( (cpShifted >= (wf->wavSize>>1)) && (so->state != STATE_RAMPDOWN)) | ||
301 | stopVoice(so); | ||
306 | 302 | ||
307 | int s2=getSample(wf, (so->cp>>10)+1); | 303 | s2 = getSample((cpShifted)+1); |
308 | 304 | ||
309 | if((wf->mode & (LOOP_REVERSE|LOOP_PINGPONG)) && so->loopState == STATE_LOOPING && (so->cp>>10 <= (wf->startLoop>>1))) | 305 | if((wf->mode & (LOOP_REVERSE|LOOP_PINGPONG)) && so->loopState == STATE_LOOPING && (cpShifted <= (wf->startLoop>>1))) |
310 | { | 306 | { |
311 | if(wf->mode & LOOP_REVERSE) | 307 | if(wf->mode & LOOP_REVERSE) |
312 | { | 308 | { |
313 | so->cp = (wf->endLoop)<<9; | 309 | so->cp = (wf->endLoop)<<9; |
314 | s2=getSample(wf, (so->cp>>10)); | 310 | cpShifted = so->cp >> 10; |
311 | s2=getSample((cpShifted)); | ||
315 | } else | 312 | } else |
313 | { | ||
314 | so->delta = -so->delta; | ||
316 | so->loopDir = LOOPDIR_FORWARD; | 315 | so->loopDir = LOOPDIR_FORWARD; |
316 | } | ||
317 | } | 317 | } |
318 | 318 | ||
319 | if((wf->mode & 28) && (so->cp>>10 >= wf->endLoop>>1)) | 319 | if((wf->mode & 28) && (so->cp>>10 >= wf->endLoop>>1)) |
@@ -322,14 +322,21 @@ inline signed short int synthVoice(int v) | |||
322 | if((wf->mode & (24)) == 0) | 322 | if((wf->mode & (24)) == 0) |
323 | { | 323 | { |
324 | so->cp = (wf->startLoop)<<9; | 324 | so->cp = (wf->startLoop)<<9; |
325 | s2=getSample(wf, (so->cp>>10)); | 325 | cpShifted = so->cp >> 10; |
326 | s2=getSample((cpShifted)); | ||
326 | } else | 327 | } else |
328 | { | ||
329 | so->delta = -so->delta; | ||
327 | so->loopDir = LOOPDIR_REVERSE; | 330 | so->loopDir = LOOPDIR_REVERSE; |
331 | } | ||
328 | } | 332 | } |
329 | 333 | ||
330 | //Better, working, linear interpolation | 334 | //Better, working, linear interpolation |
331 | int s1=getSample(wf, (so->cp>>10)); | 335 | s1=getSample((cpShifted)); |
332 | s = s1 + ((long)((s2 - s1) * (so->cp & 1023))>>10); | 336 | s = s1 + ((signed)((s2 - s1) * (so->cp & 1023))>>10); |
337 | |||
338 | |||
339 | //ADSR COMMENT WOULD GO FROM HERE......... | ||
333 | 340 | ||
334 | if(so->curRate == 0) | 341 | if(so->curRate == 0) |
335 | stopVoice(so); | 342 | stopVoice(so); |
@@ -366,8 +373,9 @@ inline signed short int synthVoice(int v) | |||
366 | so->isUsed=0; //This is OK | 373 | so->isUsed=0; //This is OK |
367 | 374 | ||
368 | 375 | ||
369 | s = s * (so->curOffset >> 22); | 376 | s = (s * (so->curOffset >> 22) >> 6); |
370 | s = s>>6; | 377 | |
378 | // ............. TO HERE | ||
371 | 379 | ||
372 | 380 | ||
373 | if(so->state == STATE_RAMPDOWN) | 381 | if(so->state == STATE_RAMPDOWN) |
@@ -377,64 +385,28 @@ inline signed short int synthVoice(int v) | |||
377 | so->isUsed=0; | 385 | so->isUsed=0; |
378 | } | 386 | } |
379 | 387 | ||
380 | s = s * so->decay; s = s >> 9; | 388 | s = s * so->decay; s = s >> 10; |
381 | 389 | ||
382 | return s*((signed short int)so->vol*(signed short int)chVol[so->ch])>>14; | 390 | return s*((signed short int)so->vol*(signed short int)chVol[so->ch])>>14; |
383 | } | 391 | } |
384 | 392 | ||
385 | 393 | ||
386 | |||
387 | int mhL[16]; | ||
388 | int mhR[16]; | ||
389 | int mp=0; //Mix position, for circular array | ||
390 | // Was stuff for Ghetto Lowpass Filter, now deprecated. | ||
391 | |||
392 | |||
393 | inline void synthSample(int * mixL, int * mixR) | 394 | inline void synthSample(int * mixL, int * mixR) |
394 | { | 395 | { |
395 | int a=0; | 396 | // signed int leftMix=0, rightMix=0, |
396 | signed long int leftMix=0, rightMix=0, sample=0; | 397 | *mixL = 0; |
397 | for(a=0; a<MAX_VOICES; a++) | 398 | *mixR = 0; |
399 | for(currentVoice=0; currentVoice<MAX_VOICES; currentVoice++) | ||
398 | { | 400 | { |
399 | if(voices[a].isUsed==1) | 401 | if(voices[currentVoice].isUsed==1) |
400 | { | 402 | { |
401 | sample = synthVoice(a); | 403 | sample = synthVoice(currentVoice); |
402 | 404 | *mixL += (sample*chPanLeft[voices[currentVoice].ch])>>7; | |
403 | leftMix += (sample*chPanLeft[voices[a].ch])>>7; | 405 | *mixR += (sample*chPanRight[voices[currentVoice].ch])>>7; |
404 | rightMix += (sample*chPanRight[voices[a].ch])>>7; | ||
405 | } | 406 | } |
406 | } | 407 | } |
407 | 408 | ||
408 | //TODO: Automatic Gain Control, anyone? | 409 | //TODO: Automatic Gain Control, anyone? |
409 | //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? |
410 | *mixL = leftMix; | ||
411 | *mixR = rightMix; | ||
412 | |||
413 | return; //No more ghetto lowpass filter.. linear intrpolation works well. | 411 | return; //No more ghetto lowpass filter.. linear intrpolation works well. |
414 | |||
415 | |||
416 | // HACK HACK HACK | ||
417 | // This is the infamous Ghetto Lowpass Filter | ||
418 | // Now that I have linear interpolation, it should not be needed anymore. | ||
419 | /* | ||
420 | mp++; | ||
421 | if(mp==4) | ||
422 | mp=0; | ||
423 | |||
424 | mhL[mp]=leftMix; | ||
425 | mhR[mp]=rightMix; | ||
426 | |||
427 | *mixL = 0; | ||
428 | *mixR = 0; | ||
429 | |||
430 | |||
431 | for(a=0; a<4; a++) | ||
432 | { | ||
433 | *mixL += mhL[a]; | ||
434 | *mixR += mhR[a]; | ||
435 | } | ||
436 | *mixL = *mixL>>4; | ||
437 | *mixR = *mixR>>4; | ||
438 | */ | ||
439 | // END HACK END HACK END HACK | ||
440 | } | 412 | } |
diff --git a/apps/plugins/midi2wav.c b/apps/plugins/midi2wav.c index 3cf2866a12..6dc7a626b5 100644 --- a/apps/plugins/midi2wav.c +++ b/apps/plugins/midi2wav.c | |||
@@ -16,7 +16,7 @@ | |||
16 | * | 16 | * |
17 | ****************************************************************************/ | 17 | ****************************************************************************/ |
18 | 18 | ||
19 | #define SAMPLE_RATE 48000 | 19 | #define SAMPLE_RATE 22050 |
20 | #define MAX_VOICES 100 | 20 | #define MAX_VOICES 100 |
21 | 21 | ||
22 | 22 | ||
@@ -37,6 +37,12 @@ | |||
37 | 37 | ||
38 | 38 | ||
39 | #include "../../plugin.h" | 39 | #include "../../plugin.h" |
40 | |||
41 | #include "lib/xxx2wav.h" | ||
42 | |||
43 | int numberOfSamples IDATA_ATTR; | ||
44 | long bpm; | ||
45 | |||
40 | #include "midi/midiutil.c" | 46 | #include "midi/midiutil.c" |
41 | #include "midi/guspat.h" | 47 | #include "midi/guspat.h" |
42 | #include "midi/guspat.c" | 48 | #include "midi/guspat.c" |
@@ -46,7 +52,6 @@ | |||
46 | 52 | ||
47 | 53 | ||
48 | 54 | ||
49 | #include "lib/xxx2wav.h" | ||
50 | 55 | ||
51 | int fd=-1; //File descriptor where the output is written | 56 | int fd=-1; //File descriptor where the output is written |
52 | 57 | ||
@@ -58,6 +63,7 @@ struct plugin_api * rb; | |||
58 | 63 | ||
59 | 64 | ||
60 | 65 | ||
66 | |||
61 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | 67 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) |
62 | { | 68 | { |
63 | TEST_PLUGIN_API(api); | 69 | TEST_PLUGIN_API(api); |
@@ -80,6 +86,14 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
80 | return PLUGIN_OK; | 86 | return PLUGIN_OK; |
81 | } | 87 | } |
82 | 88 | ||
89 | signed char outputBuffer[3000] IDATA_ATTR; //signed char.. gonna run out of iram ... ! | ||
90 | |||
91 | |||
92 | int currentSample IDATA_ATTR; | ||
93 | int outputBufferPosition IDATA_ATTR; | ||
94 | int outputSampleOne IDATA_ATTR; | ||
95 | int outputSampleTwo IDATA_ATTR; | ||
96 | |||
83 | 97 | ||
84 | int midimain(void * filename) | 98 | int midimain(void * filename) |
85 | { | 99 | { |
@@ -89,9 +103,6 @@ int midimain(void * filename) | |||
89 | rb->splash(HZ/5, true, "LOADING MIDI"); | 103 | rb->splash(HZ/5, true, "LOADING MIDI"); |
90 | 104 | ||
91 | struct MIDIfile * mf = loadFile(filename); | 105 | struct MIDIfile * mf = loadFile(filename); |
92 | long bpm, nsmp, l; | ||
93 | |||
94 | int bp=0; | ||
95 | 106 | ||
96 | rb->splash(HZ/5, true, "LOADING PATCHES"); | 107 | rb->splash(HZ/5, true, "LOADING PATCHES"); |
97 | if (initSynth(mf, "/.rockbox/patchset/patchset.cfg", "/.rockbox/patchset/drums.cfg") == -1) | 108 | if (initSynth(mf, "/.rockbox/patchset/patchset.cfg", "/.rockbox/patchset/drums.cfg") == -1) |
@@ -125,7 +136,7 @@ int midimain(void * filename) | |||
125 | samp=arg; | 136 | samp=arg; |
126 | #else | 137 | #else |
127 | file_info_struct file_info; | 138 | file_info_struct file_info; |
128 | file_info.samplerate = 48000; | 139 | file_info.samplerate = SAMPLE_RATE; |
129 | file_info.infile = fd; | 140 | file_info.infile = fd; |
130 | file_info.channels = 2; | 141 | file_info.channels = 2; |
131 | file_info.bitspersample = 16; | 142 | file_info.bitspersample = 16; |
@@ -134,12 +145,11 @@ int midimain(void * filename) | |||
134 | #endif | 145 | #endif |
135 | 146 | ||
136 | 147 | ||
137 | rb->splash(HZ/5, true, " START PLAYING "); | 148 | rb->splash(HZ/5, true, " Starting Playback "); |
138 | 149 | ||
139 | 150 | ||
140 | 151 | ||
141 | 152 | ||
142 | signed char buf[3000]; | ||
143 | 153 | ||
144 | // tick() will do one MIDI clock tick. Then, there's a loop here that | 154 | // tick() will do one MIDI clock tick. Then, there's a loop here that |
145 | // will generate the right number of samples per MIDI tick. The whole | 155 | // will generate the right number of samples per MIDI tick. The whole |
@@ -152,49 +162,56 @@ int midimain(void * filename) | |||
152 | 162 | ||
153 | printf("\nOkay, starting sequencing"); | 163 | printf("\nOkay, starting sequencing"); |
154 | 164 | ||
165 | |||
166 | currentSample=0; //Sample counting variable | ||
167 | outputBufferPosition = 0; | ||
168 | |||
169 | |||
170 | bpm=mf->div*1000000/tempo; | ||
171 | numberOfSamples=SAMPLE_RATE/bpm; | ||
172 | |||
173 | |||
174 | |||
155 | //Tick() will return 0 if there are no more events left to play | 175 | //Tick() will return 0 if there are no more events left to play |
156 | while(tick(mf)) | 176 | while(tick(mf)) |
157 | { | 177 | { |
158 | 178 | ||
159 | //Some annoying math to compute the number of samples | 179 | //Some annoying math to compute the number of samples |
160 | //to syntehsize per each MIDI tick. | 180 | //to syntehsize per each MIDI tick. |
161 | bpm=mf->div*1000000/tempo; | ||
162 | nsmp=SAMPLE_RATE/bpm; | ||
163 | 181 | ||
164 | //Yes we need to do this math each time because the tempo | 182 | //Yes we need to do this math each time because the tempo |
165 | //could have changed. | 183 | //could have changed. |
166 | 184 | ||
167 | // On second thought, this can be moved to the event that | 185 | // On second thought, this can be moved to the event that |
168 | //recalculates the tempo, to save a little bit of CPU time. | 186 | //recalculates the tempo, to save a little bit of CPU time. |
169 | for(l=0; l<nsmp; l++) | 187 | for(currentSample=0; currentSample<numberOfSamples; currentSample++) |
170 | { | 188 | { |
171 | int s1, s2; | ||
172 | 189 | ||
173 | synthSample(&s1, &s2); | 190 | synthSample(&outputSampleOne, &outputSampleTwo); |
174 | 191 | ||
175 | 192 | ||
176 | //16-bit audio because, well, it's better | 193 | //16-bit audio because, well, it's better |
177 | // But really because ALSA's OSS emulation sounds extremely | 194 | // But really because ALSA's OSS emulation sounds extremely |
178 | //noisy and distorted when in 8-bit mode. I still do not know | 195 | //noisy and distorted when in 8-bit mode. I still do not know |
179 | //why this happens. | 196 | //why this happens. |
180 | buf[bp]=s1&0XFF; // Low byte first | 197 | outputBuffer[outputBufferPosition]=outputSampleOne&0XFF; // Low byte first |
181 | bp++; | 198 | outputBufferPosition++; |
182 | buf[bp]=s1>>8; //High byte second | 199 | outputBuffer[outputBufferPosition]=outputSampleOne>>8; //High byte second |
183 | bp++; | 200 | outputBufferPosition++; |
184 | 201 | ||
185 | buf[bp]=s2&0XFF; // Low byte first | 202 | outputBuffer[outputBufferPosition]=outputSampleTwo&0XFF; // Low byte first |
186 | bp++; | 203 | outputBufferPosition++; |
187 | buf[bp]=s2>>8; //High byte second | 204 | outputBuffer[outputBufferPosition]=outputSampleTwo>>8; //High byte second |
188 | bp++; | 205 | outputBufferPosition++; |
189 | 206 | ||
190 | 207 | ||
191 | //As soon as we produce 2000 bytes of sound, | 208 | //As soon as we produce 2000 bytes of sound, |
192 | //write it to the sound card. Why 2000? I have | 209 | //write it to the sound card. Why 2000? I have |
193 | //no idea. It's 1 AM and I am dead tired. | 210 | //no idea. It's 1 AM and I am dead tired. |
194 | if(bp>=2000) | 211 | if(outputBufferPosition>=2000) |
195 | { | 212 | { |
196 | rb->write(fd, buf, 2000); | 213 | rb->write(fd, outputBuffer, 2000); |
197 | bp=0; | 214 | outputBufferPosition=0; |
198 | } | 215 | } |
199 | } | 216 | } |
200 | } | 217 | } |