1

I am trying to make a psudo drum kit with my Arduino Due and a couple Force Sensitive Resistors (activated with my fingers, no drum sticks). So far in my testing I'm only using one FSR. I've attached an SD Card reader and put a WAV File on there (44100 Hz, 16-bit, stereo). In my 'Loop', I read in the resistance of the FSR to know if it's been triggered, then I play the WAV file accordingly. It works but its not that fast. If this project is going to work, the response time needs to be much faster.

Here's my code:

#include "SD.h" //Lib to read SD card
#include "SPI.h" //SPI lib for SD card
#include <Audio.h>

#define SD_ChipSelectPin 2

const int FSR_PIN = A0; // Pin connected to FSR/resistor divider

const float VCC = 4.875; 
const float R_DIV = 10000.0; 

void setup() 
{
  Serial.println("Starting Drum Kit!");
  Serial.begin(9600);
  while (!Serial) {}

  pinMode(FSR_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);


  Serial.print("Initializing SD Card...");
  if (!SD.begin(SD_ChipSelectPin)) {
    Serial.println("FAILED!");
    while(true);
  }
  Serial.println("done");

  // 44100kHz stereo => 88200 sample rate
  // 100 mSec of prebuffering.
  Audio.begin(88200, 100);

  void loop() 
{
  File snare_file;
  short snare_buffer[1024];
  int fsrADC = analogRead(FSR_PIN);
  if (fsrADC > 20) // If the analog reading is non-zero
  {
    Serial.println(String(fsrADC));

    snare_file = SD.open("606snare.wav");
    while (snare_file.available()) {   
      snare_file.read(snare_buffer, 1024);
      Audio.prepare(snare_buffer, 1024, 1024);
      Audio.write(snare_buffer, 1024);
    }
    snare_file.close();
  }
}

If I hold down the sensor (constant triggering), the fastest that the file plays is about every half second. Here's the Serial output:

15:12:28.453 -> Initializing SD Card...done
15:12:28.487 -> 1023
15:12:28.930 -> 1023
15:12:29.510 -> 1023
15:12:30.050 -> 1023
15:12:30.628 -> 1023
15:12:31.136 -> 1023
15:12:31.744 -> 1023
15:12:32.328 -> 1023
15:12:32.834 -> 1023
15:12:33.411 -> 1023
15:12:33.955 -> 1023

I've tried playing around with loading the file and buffer in the setup section but I can't get it to work properly. There's not a whole lot of documentation on the Audio library either.

If you know of a better way to speed this up, or if I should be using a different library, please let me know.

3
  • You wrote, that you tried loading the file in setup(), but it didn't work properly. How did it not work? I think moving the loading there is really time consuming. Though keeping the sound loaded permanently might get a problem, when you need to load several files for several drum pads. – chrisl Mar 1 '20 at 22:10
  • I tried creating a global snare_buffer. Then in the setup I would open the file, read the file into the global snare_buffer, and close the file. Then in the loop I would call the two Audio commands: Audio.prepare and Audio.write. This resulted in no sound being produced. I'm not sure how the Audio library works. There wasn't a whole lot of documentation on it. Not sure if there's a better way or a better library. – alexs973 Mar 1 '20 at 22:15
  • I would try to also execute prepare in setup, then only call write in loop. Also not closing the file. If that still doesn't give you the required performance, you might need to use an external player, that just get's triggered by the Arduino. – chrisl Mar 2 '20 at 19:54
1

This is not really a 'solution', but it might help you in finding out where the real problem is.

Check out which of the statements in the loop function uses up the most time, probably;

  1. int fsrADC = analogRead(FSR_PIN);
  2. Serial.println(String(fsrADC));
  3. snare_file = SD.open("606snare.wav");
  4. while (snare_file.available()) {
  5. snare_file.read(snare_buffer, 1024);
  6. Audio.prepare(snare_buffer, 1024, 1024);
  7. Audio.write(snare_buffer, 1024);
  8. snare_file.close()

Try improving the most time consuming item if possible.

Some possibilities you can try in the steps above:

  1. Do not use AnalogRead but direct port commands
  2. Remove this completely or at least remove the String instance.
  3. Not much you can do here, except not using a file system but raw SD read (you might have problems getting the files on your SD) without a dedicated program on your PC
  4. Not sure about improving this one
  5. Read less bytes, although it might even worsen things. Or read the bytes BEFORE waiting on the trigger (if you know which sample will be played).
  6. Execute the prepare as before the trigger as 5 if possible.
  7. Not sure about this... High likely you cannot keep too many files open at the same time.

Afaik in my synthesizer (Korg Kronos), it reads from all samples the initial part, meaning it can startup the data from RAM, while the rest is read through SSD (in your case SD). However, you might not have enough memory in an Arduino for that.

2
  • I know that it's not the analogRead or the print statement. If I comment everything else out and just leave those two in the loop(), the response time is extremely fast. There must be a way to read in my file into the buffer in setup(). I think the main bottle neck is opening and closing the file each time. I'm not sure how to get around this. – alexs973 Mar 1 '20 at 22:17
  • With millis you can exactly time it (run each command 1000 times, print times AFTERWARDS and divide it by 1000). Than you have to check into the library what happens exactly. When opening/closing a file takes too long, concatten all files you need, and read manually from the part of the big single file what you need. – Michel Keijzers Mar 1 '20 at 23:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.