The native signature is: float ***output. This means that the output argument receives a pointer (a single value) that points to an array of pointers (float**) that each point to a float array (float*). The following code should help:
try ( MemoryStack stack = stackPush() ) {
IntBuffer channels_p = stack.mallocInt(1); // int*
IntBuffer samples_p = stack.mallocInt(1); // int*
PointerBuffer output_ppp = stack.mallocPointer(1); // float***
stb_vorbis_decode_frame_pushdata(f, datablock, channels_p, output_ppp, samples_p);
int channels = channels_p.get(0);
int samples = samples_p.get(0);
PointerBuffer output_pp = output_ppp.getPointerBuffer(channels); // float**
for ( int c = 0; c < channels; c++ ) {
FloatBuffer channel = output_pp.getFloatBuffer(c, samples); // float*
for ( int s = 0; s < samples; s++ ) {
float sample = channel.get(s);
// ...
}
}
}