미디 어플리케이션 개발을 위해선 좋은 예제들이 종종 필요하다. For those looking to develop MIDI applications, good examples are often needed to get you started.
다음의 예제들은 LAD 메일링 리스트에 예제나 문서/참고자료로 포스팅 됐던 것들이다. The following examples were posted to the LAD mailing list in a thread about examples and documentation/tutorials.
아래는 Dr. Matthias Nagorni의 ALSA 0.9 시퀀서 클라이언트 셈플이다. 이것은 입력 가능한(writeable) 시퀀서 클라이언트를 만들고, Pitchbender-, 7-Bit Controller-, Note-event 들을 stderr를 통해 출력한다.
더 많은 예제들을 이 문서의 링크 섹션에 있는 Matthias의 사이트를 통해 입수할 수 있다.
다음과 같이 컴파일하라:
[phil@beatbox] $ gcc seqdemo.c -o seqdemo -lasound
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <alsa/asoundlib.h>
snd_seq_t *open_seq();
void midi_action(snd_seq_t *seq_handle);
snd_seq_t *open_seq() {
snd_seq_t *seq_handle;
int portid;
if (snd_seq_open(&seq_handle, "hw", SND_SEQ_OPEN_DUPLEX, 0) < 0) {
fprintf(stderr, "Error opening ALSA sequencer.\n");
exit(1);
}
snd_seq_set_client_name(seq_handle, "ALSA Sequencer Demo");
if ((portid = snd_seq_create_simple_port(seq_handle, "ALSA Sequencer Demo",
SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
SND_SEQ_PORT_TYPE_APPLICATION)) < 0) {
fprintf(stderr, "Error creating sequencer port.\n");
exit(1);
}
return(seq_handle);
}
void midi_action(snd_seq_t *seq_handle) {
snd_seq_event_t *ev;
do {
snd_seq_event_input(seq_handle, &ev);
switch (ev->type) {
case SND_SEQ_EVENT_CONTROLLER:
fprintf(stderr, "Control event on Channel %2d: %5d \r",
ev->data.control.channel, ev->data.control.value);
break;
case SND_SEQ_EVENT_PITCHBEND:
fprintf(stderr, "Pitchbender event on Channel %2d: %5d \r",
ev->data.control.channel, ev->data.control.value);
break;
case SND_SEQ_EVENT_NOTEON:
fprintf(stderr, "Note On event on Channel %2d: %5d \r",
ev->data.control.channel, ev->data.note.note);
break;
case SND_SEQ_EVENT_NOTEOFF:
fprintf(stderr, "Note Off event on Channel %2d: %5d \r",
ev->data.control.channel, ev->data.note.note);
break;
}
snd_seq_free_event(ev);
} while (snd_seq_event_input_pending(seq_handle, 0) > 0);
}
int main(int argc, char *argv[]) {
snd_seq_t *seq_handle;
int npfd;
struct pollfd *pfd;
seq_handle = open_seq();
npfd = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd));
snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN);
while (1) {
if (poll(pfd, npfd, 100000) > 0) {
midi_action(seq_handle);
}
}
}
|
아래는 Nick Dowell 가 만든 ALSA 0.9 MIDI 리다이렉터(redirector) 이다.
/* ALSA Sequencer MIDI redirector.
인풋을 미디 채널을 통해 설정된 아웃풋으로 리다이렉트한다.
(Linux-Audio-Dev 에서 Nathaniel Virgo 에게서 요청받은 것임 ;-)
Dr. Matthias Nagorni 의 ALSA seq 예제를 기초로 했음
Nick Dowell <nixx@nixx.org.uk>
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <alsa/asoundlib.h>
int
main()
{
snd_seq_t *seq_handle;
snd_seq_event_t *ev;
int i;
int portid; /* input port */
int oportid[16]; /* output ports */
int npfd;
struct pollfd *pfd;
char txt[20];
if (snd_seq_open(&seq_handle, "hw", SND_SEQ_OPEN_DUPLEX, 0) < 0) {
fprintf(stderr, "Error opening ALSA sequencer.\n");
exit(1);
}
snd_seq_set_client_name(seq_handle, "MIDI Redirect");
/* open one input port */
if ((portid = snd_seq_create_simple_port
(seq_handle, "Input",
SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE,
SND_SEQ_PORT_TYPE_APPLICATION)) < 0) {
fprintf(stderr, "fatal error: could not open input port.\n");
exit(1);
}
/* open 16 output ports for the MIDI channels */
for (i=0; i<16; i++){
sprintf( txt, "MIDI Channel %d", i );
if ((oportid[i] = snd_seq_create_simple_port
(seq_handle, txt,
SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ,
SND_SEQ_PORT_TYPE_APPLICATION)) < 0) {
fprintf(stderr, "fatal error: could not open output port.\n");
exit(1);
}
}
npfd = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd));
snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN);
while (1) /* main loop */
if (poll(pfd, npfd, 1000000) > 0){
do {
snd_seq_event_input(seq_handle, &ev);
snd_seq_ev_set_source( ev, oportid[ev->data.control.channel] );
snd_seq_ev_set_subs( ev );
snd_seq_ev_set_direct( ev );
snd_seq_event_output_direct( seq_handle, ev );
snd_seq_free_event(ev);
} while (snd_seq_event_input_pending(seq_handle, 0) > 0);
}
return 0;
}
|
아래는 Craig Stuart Sapp이 작성한, OSS의 /dev/midi 인터페이스에 데이터를 보내는 예제이다.
더 많은 예제들을 이 문서의 링크 섹션에 나와 있는 Craig 의 사이트에서 구할 수 있다.
//
// Programmer: Craig Stuart Sapp [craig@ccrma.stanford.edu]
// Creation Date: Mon Dec 21 18:00:42 PST 1998
// Last Modified: Mon Dec 21 18:00:42 PST 1998
// Filename: ...linuxmidi/output/method1.c
// Syntax: C
// $Smake: gcc -O -o devmidiout devmidiout.c && strip devmidiout
//
#include <linux/soundcard.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main(void) {
char* device = "/dev/midi" ;
unsigned char data[3] = {0x90, 60, 127};
// step 1: open the OSS device for writing
int fd = open(device, O_WRONLY, 0);
if (fd < 0) {
printf("Error: cannot open %s\n", device);
exit(1);
}
// step 2: write the MIDI information to the OSS device
write(fd, data, sizeof(data));
// step 3: (optional) close the OSS device
close(fd);
return 0;
} |