117 lines
3.8 KiB
Java
117 lines
3.8 KiB
Java
package electrosphere.audio;
|
|
|
|
import electrosphere.logger.LoggerInterface;
|
|
import electrosphere.util.FileUtils;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.IntBuffer;
|
|
import java.nio.ShortBuffer;
|
|
import java.nio.channels.Channels;
|
|
import java.nio.channels.ReadableByteChannel;
|
|
import java.nio.channels.SeekableByteChannel;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.Paths;
|
|
import org.lwjgl.BufferUtils;
|
|
import static org.lwjgl.BufferUtils.createByteBuffer;
|
|
import static org.lwjgl.openal.AL10.*;
|
|
import static org.lwjgl.stb.STBVorbis.*;
|
|
import org.lwjgl.stb.STBVorbisInfo;
|
|
import org.lwjgl.system.MemoryStack;
|
|
import org.lwjgl.system.MemoryUtil;
|
|
import static org.lwjgl.system.MemoryUtil.NULL;
|
|
|
|
public class AudioBuffer {
|
|
|
|
private int bufferId;
|
|
|
|
private ByteBuffer vorbis = null;
|
|
|
|
private ShortBuffer pcm = null;
|
|
|
|
public AudioBuffer(String fileName) {
|
|
bufferId = alGenBuffers();
|
|
try (STBVorbisInfo info = STBVorbisInfo.malloc()) {
|
|
ShortBuffer pcm = readVorbis(fileName, 32 * 1024, info);
|
|
// Copy to buffer
|
|
alBufferData(bufferId, info.channels() == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, pcm, info.sample_rate());
|
|
} catch (Exception e){
|
|
LoggerInterface.loggerEngine.ERROR("Failed to load audio", e);
|
|
// e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
|
|
private ShortBuffer readVorbis(String resource, int bufferSize, STBVorbisInfo info) throws Exception {
|
|
try (MemoryStack stack = MemoryStack.stackPush()) {
|
|
vorbis = AudioBuffer.ioResourceToByteBuffer(resource, bufferSize);
|
|
IntBuffer error = stack.mallocInt(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);
|
|
|
|
pcm = MemoryUtil.memAllocShort(lengthSamples);
|
|
|
|
pcm.limit(stb_vorbis_get_samples_short_interleaved(decoder, channels, pcm) * channels);
|
|
stb_vorbis_close(decoder);
|
|
|
|
return pcm;
|
|
}
|
|
}
|
|
|
|
public static ByteBuffer ioResourceToByteBuffer(String resource, int bufferSize) throws IOException {
|
|
ByteBuffer buffer;
|
|
|
|
Path path = Paths.get(resource);
|
|
if (Files.isReadable(path)) {
|
|
try (SeekableByteChannel fc = Files.newByteChannel(path)) {
|
|
buffer = BufferUtils.createByteBuffer((int) fc.size() + 1);
|
|
while (fc.read(buffer) != -1) ;
|
|
}
|
|
} else {
|
|
try (
|
|
InputStream source = FileUtils.getAssetFileAsStream(resource);
|
|
ReadableByteChannel rbc = Channels.newChannel(source)
|
|
) {
|
|
buffer = createByteBuffer(bufferSize);
|
|
|
|
while (true) {
|
|
int bytes = rbc.read(buffer);
|
|
if (bytes == -1) {
|
|
break;
|
|
}
|
|
if (buffer.remaining() == 0) {
|
|
int capacity = buffer.capacity();
|
|
ByteBuffer newBuffer = createByteBuffer(capacity * 2);
|
|
for(int i = 0; i < capacity; i++){
|
|
newBuffer.put(buffer.get());
|
|
}
|
|
buffer = newBuffer;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
buffer.flip();
|
|
return buffer;
|
|
}
|
|
|
|
|
|
public int getBufferId() {
|
|
return this.bufferId;
|
|
}
|
|
|
|
public void cleanup() {
|
|
alDeleteBuffers(this.bufferId);
|
|
}
|
|
|
|
}
|