/*
* Info.java
*
* This file is part of Tritonus: http://www.tritonus.org/
*/
/*
* Copyright (c) 2000 - 2005 by Matthias Pfisterer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
|<--- this code is formatted to fit into 80 columns --->|
*/
package org.tritonus.lowlevel.pvorbis;
import org.tritonus.lowlevel.pogg.Ogg;
import org.tritonus.lowlevel.pogg.Packet;
import org.tritonus.lowlevel.pogg.Buffer;
import org.tritonus.share.TDebug;
/** Wrapper for vorbis_info.
*/
@SuppressWarnings("unused")
public class Info
implements VorbisConstants
{
static
{
Ogg.loadNativeLibrary();
if (TDebug.TraceVorbisNative)
{
setTrace(true);
}
}
/**
* Holds the pointer to vorbis_info
* for the native code.
* This must be long to be 64bit-clean.
*/
private long m_lNativeHandle;
private int m_nVersion;
private int m_nChannels;
private int m_nRate;
private int m_nBitrateUpper;
private int m_nBitrateNominal;
private int m_nBitrateLower;
public Info()
{
if (TDebug.TraceVorbisNative) { TDebug.out("Info.<init>(): begin"); }
int nReturn = malloc();
if (nReturn < 0)
{
throw new RuntimeException("malloc of vorbis_info failed");
}
if (TDebug.TraceVorbisNative) { TDebug.out("Info.<init>(): end"); }
}
@Override
public void finalize()
{
// TODO: call free()
// call super.finalize() first or last?
// and introduce a flag if free() has already been called?
}
private native int malloc();
public native void free();
/** Calls vorbis_info_init().
*/
public void init()
{
m_nVersion = 0;
m_nChannels = 0;
m_nRate = 0;
m_nBitrateUpper = 0;
m_nBitrateNominal = 0;
m_nBitrateLower = 0;
// TODO: allocate codec_setup_info
init_native();
}
/** Calls vorbis_info_init().
*/
public native void init_native();
/** Calls vorbis_info_clear().
*/
public void clear()
{
// TODO: lots of stuff in codec_setup_info
m_nVersion = 0;
m_nChannels = 0;
m_nRate = 0;
m_nBitrateUpper = 0;
m_nBitrateNominal = 0;
m_nBitrateLower = 0;
clear_native();
}
/** Calls vorbis_info_clear().
*/
public native void clear_native();
public int getVersion()
{
return getVersion_native();
}
private native int getVersion_native();
public void setValues(int nVersion,
int nChannels,
int nRate,
int nBitrateUpper,
int nBitrateNominal,
int nBitrateLower,
int nBlocksize0,
int nBlocksize1)
{
m_nVersion = nVersion;
m_nChannels = nChannels;
m_nRate = nRate;
m_nBitrateUpper = nBitrateUpper;
m_nBitrateNominal = nBitrateNominal;
m_nBitrateLower = nBitrateLower;
setValues_native(nVersion,
nChannels,
nRate,
nBitrateUpper,
nBitrateNominal,
nBitrateLower,
nBlocksize0,
nBlocksize1);
}
private native void setValues_native(int nVersion,
int nChannels,
int nRate,
int nBitrateUpper,
int nBitrateNominal,
int nBitrateLower,
int nBlocksize0,
int nBlocksize1);
public int getBlocksize0()
{
return getBlocksize_native(0);
}
public int getBlocksize1()
{
return getBlocksize_native(1);
}
/**
@param nIndex which blocksize is desired. Has to be either 0 or
1.
*/
private native int getBlocksize_native(int nIndex);
/** Accesses channels.
*/
public int getChannels()
{
// return m_nChannels;
return getChannels_native();
}
/** Accesses channels.
*/
private native int getChannels_native();
/** Accesses rate.
*/
public int getRate()
{
//return m_nRate;
return getRate_native();
}
/** Accesses rate.
*/
private native int getRate_native();
public int getBitrateUpper()
{
//return m_nBitrateUpper;
return getBitrateUpper_native();
}
private native int getBitrateUpper_native();
public int getBitrateNominal()
{
//return m_nBitrateNominal;
return getBitrateNominal_native();
}
private native int getBitrateNominal_native();
public int getBitrateLower()
{
//return m_nBitrateLower;
return getBitrateLower_native();
}
private native int getBitrateLower_native();
/** Calls vorbis_encode_init().
*/
public int encodeInit(
int nChannels,
int nRate,
int nMaxBitrate,
int nNominalBitrate,
int nMinBitrate)
{
return encodeInit_native(
nChannels,
nRate,
nMaxBitrate,
nNominalBitrate,
nMinBitrate);
}
/** Calls vorbis_encode_init().
*/
private native int encodeInit_native(
int nChannels,
int nRate,
int nMaxBitrate,
int nNominalBitrate,
int nMinBitrate);
/** Calls vorbis_encode_init_vbr().
*/
public int encodeInitVBR(
int nChannels,
int nRate,
float fQuality)
{
return encodeInitVBR_native(
nChannels,
nRate,
fQuality);
}
/** Calls vorbis_encode_init_vbr().
*/
private native int encodeInitVBR_native(
int nChannels,
int nRate,
float fQuality);
/** Calls vorbis_synthesis_headerin().
*/
public int headerIn(Comment comment, Packet packet)
{
if(packet == null)
{
return OV_EBADHEADER;
}
Buffer buffer = new Buffer();
byte[] abData = packet.getData();
//Buffer.outBuffer(abData);
buffer.readInit(abData, abData.length);
/* Which of the three types of header is this? */
/* Also verify header-ness, vorbis */
int packtype = buffer.read(8);
//TDebug.out("packtype: " + packtype);
String s = buffer.readString(6);
if(! "vorbis".equals(s))
{
/* not a vorbis header */
buffer.free();
return OV_ENOTVORBIS;
}
int r;
switch (packtype)
{
case 0x01: /* least significant *bit* is read first */
if(! packet.isBos())
{
/* Not the initial packet */
buffer.free();
return OV_EBADHEADER;
}
if (getRate() != 0)
{
/* previously initialized info header */
buffer.free();
return OV_EBADHEADER;
}
r = unpack(buffer);
buffer.free();
return r;
case 0x03: /* least significant *bit* is read first */
if (getRate() == 0)
{
/* um... we didn't get the initial header */
buffer.free();
return OV_EBADHEADER;
}
r = comment.unpack(buffer);
buffer.free();
return r;
case 0x05: /* least significant *bit* is read first */
if (getRate() == 0 || comment.getVendor() == null)
{
/* um... we didn;t get the initial header or comments yet */
buffer.free();
return OV_EBADHEADER;
}
r = headerIn_native(buffer, packtype, packet);
buffer.free();
return r;
//return(_vorbis_unpack_books(vi,&buffer));
default:
/* Not a valid vorbis header type */
buffer.free();
return OV_EBADHEADER;
}
}
/** Calls vorbis_synthesis_headerin().
*/
private native int headerIn_native(Buffer buffer, int nPacketType,
Packet packet);
public int pack(Buffer buffer)
{
/* preamble */
buffer.write(0x01, 8);
buffer.write("vorbis");
buffer.write(0x00, 32); // version
buffer.write(getChannels(), 8);
buffer.write(getRate(), 32);
buffer.write(getBitrateUpper(), 32);
buffer.write(getBitrateNominal(), 32);
buffer.write(getBitrateLower(), 32);
buffer.write(ilog2(getBlocksize0()), 4);
buffer.write(ilog2(getBlocksize1()), 4);
/* end of packet */
buffer.write(1, 1);
return 0;
}
public int unpack(Buffer buffer)
{
int nVersion = buffer.read(32);
if (nVersion != 0)
{
return OV_EVERSION;
}
int nChannels = buffer.read(8);
int nRate = buffer.read(32);
int nBitrateUpper = buffer.read(32);
int nBitrateNominal = buffer.read(32);
int nBitrateLower = buffer.read(32);
int nBlocksize0 = 1 << buffer.read(4);
int nBlocksize1 = 1 << buffer.read(4);
if (nChannels < 1 || nRate < 1 ||
nBlocksize0 < 8 || nBlocksize1 < nBlocksize0)
{
clear();
return OV_EBADHEADER;
}
/* EOP check */
if (buffer.read(1) != 1)
{
clear();
return OV_EBADHEADER;
}
setValues(nVersion,
nChannels,
nRate,
nBitrateUpper,
nBitrateNominal,
nBitrateLower,
nBlocksize0,
nBlocksize1);
// everything ok.
return 0;
}
private static native void setTrace(boolean bTrace);
private static int ilog2(int v)
{
int ret = 0;
if (v != 0)
--v;
while (v != 0)
{
ret++;
v >>= 1;
}
return ret;
}
}
/*** Info.java ***/