Open AL with LWJGL 3

Started by lucasfraser, July 17, 2016, 07:33:26

Previous topic - Next topic

lucasfraser

Hi Guys,

I've had a bit of a look at the examples and had a play around but haven't been able to get a solid audio system working in my game.

I'm interested to know if anyone has some base code or some well documented examples I could go through to get my system working fully?

Ideally it will load in .ogg files :)

Cheers,
Lucas

spasi

Could you share some details about your environment? (OS, JVM, etc)

Are you getting any errors from OpenAL? Setting the ALSOFT_LOGLEVEL environment variable to 3 might provide useful information. See env-vars.txt for more details.

lucasfraser

Quote from: spasi on July 17, 2016, 09:27:44
Could you share some details about your environment? (OS, JVM, etc)

Are you getting any errors from OpenAL? Setting the ALSOFT_LOGLEVEL environment variable to 3 might provide useful information. See env-vars.txt for more details.

Hi there Spasi,

I've tried a few implementations, some worked some didn't, the main issue I was having was that I loaded the files in and it would cut out half way through a song... That was it... No errors, I presume something along the lines of an issue when I loaded the file into memory.

Really I'm just looking for advice before I start trying to implement this again.

EDIT: For the record: Windows, Java 8 (oracle), latest LWJGL release

Cheers.
Lucas

spasi

Could you provide a minimal code sample that reproduces the issue?

lucasfraser

Hi Again, below is my code that was cutting off the sound file

SoundUtils.java (loads up the vorbris into memory)
public class SoundUtils {

    static ByteBuffer readVorbis(String resource, int bufferSize, STBVorbisInfo info) {
        ByteBuffer vorbis;
        try {
            vorbis = ioResourceToByteBuffer(resource, bufferSize);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        IntBuffer error = BufferUtils.createIntBuffer(1);
        long decoder = stb_vorbis_open_memory(vorbis, error, null);
        if ( decoder == NULL )
            throw new RuntimeException("Failed to open Ogg Vorbis file. Error: " + error.get(0));

        stb_vorbis_get_info(decoder, info);

        int channels = info.channels();

        int lengthSamples = stb_vorbis_stream_length_in_samples(decoder);

        ByteBuffer pcm = BufferUtils.createByteBuffer(lengthSamples * 2);

        stb_vorbis_get_samples_short_interleaved(decoder, channels, pcm, lengthSamples);
        stb_vorbis_close(decoder);

        return pcm;
    }

    private static ByteBuffer resizeBuffer(ByteBuffer buffer, int newCapacity) {
        ByteBuffer newBuffer = BufferUtils.createByteBuffer(newCapacity);
        buffer.flip();
        newBuffer.put(buffer);
        return newBuffer;
    }

    public static ByteBuffer ioResourceToByteBuffer(String resource, int bufferSize) throws IOException {
        ByteBuffer buffer;

        File file = new File(resource);
        if ( file.isFile() ) {
            FileInputStream fis = new FileInputStream(file);
            FileChannel fc = fis.getChannel();

            buffer = BufferUtils.createByteBuffer((int)fc.size() + 1);

            while ( fc.read(buffer) != -1 ) ;

            fis.close();
            fc.close();
        } else {
            buffer = createByteBuffer(bufferSize);

            InputStream source = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
            if ( source == null )
                throw new FileNotFoundException(resource);

            try {
                ReadableByteChannel rbc = Channels.newChannel(source);
                try {
                    while ( true ) {
                        int bytes = rbc.read(buffer);
                        if ( bytes == -1 )
                            break;
                        if ( buffer.remaining() == 0 )
                            buffer = resizeBuffer(buffer, buffer.capacity() * 2);
                    }
                } finally {
                    rbc.close();
                }
            } finally {
                source.close();
            }
        }
        buffer.flip();
        return buffer;
    }
}



Then there is the actual sound object

public class AudioObject {

    Vector3f position = new Vector3f(0, 0, 0);
    float volume = 1f;
    private boolean looping;

    int source = 0;
    int buffer = 0;


    public AudioObject(String filename){ //loads file
        loadAudio(filename);
        setVolume(volume);
        setPosition(position);
    }

    private void loadAudio(String filename){

        STBVorbisInfo info = STBVorbisInfo.malloc();
        ByteBuffer pcm = readVorbis(filename, 0, info);

        // generate buffers and sources
        buffer = alGenBuffers();
        checkALError();

        source = alGenSources();
        checkALError();

        //copy to buffer
        alBufferData(buffer, AL_FORMAT_STEREO16, pcm, info.sample_rate());
        checkALError();

        info.free();

        //set up source input
        alSourcei(source, AL_BUFFER, buffer);
        checkALError();

        setPosition(position);
        alSourcef(source, AL_REFERENCE_DISTANCE, 0);
        alSourcef(source, AL_MAX_DISTANCE, 100);


        //play source 0
        alSourcePlay(source);
        checkALError();

    }

    public void setVolume(float vol){
        alSourcef(source, AL_GAIN, vol);
        checkALError();
    }

    public void setPosition(Vector3f pos){
        alSource3f(source, AL_POSITION, pos.getX(), pos.getY(), pos.getZ());
        checkALError();
    }

    public void setLooping(boolean looping){
        if(looping) {
            alSourcei(source, AL_LOOPING, AL_TRUE);
        }
        else{
            alSourcei(source, AL_LOOPING, AL_FALSE);
        }
        checkALError();
    }

    public void stop(){
        alSourceStop(source);

        //delete buffers and sources
        alDeleteSources(source);

        alDeleteBuffers(buffer);
    }
}


Hopefully there is just something I missed amongst the loading and playing code. If not, any resources with some base code would be great to look over :)

Cheers.
Lucas

spasi

First of all, I don't think you're using the 3.0.0 release. There's no stb_vorbis_get_samples_short_interleaved that accepts a ByteBuffer in 3.0.0.

Your code works for me with the following changes:

1) Changed readVorbis to create a ShortBuffer:

ShortBuffer pcm = createShortBuffer(lengthSamples);

pcm.limit(stb_vorbis_get_samples_short_interleaved(decoder, channels, pcm) * channels);


2) Used a non-zero bufferSize in the readVorbis call.