org.tritonus.lowlevel.pvorbis.StaticCodebook Maven / Gradle / Ivy
The newest version!
/*
* StaticCodebook.java
*
* This file is part of Tritonus: http://www.tritonus.org/
*/
/*
* Copyright (c) 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.Buffer;
import org.tritonus.share.TDebug;
/** Holds the static part of a codebook.
*/
@SuppressWarnings("unused")
public class StaticCodebook
implements VorbisConstants
{
private int m_nDimensions;
private int m_nEntries;
private int[] m_anLengths;
private int m_nMaptype;
private int m_nQMin;
private int m_nQDelta;
private int m_nQQuant;
private int m_nQSequencep;
private int[] m_anQuants;
public StaticCodebook()
{
if (TDebug.TraceVorbisNative) { TDebug.out("StaticCodebook.(): begin"); }
if (TDebug.TraceVorbisNative) { TDebug.out("StaticCodebook.(): end"); }
}
/**
*/
public void clear()
{
m_nDimensions = 0;
m_nEntries = 0;
m_anLengths = null;
m_nMaptype = 0;
m_nQMin = 0;
m_nQDelta = 0;
m_nQQuant = 0;
m_nQSequencep = 0;
m_anQuants = null;
}
/** Initializes the comment object.
Sets the vendor string to null and
removes all comments.
*/
public void init()
{
// m_vendor = null;
// m_comments = new ArrayList();
}
public int pack(Buffer buffer)
{
// String strVendor = "tritonus.org pvorbis library";
// //String strVendor = "Xiph.Org libVorbis I 20030909";
// /* preamble */
// buffer.write(0x03, 8);
// buffer.write("vorbis");
// /* vendor */
// buffer.writeWithLength(strVendor);
// /* comments */
// buffer.write(m_comments.size(), 32);
// if(m_comments.size() > 0)
// {
// for(int i = 0; i < m_comments.size(); i++)
// {
// buffer.writeWithLength(m_comments.get(i));
// }
// }
// buffer.write(1, 1);
return 0;
}
public int unpack(Buffer buffer)
{
int nMagic = buffer.read(24);
if (nMagic != 0x564342)
{
clear();
return -1;
}
m_nDimensions = buffer.read(16);
m_nEntries = buffer.read(24);
if (m_nEntries == -1)
{
clear();
return -1;
}
m_anLengths = new int[m_nEntries];
/* are the lengths ordered or not? */
if (! buffer.readFlag()) // unordered
{
/* sparse? */
if (buffer.readFlag()) // yes, sparse
{
for (int i = 0; i < m_nEntries; i++)
{
if (buffer.readFlag()) // value present
{
int nLength = buffer.read(5);
if (nLength == -1)
{
clear();
return -1;
}
m_anLengths[i] = nLength + 1;
}
else
{
m_anLengths[i] = 0;
}
}
}
else // not sparse
{
for (int i = 0; i < m_nEntries; i++)
{
int nLength = buffer.read(5);
if (nLength == -1)
{
clear();
return -1;
}
m_anLengths[i] = nLength + 1;
}
}
}
else // lengths ordered
{
int nLength = buffer.read(5) + 1;
for (int i = 0; i < m_nEntries;)
{
int nCount = buffer.read(ilog(m_nEntries - i));
if (nCount == -1)
{
clear();
return -1;
}
for (int j = 0; j < nCount; j++, i++)
{
m_anLengths[i] = nLength;
}
nLength++;
}
}
m_nMaptype = buffer.read(4);
if (m_nMaptype == 1 || m_nMaptype == 2)
{
m_nQMin = buffer.read(32);
m_nQDelta = buffer.read(32);
m_nQQuant = buffer.read(4) + 1;
m_nQSequencep = buffer.read(1);
int nQuantVals = 0;
if (m_nMaptype == 1)
{
nQuantVals = calculateMaptype1Quantvals();
}
else if (m_nMaptype == 2)
{
nQuantVals = m_nEntries * m_nDimensions;
}
m_anQuants = new int[nQuantVals];
for (int i = 0; i < nQuantVals; i++)
{
m_anQuants[i] = buffer.read(m_nQQuant);
}
if (nQuantVals != 0 && m_anQuants[nQuantVals - 1] == -1)
{
clear();
return -1;
}
}
else if (m_nMaptype > 2)
{
clear();
return -1;
}
// everything ok.
return 0;
}
/** Calculate the number of quants in a maptype 1 codebook.
*/
private int calculateMaptype1Quantvals()
{
int vals = (int) Math.floor(Math.pow(m_nEntries, 1.0f / m_nDimensions));
/* the above *should* be reliable, but we'll not assume that FP is
ever reliable when bitstream sync is at stake; verify via integer
means that vals really is the greatest value of dim for which
vals^b->bim <= b->entries */
/* treat the above as an initial guess */
while (true)
{
int acc = 1;
int acc1 = 1;
int i;
for (i = 0; i < m_nDimensions; i++)
{
acc *= vals;
acc1 *= vals + 1;
}
if (acc <= m_nEntries && acc1 > m_nEntries)
{
return vals;
}
else
{
if (acc > m_nEntries)
{
vals--;
}
else
{
vals++;
}
}
}
}
private static int ilog(int v)
{
int ret = 0;
while (v != 0)
{
ret++;
v >>= 1;
}
return ret;
}
}
/*** StaticCodebook.java ***/