コード例 #1
0
ファイル: midiplay.c プロジェクト: Rockbox/rockbox
enum plugin_status plugin_start(const void* parameter)
{
    int retval;

    if (parameter == NULL)
    {
        rb->splash(HZ*2, " Play .MID file ");
        return PLUGIN_OK;
    }
    rb->lcd_setfont(FONT_SYSFIXED);

    midi_debug("%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);

    rb->splash(HZ, "FINISHED PLAYING");

    if (retval == -1)
        return PLUGIN_ERROR;
    return PLUGIN_OK;
}
コード例 #2
0
ファイル: midiplay.c プロジェクト: ntj/rockbox
void get_more(unsigned char** start, size_t* size)
{
#ifndef SYNC
    if(lastswap != swap)
    {
        midi_debug("Buffer miss!"); /* Comment out the midi_debug to make missses less noticable. */
    }

#else
    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;
#else
    *start = (unsigned char*)(gmbuf);
#endif
}
コード例 #3
0
ファイル: midifile.c プロジェクト: 4nykey/rockbox
int readID(int file)
{
    char id[5];
    id[4]=0;
    BYTE a;

    for(a=0; a<4; a++)
        id[a]=readChar(file);
    if(eof(file))
    {
        midi_debug("End of file reached.");
        return ID_EOF;
    }
    if(rb->strcmp(id, "MThd")==0)
        return ID_MTHD;
    if(rb->strcmp(id, "MTrk")==0)
        return ID_MTRK;
    if(rb->strcmp(id, "RIFF")==0)
        return ID_RIFF;
    return ID_UNKNOWN;
}
コード例 #4
0
ファイル: midiplay.c プロジェクト: ntj/rockbox
enum plugin_status plugin_start(const void* parameter)
{
    int retval;

    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

    midi_debug("%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;
}
コード例 #5
0
ファイル: midifile.c プロジェクト: 4nykey/rockbox
struct Track * readTrack(int file)
{
    struct Track * trk = &tracks[curr_track++];
    rb->memset(trk, 0, sizeof(struct Track));

    trk->size = readFourBytes(file);
    trk->pos = 0;
    trk->delta = 0;

    int numEvents=0;

    int pos = rb->lseek(file, 0, SEEK_CUR);

    while(readEvent(file, NULL))    /* Memory saving technique                   */
        numEvents++;                /* Attempt to read in events, count how many */
                                    /* THEN allocate memory and read them in     */
    rb->lseek(file, pos, SEEK_SET);

    int trackSize = (numEvents+1) * sizeof(struct Event);
    void * dataPtr = malloc(trackSize);
    trk->dataBlock = dataPtr;

    numEvents=0;

    while(readEvent(file, dataPtr))
    {
        if(trackSize < dataPtr-trk->dataBlock)
        {
            midi_debug("Track parser memory out of bounds");
            exit(1);
        }
        dataPtr+=sizeof(struct Event);
        numEvents++;
    }
    trk->numEvents = numEvents;

    return trk;
}
コード例 #6
0
ファイル: midiplay.c プロジェクト: Rockbox/rockbox
static void get_more(const void** start, size_t* size)
{
#ifndef SYNC
    if(lastswap != swap)
    {
        midi_debug("Buffer miss!"); /* Comment out the midi_debug to make missses less noticable. */
    }

#else
    synthbuf();  /* For some reason midiplayer crashes when an update is forced */
#endif

    *size = samples_in_buf*sizeof(int32_t);
#ifndef SYNC
    *start = swap ? gmbuf : gmbuf + BUF_SIZE;
    swap = !swap;
#else
    *start = gmbuf;
#endif
    if (samples_in_buf==0) {
        *start = NULL;
        quit = true;    /* this was the last buffer to play */
    }
}
コード例 #7
0
ファイル: midiplay.c プロジェクト: Rockbox/rockbox
static int midimain(const void * filename)
{
    int a, notes_used, vol;
    bool is_playing = true;  /* false = paused */

#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
    rb->cpu_boost(true);
#endif
    midi_debug("Loading file");
    mf = loadFile(filename);

    if (mf == NULL)
    {
        midi_debug("Error loading file.");
#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
        rb->cpu_boost(false);
#endif
        return -1;
    }

    if (initSynth(mf, ROCKBOX_DIR "/patchset/patchset.cfg",
        ROCKBOX_DIR "/patchset/drums.cfg") == -1)
    {
#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
        rb->cpu_boost(false);
#endif
        return -1;
    }

    rb->pcm_play_stop();
#if INPUT_SRC_CAPS != 0
    /* Select playback */
    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 */

    /*
        * tick() will do one MIDI clock tick. Then, there's a loop here that
        * will generate the right number of samples per MIDI tick. The whole
        * MIDI playback is timed in terms of this value.. there are no forced
        * delays or anything. It just produces enough samples for each tick, and
        * the playback of these samples is what makes the timings right.
        *
        * This seems to work quite well. On a laptop, anyway.
        */

    midi_debug("Okay, starting sequencing");

    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
    {
        notes_used = 0;
        for (a = 0; a < MAX_VOICES; a++)
            if (voices[a].isUsed)
                notes_used++;
        tick();
    } while (notes_used == 0);

#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
    rb->cpu_boost(false);
#endif

    playing_time = 0;
    samples_this_second = 0;

    synthbuf();
    rb->pcm_play_data(&get_more, NULL, NULL, 0);

    while (!quit)
    {
    #ifndef SYNC
        synthbuf();
    #endif
        rb->yield();

        /* Prevent idle poweroff */
        rb->reset_poweroff_timer();

        /* Code taken from Oscilloscope plugin */
        switch (rb->button_get(false))
        {
            case MIDI_VOL_UP:
            case MIDI_VOL_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 MIDI_VOL_DOWN:
            case MIDI_VOL_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 MIDI_REWIND:
            {
                /* Rewinding is tricky. Basically start the file over */
                /* but run through the tracks without the synth running */
                rb->pcm_play_stop();
#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
                rb->cpu_boost(true);
#endif
                seekBackward(5);
#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
                rb->cpu_boost(false);
#endif
                lastswap = !swap;
                synthbuf();
                midi_debug("Rewind to %d:%02d\n", playing_time/60, playing_time%60);
                if (is_playing)
                    rb->pcm_play_data(&get_more, NULL, NULL, 0);
                break;
            }

            case MIDI_FFWD:
            {
                rb->pcm_play_stop();
                seekForward(5);
                lastswap = !swap;
                synthbuf();
                midi_debug("Skip to %d:%02d\n", playing_time/60, playing_time%60);
                if (is_playing)
                    rb->pcm_play_data(&get_more, NULL, NULL, 0);
                break;
            }

            case MIDI_PLAYPAUSE:
            {
                if (is_playing)
                {
                    midi_debug("Paused at %d:%02d\n", playing_time/60, playing_time%60);
                    is_playing = false;
                    rb->pcm_play_stop();
                } else
                {
                    midi_debug("Playing from %d:%02d\n", playing_time/60, playing_time%60);
                    is_playing = true;
                    rb->pcm_play_data(&get_more, NULL, NULL, 0);
                }
                break;
            }

#ifdef MIDI_RC_QUIT
            case MIDI_RC_QUIT:
#endif
            case MIDI_QUIT:
                quit = true;
        }
    }
    return 0;
}
コード例 #8
0
ファイル: midifile.c プロジェクト: 4nykey/rockbox
struct MIDIfile * loadFile(const char * filename)
{
    struct MIDIfile * mfload;
    int file = rb->open (filename, O_RDONLY);

    if(file < 0)
    {
        midi_debug("Could not open file");
        return NULL;
    }

    mfload = &midi_file;

    rb->memset(mfload, 0, sizeof(struct MIDIfile));

    int fileID = readID(file);
    if(fileID != ID_MTHD)
    {
        if(fileID == ID_RIFF)
        {
            midi_debug("Detected RMID file");
            midi_debug("Looking for MThd header");
            char dummy[17];
            rb->read(file, &dummy, 16);
            if(readID(file) != ID_MTHD)
            {
                rb->close(file);
                midi_debug("Invalid MIDI header within RIFF.");
                return NULL;
            }

        } else
        {
            rb->close(file);
            midi_debug("Invalid file header chunk.");
            return NULL;
        }
    }

    if(readFourBytes(file)!=6)
    {
        rb->close(file);
        midi_debug("Header chunk size invalid.");
        return NULL;
    }

    if(readTwoBytes(file)==2)
    {
        rb->close(file);
        midi_debug("MIDI file type 2 not supported");
        return NULL;
    }

    mfload->numTracks = readTwoBytes(file);
    mfload->div = readTwoBytes(file);

    int track=0;

    midi_debug("File has %d tracks.", mfload->numTracks);

    while(! eof(file) && track < mfload->numTracks)
    {
        unsigned char id = readID(file);


        if(id == ID_EOF)
        {
            if(mfload->numTracks != track)
            {
                midi_debug("Warning: file claims to have %d tracks. I only see %d here.", mfload->numTracks, track);
                mfload->numTracks = track;
            }
            rb->close(file);
            return mfload;
        }

        if(id == ID_MTRK)
        {
            mfload->tracks[track] = readTrack(file);
            track++;
        } else
        {
            midi_debug("SKIPPING TRACK");
            int len = readFourBytes(file);
            while(--len)
                readChar(file);
        }
    }

    rb->close(file);
    return mfload;

}
コード例 #9
0
ファイル: midifile.c プロジェクト: 4nykey/rockbox
/* Returns 0 if done, 1 if keep going */
static int readEvent(int file, void * dest)
{
    struct Event dummy;
    struct Event * ev = (struct Event *) dest;

    if(ev == NULL)
        ev = &dummy; /* If we are just counting events instead of loading them */

    ev->delta = readVarData(file);


    int t=readChar(file);

    if((t&0x80) == 0x80) /* if not a running status event */
    {
        ev->status = t;
        if(t == 0xFF)
        {
            ev->d1 = readChar(file);
            ev->len = readVarData(file);

            /* Allocate and read in the data block */
            if(dest != NULL)
            {
                /* Null-terminate for text events */
                ev->evData = malloc(ev->len+1); /* Extra byte for the null termination */

                rb->read(file, ev->evData, ev->len);
                ev->evData[ev->len] = 0;

                switch(ev->d1)
                {
                    case 0x01:  /* Generic text */
                    {
                        midi_debug("Text: %s", ev->evData);
                        break;
                    }

                    case 0x02:  /* A copyright string within the file */
                    {
                        midi_debug("Copyright: %s", ev->evData);
                        break;
                    }

                    case 0x03:  /* Sequence of track name */
                    {
                        midi_debug("Name: %s", ev->evData);
                        break;
                    }

                    case 0x04:  /* Instrument (synth) name */
                    {
                        midi_debug("Instrument: %s", ev->evData);
                        break;
                    }

                    case 0x05:  /* Lyrics. These appear on the tracks at the right times */
                    {           /* Usually only a small 'piece' of the lyrics.           */
                                /* Maybe the sequencer should print these at play time?  */
                        midi_debug("Lyric: %s", ev->evData);
                        break;
                    }

                    case 0x06:  /* Text marker */
                    {
                        midi_debug("Marker: %s", ev->evData);
                        break;
                    }


                    case 0x07:  /* Cue point */
                    {
                        midi_debug("Cue point: %s", ev->evData);
                        break;
                    }

                    case 0x08:  /* Program name */
                    {
                        midi_debug("Patch: %s", ev->evData);
                        break;
                    }


                    case 0x09:  /* Device name. Very much irrelevant here, though. */
                    {
                        midi_debug("Port: %s", ev->evData);
                        break;
                    }
                }
            }
            else
            {
                /*
                 * Don't allocate anything, just see how much it would take
                 * To make memory usage efficient
                 */
                unsigned int a=0;
                for(a=0; a<ev->len; a++)
                    readChar(file); //Skip skip
            }

            if(ev->d1 == 0x2F)
            {
                return 0;   /* Termination meta-event */
            }
        } else              /* If part of a running status event */
        {
            rStatus = t;
            ev->status = t;
            ev->d1 = readChar(file);

            if (  ((t & 0xF0) != 0xD0) && ((t & 0xF0) != 0xC0) && ((t & 0xF0) > 0x40) )
            {
                ev->d2 = readChar(file);
            } else
                ev->d2 = 127;
        }
    } else  /* Running Status */
    {
        ev->status = rStatus;
        ev->d1 = t;
        if (  ((rStatus & 0xF0) != 0xD0) && ((rStatus & 0xF0) != 0xC0) && ((rStatus & 0xF0) > 0x40) )
        {
            ev->d2 = readChar(file);
        } else
            ev->d2 = 127;
    }
    return 1;
}