9. ¹Ìµð °³¹ß

¹Ìµð ¾îÇø®ÄÉÀÌ¼Ç °³¹ßÀ» À§Çؼ± ÁÁÀº ¿¹Á¦µéÀÌ Á¾Á¾ ÇÊ¿äÇÏ´Ù. 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.
   ÀÎDzÀ» ¹Ìµð ä³ÎÀ» ÅëÇØ ¼³Á¤µÈ ¾Æ¿ôDzÀ¸·Î ¸®´ÙÀÌ·ºÆ®ÇÑ´Ù.
   (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;
}