Friday 14 June 2013

Polyphonic sampler

After making a simple sampler, let's code a polyphonic sampler now.
First of all, it's necessary to copy samples on a SD card. The samples need to be consecutive, so the best to do is to format SD card before copying the samples.

As usual, the groovuino library will be used.
The names of the samples used have to be changed in the samplerl.h file.

Here is the code.

First, call groovuino library elements you will need, and instanciate objects :

#include <arduino.h>
#include <sequencer.h>

const int samplernumber = 6; // polyphony

Pattern drumpat[samplernumber];

#include <SdFat.h>

SdFat sd;
Sd2Card *card = sd.card();

#include <samplerl.h>
#include <DueTimer.h>


Samplerl samp[samplernumber];

uint32_t step = 0;
int bpm=120;

Now, the setup function where you initialize your data. This is here you will enter a drum sequence.
There are 96 steps in a measure. So 24 steps for each time, 12 steps for a quaver...

void setup()
{
  Serial.begin(9600);
 
  bpm = 120;

  Timer0.attachInterrupt(loop1).setFrequency(44100).start();
  Timer4.attachInterrupt(loop2).setFrequency((bpm*24/60)).start();

  analogWrite(DAC1,0);

  sd.begin(chipSelect, SPI_FULL_SPEED);

  for(int i=0; i<samplernumber; i++)
  {
    samp[i].init();
    samp[i].load(samplefile[i]);
    delay(5);
  }

  for(int i=0; i<samplernumber; i++)
  {
    drumpat[i].init();
  }

// Drum sequence
  drumpat[0].noteon[0] = true;
  drumpat[0].seqvol[0] = 50;

  drumpat[0].noteon[12] = true;
  drumpat[0].seqvol[12] = 50;

  drumpat[2].noteon[48] = true;
  drumpat[2].seqvol[48] = 50;

  drumpat[3].noteon[48] = true;
  drumpat[3].seqvol[48] = 50;

  drumpat[3].noteon[24] = true;
  drumpat[3].seqvol[24] = 50;

  drumpat[3].noteon[72] = true;
  drumpat[3].seqvol[72] = 50;

  drumpat[2].noteon[72] = true;
  drumpat[2].seqvol[72] = 50;

  drumpat[0].noteon[72] = true;
  drumpat[0].seqvol[72] = 50;

  drumpat[4].noteon[48] = true;
  drumpat[4].seqvol[48] = 80;

  drumpat[5].noteon[48] = true;
  drumpat[5].seqvol[48] = 80;

  drumpat[5].noteon[36] = true;
  drumpat[5].seqvol[36] = 80;

  drumpat[0].noteon[24] = true;
  drumpat[0].seqvol[24] = 50;

  drumpat[1].noteon[24] = true;
  drumpat[1].seqvol[24] = 50;

  drumpat[1].noteon[0] = true;
  drumpat[1].seqvol[0] = 80;

  drumpat[1].noteon[12] = true;
  drumpat[1].seqvol[12] = 20;

  drumpat[1].noteon[24] = true;
  drumpat[1].seqvol[24] = 80;

  drumpat[1].noteon[36] = true;
  drumpat[1].seqvol[36] = 20;

  drumpat[1].noteon[48] = true;
  drumpat[1].seqvol[48] = 80;

  drumpat[1].noteon[60] = true;
  drumpat[1].seqvol[60] = 20;

  drumpat[1].noteon[72] = true;
  drumpat[1].seqvol[72] = 80;

  drumpat[1].noteon[84] = true;
  drumpat[1].seqvol[84] = 20;
}



The sample buffers are filled in the main loop :

void loop() 

  for(int i=0; i<samplernumber; i++)
  {
    if(samp[i].buffill()) i= 100;
  }
}


The 44 kHz loop to generate the sample sound :

void loop1() 

  int32_t ulOutput=2048;

  for(int i=0; i<samplernumber; i++)
  {
    samp[i].next();
    ulOutput += samp[i].output();
  }
  
  if(ulOutput>4095) ulOutput=4095;
  if(ulOutput<0) ulOutput=0;
   
  dacc_write_conversion_data(DACC_INTERFACE, ulOutput); 
}


The sequencer loop :


void loop2()
{
    if(step>=95) step = 0;
    else step++;
    for(int i=0; i<samplernumber; i++)
    {
      if(drumpat[i].noteon[step])
      {
        samp[i].splay(drumpat[i].seqvol[step], 1);
      }
    }
}