started implementing AudioEngine

This commit is contained in:
DaniTheSkunk 2022-10-13 05:09:22 +00:00
parent 4486bb67a9
commit 87b3faaa81
2 changed files with 100 additions and 57 deletions

View File

@ -1,5 +1,6 @@
package com.danitheskunk.skunkworks;
import com.danitheskunk.skunkworks.audio.AudioEngine;
import org.lwjgl.openal.AL;
import org.lwjgl.openal.ALC;
@ -14,63 +15,11 @@ import static org.lwjgl.openal.AL10.*;
import static org.lwjgl.openal.ALC10.*;
public class TestSound {
public static void main(String args[]) {
var device = alcOpenDevice((ByteBuffer) null);
if(device == 0) {
throw new RuntimeException("couldn't init openal device");
}
var deviceCaps = ALC.createCapabilities(device);
var context = alcCreateContext(device, (IntBuffer) null);
if(context == 0) {
throw new RuntimeException("couldn't create openal context");
}
alcMakeContextCurrent(context);
AL.createCapabilities(deviceCaps);
var buf = alGenBuffers();
int sampleRate = 44100;
var samples = new short[sampleRate * 2];
for(int i = 0; i < samples.length; ++i) {
var s = Math.sin(2 * Math.PI * 220 * i / (double) sampleRate);
var s2 = Math.sin(2 * Math.PI * 440 * i / (double) sampleRate +
s * 10 * (88200 - i) / 88200);
//s = s * s2 * i / 88200;
s = s2 * (88200 - i) / 88200;
samples[i] = (short) (s * 32760);
}
var bb = ByteBuffer.allocate(samples.length * 2);
for(int i = 0; i < samples.length; ++i) {
bb.putShort(samples[i]);
}
var bytes = bb.array();
AudioInputStream audio;
var format = new AudioFormat(sampleRate, 16, 1, true, true);
audio = new AudioInputStream(
new ByteArrayInputStream(bytes),
format,
bytes.length
);
try {
AudioSystem.write(audio,
AudioFileFormat.Type.WAVE,
new File("meow.wav")
);
} catch(IOException e) {
throw new RuntimeException(e);
}
alBufferData(buf, AL_FORMAT_MONO16, samples, sampleRate);
var src = alGenSources();
alSourcei(src, AL_BUFFER, buf);
alSourcePlay(src);
try {
Thread.sleep(3000);
} catch(InterruptedException e) {
throw new RuntimeException(e);
public static void main(String args[]) throws InterruptedException {
var engine = new AudioEngine(44100, 256, 8);
for(int i = 0; i < 120; ++i) {
engine.refill();
Thread.sleep(20);
}
}
}

View File

@ -0,0 +1,94 @@
package com.danitheskunk.skunkworks.audio;
import org.lwjgl.openal.AL;
import org.lwjgl.openal.ALC;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.Random;
import static org.lwjgl.openal.AL10.*;
import static org.lwjgl.openal.ALC10.*;
public class AudioEngine {
private int sampleRate;
private int bufferSize;
private int bufferCount;
private long device;
private long context;
private int source;
private int tick = 0;
public AudioEngine(int sampleRate, int bufferSize, int bufferCount) {
this.sampleRate = sampleRate;
this.bufferSize = bufferSize;
this.bufferCount = bufferCount;
device = alcOpenDevice((ByteBuffer) null);
if(device == 0) {
throw new RuntimeException("couldn't init openal device");
}
var deviceCaps = ALC.createCapabilities(device);
context = alcCreateContext(device, (IntBuffer) null);
if(context == 0) {
throw new RuntimeException("couldn't create openal context");
}
alcMakeContextCurrent(context);
AL.createCapabilities(deviceCaps);
this.source = alGenSources();
for(int i = 0; i < bufferCount; ++i) {
addEmptyBuffer();
}
alSourcePlay(source);
}
public void close() {
alcDestroyContext(context);
alcCloseDevice(device);
}
private void fillBuffer(int buffer) {
var buf = new double[bufferSize * 2];
for(int i = 0; i < bufferSize; ++i) {
double time = (double) tick / (double) sampleRate;
var s = Math.sin(2 * Math.PI * 440 * time);
buf[i * 2] = s;
buf[i * 2 + 1] = s;
++tick;
}
var shortBuffer = new short[bufferSize * 2];
for(int i = 0; i < bufferSize * 2; ++i) {
shortBuffer[i] = (short) (buf[i] * 32760);
}
alBufferData(buffer, AL_FORMAT_STEREO16, shortBuffer, sampleRate);
}
private void addEmptyBuffer() {
var buf = alGenBuffers();
fillBuffer(buf);
alSourceQueueBuffers(source, buf);
}
public void refill() {
var bufCount = alGetSourcei(source, AL_BUFFERS_PROCESSED);
var bufs = new int[bufCount];
alSourceUnqueueBuffers(source, bufs);
for(int i = 0; i < bufCount; ++i) {
fillBuffer(bufs[i]);
alSourceQueueBuffers(source, bufs[i]);
}
if(alGetSourcei(source, AL_SOURCE_STATE) != AL_PLAYING) {
System.out.println("buffer underrun, addng buffer");
addEmptyBuffer();
alSourcePlay(source);
}
}
public int getSampleRate() {
return sampleRate;
}
}