diff options
Diffstat (limited to 'apps/plugins/midi/midiplay.c')
-rw-r--r-- | apps/plugins/midi/midiplay.c | 174 |
1 files changed, 116 insertions, 58 deletions
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 | |||
351 | struct MIDIfile * mf IBSS_ATTR; | 355 | struct MIDIfile * mf IBSS_ATTR; |
352 | 356 | ||
353 | int number_of_samples IBSS_ATTR; /* the number of samples in the current tick */ | 357 | int 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 | |||
355 | int samples_this_second IBSS_ATTR; /* How many samples produced during this second so far? */ | 359 | int samples_this_second IBSS_ATTR; /* How many samples produced during this second so far? */ |
356 | long bpm IBSS_ATTR; | 360 | long bpm IBSS_ATTR; |
357 | 361 | ||
358 | int32_t gmbuf[BUF_SIZE*NBUF]; | 362 | #ifndef SYNC |
359 | static unsigned int samples_in_buf; | 363 | /* Small silence clip. ~5.80ms @ 44.1kHz */ |
364 | static int32_t silence[256] ALIGNED_ATTR(4) = { 0 }; | ||
365 | |||
366 | static int32_t gmbuf[BUF_SIZE * NBUF] ALIGNED_ATTR(4); | ||
367 | |||
368 | static volatile bool swap = false; | ||
369 | static volatile bool lastswap = true; | ||
370 | #else | ||
371 | static int32_t gmbuf[BUF_SIZE] ALIGNED_ATTR(4); | ||
372 | #endif | ||
373 | |||
374 | static volatile size_t samples_in_buf; | ||
360 | 375 | ||
361 | bool midi_end = false; | 376 | static volatile bool midi_end = false; |
362 | bool quit = false; | 377 | static volatile bool quit = false; |
363 | bool swap = false; | 378 | |
364 | bool lastswap = true; | 379 | static int32_t samp_buf[MAX_SAMPLES * 2] IBSS_ATTR; |
380 | |||
381 | static struct dsp_config *dsp; | ||
382 | static struct dsp_buffer src; | ||
383 | static struct dsp_buffer dst; | ||
365 | 384 | ||
366 | static inline void synthbuf(void) | 385 | static 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) | |||
409 | static void get_more(const void** start, size_t* size) | 440 | static 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 | ||
434 | static int midimain(const void * filename) | 466 | static 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) |