summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2019-08-04 16:58:20 -0400
committerSolomon Peachy <pizza@shaftnet.org>2019-08-05 20:48:40 +0200
commited724fecb15d90d8075ed1edb963f455cb91b0a1 (patch)
tree6b72250278e5170bc7ed4b8263f48eb8e8dc1c61 /apps
parenteea5bfc9aec35686406296641b37bcc2c731fbbb (diff)
downloadrockbox-ed724fecb15d90d8075ed1edb963f455cb91b0a1.tar.gz
rockbox-ed724fecb15d90d8075ed1edb963f455cb91b0a1.zip
Midiplay plugin ehancements
- Improved robustness - Improved sound quality - Use mixer and DSP Patch by Igor Poretsky Change-Id: I6fa617158cbaa53ae842295cdbdbe3a478e49ded
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/midi/guspat.c60
-rw-r--r--apps/plugins/midi/midifile.c23
-rw-r--r--apps/plugins/midi/midiplay.c174
-rw-r--r--apps/plugins/midi/midiutil.c38
-rw-r--r--apps/plugins/midi/midiutil.h5
-rw-r--r--apps/plugins/midi/synth.c41
-rw-r--r--apps/plugins/midi/synth.h2
7 files changed, 230 insertions, 113 deletions
diff --git a/apps/plugins/midi/guspat.c b/apps/plugins/midi/guspat.c
index f650555520..d94fbce021 100644
--- a/apps/plugins/midi/guspat.c
+++ b/apps/plugins/midi/guspat.c
@@ -66,6 +66,8 @@ static struct GWaveform * loadWaveform(int file)
66 rb->memset(wav, 0, sizeof(struct GWaveform)); 66 rb->memset(wav, 0, sizeof(struct GWaveform));
67 67
68 wav->name=readData(file, 7); 68 wav->name=readData(file, 7);
69 if (!wav->name)
70 return NULL;
69/* printf("\nWAVE NAME = [%s]", wav->name); */ 71/* printf("\nWAVE NAME = [%s]", wav->name); */
70 wav->fractions=readChar(file); 72 wav->fractions=readChar(file);
71 wav->wavSize=readDWord(file); 73 wav->wavSize=readDWord(file);
@@ -81,7 +83,11 @@ static struct GWaveform * loadWaveform(int file)
81 83
82 wav->balance=readChar(file); 84 wav->balance=readChar(file);
83 wav->envRate=readData(file, 6); 85 wav->envRate=readData(file, 6);
86 if (!wav->envRate)
87 return NULL;
84 wav->envOffset=readData(file, 6); 88 wav->envOffset=readData(file, 6);
89 if (!wav->envOffset)
90 return NULL;
85 91
86 wav->tremSweep=readChar(file); 92 wav->tremSweep=readChar(file);
87 wav->tremRate=readChar(file); 93 wav->tremRate=readChar(file);
@@ -95,7 +101,11 @@ static struct GWaveform * loadWaveform(int file)
95 wav->scaleFactor=readWord(file); 101 wav->scaleFactor=readWord(file);
96/* printf("\nScaleFreq = %d ScaleFactor = %d RootFreq = %d", wav->scaleFreq, wav->scaleFactor, wav->rootFreq); */ 102/* printf("\nScaleFreq = %d ScaleFactor = %d RootFreq = %d", wav->scaleFreq, wav->scaleFactor, wav->rootFreq); */
97 wav->res=readData(file, 36); 103 wav->res=readData(file, 36);
104 if (!wav->res)
105 return NULL;
98 wav->data=readData(file, wav->wavSize); 106 wav->data=readData(file, wav->wavSize);
107 if (!wav->data)
108 return NULL;
99 109
100 wav->numSamples = wav->wavSize / 2; 110 wav->numSamples = wav->wavSize / 2;
101 wav->startLoop = wav->startLoop >> 1; 111 wav->startLoop = wav->startLoop >> 1;
@@ -166,7 +176,10 @@ static int selectWaveform(struct GPatch * pat, int midiNote)
166struct GPatch * gusload(char * filename) 176struct GPatch * gusload(char * filename)
167{ 177{
168 struct GPatch * gp = (struct GPatch *)malloc(sizeof(struct GPatch)); 178 struct GPatch * gp = (struct GPatch *)malloc(sizeof(struct GPatch));
169 rb->memset(gp, 0, sizeof(struct GPatch)); 179
180 if (gp)
181 rb->memset(gp, 0, sizeof(struct GPatch));
182 else return NULL;
170 183
171 int file = rb->open(filename, O_RDONLY); 184 int file = rb->open(filename, O_RDONLY);
172 185
@@ -179,8 +192,23 @@ struct GPatch * gusload(char * filename)
179 } 192 }
180 193
181 gp->header=readData(file, 12); 194 gp->header=readData(file, 12);
195 if (!gp->header)
196 {
197 rb->close(file);
198 return NULL;
199 }
182 gp->gravisid=readData(file, 10); 200 gp->gravisid=readData(file, 10);
201 if (!gp->gravisid)
202 {
203 rb->close(file);
204 return NULL;
205 }
183 gp->desc=readData(file, 60); 206 gp->desc=readData(file, 60);
207 if (!gp->desc)
208 {
209 rb->close(file);
210 return NULL;
211 }
184 gp->inst=readChar(file); 212 gp->inst=readChar(file);
185 gp->voc=readChar(file); 213 gp->voc=readChar(file);
186 gp->chan=readChar(file); 214 gp->chan=readChar(file);
@@ -188,28 +216,52 @@ struct GPatch * gusload(char * filename)
188 gp->vol=readWord(file); 216 gp->vol=readWord(file);
189 gp->datSize=readDWord(file); 217 gp->datSize=readDWord(file);
190 gp->res=readData(file, 36); 218 gp->res=readData(file, 36);
219 if (!gp->res)
220 {
221 rb->close(file);
222 return NULL;
223 }
191 224
192 gp->instrID=readWord(file); 225 gp->instrID=readWord(file);
193 gp->instrName=readData(file,16); 226 gp->instrName=readData(file,16);
227 if (!gp->instrName)
228 {
229 rb->close(file);
230 return NULL;
231 }
194 gp->instrSize=readDWord(file); 232 gp->instrSize=readDWord(file);
195 gp->layers=readChar(file); 233 gp->layers=readChar(file);
196 gp->instrRes=readData(file,40); 234 gp->instrRes=readData(file,40);
197 235 if (!gp->instrRes)
236 {
237 rb->close(file);
238 return NULL;
239 }
198 240
199 gp->layerDup=readChar(file); 241 gp->layerDup=readChar(file);
200 gp->layerID=readChar(file); 242 gp->layerID=readChar(file);
201 gp->layerSize=readDWord(file); 243 gp->layerSize=readDWord(file);
202 gp->numWaves=readChar(file); 244 gp->numWaves=readChar(file);
203 gp->layerRes=readData(file,40); 245 gp->layerRes=readData(file,40);
204 246 if (!gp->layerRes)
247 {
248 rb->close(file);
249 return NULL;
250 }
205 251
206/* printf("\nFILE: %s", filename); */ 252/* printf("\nFILE: %s", filename); */
207/* printf("\nlayerSamples=%d", gp->numWaves); */ 253/* printf("\nlayerSamples=%d", gp->numWaves); */
208 254
209 int a=0; 255 int a=0;
210 for(a=0; a<gp->numWaves; a++) 256 for(a=0; a<gp->numWaves; a++)
257 {
211 gp->waveforms[a] = loadWaveform(file); 258 gp->waveforms[a] = loadWaveform(file);
212 259 if (!gp->waveforms[a])
260 {
261 rb->close(file);
262 return NULL;
263 }
264 }
213 265
214/* printf("\nPrecomputing note table"); */ 266/* printf("\nPrecomputing note table"); */
215 267
diff --git a/apps/plugins/midi/midifile.c b/apps/plugins/midi/midifile.c
index 86544fd944..2340c6d14f 100644
--- a/apps/plugins/midi/midifile.c
+++ b/apps/plugins/midi/midifile.c
@@ -106,6 +106,11 @@ struct MIDIfile * loadFile(const char * filename)
106 if(id == ID_MTRK) 106 if(id == ID_MTRK)
107 { 107 {
108 mfload->tracks[track] = readTrack(file); 108 mfload->tracks[track] = readTrack(file);
109 if (!mfload->tracks[track])
110 {
111 rb->close(file);
112 return NULL;
113 }
109 track++; 114 track++;
110 } else 115 } else
111 { 116 {
@@ -125,7 +130,7 @@ struct MIDIfile * loadFile(const char * filename)
125 * and then track 2 starts loading */ 130 * and then track 2 starts loading */
126 131
127int rStatus = 0; 132int rStatus = 0;
128/* Returns 0 if done, 1 if keep going */ 133/* Returns 0 if done, 1 if keep going and -1 in case of error */
129static int readEvent(int file, void * dest) 134static int readEvent(int file, void * dest)
130{ 135{
131 struct Event dummy; 136 struct Event dummy;
@@ -152,6 +157,8 @@ static int readEvent(int file, void * dest)
152 { 157 {
153 /* Null-terminate for text events */ 158 /* Null-terminate for text events */
154 ev->evData = malloc(ev->len+1); /* Extra byte for the null termination */ 159 ev->evData = malloc(ev->len+1); /* Extra byte for the null termination */
160 if (!ev->evData)
161 return -1;
155 162
156 rb->read(file, ev->evData, ev->len); 163 rb->read(file, ev->evData, ev->len);
157 ev->evData[ev->len] = 0; 164 ev->evData[ev->len] = 0;
@@ -272,27 +279,35 @@ struct Track * readTrack(int file)
272 279
273 int pos = rb->lseek(file, 0, SEEK_CUR); 280 int pos = rb->lseek(file, 0, SEEK_CUR);
274 281
275 while(readEvent(file, NULL)) /* Memory saving technique */ 282 int evstat;
283
284 while ((evstat = readEvent(file, NULL)) > 0) /* Memory saving technique */
276 numEvents++; /* Attempt to read in events, count how many */ 285 numEvents++; /* Attempt to read in events, count how many */
277 /* THEN allocate memory and read them in */ 286 /* THEN allocate memory and read them in */
287 if (evstat < 0)
288 return NULL;
278 rb->lseek(file, pos, SEEK_SET); 289 rb->lseek(file, pos, SEEK_SET);
279 290
280 int trackSize = (numEvents+1) * sizeof(struct Event); 291 int trackSize = (numEvents+1) * sizeof(struct Event);
281 void * dataPtr = malloc(trackSize); 292 void * dataPtr = malloc(trackSize);
293 if (!dataPtr)
294 return NULL;
282 trk->dataBlock = dataPtr; 295 trk->dataBlock = dataPtr;
283 296
284 numEvents=0; 297 numEvents=0;
285 298
286 while(readEvent(file, dataPtr)) 299 while ((evstat = readEvent(file, dataPtr)) > 0)
287 { 300 {
288 if(trackSize < dataPtr-trk->dataBlock) 301 if(trackSize < dataPtr-trk->dataBlock)
289 { 302 {
290 midi_debug("Track parser memory out of bounds"); 303 midi_debug("Track parser memory out of bounds");
291 exit(1); 304 return NULL;
292 } 305 }
293 dataPtr+=sizeof(struct Event); 306 dataPtr+=sizeof(struct Event);
294 numEvents++; 307 numEvents++;
295 } 308 }
309 if (evstat < 0)
310 return NULL;
296 trk->numEvents = numEvents; 311 trk->numEvents = numEvents;
297 312
298 return trk; 313 return trk;
diff --git a/apps/plugins/midi/midiplay.c b/apps/plugins/midi/midiplay.c
index bef13b649d..8e867e5173 100644
--- a/apps/plugins/midi/midiplay.c
+++ b/apps/plugins/midi/midiplay.c
@@ -348,6 +348,10 @@
348#define SYNC 348#define SYNC
349#endif 349#endif
350 350
351#ifndef ALIGNED_ATTR
352#define ALIGNED_ATTR(x) __attribute__((aligned(x)))
353#endif
354
351struct MIDIfile * mf IBSS_ATTR; 355struct MIDIfile * mf IBSS_ATTR;
352 356
353int number_of_samples IBSS_ATTR; /* the number of samples in the current tick */ 357int number_of_samples IBSS_ATTR; /* the number of samples in the current tick */
@@ -355,52 +359,79 @@ int playing_time IBSS_ATTR; /* How many seconds into the file have we been play
355int samples_this_second IBSS_ATTR; /* How many samples produced during this second so far? */ 359int samples_this_second IBSS_ATTR; /* How many samples produced during this second so far? */
356long bpm IBSS_ATTR; 360long bpm IBSS_ATTR;
357 361
358int32_t gmbuf[BUF_SIZE*NBUF]; 362#ifndef SYNC
359static unsigned int samples_in_buf; 363/* Small silence clip. ~5.80ms @ 44.1kHz */
364static int32_t silence[256] ALIGNED_ATTR(4) = { 0 };
365
366static int32_t gmbuf[BUF_SIZE * NBUF] ALIGNED_ATTR(4);
367
368static volatile bool swap = false;
369static volatile bool lastswap = true;
370#else
371static int32_t gmbuf[BUF_SIZE] ALIGNED_ATTR(4);
372#endif
373
374static volatile size_t samples_in_buf;
360 375
361bool midi_end = false; 376static volatile bool midi_end = false;
362bool quit = false; 377static volatile bool quit = false;
363bool swap = false; 378
364bool lastswap = true; 379static int32_t samp_buf[MAX_SAMPLES * 2] IBSS_ATTR;
380
381static struct dsp_config *dsp;
382static struct dsp_buffer src;
383static struct dsp_buffer dst;
365 384
366static inline void synthbuf(void) 385static inline void synthbuf(void)
367{ 386{
368 int32_t *outptr; 387 int32_t *outptr;
369 int i = BUF_SIZE; 388 int available = BUF_SIZE;
370 389
371#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
372 rb->cpu_boost(true);
373#endif
374#ifndef SYNC 390#ifndef SYNC
375 if (lastswap == swap) 391 if (lastswap == swap)
376 return; 392 return;
377 lastswap = swap;
378 393
379 outptr = (swap ? gmbuf : gmbuf+BUF_SIZE); 394 outptr = (swap ? gmbuf : gmbuf+BUF_SIZE);
380#else 395#else
381 outptr = gmbuf; 396 outptr = gmbuf;
382#endif 397#endif
383 if (midi_end) {
384 samples_in_buf = 0;
385 return;
386 }
387 398
399#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
400 rb->cpu_boost(true);
401#endif
388 /* synth samples for as many whole ticks as we can fit in the buffer */ 402 /* synth samples for as many whole ticks as we can fit in the buffer */
389 for (; i >= number_of_samples; i -= number_of_samples) 403 while (available > 0)
390 { 404 {
391 synthSamples((int32_t*)outptr, number_of_samples); 405 if ((dst.remcount <= 0) && !midi_end)
392 outptr += number_of_samples; 406 {
393#ifndef SYNC 407 int nsamples = synthSamples(samp_buf, number_of_samples);
394 /* synthbuf is called in interrupt context is SYNC is defined so it cannot yield 408 if (nsamples < number_of_samples)
395 that bug causing the sim to crach when not using SYNC should really be fixed */ 409 number_of_samples -= nsamples;
396 rb->yield(); 410 else if (!tick())
397#endif 411 midi_end = true; /* no more midi data to play */
398 if (tick() == 0) 412 src.remcount = nsamples;
399 midi_end = true; /* no more midi data to play */ 413 src.pin[0] = &samp_buf[0];
414 src.pin[1] = &samp_buf[1];
415 src.proc_mask = 0;
416 }
417 dst.remcount = 0;
418 dst.bufcount = available;
419 dst.p16out = (int16_t *)outptr;
420 rb->dsp_process(dsp, &src, &dst);
421 if (dst.remcount > 0)
422 {
423 outptr += dst.remcount;
424 available -= dst.remcount;
425 }
426 else if (midi_end)
427 break;
400 } 428 }
401 429
402 /* how many samples did we write to the buffer? */ 430 /* how many samples did we write to the buffer? */
403 samples_in_buf = BUF_SIZE-i; 431 samples_in_buf = BUF_SIZE - available;
432#ifndef SYNC
433 lastswap = swap;
434#endif
404#if defined(HAVE_ADJUSTABLE_CPU_FREQ) 435#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
405 rb->cpu_boost(false); 436 rb->cpu_boost(false);
406#endif 437#endif
@@ -409,26 +440,27 @@ static inline void synthbuf(void)
409static void get_more(const void** start, size_t* size) 440static void get_more(const void** start, size_t* size)
410{ 441{
411#ifndef SYNC 442#ifndef SYNC
412 if(lastswap != swap) 443 swap = !swap;
444 if(lastswap == swap)
413 { 445 {
414 midi_debug("Buffer miss!"); /* Comment out the midi_debug to make missses less noticable. */ 446 *start = silence;
447 *size = sizeof(silence);
448 swap = !swap;
449 return;
415 } 450 }
416 451 else if (samples_in_buf)
452 *start = swap ? (gmbuf + BUF_SIZE) : gmbuf;
417#else 453#else
418 synthbuf(); /* For some reason midiplayer crashes when an update is forced */ 454 synthbuf(); /* For some reason midiplayer crashes when an update is forced */
455 if (samples_in_buf)
456 *start = gmbuf;
419#endif 457#endif
420 458 else
421 *size = samples_in_buf*sizeof(int32_t); 459 {
422#ifndef SYNC
423 *start = swap ? gmbuf : gmbuf + BUF_SIZE;
424 swap = !swap;
425#else
426 *start = gmbuf;
427#endif
428 if (samples_in_buf==0) {
429 *start = NULL; 460 *start = NULL;
430 quit = true; /* this was the last buffer to play */ 461 quit = true; /* this was the last buffer to play */
431 } 462 }
463 *size = samples_in_buf*sizeof(int32_t);
432} 464}
433 465
434static int midimain(const void * filename) 466static int midimain(const void * filename)
@@ -460,13 +492,26 @@ static int midimain(const void * filename)
460 return -1; 492 return -1;
461 } 493 }
462 494
495 rb->talk_force_shutup();
463 rb->pcm_play_stop(); 496 rb->pcm_play_stop();
464#if INPUT_SRC_CAPS != 0 497#if INPUT_SRC_CAPS != 0
465 /* Select playback */ 498 /* Select playback */
466 rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); 499 rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
467 rb->audio_set_output_source(AUDIO_SRC_PLAYBACK); 500 rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
468#endif 501#endif
469 rb->pcm_set_frequency(SAMPLE_RATE); /* 44100 22050 11025 */ 502
503 dst.remcount = 0;
504 dsp = rb->dsp_get_config(CODEC_IDX_AUDIO);
505 rb->dsp_configure(dsp, DSP_RESET, 0);
506 rb->dsp_configure(dsp, DSP_FLUSH, 0);
507 rb->dsp_configure(dsp, DSP_SET_OUT_FREQUENCY, rb->mixer_get_frequency());
508#ifdef HAVE_PITCHCONTROL
509 rb->sound_set_pitch(PITCH_SPEED_100);
510 rb->dsp_set_timestretch(PITCH_SPEED_100);
511#endif
512 rb->dsp_configure(dsp, DSP_SET_SAMPLE_DEPTH, 22);
513 rb->dsp_configure(dsp, DSP_SET_FREQUENCY, SAMPLE_RATE); /* 44100 22050 11025 */
514 rb->dsp_configure(dsp, DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
470 515
471 /* 516 /*
472 * tick() will do one MIDI clock tick. Then, there's a loop here that 517 * tick() will do one MIDI clock tick. Then, there's a loop here that
@@ -501,8 +546,12 @@ static int midimain(const void * filename)
501 playing_time = 0; 546 playing_time = 0;
502 samples_this_second = 0; 547 samples_this_second = 0;
503 548
549#ifndef SYNC
504 synthbuf(); 550 synthbuf();
505 rb->pcm_play_data(&get_more, NULL, NULL, 0); 551#endif
552
553 rb->pcmbuf_fade(false, true);
554 rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0);
506 555
507 while (!quit) 556 while (!quit)
508 { 557 {
@@ -547,7 +596,9 @@ static int midimain(const void * filename)
547 { 596 {
548 /* Rewinding is tricky. Basically start the file over */ 597 /* Rewinding is tricky. Basically start the file over */
549 /* but run through the tracks without the synth running */ 598 /* but run through the tracks without the synth running */
550 rb->pcm_play_stop(); 599 rb->mixer_channel_stop(PCM_MIXER_CHAN_PLAYBACK);
600 rb->dsp_configure(dsp, DSP_FLUSH, 0);
601 dst.remcount = 0;
551#if defined(HAVE_ADJUSTABLE_CPU_FREQ) 602#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
552 rb->cpu_boost(true); 603 rb->cpu_boost(true);
553#endif 604#endif
@@ -555,39 +606,45 @@ static int midimain(const void * filename)
555#if defined(HAVE_ADJUSTABLE_CPU_FREQ) 606#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
556 rb->cpu_boost(false); 607 rb->cpu_boost(false);
557#endif 608#endif
609#ifndef SYNC
558 lastswap = !swap; 610 lastswap = !swap;
559 synthbuf(); 611 synthbuf();
612#endif
560 midi_debug("Rewind to %d:%02d\n", playing_time/60, playing_time%60); 613 midi_debug("Rewind to %d:%02d\n", playing_time/60, playing_time%60);
561 if (is_playing) 614 if (is_playing)
562 rb->pcm_play_data(&get_more, NULL, NULL, 0); 615 rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0);
563 break; 616 break;
564 } 617 }
565 618
566 case MIDI_FFWD: 619 case MIDI_FFWD:
567 { 620 {
568 rb->pcm_play_stop(); 621 rb->mixer_channel_stop(PCM_MIXER_CHAN_PLAYBACK);
622 rb->dsp_configure(dsp, DSP_FLUSH, 0);
623 dst.remcount = 0;
624#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
625 rb->cpu_boost(true);
626#endif
569 seekForward(5); 627 seekForward(5);
628#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
629 rb->cpu_boost(false);
630#endif
631#ifndef SYNC
570 lastswap = !swap; 632 lastswap = !swap;
571 synthbuf(); 633 synthbuf();
634#endif
572 midi_debug("Skip to %d:%02d\n", playing_time/60, playing_time%60); 635 midi_debug("Skip to %d:%02d\n", playing_time/60, playing_time%60);
573 if (is_playing) 636 if (is_playing)
574 rb->pcm_play_data(&get_more, NULL, NULL, 0); 637 rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0);
575 break; 638 break;
576 } 639 }
577 640
578 case MIDI_PLAYPAUSE: 641 case MIDI_PLAYPAUSE:
579 { 642 {
580 if (is_playing) 643 is_playing = !is_playing;
581 { 644 midi_debug("%s %d:%02d\n",
582 midi_debug("Paused at %d:%02d\n", playing_time/60, playing_time%60); 645 is_playing ? "Playing from" : "Paused at",
583 is_playing = false; 646 playing_time/60, playing_time%60);
584 rb->pcm_play_stop(); 647 rb->mixer_channel_play_pause(PCM_MIXER_CHAN_PLAYBACK, is_playing);
585 } else
586 {
587 midi_debug("Playing from %d:%02d\n", playing_time/60, playing_time%60);
588 is_playing = true;
589 rb->pcm_play_data(&get_more, NULL, NULL, 0);
590 }
591 break; 648 break;
592 } 649 }
593 650
@@ -598,6 +655,10 @@ static int midimain(const void * filename)
598 quit = true; 655 quit = true;
599 } 656 }
600 } 657 }
658
659 rb->pcmbuf_fade(false, false);
660 rb->mixer_channel_stop(PCM_MIXER_CHAN_PLAYBACK);
661
601 return 0; 662 return 0;
602} 663}
603 664
@@ -625,9 +686,6 @@ enum plugin_status plugin_start(const void* parameter)
625 rb->profstop(); 686 rb->profstop();
626#endif 687#endif
627 688
628 rb->pcm_play_stop();
629 rb->pcm_set_frequency(HW_SAMPR_DEFAULT);
630
631 rb->splash(HZ, "FINISHED PLAYING"); 689 rb->splash(HZ, "FINISHED PLAYING");
632 690
633 if (retval == -1) 691 if (retval == -1)
diff --git a/apps/plugins/midi/midiutil.c b/apps/plugins/midi/midiutil.c
index bfac1d5244..b9e57a405b 100644
--- a/apps/plugins/midi/midiutil.c
+++ b/apps/plugins/midi/midiutil.c
@@ -39,37 +39,40 @@ struct SynthObject voices[MAX_VOICES] IBSS_ATTR;
39 39
40static void *alloc(int size) 40static void *alloc(int size)
41{ 41{
42 static char *offset = NULL; 42 static char *offset[2] = {NULL};
43 static size_t totalSize = 0; 43 static size_t totalSize[2] = {0};
44 char *ret; 44 char *ret;
45 int n;
45 46
46 int remainder = size % 4; 47 int remainder = size % 4;
47 48
48 size = size + 4-remainder; 49 size = size + 4-remainder;
49 50
50 if (offset == NULL) 51 if (offset[0] == NULL)
51 { 52 {
52 offset = rb->plugin_get_audio_buffer(&totalSize); 53 offset[0] = rb->plugin_get_buffer(&totalSize[0]);
53 } 54 }
54 55
55 if (size + 4 > (int)totalSize) 56 if (offset[1] == NULL)
56 { 57 {
57 midi_debug("Out of Memory"); 58 offset[1] = rb->plugin_get_audio_buffer(&totalSize[1]);
58 midi_debug("MALLOC BARF"); 59 }
59 midi_debug("MALLOC BARF"); 60
60 midi_debug("MALLOC BARF"); 61 n = (totalSize[0] > totalSize[1]) ? 1 : 0;
61 midi_debug("MALLOC BARF");
62 midi_debug("MALLOC BARF");
63 /* We've made our point. */
64 62
63 if (size + 4 > (int)totalSize[n])
64 n ^= 1;
65 if (size + 4 > (int)totalSize[n])
66 {
67 midi_debug("Out of Memory");
65 return NULL; 68 return NULL;
66 } 69 }
67 70
68 ret = offset + 4; 71 ret = offset[n] + 4;
69 *((unsigned int *)offset) = size; 72 *((unsigned int *)offset[n]) = size;
70 73
71 offset += size + 4; 74 offset[n] += size + 4;
72 totalSize -= size + 4; 75 totalSize[n] -= size + 4;
73 return ret; 76 return ret;
74} 77}
75 78
@@ -117,7 +120,8 @@ unsigned char readChar(int file)
117void * readData(int file, int len) 120void * readData(int file, int len)
118{ 121{
119 void * dat = malloc(len); 122 void * dat = malloc(len);
120 rb->read(file, dat, len); 123 if (dat)
124 rb->read(file, dat, len);
121 return dat; 125 return dat;
122} 126}
123 127
diff --git a/apps/plugins/midi/midiutil.h b/apps/plugins/midi/midiutil.h
index cf3666c97f..72bff11b3f 100644
--- a/apps/plugins/midi/midiutil.h
+++ b/apps/plugins/midi/midiutil.h
@@ -25,14 +25,11 @@
25 25
26#define BUF_SIZE 16384 /* 64 kB output buffers */ 26#define BUF_SIZE 16384 /* 64 kB output buffers */
27#define NBUF 2 27#define NBUF 2
28#define MAX_SAMPLES 512
28 29
29#ifndef SIMULATOR 30#ifndef SIMULATOR
30 31
31#if (HW_SAMPR_CAPS & SAMPR_CAP_22) /* use 22050Hz if we can */
32#define SAMPLE_RATE SAMPR_22 /* 22050 */
33#else
34#define SAMPLE_RATE SAMPR_44 /* 44100 */ 32#define SAMPLE_RATE SAMPR_44 /* 44100 */
35#endif
36 33
37/* Some of the pp based targets can't handle too many voices 34/* Some of the pp based targets can't handle too many voices
38 mainly because they have to use 44100Hz sample rate, this could be 35 mainly because they have to use 44100Hz sample rate, this could be
diff --git a/apps/plugins/midi/synth.c b/apps/plugins/midi/synth.c
index e95dd7cec9..f199d544e5 100644
--- a/apps/plugins/midi/synth.c
+++ b/apps/plugins/midi/synth.c
@@ -300,7 +300,8 @@ static inline void synthVoice(struct SynthObject * so, int32_t * out, unsigned i
300 s1 = so->decay; 300 s1 = so->decay;
301 s2 = s1 * pan; 301 s2 = s1 * pan;
302 s1 = (s1 << 7) -s2; 302 s1 = (s1 << 7) -s2;
303 *(out++) += ((s1 << 9) & 0xFFFF0000) | ((s2 >> 7) &0xFFFF); 303 *(out++) += s1;
304 *(out++) += s2;
304 continue; 305 continue;
305 } 306 }
306 } else /* OK to advance voice */ 307 } else /* OK to advance voice */
@@ -431,7 +432,8 @@ static inline void synthVoice(struct SynthObject * so, int32_t * out, unsigned i
431 432
432 s2 = s1 * pan; 433 s2 = s1 * pan;
433 s1 = (s1 << 7) - s2; 434 s1 = (s1 << 7) - s2;
434 *(out++) += ((s1 << 9) & 0xFFFF0000) | ((s2 >> 7) &0xFFFF); 435 *(out++) += s1;
436 *(out++) += s2;
435 } 437 }
436 438
437 /* store these again */ 439 /* store these again */
@@ -441,40 +443,29 @@ static inline void synthVoice(struct SynthObject * so, int32_t * out, unsigned i
441 return; 443 return;
442} 444}
443 445
444/* buffer to hold all the samples for the current tick, this is a hack
445 neccesary for coldfire targets as pcm_play_data uses the dma which cannot
446 access iram */
447int32_t samp_buf[512] IBSS_ATTR;
448
449/* synth num_samples samples and write them to the */ 446/* synth num_samples samples and write them to the */
450/* buffer pointed to by buf_ptr */ 447/* buffer pointed to by buf_ptr */
451void synthSamples(int32_t *buf_ptr, unsigned int num_samples) ICODE_ATTR; 448size_t synthSamples(int32_t *buf_ptr, size_t num_samples) ICODE_ATTR;
452void synthSamples(int32_t *buf_ptr, unsigned int num_samples) 449size_t synthSamples(int32_t *buf_ptr, size_t num_samples)
453{ 450{
454 if (UNLIKELY(num_samples > 512)) 451 unsigned int i;
455 DEBUGF("num_samples is too big!\n"); 452 struct SynthObject *voicept;
456 else 453 size_t nsamples = MIN(num_samples, MAX_SAMPLES);
457 {
458 int i;
459 struct SynthObject *voicept;
460 454
461 rb->memset(samp_buf, 0, num_samples*4); 455 rb->memset(buf_ptr, 0, nsamples * 2 * sizeof(int32_t));
462 456
463 for(i=0; i < MAX_VOICES; i++) 457 for(i=0; i < MAX_VOICES; i++)
458 {
459 voicept=&voices[i];
460 if(voicept->isUsed)
464 { 461 {
465 voicept=&voices[i]; 462 synthVoice(voicept, buf_ptr, nsamples);
466 if(voicept->isUsed)
467 {
468 synthVoice(voicept, samp_buf, num_samples);
469 }
470 } 463 }
471
472 rb->memcpy(buf_ptr, samp_buf, num_samples*4);
473 } 464 }
474 465
475 /* TODO: Automatic Gain Control, anyone? */ 466 /* TODO: Automatic Gain Control, anyone? */
476 /* Or, should this be implemented on the DSP's output volume instead? */ 467 /* Or, should this be implemented on the DSP's output volume instead? */
477 468
478 return; /* No more ghetto lowpass filter. Linear interpolation works well. */ 469 return nsamples; /* No more ghetto lowpass filter. Linear interpolation works well. */
479} 470}
480 471
diff --git a/apps/plugins/midi/synth.h b/apps/plugins/midi/synth.h
index 4cc6a545f0..b44da21fd2 100644
--- a/apps/plugins/midi/synth.h
+++ b/apps/plugins/midi/synth.h
@@ -20,7 +20,7 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig); 21int initSynth(struct MIDIfile * mf, char * filename, char * drumConfig);
22void setPoint(struct SynthObject * so, int pt); 22void setPoint(struct SynthObject * so, int pt);
23void synthSamples(int32_t *buf_ptr, unsigned int num_samples); 23size_t synthSamples(int32_t *buf_ptr, size_t num_samples);
24 24
25void resetControllers(void); 25void resetControllers(void);
26 26