отправлять миди-сообщения из C++

Я использую Raspberry Pi, так что это что-то вроде Debian (Raspbian).

У меня работает синтезатор (Zynaddsubfx), и я хочу отправить ему миди-сообщения из кода, чтобы он воспроизводил музыку для меня. Я буду использовать ALSA для этого.

Мне удалось создать "излучающий порт" в моей программе, выполнив следующие действия:

snd_seq_create_simple_port(seq_handle, "My own sequencer",
    SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,
    SND_SEQ_PORT_TYPE_APPLICATION)

теперь я вижу ZynSubAddFX в aconnect -ol и свой собственный секвенсор в aconnect -il. И я могу их подключить:

pi@cacharro:~/projects/tests$ aconnect 129:0 128:0
pi@cacharro:~/projects/tests$ Info, alsa midi port connected

для этого, как было предложено CL, я использовал open snd_seq_open, сохранил последовательность, а затем использовал snd_seq_create_simple_port.. НО:

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

Есть ли способ отправить простые миди-команды, такие как note on/note off, через мой открытый порт???


person javirs    schedule 16.01.2014    source источник
comment
Это ZynAddSubFX, скомпилированный для Jack или OSS MIDI?   -  person CL.    schedule 16.01.2014
comment
Я обновил свой вопрос новыми деталями, я думаю, ответ на ваш вопрос заключается в том, что он может работать со всеми тремя элементами, важным из которых является ALSA, похоже, он работает правильно для этого :)   -  person javirs    schedule 16.01.2014


Ответы (1)


Чтобы отправить некоторые события в определенное время:

  • открыть секвенсор;
  • создать свой (исходный) порт;
  • построить и отправить некоторые события.

Чтобы открыть секвенсор, вызовите snd_seq_open. (Вы можете получить свой номер клиента с помощью snd_seq_client_id.)

    snd_seq_t seq;
    snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0);

Чтобы создать порт, выделите информационный объект порта с помощью snd_seq_port_info_alloca, установите параметры порта с помощью snd_seq_port_info_set_xxx и call snd_seq_create_port. Или просто позвоните snd_seq_create_simple_port.

    int port;
    port = snd_seq_create_simple_port(seq, "my port",
            SND_SEQ_PORT_CAP_READ | SND_SEQ_POR_CAP_WRITE,
            SND_SEQ_PORT_TYPE_APPLICATION);

Чтобы отправить событие, выделите структуру события (просто для разнообразия вы можете использовать локальную переменную snd_seq_event_t) и вызовите различные функции snd_seq_ev_xxx для установки ее свойств. Затем позвоните snd_seq_event_output и snd_seq_drain_output после отправки всех событий.

    snd_seq_event_t ev;
    snd_seq_ev_clear(&ev);
    snd_seq_ev_set_direct(&ev);

    /* either */
    snd_seq_ev_set_dest(&ev, 64, 0); /* send to 64:0 */
    /* or */
    snd_seq_ev_set_subs(&ev);        /* send to subscribers of source port */

    snd_seq_ev_set_noteon(&ev, 0, 60, 127);
    snd_seq_event_output(seq, &ev);

    snd_seq_ev_set_noteon(&ev, 0, 67, 127);
    snd_seq_event_output(seq, &ev);

    snd_seq_drain_output(seq);
person CL.    schedule 16.01.2014
comment
безусловно, самая полезная помощь, которую я получил по этой теме. Если мой инструмент когда-нибудь станет нормальным, я буду с открытым исходным кодом, и ваше имя будет там. благодаря. Работает как шарм - person javirs; 17.01.2014