package org.jcodec.player.filters.audio;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import javax.sound.sampled.AudioFormat;
import org.jcodec.codecs.wav.WavHeader;
import org.jcodec.common.NIOUtils;
import org.jcodec.common.model.AudioFrame;
import org.jcodec.common.model.RationalLarge;
import org.jcodec.player.filters.MediaInfo;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* @author The JCodec project
*
*/
public class WavAudioSource implements AudioSource {
private static final int FRAMES_PER_PACKET = 2048;
private WavHeader header;
private FileChannel src;
private int frameSize;
private AudioFormat format;
private long headerSize;
public WavAudioSource(File src) throws IOException {
header = WavHeader.read(src);
headerSize = src.length() - header.dataSize;
this.src = new FileInputStream(src).getChannel();
this.src.position(header.dataOffset);
frameSize = header.fmt.numChannels * (header.fmt.bitsPerSample >> 3);
}
public MediaInfo.AudioInfo getAudioInfo() {
format = new AudioFormat(header.fmt.sampleRate, header.fmt.bitsPerSample, header.fmt.numChannels, true, false);
return new MediaInfo.AudioInfo("pcm", header.fmt.sampleRate, header.dataSize / frameSize, header.dataSize
/ frameSize, "", null, format, header.getChannelLabels());
}
public AudioFrame getFrame(ByteBuffer data) throws IOException {
int toRead = frameSize * FRAMES_PER_PACKET;
if (data.remaining() < toRead)
throw new IllegalArgumentException("Data won't fit");
ByteBuffer dd = data.duplicate();
int read;
if ((read = NIOUtils.read(src, dd, toRead)) != toRead) {
NIOUtils.fill(dd, (byte) 0);
}
long pts = (src.position() - headerSize) / header.fmt.blockAlign;
dd.flip();
return new AudioFrame(dd, format, FRAMES_PER_PACKET, pts, FRAMES_PER_PACKET, header.fmt.sampleRate,
(int) (pts / FRAMES_PER_PACKET));
}
public boolean drySeek(RationalLarge second) throws IOException {
int frameSize = header.fmt.numChannels * (header.fmt.bitsPerSample >> 3);
long off = second.multiplyS((long) header.fmt.sampleRate) * frameSize;
long where = header.dataOffset + off - (off % frameSize);
return where < src.size();
}
public void seek(RationalLarge second) throws IOException {
int frameSize = header.fmt.numChannels * (header.fmt.bitsPerSample >> 3);
long off = second.multiplyS((long) header.fmt.sampleRate) * frameSize;
long where = header.dataOffset + off - (off % frameSize);
src.position(where);
}
public RationalLarge getPos() {
try {
int frameSize = header.fmt.numChannels * (header.fmt.bitsPerSample >> 3);
return new RationalLarge((src.position() - header.dataOffset) / frameSize, header.fmt.sampleRate);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public void close() throws IOException {
this.src.close();
}
}