Постобработка потоку подій MIDI

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

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

Давайте також скористаємося можливістю збору сякий статистики опотоке подій MIDI Ми простежимо за гучністю звучання нот і визначимо максимальну загальну гучність твору Ha основі цієї інформації я можу

отмасштабовані амплітуду відтвореного сигналу і уникнути переповнило-

ня Щоб не ускладнювати завдання, ми не будемо відстежувати основну гучність, гучність каналу іекспресію(Тимчасова зміна гучності каналу, що використовується для акцентування)

Лістинг 2218

void MidiRead::PostProcess() {

cerr &lt&lt &quotAnalyzing MIDI file "

/ / Аналізуємо MIDI-файл ..

double samplesPerTick / / Кількість відліків,

/ / Які необхідно

/ / Відтворити на кожен

/ / Тик MIDI

double samplesRemainingFraction / / Відкладено дрібних

/ / Звітів

samplesRemainingFraction = 00

/ / Для виявлення

/ / Максимального значення

long currentVolume = 0 long maxTotalVolume = 0 long simultaneousNotes = 0

long maxSimultaneousNotes = 0

char volume [16] [128] / / Рівень кожної

/ / З відтворюваних нот

for(int i=0i&lt16i++)

for(int j=0j&lt128j++)

volume[i][j] = 0

bool possible[16]

bool active[16]

for(int j=0j&lt16j++) { active[j] = false possible[j] = true

/ / Для визначення

/ / Використовуваних каналів

}

MidiEvent *pEvent = _events MidiEvent *pLastEvent = 0 while(pEvent) {

/ / Перетворимо затримку

/ / З тиків в відліки звуку

if (pEvent-&gtdelay &gt 0) {

float samples = pEvent-&gtdelay * samplesPerTick

+ samplesRemainingFraction

pEvent-&gtdelay = static_cast&ltunsigned long&gt(samples)

samplesRemainingFraction = samples pEvent-&gtdelay

}

/ / Відслідковуємо

/ / Максимальний рівень

int ch = pEvent-&gtstatus &amp 0x0F switch(pEvent-&gtstatus &amp 0xF0) { case 0x90:

if ((pEvent-> data [1] = 0) && possible [ch]) {active [ch] = true / / Цей канал використаний if (volume [ch] [pEvent-> data [0]]) {

/ / Нота вже включена!

/ / Відключаємо, перш ніж іти

/ / Далі ..

currentVolume = volume[ch][ pEvent-&gtdata[0] ]

simultaneousNotes–

}

volume[ch][ pEvent-&gtdata[0] ] = pEvent-&gtdata[1]

currentVolume += volume[ch][ pEvent-&gtdata[0] ]

if (currentVolume &gt maxTotalVolume)

maxTotalVolume = currentVolume

simultaneousNotes++

if (simultaneousNotes &gt maxSimultaneousNotes)

maxSimultaneousNotes = simultaneousNotes

break

}

/ / Включення ноти з нульовою

/ / Швидкістю це на самому

/ / Справі відключення ноти

/ / Перетворимо в відключення

pEvent-&gtstatus = 0x80 | ch

pEvent-> data [l] = 64 / / Co середньою швидкістю

/ / Відкидаю і обробляємо його

/ / Як відключення ноти

case 0x80:

currentVolume = volume[ch][ pEvent-&gtdata[0] ]

simultaneousNotes–

volume[ch][ pEvent-&gtdata[0] ] = 0

break

}

pLastEvent = pEvent

pEvent = pEvent-&gtnext

}

/ / Готово

cerr &lt&lt &quot. done\n"

/ / Максимальна кількість одночасно

/ / Оброблюваних нот

cerr &lt&lt &quotMaximum Simultaneous Notes: &quot &lt&lt maxSimultaneousNotes

&lt&lt &quot\n"

/ / Максимальний сумарний рівень

cerr &lt&lt &quotMaximum Total volume: &quot &lt&lt maxTotalVolume &lt&lt &quot\n"

cerr &lt&lt &quot\n"

/ / Встановлюємо частоту дискретизації

/ / На мапі інструментів

_instrumentMap-&gtSamplingRate(SamplingRate() )

}

Структура каналів залежить від файлу C метою прискорення відтворення я Ініціалізується всі вільні канали для використання спеціального обектa MidiChannelSilent, який не здійснює програвання, але є

швидким Використовувані, але ще не проініціалізувати канали ініціал-

зіруются для застосування значень за замовчуванням General MIDI

Лістинг 2219 Ініціалізація каналів

{

for(int ch=0 ch&lt 16 ch++) {

/ / Заповнюємо порожні канали

if (_channel [ch]) continue / / Вже тут

if (active[ch])

_channel[ch] = new MidiChannelSilent()

else {

int instrumentSet

if (ch==10) instrumentSet = MidiInstrumentMap::gmRhythmBank

else      instrumentSet = MidiInstrumentMap::gmMelodyBank

_channel[ch] = new MidiChannelStandard(

this, instrumentSet,

10/maxTotalVolume)

}

}

}

Хоча розглянутий процес обробки поста багато спрощує, у нього є один серйозний недолік Зараз багато експериментують з MIDI як із засобом потокового розповсюдження музичних даних по мережі Internet Результати виходять непогані, тому що потоки MIDI досить компактні, що полегшує проблеми з шириною смуги пропускання Використовуваний мною підхід не допускає подібної «потоковості», так як до початку відтворення необхідно прочитати весь потік подій

Базовий і розширений MIDI

Щоб полегшити роботу постачальникам апаратного забезпечення для персональних компютерів, специфікація мультимедійного ПК (Multimedia PC, MPC), спочатку опублікована Microsoft, визначає два рівня сумісності апаратури з MIDI Ідея полягає в тому, що системи низької цінової категорії можуть забезпечувати мінімальну базову підтримку мултітембрового синтезатора(Base Multitimbral Synthesizer), в той час як системи більш високого класу можуть забезпечувати розширену підтримку мультітембрового синтезатора(Extended Multitimbral Synthesizer) Два рівня підтримки відомі якбазовий MIDI(Base MlDI) ірозширений MIDI(Extended MIDI) Підтримка цих стандартів поступово сходить нанівець, так як все більш поширеною стає підтримка General MIDI, проте безліч файлів в архівах Internet все ще використовують ці угоди MPC

Дані стандарти мають значно меншими можливостями, ніж стандарт General MIDI B Зокрема, базовий MIDI вимагає підтримки всього шести паралельних нот мелодії на трьох інструментах та трьох паралельних

нот ритму на трьох інструментах Розширений MIDI вимагає підтримки 16 паралельних нот мелодії на 9 інструментах і 16 паралельних нот ритму на 8 інструментах Для порівняння згадаємо, що стандарт General MIDI вимагає, щоб пристрій відтворення здійснювало підтримку 16 паралельних нот мелодії на 16 інструментах і 8 паралельних нот ритму на 8 інструментах

Одна з цілей розробки цих стандартів дозволити включати в один MIDIфайл спрощену версію, яку можна програти на синтезаторі базового MIDI, і більш повну версію, яку можна програти на синтезаторі розширеного MIDI Стандарт реалізує подібний підхід шляхом поділу каналів MIDI Канали з 1-го по 10-й використовуються розширеним MIDI, з 13-го по 16-й базовим MIDI Визначення інструментів відповідають General MIDI, за винятком того, що базовий MIDI пріменякет канал 16 для мелодійних ударних інструментів Канали 11 і 12 не використовуються Стандарт MPC дозволяє авторам творів включати в один файл MIDI версії для базового і розширеного MIDI Система, що підтримує Базовий MIDI, буде програвати тільки канали з 13-го по 16-й, а система з підтримкою розширеного MIDI програватиме тільки канали з 1-го по 10-й

Визначення базовий / розширений MIDI ненадійні, так як вони вступають впротіворечіе зі стандартом General MIDI в двох аспектах По-перше, стандарт MPC підтримує включення авторами в один файл MIDI двох версій пісні і припускає, що конкретна система програватиме тільки одну з версій B стандарті General MIDI активні всі канали B результаті синтезатор General MIDI програє одночасно версії і базового, і розширеного MIDI

Більш суттєва проблема полягає в тому, що стандарт MPC розпорядженні мелодійні ударні інструменти на 10 і 16 каналах B General MIDI канал 16 це канал мелодії

K щастя, Microsoft стандартизувала спосіб позначки файлів MPC MIDI B відповідності з документом Microsoft Win32 Programmers Reference {Керівництво програміста в середовищі Microsoft Win32)файли MIDI, сформовані відповідно до стандарту MPC, повинні відповідним чином позначатися Ця позначка полягає у використанні специфічного для синтезатора метасобитія (воно обговорюється пізніше), що містить З-байтний ідентифікатор виробника: ID

00 00 65 Зустрічаючи це метасобитіе, Windows програє файл згідно стандартам MPC, в іншому випадку просить користувача конфігурувати пристрій відтворення MIDI

B нашому випадку можна імітувати пристрій розширеного MIDI, очис-

тив канали з 11-го по 16-й

Лістинг 2220 Перевірка на подію MPC MIDI

if ((pEvent-> status == 0xFF) / / Метасобитіе

&& (PEvent-> data [0] == 127) / / Специфічне

/ / Для секвенсора

&amp&amp (pEvent-&gtmetaData-&gtlength &gt= 3)

&& (PEvent-> metaData-> data [0] == 0) / / 3-байтний ідентифікатор

/ / Виробника

&amp&amp (pEvent-&gtmetaData-&gtdata[1] == 0)  // 0 0 65 = Microsoft

&amp&amp (pEvent-&gtmetaData-&gtdata[2] == 65)

) {

/ / Це файл MPC MIDI

cerr &lt&lt &quotThis is an MPC MIDI file\n"

/ / Звільняємо канали з 11

/ / По 16 (у нас

/ / Розширене пристрій

// MIDI)

for (int i=10i&lt16i++)

if(_channel[i]) {

_channel[i] = new MidiChannelSilent()

possible [i] = false / / He враховуємо ноти на

/ / Цих каналах

}

}

Джерело: Кінтцель Т Керівництво програміста по роботі зі звуком = 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>

*

*