package org.jcodec.player.filters.audio;
import java.io.IOException;
import java.nio.ByteBuffer;
import javax.sound.sampled.AudioFormat;
import org.jcodec.common.model.AudioFrame;
import org.jcodec.common.model.ChannelLabel;
import org.jcodec.common.model.RationalLarge;
import org.jcodec.player.filters.MediaInfo;
import org.jcodec.player.filters.MediaInfo.AudioInfo;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* @author The JCodec project
*
*/
public class ChannelSelector implements AudioSource {
private AudioSource src;
private AudioFormat srcFormat;
private ByteBuffer buffer;
private AudioFormat newFormat;
private int pattern;
private int channels;
public ChannelSelector(AudioSource src, int pattern) throws IOException {
this.src = src;
this.pattern = pattern;
AudioInfo audioInfo = src.getAudioInfo();
this.srcFormat = audioInfo.getFormat();
buffer = ByteBuffer.allocate(96000 * 2 * srcFormat.getFrameSize());
channels = 0;
for (int i = 0; i < 32; i++) {
channels += pattern & 0x1;
pattern >>= 1;
}
newFormat = new AudioFormat(srcFormat.getSampleRate(), srcFormat.getSampleSizeInBits(), channels, true,
srcFormat.isBigEndian());
}
public MediaInfo.AudioInfo getAudioInfo() throws IOException {
AudioInfo audioInfo = src.getAudioInfo();
ChannelLabel[] srcLabels = audioInfo.getLabels();
ChannelLabel[] resultLabels = new ChannelLabel[channels];
for (int i = 0, lbl = 0; i < 32; i++) {
if ((pattern & 0x1) == 1) {
resultLabels[lbl++] = srcLabels[i];
}
pattern >>= 1;
}
return new AudioInfo(audioInfo.getFourcc(), audioInfo.getTimescale(), audioInfo.getDuration(),
audioInfo.getNFrames(), audioInfo.getName(), null, newFormat, resultLabels);
}
public AudioFrame getFrame(ByteBuffer result) throws IOException {
AudioFrame from = src.getFrame(buffer);
if (from == null)
return null;
ByteBuffer dd = result.duplicate();
ByteBuffer data = from.getData();
int channels = srcFormat.getChannels(), sampleSize = srcFormat.getSampleSizeInBits() >> 3;
while(data.hasRemaining()) {
for (int z = 0; z < channels; z++) {
if (((pattern >> z) & 0x1) == 1) {
dd.put(buffer.get());
if (sampleSize > 1)
dd.put(buffer.get());
if (sampleSize > 2)
dd.put(buffer.get());
} else {
buffer.position(buffer.position() + sampleSize);
}
}
}
dd.flip();
return new AudioFrame(dd, newFormat, from.getNFrames(), from.getPts(),
from.getDuration(), from.getTimescale(), from.getFrameNo());
}
public boolean drySeek(RationalLarge second) throws IOException {
return src.drySeek(second);
}
public void seek(RationalLarge second) throws IOException {
src.seek(second);
}
@Override
public void close() throws IOException {
src.close();
}
}