Processing and Threads

I've got the following little threaded application that records some sound until the user releases the mouse button:

import javax.sound.sampled.*;
import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import http.requests.*;
import java.util.concurrent.atomic.AtomicInteger;

final JavaSoundRecorder recorder = new JavaSoundRecorder(); 
Thread thread;

boolean recording = false;

void setup()
{
}

void draw()
{
  //println(rr.getStop());
  print(frameCount + " ");
}

void mouseReleased()
{
  println(" released ");  
  recording = false;
}

void mousePressed()
{
  println(" started ");
  recording = true;

  thread = new Thread(new Runnable() {
   public void run() {
     try {
       Thread.sleep(50); // this is fine if I just timeout and bail
       Thread.yield();
       if (!recording) {
         println(" not recording ");
         recorder.finish();
         thread.join();
       }
     } 
     catch (InterruptedException ex) {
       ex.printStackTrace();
     }
   }
  });

  thread.start();
  // start recording
  recorder.start("test.wav");

  println(" OK " );
}

Works perfectly if I just time out the thread with a fixed time amount but I can't get the thread to listen to any input from the user. The sketch completely stops running the main p5 thread; no draw(), no mouseReleased(), etc. This is, I'm guessing, because my little recorder class is creating a second thread that starves the main P5 thread:

    public class JavaSoundRecorder {

      long length;

      // format of audio file
      AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;

      // the line from which audio data is captured
      TargetDataLine line;

      /**
       * Defines an audio format
       */
      AudioFormat getAudioFormat() {
          float sampleRate = 8000;
          int sampleSizeInBits = 8;
          int channels = 2;
          boolean signed = true;
          boolean bigEndian = true;
          AudioFormat format = new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
          return format;
      }

      /**
       * Captures the sound and record into a WAV file
       */
      void start( String path) {

          String finalPath = sketchPath() + "/" + path;

          File wavFile = new File(finalPath);

          System.out.println(finalPath);

          try {
              AudioFormat format = getAudioFormat();
              DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);

              // checks if system supports the data line
              if (!AudioSystem.isLineSupported(info)) {
                  System.out.println("Line not supported");
                  System.exit(0);
              }
              line = (TargetDataLine) AudioSystem.getLine(info);
              line.open(format);
              line.start();   // start capturing

              println("Start capturing...");

              AudioInputStream ais = new AudioInputStream(line);

              length = ais.getFrameLength() * ais.getFormat().getFrameSize();

              println("Start recording...");

              // start recording
              AudioSystem.write(ais, fileType, wavFile);

          } catch (LineUnavailableException ex) {
              ex.printStackTrace();
          } catch (IOException ioe) {
              ioe.printStackTrace();
          }
      }

      /**
       * Closes the target data line to finish capturing and recording
       */
      void finish() {
          println("Finished");
          line.stop();
          line.close();
      }

    }

I'm used to C++ threads and don't really understand what's going on under the hood of the JVM threading, can anyone enlighten me as to how to get my AudioInputStream based class to play nice with the main p5 thread?

Answers

  • my little recorder class is creating a second thread

    Your recorder doesn't create a thread.

    You just call the start method of it in the main thread. So the code in this method is executed by the main thread. When it reach AudioSystem.write(ais, fileType, wavFile) it blocks the main thread.

    To solve this you should call the recorder method in a separate thread.

Sign In or Register to comment.