Hey silent_ptr, I'm just starting with OpenAL and I've been hitting a lot of the same problems as you so I took a look at your code.
Firstly, I notice from the filename you're passing in a .mp3 file to the ogg vorbis decoder, which probably won't work. Best test this out with an ogg encoded sound file.
I was able to recreate your EXCEPTION_ACCESS_VIOLATION crash locally, and I found a few things:
You're not checking the result of stb_vorbis_decode_filename, as it will return -1 on error.
We also need the number of samples for later...
int samplesDecoded = STBVorbis.stb_vorbis_decode_filename("C:\\Git\\test-project\\src\\main\\resources\\music.ogg", channelsPtr, sampleRatePtr, dataPtr);
if (samplesDecoded == -1) {
throw new IllegalStateException("No samples were decoded");
}
The next problem is with alBufferData:
You're hardcoding the format which isn't ideal, you can replace that with (channels == 1 ? AL11.AL_FORMAT_MONO16 : AL11.AL_FORMAT_STEREO16)
The data being passed in isn't right for a couple of reasons:
dataPtr.sizeof() just gets the size of the pointer itself in bytes (which is 4 bytes on a 32bit JVM and 8 bytes on a 64bit JVM) and not the size of the buffer which is what you were expecting.
Each sample is a short, so the size of the buffer that is referenced by the pointer will be the number of samples decoded multipled by the number of channels multiplied by the number of bytes in a short (samplesDecoded * channels * Short.BYTES).
We can get the data either by getting a ByteBuffer of the previously calulated size from the PointerBuffer:
dataPtr.getByteBuffer(samplesDecoded * channels * Short.BYTES)
or by just getting a ShortBuffer:
dataPtr.getShortBuffer(samplesDecoded * channels)
Putting it all together, here is an example that works (on my machine at least):
public static void main(String[] args) {
int alError;
long device = ALC11.alcOpenDevice((ByteBuffer)null);
if (device == 0)
{
throw new IllegalStateException();
}
ALCCapabilities capabilities = ALC.createCapabilities(device);
if (capabilities == null)
{
ALC11.alcCloseDevice(device);
throw new IllegalStateException();
}
long context = ALC11.alcCreateContext(device, (IntBuffer)null);
ALC11.alcMakeContextCurrent(context);
AL.createCapabilities(capabilities);
int buffer = AL11.alGenBuffers();
int channels;
int sampleRate;
try (MemoryStack stack = MemoryStack.stackPush())
{
IntBuffer channelsPtr = stack.mallocInt(1);
IntBuffer sampleRatePtr = stack.mallocInt(1);
PointerBuffer dataPtr = stack.mallocPointer(1);
int samplesDecoded = STBVorbis.stb_vorbis_decode_filename("C:\\Git\\test-project\\src\\main\\resources\\music.ogg", channelsPtr, sampleRatePtr, dataPtr);
if (samplesDecoded == -1) {
throw new IllegalStateException("No samples were decoded");
}
// Metadata
channels = channelsPtr.get();
sampleRate = sampleRatePtr.get(0);
AL11.alBufferData(
buffer,
(channels == 1 ? AL11.AL_FORMAT_MONO16 : AL11.AL_FORMAT_STEREO16),
dataPtr.getShortBuffer(samplesDecoded * channels),
//dataPtr.getByteBuffer(samplesDecoded * channels * Short.BYTES),
sampleRate
);
alError = AL11.alGetError(); System.out.printf("alGetError=%s%n", AL10.alGetString(alError));
}
int source = AL11.alGenSources();
AL11.alSourcei(source, AL11.AL_BUFFER, buffer);
alError = AL11.alGetError(); System.out.printf("alGetError=%s%n", AL10.alGetString(alError));
AL11.alSourcePlay(source);
alError = AL11.alGetError(); System.out.printf("alGetError=%s%n", AL10.alGetString(alError));
while (AL11.alGetSourcei(source, AL10.AL_SOURCE_STATE) == AL10.AL_PLAYING) {
;
}
}