diff --git a/com/danitheskunk/skunkworks/TestSound.java b/com/danitheskunk/skunkworks/TestSound.java index 4d0e51e..a310c81 100644 --- a/com/danitheskunk/skunkworks/TestSound.java +++ b/com/danitheskunk/skunkworks/TestSound.java @@ -19,18 +19,34 @@ import static org.lwjgl.openal.ALC10.*; public class TestSound { public static void main(String args[]) throws InterruptedException { - var engine = new AudioEngine(44100, 256, 8); + var engine = new AudioEngine(44100, 256, 16); var mix = new Mixer(engine, 4); var sin1 = new Sine(engine, 440); var sin2 = new Sine(engine, 659.25); var sin3 = new Sine(engine, 523.25); - Node.connect(sin1, 0, mix, 0); - Node.connect(sin2, 0, mix, 1); - Node.connect(sin3, 0, mix, 2); engine.setNode(mix); - for(int i = 0; i < 120; ++i) { + Node.connect(sin1, 0, mix, 0); + Node.connect(sin3, 0, mix, 1); + Node.connect(sin2, 0, mix, 2); + + var sample = engine.loadSample("C:\\Users\\dani\\Downloads\\Untitled" + + ".wav"); + /* + for(int i = 0; i < 60; ++i) { engine.refill(); Thread.sleep(20); } + + for(int i = 0; i < 60; ++i) { + engine.refill(); + Thread.sleep(20); + } + + for(int i = 0; i < 60; ++i) { + engine.refill(); + Thread.sleep(20); + } + + */ } } diff --git a/com/danitheskunk/skunkworks/audio/AudioEngine.java b/com/danitheskunk/skunkworks/audio/AudioEngine.java index fa525a1..7d72a7f 100644 --- a/com/danitheskunk/skunkworks/audio/AudioEngine.java +++ b/com/danitheskunk/skunkworks/audio/AudioEngine.java @@ -4,6 +4,13 @@ import com.danitheskunk.skunkworks.audio.nodes.Node; import org.lwjgl.openal.AL; import org.lwjgl.openal.ALC; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.IntBuffer; @@ -97,4 +104,53 @@ public class AudioEngine { public void setNode(Node node) { this.node = node; } + + public ISample loadSample(String path) { + //todo: clean up this code + FileInputStream file = null; + try { + file = new FileInputStream(path); + } catch(FileNotFoundException e) { + throw new RuntimeException(e); + } + var bufFile = new BufferedInputStream(file); + AudioInputStream audio; + byte[] bytes; + try { + audio = AudioSystem.getAudioInputStream(bufFile); + } catch(UnsupportedAudioFileException | IOException e) { + throw new RuntimeException(e); + } + var format = audio.getFormat(); + int channels = format.getChannels(); + if(channels <= 0 || channels > 2) { + throw new RuntimeException("can only handle mono or stereo " + + "samples"); + } + int bytesPerFrame = format.getFrameSize(); + if(bytesPerFrame / channels != 2) { + throw new RuntimeException("currently only 16-bit audio samples " + + "supported"); + } + + try { + bytes = audio.readAllBytes(); + audio.close(); + file.close(); + } catch(IOException e) { + throw new RuntimeException(e); + } + var sample = new Samplei(bytes.length / 2 / channels, channels == 2); + for(int i = 0; i < bytes.length / 2 / channels; ++i) { + var l = bytes[i * 2 * channels] + bytes[i * 2 * channels + 1] << 8; + if(channels == 2) { + var r = bytes[i * 2 * channels + 2] + + bytes[i * 2 * channels + 3] << 8; + sample.setSamplei(i, (short) l, (short) r); + } else { + sample.setSamplei(i, (short) l); + } + } + return sample; + } } diff --git a/com/danitheskunk/skunkworks/audio/ISample.java b/com/danitheskunk/skunkworks/audio/ISample.java index e9f4b6e..7de4628 100644 --- a/com/danitheskunk/skunkworks/audio/ISample.java +++ b/com/danitheskunk/skunkworks/audio/ISample.java @@ -8,9 +8,9 @@ public interface ISample { double getSampleRight(int pos); - void setSample(int pos, int left); + void setSamplei(int pos, short left); - void setSample(int pos, int left, int right); + void setSamplei(int pos, short left, short right); - void isStereo(); + boolean isStereo(); } diff --git a/com/danitheskunk/skunkworks/audio/Samplei.java b/com/danitheskunk/skunkworks/audio/Samplei.java index 84db8ce..6c0ecd0 100644 --- a/com/danitheskunk/skunkworks/audio/Samplei.java +++ b/com/danitheskunk/skunkworks/audio/Samplei.java @@ -1,12 +1,17 @@ package com.danitheskunk.skunkworks.audio; public class Samplei implements ISample { - private double[] left; - private double[] right; + private short[] left; + private short[] right; public Samplei(int length, boolean stereo) { - left = new double[length]; - right = stereo ? new double[length] : left; + left = new short[length]; + right = stereo ? new short[length] : left; + } + + public Samplei(short[] left, short[] right) { + this.left = left; + this.right = right == null ? left : right; } @Override @@ -16,27 +21,27 @@ public class Samplei implements ISample { @Override public double getSampleLeft(int pos) { - return left[pos]; + return (double) left[pos] / 32768.0; } @Override public double getSampleRight(int pos) { - return right[pos]; + return (double) right[pos] / 32768.0; } @Override - public void setSample(int pos, int left) { + public void setSamplei(int pos, short left) { this.left[pos] = left; } @Override - public void setSample(int pos, int left, int right) { + public void setSamplei(int pos, short left, short right) { this.left[pos] = left; this.right[pos] = right; } @Override - public void isStereo() { - + public boolean isStereo() { + return left != right; } }