package sound;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import org.lwjgl.openal.AL10;
import exception.IncorrectFormatException;
public class WaveLoader extends SoundLoader
{
private boolean loaded_correctly = false;
private int sample_rate;
private int number_of_channels;
private int byte_rate;
private int block_align;
private int sample_size;
private int format;
private final IntBuffer RIFF = IntBuffer.wrap(new int[]{0x52, 0x49, 0x46, 0x46});
private final IntBuffer WAVE = IntBuffer.wrap(new int[]{0x57, 0x41, 0x56, 0x45});
private final IntBuffer FMT_ = IntBuffer.wrap(new int[]{0x66, 0x6D, 0x74, 0x20});
private final IntBuffer DATA = IntBuffer.wrap(new int[]{0x64, 0x61, 0x74, 0x61});
private FileInputStream dir;
public WaveLoader(String path)
{
path = WaveLoader.class.getResource(path).getPath();
File potential_wav = new File(path);
try
{
dir = new FileInputStream(path);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
return;
}
try
{
//Read in the first 4 bytes. These bytes should spell RIFF.
byte[] buffer = new byte[4];
dir.read(buffer);
//Unsign the bytes and put it into a IntBuffer for comparison to the IntBuffer RIFF
IntBuffer is_riff = IntBuffer.wrap(this.unsign_byte(buffer));
if(RIFF.compareTo(is_riff) != 0)
{
new IncorrectFormatException(IncorrectFormatException.NOT_A_RIFF);
return;
}
//The next 4 bytes describe the total filesize minus 8.
dir.read(buffer);
int length = turn_byte_buffer_into_int(buffer);
if(length+8 != potential_wav.length())
{
new IncorrectFormatException(IncorrectFormatException.INCORRECT_FILESIZE);
return;
}
//The next 4 bytes should read WAVE
dir.read(buffer);
IntBuffer is_wave = IntBuffer.wrap(this.unsign_byte(buffer));
if(WAVE.compareTo(is_wave) != 0)
{
new IncorrectFormatException(IncorrectFormatException.NOT_A_WAVE);
return;
}
//As the format is WAVE, the next 4 bytes should read "fmt ". Includes the space.
dir.read(buffer);
IntBuffer is_fmt = IntBuffer.wrap(this.unsign_byte(buffer));
if(FMT_.compareTo(is_fmt) != 0)
{
new IncorrectFormatException(IncorrectFormatException.DOES_NOT_HAVE_FMT);
return;
}
//Next we read the subchunk size. As we are reading an uncompressed .wav, it should be 16.
dir.read(buffer);
length = turn_byte_buffer_into_int(buffer);
if(length != 16)
{
new IncorrectFormatException(IncorrectFormatException.SUBCHUNK_SIZE_INCORRECT);
return;
}
clear(buffer);
//Next we read in the AudioFormat. This must equal 1 for PCM
dir.read(buffer, 0, 2);
length = turn_byte_buffer_into_int(buffer);
if(length != 1)
{
new IncorrectFormatException(IncorrectFormatException.COMPRESSION_DETECTED);
return;
}
//Now we need to read in the number of channels
clear(buffer);
dir.read(buffer, 0, 2);
number_of_channels = turn_byte_buffer_into_int(buffer);
//Next is the sample rate;
dir.read(buffer);
sample_rate = turn_byte_buffer_into_int(buffer);
//Now the byte rate
dir.read(buffer);
byte_rate = turn_byte_buffer_into_int(buffer);
//The block align size (Size of one sample with all channels.
clear(buffer);
dir.read(buffer, 0, 2);
block_align = turn_byte_buffer_into_int(buffer);
//Read in the bits per sample;
clear(buffer);
dir.read(buffer, 0, 2);
sample_size = turn_byte_buffer_into_int(buffer);
//The next thing should be the value data.
dir.read(buffer);
IntBuffer is_data = IntBuffer.wrap(this.unsign_byte(buffer));
if(DATA.compareTo(is_data) != 0)
{
new IncorrectFormatException(IncorrectFormatException.DATA_NOT_FOUND);
return;
}
//remainder filesize. Don't care about it.
dir.read(buffer);
}
catch(IOException e)
{
e.printStackTrace();
}
if(sample_size == 8)
{
if(number_of_channels == 1)
{
format = AL10.AL_FORMAT_MONO8;
}
else if(number_of_channels == 2)
{
format = AL10.AL_FORMAT_STEREO8;
}
else
{
new IncorrectFormatException(IncorrectFormatException.UNSUPPORTED_CHANNEL_NUMBER);
return;
}
}
else if(sample_size == 16)
{
if(number_of_channels == 1)
{
format = AL10.AL_FORMAT_MONO16;
}
else if(number_of_channels == 2)
{
format = AL10.AL_FORMAT_STEREO16;
}
else
{
new IncorrectFormatException(IncorrectFormatException.UNSUPPORTED_CHANNEL_NUMBER);
return;
}
}
else
{
new IncorrectFormatException(IncorrectFormatException.UNSUPPORTED_SAMPLE_SIZE);
return;
}
loaded_correctly = true;
}
@Override
public int read(ByteBuffer buffer)
{
buffer.clear();
byte[] buf = new byte[buffer.capacity()];
int amount_read = -1;
try
{
amount_read = dir.read(buf);
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
buffer.put(buf);
return amount_read;
}
public int getFormat()
{
return format;
}
public int getSampleRate()
{
return sample_rate;
}
public boolean readCorrectly()
{
return loaded_correctly;
}
private int turn_byte_buffer_into_int(byte[] buf)
{
ByteBuffer bb = ByteBuffer.allocate(4);
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.put(buf);
bb.rewind();
return bb.getInt();
}
private void clear(byte[] buffer)
{
for(int i = 0; i < buffer.length; i++)
buffer[i] = 0;
}
private int[] unsign_byte(byte[] b)
{
int[] rv = new int[b.length];
for(int i = 0; i < rv.length; i++)
{
rv[i] = 0xFF & b[i];
}
return rv;
}
}