Go Down

Topic: Schoo Project-Arduino Midi Drumpads (Read 187 times) previous topic - next topic

wherner1

Apr 25, 2016, 03:11 pm Last Edit: Apr 27, 2016, 04:40 pm by wherner1
I was wondering how you changed each drum pad to a different sound in a midi drum project. I have mine working, I have 4 pads and I'm using fl studio 12, hairless midi, and loop midi. I have to get a school project done quickly so I'm hoping for a quick response. Currently all pads work but they're just a variation of the same note. Like snare would be c5 and each other pad would play a different variation and pitch of that note. Here is the code that I tried to change. Could someone to help to where like each pad would be a different item, snare, bass drum, hi hat, and clap or something.

I have an arduino UNO and 4 piezos wired starting at A0 to A3. I have the other analog inputs grounded from a previous build but I dont think that'd effect it.

Here is the code: Thanks in advance anyone who can help a newbie for a school project

Code: [Select]
//Piezo defines
#define NUM_PIEZOS 4
#define SNARE_THRESHOLD 30     //anything < TRIGGER_THRESHOLD is treated as 0
#define LTOM_THRESHOLD 30
#define RTOM_THRESHOLD 30
#define LCYM_THRESHOLD 100
#define RCYM_THRESHOLD 100
#define KICK_THRESHOLD 50
#define START_SLOT 0     //first analog slot of piezos

//MIDI note defines for each trigger
#define SNARE_NOTE 70
#define LTOM_NOTE 71
#define RTOM_NOTE 72
#define LCYM_NOTE 73
#define RCYM_NOTE 74
#define KICK_NOTE 75

//MIDI defines
#define NOTE_ON_CMD 0x90
#define NOTE_OFF_CMD 0x80
#define MAX_MIDI_VELOCITY 127

//MIDI baud rate
#define SERIAL_RATE 115200

//Program defines
//ALL TIME MEASURED IN MILLISECONDS
#define SIGNAL_BUFFER_SIZE 100
#define PEAK_BUFFER_SIZE 30
#define MAX_TIME_BETWEEN_PEAKS 20
#define MIN_TIME_BETWEEN_NOTES 50

//map that holds the mux slots of the piezos
unsigned short slotMap[NUM_PIEZOS];

//map that holds the respective note to each piezo
unsigned short noteMap[NUM_PIEZOS];

//map that holds the respective threshold to each piezo
unsigned short thresholdMap[NUM_PIEZOS];

//Ring buffers to store analog signal and peaks
short currentSignalIndex[NUM_PIEZOS];
short currentPeakIndex[NUM_PIEZOS];
unsigned short signalBuffer[NUM_PIEZOS][SIGNAL_BUFFER_SIZE];
unsigned short peakBuffer[NUM_PIEZOS][PEAK_BUFFER_SIZE];

boolean noteReady[NUM_PIEZOS];
unsigned short noteReadyVelocity[NUM_PIEZOS];
boolean isLastPeakZeroed[NUM_PIEZOS];

unsigned long lastPeakTime[NUM_PIEZOS];
unsigned long lastNoteTime[NUM_PIEZOS];

void setup()
{
Serial.begin(SERIAL_RATE);

//initialize globals
for(short i=0; i<NUM_PIEZOS; ++i)
{
  currentSignalIndex[i] = 0;
  currentPeakIndex[i] = 0;
  memset(signalBuffer[i],0,sizeof(signalBuffer[i]));
  memset(peakBuffer[i],0,sizeof(peakBuffer[i]));
  noteReady[i] = false;
  noteReadyVelocity[i] = 0;
  isLastPeakZeroed[i] = true;
  lastPeakTime[i] = 0;
  lastNoteTime[i] = 0;    
  slotMap[i] = START_SLOT + i;
}

thresholdMap[0] = KICK_THRESHOLD;
thresholdMap[1] = RTOM_THRESHOLD;
thresholdMap[2] = RCYM_THRESHOLD;
thresholdMap[3] = LCYM_THRESHOLD;
thresholdMap[4] = SNARE_THRESHOLD;
thresholdMap[5] = LTOM_THRESHOLD;  

noteMap[0] = KICK_NOTE;
noteMap[1] = RTOM_NOTE;
noteMap[2] = RCYM_NOTE;
noteMap[3] = LCYM_NOTE;
noteMap[4] = SNARE_NOTE;
noteMap[5] = LTOM_NOTE;  
}

void loop()
{
unsigned long currentTime = millis();

for(short i=0; i<NUM_PIEZOS; ++i)
{
  //get a new signal from analog read
  unsigned short newSignal = analogRead(slotMap[i]);
  signalBuffer[i][currentSignalIndex[i]] = newSignal;
 
  //if new signal is 0
  if(newSignal < thresholdMap[i])
  {
    if(!isLastPeakZeroed[i] && (currentTime - lastPeakTime[i]) > MAX_TIME_BETWEEN_PEAKS)
    {
      recordNewPeak(i,0);
    }
    else
    {
      //get previous signal
      short prevSignalIndex = currentSignalIndex[i]-1;
      if(prevSignalIndex < 0) prevSignalIndex = SIGNAL_BUFFER_SIZE-1;        
      unsigned short prevSignal = signalBuffer[i][prevSignalIndex];
     
      unsigned short newPeak = 0;
     
      //find the wave peak if previous signal was not 0 by going
      //through previous signal values until another 0 is reached
      while(prevSignal >= thresholdMap[i])
      {
        if(signalBuffer[i][prevSignalIndex] > newPeak)
        {
          newPeak = signalBuffer[i][prevSignalIndex];        
        }
       
        //decrement previous signal index, and get previous signal
        prevSignalIndex--;
        if(prevSignalIndex < 0) prevSignalIndex = SIGNAL_BUFFER_SIZE-1;
        prevSignal = signalBuffer[i][prevSignalIndex];
      }
     
      if(newPeak > 0)
      {
        recordNewPeak(i, newPeak);
      }
    }

  }
     
  currentSignalIndex[i]++;
  if(currentSignalIndex[i] == SIGNAL_BUFFER_SIZE) currentSignalIndex[i] = 0;
}
}

void recordNewPeak(short slot, short newPeak)
{
isLastPeakZeroed[slot] = (newPeak == 0);

unsigned long currentTime = millis();
lastPeakTime[slot] = currentTime;

//new peak recorded (newPeak)
peakBuffer[slot][currentPeakIndex[slot]] = newPeak;

//1 of 3 cases can happen:
// 1) note ready - if new peak >= previous peak
// 2) note fire - if new peak < previous peak and previous peak was a note ready
// 3) no note - if new peak < previous peak and previous peak was NOT note ready

//get previous peak
short prevPeakIndex = currentPeakIndex[slot]-1;
if(prevPeakIndex < 0) prevPeakIndex = PEAK_BUFFER_SIZE-1;        
unsigned short prevPeak = peakBuffer[slot][prevPeakIndex];
 
if(newPeak > prevPeak && (currentTime - lastNoteTime[slot])>MIN_TIME_BETWEEN_NOTES)
{
  noteReady[slot] = true;
  if(newPeak > noteReadyVelocity[slot])
    noteReadyVelocity[slot] = newPeak;
}
else if(newPeak < prevPeak && noteReady[slot])
{
  noteFire(noteMap[slot], noteReadyVelocity[slot]);
  noteReady[slot] = false;
  noteReadyVelocity[slot] = 0;
  lastNoteTime[slot] = currentTime;
}

currentPeakIndex[slot]++;
if(currentPeakIndex[slot] == PEAK_BUFFER_SIZE) currentPeakIndex[slot] = 0;  
}

void noteFire(unsigned short note, unsigned short velocity)
{
if(velocity > MAX_MIDI_VELOCITY)
  velocity = MAX_MIDI_VELOCITY;

midiNoteOn(note, velocity);
midiNoteOff(note, velocity);
}

void midiNoteOn(byte note, byte midiVelocity)
{
Serial.write(NOTE_ON_CMD);
Serial.write(note);
Serial.write(midiVelocity);
}

void midiNoteOff(byte note, byte midiVelocity)
{
Serial.write(NOTE_OFF_CMD);
Serial.write(note);
Serial.write(midiVelocity);
}

Grumpy_Mike

Read the how to use the forum and correct that post to post code correctly.

To get the MIDI to produce different percussion sounds send over channel 13 as this is the percussion channels for most MIDI sound generators, look up what yours is.

wherner1


CrossRoads

Select More:Modify at the lower right of the box.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

wherner1

Give it a few minutes, its says I cant modify the code, that I've hit the limit

CrossRoads

Time limit? That goes away after so many posts.
Size limit? Reply, and click "Attachments and other options" to attach the .ino file if it's too big.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

CrossRoads

What length data do you get with
short and unsigned short?
I've not seen those before.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

wherner1

I'm not quite sure, I borrowed the code from another project and was trying to modify it to my own needs

Grumpy_Mike

Quote
I borrowed the code
So you are going to give it back?

Do you understand any of it?

What is your MIDI sound generator?

wherner1

I'm using fl studio and the ASIO4ALL driver. And sort of, but not really. It works as far as putting out a sound of drums that I can customize for different sounds. They all send the same note but a different tone of that note.
A0=D#6
A1= C6
A2=D6
A3=C#6

A's being our 4 piezoes connected to the analog connections on our arduino uno.
A4 and 5 are grounded.

Grumpy_Mike

Read reply #1 again.
Have you tried this?
Do you understand this?

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy