Using Audiotrack() and running other processes..

edited July 2015 in Android Mode

Hi all. I am having fun using Processing for Android to program my SBC which is running Andoid 4.4. I have a project I am working on that involves playing some sine waves and using an accelerometer to change the frequency. The code I am using to produce the sinewaves is from a theremin project I found on the web and uses a runnable class to call the audiotrack object. The code is here:

`public class tonebox implements Runnable {

// If you change this, then you will have to adjust some of the // other cyclic factors as well, notably warble. Sample length // makes for more nimble tone changes. public int sampleLength = 64; // This is the frequency max. Most examples show 44100, but this // only invites static. We never climb above about 3000 so this // could even be set lower. public int freqRange = 11025;

// 1 to maxTones independent tones public int maxTones = 6; private int howl = 1; private boolean fuzz = false;

private double warbMag = 0.0; private double warbFreq = 0.0; // range in hertz, suggest 200 to 2500 private double freq = 0.0; private double volume = 0.0; private boolean go = true; private boolean finished = false;

AudioTrack Track;//= new AudioTrack(AudioManager.STREAM_MUSIC, // freqRange, AudioFormat.CHANNEL_CONFIGURATION_MONO, // AudioFormat.ENCODING_PCM_16BIT, sampleLength, // AudioTrack.MODE_STATIC);;

// magnitude of warble oscillation, suggest 0.0 to 50 public synchronized void warbleMagnitude(int wm) {

warbMag = (double) wm;

}

// suggest 0.0 to 0.15 public synchronized void warbleFrequency(double wf) {

warbFreq = wf;

}

public synchronized void frequency(int fr) {

freq = (double) fr;

}

// volume is 0.0 to 1.0 public synchronized void volume(double vol) {

volume = vol;

}

public void start(boolean g) {

go = g;

}

public synchronized void howl(int h) {

howl = h;

}

public void run() {

short samples[] = new short[sampleLength];
double freqBase[] = new double[maxTones];
int freqTrack[] = new int[maxTones];
int freqVector[] = new int[maxTones];
double angle[] = new double[maxTones];
double collectedAngle;
double computedWarble = 0;
int fuzzBase;

Random gen = new Random();

// set up audio Track and start it
int minSize = AudioTrack.getMinBufferSize(

freqRange, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT );

Track = new AudioTrack( AudioManager.STREAM_MUSIC, freqRange, 

AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, 
minSize, AudioTrack.MODE_STREAM);

Track.play();

// feed it samples
while (!finished) {




  if (go) {

    // compute the base sample frequency
    freqBase[0] = freq + warbMag * Math.sin(computedWarble);

    // append any additional harmonics
    for ( int i = 1; i < howl; i++) {

      freqVector[i] += gen.nextInt(3) - 1;
      if ( Math.abs(freqVector[i]) > 6 ) freqVector[i] = (int) (freqVector[i] / 2);
      freqTrack[i] += freqVector[i];
      if ( Math.abs(freqTrack[i]) > 100) freqVector[i] = -freqVector[i];
      freqBase[i] = freqBase[0] + freqTrack[i];
    }

    // fill sample
    for (int i = 0; i < sampleLength; i++ ) {

      collectedAngle = 0;

      // compute base tone and then append any additional
      for ( int j = 0; j < howl; j++) {

        // for fuzz, compute a parabolic random displacement
        if (fuzz) {

          fuzzBase = 0;
          for (int k = 0; k < 5; k++)

            fuzzBase += gen.nextInt(15);

          freqBase[j] += fuzzBase - 35;
        }

        angle[j] += 2 * Math.PI * freqBase[j] / freqRange;
        if (angle[j] > (2 * Math.PI))

          angle[j] -= (2 * Math.PI);


        collectedAngle += Math.sin(angle[j]);
      }

      samples[i] = (short) ((collectedAngle / howl) * Short.MAX_VALUE * volume);
    }

    // advance warble
    computedWarble += warbFreq;
    if (computedWarble > (2 * Math.PI)) {

      computedWarble -= (2 * Math.PI);
    }

    // shove the sample into the stream
    Track.write(samples, 0, sampleLength);

    go2=go;
  } 
  else {

    // wait when stopped
    try {

      Thread.sleep(100);
    } 
    catch (InterruptedException e) {

      e.printStackTrace();
    }
  }
}

} }`

It is easy to use. I set up frequency and volume in void setup() and call the run() method in void draw() It plays.

I also want to read some accelerometer values so have a function to call a bash script on my Android device. The code is here:

`void readaccel() { // what command to run String commandToRun = "mpu-6050-getbyte 3b"; // String commandToRun = "ls"; // String commandToRun = "wc -w sourcefile.extension"; // String commandToRun = "cp sourcefile.extension destinationfile.extension"; // String commandToRun = "./yourBashScript.sh";

File workingDir = new File("/system/bin/"); // where to do it - should be full path String returnedValues; // value to return any results

// give us some info:

// println("Running command: " + commandToRun); // println("Location: " + workingDir); // println("---------------------------------------------\n");

try {

// complicated!  basically, we have to load the exec command within Java's Runtime
// exec asks for 1. command to run, 2. null which essentially tells Processing to 
// inherit the environment settings from the current setup (I am a bit confused on
// this so it seems best to leave it), and 3. location to work (full path is best)
Process p = Runtime.getRuntime().exec(commandToRun, null, workingDir);

// variable to check if we've received confirmation of the command
int i = p.waitFor();

// if we have an output, print to screen
if (i==0 ) {

  // BufferedReader used to get values back from the command
  BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));

  // read the output from the command
  while ( (returnedValues = stdInput.readLine ()) != null) {
    println(returnedValues);
    x=((returnedValues));
    // xcoord=Integer.parseInt(returnedValues,2);
  }
}

// if there are any error messages but we can still get an output, they print here
else {
  BufferedReader stdErr = new BufferedReader(new InputStreamReader(p.getErrorStream()));

  // if something is returned (ie: not null) print the result
  while ( (returnedValues = stdErr.readLine ()) != null) {
    println(returnedValues);
  }
}
// box.run();

}

// if there is an error, let us know catch (Exception e) { println("Error running command!");
println(e); } }`

It works fine but when I try to run both the audiotrack class and the accelerometer reader in draw(), audiotrack blocks the accelerometer process. I'm not up on threads but could someone please help me work out how to run both processes at the same time?

Thanks. Steve.S

p.s. i dont know why my code isn't being formatted properly. sorry.

Answers

Sign In or Register to comment.