Главная » Программирование звука » Каналы MIDI

0

Как было  показано в предыдущем разделе, объект MidiRead преобразует события в запросы к объектам каналов. Теперь пришло время заняться тем, что необходимо объектам каналов для удовлетворения этих запросов.

Для  большинства  функций  воспроизведения  не  важно,  какой  объект  доступен на канале до тех пор, пока объект канала отвечает на определенные сообщения.   Класс   MidiChannelAbstract определяет   возможности   объекта   канала MIDI. Большинство этих методов поддерживают один тип событий MIDI.

Листинг 22.23. Объект канала MIDI

// Канал контролирует  воспроизводимые в  настоящий момент ноты. class MidiChannelAbstract {

public:

virtual ~MidiChannelAbstract() {};

virtual void StartNote(int pitch, int velocity) = 0; virtual void EndNote(int pitch, int velocity) = 0; virtual void Program(int instrument) = 0;

virtual void ChannelAftertouch(int velocity) = 0; virtual void KeyAftertouch(int note, int velocity) = 0; virtual void Mode(int mode, int value) = 0;

virtual void PitchBend(int value) = 0;

virtual size_t AddSamples(AudioSample *buffer, size_t numberSamples) = 0;

};

Для проигрывания  файлов базового  или расширенного  MIDI  желательно  уметь заглушать  один  или  несколько  каналов.  Этот  простой  фиктивный  класс  успешно реализует «молчащий» канал.

Листинг 22.23. Объект канала MIDI (продолжение)

// Заполнитель, который  ничего не   делает.

class MidiChannelSilent: public MidiChannelAbstract {

public:

~MidiChannelSilent() {};

void StartNote(int, int) {}; void EndNote(int, int) {}; void Program(int) {};

void ChannelAftertouch(int) {}; void KeyAftertouch(int, int) {}; void Mode(int, int) {};

void PitchBend(int) {};

size_t AddSamples(AudioSample *, size_t) { return 0; };

};

Конечно, «молчащие» каналы это исключение. Обычный канал должен отслеживать  проигрываемые  ноты  и  манипулировать  множеством  инструментов.  Для упрощения   работы   с   инструментами   я   выделил   все   аспекты   управления   ими в единый объект «карта инструментов», который мы рассмотрим позднее.

Листинг 22.23. Объект канала MIDI (продолжение)

// Канал контролирует  воспроизводимые в  настоящий момент ноты. class MidiChannelStandard: public MidiChannelAbstract { private:

float _masterVolume; float _channelVolume; MidiRead *_midiRead;

int _defaultInstrumentBank;

int _currentInstrumentBank; int _currentInstrumentNumber; int _currentTuning;

AbstractNote *_note[128];            // Воспроизводимые  ноты.

int _controllerLong[32];             // 14-битные  контроллеры. int _controllerShort[32];            // 7-битные  контроллеры. int _currentRegisteredParameter;

int _registeredParameter[8];         // Зарегистрированные

// параметры.

void AllNotesOff();

void ResetControllers();

public:

MidiChannelStandard(MidiRead *midiObject, int instrumentBank, float masterVolume);

~MidiChannelStandard();

void StartNote(int pitch, int velocity); void EndNote(int pitch, int velocity); void Program(int instrument);

void ChannelAftertouch(int velocity);

void KeyAftertouch(int note, int velocity);

void Mode(int mode, int value);

void PitchBend(int value);

size_t AddSamples(AudioSample *buffer, size_t numberSamples);

};

Листинг 22.24.

MidiChannelStandard:: MidiChannelStandard(MidiRead *midiRead,

int currentBank,

float masterVolume) {

_masterVolume = masterVolume;

_midiRead = midiRead;

_defaultInstrumentBank = currentBank;

_currentInstrumentBank = currentBank;

_currentInstrumentNumber = 0;

_currentTuning = 0;

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

_note[i] = 0; ResetControllers();

}

MidiChannelStandard::~MidiChannelStandard(){ // Очистка.

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

if(_note[i]) {

delete _note[i];

_note[i] = 0;

}

}

Одно  из  отличий  простого  электронного  синтезатора  от  фортепиано  состоит в том, что последнее издает различные звуки в зависимости от того, насколько быстро вы отпускаете клавишу. Протокол MIDI реализует подобное поведение через скорость, которая определяет, как быстро вы нажимаете или отпускаете клавишу. Что касается  событий  включения  нот,  то  более  высокая  скорость  выражается  в  более громком звучании ноты (часто также происходит общее изменение звуковой картины). Для событий выключения нот более высокая скорость означает более быстрое отпускание клавиши, а следовательно, меньшую длительность звучания.

Листинг 22.24. (продолжение)

void MidiChannelStandard::Program(int instrument) {

_currentInstrumentNumber = instrument;

_currentInstrumentBank = _controllerLong[0];

}

void MidiChannelStandard::StartNote(int note, int velocity) {

if (_note[note]) delete _note[note];

// Выбор  соответствующего инструмента.

AbstractInstrument *instr =

_midiRead->InstrumentMap()-

>Instrument(_currentInstrumentBank,

_currentInstrumentNumber,note);

// Получаем настройку  для  этой  ноты. float pitch = _midiRead->TuningMap()-

>Tuning(_currentTuning,note);

_note[note] = instr->NewNote(pitch, velocity*_channelVolume*_masterVolume);

}

void MidiChannelStandard::EndNote(int note, int velocity) {

if (_note [note] )

_note[note]->EndNote(velocity/127.0);

}

void MidiChannelStandard::AllNotesOff() {

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

if(_note[i])

_note[i]->EndNote(0.0);

}

Механизмы aftertouch и Pitch Wheel

B  этой  части  особенно  явственно  проявляется  клавиатурное  наследие  MIDI. Совершенные   клавиатуры   позволяют   управлять   звучанием   ноты,   которая   уже проигрывается.   Эта   возможность   осуществляется   путем   использования   датчика давления, расположенного под клавишей. Изменяя давление, называемое также

aftertouch  (послекасание),  музыкант  изменяет  звучание.  Обычно  такое  удержание клавиши  изменяет  параметр  вибрато,  но,  в  зависимости  от  клавиатуры,  могут  меняться  и  другие  характеристики  звука.  Многие  электронные  клавиатуры  также поддерживают  полноценное  колесо  высоты  тона  (pitch  wheel)  звука,  которое  позволяет  отклонять  высоту  тона  для  всех  нот.  Механизм  управления  высотой  оказывает воздействие на весь канал, а не на одну ноту. Кроме того, используются два сообщения aftertouch: одно для отдельной ноты, другое для целого канала.

Листинг 22.24. (продолжение)

// Я  пока не   работаю  с aftertouch и  pitch wheel.

void MidiChannelStandard::KeyAftertouch(int note, int velocity) {

cerr << "Key Aftertouch: " << note << " velocity: " <<

velocity << "\n";

}

void MidiChannelStandard::ChannelAftertouch(int velocity) {

cerr << "Channel Aftertouch: velocity: " << velocity << "\n";

}

void MidiChannelStandard::PitchBend(int) {

}

Воспроизведение   канала   осуществляется   путем   проигрывания   всех   актив-

ных в текущий момент времени нот.

Листинг 22.24. (продолжение)

size_t MidiChannelStandard::AddSamples(AudioSample *buffer, size_t

numberSamples) {

for(int i=0; i< 128; i++) {

if (_note[i]) {

size_t samplesRead =

_note[i]->AddSamples(buffer,numberSamples);

if (samplesRead < numberSamples) { // Воспроизведение

// ноты   окончено?

delete _note[i];

_note[i] = 0;

}

}

}

return numberSamples;

}

Контроллеры и режимы

События  с кодами от  0xB0 до  0xBF используются для  изменения  различных параметров.  Эти   параметры   разделены   на   четыре   группы:   7-битные   элементы управления  (контроллеры)  постоянного  действия,  14-битные  элементы  управления постоянного действия, параметры и канальные режимы.

7-битные элементы управления

Сообщение  смены  управления  содержит  два  байта  данных.  Первый  опреде-

ляет, что нужно поменять (номер элемента управления); второй определяет новое

значение.  Как  и  для  всех  байтов  данных,  значения  ограничены  семью  битами. B  большинстве  случаев  этого  более  чем  достаточно.  B  стандарте  MIDI  для  этих целей резервируются элементы управления с 64-го по 95-й (0x40 0x5F).

B  табл.  22.7  приведена  сводная  информация  по  7-битным  элементам  управ-

ления.  Заметим,  что  некоторые  из  них  используют  меньше  128  значений.  Например,  элементы  управления  легато  и  портаменто  либо  активируют,  либо  дезактивируют   соответствующий   эффект.   Для   таких   элементов   управления   значения меньшие  64  являются  дезактивирующими,  а  значения  большие  или  равные  64 трактуются  как  активирующие.  Это  справедливо  для  любого  элемента  управления   с   небольшим   диапазоном;   0   всегда   представляет   минимальное   значения,

127     максимальное;   остальные   значения   соответствующим   образом   интерпо-

лируются.

Таблица 22.7. Семибитные контроллеры

Сообщение                            Описание

(шестнадцатеричное)

Bc 40 vv                                   Педаль демпфера (вкл/выкл) Bc 41 vv                                   Портаменто (вкл/выкл)

Bc 42 vv                                   Сустенуто

Bc 43 vv                                   Левая педаль

Bc 44 vv                                   Педаль легато (вкл/выкл) Bc 45 vv                                   Пауза 2

Bc 46 vv                                   Элемент управления звуком 1 (варьирование звука)

Bc 47 vv                                   Элемент управления звуком 2 (интенсивность тембра/гармоник) Bc 48 vv                                   Элемент управления звуком 3 (время затухания)

Bc 49 vv                                   Элемент управления звуком 4 (время атаки) Bc 4A vv                                   Элемент управления звуком 5 (яркость)

Bc 4B vv                                   Элемент управления звуком 6 (нет определения) Bc 4C vv                                  Элемент управления звуком 7 (нет определения) Bc 4D vv                                  Элемент управления звуком 8 (нет определения) Bc 4E vv                                   Элемент управления звуком 9 (нет определения) Bc 4F vv                                   Элемент управления звуком 10 (нет определения) Bc 50 vv                                   Элемент управления общего назначения 5

Bc 51 vv                                   Элемент управления общего назначения 6

Bc 52 vv                                   Элемент управления общего назначения 7

Bc 53 vv                                   Элемент управления общего назначения 8

Bc 54 vv                                   Элемент управления портаменто

Bc 5B vv                                   Глубина эффекта 1

Bc 5C vv                                   Глубина эффекта 2

Bc 5D vv                                  Глубина эффекта 3

Bc 5E vv                                   Глубина эффекта 4

Bc 5F vv                                   Глубина эффекта 5

14-битные контроллеры

B некоторых случаях семи бит оказывается недостаточно, поэтому стандарт MIDI также описывает 32 четырнадцатибитных контроллера. Для такого элемента управления нужны два номера: один для старших семи бит, второй для младших.

Номера  элементов  управления  с  0  по  31  (0x00 0x1F)  используются  для старших семи бит 14-битных элементов управления, а номера с 32 по 63 (0x20 -

0x3F)   для  младших  семи  бит.  B  табл.  22.8  перечисляются  определенные  в  на-

стоящее  время  14-битные  элементы  управления.  Так  как  две  половины  задаются

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

Параметры

Некоторые  элементы  управления  работают  чуть иначе   по параметрическому механизму. Вместо непосредственного указания значения элемента управления сначала  выбирается  соответствующий  параметр  путем  посылки  его  14-битного  кода (используются два сообщения для передачи старшей и младшей семерки битов),

Таблица 22.8. Четырнадцатибитные контроллеры

Контроллер для

старших семи бит

Контроллер для

младших семи бит

Описание

0 (0x00)

32 (0x20)

Выбор банка

1 (0x01)

33 (0x21)

Колесо или рычаг модуляции

2 (0x02)

34 (0x22)

Элемент управления воздухом

3 (0x03)

35 (0x23)

Не определено

4 (0x04)

5 (0x05)

36 (0x24)

37 (0x25)

Элемент управления ногой

Период портаменто

6 (0x06)

38 (0x26)

Ввод данных

7 (0x07)

8 (0x08)

39 (0x27)

40 (0x28)

Громкость канала

Баланс

9 (0x09)

41 (0x29)

Не определено

10 (0x0A)

42 (0x2A)

Панорамирование

11 (0x0B)

43 (0x2B)

Элемент управления экспрессией

12 (0x0C)

44 (0x2C)

Управление эффектами 1

13 (0x0D)

45 (0x2D)

Управление эффектами 2

14 (0x0E)

46 (0x2E)

Не определено

15 (0x0F)

47 (0x2F)

Не определено

16 (0x10)

48 (0x30)

Элемент управления общего назначения 1

17 (0x11)

49 (0x31)

Элемент управления общего назначения 2

18 (0x12)

50 (0x32)

Элемент управления общего назначения 3

20 (0x13)

51 (0x33)

Элемент управления общего назначения 4

20-31

52-63

Не определено

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

14-битные значения. B стандарте описано до 16384 зарегистрированных (registered) параметров  и,  кроме  того,  16384  незарегистрированных  (non-registered).  Зарегистрированные  параметры  являются  официальной  частью  стандарта,  незарегистриро-

ванные могут использоваться кем угодно в любых целях. Как следует из табл. 22.9,

для  параметрического  механизма  необходимо  всего  8  номеров элементов  управления. B табл. 22.10 перечислены основные зарегистрированные на настоящее время параметры. Заметьте, что параметры 1 и 2 представляют одно 28-битное значение настройки.

Чтобы посмотреть, как работает этот механизм, зададим для параметра 2 (гру-

бая настройка) канала 3 значение 0x12BC такой последовательностью байтов:

?  0xB2 0x64 0x00 выбор зарегистрированного параметра, старшие 7бит ко-

торого равны 0;

?  0x65 0x002 полный выбор зарегистрированного параметра 2 (обратите

внимание на непрерывный статус; неявно используется значение 0xB2);

?  0x06 0x25 послать старшие 7 бит нового значения грубой настройки;

?  0x06 0x3C послать младшие 7 бит нового значения грубой настройки.

Режимы каналов

Помимо контроллеров, существует восемь сообщенин режима канала (channel mode). Номер канала в этом случае имеет совершенно другое значение. Вспомним,

Таблица 22.9. Сообщения контроллеров для смены параметров

Сообщение                            Описание

(шестнадцатеричное)

Bc 06 vv                                   Элемент данных: задает старшие 7 бит текущего параметра

Bc 26 vv                                   Элемент данных: задает младшие 7 бит текущего параметра

Bc 60 vv                                    Инкремент данных: увеличивает на единицу текущий параметр Bc 61 vv                                   Декремент данных: уменьшает на единицу текущий параметр Bc 62 vv                                   Выбор незарегистрированного параметра (старшие 7 бит,

младшие 7 бит равны 0)

Bc 63 vv                                   Выбор незарегистрированного параметра (младшие 7 бит) Bc 64 vv                                   Выбор зарегистрированного параметра (старшие 7 бит,

младшие 7 бит равны 0)

Bc 65 vv                                    Выбор зарегистрированного параметра (младшие 7 бит)

Таблица 22.10. Зарегистрированные параметры

Параметр                                Описание

0                                               Чувствительность механизма варьирования высоты

1                                               Точная настройка

2                                                Грубая настройка

3                                                Выбор программы настройки

4                                                Выбор банка настройки

что  обычная  среда  функционирования  MIDI  представляет  собой  множество  связанных друг с другом устройств. Каждое устройство может работать с любым подмножеством  из  16  каналов.  Для  упрощения  решения  определенных  задач  каждое устройство также имеет базовый канал (basic channel).

Сообщения  режима  канала,  посылаемые  в  этот  базовый  канал,  изменяют  режим  работы  всего  устройства.  Если  какой-нибудь  один  синтезатор  работает  со всеми каналами, базовым чаще всего является канал 1.

B  случае  с  синтезатором,  реализованном  на  программном  уровне  (примерно так  как  продемонстрировано  в  этой  главе),  остается  неясным  вопрос  интерпретации  базового  канала.  Программный  синтезатор  можно  рассматривать  как  одно устройство, работающее со всеми 16 каналами, или как 16 виртуальных устройств, каждое из которых работает с одним каналом. B программе, описанной в этой главе,  я  использовал  последнюю  интерпретацию.  B  табл.  22.11  приведена  общая  информация по сообщениям режима канала.

Режим omni (omni mode) определяет, будет ли заданный бокс работать со всеми  каналами  (активный  omni)  или  только  со  своим  базовым  каналом  (пассивный omni).  Монофоническийрежим  (mono  mode)  и  полифоническийрежим  (poly  mode) определяют  способ обработки  параллельных  нот  одним  каналом.  B  первом  случае каждый  канал  воспроизводит  в  любой момент  времени  одну  ноту;  если  активизирующее  ноту  событие  получено  до  отключения  предыдущей  ноты,  то  проигрываемая  в  текущий  момент  времени  нота  меняет  высоту.  Это  вариант  легато.  Заметим,  что  отправитель  все  равно  должен  послать  дезактивирующее  событие  для предыдущей  ноты.  Основное  правило  MIDI  состоит  в  том,  что  за  любым  активирующим  ноту  событием  должно  рано  или  поздно  следовать  соответствующее  дезактивирующее  событие.  B  полифоническом  режиме  каждый  канал  может  воспроизводить столько нот, сколько сумеет.

Таблица 22.11. Сообщения режима канала

Сообщение                             Описание

(шестнадцатеричное)

Bc F8 00                                    Выключить весь звук: выключить все ноты, эхо пауз и т.д. Bc F9 00                                    Повторно инициализировать все элементы управления

(игнорируется в режиме omni)

Bc FA vv                                    Местное управление

Bc FB 00                                   Выключить все ноты

Bc FC 00                                   Выключить режим omni, а также все ноты

Bc FD 00                                   Включить omni (также выключить все ноты)

Bc FE vv                                    Включить монорежим/отключить полифонию (также выключить все ноты): vv количество каналов, которые, начиная с базового,

должны использовать монорежим

Bc FF 00                                   Включить полифонию/отключить монорежим (также выключить все ноты)

Реализация

Листинг 22.24. (продолжение)

void MidiChannelStandard::Mode(int mode, int value) {

// 14-битные  контроллеры.

if (mode < 32)                  // 0-31 старшие  биты   (MSB).

_controllerLong[mode] = value << 7;

if ((mode >= 32) && (mode < 64)) // Младшие  биты   (LSB).

_controllerLong[mode-32] =

(_controllerLong[mode-32] & 0x3F80) + value;

// 7-битные  контроллеры.

if ((mode >= 64) && (mode < 96)) // Однобайтные  контроллеры.

_controllerShort[mode-64] = value;

// Настройка параметров

if (mode == 96) {               // 96 увеличение данных.

_registeredParameter[_currentRegisteredParameter]++;

_controllerLong[6] =

_registeredParameter[_currentRegisteredParameter];

}

if (mode == 97) {               // 97 уменьшение  данных.

_registeredParameter[_currentRegisteredParameter]–;

_controllerLong[6] =

_registeredParameter[_currentRegisteredParameter];

}

// 98 нерегистрированные  параметры LSB.

// 99 нерегистрированные  параметры MSB.

if (mode == 100) {    // Зарегистрированные  параметры LSB.

_currentRegisteredParameter = (_currentRegisteredParameter & 0x3F80)+(value);

_controllerLong[6] =

_registeredParameter [_currentRegisteredParameter];

}

if (mode == 101) {    // Зарегистрированные  параметры MSB.

_currentRegisteredParameter = value<<7;

_controllerLong[6] =

_registeredParameter[_currentRegisteredParameter];

}

/**************************************/

/* Сообщения режимов канала   (120—127) */

/**************************************/

// 120 звук  выключен полностью.

// 121 перезапустить все контроллеры.

if (mode == 121) ResetControllers();

// 123 все ноты   отключены  (124—127 -

// то же  самое).

if (mode >= 123) AllNotesOff();

// 124 режим   omni отключен.

// 125 режим   omni включен.

// 126 монофонический  режим   включен

// (одна нота  на   канал).

// 127 полифонический   режим

// включен  (несколько  нот

// на   канал).

}

void MidiChannelStandard::ResetControllers() {

int i ;

for(i=0;i<32;i++) {

_controllerLong[i] = 0;

_controllerShort[i] = 0;

}

for(i=0;i<8;i++) {

_registeredParameter[i] = 0;

}

_controllerLong[0] = _defaultInstrumentBank;

_controllerLong[7] = 100 << 7; // Громкость  по   умолчанию.

_controllerLong[8] = 0x2000;   // Контроль  баланса: 1/2 =

// одинаковый уровень

// выходных  сигналов.

_controllerLong[10] = 0x2000;  // Контроль  панорамы: 1/2 =

// центрирована.

_controllerLong[ll] = 0x2000;  // Среднее  выражение.

_currentRegisteredParameter = 0;

_registeredParameter[0] = 0;

//

Смещение высоты  тона

//

по   умолчанию:

//

плюс-минус  2 полутона.

_registeredParameter[1] = 0x2000;

//

Тонкая настройка

//

по  умолчанию.

_registeredParameter[2] = 0x2000;

//

Грубая настройка

//

по  умолчанию.

// Обновляем ряд  смешанных переменных.

_channelVolume = _controllerLong[7]/16384.0;

}

Настройка нот в MIDI

Недавно  к  стандарту  MIDI  было  сделано  дополнение:  теперь  предусмотрена возможность  переопределять  значения  высоты  нот  MIDI.  Для  реализации  этого в  моем  проигрывателе  MIDI  есть  единая  карта  настройки,  которая  преобразует нотные значения в частоты.

B  исходной  версии  карта  настройки  использует  равномерно  темперированную шкалу, в которой Ля 440 Гц это нота 69. (Спецификация General MIDI требует, чтобы среднее До соответствовало ноте 60, что эквивалентно нашему варианту.)

Листинг 22.25. Карта настройки MIDI

class MidiTuningMap {

public:

float Tuning(int, int note) {

return 440.0*pow(2.0,(note-69)/12.0);

}

};

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

По теме:

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