Главная » Программирование звука » Воспроизведение потока событий MIDI

0

Теперь,  когда  MIDI  уже  считаны  в  память,  а  дельты  преобразованы  в  количество  отсчетов,  осуществить  проигрывание  событий  достаточно  просто.  Метод GetSamples быстро  просматривает  поток  событий;  для  каждого  дельта  интервала,  в  соответствии  с  его  длительностью,  осуществляется  проигрывание  всех  каналов; каждое событие направляется в соответствующий канал.

Листинг 22.21. Воспроизведение событий MIDI

size_t MidiRead::GetSamples(AudioSample *buffer, size_t numSamples) {

_currentEvent = _events; // Начинаем с  первого  события.

_samplesRemaining = 0;

}

for(size_t i=0; i<numSamples; i++)

buffer[i]=0;

size_t samplesReturned = 0;

while (_currentEvent && (numSamples>0)) {

if (_samplesRemaining > 0) {

size_t samplesToPlay = numSamples;

if (samplesToPlay > _samplesRemaining)

samplesToPlay = _samplesRemaining;

for (int i=0;i<16;i++)

_channel[i]->AddSamples(buffer,samplesToPlay);

buffer += samplesToPlay;

samplesReturned += samplesToPlay;

_samplesRemaining = samplesToPlay;

numSamples = samplesToPlay;

if (numSamples == 0)

return samplesReturned;

}

_samplesRemaining += _currentEvent->delay;

_currentEvent = _currentEvent->next;

}

return samplesReturned;

}

Большинство сообщений каналов направляется в отдельный канал.

Листинг 22.22. Воспроизведение одного события MIDI

int ch = _currentEvent->status & 0xF; switch(_currentEvent->status & 0xF0) { case 0x80:        // Отключение  ноты.

_channel[ch]->EndNote(_currentEvent->data[0],_currentEvent-

>data[1] ) ;

break;

case 0x90:        // Включение  ноты.

if (_currentEvent->data[1] = = 0)

_channel[ch]->EndNote(_currentEvent->data[0], 64);

else

_channel[ch]->StartNote(_currentEvent->data[0],

_currentEvent->data[1]);

break;

case 0xA0:        // Ключ  послекасания.

_channel[ch]->KeyAftertouch(_currentEvent->data[0],

_currentEvent->data[1] );

break;

case 0xB0:        // Смена   режима.

_channel[ch]->Mode(_currentEvent->data[0],

_currentEvent->data[1]) ;

break;

case 0xC0:        // Программируем  канал.

_channel[ch]->Program(_currentEvent->data[0]);

break;

case 0xD0:        // Канал  послекасания.

_channel[ch]->ChannelAftertouch(_currentEvent->data[0]);

break;

case 0xE0:        // Изменение высоты тона  ("колесо  высоты").

_channel[ch]->PitchBend(_currentEvent->data[1]*12 8

+ _currentEvent->data[0]);

break;

case 0xF0:        // Особые   события.

if(_currentEvent->status == 0xFF) {      // Метасобытие.

switch(_currentEvent->data[0]) {

case 0: break;               // Порядковый номер  дорожки.

case 1: case 2: case 3: case 4: case 5:

case 6: case 7: case 8: case 9: case 10:

case 11: case 12: case 13: case 14: case 15:

break;                   // Текстовый  коментарий.

case 47: break;              // Конец   дорожки.

case 81: break;              // Темп.

case 88: break;              // Сигнатура времени.

case 89: break;              // Тональность.

case 127: break;             // Специфичное для  секвенсора.

// Дорожка  … (Мета   …)

default: fprintf(stderr,"Track %2d: (Meta 0x%02x)\n",

_currentEvent->track,

_currentEvent->data[0]);

}

} else if(_currentEvent->status == 0xF0) {

// Эксклюзивное  событие.

// Дорожка … (эксклюзивное

// событие).

fprintf(stderr,"Track %2d: (Sysex Event)\n",

_currentEvent->track);

} else if(_currentEvent->status == 0xF7) {

// Специальное эксклюзивное

// событие.

// Дорожка … (специальное

// эксклюзивное событие).

fprintf(stderr,"Track %2d: (Special Sysex Event)\n",

_currentEvent->track);

} else {

// Дорожка  … : Статус:

fprintf(stderr,"Track %2d: ",_currentEvent->track);

fprintf(stderr, "Status: 0x%02x\n", _currentEvent->status);

}

break;

default:                          // Есть события,  которые

// не   рассмотрены  выше?

// Дорожка … Ошибочный  статус …

fprintf(stderr,"Track %2d, Bad Status: 0x%x\n",

_currentEvent->track,_currentEvent->status);

break;

}

Источник: Кинтцель Т.  Руководство программиста по работе со звуком = A Programmer’s Guide to Sound: Пер. с англ. М.: ДМК Пресс, 2000. 432 с, ил. (Серия «Для программистов»).

По теме:

  • Комментарии