コード例 #1
0
ファイル: fluid_midi.c プロジェクト: midifi/fluidsynth
/*
 * fluid_midi_file_read_mthd
 */
int
fluid_midi_file_read_mthd(fluid_midi_file *mf)
{
    char mthd[15];
    if (fluid_midi_file_read(mf, mthd, 14) != FLUID_OK) {
        return FLUID_FAILED;
    }
    if ((FLUID_STRNCMP(mthd, "MThd", 4) != 0) || (mthd[7] != 6)
            || (mthd[9] > 2)) {
        FLUID_LOG(FLUID_ERR,
                "Doesn't look like a MIDI file: invalid MThd header");
        return FLUID_FAILED;
    }
    mf->type = mthd[9];
    mf->ntracks = (unsigned) mthd[11];
    mf->ntracks += (unsigned int) (mthd[10]) << 16;
    if ((mthd[12]) < 0) {
        mf->uses_smpte = 1;
        mf->smpte_fps = -mthd[12];
        mf->smpte_res = (unsigned) mthd[13];
        FLUID_LOG(FLUID_ERR, "File uses SMPTE timing -- Not implemented yet");
        return FLUID_FAILED;
    } else {
        mf->uses_smpte = 0;
        mf->division = (mthd[12] << 8) | (mthd[13] & 0xff);
        FLUID_LOG(FLUID_DBG, "Division=%d", mf->division);
    }
    return FLUID_OK;
}
コード例 #2
0
ファイル: fluid_midi.c プロジェクト: caomw/fluidsynth
/*
 * fluid_midi_file_read_tracklen
 */
int fluid_midi_file_read_tracklen(fluid_midi_file* mf)
{
	unsigned char length[5];
	if (fluid_midi_file_read(mf, length, 4) != FLUID_OK) {
		return FLUID_FAILED;
	}
	mf->tracklen = fluid_getlength(length);
	mf->trackpos = 0;
	mf->eot = 0;
	return FLUID_OK;
}
コード例 #3
0
ファイル: fluid_midi.c プロジェクト: midifi/fluidsynth
/*
 * fluid_midi_file_read_event
 */
int
fluid_midi_file_read_event(fluid_midi_file *mf, fluid_track_t *track, int num)
{
    int status;
    int type;
    int tempo;
    unsigned char *metadata = NULL;
    unsigned char *dyn_buf = NULL;
    unsigned char static_buf[256];
    int nominator, denominator, clocks, notes;
    fluid_midi_event_t *evt;
    int channel = 0;
    int param1 = 0;
    int param2 = 0;
    int size;

    /* read the delta-time of the event */
    if (fluid_midi_file_read_varlen(mf) != FLUID_OK) {
        return FLUID_FAILED;
    }
    mf->dtime += mf->varlen;

    /* read the status byte */
    status = fluid_midi_file_getc(mf);
    if (status < 0) {
        FLUID_LOG(FLUID_ERR, "Unexpected end of file");
        return FLUID_FAILED;
    }

    /* not a valid status byte: use the running status instead */
    if ((status & 0x80) == 0) {
        if ((mf->running_status & 0x80) == 0) {
            FLUID_LOG(FLUID_ERR, "Undefined status and invalid running status");
            return FLUID_FAILED;
        }
        fluid_midi_file_push(mf, status);
        status = mf->running_status;
    }

    /* check what message we have */

    mf->running_status = status;

    if ((status == MIDI_SYSEX)) { /* system exclusif */
        /* read the length of the message */
        if (fluid_midi_file_read_varlen(mf) != FLUID_OK) {
            return FLUID_FAILED;
        }

        if (mf->varlen) {
            FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__,
                    __LINE__, mf->varlen);
            metadata = FLUID_MALLOC(mf->varlen + 1);

            if (metadata == NULL) {
                FLUID_LOG(FLUID_PANIC, "Out of memory");
                return FLUID_FAILED;
            }

            /* read the data of the message */
            if (fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK) {
                FLUID_FREE (metadata);
                return FLUID_FAILED;
            }

            evt = new_fluid_midi_event();
            if (evt == NULL) {
                FLUID_LOG(FLUID_ERR, "Out of memory");
                FLUID_FREE (metadata);
                return FLUID_FAILED;
            }

            evt->dtime = mf->dtime;
            size = mf->varlen;

            if (metadata[mf->varlen - 1] == MIDI_EOX)
                size--;

            /* Add SYSEX event and indicate that its dynamically allocated and should be freed with event */
            fluid_midi_event_set_sysex(evt, metadata, size, TRUE);
            fluid_track_add_event(track, evt);
            mf->dtime = 0;
        }

        return FLUID_OK;

    } else if (status == MIDI_META_EVENT) { /* meta events */

        int result = FLUID_OK;

        /* get the type of the meta message */
        type = fluid_midi_file_getc(mf);
        if (type < 0) {
            FLUID_LOG(FLUID_ERR, "Unexpected end of file");
            return FLUID_FAILED;
        }

        /* get the length of the data part */
        if (fluid_midi_file_read_varlen(mf) != FLUID_OK) {
            return FLUID_FAILED;
        }

        if (mf->varlen < 255) {
            metadata = &static_buf[0];
        } else {
            FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__,
                    __LINE__, mf->varlen);
            dyn_buf = FLUID_MALLOC(mf->varlen + 1);
            if (dyn_buf == NULL) {
                FLUID_LOG(FLUID_PANIC, "Out of memory");
                return FLUID_FAILED;
            }
            metadata = dyn_buf;
        }

        /* read the data */
        if (mf->varlen) {
            if (fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK) {
                if (dyn_buf) {
                    FLUID_FREE(dyn_buf);
                }
                return FLUID_FAILED;
            }
        }

        /* handle meta data */
        switch (type) {

            case MIDI_COPYRIGHT:
                metadata[mf->varlen] = 0;
                break;

            case MIDI_TRACK_NAME:
                metadata[mf->varlen] = 0;
                fluid_track_set_name(track, (char *) metadata);
                break;

            case MIDI_INST_NAME:
                metadata[mf->varlen] = 0;
                break;

            case MIDI_LYRIC:
                break;

            case MIDI_MARKER:
                break;

            case MIDI_CUE_POINT:
                break; /* don't care much for text events */

            case MIDI_EOT:
                if (mf->varlen != 0) {
                    FLUID_LOG(FLUID_ERR, "Invalid length for EndOfTrack event");
                    result = FLUID_FAILED;
                    break;
                }
                mf->eot = 1;
                evt = new_fluid_midi_event();
                if (evt == NULL) {
                    FLUID_LOG(FLUID_ERR, "Out of memory");
                    result = FLUID_FAILED;
                    break;
                }
                evt->dtime = mf->dtime;
                evt->type = MIDI_EOT;
                fluid_track_add_event(track, evt);
                mf->dtime = 0;
                break;

            case MIDI_SET_TEMPO:
                if (mf->varlen != 3) {
                    FLUID_LOG(FLUID_ERR,
                            "Invalid length for SetTempo meta event");
                    result = FLUID_FAILED;
                    break;
                }
                tempo = (metadata[0] << 16) + (metadata[1] << 8) + metadata[2];
                evt = new_fluid_midi_event();
                if (evt == NULL) {
                    FLUID_LOG(FLUID_ERR, "Out of memory");
                    result = FLUID_FAILED;
                    break;
                }
                evt->dtime = mf->dtime;
                evt->type = MIDI_SET_TEMPO;
                evt->channel = 0;
                evt->param1 = tempo;
                evt->param2 = 0;
                fluid_track_add_event(track, evt);
                mf->dtime = 0;
                break;

            case MIDI_SMPTE_OFFSET:
                if (mf->varlen != 5) {
                    FLUID_LOG(FLUID_ERR,
                            "Invalid length for SMPTE Offset meta event");
                    result = FLUID_FAILED;
                    break;
                }
                break; /* we don't use smtp */

            case MIDI_TIME_SIGNATURE:
                if (mf->varlen != 4) {
                    FLUID_LOG(FLUID_ERR,
                            "Invalid length for TimeSignature meta event");
                    result = FLUID_FAILED;
                    break;
                }
                nominator = metadata[0];
                denominator = pow(2.0, (double) metadata[1]);
                clocks = metadata[2];
                notes = metadata[3];

                FLUID_LOG(FLUID_DBG,
                        "signature=%d/%d, metronome=%d, 32nd-notes=%d",
                        nominator, denominator, clocks, notes);

                break;

            case MIDI_KEY_SIGNATURE:
                if (mf->varlen != 2) {
                    FLUID_LOG(FLUID_ERR,
                            "Invalid length for KeySignature meta event");
                    result = FLUID_FAILED;
                    break;
                }
                /* We don't care about key signatures anyway */
                /* sf = metadata[0];
                mi = metadata[1]; */
                break;

            case MIDI_SEQUENCER_EVENT:
                break;

            default:
                break;
        }

        if (dyn_buf) {
            FLUID_LOG(FLUID_DBG, "%s: %d: free metadata", __FILE__, __LINE__);
            FLUID_FREE(dyn_buf);
        }

        return result;

    } else { /* channel messages */

        type = status & 0xf0;
        channel = status & 0x0f;

        /* all channel message have at least 1 byte of associated data */
        if ((param1 = fluid_midi_file_getc(mf)) < 0) {
            FLUID_LOG(FLUID_ERR, "Unexpected end of file");
            return FLUID_FAILED;
        }

        switch (type) {

            case NOTE_ON:
                if ((param2 = fluid_midi_file_getc(mf)) < 0) {
                    FLUID_LOG(FLUID_ERR, "Unexpected end of file");
                    return FLUID_FAILED;
                }
                break;

            case NOTE_OFF:
                if ((param2 = fluid_midi_file_getc(mf)) < 0) {
                    FLUID_LOG(FLUID_ERR, "Unexpected end of file");
                    return FLUID_FAILED;
                }
                break;

            case KEY_PRESSURE:
                if ((param2 = fluid_midi_file_getc(mf)) < 0) {
                    FLUID_LOG(FLUID_ERR, "Unexpected end of file");
                    return FLUID_FAILED;
                }
                break;

            case CONTROL_CHANGE:
                if ((param2 = fluid_midi_file_getc(mf)) < 0) {
                    FLUID_LOG(FLUID_ERR, "Unexpected end of file");
                    return FLUID_FAILED;
                }
                break;

            case PROGRAM_CHANGE:
                break;

            case CHANNEL_PRESSURE:
                break;

            case PITCH_BEND:
                if ((param2 = fluid_midi_file_getc(mf)) < 0) {
                    FLUID_LOG(FLUID_ERR, "Unexpected end of file");
                    return FLUID_FAILED;
                }

                param1 = ((param2 & 0x7f) << 7) | (param1 & 0x7f);
                param2 = 0;
                break;

            default:
                /* Can't possibly happen !? */
                FLUID_LOG(FLUID_ERR, "Unrecognized MIDI event");
                return FLUID_FAILED;
        }
        evt = new_fluid_midi_event();
        if (evt == NULL) {
            FLUID_LOG(FLUID_ERR, "Out of memory");
            return FLUID_FAILED;
        }
        evt->dtime = mf->dtime;
        evt->type = type;
        evt->channel = channel;
        evt->param1 = param1;
        evt->param2 = param2;
        evt->track = num;
        fluid_track_add_event(track, evt);
        mf->dtime = 0;
    }
    return FLUID_OK;
}
コード例 #4
0
ファイル: fluid_midi.c プロジェクト: midifi/fluidsynth
/*
 * fluid_midi_file_read_track
 */
int
fluid_midi_file_read_track(fluid_midi_file *mf, fluid_player_t *player, int num)
{
    fluid_track_t *track;
    unsigned char id[5], length[5];
    int found_track = 0;
    int skip;

    if (fluid_midi_file_read(mf, id, 4) != FLUID_OK) {
        return FLUID_FAILED;
    }
    id[4] = '\0';
    mf->dtime = 0;

    while (!found_track) {

        if (fluid_isasciistring((char *) id) == 0) {
            FLUID_LOG(FLUID_ERR,
                    "An non-ascii track header found, corrupt file");
            return FLUID_FAILED;

        } else if (strcmp((char *) id, "MTrk") == 0) {

            found_track = 1;

            if (fluid_midi_file_read_tracklen(mf) != FLUID_OK) {
                return FLUID_FAILED;
            }

            track = new_fluid_track(num);
            if (track == NULL) {
                FLUID_LOG(FLUID_ERR, "Out of memory");
                return FLUID_FAILED;
            }

            while (!fluid_midi_file_eot(mf)) {
                if (fluid_midi_file_read_event(mf, track, num) != FLUID_OK) {
                    delete_fluid_track(track);
                    return FLUID_FAILED;
                }
            }

            /* Skip remaining track data, if any */
            if (mf->trackpos < mf->tracklen)
                fluid_midi_file_skip(mf, mf->tracklen - mf->trackpos);

            fluid_player_add_track(player, track);

        } else {
            found_track = 0;
            if (fluid_midi_file_read(mf, length, 4) != FLUID_OK) {
                return FLUID_FAILED;
            }
            skip = fluid_getlength(length);
            /* fseek(mf->fp, skip, SEEK_CUR); */
            if (fluid_midi_file_skip(mf, skip) != FLUID_OK) {
                return FLUID_FAILED;
            }
        }
    }
    if (fluid_midi_file_eof(mf)) {
        FLUID_LOG(FLUID_ERR, "Unexpected end of file");
        return FLUID_FAILED;
    }
    return FLUID_OK;
}