Playing sound randomly with Arduino input trigger

edited April 2017 in Arduino

Hi, I am currently writing a program that reacts visually to some touch sensitive electrodes, I have the visuals pretty much perfect, and now I want to add sound. There will be a continuous background ambient sound, but I want to add little 'splash' noises for when an electrode is touched. However I want to use an array so the sound is selected randomly, to prevent annoying repetitive sounds, and I also want to NOT play any 'splash' sounds sometimes, to again add an organic feeling and prevent any repetition. When the PressedArray goes below the 800 threshold, that means the electrode is being pressed. Here is my code (as cleaned up as possible):

import processing.serial.*;
import ddf.minim.*;

Minim minim;
AudioPlayer bgm;

int count = 2;
AudioPlayer [] splashes = new AudioPlayer[count];

float hue;

//creating variable for colour for later
color c;

//mapping colour and place from electrode array values
float colMap;
float disMape;

int disMap;

color b = color(0, 0, 0);

//arduino port stuff
int lf = 10; //ASCII for end of line or line feed  
Serial myPort;  //the Serial connection to processing

//creating arrays for electrodes
int[] pressedArray = new int[13];
boolean[] isPressed = new boolean[13];
PVector[] pressedPositions = new PVector[13];


void setup() {
  fullScreen();
  colorMode(HSB, 255);

  //loading soundfile
  minim = new Minim(this);

  //background ambience
  bgm = minim.loadFile("ambientloop.wav");
  bgm.loop();

  splashes[0] = minim.loadFile("smallsplash.aiff");
  splashes[1] = minim.loadFile("tinysplash.wav");
  splashes[2] = minim.loadFile("splash2.wav");
  splashes[3] = minim.loadFile("splash3.wav");
  splashes[4] = minim.loadFile("splash4.wav");


  //initial array for electrodes and circles
  for (int i = 0; i < 13; i++) {
    pressedArray[i]= 0;
    pressedPositions[i] = new PVector(0, 0);
    isPressed[i] = false;
  }

  //printing array values for use in code (values go from around 930(when not touching) and 120(when pressing quite hard)
  printArray(Serial.list());
  myPort = new Serial(this, Serial.list()[3], 57600);
}


void draw() {
  background(0);
  circ(); //it might be useful to run the code as a separate function for now
}


void circ() {

  for (int j=0; j<pressedArray.length-1; j++) {

    //using array values
    if (pressedArray[j]<800) {

      //create new position when electrode IS NOT pressed
      if (isPressed[j] == false) {
        pressedPositions[j] = new PVector(random(width), random(height));
      }

      isPressed[j] = true;

      //mapping colours
      colMap = map(pressedArray[j], 600, 0, 0, 255);
      c = color(colMap, 255, 255, 30);
      b = color(colMap, 255, 255, 0);

      //changing size
      disMape = map(pressedArray[j], 1000, 0, 50, 400);
      disMap = floor(disMape);

      //making nice blurry circles
      for (int k=disMap; k>=0; k-=5) {

        //lerp colour to create gradient for edges, going from full colour to black
        color interA = lerpColor(c, b, map(k, 0, disMap, 0, 1));

        //drawing the ellipses
        noStroke();
        fill(interA);
        ellipse(pressedPositions[j].x, pressedPositions[j].y, k, k);
      }
    } else {
      isPressed[j] = false;
    }
  }
}


//try not to mess with this
void serialEvent (Serial p) {
  try {
    String myString = p.readStringUntil(lf);
    if (myString != null) {
      myString = trim(myString);
      println(myString);
      String[]in = split(myString, '>');
      for (int i = 0; i < in.length; i ++) {
        pressedArray[i] = int(in[i]);
      }
    }
  }
  catch(Exception e) {
  }
}

I'm aware you might not be able to run this code, as you don't have the physical components, but I'd really appreciate some help.

Tagged:

Answers

  • edited April 2017 Answer ✓

    Line 7 has should be 5 based on line 44-48. Is it a typo?

    Have the following function to trigger the sound.

    Kf

    ****EDIT: typo in var definition

    final int playSilence = -1;
    int sountToPlay;
    
    void triggerSound(){
      soundToPlay=random(splashes.length);
    
      //Play silence 50% of the time. You can change it 
      //to have a higher or lower probability to be a silence
      if(random()<0.5)
        soundToPlay=playSilence;
    
       //Disable all sounds in case any is playing
       for(AudioPlayer au : splashes){
          au.stop();
       }
    
       if(soundToPlay!=playSilence){
         splashes[soundToPlay].play();
       }
    }
    
  • Yes of course, my apologies. In the code you've posted, where would that index be placed? Thank you so much!

  • The function triggerSound() is at the same level than draw or setup. The variables sountToPlay and playSilence need to be at a global scope. You call this function when you want it to trigger, which you describe to be above your threshold of 800.

    However, I can see this is not going to work right away. Anytime the threshold is above 800, it will generate a random number and generate a random file or silence. You need to make sure the above function only gets trigger once (trigger and latches) and it will trigger again only if it goes above the thresold after going below threshold. You will need:

    //Global Scope
    final int playSilence = -1;
    int sountToPlay;
    bool triggerStatus=false;
    

    Now in draw() and notice I change your conditional inequality to match it to my previous description:

    //Trigger condition:
    //Above threshold and not trigger before (trigger not latched)
    if (pressedArray[j] > 800 && triggerStatus==false) {
       triggerSound();
       triggerStatus=true; //Latch trigger. No new triggers but only after it goes below threshold
    } else{
       triggerStatus=false;  //Release trigger latch
       //Here you could pause all your splash sounds if desired.
    }
    

    Notice this is untested code. The concept is still valid. Notice I was not careful to consider your design of triggering since you are triggering from an array in line 75. You will need to adapt your code for your needs.

    Kf

  • I thought the same thing, and I'm glad you were able to help. The sound should be triggered when the electrode is pressed, so should it be swapped where the trigger is false when the array value goes below 800? (which is how the visuals are triggered) I'll test this new development and keep working at it. thank you

  • Yes, just change it to " less than 800". Give it a try and I am sure you can get it to work based on this concept.

    Kf

  • I'm having an error in the triggerSound function, it's saying "Type mismatch, "float" does not match "int"" for the line that says 'soundToPlay=random(splashes.length);'. What could I do to fix this?

  • soundToPlay=(int)random(splashes.length);
    

    Kf

Sign In or Register to comment.