From 1adc869d9ca7b0dcc173e607976fddcde34f3e3a Mon Sep 17 00:00:00 2001 From: Nils Wallménius Date: Sat, 28 Mar 2009 11:27:56 +0000 Subject: midi: yield more, fixes flickering backlight fade on some targets while playing midi. Some coding style clean up, it's a little better but still a mess git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20562 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/midi/midiplay.c | 313 +++++++++++++++++++----------------------- apps/plugins/midi/midiutil.h | 10 +- apps/plugins/midi/sequencer.c | 225 ++++++++++++++---------------- 3 files changed, 258 insertions(+), 290 deletions(-) diff --git a/apps/plugins/midi/midiplay.c b/apps/plugins/midi/midiplay.c index ac23187686..b0024087b6 100644 --- a/apps/plugins/midi/midiplay.c +++ b/apps/plugins/midi/midiplay.c @@ -29,24 +29,7 @@ PLUGIN_HEADER PLUGIN_IRAM_DECLARE /* variable button definitions */ -#if CONFIG_KEYPAD == RECORDER_PAD -#define BTN_QUIT BUTTON_OFF -#define BTN_RIGHT BUTTON_RIGHT -#define BTN_UP BUTTON_UP -#define BTN_DOWN BUTTON_DOWN -#define BTN_LEFT BUTTON_LEFT -#define BTN_PLAY BUTTON_PLAY - -#elif CONFIG_KEYPAD == ONDIO_PAD -#define BTN_QUIT BUTTON_OFF -#define BTN_RIGHT BUTTON_RIGHT -#define BTN_UP BUTTON_UP -#define BTN_DOWN BUTTON_DOWN -#define BTN_LEFT BUTTON_LEFT -#define BTN_PLAY (BUTTON_MENU | BUTTON_OFF) - - -#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) +#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) #define BTN_QUIT BUTTON_OFF #define BTN_RIGHT BUTTON_RIGHT #define BTN_UP BUTTON_UP @@ -209,110 +192,67 @@ PLUGIN_IRAM_DECLARE struct MIDIfile * mf IBSS_ATTR; -int numberOfSamples IBSS_ATTR; /* the number of samples in the current tick */ -int playingTime IBSS_ATTR; /* How many seconds into the file have we been playing? */ -int samplesThisSecond IBSS_ATTR; /* How many samples produced during this second so far? */ - +int number_of_samples IBSS_ATTR; /* the number of samples in the current tick */ +int playing_time IBSS_ATTR; /* How many seconds into the file have we been playing? */ +int samples_this_second IBSS_ATTR; /* How many samples produced during this second so far? */ long bpm IBSS_ATTR; int32_t gmbuf[BUF_SIZE*NBUF]; static unsigned int samples_in_buf; -int quit=0; - -static int midimain(const void * filename); - -enum plugin_status plugin_start(const void* parameter) -{ - int retval = 0; - - - PLUGIN_IRAM_INIT(rb) - - if(parameter == NULL) - { - rb->splash(HZ*2, " Play .MID file "); - return PLUGIN_OK; - } - rb->lcd_setfont(0); - -#if defined(HAVE_ADJUSTABLE_CPU_FREQ) - rb->cpu_boost(true); -#endif - - printf("%s", parameter); - /* rb->splash(HZ, true, parameter); */ - -#ifdef RB_PROFILE - rb->profile_thread(); -#endif - - retval = midimain(parameter); - -#ifdef RB_PROFILE - rb->profstop(); -#endif - - rb->pcm_play_stop(); - rb->pcm_set_frequency(HW_SAMPR_DEFAULT); - -#if defined(HAVE_ADJUSTABLE_CPU_FREQ) - rb->cpu_boost(false); -#endif - rb->splash(HZ, "FINISHED PLAYING"); - - if(retval == -1) - return PLUGIN_ERROR; - return PLUGIN_OK; -} - -bool swap=0; -bool lastswap=1; +bool quit = false; +bool swap = false; +bool lastswap = true; static inline void synthbuf(void) { int32_t *outptr; - int i=BUF_SIZE; + int i = BUF_SIZE; #ifndef SYNC - if(lastswap==swap) return; - lastswap=swap; + if (lastswap == swap) + return; + lastswap = swap; - outptr=(swap ? gmbuf : gmbuf+BUF_SIZE); + outptr = (swap ? gmbuf : gmbuf+BUF_SIZE); #else - outptr=gmbuf; + outptr = gmbuf; #endif /* synth samples for as many whole ticks as we can fit in the buffer */ - for(; i >= numberOfSamples; i -= numberOfSamples) + for (; i >= number_of_samples; i -= number_of_samples) { - synthSamples((int32_t*)outptr, numberOfSamples); - outptr += numberOfSamples; - if( tick() == 0 ) - quit=1; + synthSamples((int32_t*)outptr, number_of_samples); + outptr += number_of_samples; +#ifndef SYNC + /* synthbuf is called in interrupt context is SYNC is defined so it cannot yield + that bug causing the sim to crach when not using SYNC should really be fixed */ + rb->yield(); +#endif + if (tick() == 0) + quit = true; } /* how many samples did we write to the buffer? */ samples_in_buf = BUF_SIZE-i; - } void get_more(unsigned char** start, size_t* size) { #ifndef SYNC - if(lastswap!=swap) + if(lastswap != swap) { - printf("Buffer miss!"); // Comment out the printf to make missses less noticable. + printf("Buffer miss!"); /* Comment out the printf to make missses less noticable. */ } #else - synthbuf(); // For some reason midiplayer crashes when an update is forced + synthbuf(); /* For some reason midiplayer crashes when an update is forced */ #endif *size = samples_in_buf*sizeof(int32_t); #ifndef SYNC *start = (unsigned char*)((swap ? gmbuf : gmbuf + BUF_SIZE)); - swap=!swap; + swap = !swap; #else *start = (unsigned char*)(gmbuf); #endif @@ -320,12 +260,13 @@ void get_more(unsigned char** start, size_t* size) static int midimain(const void * filename) { - int notesUsed = 0; - int a=0; + int a, notes_used, vol; + bool is_playing = true; /* false = paused */ + printf("Loading file"); - mf= loadFile(filename); + mf = loadFile(filename); - if(mf == NULL) + if (mf == NULL) { printf("Error loading file."); return -1; @@ -341,7 +282,7 @@ static int midimain(const void * filename) rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); rb->audio_set_output_source(AUDIO_SRC_PLAYBACK); #endif - rb->pcm_set_frequency(SAMPLE_RATE); // 44100 22050 11025 + rb->pcm_set_frequency(SAMPLE_RATE); /* 44100 22050 11025 */ /* * tick() will do one MIDI clock tick. Then, there's a loop here that @@ -355,32 +296,27 @@ static int midimain(const void * filename) printf("Okay, starting sequencing"); - bpm=mf->div*1000000/tempo; - numberOfSamples=SAMPLE_RATE/bpm; - - + bpm = mf->div*1000000/tempo; + number_of_samples = SAMPLE_RATE/bpm; /* Skip over any junk in the beginning of the file, so start playing */ /* after the first note event */ do { - notesUsed = 0; - for(a=0; apcm_play_data(&get_more, NULL, 0); - int isPlaying = 1; /* 0 = paused */ - int vol=0; - - while(!quit) + while (!quit) { #ifndef SYNC synthbuf(); @@ -391,80 +327,121 @@ static int midimain(const void * filename) rb->reset_poweroff_timer(); /* Code taken from Oscilloscope plugin */ - switch(rb->button_get(false)) + switch (rb->button_get(false)) { - case BTN_UP: - case BTN_UP | BUTTON_REPEAT: - vol = rb->global_settings->volume; - if (vol < rb->sound_max(SOUND_VOLUME)) - { - vol++; - rb->sound_set(SOUND_VOLUME, vol); - rb->global_settings->volume = vol; - } - break; - - case BTN_DOWN: - case BTN_DOWN | BUTTON_REPEAT: - vol = rb->global_settings->volume; - if (vol > rb->sound_min(SOUND_VOLUME)) - { - vol--; - rb->sound_set(SOUND_VOLUME, vol); - rb->global_settings->volume = vol; - } - break; - - - case BTN_LEFT: + case BTN_UP: + case BTN_UP | BUTTON_REPEAT: + { + vol = rb->global_settings->volume; + if (vol < rb->sound_max(SOUND_VOLUME)) { - /* Rewinding is tricky. Basically start the file over */ - /* but run through the tracks without the synth running */ - rb->pcm_play_stop(); - seekBackward(5); - printf("Rewind to %d:%02d\n", playingTime/60, playingTime%60); - - if(isPlaying) - rb->pcm_play_data(&get_more, NULL, 0); - break; + vol++; + rb->sound_set(SOUND_VOLUME, vol); + rb->global_settings->volume = vol; } - - case BTN_RIGHT: + break; + } + + case BTN_DOWN: + case BTN_DOWN | BUTTON_REPEAT: + { + vol = rb->global_settings->volume; + if (vol > rb->sound_min(SOUND_VOLUME)) { - rb->pcm_play_stop(); - seekForward(5); - printf("Skip to %d:%02d\n", playingTime/60, playingTime%60); - - if(isPlaying) - rb->pcm_play_data(&get_more, NULL, 0); - break; + vol--; + rb->sound_set(SOUND_VOLUME, vol); + rb->global_settings->volume = vol; } - - case BTN_PLAY: + break; + } + + case BTN_LEFT: + { + /* Rewinding is tricky. Basically start the file over */ + /* but run through the tracks without the synth running */ + rb->pcm_play_stop(); + seekBackward(5); + printf("Rewind to %d:%02d\n", playing_time/60, playing_time%60); + if (is_playing) + rb->pcm_play_data(&get_more, NULL, 0); + break; + } + + case BTN_RIGHT: + { + rb->pcm_play_stop(); + seekForward(5); + printf("Skip to %d:%02d\n", playing_time/60, playing_time%60); + if (is_playing) + rb->pcm_play_data(&get_more, NULL, 0); + break; + } + + case BTN_PLAY: + { + if (is_playing) + { + printf("Paused at %d:%02d\n", playing_time/60, playing_time%60); + is_playing = false; + rb->pcm_play_stop(); + } else { - if(isPlaying == 1) - { - printf("Paused at %d:%02d\n", playingTime/60, playingTime%60); - isPlaying = 0; - rb->pcm_play_stop(); - } else - { - printf("Playing from %d:%02d\n", playingTime/60, playingTime%60); - isPlaying = 1; - rb->pcm_play_data(&get_more, NULL, 0); - } - break; + printf("Playing from %d:%02d\n", playing_time/60, playing_time%60); + is_playing = true; + rb->pcm_play_data(&get_more, NULL, 0); } + break; + } #ifdef BTN_RC_QUIT - case BTN_RC_QUIT: + case BTN_RC_QUIT: #endif - case BTN_QUIT: - quit=1; + case BTN_QUIT: + quit = true; } + } + return 0; +} +enum plugin_status plugin_start(const void* parameter) +{ + int retval; + PLUGIN_IRAM_INIT(rb) + if (parameter == NULL) + { + rb->splash(HZ*2, " Play .MID file "); + return PLUGIN_OK; } + rb->lcd_setfont(0); - return 0; +#if defined(HAVE_ADJUSTABLE_CPU_FREQ) + rb->cpu_boost(true); +#endif + + printf("%s", parameter); + /* rb->splash(HZ, true, parameter); */ + +#ifdef RB_PROFILE + rb->profile_thread(); +#endif + + retval = midimain(parameter); + +#ifdef RB_PROFILE + rb->profstop(); +#endif + + rb->pcm_play_stop(); + rb->pcm_set_frequency(HW_SAMPR_DEFAULT); + +#if defined(HAVE_ADJUSTABLE_CPU_FREQ) + rb->cpu_boost(false); +#endif + rb->splash(HZ, "FINISHED PLAYING"); + + if (retval == -1) + return PLUGIN_ERROR; + return PLUGIN_OK; } + diff --git a/apps/plugins/midi/midiutil.h b/apps/plugins/midi/midiutil.h index 4b1afa2928..ba64a00e28 100644 --- a/apps/plugins/midi/midiutil.h +++ b/apps/plugins/midi/midiutil.h @@ -32,8 +32,10 @@ #define SAMPLE_RATE SAMPR_44 /* 44100 */ #endif -#ifdef CPU_PP /* the pp based targets can't handle too many voices - mainly because they have to use 44100Hz sample rate */ +/* Some of the pp based targets can't handle too many voices + mainly because they have to use 44100Hz sample rate, this could be + improved to increase MAX_VOICES for targets that can do 22kHz */ +#ifdef CPU_PP #define MAX_VOICES 16 #else #define MAX_VOICES 24 /* Note: 24 midi channels is the minimum general midi spec implementation */ @@ -166,6 +168,8 @@ extern struct GPatch * drumSet[128]; extern struct MIDIfile * mf; -extern int numberOfSamples; +extern int number_of_samples; +extern int playing_time IBSS_ATTR; +extern int samples_this_second IBSS_ATTR; extern long bpm; diff --git a/apps/plugins/midi/sequencer.c b/apps/plugins/midi/sequencer.c index 11dd0e3f96..f97cac0130 100644 --- a/apps/plugins/midi/sequencer.c +++ b/apps/plugins/midi/sequencer.c @@ -23,10 +23,7 @@ #include "guspat.h" #include "synth.h" -extern int playingTime IBSS_ATTR; -extern int samplesThisSecond IBSS_ATTR; - -long tempo=375000; +long tempo = 375000; /* From the old patch config.... each patch is scaled. * Should be moved into patchset.cfg @@ -62,13 +59,13 @@ static inline void setVolScale(int a) static inline void setVol(int ch, int vol) { - int a=0; - chVol[ch]=vol; + int a; + chVol[ch] = vol; /* If channel volume changes, we need to recalculate the volume scale */ /* factor for all voices active on this channel */ - for(a=0; awaveforms[patchSet[chPat[ch]]->noteTable[note]]; - so->wf=wf; + struct GWaveform * wf = + patchSet[chPat[ch]]->waveforms[patchSet[chPat[ch]]->noteTable[note]]; + so->wf = wf; /* Used to be unsigned int, but math had to be done in different order to avoid overflow */ - unsigned long long delta= 0; + unsigned long long delta = 0; /* Old formula: @@ -169,10 +165,10 @@ static void findDelta(struct SynthObject * so, int ch, int note) static inline void computeDeltas(int ch) { - int a=0; - for(a = 0; awaveforms[0]; - voices[a].wf=wf; + voices[a].wf = wf; voices[a].delta = (((gustable[note]<rootFreq) * wf->sampRate / SAMPLE_RATE); - if(wf->mode & 28) + if (wf->mode & 28) // printf("\nWoah, a drum patch has a loop. Stripping the loop..."); wf->mode = wf->mode & (255-28); /* Turn it on */ - voices[a].isUsed=true; + voices[a].isUsed = true; setPoint(&voices[a], 0); } else @@ -284,16 +280,15 @@ inline void pressNote(int ch, int note, int vol) static void releaseNote(int ch, int note) { - - if(ch==9) + if (ch == 9) return; - int a=0; - for(a=0; amode & 28)) + if (voices[a].wf->mode & 28) { setPoint(&voices[a], 3); } @@ -306,10 +301,10 @@ static void sendEvent(struct Event * ev) const unsigned char status_low = ev->status & 0x0F; const unsigned char d1 = ev->d1; const unsigned char d2 = ev->d2; - switch(ev->status & 0xF0) + switch (ev->status & 0xF0) { case MIDI_CONTROL: - switch(d1) + switch (d1) { case CTRL_VOLUME: { @@ -318,7 +313,7 @@ static void sendEvent(struct Event * ev) } case CTRL_PANNING: { - chPan[status_low]=d2; + chPan[status_low] = d2; return; } case CTRL_DATAENT_MSB: @@ -365,7 +360,7 @@ static void sendEvent(struct Event * ev) return; case MIDI_NOTE_ON: - switch(d2) + switch (d2) { case 0: /* Release by vol=0 */ releaseNote(status_low, d1); @@ -381,139 +376,131 @@ static void sendEvent(struct Event * ev) return; case MIDI_PRGM: - if((status_low) != 9) + if (status_low != 9) setPatch(status_low, d1); } } void rewindFile(void) { - int i=0; - for(i=0; inumTracks; i++) + int i; + for (i = 0; i < mf->numTracks; i++) { mf->tracks[i]->delta = 0; mf->tracks[i]->pos = 0; } } - int tick(void) ICODE_ATTR; - -void seekBackward(int nsec) -{ - int notesUsed = 0, a=0; - int desiredTime = playingTime - nsec; /* Rewind 5 sec */ - - if(desiredTime < 0) - desiredTime = 0; - - /* Set controllers to default values */ - resetControllers(); - - /* Set the tempo to defalt */ - bpm=mf->div*1000000/tempo; - numberOfSamples=SAMPLE_RATE/bpm; - - - /* Reset the tracks to start */ - rewindFile(); - - /* Reset the time counter to 0 */ - playingTime = 0; - samplesThisSecond = 0; - - /* Quickly run through any initial things that occur before notes */ - do - { - notesUsed = 0; - for(a=0; anumTracks; a++) + int a, tracksAdv=0; + for (a = 0; a < mf->numTracks; a++) { struct Track * tr = mf->tracks[a]; - if(tr == NULL) + if (tr == NULL) printf("NULL TRACK: %d", a); - //BIG DEBUG STATEMENT //printf("\nTrack %2d, Event = %4d of %4d, Delta = %5d, Next = %4d", a, tr->pos, tr->numEvents, tr->delta, getEvent(tr, tr->pos)->delta); - - if(tr != NULL && (tr->pos < tr->numEvents)) + if (tr != NULL && (tr->pos < tr->numEvents)) { tr->delta++; tracksAdv++; - while(getEvent(tr, tr->pos)->delta <= tr->delta) + while (getEvent(tr, tr->pos)->delta <= tr->delta) { struct Event * e = getEvent(tr, tr->pos); - if(e->status != 0xFF) + if (e->status != 0xFF) { sendEvent(e); - if(((e->status&0xF0) == MIDI_PRGM)) + if ((e->status&0xF0) == MIDI_PRGM) { /* printf("\nPatch Event, patch[%d] ==> %d", e->status&0xF, e->d1); */ } } else { - if(e->d1 == 0x51) + if (e->d1 == 0x51) { tempo = (((short)e->evData[0])<<16)|(((short)e->evData[1])<<8)|(e->evData[2]); /* printf("\nMeta-Event: Tempo Set = %d", tempo); */ bpm=mf->div*1000000/tempo; - numberOfSamples=SAMPLE_RATE/bpm; + number_of_samples=SAMPLE_RATE/bpm; } } tr->delta = 0; tr->pos++; - if(tr->pos>=(tr->numEvents-1)) + if (tr->pos >= (tr->numEvents-1)) break; } } } - samplesThisSecond += numberOfSamples; + samples_this_second += number_of_samples; - while(samplesThisSecond >= SAMPLE_RATE) + while (samples_this_second >= SAMPLE_RATE) { - samplesThisSecond -= SAMPLE_RATE; - playingTime++; -// printf("Time: %d sec\n", playingTime); + samples_this_second -= SAMPLE_RATE; + playing_time++; } - if(tracksAdv != 0) + if (tracksAdv != 0) return 1; else return 0; } +void seekBackward(int nsec) +{ + int notes_used, a; + int desired_time = playing_time - nsec; /* Rewind 5 sec */ + + if (desired_time < 0) + desired_time = 0; + + /* Set controllers to default values */ + resetControllers(); + + /* Set the tempo to defalt */ + bpm = mf->div*1000000/tempo; + number_of_samples = SAMPLE_RATE/bpm; + + /* Reset the tracks to start */ + rewindFile(); + + /* Reset the time counter to 0 */ + playing_time = 0; + samples_this_second = 0; + + /* Quickly run through any initial things that occur before notes */ + do + { + notes_used = 0; + for (a = 0; a < MAX_VOICES; a++) + if (voices[a].isUsed) + notes_used++; + tick(); + } while (notes_used == 0); + + /* Reset the time counter to 0 */ + playing_time = 0; + samples_this_second = 0; + + /* Tick until goal is reached */ + while (playing_time < desired_time) + tick(); +} + +void seekForward(int nsec) +{ + int desired_time = playing_time + nsec; + while (tick() && playing_time < desired_time); +} + -- cgit v1.2.3