Доріжки MIDI

Зауважимо, що доріжка відрізняється від каналу MIDI Хоча найбільш поширений підхід для многодорожечной файлу програвати кожну доріжку в окремому каналі, композитори можуть залучити стільки доріжок, скільки захочуть, і будь-яким чином використовувати їх для гри на інструментах по різних каналах

Внутрішня структура доріжки являє собою просту послідовність подій MIDI, кожному з яких передує значеннядельта-часу (Відносного часу)

Цілі значення змінної довжини

З економії місця файли MIDI використовують цілі значення змінної довжини для зберігання значень дельта-часу та інших важливих параметрів Це дозволяє найбільш поширені значення (такі як нуль) зберігати в одному байті і одночасно обробляти значення розміром аж до 32 біт

B даному форматі в кожному байті зберігається 7 біт найстарший показує, чи є цей байт останнім (старший біт дорівнює нулю) або за ним ідуть інші (старший біт дорівнює одиниці)

Наступний короткий фрагмент коду зчитує ціле значення змінної довжини з потоку istream Він зберігає кількість прочитаних байтів у змінній * size

Лістинг 223 Читання цілих чисел змінної довжини

static unsigned long ReadVarInt(istream &ampin, int *size) {

*size = 0

unsigned long 1, retVal = 0

do {

l = static_cast&ltunsigned long&gt(inget()) &amp 255 (*size)++

if (*size &gt 6) {

cerr &lt&lt &quotUnterminated variable integer\n"

exit(1)

}

retVal = (retVal &lt&lt 7) + (l &amp 0x7F)

} while (l &amp 0x80)

return retVal

}

Відносний час

Події MIDI відбуваються в певні моменти часу Існують два способи обліку подібної інформації Можна зберігати абсолютний час виникнення події або інтервали часу між подіями Файли MIDI використовують останній підхід Кожна подія випереджається числом, що показує кількістьтиків,відокремлюють його від попередньої події (Більш докладно питання синхронізації MIDI, а також способи визначення тривалості тика описані в розділі «Синхронізація MIDI» в цієї глави)

Точна тривалість тика залежить від формату часу, зазначеного в заголовки-

ке, і може бути змінена спеціальним подією у межах файла

Читання доріжок MIDI

Як я вже говорив, доріжка MIDI це список подій MIDI, кожне з яких передує значенням дельта-часу Кожен блок у файлі MIDI має певну довжину, тому ми повинні уважно стежити за кількістю прочитаних байтів, щоб знати, коли закінчиться інформація доріжки Якщо це не перша доріжка, вам слід упевнитися, що події вставляються відповідним чином у зберігається в памяті список подій

Лістинг 224 Читання блоку доріжки MIDI

void MidiRead::ReadTracks() {

int tracksRead = 0

/ / Читаємо залишилися блоки

while (_streameof() &amp&amp (tracksRead &lt _numberTracks)) {

unsigned long chunkType = ReadIntMsb(_stream,4)

long bytesRemaining = ReadIntMsb(_stream,4)

if (_streameof ()) continue / / Пропускаємо залишилася

/ / Частина циклу

/ / Якщо блок не відноситься

/ / До блоків MTrk, пропускаємо його

if (chunkType = ChunkName(&quotM&quot,T,r,k)) {

char name[5]

name[0] = chunkType &gt&gt 24     name[1] = chunkType &gt&gt 16 name[2] = chunkType &gt&gt 8           name[3] = chunkType name[4] = 0

/ / Блок ні розпізнаний

cerr &lt&lt &quotUnrecognized chunk `&quot &lt&lt name &lt&lt &quot&quot\n" SkipBytes(_stream,bytesRemaining)

continue / / Зворотно на початок циклу while

}

tracksRead++

/ / Читаємо тільки першу доріжку

/ / У файлі типу 2

if ((_fileType == 2) &amp (tracksRead &gt 1)) { SkipBytes(_stream,bytesRemaining) continue

}

MidiEvent *pLastEvent = 0

while((bytesRemaining &gt 0)&amp&amp(_streameof())) { MidiEvent *pEvent = new MidiEvent

pEvent-&gttrack = tracksRead

if(bytesRemaining &lt 0) {

cerr &lt&lt &quotContents of track chunk were too long\n"

}

}

}

}

Як і при написанні будь-якої програми додавання значення в список, для внесення події MIDI у відповідний список необхідно розглянути два випадки: перший коли подія вставляється в початок списку (в цьому випадку потрібно

оновити заголовок списку), і другий коли подія приходить в середину спис-

ка (у цьому випадку оновлюється інший покажчик next)

Положення ускладнюється необхідністю своєчасно вставляти подія і неможливістю відповідним чином виправляти затримки

Лістинг 225 Вставка події MIDI в список

if ( _events

|| (pLastEvent &amp&amp (_events-&gtdelay &gt pEvent-&gtdelay))) {

/ / Ця подія йде в титул списку

pEvent-&gtnext = _events

_events = pLastEvent = pEvent

} Else {/ / He в початок списку

if ( pLastEvent) {/ / Переходимо за перший елемент списку

pLastEvent = _events

pEvent-&gtdelay = _events-&gtdelay

}

while(pLastEvent-&gtnext

/ / Пропускаємо події,

/ / Що сталися раніше

&amp&amp pLastEvent-&gtnext-&gtdelay &lt= pEvent-&gtdelay ) { pEvent-&gtdelay = pLastEvent-&gtnext-&gtdelay pLastEvent = pLastEvent-&gtnext

}

/ / Вклеюють в список

pEvent-&gtnext = pLastEvent-&gtnext

pLastEvent-&gtnext = pEvent

}

if (pEvent-> next) / / Якщо є наступні елементи,

/ / То зменшуємо затримку

pEvent-&gtnext-&gtdelay = pEvent-&gtdelay

pLastEvent = pEvent / / Остання подія в цій доріжці

Джерело: Кінтцель Т Керівництво програміста по роботі зі звуком = A Programmers Guide to Sound: Пер з англ М: ДМК Пресс, 2000 432 с, іл (Серія «Для програмістів»)

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*