Compare commits
No commits in common. "f52d6e66e3f06b1f02db3b9d1a4a521b7e197b6e" and "a05892e677ed31b851a458bf5bbf4eb96d08fbc2" have entirely different histories.
f52d6e66e3
...
a05892e677
|
@ -3,7 +3,6 @@ package com.danitheskunk.skunkworks;
|
||||||
import com.danitheskunk.skunkworks.audio.AudioEngine;
|
import com.danitheskunk.skunkworks.audio.AudioEngine;
|
||||||
import com.danitheskunk.skunkworks.audio.nodes.Mixer;
|
import com.danitheskunk.skunkworks.audio.nodes.Mixer;
|
||||||
import com.danitheskunk.skunkworks.audio.nodes.Node;
|
import com.danitheskunk.skunkworks.audio.nodes.Node;
|
||||||
import com.danitheskunk.skunkworks.audio.nodes.SamplePlayer;
|
|
||||||
import com.danitheskunk.skunkworks.audio.nodes.Sine;
|
import com.danitheskunk.skunkworks.audio.nodes.Sine;
|
||||||
import org.lwjgl.openal.AL;
|
import org.lwjgl.openal.AL;
|
||||||
import org.lwjgl.openal.ALC;
|
import org.lwjgl.openal.ALC;
|
||||||
|
@ -20,44 +19,18 @@ import static org.lwjgl.openal.ALC10.*;
|
||||||
|
|
||||||
public class TestSound {
|
public class TestSound {
|
||||||
public static void main(String args[]) throws InterruptedException {
|
public static void main(String args[]) throws InterruptedException {
|
||||||
var engine = new AudioEngine(44100, 256, 16);
|
var engine = new AudioEngine(44100, 256, 8);
|
||||||
var mix = new Mixer(engine, 4);
|
var mix = new Mixer(engine, 4);
|
||||||
var sin1 = new Sine(engine, 440);
|
var sin1 = new Sine(engine, 440);
|
||||||
var sin2 = new Sine(engine, 659.25);
|
var sin2 = new Sine(engine, 659.25);
|
||||||
var sin3 = new Sine(engine, 523.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);
|
engine.setNode(mix);
|
||||||
//Node.connect(sin1, 0, mix, 0);
|
for(int i = 0; i < 120; ++i) {
|
||||||
//Node.connect(sin3, 0, mix, 1);
|
|
||||||
//Node.connect(sin2, 0, mix, 2);
|
|
||||||
|
|
||||||
var loop = engine.loadSample("C:\\Users\\dani\\Downloads\\AKWF" +
|
|
||||||
"\\AKWF_bw_sin\\AKWF_sin_0001.wav");
|
|
||||||
var sample = engine.loadSample("C:\\Users\\dani\\Downloads\\Untitled" +
|
|
||||||
".wav");
|
|
||||||
var kick = engine.loadSample("C:\\samples\\drum\\legowelt\\BASEDRUMS" +
|
|
||||||
"\\Legowelt Basedrum 007.wav");
|
|
||||||
var player = new SamplePlayer(engine);
|
|
||||||
Node.connect(player, 0, mix, 0);
|
|
||||||
|
|
||||||
player.play(loop, true);
|
|
||||||
for(int j = 0; j < 10; ++j) {
|
|
||||||
//player.play(kick);
|
|
||||||
for(int i = 0; i < 50; ++i) {
|
|
||||||
engine.refill();
|
|
||||||
Thread.sleep(20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
for(int i = 0; i < 60; ++i) {
|
|
||||||
engine.refill();
|
engine.refill();
|
||||||
Thread.sleep(20);
|
Thread.sleep(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < 60; ++i) {
|
|
||||||
engine.refill();
|
|
||||||
Thread.sleep(20);
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,6 @@ import com.danitheskunk.skunkworks.audio.nodes.Node;
|
||||||
import org.lwjgl.openal.AL;
|
import org.lwjgl.openal.AL;
|
||||||
import org.lwjgl.openal.ALC;
|
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.ByteBuffer;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
@ -104,54 +97,4 @@ public class AudioEngine {
|
||||||
public void setNode(Node node) {
|
public void setNode(Node node) {
|
||||||
this.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] & 0xFF) +
|
|
||||||
(bytes[i * 2 * channels + 1] & 0xFF) * 256;
|
|
||||||
if(channels == 2) {
|
|
||||||
var r = (bytes[i * 2 * channels + 2] & 0xFF) +
|
|
||||||
(bytes[i * 2 * channels + 3] & 0xFF) * 256;
|
|
||||||
sample.setSamplei(i, (short) l, (short) r);
|
|
||||||
} else {
|
|
||||||
sample.setSamplei(i, (short) l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sample;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,9 @@ public interface ISample {
|
||||||
|
|
||||||
double getSampleRight(int pos);
|
double getSampleRight(int pos);
|
||||||
|
|
||||||
void setSamplei(int pos, short left);
|
void setSample(int pos, int left);
|
||||||
|
|
||||||
void setSamplei(int pos, short left, short right);
|
void setSample(int pos, int left, int right);
|
||||||
|
|
||||||
boolean isStereo();
|
void isStereo();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,12 @@
|
||||||
package com.danitheskunk.skunkworks.audio;
|
package com.danitheskunk.skunkworks.audio;
|
||||||
|
|
||||||
public class Samplei implements ISample {
|
public class Samplei implements ISample {
|
||||||
private short[] left;
|
private double[] left;
|
||||||
private short[] right;
|
private double[] right;
|
||||||
|
|
||||||
public Samplei(int length, boolean stereo) {
|
public Samplei(int length, boolean stereo) {
|
||||||
left = new short[length];
|
left = new double[length];
|
||||||
right = stereo ? new short[length] : left;
|
right = stereo ? new double[length] : left;
|
||||||
}
|
|
||||||
|
|
||||||
public Samplei(short[] left, short[] right) {
|
|
||||||
this.left = left;
|
|
||||||
this.right = right == null ? left : right;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -21,27 +16,27 @@ public class Samplei implements ISample {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getSampleLeft(int pos) {
|
public double getSampleLeft(int pos) {
|
||||||
return (double) left[pos] / 32768.0;
|
return left[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getSampleRight(int pos) {
|
public double getSampleRight(int pos) {
|
||||||
return (double) right[pos] / 32768.0;
|
return right[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSamplei(int pos, short left) {
|
public void setSample(int pos, int left) {
|
||||||
this.left[pos] = left;
|
this.left[pos] = left;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSamplei(int pos, short left, short right) {
|
public void setSample(int pos, int left, int right) {
|
||||||
this.left[pos] = left;
|
this.left[pos] = left;
|
||||||
this.right[pos] = right;
|
this.right[pos] = right;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isStereo() {
|
public void isStereo() {
|
||||||
return left != right;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
package com.danitheskunk.skunkworks.audio.nodes;
|
|
||||||
|
|
||||||
import com.danitheskunk.skunkworks.audio.AudioBuffer;
|
|
||||||
import com.danitheskunk.skunkworks.audio.AudioEngine;
|
|
||||||
import com.danitheskunk.skunkworks.audio.ISample;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class SamplePlayer extends Node {
|
|
||||||
private List<PlayingSample> samples;
|
|
||||||
|
|
||||||
public SamplePlayer(AudioEngine engine) {
|
|
||||||
super(engine, 0, 1);
|
|
||||||
samples = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AudioBuffer getBuffer(int slot) {
|
|
||||||
var bufsize = getEngine().getBufferSize();
|
|
||||||
var buf = new AudioBuffer(bufsize);
|
|
||||||
var toRemove = new ArrayList<PlayingSample>();
|
|
||||||
for(int i = 0; i < bufsize; ++i) {
|
|
||||||
double l = 0;
|
|
||||||
double r = 0;
|
|
||||||
for(var sample : samples) {
|
|
||||||
if(sample.loop) {
|
|
||||||
sample.tick %= sample.sample.getLength();
|
|
||||||
}
|
|
||||||
if(sample.tick < sample.sample.getLength()) {
|
|
||||||
l += sample.sample.getSampleLeft(sample.tick);
|
|
||||||
r += sample.sample.getSampleRight(sample.tick);
|
|
||||||
++sample.tick;
|
|
||||||
} else {
|
|
||||||
toRemove.add(sample);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(var sample : toRemove) {
|
|
||||||
samples.remove(sample);
|
|
||||||
}
|
|
||||||
toRemove.clear();
|
|
||||||
buf.setSample(i, l, r);
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void play(ISample sample) {
|
|
||||||
play(sample, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void play(ISample sample, boolean looping) {
|
|
||||||
var s = new PlayingSample();
|
|
||||||
s.sample = sample;
|
|
||||||
s.loop = looping;
|
|
||||||
s.tick = 0;
|
|
||||||
samples.add(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class PlayingSample {
|
|
||||||
ISample sample;
|
|
||||||
int tick;
|
|
||||||
boolean loop;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue