contemporary miDIY

후니다님이 알려주신 피에조 드럼 링크를 참조했습니다.

악기는 두 부분으로 나눌수 있는데요 하나는 피에조 드럼 부분이구요,

하나는 버튼 8개와 노브 1개로 이루어진 시퀀서 부분입니다.

버튼 두 개가 한 쌍으로 하나는 note,

하나는 반복되는 주기(온음표, 이분음표, 4분음표… 32분음표?)를 결정할 수 있습니다.

이런게 4개 있는데 그럼 이걸 4스탭이라고 하나요?

또 추가로 midi out 채널을 바꿀 수 있어서 중간에 악기 소리를 바꿀 수도 있구요,

전체 4개의 빠르기도 한 번에 조절할 수 있습니다.

처음 만들기 시작할 땐 피에조에 집중했었는데,

만들고 보니 이걸 아두이노에 올릴 수있는 쉴드형으로 만들고, 버튼을 더 많이 다는건 어떨까 싶네요.

그리고 아마 상태를 표시하는 lcd는 필수일것 같구요.

또 각 버튼 쌍마다 보낼 수있는 미디 채널을 따로 설정할 수 있게 하면 몇 개는 영상을 컨트롤 하는데 쓰는 식으로 나눌 수 도 있을 것 같습니다.

아무튼 만들면서 고민했던 것은,

한정적인 아날로그 인풋을 어떻게 여러 용도로 쓸 수 있을까하는 것이었는데,

버튼을 누를때 노브의 값을 읽어 각각의 변수에 저장하는 방식이라면,

다이나믹할 순 없지만 버튼이 100개라도 각각 다른 값을 줄 수 있으니 이점이 있는것 같습니다.

그리고 또 한가지는 각 스탭마다 다른 간격으로 어떻게 소리를 내도록 할까 였는데,

처음에는 석종님이 알려주신  Timer1 라이브러리를 써보려고 했으나,

이건 말하자면 시계가 하나뿐인거여서 두개 이상 각각 다른 시계를 가지도록 할 수 없을것 같아 포기했구요,

아두이노 예제 중에 Blinkwithoutdelay라는 것이 있는데,

여기서 이용한 시간을 재는 방식을 사용했습니다.

결과적으로 완전히 정확한것 같지 않고, 또 이개 몇개까지 확장이 가능할지 의문이지만

일단 괜찮은것 같습니다.

기타 잡설이었구요,

히두이노로 만들었더니 그냥 시리얼투미디 할때보다 안정적인것 같습니다.

그리고 히두이노로 만들려면 아두이노에 올리는 코드에서

Serial.begin(31250);

으로 해줘야 하더군요.

31250이 midi의 통신 속도이기 때문이려나요.

아두이노 코드를 첨부합니다.

윗부분은 피에조 드럼 코드를 거의 그대로 썼구요,

//for button 부터 시퀀서 부분입니다.

/*

set knob and then press buttoun you want to change.

bu0  bu2   bu4   bu6 : set each track's pitch(0 ~ 127)
bu1  bu3   bu5   bu7 : set each track's tempo(4 ~ 0.0156 sec)

set tempo 0(right end of knob, then press tempo button), stop sending MIDI message.

if you want to chane BPM, set knob(left to right, 140 to 30), and then press bu0 and press bu7 before release bu0.

*/



unsigned char PadNote[5] = {52,46,66,63,40};         // MIDI notes from 0 to 127 (Mid C = 60)
int PadCutOff[5] = {600,600,600,600,600};           // Minimum Analog value to cause a drum hit
int MaxPlayTime[5] = {90,90,90,90,90};               // Cycles before a 2nd hit is allowed

int bpm = 60;
int moutch = 0; //midi out channel
boolean VelocityFlag  = true;                           // Velocity ON (true) or OFF (false)
boolean activePad[6] = {0,0,0,0,0,0};                   // Array of flags of pad currently playing
int PinPlayTime[6] = {0,0,0,0,0,0};                     // Counter since pad started to play
int but_get[8] = {0, 0, 0, 0, 0, 0, 0, 0};            //get actual value from knob
int but_state[8] = {0, 0, 0, 0, 0, 0, 0, 0};          //check LOW/HIGH
int but_map[8] = {60, 0, 62, 0, 64, 0, 66, 0};
float but_map_reci[8] = {0, 60, 0, 62, 0, 64, 0, 66};
int but_map_reci_mil[8] = {0, 0, 0, 0, 0, 0, 0, 0};
long but_time[8] = {1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000};                  //store each track's tempo for auto loop
boolean but_flag[8] = {0, 0, 0, 0, 0, 0, 0, 0};

unsigned char status;

int pin = 0;
int hitavg = 0;


void setup()
{
//  Serial.begin(57600);                                  // connect to the serial port 115200
  Serial.begin(31250); //for make hiduino

  for(int i = 0; i < 8; i++)
  {
  pinMode(2 + i, INPUT);
  }

}



void loop()
{
  for(int pin=0; pin < 5; pin++)
  {
    hitavg = analogRead(pin);                              // read the input pin

    if((hitavg > PadCutOff[pin]))
    {
      if((activePad[pin] == false))
      {
        if(VelocityFlag == true)
        {
//          hitavg = 127 / ((1023 - PadCutOff[pin]) / (hitavg - PadCutOff[pin]));    // With full range (Too sensitive ?)
          hitavg = (hitavg / 8) -1 ;                                                 // Upper range
        }
        else
        {
          hitavg = 127;
        }

//        Serial.println("hit");
//        Serial.println(pin);
        MIDI_TX(0, 144,PadNote[pin],hitavg); //note ON
        PinPlayTime[pin] = 0;
        activePad[pin] = true;
      }
      else
      {
        PinPlayTime[pin] = PinPlayTime[pin] + 1;
      }
    }
    else if((activePad[pin] == true))
    {
      PinPlayTime[pin] = PinPlayTime[pin] + 1;

      if(PinPlayTime[pin] > MaxPlayTime[pin])
      {
//        activePad[pin] = false; //ORIGINAL CODE
//        MIDI_TX(128,PadNote[pin],127); //note OFF


        MIDI_TX(0, 128,PadNote[pin],127); //note OFF
        activePad[pin] = false;
        //Serial.println("down"+pin);

      }
    }
  }


/////////////////////////////////////////////////////////////
///////////////////////////for buttons///////////////////////



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

    but_state[i] = digitalRead(2 + i);

      if(but_state[0] == HIGH && but_state[7] == HIGH && but_flag[7] == false)
      {
        bpm = map(but_get[0], 0, 1023, 30, 140); // push but0 and but7 at the same time, change bpm
//        Serial.println(bpm);
      }


      if(but_state[2] == HIGH && but_state[7] == HIGH && but_flag[7] == false)
      {
        moutch = map(but_get[2], 0, 1023, 0, 15); // push but2 and but7 at the same time, change midi out channel
//        Serial.println(bpm);
      }


    if(but_state[i] == HIGH && but_flag[i] == false)
    {
      but_flag[i] = true;
      but_get[i] = analogRead(A5); //update but_get


      if(i%2 == 0) //butnum 0, 2, 4, 6, about NOTE
      {
        but_map[i] = map(but_get[i], 0, 1023, 0, 127);
//        Serial.println(but_map[i]);

      }

      else if(i%2 == 1) //butnum 1, 3, 5, 7, about TEMPO
      {
        but_time[i] = millis(); //reset timer
        but_map[i] = map(but_get[i], 0, 1023, 0, 10);

        but_map[i] = int(but_map[i]); //like floor

        but_map_reci[i] = (1.0/(pow(2, (but_map[i]-3)))) * (60.0/bpm);

        but_map_reci_mil[i] = but_map_reci[i] * 1000; //convert millisecond

//        Serial.println(but_map[i]);
//        Serial.println(but_map_reci[i]);

      }
    }
    else if(but_state[i] == LOW)
   {
      but_flag[i] = false;

      if( i % 2 == 1)
      {
        if(but_map[i] != 0)
        {
          if ((millis() - but_time[i]) % but_map_reci_mil[i] == 0) //when current time - but_time == but_map
            {
              int v_of_auto = random(65, 125); //random velocity
              MIDI_TX(moutch, 144, but_map[i - 1], v_of_auto); //note ON
              //Serial.println(millis());
            }
        }
      }
   }
  }

}


void MIDI_TX(int ch, unsigned char MESSAGE, unsigned char PITCH, unsigned char VELOCITY)
{
  status = MESSAGE + ch;
  Serial.print(status);
  Serial.print(PITCH);
  Serial.write(VELOCITY);
}

Advertisements