Декодировать поле переменной длины MIDI

Как декодировать поля переменной длины в MIDI? Описание, найденное в [1], дает только несколько примеров, не упоминая, что происходит, если установлен старший бит. Это мой текущий код:

uint32_t MuStudio::MIDI::FileReader::varfieldGet()
    {
//  Note: always swap bytes on return since the loop reads in LE fashion since it
//  it cannot be known a priori how many bytes to read

    uint32_t ret=0;
    uint8_t byte_in;
    uint8_t k=0;
    while(!m_source.eof())
        {
        byte_in=m_source.byteGet();
        if(byte_in&0x80)
            {
            if(k==sizeof(ret))
                {break;}
        //  How to continue here?
            }
        else
            {return __builtin_bswap32(ret|(byte_in<<k));}
        }

    while(!m_source.eof() && byte_in&0x80)
        {byte_in=m_source.byteGet();}

    return __builtin_bswap32(ret);
    }

[1] http://www.music.mcgill.ca/~ich/classes/mumt306/midiformat.pdf


person user877329    schedule 12.07.2014    source источник


Ответы (1)


Значения переменной длины являются не прямыми, а прямыми, но это не имеет значения, потому что вы читаете их по одному байту за раз и создаете результат в своем родном порядке байтов.

Когда вы комбинируете байт с предыдущими прочитанными битами, вы должны сдвигать предыдущие биты, а не текущий байт.

Когда установлен старший бит, вам не нужно делать ничего особенного; когда бит очищен, вы должны остановиться:

uint32_t varfieldGet()
{
    uint32_t ret = 0;
    uint8_t byte_in;

    for (;;)
    {
        if (m_source.eof())
            // return error
        byte_in = m_source.byteGet();
        ret = (ret << 7) | (byte_in & 0x7f);
        if (!(byte_in & 0x80))
            return ret;
    }
}
person CL.    schedule 12.07.2014
comment
Как вы относитесь к переполнению в ret? - person user877329; 12.07.2014
comment
Этот код не работает. Вы можете изменить цикл for. - person CL.; 13.07.2014
comment
Является ли условие завершения n_iter==sizeof(uint32_t) - person user877329; 13.07.2014