Initial commit.
This commit is contained in:
114
src/dk/itu/mario/engine/sonar/sample/SampleLoader.java
Normal file
114
src/dk/itu/mario/engine/sonar/sample/SampleLoader.java
Normal file
@@ -0,0 +1,114 @@
|
||||
package dk.itu.mario.engine.sonar.sample;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
import javax.sound.sampled.AudioInputStream;
|
||||
import javax.sound.sampled.AudioSystem;
|
||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||
|
||||
public class SampleLoader
|
||||
{
|
||||
/**
|
||||
* Loads a sample from an url
|
||||
*/
|
||||
public static SonarSample loadSample(String resourceName) throws UnsupportedAudioFileException, IOException
|
||||
{
|
||||
// Hack to prevent "mark/reset not supported" on some systems
|
||||
InputStream in=SampleLoader.class.getResourceAsStream(resourceName);
|
||||
byte[] d = rip(in);
|
||||
AudioInputStream ais = AudioSystem.getAudioInputStream(new ByteArrayInputStream(d));
|
||||
return buildSample(rip(ais), ais.getFormat());
|
||||
}
|
||||
|
||||
/**
|
||||
* Rips the entire contents of an inputstream into a byte array
|
||||
*/
|
||||
private static byte[] rip(InputStream in) throws IOException
|
||||
{
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
byte[] b = new byte[4096];
|
||||
|
||||
int read = 0;
|
||||
while ((read = in.read(b)) > 0)
|
||||
{
|
||||
bos.write(b, 0, read);
|
||||
}
|
||||
|
||||
bos.close();
|
||||
return bos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorganizes audio sample data into the intenal sonar format
|
||||
*/
|
||||
private static SonarSample buildSample(byte[] b, AudioFormat af) throws UnsupportedAudioFileException
|
||||
{
|
||||
// Rip audioformat data
|
||||
int channels = af.getChannels();
|
||||
int sampleSize = af.getSampleSizeInBits();
|
||||
float rate = af.getFrameRate();
|
||||
boolean signed = af.getEncoding() == AudioFormat.Encoding.PCM_SIGNED;
|
||||
|
||||
// Sanity checking
|
||||
if (channels != 1) throw new UnsupportedAudioFileException("Only mono samples are supported");
|
||||
if (!(sampleSize == 8 || sampleSize == 16 || sampleSize == 32)) throw new UnsupportedAudioFileException("Unsupported sample size");
|
||||
if (!(af.getEncoding() == AudioFormat.Encoding.PCM_UNSIGNED || af.getEncoding() == AudioFormat.Encoding.PCM_SIGNED)) throw new UnsupportedAudioFileException("Unsupported encoding");
|
||||
|
||||
// Wrap the data into a bytebuffer, and set up the byte order
|
||||
ByteBuffer bb = ByteBuffer.wrap(b);
|
||||
bb.order(af.isBigEndian() ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
int s = b.length / (sampleSize / 8);
|
||||
float[] buf = new float[s];
|
||||
// Six different cases for reordering the data. Can this be improved without slowing it down?
|
||||
if (sampleSize == 8)
|
||||
{
|
||||
if (signed)
|
||||
{
|
||||
for (int i = 0; i < s; i++)
|
||||
buf[i] = bb.get() / (float)0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < s; i++)
|
||||
buf[i] = ((bb.get()&0xFF)-0x80) / (float)0x80;
|
||||
}
|
||||
}
|
||||
else if (sampleSize == 16)
|
||||
{
|
||||
if (signed)
|
||||
{
|
||||
for (int i = 0; i < s; i++)
|
||||
buf[i] = bb.getShort() / (float)0x8000;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < s; i++)
|
||||
buf[i] = ((bb.getShort()&0xFFFF)-0x8000) / (float)0x8000;
|
||||
}
|
||||
}
|
||||
else if (sampleSize == 32)
|
||||
{
|
||||
if (signed)
|
||||
{
|
||||
for (int i = 0; i < s; i++)
|
||||
buf[i] = bb.getInt() / (float)0x80000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nasty.. check this.
|
||||
for (int i = 0; i < s; i++)
|
||||
buf[i] = ((bb.getInt()&0xFFFFFFFFl)-0x80000000l) / (float)0x80000000;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the completed sample
|
||||
return new SonarSample(buf, rate);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user