Hello Guest

Am I doing something wrong here? (peer review)

  • 0 Replies
  • 8259 Views
*

Offline moci

  • *
  • 27
    • mathiasverboven.net
Am I doing something wrong here? (peer review)
« on: February 13, 2012, 20:41:08 »
Hi, the goal is simple. Create a microphone streamer that has one source.
The stream can be delayed by some arbitrary amount (5 seconds in this case).

It works, but it's always worth having smarter people go over the code.

Here's the general class that has a main:
Code: [Select]
package capturetest;

public class MicStreamer {
public static void main(String[] args) {
InputStreamer inputStreamer = new InputStreamer();
InputThread inputThread = new InputThread(inputStreamer);

(new Thread(inputThread)).start();
inputStreamer.execute();
}
}

Here's the actual streaming class:
Code: [Select]
package capturetest;

import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.openal.AL;
import org.lwjgl.openal.AL10;
import org.lwjgl.openal.ALC10;
import org.lwjgl.openal.ALC11;
import org.lwjgl.openal.ALCdevice;

public class InputStreamer {
public boolean doneCapturing = false;

public void execute() {
// Initialize LWJGL  OpenAL
try {
AL.create();
} catch (LWJGLException le) {
le.printStackTrace();
return;
}
this.checkErrors();

int FREQ = 44100;
int FORMAT = AL10.AL_FORMAT_MONO16;
int BUFFERSIZE = FREQ / 50;
int BYTESPERSAMPLE = 16 / 8;

// Connect to the input driver, it will allow us to capture sound
ALCdevice inputDevice = ALC11.alcCaptureOpenDevice(null, FREQ, FORMAT, BUFFERSIZE);
// Connect to the rapture3D driver, it will do the HRTF processing.
ALCdevice outputDevice = ALC10.alcOpenDevice("Rapture3D");

this.checkErrors();

IntBuffer samplesCaptured = BufferUtils.createIntBuffer(1);
ByteBuffer samplesBuffer = BufferUtils.createByteBuffer(BUFFERSIZE * BYTESPERSAMPLE);

// Create a source object
int source = AL10.alGenSources();

// Add delay of X seconds
int delayTime = 5;
int delayBuffer = AL10.alGenBuffers();
ByteBuffer delaySamples = BufferUtils.createByteBuffer(FREQ * BYTESPERSAMPLE * delayTime);

AL10.alBufferData(delayBuffer, FORMAT, delaySamples, FREQ);
AL10.alSourceQueueBuffers(source, delayBuffer);

AL10.alDeleteBuffers(delayBuffer);

this.checkErrors();

while (!doneCapturing) {
// Start capturing
ALC11.alcCaptureStart(inputDevice);

// Wait until the proper amount of samples has been captured
while (samplesCaptured.get(0) < BUFFERSIZE) {
ALC10.alcGetInteger(inputDevice, ALC11.ALC_CAPTURE_SAMPLES, samplesCaptured);
}

// Stop capturing
ALC11.alcCaptureStop(inputDevice);

// Retrieve the captured samples and set counter
ALC11.alcCaptureSamples(inputDevice, samplesBuffer, BUFFERSIZE);
ALC10.alcGetInteger(inputDevice, ALC11.ALC_CAPTURE_SAMPLES, samplesCaptured);

this.checkErrors();

// Create new buffer object
int buffer = AL10.alGenBuffers();

// Put samples data in buffer object
AL10.alBufferData(buffer, FORMAT, samplesBuffer, FREQ);

// Queue buffer to the source object
AL10.alSourceQueueBuffers(source, buffer);

int sourceState = AL10.alGetSourcei(source, AL10.AL_SOURCE_STATE);
if (sourceState != AL10.AL_PLAYING) {
AL10.alSourcePlay(source);
}

// Destroy buffer
AL10.alDeleteBuffers(buffer);

// Dequeue processed buffers
AL10.alSourceUnqueueBuffers(source);

this.checkErrors();
}

// Close the in/out device
ALC10.alcCloseDevice(inputDevice);
ALC10.alcCloseDevice(outputDevice);

// Destroy source object
AL10.alDeleteSources(source);

// Close OpenAL
AL.destroy();
}

/**
* Check the current error state of AL
* @return true if there was an error. false if 'AL_NO_ERROR' (no error).
*/
private boolean checkOpenALErrors() {
boolean ret = true;

switch (AL10.alGetError()) {
case AL10.AL_NO_ERROR:
ret = false;
break;
case AL10.AL_INVALID_NAME:
System.out.println("Invalid name parameter.");
break;
case AL10.AL_INVALID_ENUM:
System.out.println("Invalid parameter.");
break;
case AL10.AL_INVALID_VALUE:
System.out.println("Invalid enum parameter value.");
break;
case AL10.AL_INVALID_OPERATION:
System.out.println("Illegal call.");
break;
case AL10.AL_OUT_OF_MEMORY:
System.out.println("Unable to allocate memory.");
}

if (ret) {
System.out.println("- Error in AL.");
}

return ret;
}

/**
* Check the current error state of ALC
* @return true if there was an error. false if 'ALC_NO_ERROR' (no error).
*/
private boolean checkOpenALCErrors() {
boolean ret = true;

switch (AL10.alGetError()) {
case ALC10.ALC_NO_ERROR:
ret = false;
break;
case ALC10.ALC_INVALID_DEVICE:
System.out.println("The device handle or specifiers names an inaccessible driver/server");
break;
case ALC10.ALC_INVALID_CONTEXT:
System.out.println("The Context argument does not name a valid context.");
break;
case ALC10.ALC_INVALID_ENUM:
System.out.println("A token used is not valid, or not applicable.");
break;
case ALC10.ALC_INVALID_VALUE:
System.out.println("A value (e.g. Attribute is not valid, or not applicable.");
break;
case ALC10.ALC_OUT_OF_MEMORY:
System.out.println("Unable to allocate memory.");
break;
}

if (ret) {
System.out.println("- Error in ALC.");
}

return ret;
}

private boolean checkErrors() {
return this.checkOpenALErrors() || this.checkOpenALCErrors();
}
}

Here is the input request class (for stopping the application) - a dirty copy/paste from OpenAL_lesson1 from the wiki:
Code: [Select]
package capturetest;

import java.util.Scanner;

public class InputThread implements Runnable {
private InputStreamer _streamer;

public InputThread(InputStreamer streamer) {
_streamer = streamer;
}

public void run() {
   char c = ' ';
   Scanner stdin = new Scanner(System.in);
   while(c != 'q') {
    try {
     System.out.print("Input (q to stop): ");
     c = (char)stdin.nextLine().charAt(0);
    } catch (Exception ex) {
    c = 'q';
    }
   
    if (c == 'q') {
    _streamer.doneCapturing = true;
    }
   }
}
}

If you would run this code, mind that I'm using "Rapture3D" as an output device, you might not have it installed and must replace it with a "null" to select a default device. I'm using LWJGL 2.8.3 .

Thanks
« Last Edit: February 21, 2012, 08:24:51 by moci »