Beads - Samples all play on AudioContext start

I’m testing out the Beads library and I’ve got some samples playing via SamplePlayer. The problem is, after loading the samples in and setting up the AudioContext in the setup method, using ac.start() causes all the samples to play one time, all at once, and then they play as normal when triggered/expected.

I’m fairly new to Beads but I’ve followed the whole tutorial book Sonifying Processing, and I’m developing on the examples in that book. The structure of my code is just:

  • Create AudioContext ac
  • Create a master Gain object (with gain 0.0, no Glides involved)
  • Load samples into array of SamplePlayers, using setKillOnEnd to false, and add them all as input to the masterGain
  • Add masterGain to ac using ac.out.addInput()
  • ac.start()

I use setToLoopStart() and then start() on each SamplePlayer as required following this, and they play fine, but a cacophony of samples at the start of the program is not what I expect. Is this the intended AudioContext behaviour and I am just misunderstanding it?
Is there a way to pause any playback of samples until specifically triggered, or is it possible to start an AudioContext and then add SamplePlayers? Any pointers would be much appreciated!

1 Like

Could you post your code?

Thanks for your response - code pasted below:

import beads.*;
import java.util.Arrays;
import java.io.File;
import java.util.Random;

AudioContext ac;
SamplePlayer[] snares;
SamplePlayer[] kicks;
SamplePlayer[] hats;

int snareCount = 0;
int kickCount = 0;
int hatCount = 0;
String[] snareFiles;
String[] kickFiles;
String[] hatFiles;
Gain masterGain;

void setup() {
  size(500, 500);
  ac = new AudioContext();
  
  masterGain = loadSamples();

  ac.out.addInput(masterGain);
  
  if ((snareCount == 0) || (kickCount == 0) || (hatCount == 0))
    print("Could not find requested samples! Exiting.");
  
  Clock beatCounter = new Clock(ac, 700);
  beatCounter.setTicksPerBeat(2);
  
  Bead musicMaker = new Bead() {
    public void messageReceived(Bead message) {
      playStuff(message);
    }
  };
 
 beatCounter.addMessageListener(musicMaker);
 ac.out.addDependent(beatCounter);
 ac.start();
 
 masterGain.setGain(1);
 
}

void draw() {
}

void playStuff(Bead message) {
 // This plays the samples according to Clock beats, but is removed because it's a long method
}


Gain loadSamples() {
  Gain masterGain = new Gain(ac, 1, 0.0);
  
  String snarePath = sketchPath("") + "data/snare";
  String kickPath = sketchPath("") + "data/kick";
  String hatPath = sketchPath("") + "data/hats";
  
  File snaresFolder = new File(snarePath);
  File kicksFolder = new File(kickPath);
  File hatsFolder = new File(hatPath);
  
  File[] snaresList = snaresFolder.listFiles();
  File[] kicksList = kicksFolder.listFiles();
  File[] hatsList = hatsFolder.listFiles();
  
  snareFiles = new String[snaresList.length];
  kickFiles = new String[kicksList.length];
  hatFiles = new String[hatsList.length];
  
  //Read in snares
  for (int i = 0; i < snaresList.length; i++) {
    if ((snaresList[i].isFile()) && (snaresList[i].getName().endsWith(".wav"))) {
      snareFiles[snareCount] = snaresList[i].getName();
      snareCount++;
    }
  }
  //Read in kicks
  for (int i = 0; i < kicksList.length; i++) {
    if ((kicksList[i].isFile()) && ( kicksList[i].getName().endsWith(".wav"))){
      kickFiles[kickCount] = kicksList[i].getName();
      kickCount++;
    }
  }
  //Read in hats
  for (int i = 0; i < hatsList.length; i++) {
    if ((hatsList[i].isFile()) && (hatsList[i].getName().endsWith(".wav"))) {
      hatFiles[hatCount] = hatsList[i].getName();
      hatCount++;
    }
  }
  
    try {
    snares = new SamplePlayer[snareCount];
    kicks = new SamplePlayer[kickCount];
    hats = new SamplePlayer[hatCount];

    for (int i = 0; i < snareCount; i++) {
      snares[i] = new SamplePlayer(ac, new Sample(snarePath + "/" + snareFiles[i]));
      snares[i].setKillOnEnd(false);
      masterGain.addInput(snares[i]);
    }
    for (int i = 0; i < kickCount; i++) {
      kicks[i] = new SamplePlayer(ac, new Sample(kickPath + "/" + kickFiles[i]));
      kicks[i].setKillOnEnd(false);
      masterGain.addInput(kicks[i]);
    }
    for (int i = 0; i < hatCount; i++) {
      hats[i] = new SamplePlayer(ac, new Sample(hatPath + "/" + hatFiles[i]));
      hats[i].setKillOnEnd(false);
      masterGain.addInput(hats[i]);
    }
  } catch (Exception e) {
    e.printStackTrace();
    exit();
  }
  
  return (masterGain);
  
}

The code run as-is in this sample plays all the samples once and then does nothing else.

I think I forgot to mention that after setting the masterGain value to 0.0 on creation, I reset it to 1.0 after ac.start(). Removing this line does leave the gain at 0, and the samples presumably play muted, but I thought that it was on the line ac.start() that the samples play - clearly not, given that the gain isn’t changed until after this. Essentially, I’m just not sure which part of the code is making all the samples play that one time!

1 Like