Skip to content

Recording Audio

Hangman edited this page Jan 9, 2022 · 1 revision

The CaptureDevice class gives you access to an input device from which you can obtain and record audio data. It also gives access to some static functions that provide information about the available hardware. CaptureDevice is independent from the rest of TuningFork, so you can use a CaptureDevice without initializing Audio. I doubt it's of much use but it's possible to have multiple instances of CaptureDevice co-existing.

Opening a CaptureDevice

To open the default input device with default settings is pretty simple:

CaptureDevice device = CaptureDevice.open();
if (device == null) {
    // failed to open the device
}

If you want to configure the audio settings for the CaptureDevice (choose a specific microphone to use as input for example):

CaptureConfig config = new CaptureConfig(); // the config is initialized with default settings
config.setPcmFormat(PcmFormat.MONO_16_BIT);
config.setFrequency(48000);
config.setBufferSize(8192 * 2);
config.setDeviceSpecifier(deviceName);
config.setLogger(myLogger);

CaptureDevice captureDevice = CaptureDevice.open(config);
if (device == null) {
    // failed to open the device
}

To get a list of available input devices:

List<String> availableDevices = CaptureDevice.availableDevices();

Capturing audio

After opening it, the device will be in an idle state. To actually start the capture process you have to call:

device.startCapture();

Once the capture is started, you can fetch pcm data from the device. To do that, you need a buffer to store the data. It's recommended to make this buffer smaller than the internal capture buffer that OpenAL uses (the one you have configured in CaptureConfig). If you opened the CaptureDevice without a configuration, you can check what buffer size was used with device.getBufferSize(). In most cases you want to fetch audio data continuously from the device, so here's an example how to do that:

// setup
int bufferSize = 4410;
ByteBuffer buffer = BufferUtils.newByteBuffer(bufferSize);

...

// in render loop
while (device.capturedSamples() >= bufferSize) {
    buffer.clear();
    device.fetch8BitSamples(buffer, bufferSize);
    // buffer is now filled with actual data captured by the device
    // do something with the data
}

You may have noticed that the method to fetch pcm data from the device is named fetch8BitSamples. You guessed right, there's also a method fetch16BitSamples() for which you need a ShortBuffer. To stop the capture process again, call:

device.stopCapture();

Closing a CaptureDevice

As always, don't forget to dispose:

device.dispose();

Full example

Check out the Capture Test for a full self-contained runnable example.