LINUX.ORG.RU

Программирование MIDI в Linux. Есть хоть один спец?


0

0

Здравствуйте!


Есть такая простая задачка - написать программу (C/C++), которая бы на указанный midi девайс отправила ноту До, и ее было бы слышно в динамиках. (Когда пойму как это делать, дальше прогать MIDI интерфейс будет делом техники).

В рунете нет вообще ни одной статьи по теме. У буржуев нашел вот такую хорошую описаловку

Introduction to MIDI programming in Linux http://ccrma-www.stanford.edu/~craig/articles/linuxmidi/

делаю по ней, но ничего не работает (нет звука).

Пример исходника http://paste.org.ru/?ktiqtu (110 строк)


Насколько я понял, видимо в описаловке информация устарела. Ныне миди-девайсы каким-то образом регистрятся в системе, получают свои номера вида XXX:X, и их можно увидеть, например, через команду

pmidi -l

или

aconnect -i -o

незарегистрированная как девайс программа, видимо, не может работать с MIDI устройствами. И вот не могу найти инфы, как же делать так, чтоб программа создала MIDI-устройство, через которое ее можно соединить (через aconnect) с другим MIDI-устройством (например, синтезатором amSynth).

Или все-таки, можно просто обращаться к MIDI-устройству? Но как? Я не понял, какой номер надо использовать. В моем коде по описаловке есть просто один номер int, а не номер вида XXX:X.


Вот что у меня показывает pmidi

# pmidi -l
клиент 0: 'System' [тип=ядро]
0 'Timer '
1 'Announce '
клиент 14: 'Midi Through' [тип=ядро]
0 'Midi Through Port-0'
клиент 16: 'SB Live 5.1' [тип=ядро]
0 'EMU10K1 MPU-401 (UART)'
клиент 17: 'Emu10k1 WaveTable' [тип=ядро]
0 'Emu10k1 Port 0 '
1 'Emu10k1 Port 1 '
2 'Emu10k1 Port 2 '
3 'Emu10k1 Port 3 '
клиент 128: 'amSynth' [тип=пользователь]
0 'amSynth MIDI IN '
1 'amSynth MIDI OUT'
клиент 129: 'Virtual Keyboard' [тип=пользователь]
0 'Virtual Keyboard'

А вот что показывает моя программа

There are: 7 MIDI external output devices available
0: Device 0 Name Midi Through Port-0
1: Device 1 Name EMU10K1 MPU-401 (UART)
2: Device 2 Name Emu10k1 Port 0
3: Device 3 Name Emu10k1 Port 1
4: Device 4 Name Emu10k1 Port 2
5: Device 5 Name Emu10k1 Port 3
6: Device 6 Name Virtual Keyboard

There are: 1 MIDI internal output devices available
0: Device 0 Name Emu10k1

Видно, что самодельная прога виртуального синтезатора amSynth вообще не видит.


Пробовал соединяться по номерам 0-7, 14, 16, 17, 128, 129, ни на одном устройстве звука не было. (Хотя amSynth играет звук по командам от Virtual Keyboard, но я их соединил через aconnect 129:0 128:0).


Кто что может сказать по вопросу?


Ответ на: комментарий от anonymous

> SB Live? А хоть один банк с семплами подгрузили (*.SF2)?

Да, SBLive 5.1. Семплы подгружены конечно (8Mb), в Virtual Keyboard ими можно играть.

xintrea
() автор топика
Ответ на: комментарий от anonymous2

> aplaymidi -l
> aplaymidi -p client:port midifile


> если последнее поет, качаем исходники alsa.



Поет. А исходники alsa зачем? Хотите поведать миру, что код - лучшая документация?

xintrea
() автор топика
Ответ на: комментарий от anonymous2

> я напрямую в порты midi не писал, но делал конвертер xmi -> midi.

Совсем одно и тоже...

xintrea
() автор топика

Мда, спецов на лоре какобычно нет, все приходится делать самому.

Статья Introduction to MIDI programming in Linux действительно устарела, нынче через ioctl() с Midi под линухом не работают. А работают через классы абстракций, которые предоставляет ALSA. По мне, так это очень неудобно, писанины стало больше, а результат такой же как и при прямых midi командах.


Работающий пример ниже, может кому пригодится.


>-----8<-----


#include <stdio.h>
#include "alsa/asoundlib.h"

int main(int argc, char *argv[])
{
snd_seq_t *handle; // Указатель на секвенсор
snd_seq_event_t ev; // Событие, отправляемое в секвенсор

// Секвенсор открывается
snd_seq_open(&handle, "hw", SND_SEQ_OPEN_DUPLEX, 0);
snd_seq_alloc_queue(handle);

// Событие очищается
snd_seq_ev_clear(&ev);

// Номер виртуального порта 17:0 на котором находится воспроизводящее Midi-устройство
ev.dest.client=17;
ev.dest.port=0;

// Создается событие включения ноты
ev.type = SND_SEQ_EVENT_NOTEON;
ev.data.note.channel = 0; // Нота будет проиграна в канале 0
ev.data.note.note = 64 ; // Нота До пятой октавы
ev.data.note.velocity = 127; // Громкость максимальная
snd_seq_event_output_direct(handle, &ev); // Проигрывание напрямую без использования очереди

// Нота играет секунду
sleep(1);

// Нота выключается
ev.type = SND_SEQ_EVENT_NOTEOFF;
snd_seq_event_output_direct(handle, &ev); // Выключение напрямую без использования очереди

// Секвенсор закрывается
snd_seq_drain_output(handle);

return 0;
}

>-----8<-----



Скомпилить можно так

gcc -L/usr/lib -O3 -Wall -o midi midi.c -lm -lasound -ldl -lpthread

xintrea
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.