⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smf.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 2 页
字号:
        return -1;    length = ReadVarInt (s);    if (length < 0)        return -1;    payload = malloc (length + 1);    if ((payload == NULL)     || (stream_Read (s, payload, length) != length))    {        free (payload);        return -1;    }    payload[length] = '\0';    switch (type)    {        case 0x00: /* Sequence Number */            break;        case 0x01: /* Text (comment) */            EnsureUTF8 ((char *)payload);            msg_Info (p_demux, "Text      : %s", (char *)payload);            break;        case 0x02: /* Copyright */            EnsureUTF8 ((char *)payload);            msg_Info (p_demux, "Copyright : %s", (char *)payload);            break;        case 0x03: /* Track name */            EnsureUTF8 ((char *)payload);            msg_Info (p_demux, "Track name: %s", (char *)payload);            break;        case 0x04: /* Instrument name */            EnsureUTF8 ((char *)payload);            msg_Info (p_demux, "Instrument: %s", (char *)payload);            break;        case 0x05: /* Lyric (one syllable) */            /*EnsureUTF8 ((char *)payload);*/            break;        case 0x06: /* Marker text */            EnsureUTF8 ((char *)payload);            msg_Info (p_demux, "Marker    : %s", (char *)payload);        case 0x07: /* Cue point (WAVE filename) */            EnsureUTF8 ((char *)payload);            msg_Info (p_demux, "Cue point : %s", (char *)payload);            break;        case 0x08: /* Program/Patch name */            EnsureUTF8 ((char *)payload);            msg_Info (p_demux, "Patch name: %s", (char *)payload);            break;        case 0x09: /* MIDI port name */            EnsureUTF8 ((char *)payload);            msg_Dbg (p_demux, "MIDI port : %s", (char *)payload);            break;        case 0x2F: /* End of track */            if (tr->end != stream_Tell (s))            {                msg_Err (p_demux, "misplaced end of track");                ret = -1;            }            break;        case 0x51: /* Tempo */            if (length == 3)            {                uint32_t uspqn = (payload[0] << 16)                               | (payload[1] << 8) | payload[2];                unsigned tempo = 60 * 1000000 / (uspqn ? uspqn : 1);                msg_Dbg (p_demux, "tempo: %uus/qn -> %u BPM",                         (unsigned)uspqn, tempo);                if (tempo < TEMPO_MIN)                {                    msg_Warn (p_demux, "tempo too slow -> %u BPM", TEMPO_MIN);                    tempo = TEMPO_MIN;                }                else                if (tempo > TEMPO_MAX)                {                    msg_Warn (p_demux, "tempo too fast -> %u BPM", TEMPO_MAX);                    tempo = TEMPO_MAX;                }                date_Change (&p_sys->pts, p_sys->ppqn * tempo, 60);            }            else                ret = -1;            break;        case 0x54: /* SMPTE offset */            if (length == 5)                msg_Warn (p_demux, "SMPTE offset not implemented");            else                ret = -1;            break;        case 0x58: /* Time signature */            if (length == 4)                ;            else                ret = -1;            break;        case 0x59: /* Key signature */            if (length == 2)                ;            else                ret = -1;            break;        case 0x7f: /* Proprietary event */            msg_Dbg (p_demux, "ignored proprietary SMF Meta Event (%d bytes)",                     length);            break;        default:            msg_Warn (p_demux, "unknown SMF Meta Event type 0x%02X (%d bytes)",                      type, length);    }    free (payload);    return 0;}staticint HandleMessage (demux_t *p_demux, mtrk_t *tr){    stream_t *s = p_demux->s;    block_t *block;    uint8_t first, event;    unsigned datalen;    if (stream_Seek (s, tr->offset)     || (stream_Read (s, &first, 1) != 1))        return -1;    event = (first & 0x80) ? first : tr->running_event;    switch (event & 0xf0)    {        case 0xF0: /* System Exclusive */            switch (event)            {                case 0xF0: /* System Specific */                {                    /* TODO: don't skip these */                    stream_Read (s, NULL, 1); /* Manuf ID */                    for (;;)                    {                        uint8_t c;                        if (stream_Read (s, &c, 1) != 1)                            return -1;                        if (c == 0xF7)                            goto skip;                    }                    /* never reached */                }                case 0xFF: /* SMF Meta Event */                    if (HandleMeta (p_demux, tr))                        return -1;                    /* We MUST NOT pass this event forward. It would be                     * confused as a MIDI Reset real-time event. */                    goto skip;                case 0xF1:                case 0xF3:                    datalen = 1;                    break;                case 0xF2:                    datalen = 2;                    break;                case 0xF4:                case 0xF5:                    /* We cannot handle undefined "common" (non-real-time)                     * events inside SMF, as we cannot differentiate a                     * one byte delta-time (< 0x80) from event data. */                case 0xF7: /* End of sysex -> should never happen(?) */                    msg_Err (p_demux, "unknown MIDI event 0x%02X", event);                    return -1; /* undefined events */                default:                    datalen = 0;                    break;            }        case 0xC0:        case 0xD0:            datalen = 1;            break;        default:            datalen = 2;            break;    }    /* FIXME: one message per block is very inefficient */    block = block_New (p_demux, 1 + datalen);    if (block == NULL)        goto skip;    block->p_buffer[0] = event;    if (first & 0x80)    {        stream_Read (s, block->p_buffer + 1, datalen);    }    else    {        if (datalen == 0)        {            msg_Err (p_demux, "malformatted MIDI event");            return -1; /* can't use implicit running status with empty payload! */        }        block->p_buffer[1] = first;        if (datalen > 1)            stream_Read (s, block->p_buffer + 2, datalen - 1);    }    block->i_dts = block->i_pts = date_Get (&p_demux->p_sys->pts);    es_out_Send (p_demux->out, p_demux->p_sys->es, block);skip:    if (event < 0xF8)        /* If event is not real-time, update running status */        tr->running_event = event;    tr->offset = stream_Tell (s);    return 0;}/***************************************************************************** * Demux: read chunks and send them to the synthetizer ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, 1 otherwise *****************************************************************************/static int Demux (demux_t *p_demux){    stream_t *s = p_demux->s;    demux_sys_t *p_sys = p_demux->p_sys;    uint64_t     pulse = p_sys->pulse, next_pulse = UINT64_MAX;    if (pulse == UINT64_MAX)        return 0; /* all tracks are done */    es_out_Control (p_demux->out, ES_OUT_SET_PCR, date_Get (&p_sys->pts));    for (unsigned i = 0; i < p_sys->trackc; i++)    {        mtrk_t *track = p_sys->trackv + i;        while (track->next == pulse)        {            if (HandleMessage (p_demux, track)             || ReadDeltaTime (s, track))            {                msg_Err (p_demux, "fatal parsing error");                return VLC_EGENERIC;            }        }        if (track->next < next_pulse)            next_pulse = track->next;    }    mtime_t cur_tick = (date_Get (&p_sys->pts) + 9999) / 10000, last_tick;    if (next_pulse != UINT64_MAX)        last_tick = date_Increment (&p_sys->pts, next_pulse - pulse) / 10000;    else        last_tick = cur_tick + 1;    /* MIDI Tick emulation (ping the decoder every 10ms) */    while (cur_tick < last_tick)    {        block_t *tick = block_New (p_demux, 1);        if (tick == NULL)            break;        tick->p_buffer[0] = 0xF9;        tick->i_dts = tick->i_pts = cur_tick++ * 10000;        es_out_Send (p_demux->out, p_sys->es, tick);    }    p_sys->pulse = next_pulse;    return 1;}/***************************************************************************** * Control: *****************************************************************************/static int Control (demux_t *p_demux, int i_query, va_list args){    demux_sys_t *p_sys = p_demux->p_sys;    switch (i_query)    {        case DEMUX_GET_TIME:        {            *(va_arg (args, int64_t *)) = date_Get (&p_sys->pts);            return 0;        }#if 0        /* TODO: */        case DEMUX_SET_TIME:        case DEMUX_GET_POSITION:        case DEMUX_SET_POSITION:        case DEMUX_GET_LENGTH:#endif    }    return VLC_EGENERIC;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -