зеркало из https://github.com/mono/csvorbis.git
Removed all warnings. FFT still needs work.
Added test application. svn path=/trunk/csvorbis/; revision=4017
This commit is contained in:
Родитель
6530017e23
Коммит
7aed3ef62b
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 1.1 KiB |
|
@ -0,0 +1,58 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
[assembly: AssemblyTitle("")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
//
|
||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||
//
|
||||
// Use the attributes below to control which key is used for signing.
|
||||
//
|
||||
// Notes:
|
||||
// (*) If no key is specified, the assembly is not signed.
|
||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||
// a key.
|
||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||
// following processing occurs:
|
||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||
// in the KeyFile is installed into the CSP and used.
|
||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||
// When specifying the KeyFile, the location of the KeyFile should be
|
||||
// relative to the project output directory which is
|
||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
||||
// located in the project directory, you would specify the AssemblyKeyFile
|
||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||
// documentation for more information on this.
|
||||
//
|
||||
[assembly: AssemblyDelaySign(false)]
|
||||
[assembly: AssemblyKeyFile("")]
|
||||
[assembly: AssemblyKeyName("")]
|
|
@ -0,0 +1,343 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using csogg;
|
||||
using csvorbis;
|
||||
|
||||
namespace OggDecoder
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for Class1.
|
||||
/// </summary>
|
||||
class Decoder
|
||||
{
|
||||
|
||||
static int convsize=4096*2;
|
||||
static byte[] convbuffer=new byte[convsize]; // take 8k out of the data segment, not the stack
|
||||
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main(string[] args)
|
||||
{
|
||||
TextWriter s_err = Console.Error;
|
||||
FileStream input = null, output = null;
|
||||
|
||||
if(args.Length == 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
input = new FileStream(args[0], FileMode.Open);
|
||||
output = new FileStream(args[1], FileMode.OpenOrCreate);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
s_err.WriteLine(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SyncState oy=new SyncState(); // sync and verify incoming physical bitstream
|
||||
StreamState os=new StreamState(); // take physical pages, weld into a logical stream of packets
|
||||
Page og=new Page(); // one Ogg bitstream page. Vorbis packets are inside
|
||||
Packet op=new Packet(); // one raw packet of data for decode
|
||||
|
||||
Info vi=new Info(); // struct that stores all the static vorbis bitstream settings
|
||||
Comment vc=new Comment(); // struct that stores all the bitstream user comments
|
||||
DspState vd=new DspState(); // central working state for the packet->PCM decoder
|
||||
Block vb=new Block(vd); // local working space for packet->PCM decode
|
||||
|
||||
byte[] buffer;
|
||||
int bytes=0;
|
||||
|
||||
// Decode setup
|
||||
|
||||
oy.init(); // Now we can read pages
|
||||
|
||||
while(true)
|
||||
{ // we repeat if the bitstream is chained
|
||||
int eos=0;
|
||||
|
||||
// grab some data at the head of the stream. We want the first page
|
||||
// (which is guaranteed to be small and only contain the Vorbis
|
||||
// stream initial header) We need the first page to get the stream
|
||||
// serialno.
|
||||
|
||||
// submit a 4k block to libvorbis' Ogg layer
|
||||
int index=oy.buffer(4096);
|
||||
buffer=oy.data;
|
||||
try
|
||||
{
|
||||
s_err.WriteLine("Read a little bit...");
|
||||
bytes = input.Read(buffer, index, 4096);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
s_err.WriteLine(e);
|
||||
}
|
||||
oy.wrote(bytes);
|
||||
|
||||
// Get the first page.
|
||||
if(oy.pageout(og)!=1)
|
||||
{
|
||||
// have we simply run out of data? If so, we're done.
|
||||
if(bytes<4096)break;
|
||||
|
||||
// error case. Must not be Vorbis data
|
||||
s_err.WriteLine("Input does not appear to be an Ogg bitstream.");
|
||||
}
|
||||
|
||||
// Get the serial number and set up the rest of decode.
|
||||
// serialno first; use it to set up a logical stream
|
||||
os.init(og.serialno());
|
||||
|
||||
// extract the initial header from the first page and verify that the
|
||||
// Ogg bitstream is in fact Vorbis data
|
||||
|
||||
// I handle the initial header first instead of just having the code
|
||||
// read all three Vorbis headers at once because reading the initial
|
||||
// header is an easy way to identify a Vorbis bitstream and it's
|
||||
// useful to see that functionality seperated out.
|
||||
|
||||
vi.init();
|
||||
vc.init();
|
||||
if(os.pagein(og)<0)
|
||||
{
|
||||
// error; stream version mismatch perhaps
|
||||
s_err.WriteLine("Error reading first page of Ogg bitstream data.");
|
||||
}
|
||||
|
||||
if(os.packetout(op)!=1)
|
||||
{
|
||||
// no page? must not be vorbis
|
||||
s_err.WriteLine("Error reading initial header packet.");
|
||||
}
|
||||
|
||||
if(vi.synthesis_headerin(vc,op)<0)
|
||||
{
|
||||
// error case; not a vorbis header
|
||||
s_err.WriteLine("This Ogg bitstream does not contain Vorbis audio data.");
|
||||
}
|
||||
|
||||
// At this point, we're sure we're Vorbis. We've set up the logical
|
||||
// (Ogg) bitstream decoder. Get the comment and codebook headers and
|
||||
// set up the Vorbis decoder
|
||||
|
||||
// The next two packets in order are the comment and codebook headers.
|
||||
// They're likely large and may span multiple pages. Thus we reead
|
||||
// and submit data until we get our two pacakets, watching that no
|
||||
// pages are missing. If a page is missing, error out; losing a
|
||||
// header page is the only place where missing data is fatal. */
|
||||
|
||||
int i=0;
|
||||
s_err.WriteLine("Starting the fun...");
|
||||
while(i<2)
|
||||
{
|
||||
while(i<2)
|
||||
{
|
||||
|
||||
int result=oy.pageout(og);
|
||||
if(result==0) break; // Need more data
|
||||
// Don't complain about missing or corrupt data yet. We'll
|
||||
// catch it at the packet output phase
|
||||
|
||||
if(result==1)
|
||||
{
|
||||
os.pagein(og); // we can ignore any errors here
|
||||
// as they'll also become apparent
|
||||
// at packetout
|
||||
while(i<2)
|
||||
{
|
||||
result=os.packetout(op);
|
||||
if(result==0)break;
|
||||
if(result==-1)
|
||||
{
|
||||
// Uh oh; data at some point was corrupted or missing!
|
||||
// We can't tolerate that in a header. Die.
|
||||
s_err.WriteLine("Corrupt secondary header. Exiting.");
|
||||
}
|
||||
vi.synthesis_headerin(vc,op);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// no harm in not checking before adding more
|
||||
index=oy.buffer(4096);
|
||||
buffer=oy.data;
|
||||
try
|
||||
{
|
||||
bytes=input.Read(buffer, index, 4096);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
s_err.WriteLine(e);
|
||||
}
|
||||
if(bytes==0 && i<2)
|
||||
{
|
||||
s_err.WriteLine("End of file before finding all Vorbis headers!");
|
||||
}
|
||||
oy.wrote(bytes);
|
||||
}
|
||||
|
||||
// Throw the comments plus a few lines about the bitstream we're
|
||||
// decoding
|
||||
{
|
||||
byte[][] ptr=vc.user_comments;
|
||||
for(int j=0; j<ptr.Length;j++)
|
||||
{
|
||||
if(ptr[j]==null) break;
|
||||
s_err.WriteLine(ptr[j].ToString());
|
||||
}
|
||||
s_err.WriteLine("\nBitstream is "+vi.channels+" channel, "+vi.rate+"Hz");
|
||||
s_err.WriteLine("Encoded by: "+vc.vendor.ToString()+"\n");
|
||||
}
|
||||
|
||||
convsize=4096/vi.channels;
|
||||
|
||||
// OK, got and parsed all three headers. Initialize the Vorbis
|
||||
// packet->PCM decoder.
|
||||
s_err.WriteLine("Entering Init Routines");
|
||||
vd.synthesis_init(vi); // central decode state
|
||||
s_err.WriteLine("synthesis_init DONE");
|
||||
vb.init(vd); // local state for most of the decode
|
||||
s_err.WriteLine("Init DONE!");
|
||||
// so multiple block decodes can
|
||||
// proceed in parallel. We could init
|
||||
// multiple vorbis_block structures
|
||||
// for vd here
|
||||
|
||||
float[][][] _pcm=new float[1][][];
|
||||
int[] _index=new int[vi.channels];
|
||||
// The rest is just a straight decode loop until end of stream
|
||||
while(eos==0)
|
||||
{
|
||||
while(eos==0)
|
||||
{
|
||||
|
||||
int result=oy.pageout(og);
|
||||
if(result==0)break; // need more data
|
||||
if(result==-1)
|
||||
{ // missing or corrupt data at this page position
|
||||
s_err.WriteLine("Corrupt or missing data in bitstream; continuing...");
|
||||
}
|
||||
else
|
||||
{
|
||||
os.pagein(og); // can safely ignore errors at
|
||||
// this point
|
||||
while(true)
|
||||
{
|
||||
result=os.packetout(op);
|
||||
|
||||
if(result==0)break; // need more data
|
||||
if(result==-1)
|
||||
{ // missing or corrupt data at this page position
|
||||
// no reason to complain; already complained above
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have a packet. Decode it
|
||||
int samples;
|
||||
if(vb.synthesis(op)==0)
|
||||
{ // test for success!
|
||||
s_err.WriteLine("Blockin' the synth");
|
||||
vd.synthesis_blockin(vb);
|
||||
s_err.WriteLine("Done.");
|
||||
}
|
||||
|
||||
// **pcm is a multichannel float vector. In stereo, for
|
||||
// example, pcm[0] is left, and pcm[1] is right. samples is
|
||||
// the size of each channel. Convert the float values
|
||||
// (-1.<=range<=1.) to whatever PCM format and write it out
|
||||
|
||||
while((samples=vd.synthesis_pcmout(_pcm, _index))>0)
|
||||
{
|
||||
float[][] pcm=_pcm[0];
|
||||
bool clipflag=false;
|
||||
int bout=(samples<convsize?samples:convsize);
|
||||
|
||||
// convert floats to 16 bit signed ints (host order) and
|
||||
// interleave
|
||||
for(i=0;i<vi.channels;i++)
|
||||
{
|
||||
int ptr=i*2;
|
||||
//int ptr=i;
|
||||
int mono=_index[i];
|
||||
for(int j=0;j<bout;j++)
|
||||
{
|
||||
int val=(int)(pcm[i][mono+j]*32767.0);
|
||||
// short val=(short)(pcm[i][mono+j]*32767.);
|
||||
// int val=(int)Math.round(pcm[i][mono+j]*32767.);
|
||||
// might as well guard against clipping
|
||||
if(val>32767)
|
||||
{
|
||||
val=32767;
|
||||
clipflag=true;
|
||||
}
|
||||
if(val<-32768)
|
||||
{
|
||||
val=-32768;
|
||||
clipflag=true;
|
||||
}
|
||||
if(val<0) val=val|0x8000;
|
||||
convbuffer[ptr]=(byte)(val);
|
||||
convbuffer[ptr+1]=(byte)((uint)val>>8);
|
||||
ptr+=2*(vi.channels);
|
||||
}
|
||||
}
|
||||
|
||||
if(clipflag)
|
||||
s_err.WriteLine("Clipping in frame "+vd.sequence);
|
||||
|
||||
s_err.WriteLine("ScribbleScribble");
|
||||
output.Write(convbuffer, 0, 2*vi.channels*bout);
|
||||
|
||||
vd.synthesis_read(bout); // tell libvorbis how
|
||||
// many samples we
|
||||
// actually consumed
|
||||
}
|
||||
}
|
||||
}
|
||||
if(og.eos()!=0)eos=1;
|
||||
}
|
||||
}
|
||||
if(eos==0)
|
||||
{
|
||||
index=oy.buffer(4096);
|
||||
buffer=oy.data;
|
||||
try
|
||||
{
|
||||
bytes=input.Read(buffer,index,4096);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
s_err.WriteLine(e);
|
||||
}
|
||||
oy.wrote(bytes);
|
||||
if(bytes==0)eos=1;
|
||||
}
|
||||
}
|
||||
|
||||
// clean up this logical bitstream; before exit we see if we're
|
||||
// followed by another [chained]
|
||||
|
||||
os.clear();
|
||||
|
||||
// ogg_page and ogg_packet structs always point to storage in
|
||||
// libvorbis. They're never freed or manipulated directly
|
||||
|
||||
vb.clear();
|
||||
vd.clear();
|
||||
vi.clear(); // must be called last
|
||||
}
|
||||
|
||||
// OK, clean up the framer
|
||||
oy.clear();
|
||||
s_err.WriteLine("Done.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
<VisualStudioProject>
|
||||
<CSHARP
|
||||
ProjectType = "Local"
|
||||
ProductVersion = "7.0.9466"
|
||||
SchemaVersion = "1.0"
|
||||
ProjectGuid = "{4CA9EB23-E111-4DAD-9932-F73E8E6C54C5}"
|
||||
>
|
||||
<Build>
|
||||
<Settings
|
||||
ApplicationIcon = "App.ico"
|
||||
AssemblyKeyContainerName = ""
|
||||
AssemblyName = "OggDecoder"
|
||||
AssemblyOriginatorKeyFile = ""
|
||||
DefaultClientScript = "JScript"
|
||||
DefaultHTMLPageLayout = "Grid"
|
||||
DefaultTargetSchema = "IE50"
|
||||
DelaySign = "false"
|
||||
OutputType = "Exe"
|
||||
RootNamespace = "OggDecoder"
|
||||
StartupObject = ""
|
||||
>
|
||||
<Config
|
||||
Name = "Debug"
|
||||
AllowUnsafeBlocks = "false"
|
||||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "DEBUG;TRACE"
|
||||
DocumentationFile = ""
|
||||
DebugSymbols = "true"
|
||||
FileAlignment = "4096"
|
||||
IncrementalBuild = "true"
|
||||
Optimize = "false"
|
||||
OutputPath = "bin\Debug\"
|
||||
RegisterForComInterop = "false"
|
||||
RemoveIntegerChecks = "false"
|
||||
TreatWarningsAsErrors = "false"
|
||||
WarningLevel = "4"
|
||||
/>
|
||||
<Config
|
||||
Name = "Release"
|
||||
AllowUnsafeBlocks = "false"
|
||||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "TRACE"
|
||||
DocumentationFile = ""
|
||||
DebugSymbols = "false"
|
||||
FileAlignment = "4096"
|
||||
IncrementalBuild = "false"
|
||||
Optimize = "true"
|
||||
OutputPath = "bin\Release\"
|
||||
RegisterForComInterop = "false"
|
||||
RemoveIntegerChecks = "false"
|
||||
TreatWarningsAsErrors = "false"
|
||||
WarningLevel = "4"
|
||||
/>
|
||||
</Settings>
|
||||
<References>
|
||||
<Reference
|
||||
Name = "System"
|
||||
AssemblyName = "System"
|
||||
HintPath = "..\..\..\..\..\..\WINNT\Microsoft.NET\Framework\v1.0.3705\System.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Data"
|
||||
AssemblyName = "System.Data"
|
||||
HintPath = "..\..\..\..\..\..\WINNT\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.XML"
|
||||
AssemblyName = "System.XML"
|
||||
HintPath = "..\..\..\..\..\..\WINNT\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "csogg"
|
||||
Project = "{FA4ACE8B-CDEE-41A3-92D7-C73069B84B83}"
|
||||
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
|
||||
/>
|
||||
<Reference
|
||||
Name = "csvorbis"
|
||||
Project = "{0087C0AF-E896-4C55-A999-5245560BCBE3}"
|
||||
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
|
||||
/>
|
||||
</References>
|
||||
</Build>
|
||||
<Files>
|
||||
<Include>
|
||||
<File
|
||||
RelPath = "App.ico"
|
||||
BuildAction = "Content"
|
||||
/>
|
||||
<File
|
||||
RelPath = "AssemblyInfo.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "OggDecoder.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
</Include>
|
||||
</Files>
|
||||
</CSHARP>
|
||||
</VisualStudioProject>
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<VisualStudioProject>
|
||||
<CSHARP>
|
||||
<Build>
|
||||
<Settings ReferencePath = "" >
|
||||
<Config
|
||||
Name = "Debug"
|
||||
EnableASPDebugging = "false"
|
||||
EnableASPXDebugging = "false"
|
||||
EnableUnmanagedDebugging = "false"
|
||||
EnableSQLServerDebugging = "false"
|
||||
RemoteDebugEnabled = "false"
|
||||
RemoteDebugMachine = ""
|
||||
StartAction = "Project"
|
||||
StartArguments = ""
|
||||
StartPage = ""
|
||||
StartProgram = ""
|
||||
StartURL = ""
|
||||
StartWorkingDirectory = ""
|
||||
StartWithIE = "true"
|
||||
/>
|
||||
<Config
|
||||
Name = "Release"
|
||||
EnableASPDebugging = "false"
|
||||
EnableASPXDebugging = "false"
|
||||
EnableUnmanagedDebugging = "false"
|
||||
EnableSQLServerDebugging = "false"
|
||||
RemoteDebugEnabled = "false"
|
||||
RemoteDebugMachine = ""
|
||||
StartAction = "Project"
|
||||
StartArguments = ""
|
||||
StartPage = ""
|
||||
StartProgram = ""
|
||||
StartURL = ""
|
||||
StartWorkingDirectory = ""
|
||||
StartWithIE = "true"
|
||||
/>
|
||||
</Settings>
|
||||
</Build>
|
||||
<OtherProjectSettings
|
||||
CopyProjectDestinationFolder = ""
|
||||
CopyProjectUncPath = ""
|
||||
CopyProjectOption = "0"
|
||||
ProjectView = "ProjectFiles"
|
||||
ProjectTrust = "0"
|
||||
/>
|
||||
</CSHARP>
|
||||
</VisualStudioProject>
|
||||
|
|
@ -70,7 +70,7 @@ namespace csogg
|
|||
storage = bytes;
|
||||
}
|
||||
|
||||
public void write(uint value, int bits)
|
||||
public void write(int vvalue, int bits)
|
||||
{
|
||||
if(endbyte + 4 >= storage)
|
||||
{
|
||||
|
@ -80,23 +80,23 @@ namespace csogg
|
|||
storage += BUFFER_INCREMENT;
|
||||
}
|
||||
|
||||
value &= mask[bits];
|
||||
vvalue = (int)((uint)vvalue & mask[bits]);
|
||||
bits += endbit;
|
||||
buffer[ptr] |= (byte)(value << endbit);
|
||||
buffer[ptr] |= (byte)(vvalue << endbit);
|
||||
|
||||
if(bits >= 8)
|
||||
{
|
||||
buffer[ptr+1] = (byte)(value >> (8-endbit));
|
||||
buffer[ptr+1] = (byte)((uint)vvalue >> (8-endbit));
|
||||
if(bits >= 16)
|
||||
{
|
||||
buffer[ptr+2] = (byte)(value >> (16-endbit));
|
||||
buffer[ptr+2] = (byte)((uint)vvalue >> (16-endbit));
|
||||
if (bits >= 24)
|
||||
{
|
||||
buffer[ptr+3] = (byte)(value >> (24-endbit));
|
||||
buffer[ptr+3] = (byte)((uint)vvalue >> (24-endbit));
|
||||
if(bits >= 32)
|
||||
{
|
||||
if(endbit > 0)
|
||||
buffer[ptr+4] = (byte)(value >> (32-endbit));
|
||||
buffer[ptr+4] = (byte)((uint)vvalue >> (32-endbit));
|
||||
else
|
||||
buffer[ptr+4]=0;
|
||||
}
|
||||
|
@ -265,6 +265,11 @@ namespace csogg
|
|||
return(ret);
|
||||
}
|
||||
|
||||
public byte[] buf()
|
||||
{
|
||||
return(buffer);
|
||||
}
|
||||
|
||||
public csBuffer()
|
||||
{
|
||||
// Really a noop?
|
||||
|
|
|
@ -9,14 +9,14 @@
|
|||
<Settings
|
||||
ApplicationIcon = ""
|
||||
AssemblyKeyContainerName = ""
|
||||
AssemblyName = "cogg"
|
||||
AssemblyName = "csogg"
|
||||
AssemblyOriginatorKeyFile = ""
|
||||
DefaultClientScript = "JScript"
|
||||
DefaultHTMLPageLayout = "Grid"
|
||||
DefaultTargetSchema = "IE50"
|
||||
DelaySign = "false"
|
||||
OutputType = "Library"
|
||||
RootNamespace = "cogg"
|
||||
RootNamespace = "csogg"
|
||||
StartupObject = ""
|
||||
>
|
||||
<Config
|
||||
|
|
|
@ -25,8 +25,11 @@
|
|||
|
||||
using System;
|
||||
|
||||
class AllocChain
|
||||
namespace csvorbis
|
||||
{
|
||||
Object ptr;
|
||||
AllocChain next;
|
||||
};
|
||||
class AllocChain
|
||||
{
|
||||
//Object ptr;
|
||||
//AllocChain next;
|
||||
};
|
||||
}
|
|
@ -26,162 +26,180 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
public class Block{
|
||||
///necessary stream state for linking to the framing abstraction
|
||||
float[][] pcm=new float[0][]; // this is a pointer into local storage
|
||||
Buffer opb=new Buffer();
|
||||
namespace csvorbis
|
||||
{
|
||||
public class Block
|
||||
{
|
||||
///necessary stream state for linking to the framing abstraction
|
||||
internal float[][] pcm=new float[0][]; // this is a pointer into local storage
|
||||
internal csBuffer opb=new csBuffer();
|
||||
|
||||
int lW;
|
||||
int W;
|
||||
int nW;
|
||||
int pcmend;
|
||||
int mode;
|
||||
internal int lW;
|
||||
internal int W;
|
||||
internal int nW;
|
||||
internal int pcmend;
|
||||
internal int mode;
|
||||
|
||||
int eofflag;
|
||||
long granulepos;
|
||||
long sequence;
|
||||
DspState vd; // For read-only access of configuration
|
||||
internal int eofflag;
|
||||
internal long granulepos;
|
||||
internal long sequence;
|
||||
internal DspState vd; // For read-only access of configuration
|
||||
|
||||
// local storage to avoid remallocing; it's up to the mapping to
|
||||
// structure it
|
||||
//byte[] localstore;
|
||||
//int localtop;
|
||||
//int localalloc;
|
||||
//int totaluse;
|
||||
//AllocChain reap;
|
||||
// local storage to avoid remallocing; it's up to the mapping to
|
||||
// structure it
|
||||
//byte[] localstore;
|
||||
//int localtop;
|
||||
//int localalloc;
|
||||
//int totaluse;
|
||||
//AllocChain reap;
|
||||
|
||||
// bitmetrics for the frame
|
||||
int glue_bits;
|
||||
int time_bits;
|
||||
int floor_bits;
|
||||
int res_bits;
|
||||
// bitmetrics for the frame
|
||||
internal int glue_bits;
|
||||
internal int time_bits;
|
||||
internal int floor_bits;
|
||||
internal int res_bits;
|
||||
|
||||
public Block(DspState vd){
|
||||
this.vd=vd;
|
||||
// localalloc=0;
|
||||
// localstore=null;
|
||||
if(vd.analysisp!=0){
|
||||
opb.writeinit();
|
||||
}
|
||||
}
|
||||
public Block(DspState vd)
|
||||
{
|
||||
this.vd=vd;
|
||||
// localalloc=0;
|
||||
// localstore=null;
|
||||
if(vd.analysisp!=0)
|
||||
{
|
||||
opb.writeinit();
|
||||
}
|
||||
}
|
||||
|
||||
public void init(DspState vd){
|
||||
this.vd=vd;
|
||||
}
|
||||
public void init(DspState vd)
|
||||
{
|
||||
this.vd=vd;
|
||||
}
|
||||
|
||||
// int alloc(int bytes){
|
||||
// bytes=(bytes+(8-1))&(~(8-1));
|
||||
// if(bytes+localtop>localalloc){
|
||||
// if(localstore!=null){
|
||||
// AllocChain link=new AllocChain();
|
||||
// totaluse+=localtop;
|
||||
// link.next=reap;
|
||||
// link.ptr=localstore;
|
||||
// reap=link;
|
||||
// }
|
||||
// // highly conservative
|
||||
// localalloc=bytes;
|
||||
// localstore=new byte[localalloc];
|
||||
// localtop=0;
|
||||
// }
|
||||
// {
|
||||
// int foo=localtop;
|
||||
// //void *ret=(void *)(((char *)vb->localstore)+vb->localtop);
|
||||
// localtop+=bytes;
|
||||
// return foo;
|
||||
// }
|
||||
// }
|
||||
// int alloc(int bytes){
|
||||
// bytes=(bytes+(8-1))&(~(8-1));
|
||||
// if(bytes+localtop>localalloc){
|
||||
// if(localstore!=null){
|
||||
// AllocChain link=new AllocChain();
|
||||
// totaluse+=localtop;
|
||||
// link.next=reap;
|
||||
// link.ptr=localstore;
|
||||
// reap=link;
|
||||
// }
|
||||
// // highly conservative
|
||||
// localalloc=bytes;
|
||||
// localstore=new byte[localalloc];
|
||||
// localtop=0;
|
||||
// }
|
||||
// {
|
||||
// int foo=localtop;
|
||||
// //void *ret=(void *)(((char *)vb->localstore)+vb->localtop);
|
||||
// localtop+=bytes;
|
||||
// return foo;
|
||||
// }
|
||||
// }
|
||||
|
||||
// reap the chain, pull the ripcord
|
||||
// void ripcord(){
|
||||
// // reap the chain
|
||||
// while(reap!=null){
|
||||
// AllocChain next=reap.next;
|
||||
// //free(reap->ptr);
|
||||
// reap.ptr=null;
|
||||
// //memset(reap,0,sizeof(struct alloc_chain));
|
||||
// //free(reap);
|
||||
// reap=next;
|
||||
// }
|
||||
// // consolidate storage
|
||||
// if(totaluse!=0){
|
||||
// //vb->localstore=realloc(vb->localstore,vb->totaluse+vb->localalloc);
|
||||
// byte[] foo=new byte[totaluse+localalloc];
|
||||
// System.arraycopy(localstore, 0, foo, 0, localstore.length);
|
||||
// localstore=foo;
|
||||
// localalloc+=totaluse;
|
||||
// totaluse=0;
|
||||
// }
|
||||
// // pull the ripcord
|
||||
// localtop=0;
|
||||
// reap=null;
|
||||
// }
|
||||
// reap the chain, pull the ripcord
|
||||
// void ripcord(){
|
||||
// // reap the chain
|
||||
// while(reap!=null){
|
||||
// AllocChain next=reap.next;
|
||||
// //free(reap->ptr);
|
||||
// reap.ptr=null;
|
||||
// //memset(reap,0,sizeof(struct alloc_chain));
|
||||
// //free(reap);
|
||||
// reap=next;
|
||||
// }
|
||||
// // consolidate storage
|
||||
// if(totaluse!=0){
|
||||
// //vb->localstore=realloc(vb->localstore,vb->totaluse+vb->localalloc);
|
||||
// byte[] foo=new byte[totaluse+localalloc];
|
||||
// Array.Copy(localstore, 0, foo, 0, localstore.length);
|
||||
// localstore=foo;
|
||||
// localalloc+=totaluse;
|
||||
// totaluse=0;
|
||||
// }
|
||||
// // pull the ripcord
|
||||
// localtop=0;
|
||||
// reap=null;
|
||||
// }
|
||||
|
||||
public int clear(){
|
||||
if(vd!=null){
|
||||
if(vd.analysisp!=0){
|
||||
opb.writeclear();
|
||||
}
|
||||
}
|
||||
//ripcord();
|
||||
//if(localstore!=null)
|
||||
// localstore=null;
|
||||
//memset(vb,0,sizeof(vorbis_block));
|
||||
return(0);
|
||||
}
|
||||
public int clear()
|
||||
{
|
||||
if(vd!=null)
|
||||
{
|
||||
if(vd.analysisp!=0)
|
||||
{
|
||||
opb.writeclear();
|
||||
}
|
||||
}
|
||||
//ripcord();
|
||||
//if(localstore!=null)
|
||||
// localstore=null;
|
||||
//memset(vb,0,sizeof(vorbis_block));
|
||||
return(0);
|
||||
}
|
||||
|
||||
public int synthesis(Packet op){
|
||||
Info vi=vd.vi;
|
||||
public int synthesis(Packet op)
|
||||
{
|
||||
Info vi=vd.vi;
|
||||
|
||||
// first things first. Make sure decode is ready
|
||||
// ripcord();
|
||||
opb.readinit(op.packet_base, op.packet, op.bytes);
|
||||
// first things first. Make sure decode is ready
|
||||
// ripcord();
|
||||
opb.readinit(op.packet_base, op.packet, op.bytes);
|
||||
|
||||
// Check the packet type
|
||||
if(opb.read(1)!=0){
|
||||
// Oops. This is not an audio data packet
|
||||
return(-1);
|
||||
}
|
||||
// Check the packet type
|
||||
if(opb.read(1)!=0)
|
||||
{
|
||||
// Oops. This is not an audio data packet
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// read our mode and pre/post windowsize
|
||||
int _mode=opb.read(vd.modebits);
|
||||
if(_mode==-1)return(-1);
|
||||
// read our mode and pre/post windowsize
|
||||
int _mode=opb.read(vd.modebits);
|
||||
if(_mode==-1)return(-1);
|
||||
|
||||
mode=_mode;
|
||||
W=vi.mode_param[mode].blockflag;
|
||||
if(W!=0){
|
||||
lW=opb.read(1);
|
||||
nW=opb.read(1);
|
||||
if(nW==-1) return(-1);
|
||||
}
|
||||
else{
|
||||
lW=0;
|
||||
nW=0;
|
||||
}
|
||||
mode=_mode;
|
||||
W=vi.mode_param[mode].blockflag;
|
||||
if(W!=0)
|
||||
{
|
||||
lW=opb.read(1);
|
||||
nW=opb.read(1);
|
||||
if(nW==-1) return(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
lW=0;
|
||||
nW=0;
|
||||
}
|
||||
|
||||
// more setup
|
||||
granulepos=op.granulepos;
|
||||
sequence=op.packetno-3; // first block is third packet
|
||||
eofflag=op.e_o_s;
|
||||
// more setup
|
||||
granulepos=op.granulepos;
|
||||
sequence=op.packetno-3; // first block is third packet
|
||||
eofflag=op.e_o_s;
|
||||
|
||||
// alloc pcm passback storage
|
||||
pcmend=vi.blocksizes[W];
|
||||
//pcm=alloc(vi.channels);
|
||||
if(pcm.length<vi.channels){
|
||||
pcm=new float[vi.channels][];
|
||||
}
|
||||
for(int i=0;i<vi.channels;i++){
|
||||
if(pcm[i]==null || pcm[i].length<pcmend){
|
||||
pcm[i]=new float[pcmend];
|
||||
//pcm[i]=alloc(pcmend);
|
||||
}
|
||||
else{
|
||||
for(int j=0;j<pcmend;j++){ pcm[i][j]=0; }
|
||||
}
|
||||
}
|
||||
// alloc pcm passback storage
|
||||
pcmend=vi.blocksizes[W];
|
||||
//pcm=alloc(vi.channels);
|
||||
if(pcm.Length<vi.channels)
|
||||
{
|
||||
pcm=new float[vi.channels][];
|
||||
}
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
{
|
||||
if(pcm[i]==null || pcm[i].Length<pcmend)
|
||||
{
|
||||
pcm[i]=new float[pcmend];
|
||||
//pcm[i]=alloc(pcmend);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int j=0;j<pcmend;j++){ pcm[i][j]=0; }
|
||||
}
|
||||
}
|
||||
|
||||
// unpack_header enforces range checking
|
||||
int type=vi.map_type[vi.mode_param[mode].mapping];
|
||||
return(FuncMapping.mapping_P[type].inverse(this, vd.mode[mode]));
|
||||
}
|
||||
// unpack_header enforces range checking
|
||||
int type=vi.map_type[vi.mode_param[mode].mapping];
|
||||
return(FuncMapping.mapping_P[type].inverse(this, vd.mode[mode]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
1258
csvorbis/CodeBook.cs
1258
csvorbis/CodeBook.cs
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -24,262 +24,284 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using csogg;
|
||||
|
||||
// the comments are not part of vorbis_info so that vorbis_info can be
|
||||
// static storage
|
||||
public class Comment
|
||||
namespace csvorbis
|
||||
{
|
||||
private static byte[] _vorbis="vorbis".getBytes();
|
||||
|
||||
private static int OV_EFAULT=-129;
|
||||
private static int OV_EIMPL=-130;
|
||||
|
||||
// unlimited user comment fields. libvorbis writes 'libvorbis'
|
||||
// whatever vendor is set to in encode
|
||||
public byte[][] user_comments;
|
||||
public int[] comment_lengths;
|
||||
public int comments;
|
||||
public byte[] vendor;
|
||||
|
||||
public void init()
|
||||
// the comments are not part of vorbis_info so that vorbis_info can be
|
||||
// static storage
|
||||
public class Comment
|
||||
{
|
||||
user_comments=null;
|
||||
comments=0;
|
||||
vendor=null;
|
||||
}
|
||||
private static String _vorbis="vorbis";
|
||||
|
||||
public void add(String comment)
|
||||
{
|
||||
add(comment.getBytes());
|
||||
}
|
||||
//private static int OV_EFAULT=-129;
|
||||
private static int OV_EIMPL=-130;
|
||||
|
||||
private void add(byte[] comment)
|
||||
{
|
||||
byte[][] foo=new byte[comments+2][];
|
||||
if(user_comments!=null)
|
||||
// unlimited user comment fields. libvorbis writes 'libvorbis'
|
||||
// whatever vendor is set to in encode
|
||||
public byte[][] user_comments;
|
||||
public int[] comment_lengths;
|
||||
public int comments;
|
||||
public byte[] vendor;
|
||||
|
||||
public void init()
|
||||
{
|
||||
System.arraycopy(user_comments, 0, foo, 0, comments);
|
||||
user_comments=null;
|
||||
comments=0;
|
||||
vendor=null;
|
||||
}
|
||||
user_comments=foo;
|
||||
|
||||
int[] goo=new int[comments+2];
|
||||
if(comment_lengths!=null)
|
||||
public void add(String comment)
|
||||
{
|
||||
System.arraycopy(comment_lengths, 0, goo, 0, comments);
|
||||
ASCIIEncoding AE = new ASCIIEncoding();
|
||||
byte[] comment_byt = AE.GetBytes(comment);
|
||||
add(comment_byt);
|
||||
}
|
||||
comment_lengths=goo;
|
||||
|
||||
byte[] bar=new byte[comment.length+1];
|
||||
System.arraycopy(comment, 0, bar, 0, comment.length);
|
||||
user_comments[comments]=bar;
|
||||
comment_lengths[comments]=comment.length;
|
||||
comments++;
|
||||
user_comments[comments]=null;
|
||||
}
|
||||
private void add(byte[] comment)
|
||||
{
|
||||
byte[][] foo=new byte[comments+2][];
|
||||
if(user_comments!=null)
|
||||
{
|
||||
Array.Copy(user_comments, 0, foo, 0, comments);
|
||||
}
|
||||
user_comments=foo;
|
||||
|
||||
public void add_tag(String tag, String contents)
|
||||
{
|
||||
if(contents==null) contents="";
|
||||
add(tag+"="+contents);
|
||||
}
|
||||
int[] goo=new int[comments+2];
|
||||
if(comment_lengths!=null)
|
||||
{
|
||||
Array.Copy(comment_lengths, 0, goo, 0, comments);
|
||||
}
|
||||
comment_lengths=goo;
|
||||
|
||||
/*
|
||||
private void add_tag(byte[] tag, byte[] contents){
|
||||
byte[] foo=new byte[tag.length+contents.length+1];
|
||||
int j=0;
|
||||
for(int i=0; i<tag.length; i++){foo[j++]=tag[i];}
|
||||
foo[j++]=(byte)'='; j++;
|
||||
for(int i=0; i<contents.length; i++){foo[j++]=tag[i];}
|
||||
add(foo);
|
||||
}
|
||||
*/
|
||||
byte[] bar=new byte[comment.Length+1];
|
||||
Array.Copy(comment, 0, bar, 0, comment.Length);
|
||||
user_comments[comments]=bar;
|
||||
comment_lengths[comments]=comment.Length;
|
||||
comments++;
|
||||
user_comments[comments]=null;
|
||||
}
|
||||
|
||||
public void add_tag(String tag, String contents)
|
||||
{
|
||||
if(contents==null) contents="";
|
||||
add(tag+"="+contents);
|
||||
}
|
||||
|
||||
/*
|
||||
private void add_tag(byte[] tag, byte[] contents){
|
||||
byte[] foo=new byte[tag.length+contents.length+1];
|
||||
int j=0;
|
||||
for(int i=0; i<tag.length; i++){foo[j++]=tag[i];}
|
||||
foo[j++]=(byte)'='; j++;
|
||||
for(int i=0; i<contents.length; i++){foo[j++]=tag[i];}
|
||||
add(foo);
|
||||
}
|
||||
*/
|
||||
|
||||
// This is more or less the same as strncasecmp - but that doesn't exist
|
||||
// * everywhere, and this is a fairly trivial function, so we include it
|
||||
static int tagcompare(byte[] s1, byte[] s2, int n)
|
||||
{
|
||||
int c=0;
|
||||
byte u1, u2;
|
||||
while(c < n)
|
||||
// This is more or less the same as strncasecmp - but that doesn't exist
|
||||
// * everywhere, and this is a fairly trivial function, so we include it
|
||||
static bool tagcompare(byte[] s1, byte[] s2, int n)
|
||||
{
|
||||
u1=s1[c]; u2=s2[c];
|
||||
if(u1>='A')u1=(byte)(u1-'A'+'a');
|
||||
if(u2>='A')u2=(byte)(u2-'A'+'a');
|
||||
if(u1!=u2){ return false; }
|
||||
c++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String query(String tag)
|
||||
{
|
||||
return query(tag, 0);
|
||||
}
|
||||
|
||||
public String query(String tag, int count)
|
||||
{
|
||||
int foo=query(tag.getBytes(), count);
|
||||
if(foo==-1)return null;
|
||||
byte[] comment=user_comments[foo];
|
||||
for(int i=0; i<comment_lengths[foo]; i++)
|
||||
{
|
||||
if(comment[i]=='=')
|
||||
int c=0;
|
||||
byte u1, u2;
|
||||
while(c < n)
|
||||
{
|
||||
return new String(comment, i+1, comment_lengths[foo]-(i+1));
|
||||
u1=s1[c]; u2=s2[c];
|
||||
if(u1>='A')u1=(byte)(u1-'A'+'a');
|
||||
if(u2>='A')u2=(byte)(u2-'A'+'a');
|
||||
if(u1!=u2){ return false; }
|
||||
c++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private int query(byte[] tag, int count)
|
||||
{
|
||||
int i=0;
|
||||
int found = 0;
|
||||
int taglen = tag.length;
|
||||
byte[] fulltag = new byte[taglen+2];
|
||||
System.arraycopy(tag, 0, fulltag, 0, tag.length);
|
||||
fulltag[tag.length]=(byte)'=';
|
||||
|
||||
for(i=0;i<comments;i++)
|
||||
public String query(String tag)
|
||||
{
|
||||
if(tagcompare(user_comments[i], fulltag, taglen))
|
||||
return query(tag, 0);
|
||||
}
|
||||
|
||||
public String query(String tag, int count)
|
||||
{
|
||||
ASCIIEncoding AE = new ASCIIEncoding();
|
||||
byte[] tag_byt = AE.GetBytes(tag);
|
||||
|
||||
int foo=query(tag_byt, count);
|
||||
if(foo==-1)return null;
|
||||
byte[] comment=user_comments[foo];
|
||||
for(int i=0; i<comment_lengths[foo]; i++)
|
||||
{
|
||||
if(count==found)
|
||||
if(comment[i]=='=')
|
||||
{
|
||||
// We return a pointer to the data, not a copy
|
||||
//return user_comments[i] + taglen + 1;
|
||||
return i;
|
||||
//TODO
|
||||
//return new String(comment, i+1, comment_lengths[foo]-(i+1));
|
||||
return "Meme";
|
||||
}
|
||||
else{ found++; }
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int unpack(Buffer opb)
|
||||
{
|
||||
int vendorlen=opb.read(32);
|
||||
if(vendorlen<0)
|
||||
private int query(byte[] tag, int count)
|
||||
{
|
||||
//goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
int i=0;
|
||||
int found = 0;
|
||||
int taglen = tag.Length;
|
||||
byte[] fulltag = new byte[taglen+2];
|
||||
Array.Copy(tag, 0, fulltag, 0, tag.Length);
|
||||
fulltag[tag.Length]=(byte)'=';
|
||||
|
||||
for(i=0;i<comments;i++)
|
||||
{
|
||||
if(tagcompare(user_comments[i], fulltag, taglen))
|
||||
{
|
||||
if(count==found)
|
||||
{
|
||||
// We return a pointer to the data, not a copy
|
||||
//return user_comments[i] + taglen + 1;
|
||||
return i;
|
||||
}
|
||||
else{ found++; }
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
vendor=new byte[vendorlen+1];
|
||||
opb.read(vendor,vendorlen);
|
||||
comments=opb.read(32);
|
||||
if(comments<0)
|
||||
|
||||
internal int unpack(csBuffer opb)
|
||||
{
|
||||
//goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
user_comments=new byte[comments+1][];
|
||||
comment_lengths=new int[comments+1];
|
||||
|
||||
for(int i=0;i<comments;i++)
|
||||
{
|
||||
int len=opb.read(32);
|
||||
if(len<0)
|
||||
int vendorlen=opb.read(32);
|
||||
if(vendorlen<0)
|
||||
{
|
||||
//goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
comment_lengths[i]=len;
|
||||
user_comments[i]=new byte[len+1];
|
||||
opb.read(user_comments[i], len);
|
||||
}
|
||||
if(opb.read(1)!=1)
|
||||
{
|
||||
//goto err_out; // EOP check
|
||||
clear();
|
||||
return(-1);
|
||||
|
||||
}
|
||||
return(0);
|
||||
// err_out:
|
||||
// comment_clear(vc);
|
||||
// return(-1);
|
||||
}
|
||||
|
||||
int pack(Buffer opb)
|
||||
{
|
||||
byte[] temp="Xiphophorus libVorbis I 20000508".getBytes();
|
||||
|
||||
// preamble
|
||||
opb.write(0x03,8);
|
||||
opb.write(_vorbis);
|
||||
|
||||
// vendor
|
||||
opb.write(temp.length,32);
|
||||
opb.write(temp);
|
||||
|
||||
// comments
|
||||
|
||||
opb.write(comments,32);
|
||||
if(comments!=0)
|
||||
{
|
||||
vendor=new byte[vendorlen+1];
|
||||
opb.read(vendor,vendorlen);
|
||||
comments=opb.read(32);
|
||||
if(comments<0)
|
||||
{
|
||||
//goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
user_comments=new byte[comments+1][];
|
||||
comment_lengths=new int[comments+1];
|
||||
|
||||
for(int i=0;i<comments;i++)
|
||||
{
|
||||
if(user_comments[i]!=null)
|
||||
int len=opb.read(32);
|
||||
if(len<0)
|
||||
{
|
||||
opb.write(comment_lengths[i],32);
|
||||
opb.write(user_comments[i]);
|
||||
//goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
else
|
||||
comment_lengths[i]=len;
|
||||
user_comments[i]=new byte[len+1];
|
||||
opb.read(user_comments[i], len);
|
||||
}
|
||||
if(opb.read(1)!=1)
|
||||
{
|
||||
//goto err_out; // EOP check
|
||||
clear();
|
||||
return(-1);
|
||||
|
||||
}
|
||||
return(0);
|
||||
// err_out:
|
||||
// comment_clear(vc);
|
||||
// return(-1);
|
||||
}
|
||||
|
||||
int pack(csBuffer opb)
|
||||
{
|
||||
String temp="Xiphophorus libVorbis I 20000508";
|
||||
|
||||
ASCIIEncoding AE = new ASCIIEncoding();
|
||||
byte[] temp_byt = AE.GetBytes(temp);
|
||||
byte[] _vorbis_byt = AE.GetBytes(_vorbis);
|
||||
|
||||
// preamble
|
||||
opb.write(0x03,8);
|
||||
opb.write(_vorbis_byt);
|
||||
|
||||
// vendor
|
||||
opb.write(temp.Length,32);
|
||||
opb.write(temp_byt);
|
||||
|
||||
// comments
|
||||
|
||||
opb.write(comments,32);
|
||||
if(comments!=0)
|
||||
{
|
||||
for(int i=0;i<comments;i++)
|
||||
{
|
||||
opb.write(0,32);
|
||||
if(user_comments[i]!=null)
|
||||
{
|
||||
opb.write(comment_lengths[i],32);
|
||||
opb.write(user_comments[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
opb.write(0,32);
|
||||
}
|
||||
}
|
||||
}
|
||||
opb.write(1,1);
|
||||
return(0);
|
||||
}
|
||||
opb.write(1,1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
public int header_out(Packet op)
|
||||
{
|
||||
Buffer opb=new Buffer();
|
||||
opb.writeinit();
|
||||
|
||||
if(pack(opb)!=0) return OV_EIMPL;
|
||||
|
||||
op.packet_base = new byte[opb.bytes()];
|
||||
op.packet=0;
|
||||
op.bytes=opb.bytes();
|
||||
System.arraycopy(opb.buffer(), 0, op.packet_base, 0, op.bytes);
|
||||
op.b_o_s=0;
|
||||
op.e_o_s=0;
|
||||
op.granulepos=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
for(int i=0;i<comments;i++)
|
||||
user_comments[i]=null;
|
||||
user_comments=null;
|
||||
vendor=null;
|
||||
}
|
||||
|
||||
public String getVendor()
|
||||
{
|
||||
return new String(vendor, 0, vendor.length-1);
|
||||
}
|
||||
public String getComment(int i)
|
||||
{
|
||||
if(comments<=i)return null;
|
||||
return new String(user_comments[i], 0, user_comments[i].length-1);
|
||||
}
|
||||
public String toString()
|
||||
{
|
||||
String foo="Vendor: "+new String(vendor, 0, vendor.length-1);
|
||||
for(int i=0; i<comments; i++)
|
||||
public int header_out(Packet op)
|
||||
{
|
||||
foo=foo+"\nComment: "+new String(user_comments[i], 0, user_comments[i].length-1);
|
||||
csBuffer opb=new csBuffer();
|
||||
opb.writeinit();
|
||||
|
||||
if(pack(opb)!=0) return OV_EIMPL;
|
||||
|
||||
op.packet_base = new byte[opb.bytes()];
|
||||
op.packet=0;
|
||||
op.bytes=opb.bytes();
|
||||
Array.Copy(opb.buf(), 0, op.packet_base, 0, op.bytes);
|
||||
op.b_o_s=0;
|
||||
op.e_o_s=0;
|
||||
op.granulepos=0;
|
||||
return 0;
|
||||
}
|
||||
foo=foo+"\n";
|
||||
return foo;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
for(int i=0;i<comments;i++)
|
||||
user_comments[i]=null;
|
||||
user_comments=null;
|
||||
vendor=null;
|
||||
}
|
||||
|
||||
public String getVendor()
|
||||
{
|
||||
//TODO
|
||||
//return new String(vendor.ToString(), 0, vendor.Length-1);
|
||||
return "The Labs";
|
||||
}
|
||||
public String getComment(int i)
|
||||
{
|
||||
if(comments<=i)return null;
|
||||
//TODO
|
||||
//Encoding asc = Encoding.ASCII;
|
||||
//return new String(user_comments[i], 0, user_comments[i].Length-1, asc);
|
||||
return "There is no spoon.";
|
||||
}
|
||||
public String toString()
|
||||
{
|
||||
//TODO
|
||||
//String foo="Vendor: "+new String(vendor.ToString(), 0, vendor.Length-1);
|
||||
//for(int i=0; i<comments; i++)
|
||||
//{
|
||||
// foo=foo+"\nComment: "+new String(user_comments[i].ToString(), 0, user_comments[i].Length-1);
|
||||
//}
|
||||
//foo=foo+"\n";
|
||||
//return foo;
|
||||
return "Blah\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
2737
csvorbis/Drft.cs
2737
csvorbis/Drft.cs
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -25,471 +25,422 @@
|
|||
|
||||
using System;
|
||||
using csogg;
|
||||
using csvorbis;
|
||||
|
||||
public class DspState
|
||||
namespace csvorbis
|
||||
{
|
||||
static float M_PI=3.1415926539f;
|
||||
static int VI_TRANSFORMB=1;
|
||||
static int VI_WINDOWB=1;
|
||||
|
||||
int analysisp;
|
||||
Info vi;
|
||||
int modebits;
|
||||
|
||||
float[][] pcm;
|
||||
//float[][] pcmret;
|
||||
int pcm_storage;
|
||||
int pcm_current;
|
||||
int pcm_returned;
|
||||
|
||||
float[] multipliers;
|
||||
int envelope_storage;
|
||||
int envelope_current;
|
||||
|
||||
int eofflag;
|
||||
|
||||
int lW;
|
||||
int W;
|
||||
int nW;
|
||||
int centerW;
|
||||
|
||||
long granulepos;
|
||||
long sequence;
|
||||
|
||||
long glue_bits;
|
||||
long time_bits;
|
||||
long floor_bits;
|
||||
long res_bits;
|
||||
|
||||
// local lookup storage
|
||||
//!! Envelope ve=new Envelope(); // envelope
|
||||
//float **window[2][2][2]; // block, leadin, leadout, type
|
||||
float[][][][][] wnd; // block, leadin, leadout, type
|
||||
//vorbis_look_transform **transform[2]; // block, type
|
||||
Object[][] transform;
|
||||
CodeBook[] fullbooks;
|
||||
// backend lookups are tied to the mode, not the backend or naked mapping
|
||||
Object[] mode;
|
||||
|
||||
// local storage, only used on the encoding side. This way the
|
||||
// application does not need to worry about freeing some packets'
|
||||
// memory and not others'; packet storage is always tracked.
|
||||
// Cleared next call to a _dsp_ function
|
||||
byte[] header;
|
||||
byte[] header1;
|
||||
byte[] header2;
|
||||
|
||||
public DspState()
|
||||
public class DspState
|
||||
{
|
||||
transform=new Object[2][];
|
||||
wnd=new float[2][][][][];
|
||||
wnd[0]=new float[2][][][];
|
||||
wnd[0][0]=new float[2][][];
|
||||
wnd[0][1]=new float[2][][];
|
||||
wnd[0][0][0]=new float[2][];
|
||||
wnd[0][0][1]=new float[2][];
|
||||
wnd[0][1][0]=new float[2][];
|
||||
wnd[0][1][1]=new float[2][];
|
||||
wnd[1]=new float[2][][][];
|
||||
wnd[1][0]=new float[2][][];
|
||||
wnd[1][1]=new float[2][][];
|
||||
wnd[1][0][0]=new float[2][];
|
||||
wnd[1][0][1]=new float[2][];
|
||||
wnd[1][1][0]=new float[2][];
|
||||
wnd[1][1][1]=new float[2][];
|
||||
}
|
||||
static float M_PI=3.1415926539f;
|
||||
static int VI_TRANSFORMB=1;
|
||||
static int VI_WINDOWB=1;
|
||||
|
||||
private static int ilog2(int v)
|
||||
{
|
||||
int ret=0;
|
||||
while(v>1)
|
||||
internal int analysisp;
|
||||
internal Info vi;
|
||||
internal int modebits;
|
||||
|
||||
float[][] pcm;
|
||||
//float[][] pcmret;
|
||||
int pcm_storage;
|
||||
int pcm_current;
|
||||
int pcm_returned;
|
||||
|
||||
float[] multipliers;
|
||||
int envelope_storage;
|
||||
int envelope_current;
|
||||
|
||||
int eofflag;
|
||||
|
||||
int lW;
|
||||
int W;
|
||||
int nW;
|
||||
int centerW;
|
||||
|
||||
long granulepos;
|
||||
public long sequence;
|
||||
|
||||
long glue_bits;
|
||||
long time_bits;
|
||||
long floor_bits;
|
||||
long res_bits;
|
||||
|
||||
// local lookup storage
|
||||
//!! Envelope ve=new Envelope(); // envelope
|
||||
//float **window[2][2][2]; // block, leadin, leadout, type
|
||||
internal float[][][][][] wnd; // block, leadin, leadout, type
|
||||
//vorbis_look_transform **transform[2]; // block, type
|
||||
internal Object[][] transform;
|
||||
internal CodeBook[] fullbooks;
|
||||
// backend lookups are tied to the mode, not the backend or naked mapping
|
||||
internal Object[] mode;
|
||||
|
||||
// local storage, only used on the encoding side. This way the
|
||||
// application does not need to worry about freeing some packets'
|
||||
// memory and not others'; packet storage is always tracked.
|
||||
// Cleared next call to a _dsp_ function
|
||||
byte[] header;
|
||||
byte[] header1;
|
||||
byte[] header2;
|
||||
|
||||
public DspState()
|
||||
{
|
||||
ret++;
|
||||
(uint)v >>= 1;
|
||||
transform=new Object[2][];
|
||||
wnd=new float[2][][][][];
|
||||
wnd[0]=new float[2][][][];
|
||||
wnd[0][0]=new float[2][][];
|
||||
wnd[0][1]=new float[2][][];
|
||||
wnd[0][0][0]=new float[2][];
|
||||
wnd[0][0][1]=new float[2][];
|
||||
wnd[0][1][0]=new float[2][];
|
||||
wnd[0][1][1]=new float[2][];
|
||||
wnd[1]=new float[2][][][];
|
||||
wnd[1][0]=new float[2][][];
|
||||
wnd[1][1]=new float[2][][];
|
||||
wnd[1][0][0]=new float[2][];
|
||||
wnd[1][0][1]=new float[2][];
|
||||
wnd[1][1][0]=new float[2][];
|
||||
wnd[1][1][1]=new float[2][];
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static float[] window(int type, int wnd, int left, int right)
|
||||
{
|
||||
float[] ret=new float[wnd];
|
||||
switch(type)
|
||||
private static int ilog2(int v)
|
||||
{
|
||||
case 0:
|
||||
// The 'vorbis window' (window 0) is sin(sin(x)*sin(x)*2pi)
|
||||
int ret=0;
|
||||
while(v>1)
|
||||
{
|
||||
int leftbegin=wnd/4-left/2;
|
||||
int rightbegin=wnd-wnd/4-right/2;
|
||||
ret++;
|
||||
v = (int)((uint)v >> 1);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
internal static float[] window(int type, int wnd, int left, int right)
|
||||
{
|
||||
float[] ret=new float[wnd];
|
||||
switch(type)
|
||||
{
|
||||
case 0:
|
||||
// The 'vorbis window' (window 0) is sin(sin(x)*sin(x)*2pi)
|
||||
{
|
||||
int leftbegin=wnd/4-left/2;
|
||||
int rightbegin=wnd-wnd/4-right/2;
|
||||
|
||||
for(int i=0;i<left;i++)
|
||||
{
|
||||
float x=(float)((i+.5)/left*M_PI/2.0);
|
||||
x=(float)Math.sin(x);
|
||||
x*=x;
|
||||
x*=M_PI/2.0;
|
||||
x=(float)Math.sin(x);
|
||||
ret[i+leftbegin]=x;
|
||||
}
|
||||
for(int i=0;i<left;i++)
|
||||
{
|
||||
float x=(float)((i+.5)/left*M_PI/2.0);
|
||||
x=(float)Math.Sin(x);
|
||||
x*=x;
|
||||
x*=(float)(M_PI/2.0);
|
||||
x=(float)Math.Sin(x);
|
||||
ret[i+leftbegin]=x;
|
||||
}
|
||||
|
||||
for(int i=leftbegin+left;i<rightbegin;i++)
|
||||
{
|
||||
ret[i]=1.f;
|
||||
}
|
||||
for(int i=leftbegin+left;i<rightbegin;i++)
|
||||
{
|
||||
ret[i]=1.0f;
|
||||
}
|
||||
|
||||
for(int i=0;i<right;i++)
|
||||
{
|
||||
float x=(float)((right-i-.5)/right*M_PI/2.0);
|
||||
x=(float)Math.sin(x);
|
||||
x*=x;
|
||||
x*=M_PI/2.0;
|
||||
x=(float)Math.sin(x);
|
||||
ret[i+rightbegin]=x;
|
||||
for(int i=0;i<right;i++)
|
||||
{
|
||||
float x=(float)((right-i-.5)/right*M_PI/2.0);
|
||||
x=(float)Math.Sin(x);
|
||||
x*=x;
|
||||
x*=(float)(M_PI/2.0);
|
||||
x=(float)Math.Sin(x);
|
||||
ret[i+rightbegin]=x;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//free(ret);
|
||||
return(null);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//free(ret);
|
||||
return(null);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
// Analysis side code, but directly related to blocking. Thus it's
|
||||
// here and not in analysis.c (which is for analysis transforms only).
|
||||
// The init is here because some of it is shared
|
||||
|
||||
int init(Info vi, int encp)
|
||||
{
|
||||
//System.err.println("DspState.init: vi="+vi+", encp="+encp);
|
||||
//memset(v,0,sizeof(vorbis_dsp_state));
|
||||
this.vi=vi;
|
||||
modebits=ilog2(vi.modes);
|
||||
|
||||
transform[0]=new Object[VI_TRANSFORMB];
|
||||
transform[1]=new Object[VI_TRANSFORMB];
|
||||
|
||||
// MDCT is tranform 0
|
||||
|
||||
transform[0][0]=new Mdct();
|
||||
transform[1][0]=new Mdct();
|
||||
((Mdct)transform[0][0]).init(vi.blocksizes[0]);
|
||||
((Mdct)transform[1][0]).init(vi.blocksizes[1]);
|
||||
|
||||
wnd[0][0][0]=new float[VI_WINDOWB][];
|
||||
wnd[0][0][1]=wnd[0][0][0];
|
||||
wnd[0][1][0]=wnd[0][0][0];
|
||||
wnd[0][1][1]=wnd[0][0][0];
|
||||
wnd[1][0][0]=new float[VI_WINDOWB][];
|
||||
wnd[1][0][1]=new float[VI_WINDOWB][];
|
||||
wnd[1][1][0]=new float[VI_WINDOWB][];
|
||||
wnd[1][1][1]=new float[VI_WINDOWB][];
|
||||
|
||||
for(int i=0;i<VI_WINDOWB;i++)
|
||||
{
|
||||
wnd[0][0][0][i]=
|
||||
wnd(i,vi.blocksizes[0],vi.blocksizes[0]/2,vi.blocksizes[0]/2);
|
||||
wnd[1][0][0][i]=
|
||||
wnd(i,vi.blocksizes[1],vi.blocksizes[0]/2,vi.blocksizes[0]/2);
|
||||
wnd[1][0][1][i]=
|
||||
wnd(i,vi.blocksizes[1],vi.blocksizes[0]/2,vi.blocksizes[1]/2);
|
||||
wnd[1][1][0][i]=
|
||||
wnd(i,vi.blocksizes[1],vi.blocksizes[1]/2,vi.blocksizes[0]/2);
|
||||
wnd[1][1][1][i]=
|
||||
wnd(i,vi.blocksizes[1],vi.blocksizes[1]/2,vi.blocksizes[1]/2);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
// if(encp){ // encode/decode differ here
|
||||
// // finish the codebooks
|
||||
// fullbooks=new CodeBook[vi.books];
|
||||
// for(int i=0;i<vi.books;i++){
|
||||
// fullbooks[i]=new CodeBook();
|
||||
// fullbooks[i].init_encode(vi.book_param[i]);
|
||||
// }
|
||||
// analysisp=1;
|
||||
// }
|
||||
// else{
|
||||
// finish the codebooks
|
||||
fullbooks=new CodeBook[vi.books];
|
||||
for(int i=0;i<vi.books;i++)
|
||||
// Analysis side code, but directly related to blocking. Thus it's
|
||||
// here and not in analysis.c (which is for analysis transforms only).
|
||||
// The init is here because some of it is shared
|
||||
|
||||
int init(Info vi, bool encp)
|
||||
{
|
||||
fullbooks[i]=new CodeBook();
|
||||
fullbooks[i].init_decode(vi.book_param[i]);
|
||||
}
|
||||
// }
|
||||
Console.Error.WriteLine("DspState.init: vi="+vi+", encp="+encp);
|
||||
//memset(v,0,sizeof(vorbis_dsp_state));
|
||||
this.vi=vi;
|
||||
modebits=ilog2(vi.modes);
|
||||
|
||||
// initialize the storage vectors to a decent size greater than the
|
||||
// minimum
|
||||
|
||||
pcm_storage=8192; // we'll assume later that we have
|
||||
// a minimum of twice the blocksize of
|
||||
// accumulated samples in analysis
|
||||
pcm=new float[vi.channels][];
|
||||
//pcmret=new float[vi.channels][];
|
||||
{
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
{
|
||||
pcm[i]=new float[pcm_storage];
|
||||
}
|
||||
}
|
||||
transform[0]=new Object[VI_TRANSFORMB];
|
||||
transform[1]=new Object[VI_TRANSFORMB];
|
||||
|
||||
// all 1 (large block) or 0 (small block)
|
||||
// explicitly set for the sake of clarity
|
||||
lW=0; // previous window size
|
||||
W=0; // current window size
|
||||
// MDCT is tranform 0
|
||||
|
||||
// all vector indexes; multiples of samples_per_envelope_step
|
||||
centerW=vi.blocksizes[1]/2;
|
||||
transform[0][0]=new Mdct();
|
||||
transform[1][0]=new Mdct();
|
||||
((Mdct)transform[0][0]).init(vi.blocksizes[0]);
|
||||
((Mdct)transform[1][0]).init(vi.blocksizes[1]);
|
||||
|
||||
pcm_current=centerW;
|
||||
wnd[0][0][0]=new float[VI_WINDOWB][];
|
||||
wnd[0][0][1]=wnd[0][0][0];
|
||||
wnd[0][1][0]=wnd[0][0][0];
|
||||
wnd[0][1][1]=wnd[0][0][0];
|
||||
wnd[1][0][0]=new float[VI_WINDOWB][];
|
||||
wnd[1][0][1]=new float[VI_WINDOWB][];
|
||||
wnd[1][1][0]=new float[VI_WINDOWB][];
|
||||
wnd[1][1][1]=new float[VI_WINDOWB][];
|
||||
|
||||
// initialize all the mapping/backend lookups
|
||||
mode=new Object[vi.modes];
|
||||
for(int i=0;i<vi.modes;i++)
|
||||
{
|
||||
int mapnum=vi.mode_param[i].mapping;
|
||||
int maptype=vi.map_type[mapnum];
|
||||
mode[i]=FuncMapping.mapping_P[maptype].look(this,vi.mode_param[i],
|
||||
vi.map_param[mapnum]);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
public int synthesis_init(Info vi)
|
||||
{
|
||||
init(vi, false);
|
||||
// Adjust centerW to allow an easier mechanism for determining output
|
||||
pcm_returned=centerW;
|
||||
centerW-= vi.blocksizes[W]/4+vi.blocksizes[lW]/4;
|
||||
granulepos=-1;
|
||||
sequence=-1;
|
||||
return(0);
|
||||
}
|
||||
|
||||
DspState(Info vi) : this()
|
||||
{
|
||||
init(vi, false);
|
||||
// Adjust centerW to allow an easier mechanism for determining output
|
||||
pcm_returned=centerW;
|
||||
centerW-= vi.blocksizes[W]/4+vi.blocksizes[lW]/4;
|
||||
granulepos=-1;
|
||||
sequence=-1;
|
||||
}
|
||||
|
||||
// Unike in analysis, the window is only partially applied for each
|
||||
// block. The time domain envelope is not yet handled at the point of
|
||||
// calling (as it relies on the previous block).
|
||||
|
||||
public int synthesis_blockin(Block vb)
|
||||
{
|
||||
// Shift out any PCM/multipliers that we returned previously
|
||||
// centerW is currently the center of the last block added
|
||||
if(centerW>vi.blocksizes[1]/2 && pcm_returned>8192)
|
||||
{
|
||||
// don't shift too much; we need to have a minimum PCM buffer of
|
||||
// 1/2 long block
|
||||
|
||||
int shiftPCM=centerW-vi.blocksizes[1]/2;
|
||||
shiftPCM=(pcm_returned<shiftPCM?pcm_returned:shiftPCM);
|
||||
|
||||
pcm_current-=shiftPCM;
|
||||
centerW-=shiftPCM;
|
||||
pcm_returned-=shiftPCM;
|
||||
if(shiftPCM!=0)
|
||||
for(int i=0;i<VI_WINDOWB;i++)
|
||||
{
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
{
|
||||
System.arraycopy(pcm[i], shiftPCM, pcm[i], 0, pcm_current);
|
||||
}
|
||||
wnd[0][0][0][i]=
|
||||
window(i,vi.blocksizes[0],vi.blocksizes[0]/2,vi.blocksizes[0]/2);
|
||||
wnd[1][0][0][i]=
|
||||
window(i,vi.blocksizes[1],vi.blocksizes[0]/2,vi.blocksizes[0]/2);
|
||||
wnd[1][0][1][i]=
|
||||
window(i,vi.blocksizes[1],vi.blocksizes[0]/2,vi.blocksizes[1]/2);
|
||||
wnd[1][1][0][i]=
|
||||
window(i,vi.blocksizes[1],vi.blocksizes[1]/2,vi.blocksizes[0]/2);
|
||||
wnd[1][1][1][i]=
|
||||
window(i,vi.blocksizes[1],vi.blocksizes[1]/2,vi.blocksizes[1]/2);
|
||||
}
|
||||
}
|
||||
|
||||
lW=W;
|
||||
W=vb.W;
|
||||
nW=-1;
|
||||
// if(encp){ // encode/decode differ here
|
||||
// // finish the codebooks
|
||||
// fullbooks=new CodeBook[vi.books];
|
||||
// for(int i=0;i<vi.books;i++){
|
||||
// fullbooks[i]=new CodeBook();
|
||||
// fullbooks[i].init_encode(vi.book_param[i]);
|
||||
// }
|
||||
// analysisp=1;
|
||||
// }
|
||||
// else{
|
||||
// finish the codebooks
|
||||
fullbooks=new CodeBook[vi.books];
|
||||
for(int i=0;i<vi.books;i++)
|
||||
{
|
||||
fullbooks[i]=new CodeBook();
|
||||
fullbooks[i].init_decode(vi.book_param[i]);
|
||||
}
|
||||
Console.Error.WriteLine("fullbooks done");
|
||||
// }
|
||||
|
||||
glue_bits+=vb.glue_bits;
|
||||
time_bits+=vb.time_bits;
|
||||
floor_bits+=vb.floor_bits;
|
||||
res_bits+=vb.res_bits;
|
||||
|
||||
if(sequence+1 != vb.sequence)granulepos=-1; // out of sequence; lose count
|
||||
|
||||
sequence=vb.sequence;
|
||||
|
||||
{
|
||||
int sizeW=vi.blocksizes[W];
|
||||
int _centerW=centerW+vi.blocksizes[lW]/4+sizeW/4;
|
||||
int beginW=_centerW-sizeW/2;
|
||||
int endW=beginW+sizeW;
|
||||
int beginSl=0;
|
||||
int endSl=0;
|
||||
|
||||
// Do we have enough PCM/mult storage for the block?
|
||||
if(endW>pcm_storage)
|
||||
// initialize the storage vectors to a decent size greater than the
|
||||
// minimum
|
||||
|
||||
pcm_storage=8192; // we'll assume later that we have
|
||||
// a minimum of twice the blocksize of
|
||||
// accumulated samples in analysis
|
||||
pcm=new float[vi.channels][];
|
||||
//pcmret=new float[vi.channels][];
|
||||
{
|
||||
// expand the storage
|
||||
pcm_storage=endW+vi.blocksizes[1];
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
{
|
||||
float[] foo=new float[pcm_storage];
|
||||
System.arraycopy(pcm[i], 0, foo, 0, pcm[i].length);
|
||||
pcm[i]=foo;
|
||||
pcm[i]=new float[pcm_storage];
|
||||
}
|
||||
}
|
||||
|
||||
// overlap/add PCM
|
||||
switch(W)
|
||||
{
|
||||
case 0:
|
||||
beginSl=0;
|
||||
endSl=vi.blocksizes[0]/2;
|
||||
break;
|
||||
case 1:
|
||||
beginSl=vi.blocksizes[1]/4-vi.blocksizes[lW]/4;
|
||||
endSl=beginSl+vi.blocksizes[lW]/2;
|
||||
break;
|
||||
}
|
||||
// all 1 (large block) or 0 (small block)
|
||||
// explicitly set for the sake of clarity
|
||||
lW=0; // previous window size
|
||||
W=0; // current window size
|
||||
|
||||
for(int j=0;j<vi.channels;j++)
|
||||
{
|
||||
int _pcm=beginW;
|
||||
// the overlap/add section
|
||||
int i=0;
|
||||
for(i=beginSl;i<endSl;i++)
|
||||
// all vector indexes; multiples of samples_per_envelope_step
|
||||
centerW=vi.blocksizes[1]/2;
|
||||
|
||||
pcm_current=centerW;
|
||||
|
||||
// initialize all the mapping/backend lookups
|
||||
mode=new Object[vi.modes];
|
||||
Console.Error.WriteLine("vi.modes: "+vi.modes);
|
||||
for(int i=0;i<vi.modes;i++)
|
||||
{
|
||||
pcm[j][_pcm+i]+=vb.pcm[j][i];
|
||||
}
|
||||
// the remaining section
|
||||
for(;i<sizeW;i++)
|
||||
{
|
||||
pcm[j][_pcm+i]=vb.pcm[j][i];
|
||||
int mapnum=vi.mode_param[i].mapping;
|
||||
int maptype=vi.map_type[mapnum];
|
||||
Console.Error.WriteLine("Entering mapping.");
|
||||
mode[i]=FuncMapping.mapping_P[maptype].look(this,vi.mode_param[i],
|
||||
vi.map_param[mapnum]);
|
||||
Console.Error.WriteLine("Done Mapping");
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
// track the frame number... This is for convenience, but also
|
||||
// making sure our last packet doesn't end with added padding. If
|
||||
// the last packet is partial, the number of samples we'll have to
|
||||
// return will be past the vb->granulepos.
|
||||
//
|
||||
// This is not foolproof! It will be confused if we begin
|
||||
// decoding at the last page after a seek or hole. In that case,
|
||||
// we don't have a starting point to judge where the last frame
|
||||
// is. For this reason, vorbisfile will always try to make sure
|
||||
// it reads the last two marked pages in proper sequence
|
||||
|
||||
if(granulepos==-1)
|
||||
public int synthesis_init(Info vi)
|
||||
{
|
||||
granulepos=vb.granulepos;
|
||||
init(vi, false);
|
||||
// Adjust centerW to allow an easier mechanism for determining output
|
||||
pcm_returned=centerW;
|
||||
centerW-= vi.blocksizes[W]/4+vi.blocksizes[lW]/4;
|
||||
granulepos=-1;
|
||||
sequence=-1;
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
|
||||
DspState(Info vi) : this()
|
||||
{
|
||||
granulepos+=(_centerW-centerW);
|
||||
if(vb.granulepos!=-1 && granulepos!=vb.granulepos)
|
||||
init(vi, false);
|
||||
// Adjust centerW to allow an easier mechanism for determining output
|
||||
pcm_returned=centerW;
|
||||
centerW-= vi.blocksizes[W]/4+vi.blocksizes[lW]/4;
|
||||
granulepos=-1;
|
||||
sequence=-1;
|
||||
}
|
||||
|
||||
// Unike in analysis, the window is only partially applied for each
|
||||
// block. The time domain envelope is not yet handled at the point of
|
||||
// calling (as it relies on the previous block).
|
||||
|
||||
public int synthesis_blockin(Block vb)
|
||||
{
|
||||
// Shift out any PCM/multipliers that we returned previously
|
||||
// centerW is currently the center of the last block added
|
||||
if(centerW>vi.blocksizes[1]/2 && pcm_returned>8192)
|
||||
{
|
||||
if(granulepos>vb.granulepos && vb.eofflag!=0)
|
||||
// don't shift too much; we need to have a minimum PCM buffer of
|
||||
// 1/2 long block
|
||||
|
||||
int shiftPCM=centerW-vi.blocksizes[1]/2;
|
||||
shiftPCM=(pcm_returned<shiftPCM?pcm_returned:shiftPCM);
|
||||
|
||||
pcm_current-=shiftPCM;
|
||||
centerW-=shiftPCM;
|
||||
pcm_returned-=shiftPCM;
|
||||
if(shiftPCM!=0)
|
||||
{
|
||||
// partial last frame. Strip the padding off
|
||||
_centerW-=(granulepos-vb.granulepos);
|
||||
}// else{ Shouldn't happen *unless* the bitstream is out of
|
||||
// spec. Either way, believe the bitstream }
|
||||
granulepos=vb.granulepos;
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
{
|
||||
Array.Copy(pcm[i], shiftPCM, pcm[i], 0, pcm_current);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update, cleanup
|
||||
lW=W;
|
||||
W=vb.W;
|
||||
nW=-1;
|
||||
|
||||
centerW=_centerW;
|
||||
pcm_current=endW;
|
||||
if(vb.eofflag!=0)eofflag=1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
glue_bits+=vb.glue_bits;
|
||||
time_bits+=vb.time_bits;
|
||||
floor_bits+=vb.floor_bits;
|
||||
res_bits+=vb.res_bits;
|
||||
|
||||
if(sequence+1 != vb.sequence)granulepos=-1; // out of sequence; lose count
|
||||
|
||||
sequence=vb.sequence;
|
||||
|
||||
// pcm==NULL indicates we just want the pending samples, no more
|
||||
public int synthesis_pcmout(float[][][] _pcm, int[] index)
|
||||
{
|
||||
if(pcm_returned<centerW)
|
||||
{
|
||||
if(_pcm!=null)
|
||||
int sizeW=vi.blocksizes[W];
|
||||
int _centerW=centerW+vi.blocksizes[lW]/4+sizeW/4;
|
||||
int beginW=_centerW-sizeW/2;
|
||||
int endW=beginW+sizeW;
|
||||
int beginSl=0;
|
||||
int endSl=0;
|
||||
|
||||
// Do we have enough PCM/mult storage for the block?
|
||||
if(endW>pcm_storage)
|
||||
{
|
||||
// expand the storage
|
||||
pcm_storage=endW+vi.blocksizes[1];
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
{
|
||||
// pcmret[i]=pcm[i]+v.pcm_returned;
|
||||
//!!!!!!!!
|
||||
index[i]=pcm_returned;
|
||||
float[] foo=new float[pcm_storage];
|
||||
Array.Copy(pcm[i], 0, foo, 0, pcm[i].Length);
|
||||
pcm[i]=foo;
|
||||
}
|
||||
_pcm[0]=pcm;
|
||||
}
|
||||
return(centerW-pcm_returned);
|
||||
|
||||
// overlap/add PCM
|
||||
switch(W)
|
||||
{
|
||||
case 0:
|
||||
beginSl=0;
|
||||
endSl=vi.blocksizes[0]/2;
|
||||
break;
|
||||
case 1:
|
||||
beginSl=vi.blocksizes[1]/4-vi.blocksizes[lW]/4;
|
||||
endSl=beginSl+vi.blocksizes[lW]/2;
|
||||
break;
|
||||
}
|
||||
|
||||
for(int j=0;j<vi.channels;j++)
|
||||
{
|
||||
int _pcm=beginW;
|
||||
// the overlap/add section
|
||||
int i=0;
|
||||
for(i=beginSl;i<endSl;i++)
|
||||
{
|
||||
pcm[j][_pcm+i]+=vb.pcm[j][i];
|
||||
}
|
||||
// the remaining section
|
||||
for(;i<sizeW;i++)
|
||||
{
|
||||
pcm[j][_pcm+i]=vb.pcm[j][i];
|
||||
}
|
||||
}
|
||||
|
||||
// track the frame number... This is for convenience, but also
|
||||
// making sure our last packet doesn't end with added padding. If
|
||||
// the last packet is partial, the number of samples we'll have to
|
||||
// return will be past the vb->granulepos.
|
||||
//
|
||||
// This is not foolproof! It will be confused if we begin
|
||||
// decoding at the last page after a seek or hole. In that case,
|
||||
// we don't have a starting point to judge where the last frame
|
||||
// is. For this reason, vorbisfile will always try to make sure
|
||||
// it reads the last two marked pages in proper sequence
|
||||
|
||||
if(granulepos==-1)
|
||||
{
|
||||
granulepos=vb.granulepos;
|
||||
}
|
||||
else
|
||||
{
|
||||
granulepos+=(_centerW-centerW);
|
||||
if(vb.granulepos!=-1 && granulepos!=vb.granulepos)
|
||||
{
|
||||
if(granulepos>vb.granulepos && vb.eofflag!=0)
|
||||
{
|
||||
// partial last frame. Strip the padding off
|
||||
_centerW = _centerW - (int)(granulepos-vb.granulepos);
|
||||
}// else{ Shouldn't happen *unless* the bitstream is out of
|
||||
// spec. Either way, believe the bitstream }
|
||||
granulepos=vb.granulepos;
|
||||
}
|
||||
}
|
||||
|
||||
// Update, cleanup
|
||||
|
||||
centerW=_centerW;
|
||||
pcm_current=endW;
|
||||
if(vb.eofflag!=0)eofflag=1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
// pcm==NULL indicates we just want the pending samples, no more
|
||||
public int synthesis_pcmout(float[][][] _pcm, int[] index)
|
||||
{
|
||||
if(pcm_returned<centerW)
|
||||
{
|
||||
if(_pcm!=null)
|
||||
{
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
{
|
||||
// pcmret[i]=pcm[i]+v.pcm_returned;
|
||||
//!!!!!!!!
|
||||
index[i]=pcm_returned;
|
||||
}
|
||||
_pcm[0]=pcm;
|
||||
}
|
||||
return(centerW-pcm_returned);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
public int synthesis_read(int bytes)
|
||||
{
|
||||
if(bytes!=0 && pcm_returned+bytes>centerW)return(-1);
|
||||
pcm_returned+=bytes;
|
||||
return(0);
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
public int synthesis_read(int bytes)
|
||||
{
|
||||
if(bytes!=0 && pcm_returned+bytes>centerW)return(-1);
|
||||
pcm_returned+=bytes;
|
||||
return(0);
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
/*
|
||||
if(window[0][0][0]!=0){
|
||||
for(i=0;i<VI_WINDOWB;i++)
|
||||
if(v->window[0][0][0][i])free(v->window[0][0][0][i]);
|
||||
free(v->window[0][0][0]);
|
||||
|
||||
for(j=0;j<2;j++)
|
||||
for(k=0;k<2;k++){
|
||||
for(i=0;i<VI_WINDOWB;i++)
|
||||
if(v->window[1][j][k][i])free(v->window[1][j][k][i]);
|
||||
free(v->window[1][j][k]);
|
||||
}
|
||||
}
|
||||
|
||||
if(v->pcm){
|
||||
for(i=0;i<vi->channels;i++)
|
||||
if(v->pcm[i])free(v->pcm[i]);
|
||||
free(v->pcm);
|
||||
if(v->pcmret)free(v->pcmret);
|
||||
}
|
||||
if(v->multipliers)free(v->multipliers);
|
||||
|
||||
_ve_envelope_clear(&v->ve);
|
||||
if(v->transform[0]){
|
||||
mdct_clear(v->transform[0][0]);
|
||||
free(v->transform[0][0]);
|
||||
free(v->transform[0]);
|
||||
}
|
||||
if(v->transform[1]){
|
||||
mdct_clear(v->transform[1][0]);
|
||||
free(v->transform[1][0]);
|
||||
free(v->transform[1]);
|
||||
}
|
||||
|
||||
// free mode lookups; these are actually vorbis_look_mapping structs
|
||||
if(vi){
|
||||
for(i=0;i<vi->modes;i++){
|
||||
int mapnum=vi->mode_param[i]->mapping;
|
||||
int maptype=vi->map_type[mapnum];
|
||||
_mapping_P[maptype]->free_look(v->mode[i]);
|
||||
}
|
||||
// free codebooks
|
||||
for(i=0;i<vi->books;i++)
|
||||
vorbis_book_clear(v->fullbooks+i);
|
||||
}
|
||||
|
||||
if(v->mode)free(v->mode);
|
||||
if(v->fullbooks)free(v->fullbooks);
|
||||
|
||||
// free header, header1, header2
|
||||
if(v->header)free(v->header);
|
||||
if(v->header1)free(v->header1);
|
||||
if(v->header2)free(v->header2);
|
||||
|
||||
memset(v,0,sizeof(vorbis_dsp_state));
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,12 +25,16 @@
|
|||
|
||||
using System;
|
||||
|
||||
class EncodeAuxNearestMatch{
|
||||
int[] ptr0;
|
||||
int[] ptr1;
|
||||
namespace csvorbis
|
||||
{
|
||||
class EncodeAuxNearestMatch
|
||||
{
|
||||
internal int[] ptr0;
|
||||
internal int[] ptr1;
|
||||
|
||||
int[] p; // decision points (each is an entry)
|
||||
int[] q; // decision points (each is an entry)
|
||||
int aux; // number of tree entries
|
||||
int alloc;
|
||||
internal int[] p; // decision points (each is an entry)
|
||||
internal int[] q; // decision points (each is an entry)
|
||||
internal int aux; // number of tree entries
|
||||
internal int alloc;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,9 +25,13 @@
|
|||
|
||||
using System;
|
||||
|
||||
class EncodeAuxThreshMatch{
|
||||
float[] quantthresh;
|
||||
int[] quantmap;
|
||||
int quantvals;
|
||||
int threshvals;
|
||||
}
|
||||
namespace csvorbis
|
||||
{
|
||||
class EncodeAuxThreshMatch
|
||||
{
|
||||
internal float[] quantthresh;
|
||||
internal int[] quantmap;
|
||||
internal int quantvals;
|
||||
internal int threshvals;
|
||||
}
|
||||
}
|
|
@ -26,370 +26,374 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
class Floor0 : FuncFloor
|
||||
namespace csvorbis
|
||||
{
|
||||
|
||||
void pack(Object i, Buffer opb)
|
||||
class Floor0 : FuncFloor
|
||||
{
|
||||
InfoFloor0 info=(InfoFloor0)i;
|
||||
opb.write(info.order,8);
|
||||
opb.write(info.rate,16);
|
||||
opb.write(info.barkmap,16);
|
||||
opb.write(info.ampbits,6);
|
||||
opb.write(info.ampdB,8);
|
||||
opb.write(info.numbooks-1,4);
|
||||
for(int j=0;j<info.numbooks;j++)
|
||||
opb.write(info.books[j],8);
|
||||
}
|
||||
|
||||
Object unpack(Info vi , Buffer opb)
|
||||
{
|
||||
InfoFloor0 info=new InfoFloor0();
|
||||
info.order=opb.read(8);
|
||||
info.rate=opb.read(16);
|
||||
info.barkmap=opb.read(16);
|
||||
info.ampbits=opb.read(6);
|
||||
info.ampdB=opb.read(8);
|
||||
info.numbooks=opb.read(4)+1;
|
||||
|
||||
if((info.order<1)||
|
||||
(info.rate<1)||
|
||||
(info.barkmap<1)||
|
||||
(info.numbooks<1))
|
||||
override public void pack(Object i, csBuffer opb)
|
||||
{
|
||||
//free_info(info);
|
||||
return(null);
|
||||
InfoFloor0 info=(InfoFloor0)i;
|
||||
opb.write(info.order,8);
|
||||
opb.write(info.rate,16);
|
||||
opb.write(info.barkmap,16);
|
||||
opb.write(info.ampbits,6);
|
||||
opb.write(info.ampdB,8);
|
||||
opb.write(info.numbooks-1,4);
|
||||
for(int j=0;j<info.numbooks;j++)
|
||||
opb.write(info.books[j],8);
|
||||
}
|
||||
|
||||
for(int j=0;j<info.numbooks;j++)
|
||||
override public Object unpack(Info vi , csBuffer opb)
|
||||
{
|
||||
info.books[j]=opb.read(8);
|
||||
if(info.books[j]<0 || info.books[j]>=vi.books)
|
||||
InfoFloor0 info=new InfoFloor0();
|
||||
info.order=opb.read(8);
|
||||
info.rate=opb.read(16);
|
||||
info.barkmap=opb.read(16);
|
||||
info.ampbits=opb.read(6);
|
||||
info.ampdB=opb.read(8);
|
||||
info.numbooks=opb.read(4)+1;
|
||||
|
||||
if((info.order<1)||
|
||||
(info.rate<1)||
|
||||
(info.barkmap<1)||
|
||||
(info.numbooks<1))
|
||||
{
|
||||
//free_info(info);
|
||||
return(null);
|
||||
}
|
||||
}
|
||||
return(info);
|
||||
// err_out:
|
||||
// free_info(info);
|
||||
// return(NULL);
|
||||
}
|
||||
Object look(DspState vd, InfoMode mi, Object i)
|
||||
{
|
||||
float scale;
|
||||
Info vi=vd.vi;
|
||||
InfoFloor0 info=(InfoFloor0)i;
|
||||
LookFloor0 look=new LookFloor0();
|
||||
look.m=info.order;
|
||||
look.n=vi.blocksizes[mi.blockflag]/2;
|
||||
look.ln=info.barkmap;
|
||||
look.vi=info;
|
||||
look.lpclook.init(look.ln,look.m);
|
||||
|
||||
// we choose a scaling constant so that:
|
||||
// floor(bark(rate/2-1)*C)=mapped-1
|
||||
// floor(bark(rate/2)*C)=mapped
|
||||
scale=look.ln/toBARK((float)(info.rate/2.0));
|
||||
|
||||
// the mapping from a linear scale to a smaller bark scale is
|
||||
// straightforward. We do *not* make sure that the linear mapping
|
||||
// does not skip bark-scale bins; the decoder simply skips them and
|
||||
// the encoder may do what it wishes in filling them. They're
|
||||
// necessary in some mapping combinations to keep the scale spacing
|
||||
// accurate
|
||||
look.linearmap=new int[look.n];
|
||||
for(int j=0;j<look.n;j++)
|
||||
{
|
||||
int val=(int)Math.floor(toBARK((float)((info.rate/2.0)/look.n*j))
|
||||
*scale); // bark numbers represent band edges
|
||||
if(val>=look.ln)val=look.ln; // guard against the approximation
|
||||
look.linearmap[j]=val;
|
||||
}
|
||||
return look;
|
||||
}
|
||||
|
||||
static float toBARK(float f)
|
||||
{
|
||||
return (float)(13.1*Math.atan(.00074*(f))+2.24*Math.atan((f)*(f)*1.85e-8)+1e-4*(f));
|
||||
}
|
||||
|
||||
Object state(Object i)
|
||||
{
|
||||
EchstateFloor0 state=new EchstateFloor0();
|
||||
InfoFloor0 info=(InfoFloor0)i;
|
||||
|
||||
// a safe size if usually too big (dim==1)
|
||||
state.codewords=new int[info.order];
|
||||
state.curve=new float[info.barkmap];
|
||||
state.frameno=-1;
|
||||
return(state);
|
||||
}
|
||||
override public void free_info(Object i){}
|
||||
override public void free_look(Object i){}
|
||||
override public void free_state(Object vs){}
|
||||
override public int forward(Block vb, Object i, float[] fin, float[] fout, Object vs){return 0;}
|
||||
|
||||
float[] lsp=null;
|
||||
int inverse(Block vb, Object i, float[] fout)
|
||||
{
|
||||
//System.err.println("Floor0.inverse "+i.getClass()+"]");
|
||||
LookFloor0 look=(LookFloor0)i;
|
||||
InfoFloor0 info=look.vi;
|
||||
int ampraw=vb.opb.read(info.ampbits);
|
||||
if(ampraw>0)
|
||||
{ // also handles the -1 out of data case
|
||||
int maxval=(1<<info.ampbits)-1;
|
||||
float amp=(float)ampraw/maxval*info.ampdB;
|
||||
int booknum=vb.opb.read(ilog(info.numbooks));
|
||||
|
||||
if(booknum!=-1 && booknum<info.numbooks)
|
||||
for(int j=0;j<info.numbooks;j++)
|
||||
{
|
||||
info.books[j]=opb.read(8);
|
||||
if(info.books[j]<0 || info.books[j]>=vi.books)
|
||||
{
|
||||
//free_info(info);
|
||||
return(null);
|
||||
}
|
||||
}
|
||||
return(info);
|
||||
// err_out:
|
||||
// free_info(info);
|
||||
// return(NULL);
|
||||
}
|
||||
override public Object look(DspState vd, InfoMode mi, Object i)
|
||||
{
|
||||
Console.Error.WriteLine("Floor0::look");
|
||||
float scale;
|
||||
Info vi=vd.vi;
|
||||
InfoFloor0 info=(InfoFloor0)i;
|
||||
LookFloor0 look=new LookFloor0();
|
||||
look.m=info.order;
|
||||
look.n=vi.blocksizes[mi.blockflag]/2;
|
||||
look.ln=info.barkmap;
|
||||
look.vi=info;
|
||||
look.lpclook.init(look.ln,look.m);
|
||||
|
||||
lock(this)
|
||||
{
|
||||
if(lsp==null||lsp.length<look.m)
|
||||
// we choose a scaling constant so that:
|
||||
// floor(bark(rate/2-1)*C)=mapped-1
|
||||
// floor(bark(rate/2)*C)=mapped
|
||||
scale=look.ln/toBARK((float)(info.rate/2.0));
|
||||
|
||||
// the mapping from a linear scale to a smaller bark scale is
|
||||
// straightforward. We do *not* make sure that the linear mapping
|
||||
// does not skip bark-scale bins; the decoder simply skips them and
|
||||
// the encoder may do what it wishes in filling them. They're
|
||||
// necessary in some mapping combinations to keep the scale spacing
|
||||
// accurate
|
||||
look.linearmap=new int[look.n];
|
||||
for(int j=0;j<look.n;j++)
|
||||
{
|
||||
int val=(int)Math.Floor(toBARK((float)((info.rate/2.0)/look.n*j))
|
||||
*scale); // bark numbers represent band edges
|
||||
if(val>=look.ln)val=look.ln; // guard against the approximation
|
||||
look.linearmap[j]=val;
|
||||
}
|
||||
return look;
|
||||
}
|
||||
|
||||
static float toBARK(float f)
|
||||
{
|
||||
return (float)(13.1*Math.Atan(.00074*(f))+2.24*Math.Atan((f)*(f)*1.85e-8)+1e-4*(f));
|
||||
}
|
||||
|
||||
Object state(Object i)
|
||||
{
|
||||
EchstateFloor0 state=new EchstateFloor0();
|
||||
InfoFloor0 info=(InfoFloor0)i;
|
||||
|
||||
// a safe size if usually too big (dim==1)
|
||||
state.codewords=new int[info.order];
|
||||
state.curve=new float[info.barkmap];
|
||||
state.frameno=-1;
|
||||
return(state);
|
||||
}
|
||||
override public void free_info(Object i){}
|
||||
override public void free_look(Object i){}
|
||||
override public void free_state(Object vs){}
|
||||
override public int forward(Block vb, Object i, float[] fin, float[] fout, Object vs){return 0;}
|
||||
|
||||
float[] lsp=null;
|
||||
int inverse(Block vb, Object i, float[] fout)
|
||||
{
|
||||
//System.err.println("Floor0.inverse "+i.getClass()+"]");
|
||||
LookFloor0 look=(LookFloor0)i;
|
||||
InfoFloor0 info=look.vi;
|
||||
int ampraw=vb.opb.read(info.ampbits);
|
||||
if(ampraw>0)
|
||||
{ // also handles the -1 out of data case
|
||||
int maxval=(1<<info.ampbits)-1;
|
||||
float amp=(float)ampraw/maxval*info.ampdB;
|
||||
int booknum=vb.opb.read(ilog(info.numbooks));
|
||||
|
||||
if(booknum!=-1 && booknum<info.numbooks)
|
||||
{
|
||||
|
||||
lock(this)
|
||||
{
|
||||
if(lsp==null||lsp.Length<look.m)
|
||||
{
|
||||
lsp=new float[look.m];
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int j=0; j<look.m; j++)lsp[j]=0.0f;
|
||||
}
|
||||
|
||||
CodeBook b=vb.vd.fullbooks[info.books[booknum]];
|
||||
float last=0.0f;
|
||||
|
||||
//memset(out,0,sizeof(float)*look->m);
|
||||
for(int j=0; j<look.m; j++)fout[j]=0.0f;
|
||||
|
||||
for(int j=0;j<look.m;j+=b.dim)
|
||||
{
|
||||
if(b.decodevs(lsp, j, vb.opb, 1, -1)==-1)
|
||||
{
|
||||
//goto eop;
|
||||
// memset(out,0,sizeof(float)*look->n);
|
||||
for(int k=0; k<look.n; k++)fout[k]=0.0f;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
for(int j=0;j<look.m;)
|
||||
{
|
||||
for(int k=0;k<b.dim;k++,j++)lsp[j]+=last;
|
||||
last=lsp[j-1];
|
||||
}
|
||||
// take the coefficients back to a spectral envelope curve
|
||||
/*
|
||||
lsp_to_lpc(out,out,look.m);
|
||||
lpc_to_curve(out,out,amp,look,"",0);
|
||||
for(int j=0;j<look.n;j++){
|
||||
out[j]=fromdB(out[j]-info.ampdB);
|
||||
}
|
||||
*/
|
||||
Lsp.lsp_to_curve(fout,look.linearmap,look.n,look.ln,
|
||||
lsp,look.m,amp,info.ampdB);
|
||||
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// eop:
|
||||
// memset(out,0,sizeof(float)*look->n);
|
||||
return(0);
|
||||
}
|
||||
|
||||
override public Object inverse1(Block vb, Object i, Object memo)
|
||||
{
|
||||
//System.err.println("Floor0.inverse "+i.getClass()+"]");
|
||||
LookFloor0 look=(LookFloor0)i;
|
||||
InfoFloor0 info=look.vi;
|
||||
float[] lsp=null;
|
||||
if(memo is float[])
|
||||
{
|
||||
lsp=(float[])memo;
|
||||
}
|
||||
|
||||
int ampraw=vb.opb.read(info.ampbits);
|
||||
if(ampraw>0)
|
||||
{ // also handles the -1 out of data case
|
||||
int maxval=(1<<info.ampbits)-1;
|
||||
float amp=(float)ampraw/maxval*info.ampdB;
|
||||
int booknum=vb.opb.read(ilog(info.numbooks));
|
||||
|
||||
if(booknum!=-1 && booknum<info.numbooks)
|
||||
{
|
||||
CodeBook b=vb.vd.fullbooks[info.books[booknum]];
|
||||
float last=0.0f;
|
||||
|
||||
if(lsp==null||lsp.Length<look.m+1)
|
||||
{
|
||||
lsp=new float[look.m];
|
||||
lsp=new float[look.m+1];
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int j=0; j<look.m; j++)lsp[j]=0.f;
|
||||
for(int j=0; j<lsp.Length; j++)lsp[j]=0.0f;
|
||||
}
|
||||
|
||||
CodeBook b=vb.vd.fullbooks[info.books[booknum]];
|
||||
float last=0.f;
|
||||
|
||||
//memset(out,0,sizeof(float)*look->m);
|
||||
for(int j=0; j<look.m; j++)fout[j]=0.0f;
|
||||
|
||||
for(int j=0;j<look.m;j+=b.dim)
|
||||
{
|
||||
if(b.decodevs(lsp, j, vb.opb, 1, -1)==-1)
|
||||
if(b.decodev_set(lsp, j, vb.opb, b.dim)==-1)
|
||||
{
|
||||
//goto eop;
|
||||
// memset(out,0,sizeof(float)*look->n);
|
||||
for(int k=0; k<look.n; k++)fout[k]=0.0f;
|
||||
return(0);
|
||||
return(null);
|
||||
}
|
||||
}
|
||||
|
||||
for(int j=0;j<look.m;)
|
||||
{
|
||||
for(int k=0;k<b.dim;k++,j++)lsp[j]+=last;
|
||||
last=lsp[j-1];
|
||||
}
|
||||
// take the coefficients back to a spectral envelope curve
|
||||
/*
|
||||
lsp_to_lpc(out,out,look.m);
|
||||
lpc_to_curve(out,out,amp,look,"",0);
|
||||
for(int j=0;j<look.n;j++){
|
||||
out[j]=fromdB(out[j]-info.ampdB);
|
||||
}
|
||||
*/
|
||||
Lsp.lsp_to_curve(fout,look.linearmap,look.n,look.ln,
|
||||
lsp,look.m,amp,info.ampdB);
|
||||
|
||||
return(1);
|
||||
lsp[look.m]=amp;
|
||||
return(lsp);
|
||||
}
|
||||
}
|
||||
// eop:
|
||||
return(null);
|
||||
}
|
||||
// eop:
|
||||
// memset(out,0,sizeof(float)*look->n);
|
||||
return(0);
|
||||
}
|
||||
|
||||
Object inverse1(Block vb, Object i, Object memo)
|
||||
{
|
||||
//System.err.println("Floor0.inverse "+i.getClass()+"]");
|
||||
LookFloor0 look=(LookFloor0)i;
|
||||
InfoFloor0 info=look.vi;
|
||||
float[] lsp=null;
|
||||
if(memo is float[])
|
||||
override public int inverse2(Block vb, Object i, Object memo, float[] fout)
|
||||
{
|
||||
lsp=(float[])memo;
|
||||
}
|
||||
//System.err.println("Floor0.inverse "+i.getClass()+"]");
|
||||
LookFloor0 look=(LookFloor0)i;
|
||||
InfoFloor0 info=look.vi;
|
||||
|
||||
int ampraw=vb.opb.read(info.ampbits);
|
||||
if(ampraw>0)
|
||||
{ // also handles the -1 out of data case
|
||||
int maxval=(1<<info.ampbits)-1;
|
||||
float amp=(float)ampraw/maxval*info.ampdB;
|
||||
int booknum=vb.opb.read(ilog(info.numbooks));
|
||||
|
||||
if(booknum!=-1 && booknum<info.numbooks)
|
||||
if(memo!=null)
|
||||
{
|
||||
CodeBook b=vb.vd.fullbooks[info.books[booknum]];
|
||||
float last=0.f;
|
||||
float[] lsp=(float[])memo;
|
||||
float amp=lsp[look.m];
|
||||
|
||||
if(lsp==null||lsp.length<look.m+1)
|
||||
{
|
||||
lsp=new float[look.m+1];
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int j=0; j<lsp.length; j++)lsp[j]=0.f;
|
||||
}
|
||||
|
||||
for(int j=0;j<look.m;j+=b.dim)
|
||||
{
|
||||
if(b.decodev_set(lsp, j, vb.opb, b.dim)==-1)
|
||||
{
|
||||
//goto eop;
|
||||
return(null);
|
||||
}
|
||||
}
|
||||
|
||||
for(int j=0;j<look.m;)
|
||||
{
|
||||
for(int k=0;k<b.dim;k++,j++)lsp[j]+=last;
|
||||
last=lsp[j-1];
|
||||
}
|
||||
lsp[look.m]=amp;
|
||||
return(lsp);
|
||||
Lsp.lsp_to_curve(fout,look.linearmap,look.n,look.ln,
|
||||
lsp,look.m,amp,info.ampdB);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
// eop:
|
||||
return(null);
|
||||
}
|
||||
|
||||
int inverse2(Block vb, Object i, Object memo, float[] fout)
|
||||
{
|
||||
//System.err.println("Floor0.inverse "+i.getClass()+"]");
|
||||
LookFloor0 look=(LookFloor0)i;
|
||||
InfoFloor0 info=look.vi;
|
||||
|
||||
if(memo!=null)
|
||||
{
|
||||
float[] lsp=(float[])memo;
|
||||
float amp=lsp[look.m];
|
||||
|
||||
Lsp.lsp_to_curve(fout,look.linearmap,look.n,look.ln,
|
||||
lsp,look.m,amp,info.ampdB);
|
||||
return(1);
|
||||
}
|
||||
// eop:
|
||||
// memset(out,0,sizeof(float)*look->n);
|
||||
for(int j=0; j<look.n; j++)
|
||||
{
|
||||
fout[j]=0.f;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static float fromdB(float x)
|
||||
{
|
||||
return (float)(Math.exp((x)*.11512925));
|
||||
}
|
||||
private static int ilog(int v)
|
||||
{
|
||||
int ret=0;
|
||||
while(v!=0)
|
||||
{
|
||||
ret++;
|
||||
(uint)v>>=1;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static void lsp_to_lpc(float[] lsp, float[] lpc, int m)
|
||||
{
|
||||
int i,j,m2=m/2;
|
||||
float[] O=new float[m2];
|
||||
float[] E=new float[m2];
|
||||
float A;
|
||||
float[] Ae=new float[m2+1];
|
||||
float[] Ao=new float[m2+1];
|
||||
float B;
|
||||
float[] Be=new float[m2];
|
||||
float[] Bo=new float[m2];
|
||||
float temp;
|
||||
|
||||
// even/odd roots setup
|
||||
for(i=0;i<m2;i++)
|
||||
{
|
||||
O[i]=(float)(-2.0*Math.cos(lsp[i*2]));
|
||||
E[i]=(float)(-2.0*Math.cos(lsp[i*2+1]));
|
||||
// eop:
|
||||
// memset(out,0,sizeof(float)*look->n);
|
||||
for(int j=0; j<look.n; j++)
|
||||
{
|
||||
fout[j]=0.0f;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
// set up impulse response
|
||||
for(j=0;j<m2;j++)
|
||||
static float fromdB(float x)
|
||||
{
|
||||
Ae[j]=0.f;
|
||||
Ao[j]=1.f;
|
||||
Be[j]=0.f;
|
||||
Bo[j]=1.f;
|
||||
return (float)(Math.Exp((x)*.11512925));
|
||||
}
|
||||
Ao[j]=1.f;
|
||||
Ae[j]=1.f;
|
||||
|
||||
// run impulse response
|
||||
for(i=1;i<m+1;i++)
|
||||
private static int ilog(int v)
|
||||
{
|
||||
A=B=0.f;
|
||||
int ret=0;
|
||||
while(v!=0)
|
||||
{
|
||||
ret++;
|
||||
v = (int)((uint)v >> 1);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static void lsp_to_lpc(float[] lsp, float[] lpc, int m)
|
||||
{
|
||||
int i,j,m2=m/2;
|
||||
float[] O=new float[m2];
|
||||
float[] E=new float[m2];
|
||||
float A;
|
||||
float[] Ae=new float[m2+1];
|
||||
float[] Ao=new float[m2+1];
|
||||
float B;
|
||||
float[] Be=new float[m2];
|
||||
float[] Bo=new float[m2];
|
||||
float temp;
|
||||
|
||||
// even/odd roots setup
|
||||
for(i=0;i<m2;i++)
|
||||
{
|
||||
O[i]=(float)(-2.0*Math.Cos(lsp[i*2]));
|
||||
E[i]=(float)(-2.0*Math.Cos(lsp[i*2+1]));
|
||||
}
|
||||
|
||||
// set up impulse response
|
||||
for(j=0;j<m2;j++)
|
||||
{
|
||||
temp=O[j]*Ao[j]+Ae[j];
|
||||
Ae[j]=Ao[j];
|
||||
Ao[j]=A;
|
||||
A+=temp;
|
||||
|
||||
temp=E[j]*Bo[j]+Be[j];
|
||||
Be[j]=Bo[j];
|
||||
Bo[j]=B;
|
||||
B+=temp;
|
||||
Ae[j]=0.0f;
|
||||
Ao[j]=1.0f;
|
||||
Be[j]=0.0f;
|
||||
Bo[j]=1.0f;
|
||||
}
|
||||
Ao[j]=1.0f;
|
||||
Ae[j]=1.0f;
|
||||
|
||||
// run impulse response
|
||||
for(i=1;i<m+1;i++)
|
||||
{
|
||||
A=B=0.0f;
|
||||
for(j=0;j<m2;j++)
|
||||
{
|
||||
temp=O[j]*Ao[j]+Ae[j];
|
||||
Ae[j]=Ao[j];
|
||||
Ao[j]=A;
|
||||
A+=temp;
|
||||
|
||||
temp=E[j]*Bo[j]+Be[j];
|
||||
Be[j]=Bo[j];
|
||||
Bo[j]=B;
|
||||
B+=temp;
|
||||
}
|
||||
lpc[i-1]=(A+Ao[j]+B-Ae[j])/2;
|
||||
Ao[j]=A;
|
||||
Ae[j]=B;
|
||||
}
|
||||
lpc[i-1]=(A+Ao[j]+B-Ae[j])/2;
|
||||
Ao[j]=A;
|
||||
Ae[j]=B;
|
||||
}
|
||||
}
|
||||
|
||||
static void lpc_to_curve(float[] curve, float[] lpc,float amp,
|
||||
LookFloor0 l, String name, int frameno)
|
||||
{
|
||||
// l->m+1 must be less than l->ln, but guard in case we get a bad stream
|
||||
float[] lcurve=new float[Math.max(l.ln*2,l.m*2+2)];
|
||||
|
||||
if(amp==0)
|
||||
static void lpc_to_curve(float[] curve, float[] lpc,float amp,
|
||||
LookFloor0 l, String name, int frameno)
|
||||
{
|
||||
//memset(curve,0,sizeof(float)*l->n);
|
||||
for(int j=0; j<l.n; j++)curve[j]=0.0f;
|
||||
return;
|
||||
// l->m+1 must be less than l->ln, but guard in case we get a bad stream
|
||||
float[] lcurve=new float[Math.Max(l.ln*2,l.m*2+2)];
|
||||
|
||||
if(amp==0)
|
||||
{
|
||||
//memset(curve,0,sizeof(float)*l->n);
|
||||
for(int j=0; j<l.n; j++)curve[j]=0.0f;
|
||||
return;
|
||||
}
|
||||
l.lpclook.lpc_to_curve(lcurve,lpc,amp);
|
||||
|
||||
for(int i=0;i<l.n;i++)curve[i]=lcurve[l.linearmap[i]];
|
||||
}
|
||||
l.lpclook.lpc_to_curve(lcurve,lpc,amp);
|
||||
|
||||
for(int i=0;i<l.n;i++)curve[i]=lcurve[l.linearmap[i]];
|
||||
}
|
||||
}
|
||||
|
||||
class InfoFloor0
|
||||
{
|
||||
int order;
|
||||
int rate;
|
||||
int barkmap;
|
||||
class InfoFloor0
|
||||
{
|
||||
internal int order;
|
||||
internal int rate;
|
||||
internal int barkmap;
|
||||
|
||||
int ampbits;
|
||||
int ampdB;
|
||||
internal int ampbits;
|
||||
internal int ampdB;
|
||||
|
||||
int numbooks; // <= 16
|
||||
int[] books=new int[16];
|
||||
}
|
||||
internal int numbooks; // <= 16
|
||||
internal int[] books=new int[16];
|
||||
}
|
||||
|
||||
class LookFloor0
|
||||
{
|
||||
int n;
|
||||
int ln;
|
||||
int m;
|
||||
int[] linearmap;
|
||||
class LookFloor0
|
||||
{
|
||||
internal int n;
|
||||
internal int ln;
|
||||
internal int m;
|
||||
internal int[] linearmap;
|
||||
|
||||
InfoFloor0 vi;
|
||||
Lpc lpclook=new Lpc();
|
||||
}
|
||||
internal InfoFloor0 vi;
|
||||
internal Lpc lpclook=new Lpc();
|
||||
}
|
||||
|
||||
class EchstateFloor0
|
||||
{
|
||||
int[] codewords;
|
||||
float[] curve;
|
||||
long frameno;
|
||||
long codes;
|
||||
}
|
||||
class EchstateFloor0
|
||||
{
|
||||
internal int[] codewords;
|
||||
internal float[] curve;
|
||||
internal long frameno;
|
||||
//internal long codes;
|
||||
}
|
||||
}
|
1218
csvorbis/Floor1.cs
1218
csvorbis/Floor1.cs
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -26,17 +26,20 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
abstract class FuncFloor
|
||||
namespace csvorbis
|
||||
{
|
||||
public static FuncFloor[] floor_P={new Floor0(),new Floor1()};
|
||||
abstract class FuncFloor
|
||||
{
|
||||
public static FuncFloor[] floor_P={new Floor0(),new Floor1()};
|
||||
|
||||
public abstract void pack(Object i, Buffer opb);
|
||||
public abstract Object unpack(Info vi, Buffer opb);
|
||||
public abstract Object look(DspState vd, InfoMode mi, Object i);
|
||||
public abstract void free_info(Object i);
|
||||
public abstract void free_look(Object i);
|
||||
public abstract void free_state(Object vs);
|
||||
public abstract int forward(Block vb, Object i, float[] fin, float[] fout, Object vs);
|
||||
public abstract Object inverse1(Block vb, Object i, Object memo);
|
||||
public abstract int inverse2(Block vb, Object i, Object memo, float[] fout);
|
||||
public abstract void pack(Object i, csBuffer opb);
|
||||
public abstract Object unpack(Info vi, csBuffer opb);
|
||||
public abstract Object look(DspState vd, InfoMode mi, Object i);
|
||||
public abstract void free_info(Object i);
|
||||
public abstract void free_look(Object i);
|
||||
public abstract void free_state(Object vs);
|
||||
public abstract int forward(Block vb, Object i, float[] fin, float[] fout, Object vs);
|
||||
public abstract Object inverse1(Block vb, Object i, Object memo);
|
||||
public abstract int inverse2(Block vb, Object i, Object memo, float[] fout);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,13 +26,17 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
abstract class FuncMapping{
|
||||
public static FuncMapping[] mapping_P={new Mapping0()};
|
||||
namespace csvorbis
|
||||
{
|
||||
abstract class FuncMapping
|
||||
{
|
||||
public static FuncMapping[] mapping_P={new Mapping0()};
|
||||
|
||||
public abstract void pack(Info info , Object imap, Buffer buffer);
|
||||
public abstract Object unpack(Info info , Buffer buffer);
|
||||
public abstract Object look(DspState vd, InfoMode vm, Object m);
|
||||
public abstract void free_info(Object imap);
|
||||
public abstract void free_look(Object imap);
|
||||
public abstract int inverse(Block vd, Object lm);
|
||||
}
|
||||
public abstract void pack(Info info , Object imap, csBuffer buffer);
|
||||
public abstract Object unpack(Info info , csBuffer buffer);
|
||||
public abstract Object look(DspState vd, InfoMode vm, Object m);
|
||||
public abstract void free_info(Object imap);
|
||||
public abstract void free_look(Object imap);
|
||||
public abstract int inverse(Block vd, Object lm);
|
||||
}
|
||||
}
|
|
@ -26,17 +26,21 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
abstract class FuncResidue
|
||||
namespace csvorbis
|
||||
{
|
||||
public static FuncResidue[] residue_P={new Residue0(),
|
||||
new Residue1(),
|
||||
new Residue2()};
|
||||
abstract class FuncResidue
|
||||
{
|
||||
public static FuncResidue[] residue_P={new Residue0(),
|
||||
new Residue1(),
|
||||
new Residue2()};
|
||||
|
||||
public abstract void pack(Object vr, csBuffer opb);
|
||||
public abstract Object unpack(Info vi, csBuffer opb);
|
||||
public abstract Object look(DspState vd, InfoMode vm, Object vr);
|
||||
public abstract void free_info(Object i);
|
||||
public abstract void free_look(Object i);
|
||||
public abstract int forward(Block vb,Object vl, float[][] fin, int ch);
|
||||
public abstract void pack(Object vr, csBuffer opb);
|
||||
public abstract Object unpack(Info vi, csBuffer opb);
|
||||
public abstract Object look(DspState vd, InfoMode vm, Object vr);
|
||||
public abstract void free_info(Object i);
|
||||
public abstract void free_look(Object i);
|
||||
public abstract int forward(Block vb,Object vl, float[][] fin, int ch);
|
||||
|
||||
public abstract int inverse(Block vb, Object vl, float[][] fin, int[] nonzero,int ch);}
|
||||
public abstract int inverse(Block vb, Object vl, float[][] fin, int[] nonzero,int ch);
|
||||
}
|
||||
}
|
|
@ -26,14 +26,18 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
abstract class FuncTime{
|
||||
public static FuncTime[] time_P={new Time0()};
|
||||
namespace csvorbis
|
||||
{
|
||||
abstract class FuncTime
|
||||
{
|
||||
public static FuncTime[] time_P={new Time0()};
|
||||
|
||||
public abstract void pack(Object i, csBuffer opb);
|
||||
public abstract Object unpack(Info vi , csBuffer opb);
|
||||
public abstract Object look(DspState vd, InfoMode vm, Object i);
|
||||
public abstract void free_info(Object i);
|
||||
public abstract void free_look(Object i);
|
||||
public abstract int forward(Block vb, Object i);
|
||||
public abstract int inverse(Block vb, Object i, float[] fin, float[] fout);
|
||||
}
|
||||
public abstract void pack(Object i, csBuffer opb);
|
||||
public abstract Object unpack(Info vi , csBuffer opb);
|
||||
public abstract Object look(DspState vd, InfoMode vm, Object i);
|
||||
public abstract void free_info(Object i);
|
||||
public abstract void free_look(Object i);
|
||||
public abstract int forward(Block vb, Object i);
|
||||
public abstract int inverse(Block vb, Object i, float[] fin, float[] fout);
|
||||
}
|
||||
}
|
897
csvorbis/Info.cs
897
csvorbis/Info.cs
|
@ -23,489 +23,552 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
using System;
|
||||
using System.Text;
|
||||
using csogg;
|
||||
|
||||
public class Info{
|
||||
private static int OV_EBADPACKET=-136;
|
||||
private static int OV_ENOTAUDIO=-135;
|
||||
private static byte[] _vorbis="vorbis".getBytes();
|
||||
private static int VI_TIMEB=1;
|
||||
private static int VI_FLOORB=2;
|
||||
private static int VI_RESB=3;
|
||||
private static int VI_MAPB=1;
|
||||
private static int VI_WINDOWB=1;
|
||||
namespace csvorbis
|
||||
{
|
||||
public class Info
|
||||
{
|
||||
private static int OV_EBADPACKET=-136;
|
||||
private static int OV_ENOTAUDIO=-135;
|
||||
private static string _vorbis="vorbis";
|
||||
private static int VI_TIMEB=1;
|
||||
private static int VI_FLOORB=2;
|
||||
private static int VI_RESB=3;
|
||||
private static int VI_MAPB=1;
|
||||
private static int VI_WINDOWB=1;
|
||||
|
||||
public int version;
|
||||
public int channels;
|
||||
public int rate;
|
||||
public int version;
|
||||
public int channels;
|
||||
public int rate;
|
||||
|
||||
// The below bitrate declarations are *hints*.
|
||||
// Combinations of the three values carry the following implications:
|
||||
//
|
||||
// all three set to the same value:
|
||||
// implies a fixed rate bitstream
|
||||
// only nominal set:
|
||||
// implies a VBR stream that averages the nominal bitrate. No hard
|
||||
// upper/lower limit
|
||||
// upper and or lower set:
|
||||
// implies a VBR bitstream that obeys the bitrate limits. nominal
|
||||
// may also be set to give a nominal rate.
|
||||
// none set:
|
||||
// the coder does not care to speculate.
|
||||
// The below bitrate declarations are *hints*.
|
||||
// Combinations of the three values carry the following implications:
|
||||
//
|
||||
// all three set to the same value:
|
||||
// implies a fixed rate bitstream
|
||||
// only nominal set:
|
||||
// implies a VBR stream that averages the nominal bitrate. No hard
|
||||
// upper/lower limit
|
||||
// upper and or lower set:
|
||||
// implies a VBR bitstream that obeys the bitrate limits. nominal
|
||||
// may also be set to give a nominal rate.
|
||||
// none set:
|
||||
// the coder does not care to speculate.
|
||||
|
||||
int bitrate_upper;
|
||||
int bitrate_nominal;
|
||||
int bitrate_lower;
|
||||
internal int bitrate_upper;
|
||||
internal int bitrate_nominal;
|
||||
internal int bitrate_lower;
|
||||
|
||||
// Vorbis supports only short and long blocks, but allows the
|
||||
// encoder to choose the sizes
|
||||
// Vorbis supports only short and long blocks, but allows the
|
||||
// encoder to choose the sizes
|
||||
|
||||
int[] blocksizes=new int[2];
|
||||
internal int[] blocksizes=new int[2];
|
||||
|
||||
// modes are the primary means of supporting on-the-fly different
|
||||
// blocksizes, different channel mappings (LR or mid-side),
|
||||
// different residue backends, etc. Each mode consists of a
|
||||
// blocksize flag and a mapping (along with the mapping setup
|
||||
// modes are the primary means of supporting on-the-fly different
|
||||
// blocksizes, different channel mappings (LR or mid-side),
|
||||
// different residue backends, etc. Each mode consists of a
|
||||
// blocksize flag and a mapping (along with the mapping setup
|
||||
|
||||
int modes;
|
||||
int maps;
|
||||
int times;
|
||||
int floors;
|
||||
int residues;
|
||||
int books;
|
||||
int psys; // encode only
|
||||
internal int modes;
|
||||
internal int maps;
|
||||
internal int times;
|
||||
internal int floors;
|
||||
internal int residues;
|
||||
internal int books;
|
||||
internal int psys; // encode only
|
||||
|
||||
InfoMode[] mode_param=null;
|
||||
internal InfoMode[] mode_param=null;
|
||||
|
||||
int[] map_type=null;
|
||||
Object[] map_param=null;
|
||||
internal int[] map_type=null;
|
||||
internal Object[] map_param=null;
|
||||
|
||||
int[] time_type=null;
|
||||
Object[] time_param=null;
|
||||
internal int[] time_type=null;
|
||||
internal Object[] time_param=null;
|
||||
|
||||
int[] floor_type=null;
|
||||
Object[] floor_param=null;
|
||||
internal int[] floor_type=null;
|
||||
internal Object[] floor_param=null;
|
||||
|
||||
int[] residue_type=null;
|
||||
Object[] residue_param=null;
|
||||
internal int[] residue_type=null;
|
||||
internal Object[] residue_param=null;
|
||||
|
||||
StaticCodeBook[] book_param=null;
|
||||
internal StaticCodeBook[] book_param=null;
|
||||
|
||||
PsyInfo[] psy_param=new PsyInfo[64]; // encode only
|
||||
internal PsyInfo[] psy_param=new PsyInfo[64]; // encode only
|
||||
|
||||
// for block long/sort tuning; encode only
|
||||
int envelopesa;
|
||||
float preecho_thresh;
|
||||
float preecho_clamp;
|
||||
// for block long/sort tuning; encode only
|
||||
//internal int envelopesa;
|
||||
//internal float preecho_thresh;
|
||||
//internal float preecho_clamp;
|
||||
|
||||
// used by synthesis, which has a full, alloced vi
|
||||
public void init(){
|
||||
rate=0;
|
||||
//memset(vi,0,sizeof(vorbis_info));
|
||||
}
|
||||
// used by synthesis, which has a full, alloced vi
|
||||
public void init()
|
||||
{
|
||||
rate=0;
|
||||
//memset(vi,0,sizeof(vorbis_info));
|
||||
}
|
||||
|
||||
public void clear(){
|
||||
for(int i=0;i<modes;i++){ mode_param[i]=null; }
|
||||
mode_param=null;
|
||||
public void clear()
|
||||
{
|
||||
for(int i=0;i<modes;i++){ mode_param[i]=null; }
|
||||
mode_param=null;
|
||||
|
||||
for(int i=0;i<maps;i++){ // unpack does the range checking
|
||||
FuncMapping.mapping_P[map_type[i]].free_info(map_param[i]);
|
||||
}
|
||||
map_param=null;
|
||||
for(int i=0;i<maps;i++)
|
||||
{ // unpack does the range checking
|
||||
FuncMapping.mapping_P[map_type[i]].free_info(map_param[i]);
|
||||
}
|
||||
map_param=null;
|
||||
|
||||
for(int i=0;i<times;i++){ // unpack does the range checking
|
||||
FuncTime.time_P[time_type[i]].free_info(time_param[i]);
|
||||
}
|
||||
time_param=null;
|
||||
for(int i=0;i<times;i++)
|
||||
{ // unpack does the range checking
|
||||
FuncTime.time_P[time_type[i]].free_info(time_param[i]);
|
||||
}
|
||||
time_param=null;
|
||||
|
||||
for(int i=0;i<floors;i++){ // unpack does the range checking
|
||||
FuncFloor.floor_P[floor_type[i]].free_info(floor_param[i]);
|
||||
}
|
||||
floor_param=null;
|
||||
for(int i=0;i<floors;i++)
|
||||
{ // unpack does the range checking
|
||||
FuncFloor.floor_P[floor_type[i]].free_info(floor_param[i]);
|
||||
}
|
||||
floor_param=null;
|
||||
|
||||
for(int i=0;i<residues;i++){ // unpack does the range checking
|
||||
FuncResidue.residue_P[residue_type[i]].free_info(residue_param[i]);
|
||||
}
|
||||
residue_param=null;
|
||||
for(int i=0;i<residues;i++)
|
||||
{ // unpack does the range checking
|
||||
FuncResidue.residue_P[residue_type[i]].free_info(residue_param[i]);
|
||||
}
|
||||
residue_param=null;
|
||||
|
||||
// the static codebooks *are* freed if you call info_clear, because
|
||||
// decode side does alloc a 'static' codebook. Calling clear on the
|
||||
// full codebook does not clear the static codebook (that's our
|
||||
// responsibility)
|
||||
for(int i=0;i<books;i++){
|
||||
// just in case the decoder pre-cleared to save space
|
||||
if(book_param[i]!=null){
|
||||
book_param[i].clear();
|
||||
book_param[i]=null;
|
||||
}
|
||||
}
|
||||
//if(vi->book_param)free(vi->book_param);
|
||||
book_param=null;
|
||||
// the static codebooks *are* freed if you call info_clear, because
|
||||
// decode side does alloc a 'static' codebook. Calling clear on the
|
||||
// full codebook does not clear the static codebook (that's our
|
||||
// responsibility)
|
||||
for(int i=0;i<books;i++)
|
||||
{
|
||||
// just in case the decoder pre-cleared to save space
|
||||
if(book_param[i]!=null)
|
||||
{
|
||||
book_param[i].clear();
|
||||
book_param[i]=null;
|
||||
}
|
||||
}
|
||||
//if(vi->book_param)free(vi->book_param);
|
||||
book_param=null;
|
||||
|
||||
for(int i=0;i<psys;i++){
|
||||
psy_param[i].free();
|
||||
}
|
||||
//if(vi->psy_param)free(vi->psy_param);
|
||||
//memset(vi,0,sizeof(vorbis_info));
|
||||
}
|
||||
for(int i=0;i<psys;i++)
|
||||
{
|
||||
psy_param[i].free();
|
||||
}
|
||||
//if(vi->psy_param)free(vi->psy_param);
|
||||
//memset(vi,0,sizeof(vorbis_info));
|
||||
}
|
||||
|
||||
// Header packing/unpacking
|
||||
int unpack_info(csBuffer opb){
|
||||
version=opb.read(32);
|
||||
if(version!=0)return(-1);
|
||||
// Header packing/unpacking
|
||||
int unpack_info(csBuffer opb)
|
||||
{
|
||||
version=opb.read(32);
|
||||
if(version!=0)return(-1);
|
||||
|
||||
channels=opb.read(8);
|
||||
rate=opb.read(32);
|
||||
channels=opb.read(8);
|
||||
rate=opb.read(32);
|
||||
|
||||
bitrate_upper=opb.read(32);
|
||||
bitrate_nominal=opb.read(32);
|
||||
bitrate_lower=opb.read(32);
|
||||
bitrate_upper=opb.read(32);
|
||||
bitrate_nominal=opb.read(32);
|
||||
bitrate_lower=opb.read(32);
|
||||
|
||||
blocksizes[0]=1<<opb.read(4);
|
||||
blocksizes[1]=1<<opb.read(4);
|
||||
blocksizes[0]=1<<opb.read(4);
|
||||
blocksizes[1]=1<<opb.read(4);
|
||||
|
||||
if((rate<1) ||
|
||||
(channels<1)||
|
||||
(blocksizes[0]<8)||
|
||||
(blocksizes[1]<blocksizes[0]) ||
|
||||
(opb.read(1)!=1)){
|
||||
//goto err_out; // EOP check
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
// err_out:
|
||||
// vorbis_info_clear(vi);
|
||||
// return(-1);
|
||||
}
|
||||
if((rate<1) ||
|
||||
(channels<1)||
|
||||
(blocksizes[0]<8)||
|
||||
(blocksizes[1]<blocksizes[0]) ||
|
||||
(opb.read(1)!=1))
|
||||
{
|
||||
//goto err_out; // EOP check
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
// err_out:
|
||||
// vorbis_info_clear(vi);
|
||||
// return(-1);
|
||||
}
|
||||
|
||||
// all of the real encoding details are here. The modes, books,
|
||||
// everything
|
||||
int unpack_books(csBuffer opb){
|
||||
// all of the real encoding details are here. The modes, books,
|
||||
// everything
|
||||
int unpack_books(csBuffer opb)
|
||||
{
|
||||
|
||||
//d* codebooks
|
||||
books=opb.read(8)+1;
|
||||
//d* codebooks
|
||||
books=opb.read(8)+1;
|
||||
|
||||
if(book_param==null || book_param.length!=books)
|
||||
book_param=new StaticCodeBook[books];
|
||||
for(int i=0;i<books;i++){
|
||||
book_param[i]=new StaticCodeBook();
|
||||
if(book_param[i].unpack(opb)!=0){
|
||||
//goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
if(book_param==null || book_param.Length!=books)
|
||||
book_param=new StaticCodeBook[books];
|
||||
for(int i=0;i<books;i++)
|
||||
{
|
||||
book_param[i]=new StaticCodeBook();
|
||||
if(book_param[i].unpack(opb)!=0)
|
||||
{
|
||||
//goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
// time backend settings
|
||||
times=opb.read(6)+1;
|
||||
if(time_type==null || time_type.length!=times) time_type=new int[times];
|
||||
if(time_param==null || time_param.length!=times)
|
||||
time_param=new Object[times];
|
||||
for(int i=0;i<times;i++){
|
||||
time_type[i]=opb.read(16);
|
||||
if(time_type[i]<0 || time_type[i]>=VI_TIMEB){
|
||||
//goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
time_param[i]=FuncTime.time_P[time_type[i]].unpack(this, opb);
|
||||
if(time_param[i]==null){
|
||||
//goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
// time backend settings
|
||||
times=opb.read(6)+1;
|
||||
if(time_type==null || time_type.Length!=times) time_type=new int[times];
|
||||
if(time_param==null || time_param.Length!=times)
|
||||
time_param=new Object[times];
|
||||
for(int i=0;i<times;i++)
|
||||
{
|
||||
time_type[i]=opb.read(16);
|
||||
if(time_type[i]<0 || time_type[i]>=VI_TIMEB)
|
||||
{
|
||||
//goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
time_param[i]=FuncTime.time_P[time_type[i]].unpack(this, opb);
|
||||
if(time_param[i]==null)
|
||||
{
|
||||
//goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
// floor backend settings
|
||||
floors=opb.read(6)+1;
|
||||
if(floor_type==null || floor_type.length!=floors)
|
||||
floor_type=new int[floors];
|
||||
if(floor_param==null || floor_param.length!=floors)
|
||||
floor_param=new Object[floors];
|
||||
// floor backend settings
|
||||
floors=opb.read(6)+1;
|
||||
if(floor_type==null || floor_type.Length!=floors)
|
||||
floor_type=new int[floors];
|
||||
if(floor_param==null || floor_param.Length!=floors)
|
||||
floor_param=new Object[floors];
|
||||
|
||||
for(int i=0;i<floors;i++){
|
||||
floor_type[i]=opb.read(16);
|
||||
if(floor_type[i]<0 || floor_type[i]>=VI_FLOORB){
|
||||
//goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
for(int i=0;i<floors;i++)
|
||||
{
|
||||
floor_type[i]=opb.read(16);
|
||||
if(floor_type[i]<0 || floor_type[i]>=VI_FLOORB)
|
||||
{
|
||||
//goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
|
||||
floor_param[i]=FuncFloor.floor_P[floor_type[i]].unpack(this,opb);
|
||||
if(floor_param[i]==null){
|
||||
//goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
floor_param[i]=FuncFloor.floor_P[floor_type[i]].unpack(this,opb);
|
||||
if(floor_param[i]==null)
|
||||
{
|
||||
//goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
// residue backend settings
|
||||
residues=opb.read(6)+1;
|
||||
// residue backend settings
|
||||
residues=opb.read(6)+1;
|
||||
|
||||
if(residue_type==null || residue_type.length!=residues)
|
||||
residue_type=new int[residues];
|
||||
if(residue_type==null || residue_type.Length!=residues)
|
||||
residue_type=new int[residues];
|
||||
|
||||
if(residue_param==null || residue_param.length!=residues)
|
||||
residue_param=new Object[residues];
|
||||
if(residue_param==null || residue_param.Length!=residues)
|
||||
residue_param=new Object[residues];
|
||||
|
||||
for(int i=0;i<residues;i++){
|
||||
residue_type[i]=opb.read(16);
|
||||
if(residue_type[i]<0 || residue_type[i]>=VI_RESB){
|
||||
// goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
residue_param[i]=FuncResidue.residue_P[residue_type[i]].unpack(this,opb);
|
||||
if(residue_param[i]==null){
|
||||
// goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
for(int i=0;i<residues;i++)
|
||||
{
|
||||
residue_type[i]=opb.read(16);
|
||||
if(residue_type[i]<0 || residue_type[i]>=VI_RESB)
|
||||
{
|
||||
// goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
residue_param[i]=FuncResidue.residue_P[residue_type[i]].unpack(this,opb);
|
||||
if(residue_param[i]==null)
|
||||
{
|
||||
// goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
// map backend settings
|
||||
maps=opb.read(6)+1;
|
||||
if(map_type==null || map_type.length!=maps) map_type=new int[maps];
|
||||
if(map_param==null || map_param.length!=maps) map_param=new Object[maps];
|
||||
for(int i=0;i<maps;i++){
|
||||
map_type[i]=opb.read(16);
|
||||
if(map_type[i]<0 || map_type[i]>=VI_MAPB){
|
||||
// goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
map_param[i]=FuncMapping.mapping_P[map_type[i]].unpack(this,opb);
|
||||
if(map_param[i]==null){
|
||||
// goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
// map backend settings
|
||||
maps=opb.read(6)+1;
|
||||
if(map_type==null || map_type.Length!=maps) map_type=new int[maps];
|
||||
if(map_param==null || map_param.Length!=maps) map_param=new Object[maps];
|
||||
for(int i=0;i<maps;i++)
|
||||
{
|
||||
map_type[i]=opb.read(16);
|
||||
if(map_type[i]<0 || map_type[i]>=VI_MAPB)
|
||||
{
|
||||
// goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
map_param[i]=FuncMapping.mapping_P[map_type[i]].unpack(this,opb);
|
||||
if(map_param[i]==null)
|
||||
{
|
||||
// goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
// mode settings
|
||||
modes=opb.read(6)+1;
|
||||
if(mode_param==null || mode_param.length!=modes)
|
||||
mode_param=new InfoMode[modes];
|
||||
for(int i=0;i<modes;i++){
|
||||
mode_param[i]=new InfoMode();
|
||||
mode_param[i].blockflag=opb.read(1);
|
||||
mode_param[i].windowtype=opb.read(16);
|
||||
mode_param[i].transformtype=opb.read(16);
|
||||
mode_param[i].mapping=opb.read(8);
|
||||
// mode settings
|
||||
modes=opb.read(6)+1;
|
||||
if(mode_param==null || mode_param.Length!=modes)
|
||||
mode_param=new InfoMode[modes];
|
||||
for(int i=0;i<modes;i++)
|
||||
{
|
||||
mode_param[i]=new InfoMode();
|
||||
mode_param[i].blockflag=opb.read(1);
|
||||
mode_param[i].windowtype=opb.read(16);
|
||||
mode_param[i].transformtype=opb.read(16);
|
||||
mode_param[i].mapping=opb.read(8);
|
||||
|
||||
if((mode_param[i].windowtype>=VI_WINDOWB)||
|
||||
(mode_param[i].transformtype>=VI_WINDOWB)||
|
||||
(mode_param[i].mapping>=maps)){
|
||||
// goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
if((mode_param[i].windowtype>=VI_WINDOWB)||
|
||||
(mode_param[i].transformtype>=VI_WINDOWB)||
|
||||
(mode_param[i].mapping>=maps))
|
||||
{
|
||||
// goto err_out;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
if(opb.read(1)!=1){
|
||||
//goto err_out; // top level EOP check
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
if(opb.read(1)!=1)
|
||||
{
|
||||
//goto err_out; // top level EOP check
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
// err_out:
|
||||
// vorbis_info_clear(vi);
|
||||
// return(-1);
|
||||
}
|
||||
return(0);
|
||||
// err_out:
|
||||
// vorbis_info_clear(vi);
|
||||
// return(-1);
|
||||
}
|
||||
|
||||
// The Vorbis header is in three packets; the initial small packet in
|
||||
// the first page that identifies basic parameters, a second packet
|
||||
// with bitstream comments and a third packet that holds the
|
||||
// codebook.
|
||||
// The Vorbis header is in three packets; the initial small packet in
|
||||
// the first page that identifies basic parameters, a second packet
|
||||
// with bitstream comments and a third packet that holds the
|
||||
// codebook.
|
||||
|
||||
public int synthesis_headerin(Comment vc, Packet op){
|
||||
Buffer opb=new Buffer();
|
||||
public int synthesis_headerin(Comment vc, Packet op)
|
||||
{
|
||||
csBuffer opb=new csBuffer();
|
||||
|
||||
if(op!=null){
|
||||
opb.readinit(op.packet_base, op.packet, op.bytes);
|
||||
if(op!=null)
|
||||
{
|
||||
opb.readinit(op.packet_base, op.packet, op.bytes);
|
||||
|
||||
// Which of the three types of header is this?
|
||||
// Also verify header-ness, vorbis
|
||||
{
|
||||
byte[] buffer=new byte[6];
|
||||
int packtype=opb.read(8);
|
||||
//memset(buffer,0,6);
|
||||
opb.read(buffer,6);
|
||||
if(buffer[0]!='v' || buffer[1]!='o' || buffer[2]!='r' ||
|
||||
buffer[3]!='b' || buffer[4]!='i' || buffer[5]!='s'){
|
||||
// not a vorbis header
|
||||
return(-1);
|
||||
}
|
||||
switch(packtype){
|
||||
case 0x01: // least significant *bit* is read first
|
||||
if(op.b_o_s==0){
|
||||
// Not the initial packet
|
||||
return(-1);
|
||||
}
|
||||
if(rate!=0){
|
||||
// previously initialized info header
|
||||
return(-1);
|
||||
}
|
||||
return(unpack_info(opb));
|
||||
case 0x03: // least significant *bit* is read first
|
||||
if(rate==0){
|
||||
// um... we didn't get the initial header
|
||||
return(-1);
|
||||
}
|
||||
return(vc.unpack(opb));
|
||||
case 0x05: // least significant *bit* is read first
|
||||
if(rate==0 || vc.vendor==null){
|
||||
// um... we didn;t get the initial header or comments yet
|
||||
return(-1);
|
||||
}
|
||||
return(unpack_books(opb));
|
||||
default:
|
||||
// Not a valid vorbis header type
|
||||
//return(-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
// Which of the three types of header is this?
|
||||
// Also verify header-ness, vorbis
|
||||
{
|
||||
byte[] buffer=new byte[6];
|
||||
int packtype=opb.read(8);
|
||||
//memset(buffer,0,6);
|
||||
opb.read(buffer,6);
|
||||
if(buffer[0]!='v' || buffer[1]!='o' || buffer[2]!='r' ||
|
||||
buffer[3]!='b' || buffer[4]!='i' || buffer[5]!='s')
|
||||
{
|
||||
// not a vorbis header
|
||||
return(-1);
|
||||
}
|
||||
switch(packtype)
|
||||
{
|
||||
case 0x01: // least significant *bit* is read first
|
||||
if(op.b_o_s==0)
|
||||
{
|
||||
// Not the initial packet
|
||||
return(-1);
|
||||
}
|
||||
if(rate!=0)
|
||||
{
|
||||
// previously initialized info header
|
||||
return(-1);
|
||||
}
|
||||
return(unpack_info(opb));
|
||||
case 0x03: // least significant *bit* is read first
|
||||
if(rate==0)
|
||||
{
|
||||
// um... we didn't get the initial header
|
||||
return(-1);
|
||||
}
|
||||
return(vc.unpack(opb));
|
||||
case 0x05: // least significant *bit* is read first
|
||||
if(rate==0 || vc.vendor==null)
|
||||
{
|
||||
// um... we didn;t get the initial header or comments yet
|
||||
return(-1);
|
||||
}
|
||||
return(unpack_books(opb));
|
||||
default:
|
||||
// Not a valid vorbis header type
|
||||
//return(-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// pack side
|
||||
int pack_info(csBuffer opb){
|
||||
// preamble
|
||||
opb.write(0x01,8);
|
||||
opb.write(_vorbis);
|
||||
// pack side
|
||||
int pack_info(csBuffer opb)
|
||||
{
|
||||
ASCIIEncoding AE = new ASCIIEncoding();
|
||||
byte[] _vorbis_byt = AE.GetBytes(_vorbis);
|
||||
|
||||
// basic information about the stream
|
||||
opb.write(0x00,32);
|
||||
opb.write(channels,8);
|
||||
opb.write(rate,32);
|
||||
// preamble
|
||||
opb.write(0x01,8);
|
||||
opb.write(_vorbis_byt);
|
||||
|
||||
opb.write(bitrate_upper,32);
|
||||
opb.write(bitrate_nominal,32);
|
||||
opb.write(bitrate_lower,32);
|
||||
// basic information about the stream
|
||||
opb.write(0x00,32);
|
||||
opb.write(channels,8);
|
||||
opb.write(rate,32);
|
||||
|
||||
opb.write(ilog2(blocksizes[0]),4);
|
||||
opb.write(ilog2(blocksizes[1]),4);
|
||||
opb.write(1,1);
|
||||
return(0);
|
||||
}
|
||||
opb.write(bitrate_upper,32);
|
||||
opb.write(bitrate_nominal,32);
|
||||
opb.write(bitrate_lower,32);
|
||||
|
||||
int pack_books(csBuffer opb){
|
||||
opb.write(0x05,8);
|
||||
opb.write(_vorbis);
|
||||
opb.write(ilog2(blocksizes[0]),4);
|
||||
opb.write(ilog2(blocksizes[1]),4);
|
||||
opb.write(1,1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
// books
|
||||
opb.write(books-1,8);
|
||||
for(int i=0;i<books;i++){
|
||||
if(book_param[i].pack(opb)!=0){
|
||||
//goto err_out;
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
int pack_books(csBuffer opb)
|
||||
{
|
||||
ASCIIEncoding AE = new ASCIIEncoding();
|
||||
byte[] _vorbis_byt = AE.GetBytes(_vorbis);
|
||||
|
||||
opb.write(0x05,8);
|
||||
opb.write(_vorbis_byt);
|
||||
|
||||
// times
|
||||
opb.write(times-1,6);
|
||||
for(int i=0;i<times;i++){
|
||||
opb.write(time_type[i],16);
|
||||
FuncTime.time_P[time_type[i]].pack(this.time_param[i],opb);
|
||||
}
|
||||
// books
|
||||
opb.write(books-1,8);
|
||||
for(int i=0;i<books;i++)
|
||||
{
|
||||
if(book_param[i].pack(opb)!=0)
|
||||
{
|
||||
//goto err_out;
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
// floors
|
||||
opb.write(floors-1,6);
|
||||
for(int i=0;i<floors;i++){
|
||||
opb.write(floor_type[i],16);
|
||||
FuncFloor.floor_P[floor_type[i]].pack(floor_param[i],opb);
|
||||
}
|
||||
// times
|
||||
opb.write(times-1,6);
|
||||
for(int i=0;i<times;i++)
|
||||
{
|
||||
opb.write(time_type[i],16);
|
||||
FuncTime.time_P[time_type[i]].pack(this.time_param[i],opb);
|
||||
}
|
||||
|
||||
// residues
|
||||
opb.write(residues-1,6);
|
||||
for(int i=0;i<residues;i++){
|
||||
opb.write(residue_type[i],16);
|
||||
FuncResidue.residue_P[residue_type[i]].pack(residue_param[i],opb);
|
||||
}
|
||||
// floors
|
||||
opb.write(floors-1,6);
|
||||
for(int i=0;i<floors;i++)
|
||||
{
|
||||
opb.write(floor_type[i],16);
|
||||
FuncFloor.floor_P[floor_type[i]].pack(floor_param[i],opb);
|
||||
}
|
||||
|
||||
// residues
|
||||
opb.write(residues-1,6);
|
||||
for(int i=0;i<residues;i++)
|
||||
{
|
||||
opb.write(residue_type[i],16);
|
||||
FuncResidue.residue_P[residue_type[i]].pack(residue_param[i],opb);
|
||||
}
|
||||
|
||||
// maps
|
||||
opb.write(maps-1,6);
|
||||
for(int i=0;i<maps;i++){
|
||||
opb.write(map_type[i],16);
|
||||
FuncMapping.mapping_P[map_type[i]].pack(this,map_param[i],opb);
|
||||
}
|
||||
// maps
|
||||
opb.write(maps-1,6);
|
||||
for(int i=0;i<maps;i++)
|
||||
{
|
||||
opb.write(map_type[i],16);
|
||||
FuncMapping.mapping_P[map_type[i]].pack(this,map_param[i],opb);
|
||||
}
|
||||
|
||||
// modes
|
||||
opb.write(modes-1,6);
|
||||
for(int i=0;i<modes;i++){
|
||||
opb.write(mode_param[i].blockflag,1);
|
||||
opb.write(mode_param[i].windowtype,16);
|
||||
opb.write(mode_param[i].transformtype,16);
|
||||
opb.write(mode_param[i].mapping,8);
|
||||
}
|
||||
opb.write(1,1);
|
||||
return(0);
|
||||
//err_out:
|
||||
//return(-1);
|
||||
}
|
||||
// modes
|
||||
opb.write(modes-1,6);
|
||||
for(int i=0;i<modes;i++)
|
||||
{
|
||||
opb.write(mode_param[i].blockflag,1);
|
||||
opb.write(mode_param[i].windowtype,16);
|
||||
opb.write(mode_param[i].transformtype,16);
|
||||
opb.write(mode_param[i].mapping,8);
|
||||
}
|
||||
opb.write(1,1);
|
||||
return(0);
|
||||
//err_out:
|
||||
//return(-1);
|
||||
}
|
||||
|
||||
// static void v_writestring(Buffer o, byte[] s){
|
||||
// int i=0;
|
||||
// while(s[i]!=0){
|
||||
// o.write(s[i++],8);
|
||||
// }
|
||||
// }
|
||||
// static void v_writestring(csBuffer o, byte[] s){
|
||||
// int i=0;
|
||||
// while(s[i]!=0){
|
||||
// o.write(s[i++],8);
|
||||
// }
|
||||
// }
|
||||
|
||||
// static void v_readstring(Buffer o, byte[] buf, int bytes){
|
||||
// int i=0
|
||||
// while(bytes--!=0){
|
||||
// buf[i++]=o.read(8);
|
||||
// }
|
||||
// }
|
||||
// static void v_readstring(csBuffer o, byte[] buf, int bytes){
|
||||
// int i=0
|
||||
// while(bytes--!=0){
|
||||
// buf[i++]=o.read(8);
|
||||
// }
|
||||
// }
|
||||
|
||||
// private Buffer opb_blocksize=new Buffer();
|
||||
public int blocksize(Packet op){
|
||||
//codec_setup_info *ci=vi->codec_setup;
|
||||
Buffer opb=new Buffer();
|
||||
// synchronized(opb_blocksize){
|
||||
int mode;
|
||||
// private csBuffer opb_blocksize=new csBuffer();
|
||||
public int blocksize(Packet op)
|
||||
{
|
||||
//codec_setup_info *ci=vi->codec_setup;
|
||||
csBuffer opb=new csBuffer();
|
||||
// synchronized(opb_blocksize){
|
||||
int mode;
|
||||
|
||||
opb.readinit(op.packet_base, op.packet, op.bytes);
|
||||
opb.readinit(op.packet_base, op.packet, op.bytes);
|
||||
|
||||
/* Check the packet type */
|
||||
if(opb.read(1)!=0){
|
||||
/* Oops. This is not an audio data packet */
|
||||
return(OV_ENOTAUDIO);
|
||||
}
|
||||
{
|
||||
int modebits=0;
|
||||
int v=modes;
|
||||
while(v>1){
|
||||
modebits++;
|
||||
(uint)v>>=1;
|
||||
}
|
||||
/* Check the packet type */
|
||||
if(opb.read(1)!=0)
|
||||
{
|
||||
/* Oops. This is not an audio data packet */
|
||||
return(OV_ENOTAUDIO);
|
||||
}
|
||||
{
|
||||
int modebits=0;
|
||||
int v=modes;
|
||||
while(v>1)
|
||||
{
|
||||
modebits++;
|
||||
v = (int)((uint)v >> 1);
|
||||
}
|
||||
|
||||
/* read our mode and pre/post windowsize */
|
||||
mode=opb.read(modebits);
|
||||
}
|
||||
if(mode==-1)return(OV_EBADPACKET);
|
||||
return(blocksizes[mode_param[mode].blockflag]);
|
||||
// }
|
||||
}
|
||||
/* read our mode and pre/post windowsize */
|
||||
mode=opb.read(modebits);
|
||||
}
|
||||
if(mode==-1)return(OV_EBADPACKET);
|
||||
return(blocksizes[mode_param[mode].blockflag]);
|
||||
// }
|
||||
}
|
||||
|
||||
private static int ilog2(int v){
|
||||
int ret=0;
|
||||
while(v>1){
|
||||
ret++;
|
||||
(uint)v >>=1 ;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
private static int ilog2(int v)
|
||||
{
|
||||
int ret=0;
|
||||
while(v>1)
|
||||
{
|
||||
ret++;
|
||||
v = (int)((uint)v >> 1);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return "version:"+new Integer(version)+
|
||||
", channels:"+new Integer(channels)+
|
||||
", rate:"+new Integer(rate)+
|
||||
", bitrate:"+new Integer(bitrate_upper)+","+
|
||||
new Integer(bitrate_nominal)+","+
|
||||
new Integer(bitrate_lower);
|
||||
}
|
||||
}
|
||||
public String toString()
|
||||
{
|
||||
return "version:"+ version.ToString() +
|
||||
", channels:"+ channels.ToString() +
|
||||
", rate:"+ rate.ToString() +
|
||||
", bitrate:"+ bitrate_upper.ToString() +","+
|
||||
bitrate_nominal.ToString() +","+
|
||||
bitrate_lower.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,9 +26,13 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
class InfoMode{
|
||||
int blockflag;
|
||||
int windowtype;
|
||||
int transformtype;
|
||||
int mapping;
|
||||
}
|
||||
namespace csvorbis
|
||||
{
|
||||
class InfoMode
|
||||
{
|
||||
internal int blockflag;
|
||||
internal int windowtype;
|
||||
internal int transformtype;
|
||||
internal int mapping;
|
||||
}
|
||||
}
|
|
@ -26,130 +26,136 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
class Lookup{
|
||||
static int COS_LOOKUP_SZ=128;
|
||||
static float[] COS_LOOKUP={
|
||||
+1.0000000000000f,+0.9996988186962f,+0.9987954562052f,+0.9972904566787f,
|
||||
+0.9951847266722f,+0.9924795345987f,+0.9891765099648f,+0.9852776423889f,
|
||||
+0.9807852804032f,+0.9757021300385f,+0.9700312531945f,+0.9637760657954f,
|
||||
+0.9569403357322f,+0.9495281805930f,+0.9415440651830f,+0.9329927988347f,
|
||||
+0.9238795325113f,+0.9142097557035f,+0.9039892931234f,+0.8932243011955f,
|
||||
+0.8819212643484f,+0.8700869911087f,+0.8577286100003f,+0.8448535652497f,
|
||||
+0.8314696123025f,+0.8175848131516f,+0.8032075314806f,+0.7883464276266f,
|
||||
+0.7730104533627f,+0.7572088465065f,+0.7409511253550f,+0.7242470829515f,
|
||||
+0.7071067811865f,+0.6895405447371f,+0.6715589548470f,+0.6531728429538f,
|
||||
+0.6343932841636f,+0.6152315905806f,+0.5956993044924f,+0.5758081914178f,
|
||||
+0.5555702330196f,+0.5349976198871f,+0.5141027441932f,+0.4928981922298f,
|
||||
+0.4713967368260f,+0.4496113296546f,+0.4275550934303f,+0.4052413140050f,
|
||||
+0.3826834323651f,+0.3598950365350f,+0.3368898533922f,+0.3136817403989f,
|
||||
+0.2902846772545f,+0.2667127574749f,+0.2429801799033f,+0.2191012401569f,
|
||||
+0.1950903220161f,+0.1709618887603f,+0.1467304744554f,+0.1224106751992f,
|
||||
+0.0980171403296f,+0.0735645635997f,+0.0490676743274f,+0.0245412285229f,
|
||||
+0.0000000000000f,-0.0245412285229f,-0.0490676743274f,-0.0735645635997f,
|
||||
-0.0980171403296f,-0.1224106751992f,-0.1467304744554f,-0.1709618887603f,
|
||||
-0.1950903220161f,-0.2191012401569f,-0.2429801799033f,-0.2667127574749f,
|
||||
-0.2902846772545f,-0.3136817403989f,-0.3368898533922f,-0.3598950365350f,
|
||||
-0.3826834323651f,-0.4052413140050f,-0.4275550934303f,-0.4496113296546f,
|
||||
-0.4713967368260f,-0.4928981922298f,-0.5141027441932f,-0.5349976198871f,
|
||||
-0.5555702330196f,-0.5758081914178f,-0.5956993044924f,-0.6152315905806f,
|
||||
-0.6343932841636f,-0.6531728429538f,-0.6715589548470f,-0.6895405447371f,
|
||||
-0.7071067811865f,-0.7242470829515f,-0.7409511253550f,-0.7572088465065f,
|
||||
-0.7730104533627f,-0.7883464276266f,-0.8032075314806f,-0.8175848131516f,
|
||||
-0.8314696123025f,-0.8448535652497f,-0.8577286100003f,-0.8700869911087f,
|
||||
-0.8819212643484f,-0.8932243011955f,-0.9039892931234f,-0.9142097557035f,
|
||||
-0.9238795325113f,-0.9329927988347f,-0.9415440651830f,-0.9495281805930f,
|
||||
-0.9569403357322f,-0.9637760657954f,-0.9700312531945f,-0.9757021300385f,
|
||||
-0.9807852804032f,-0.9852776423889f,-0.9891765099648f,-0.9924795345987f,
|
||||
-0.9951847266722f,-0.9972904566787f,-0.9987954562052f,-0.9996988186962f,
|
||||
-1.0000000000000f,
|
||||
};
|
||||
/* interpolated lookup based cos function, domain 0 to PI only */
|
||||
static float coslook(float a){
|
||||
double d=a*(.31830989*(float)COS_LOOKUP_SZ);
|
||||
int i=(int)d;
|
||||
return COS_LOOKUP[i]+ ((float)(d-i))*(COS_LOOKUP[i+1]-COS_LOOKUP[i]);
|
||||
}
|
||||
namespace csvorbis
|
||||
{
|
||||
class Lookup
|
||||
{
|
||||
static int COS_LOOKUP_SZ=128;
|
||||
static float[] COS_LOOKUP={
|
||||
+1.0000000000000f,+0.9996988186962f,+0.9987954562052f,+0.9972904566787f,
|
||||
+0.9951847266722f,+0.9924795345987f,+0.9891765099648f,+0.9852776423889f,
|
||||
+0.9807852804032f,+0.9757021300385f,+0.9700312531945f,+0.9637760657954f,
|
||||
+0.9569403357322f,+0.9495281805930f,+0.9415440651830f,+0.9329927988347f,
|
||||
+0.9238795325113f,+0.9142097557035f,+0.9039892931234f,+0.8932243011955f,
|
||||
+0.8819212643484f,+0.8700869911087f,+0.8577286100003f,+0.8448535652497f,
|
||||
+0.8314696123025f,+0.8175848131516f,+0.8032075314806f,+0.7883464276266f,
|
||||
+0.7730104533627f,+0.7572088465065f,+0.7409511253550f,+0.7242470829515f,
|
||||
+0.7071067811865f,+0.6895405447371f,+0.6715589548470f,+0.6531728429538f,
|
||||
+0.6343932841636f,+0.6152315905806f,+0.5956993044924f,+0.5758081914178f,
|
||||
+0.5555702330196f,+0.5349976198871f,+0.5141027441932f,+0.4928981922298f,
|
||||
+0.4713967368260f,+0.4496113296546f,+0.4275550934303f,+0.4052413140050f,
|
||||
+0.3826834323651f,+0.3598950365350f,+0.3368898533922f,+0.3136817403989f,
|
||||
+0.2902846772545f,+0.2667127574749f,+0.2429801799033f,+0.2191012401569f,
|
||||
+0.1950903220161f,+0.1709618887603f,+0.1467304744554f,+0.1224106751992f,
|
||||
+0.0980171403296f,+0.0735645635997f,+0.0490676743274f,+0.0245412285229f,
|
||||
+0.0000000000000f,-0.0245412285229f,-0.0490676743274f,-0.0735645635997f,
|
||||
-0.0980171403296f,-0.1224106751992f,-0.1467304744554f,-0.1709618887603f,
|
||||
-0.1950903220161f,-0.2191012401569f,-0.2429801799033f,-0.2667127574749f,
|
||||
-0.2902846772545f,-0.3136817403989f,-0.3368898533922f,-0.3598950365350f,
|
||||
-0.3826834323651f,-0.4052413140050f,-0.4275550934303f,-0.4496113296546f,
|
||||
-0.4713967368260f,-0.4928981922298f,-0.5141027441932f,-0.5349976198871f,
|
||||
-0.5555702330196f,-0.5758081914178f,-0.5956993044924f,-0.6152315905806f,
|
||||
-0.6343932841636f,-0.6531728429538f,-0.6715589548470f,-0.6895405447371f,
|
||||
-0.7071067811865f,-0.7242470829515f,-0.7409511253550f,-0.7572088465065f,
|
||||
-0.7730104533627f,-0.7883464276266f,-0.8032075314806f,-0.8175848131516f,
|
||||
-0.8314696123025f,-0.8448535652497f,-0.8577286100003f,-0.8700869911087f,
|
||||
-0.8819212643484f,-0.8932243011955f,-0.9039892931234f,-0.9142097557035f,
|
||||
-0.9238795325113f,-0.9329927988347f,-0.9415440651830f,-0.9495281805930f,
|
||||
-0.9569403357322f,-0.9637760657954f,-0.9700312531945f,-0.9757021300385f,
|
||||
-0.9807852804032f,-0.9852776423889f,-0.9891765099648f,-0.9924795345987f,
|
||||
-0.9951847266722f,-0.9972904566787f,-0.9987954562052f,-0.9996988186962f,
|
||||
-1.0000000000000f,
|
||||
};
|
||||
/* interpolated lookup based cos function, domain 0 to PI only */
|
||||
internal static float coslook(float a)
|
||||
{
|
||||
double d=a*(.31830989*(float)COS_LOOKUP_SZ);
|
||||
int i=(int)d;
|
||||
return COS_LOOKUP[i]+ ((float)(d-i))*(COS_LOOKUP[i+1]-COS_LOOKUP[i]);
|
||||
}
|
||||
|
||||
static int INVSQ_LOOKUP_SZ=32;
|
||||
static float[] INVSQ_LOOKUP={
|
||||
1.414213562373f,1.392621247646f,1.371988681140f,1.352246807566f,
|
||||
1.333333333333f,1.315191898443f,1.297771369046f,1.281025230441f,
|
||||
1.264911064067f,1.249390095109f,1.234426799697f,1.219988562661f,
|
||||
1.206045378311f,1.192569588000f,1.179535649239f,1.166919931983f,
|
||||
1.154700538379f,1.142857142857f,1.131370849898f,1.120224067222f,
|
||||
1.109400392450f,1.098884511590f,1.088662107904f,1.078719779941f,
|
||||
1.069044967650f,1.059625885652f,1.050451462878f,1.041511287847f,
|
||||
1.032795558989f,1.024295039463f,1.016001016002f,1.007905261358f,
|
||||
1.000000000000f,
|
||||
};
|
||||
/* interpolated 1./sqrt(p) where .5 <= p < 1. */
|
||||
static float invsqlook(float a){
|
||||
// System.out.println(a);
|
||||
double d=a*(2.f*(float)INVSQ_LOOKUP_SZ)-(float)INVSQ_LOOKUP_SZ;
|
||||
int i=(int)d;
|
||||
return INVSQ_LOOKUP[i]+ ((float)(d-i))*(INVSQ_LOOKUP[i+1]-INVSQ_LOOKUP[i]);
|
||||
}
|
||||
static int INVSQ_LOOKUP_SZ=32;
|
||||
static float[] INVSQ_LOOKUP={
|
||||
1.414213562373f,1.392621247646f,1.371988681140f,1.352246807566f,
|
||||
1.333333333333f,1.315191898443f,1.297771369046f,1.281025230441f,
|
||||
1.264911064067f,1.249390095109f,1.234426799697f,1.219988562661f,
|
||||
1.206045378311f,1.192569588000f,1.179535649239f,1.166919931983f,
|
||||
1.154700538379f,1.142857142857f,1.131370849898f,1.120224067222f,
|
||||
1.109400392450f,1.098884511590f,1.088662107904f,1.078719779941f,
|
||||
1.069044967650f,1.059625885652f,1.050451462878f,1.041511287847f,
|
||||
1.032795558989f,1.024295039463f,1.016001016002f,1.007905261358f,
|
||||
1.000000000000f,
|
||||
};
|
||||
/* interpolated 1./sqrt(p) where .5 <= p < 1. */
|
||||
internal static float invsqlook(float a)
|
||||
{
|
||||
// System.out.println(a);
|
||||
double d=a*(2.0f*(float)INVSQ_LOOKUP_SZ)-(float)INVSQ_LOOKUP_SZ;
|
||||
int i=(int)d;
|
||||
return INVSQ_LOOKUP[i]+ ((float)(d-i))*(INVSQ_LOOKUP[i+1]-INVSQ_LOOKUP[i]);
|
||||
}
|
||||
|
||||
static int INVSQ2EXP_LOOKUP_MIN=-32;
|
||||
static int INVSQ2EXP_LOOKUP_MAX=32;
|
||||
static float[] INVSQ2EXP_LOOKUP={
|
||||
65536.f, 46340.95001f, 32768.f, 23170.47501f,
|
||||
16384.f, 11585.2375f, 8192.f, 5792.618751f,
|
||||
4096.f, 2896.309376f, 2048.f, 1448.154688f,
|
||||
1024.f, 724.0773439f, 512.f, 362.038672f,
|
||||
256.f, 181.019336f, 128.f, 90.50966799f,
|
||||
64.f, 45.254834f, 32.f, 22.627417f,
|
||||
16.f, 11.3137085f, 8.f, 5.656854249f,
|
||||
4.f, 2.828427125f, 2.f, 1.414213562f,
|
||||
1.f, 0.7071067812f, 0.5f, 0.3535533906f,
|
||||
0.25f, 0.1767766953f, 0.125f, 0.08838834765f,
|
||||
0.0625f, 0.04419417382f, 0.03125f, 0.02209708691f,
|
||||
0.015625f, 0.01104854346f, 0.0078125f, 0.005524271728f,
|
||||
0.00390625f, 0.002762135864f, 0.001953125f, 0.001381067932f,
|
||||
0.0009765625f, 0.000690533966f, 0.00048828125f, 0.000345266983f,
|
||||
0.000244140625f,0.0001726334915f,0.0001220703125f,8.631674575e-05f,
|
||||
6.103515625e-05f,4.315837288e-05f,3.051757812e-05f,2.157918644e-05f,
|
||||
1.525878906e-05f,
|
||||
};
|
||||
/* interpolated 1./sqrt(p) where .5 <= p < 1. */
|
||||
static float invsq2explook(int a){
|
||||
return INVSQ2EXP_LOOKUP[a-INVSQ2EXP_LOOKUP_MIN];
|
||||
}
|
||||
static int INVSQ2EXP_LOOKUP_MIN=-32;
|
||||
//static int INVSQ2EXP_LOOKUP_MAX=32;
|
||||
static float[] INVSQ2EXP_LOOKUP={
|
||||
65536.0f, 46340.95001f, 32768.0f, 23170.47501f,
|
||||
16384.0f, 11585.2375f, 8192.0f, 5792.618751f,
|
||||
4096.0f, 2896.309376f, 2048.0f, 1448.154688f,
|
||||
1024.0f, 724.0773439f, 512.0f, 362.038672f,
|
||||
256.0f, 181.019336f, 128.0f, 90.50966799f,
|
||||
64.0f, 45.254834f, 32.0f, 22.627417f,
|
||||
16.0f, 11.3137085f, 8.0f, 5.656854249f,
|
||||
4.0f, 2.828427125f, 2.0f, 1.414213562f,
|
||||
1.0f, 0.7071067812f, 0.5f, 0.3535533906f,
|
||||
0.25f, 0.1767766953f, 0.125f, 0.08838834765f,
|
||||
0.0625f, 0.04419417382f, 0.03125f, 0.02209708691f,
|
||||
0.015625f, 0.01104854346f, 0.0078125f, 0.005524271728f,
|
||||
0.00390625f, 0.002762135864f, 0.001953125f, 0.001381067932f,
|
||||
0.0009765625f, 0.000690533966f, 0.00048828125f, 0.000345266983f,
|
||||
0.000244140625f,0.0001726334915f,0.0001220703125f,8.631674575e-05f,
|
||||
6.103515625e-05f,4.315837288e-05f,3.051757812e-05f,2.157918644e-05f,
|
||||
1.525878906e-05f,
|
||||
};
|
||||
/* interpolated 1./sqrt(p) where .5 <= p < 1. */
|
||||
internal static float invsq2explook(int a)
|
||||
{
|
||||
return INVSQ2EXP_LOOKUP[a-INVSQ2EXP_LOOKUP_MIN];
|
||||
}
|
||||
|
||||
const int FROMdB_LOOKUP_SZ=35;
|
||||
const int FROMdB2_LOOKUP_SZ=32;
|
||||
const int FROMdB_SHIFT=5;
|
||||
const int FROMdB2_SHIFT=3;
|
||||
const int FROMdB2_MASK=31;
|
||||
static float[] FROMdB_LOOKUP = {
|
||||
1.0f, 0.6309573445f, 0.3981071706f, 0.2511886432f,
|
||||
0.1584893192f, 0.1f, 0.06309573445f, 0.03981071706f,
|
||||
0.02511886432f, 0.01584893192f, 0.01f, 0.006309573445f,
|
||||
0.003981071706f, 0.002511886432f, 0.001584893192f, 0.001f,
|
||||
0.0006309573445f,0.0003981071706f,0.0002511886432f,0.0001584893192f,
|
||||
0.0001f,6.309573445e-05f,3.981071706e-05f,2.511886432e-05f,
|
||||
1.584893192e-05f, 1e-05f,6.309573445e-06f,3.981071706e-06f,
|
||||
2.511886432e-06f,1.584893192e-06f, 1e-06f,6.309573445e-07f,
|
||||
3.981071706e-07f,2.511886432e-07f,1.584893192e-07f,
|
||||
};
|
||||
static float[] FROMdB2_LOOKUP = {
|
||||
0.9928302478f, 0.9786445908f, 0.9646616199f, 0.9508784391f,
|
||||
0.9372921937f, 0.92390007f, 0.9106992942f, 0.8976871324f,
|
||||
0.8848608897f, 0.8722179097f, 0.8597555737f, 0.8474713009f,
|
||||
0.835362547f, 0.8234268041f, 0.8116616003f, 0.8000644989f,
|
||||
0.7886330981f, 0.7773650302f, 0.7662579617f, 0.755309592f,
|
||||
0.7445176537f, 0.7338799116f, 0.7233941627f, 0.7130582353f,
|
||||
0.7028699885f, 0.6928273125f, 0.6829281272f, 0.6731703824f,
|
||||
0.6635520573f, 0.6540711597f, 0.6447257262f, 0.6355138211f,
|
||||
};
|
||||
/* interpolated lookup based fromdB function, domain -140dB to 0dB only */
|
||||
static float fromdBlook(float a){
|
||||
int i=(int)(a*((float)(-(1<<FROMdB2_SHIFT))));
|
||||
return (i<0)?1.f:
|
||||
((i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))?0.f:
|
||||
FROMdB_LOOKUP[(uint)i>>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]);
|
||||
}
|
||||
const int FROMdB_LOOKUP_SZ=35;
|
||||
const int FROMdB2_LOOKUP_SZ=32;
|
||||
const int FROMdB_SHIFT=5;
|
||||
const int FROMdB2_SHIFT=3;
|
||||
const int FROMdB2_MASK=31;
|
||||
static float[] FROMdB_LOOKUP = {
|
||||
1.0f, 0.6309573445f, 0.3981071706f, 0.2511886432f,
|
||||
0.1584893192f, 0.1f, 0.06309573445f, 0.03981071706f,
|
||||
0.02511886432f, 0.01584893192f, 0.01f, 0.006309573445f,
|
||||
0.003981071706f, 0.002511886432f, 0.001584893192f, 0.001f,
|
||||
0.0006309573445f,0.0003981071706f,0.0002511886432f,0.0001584893192f,
|
||||
0.0001f,6.309573445e-05f,3.981071706e-05f,2.511886432e-05f,
|
||||
1.584893192e-05f, 1e-05f,6.309573445e-06f,3.981071706e-06f,
|
||||
2.511886432e-06f,1.584893192e-06f, 1e-06f,6.309573445e-07f,
|
||||
3.981071706e-07f,2.511886432e-07f,1.584893192e-07f,
|
||||
};
|
||||
static float[] FROMdB2_LOOKUP = {
|
||||
0.9928302478f, 0.9786445908f, 0.9646616199f, 0.9508784391f,
|
||||
0.9372921937f, 0.92390007f, 0.9106992942f, 0.8976871324f,
|
||||
0.8848608897f, 0.8722179097f, 0.8597555737f, 0.8474713009f,
|
||||
0.835362547f, 0.8234268041f, 0.8116616003f, 0.8000644989f,
|
||||
0.7886330981f, 0.7773650302f, 0.7662579617f, 0.755309592f,
|
||||
0.7445176537f, 0.7338799116f, 0.7233941627f, 0.7130582353f,
|
||||
0.7028699885f, 0.6928273125f, 0.6829281272f, 0.6731703824f,
|
||||
0.6635520573f, 0.6540711597f, 0.6447257262f, 0.6355138211f,
|
||||
};
|
||||
/* interpolated lookup based fromdB function, domain -140dB to 0dB only */
|
||||
internal static float fromdBlook(float a)
|
||||
{
|
||||
int i=(int)(a*((float)(-(1<<FROMdB2_SHIFT))));
|
||||
return (i<0)?1.0f:
|
||||
((i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))?0.0f:
|
||||
FROMdB_LOOKUP[(uint)i>>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
327
csvorbis/Lpc.cs
327
csvorbis/Lpc.cs
|
@ -26,229 +26,176 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
class Lpc{
|
||||
Drft fft=new Drft();
|
||||
namespace csvorbis
|
||||
{
|
||||
class Lpc
|
||||
{
|
||||
Drft fft=new Drft();
|
||||
|
||||
int ln;
|
||||
int m;
|
||||
int ln;
|
||||
int m;
|
||||
|
||||
// Autocorrelation LPC coeff generation algorithm invented by
|
||||
// N. Levinson in 1947, modified by J. Durbin in 1959.
|
||||
// Autocorrelation LPC coeff generation algorithm invented by
|
||||
// N. Levinson in 1947, modified by J. Durbin in 1959.
|
||||
|
||||
// Input : n elements of time doamin data
|
||||
// Output: m lpc coefficients, excitation energy
|
||||
// Input : n elements of time doamin data
|
||||
// Output: m lpc coefficients, excitation energy
|
||||
|
||||
static float lpc_from_data(float[] data, float[] lpc,int n,int m){
|
||||
float[] aut=new float[m+1];
|
||||
float error;
|
||||
int i,j;
|
||||
static float lpc_from_data(float[] data, float[] lpc,int n,int m)
|
||||
{
|
||||
float[] aut=new float[m+1];
|
||||
float error;
|
||||
int i,j;
|
||||
|
||||
// autocorrelation, p+1 lag coefficients
|
||||
// autocorrelation, p+1 lag coefficients
|
||||
|
||||
j=m+1;
|
||||
while(j--!=0){
|
||||
float d=0;
|
||||
for(i=j;i<n;i++)d+=data[i]*data[i-j];
|
||||
aut[j]=d;
|
||||
}
|
||||
j=m+1;
|
||||
while(j--!=0)
|
||||
{
|
||||
float d=0.0F;
|
||||
for(i=j;i<n;i++)d+=data[i]*data[i-j];
|
||||
aut[j]=d;
|
||||
}
|
||||
|
||||
// Generate lpc coefficients from autocorr values
|
||||
// Generate lpc coefficients from autocorr values
|
||||
|
||||
error=aut[0];
|
||||
/*
|
||||
if(error==0){
|
||||
for(int k=0; k<m; k++) lpc[k]=0.0f;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
error=aut[0];
|
||||
/*
|
||||
if(error==0){
|
||||
for(int k=0; k<m; k++) lpc[k]=0.0f;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
for(i=0;i<m;i++){
|
||||
float r=-aut[i+1];
|
||||
for(i=0;i<m;i++)
|
||||
{
|
||||
float r=-aut[i+1];
|
||||
|
||||
if(error==0){
|
||||
for(int k=0; k<m; k++) lpc[k]=0.0f;
|
||||
return 0;
|
||||
}
|
||||
if(error==0)
|
||||
{
|
||||
for(int k=0; k<m; k++) lpc[k]=0.0f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Sum up this iteration's reflection coefficient; note that in
|
||||
// Vorbis we don't save it. If anyone wants to recycle this code
|
||||
// and needs reflection coefficients, save the results of 'r' from
|
||||
// each iteration.
|
||||
// Sum up this iteration's reflection coefficient; note that in
|
||||
// Vorbis we don't save it. If anyone wants to recycle this code
|
||||
// and needs reflection coefficients, save the results of 'r' from
|
||||
// each iteration.
|
||||
|
||||
for(j=0;j<i;j++)r-=lpc[j]*aut[i-j];
|
||||
r/=error;
|
||||
for(j=0;j<i;j++)r-=lpc[j]*aut[i-j];
|
||||
r/=error;
|
||||
|
||||
// Update LPC coefficients and total error
|
||||
// Update LPC coefficients and total error
|
||||
|
||||
lpc[i]=r;
|
||||
for(j=0;j<i/2;j++){
|
||||
float tmp=lpc[j];
|
||||
lpc[j]+=r*lpc[i-1-j];
|
||||
lpc[i-1-j]+=r*tmp;
|
||||
}
|
||||
if(i%2!=0)lpc[j]+=lpc[j]*r;
|
||||
lpc[i]=r;
|
||||
for(j=0;j<i/2;j++)
|
||||
{
|
||||
float tmp=lpc[j];
|
||||
lpc[j]+=r*lpc[i-1-j];
|
||||
lpc[i-1-j]+=r*tmp;
|
||||
}
|
||||
if(i%2!=0)lpc[j]+=lpc[j]*r;
|
||||
|
||||
error*=1.0-r*r;
|
||||
}
|
||||
error*=(float)(1.0-r*r);
|
||||
}
|
||||
|
||||
// we need the error value to know how big an impulse to hit the
|
||||
// filter with later
|
||||
// we need the error value to know how big an impulse to hit the
|
||||
// filter with later
|
||||
|
||||
return error;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// Input : n element envelope spectral curve
|
||||
// Output: m lpc coefficients, excitation energy
|
||||
// Input : n element envelope spectral curve
|
||||
// Output: m lpc coefficients, excitation energy
|
||||
|
||||
float lpc_from_curve(float[] curve, float[] lpc){
|
||||
int n=ln;
|
||||
float[] work=new float[n+n];
|
||||
float fscale=(float)(.5/n);
|
||||
int i,j;
|
||||
float lpc_from_curve(float[] curve, float[] lpc)
|
||||
{
|
||||
int n=ln;
|
||||
float[] work=new float[n+n];
|
||||
float fscale=(float)(.5/n);
|
||||
int i,j;
|
||||
|
||||
// input is a real curve. make it complex-real
|
||||
// This mixes phase, but the LPC generation doesn't care.
|
||||
for(i=0;i<n;i++){
|
||||
work[i*2]=curve[i]*fscale;
|
||||
work[i*2+1]=0;
|
||||
}
|
||||
work[n*2-1]=curve[n-1]*fscale;
|
||||
// input is a real curve. make it complex-real
|
||||
// This mixes phase, but the LPC generation doesn't care.
|
||||
for(i=0;i<n;i++)
|
||||
{
|
||||
work[i*2]=curve[i]*fscale;
|
||||
work[i*2+1]=0;
|
||||
}
|
||||
work[n*2-1]=curve[n-1]*fscale;
|
||||
|
||||
n*=2;
|
||||
fft.backward(work);
|
||||
n*=2;
|
||||
fft.backward(work);
|
||||
|
||||
// The autocorrelation will not be circular. Shift, else we lose
|
||||
// most of the power in the edges.
|
||||
// The autocorrelation will not be circular. Shift, else we lose
|
||||
// most of the power in the edges.
|
||||
|
||||
for(i=0,j=n/2;i<n/2;){
|
||||
float temp=work[i];
|
||||
work[i++]=work[j];
|
||||
work[j++]=temp;
|
||||
}
|
||||
for(i=0,j=n/2;i<n/2;)
|
||||
{
|
||||
float temp=work[i];
|
||||
work[i++]=work[j];
|
||||
work[j++]=temp;
|
||||
}
|
||||
|
||||
return(lpc_from_data(work,lpc,n,m));
|
||||
}
|
||||
return(lpc_from_data(work,lpc,n,m));
|
||||
}
|
||||
|
||||
void init(int mapped, int m){
|
||||
//memset(l,0,sizeof(lpc_lookup));
|
||||
internal void init(int mapped, int m)
|
||||
{
|
||||
//memset(l,0,sizeof(lpc_lookup));
|
||||
Console.Error.WriteLine("lpc::init");
|
||||
ln=mapped;
|
||||
this.m=m;
|
||||
|
||||
ln=mapped;
|
||||
this.m=m;
|
||||
// we cheat decoding the LPC spectrum via FFTs
|
||||
Console.Error.WriteLine("Setting up FFT");
|
||||
fft.init(mapped*2);
|
||||
}
|
||||
|
||||
// we cheat decoding the LPC spectrum via FFTs
|
||||
fft.init(mapped*2);
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
fft.clear();
|
||||
}
|
||||
|
||||
void clear(){
|
||||
fft.clear();
|
||||
}
|
||||
static float FAST_HYPOT(float a, float b)
|
||||
{
|
||||
return (float)Math.Sqrt((a)*(a) + (b)*(b));
|
||||
}
|
||||
|
||||
static float FAST_HYPOT(float a, float b){
|
||||
return (float)Math.sqrt((a)*(a) + (b)*(b));
|
||||
}
|
||||
// One can do this the long way by generating the transfer function in
|
||||
// the time domain and taking the forward FFT of the result. The
|
||||
// results from direct calculation are cleaner and faster.
|
||||
//
|
||||
// This version does a linear curve generation and then later
|
||||
// interpolates the log curve from the linear curve.
|
||||
|
||||
// One can do this the long way by generating the transfer function in
|
||||
// the time domain and taking the forward FFT of the result. The
|
||||
// results from direct calculation are cleaner and faster.
|
||||
//
|
||||
// This version does a linear curve generation and then later
|
||||
// interpolates the log curve from the linear curve.
|
||||
internal void lpc_to_curve(float[] curve, float[] lpc, float amp)
|
||||
{
|
||||
|
||||
void lpc_to_curve(float[] curve, float[] lpc, float amp){
|
||||
//memset(curve,0,sizeof(float)*l->ln*2);
|
||||
for(int i=0; i<ln*2; i++)curve[i]=0.0f;
|
||||
|
||||
//memset(curve,0,sizeof(float)*l->ln*2);
|
||||
for(int i=0; i<ln*2; i++)curve[i]=0.0f;
|
||||
if(amp==0)return;
|
||||
|
||||
if(amp==0)return;
|
||||
for(int i=0;i<m;i++)
|
||||
{
|
||||
curve[i*2+1]=lpc[i]/(4*amp);
|
||||
curve[i*2+2]=-lpc[i]/(4*amp);
|
||||
}
|
||||
|
||||
for(int i=0;i<m;i++){
|
||||
curve[i*2+1]=lpc[i]/(4*amp);
|
||||
curve[i*2+2]=-lpc[i]/(4*amp);
|
||||
}
|
||||
fft.backward(curve); // reappropriated ;-)
|
||||
|
||||
fft.backward(curve); // reappropriated ;-)
|
||||
int l2=ln*2;
|
||||
float unit=(float)(1.0/amp);
|
||||
curve[0]=(float)(1.0/(curve[0]*2+unit));
|
||||
for(int i=1;i<ln;i++)
|
||||
{
|
||||
float real=(curve[i]+curve[l2-i]);
|
||||
float imag=(curve[i]-curve[l2-i]);
|
||||
|
||||
{
|
||||
int l2=ln*2;
|
||||
float unit=(float)(1.0/amp);
|
||||
curve[0]=(float)(1.0/(curve[0]*2+unit));
|
||||
for(int i=1;i<ln;i++){
|
||||
float real=(curve[i]+curve[l2-i]);
|
||||
float imag=(curve[i]-curve[l2-i]);
|
||||
|
||||
float a = real + unit;
|
||||
curve[i] = (float)(1.0 / FAST_HYPOT(a, imag));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// subtract or add an lpc filter to data. Vorbis doesn't actually use this.
|
||||
|
||||
static void lpc_residue(float[] coeff, float[] prime,int m,
|
||||
float[] data, int n){
|
||||
|
||||
// in: coeff[0...m-1] LPC coefficients
|
||||
// prime[0...m-1] initial values
|
||||
// data[0...n-1] data samples
|
||||
// out: data[0...n-1] residuals from LPC prediction
|
||||
|
||||
float[] work=new float[m+n];
|
||||
float y;
|
||||
|
||||
if(prime==null){
|
||||
for(int i=0;i<m;i++){
|
||||
work[i]=0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
for(int i=0;i<m;i++){
|
||||
work[i]=prime[i];
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0;i<n;i++){
|
||||
y=0;
|
||||
for(int j=0;j<m;j++){
|
||||
y-=work[i+j]*coeff[m-j-1];
|
||||
}
|
||||
work[i+m]=data[i];
|
||||
data[i]-=y;
|
||||
}
|
||||
}
|
||||
|
||||
static void lpc_predict(float[] coeff, float[] prime,int m,
|
||||
float[] data, int n){
|
||||
|
||||
// in: coeff[0...m-1] LPC coefficients
|
||||
// prime[0...m-1] initial values (allocated size of n+m-1)
|
||||
// data[0...n-1] residuals from LPC prediction
|
||||
// out: data[0...n-1] data samples
|
||||
|
||||
int o,p;
|
||||
float y;
|
||||
float[] work=new float[m+n];
|
||||
|
||||
if(prime==null){
|
||||
for(int i=0;i<m;i++){
|
||||
work[i]=0.f;
|
||||
}
|
||||
}
|
||||
else{
|
||||
for(int i=0;i<m;i++){
|
||||
work[i]=prime[i];
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0;i<n;i++){
|
||||
y=data[i];
|
||||
o=i;
|
||||
p=m;
|
||||
for(int j=0;j<m;j++){
|
||||
y-=work[o++]*coeff[--p];
|
||||
}
|
||||
data[i]=work[o]=y;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
float a = real + unit;
|
||||
curve[i] = (float)(1.0 / FAST_HYPOT(a, imag));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
170
csvorbis/Lsp.cs
170
csvorbis/Lsp.cs
|
@ -24,98 +24,110 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using csogg;
|
||||
|
||||
/*
|
||||
function: LSP (also called LSF) conversion routines
|
||||
|
||||
The LSP generation code is taken (with minimal modification) from
|
||||
"On the Computation of the LSP Frequencies" by Joseph Rothweiler
|
||||
<rothwlr@altavista.net>, available at:
|
||||
|
||||
http://www2.xtdl.com/~rothwlr/lsfpaper/lsfpage.html
|
||||
********************************************************************/
|
||||
|
||||
class Lsp
|
||||
namespace csvorbis
|
||||
{
|
||||
/*
|
||||
function: LSP (also called LSF) conversion routines
|
||||
|
||||
static float M_PI=(float)(3.1415926539);
|
||||
The LSP generation code is taken (with minimal modification) from
|
||||
"On the Computation of the LSP Frequencies" by Joseph Rothweiler
|
||||
<rothwlr@altavista.net>, available at:
|
||||
|
||||
http://www2.xtdl.com/~rothwlr/lsfpaper/lsfpage.html
|
||||
********************************************************************/
|
||||
|
||||
static void lsp_to_curve(float[] curve,
|
||||
int[] map, int n, int ln,
|
||||
float[] lsp, int m,
|
||||
float amp, float ampoffset)
|
||||
class Lsp
|
||||
{
|
||||
int i;
|
||||
float wdel=M_PI/ln;
|
||||
for(i=0;i<m;i++)lsp[i]=Lookup.coslook(lsp[i]);
|
||||
int m2=(m/2)*2;
|
||||
|
||||
i=0;
|
||||
while(i<n)
|
||||
[StructLayout(LayoutKind.Explicit, Size=32, CharSet=CharSet.Ansi)]
|
||||
class FloatHack
|
||||
{
|
||||
int k=map[i];
|
||||
float p=.7071067812f;
|
||||
float q=.7071067812f;
|
||||
float w=Lookup.coslook(wdel*k);
|
||||
int ftmp=0;
|
||||
int c=(uint)m >> 1;
|
||||
[FieldOffset(0)] public float fh_float;
|
||||
[FieldOffset(0)] public int fh_int;
|
||||
}
|
||||
static float M_PI=(float)(3.1415926539);
|
||||
|
||||
for(int j=0;j<m2;j+=2)
|
||||
{
|
||||
q*=lsp[j]-w;
|
||||
p*=lsp[j+1]-w;
|
||||
}
|
||||
internal static void lsp_to_curve(float[] curve,
|
||||
int[] map, int n, int ln,
|
||||
float[] lsp, int m,
|
||||
float amp, float ampoffset)
|
||||
{
|
||||
int i;
|
||||
float wdel=M_PI/ln;
|
||||
for(i=0;i<m;i++)lsp[i]=Lookup.coslook(lsp[i]);
|
||||
int m2=(m/2)*2;
|
||||
|
||||
if((m&1)!=0)
|
||||
i=0;
|
||||
while(i<n)
|
||||
{
|
||||
/* odd order filter; slightly assymetric */
|
||||
/* the last coefficient */
|
||||
q*=lsp[m-1]-w;
|
||||
q*=q;
|
||||
p*=p*(1.f-w*w);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* even order filter; still symmetric */
|
||||
q*=q*(1.f+w);
|
||||
p*=p*(1.f-w);
|
||||
}
|
||||
FloatHack fh = new FloatHack();
|
||||
int k=map[i];
|
||||
float p=.7071067812f;
|
||||
float q=.7071067812f;
|
||||
float w=Lookup.coslook(wdel*k);
|
||||
//int ftmp=0;
|
||||
int c=(int)((uint)m >> 1);
|
||||
|
||||
// q=frexp(p+q,&qexp);
|
||||
q=p+q;
|
||||
int hx=Float.floatToIntBits(q);
|
||||
int ix=0x7fffffff&hx;
|
||||
int qexp=0;
|
||||
|
||||
if(ix>=0x7f800000||(ix==0))
|
||||
{
|
||||
// 0,inf,nan
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ix<0x00800000)
|
||||
{ // subnormal
|
||||
q*=3.3554432000e+07; // 0x4c000000
|
||||
hx=Float.floatToIntBits(q);
|
||||
ix=0x7fffffff&hx;
|
||||
qexp=-25;
|
||||
for(int j=0;j<m2;j+=2)
|
||||
{
|
||||
q*=lsp[j]-w;
|
||||
p*=lsp[j+1]-w;
|
||||
}
|
||||
qexp += (((uint)ix >> 23)-126);
|
||||
hx=(hx&0x807fffff)|0x3f000000;
|
||||
q=Float.intBitsToFloat(hx);
|
||||
|
||||
if((m&1)!=0)
|
||||
{
|
||||
/* odd order filter; slightly assymetric */
|
||||
/* the last coefficient */
|
||||
q*=lsp[m-1]-w;
|
||||
q*=q;
|
||||
p*=p*(1.0f-w*w);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* even order filter; still symmetric */
|
||||
q*=q*(1.0f+w);
|
||||
p*=p*(1.0f-w);
|
||||
}
|
||||
|
||||
// q=frexp(p+q,&qexp);
|
||||
q=p+q;
|
||||
fh.fh_float = q;
|
||||
int hx=fh.fh_int;
|
||||
int ix=0x7fffffff&hx;
|
||||
int qexp=0;
|
||||
|
||||
if(ix>=0x7f800000||(ix==0))
|
||||
{
|
||||
// 0,inf,nan
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ix<0x00800000)
|
||||
{ // subnormal
|
||||
q*=3.3554432000e+07F; // 0x4c000000
|
||||
fh.fh_float = q;
|
||||
hx=fh.fh_int;
|
||||
ix=0x7fffffff&hx;
|
||||
qexp=-25;
|
||||
}
|
||||
qexp += (int)(((uint)ix >> 23)-126);
|
||||
hx=(int)((hx&0x807fffff)|0x3f000000);
|
||||
fh.fh_int = hx;
|
||||
q=fh.fh_float;
|
||||
}
|
||||
|
||||
q=Lookup.fromdBlook(amp*
|
||||
Lookup.invsqlook(q)*
|
||||
Lookup.invsq2explook(qexp+m)-ampoffset);
|
||||
|
||||
do{curve[i++]*=q;}
|
||||
// do{curve[i++]=q;}
|
||||
while(i<n&&map[i]==k);
|
||||
|
||||
}
|
||||
|
||||
q=Lookup.fromdBlook(amp*
|
||||
Lookup.invsqlook(q)*
|
||||
Lookup.invsq2explook(qexp+m)-ampoffset);
|
||||
|
||||
do{curve[i++]*=q;}
|
||||
// do{curve[i++]=q;}
|
||||
while(i<n&&map[i]==k);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -26,428 +26,437 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
class Mapping0 : FuncMapping
|
||||
namespace csvorbis
|
||||
{
|
||||
static int seq=0;
|
||||
void free_info(Object imap){}
|
||||
void free_look(Object imap){}
|
||||
|
||||
Object look(DspState vd, InfoMode vm, Object m)
|
||||
class Mapping0 : FuncMapping
|
||||
{
|
||||
Info vi=vd.vi;
|
||||
LookMapping0 look=new LookMapping0();
|
||||
InfoMapping0 info=look.map=(InfoMapping0)m;
|
||||
look.mode=vm;
|
||||
|
||||
look.time_look=new Object[info.submaps];
|
||||
look.floor_look=new Object[info.submaps];
|
||||
look.residue_look=new Object[info.submaps];
|
||||
//static int seq=0;
|
||||
override public void free_info(Object imap){}
|
||||
override public void free_look(Object imap){}
|
||||
|
||||
look.time_func=new FuncTime[info.submaps];
|
||||
look.floor_func=new FuncFloor[info.submaps];
|
||||
look.residue_func=new FuncResidue[info.submaps];
|
||||
|
||||
for(int i=0;i<info.submaps;i++)
|
||||
override public Object look(DspState vd, InfoMode vm, Object m)
|
||||
{
|
||||
int timenum=info.timesubmap[i];
|
||||
int floornum=info.floorsubmap[i];
|
||||
int resnum=info.residuesubmap[i];
|
||||
|
||||
look.time_func[i]=FuncTime.time_P[vi.time_type[timenum]];
|
||||
look.time_look[i]=look.time_func[i].look(vd,vm,vi.time_param[timenum]);
|
||||
look.floor_func[i]=FuncFloor.floor_P[vi.floor_type[floornum]];
|
||||
look.floor_look[i]=look.floor_func[i].
|
||||
look(vd,vm,vi.floor_param[floornum]);
|
||||
look.residue_func[i]=FuncResidue.residue_P[vi.residue_type[resnum]];
|
||||
look.residue_look[i]=look.residue_func[i].
|
||||
look(vd,vm,vi.residue_param[resnum]);
|
||||
|
||||
}
|
||||
|
||||
if(vi.psys!=0 && vd.analysisp!=0)
|
||||
{
|
||||
}
|
||||
|
||||
look.ch=vi.channels;
|
||||
|
||||
return(look);
|
||||
}
|
||||
|
||||
void pack(Info vi, Object imap, csBuffer opb)
|
||||
{
|
||||
InfoMapping0 info=(InfoMapping0)imap;
|
||||
|
||||
/* another 'we meant to do it this way' hack... up to beta 4, we
|
||||
packed 4 binary zeros here to signify one submapping in use. We
|
||||
now redefine that to mean four bitflags that indicate use of
|
||||
deeper features; bit0:submappings, bit1:coupling,
|
||||
bit2,3:reserved. This is backward compatable with all actual uses
|
||||
of the beta code. */
|
||||
|
||||
if(info.submaps>1)
|
||||
{
|
||||
opb.write(1,1);
|
||||
opb.write(info.submaps-1,4);
|
||||
}
|
||||
else
|
||||
{
|
||||
opb.write(0,1);
|
||||
}
|
||||
|
||||
if(info.coupling_steps>0)
|
||||
{
|
||||
opb.write(1,1);
|
||||
opb.write(info.coupling_steps-1,8);
|
||||
for(int i=0;i<info.coupling_steps;i++)
|
||||
{
|
||||
opb.write(info.coupling_mag[i],ilog2(vi.channels));
|
||||
opb.write(info.coupling_ang[i],ilog2(vi.channels));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
opb.write(0,1);
|
||||
}
|
||||
|
||||
opb.write(0,2); /* 2,3:reserved */
|
||||
|
||||
/* we don't write the channel submappings if we only have one... */
|
||||
if(info.submaps>1)
|
||||
{
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
opb.write(info.chmuxlist[i],4);
|
||||
}
|
||||
for(int i=0;i<info.submaps;i++)
|
||||
{
|
||||
opb.write(info.timesubmap[i],8);
|
||||
opb.write(info.floorsubmap[i],8);
|
||||
opb.write(info.residuesubmap[i],8);
|
||||
}
|
||||
}
|
||||
|
||||
// also responsible for range checking
|
||||
Object unpack(Info vi, csBuffer opb)
|
||||
{
|
||||
InfoMapping0 info=new InfoMapping0();
|
||||
|
||||
// !!!!
|
||||
if(opb.read(1)!=0)
|
||||
{
|
||||
info.submaps=opb.read(4)+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
info.submaps=1;
|
||||
}
|
||||
|
||||
if(opb.read(1)!=0)
|
||||
{
|
||||
info.coupling_steps=opb.read(8)+1;
|
||||
|
||||
for(int i=0;i<info.coupling_steps;i++)
|
||||
{
|
||||
int testM=info.coupling_mag[i]=opb.read(ilog2(vi.channels));
|
||||
int testA=info.coupling_ang[i]=opb.read(ilog2(vi.channels));
|
||||
|
||||
if(testM<0 ||
|
||||
testA<0 ||
|
||||
testM==testA ||
|
||||
testM>=vi.channels ||
|
||||
testA>=vi.channels)
|
||||
{
|
||||
//goto err_out;
|
||||
info.free();
|
||||
return(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(opb.read(2)>0)
|
||||
{ /* 2,3:reserved */
|
||||
//goto err_out;
|
||||
info.free();
|
||||
return(null);
|
||||
}
|
||||
|
||||
if(info.submaps>1)
|
||||
{
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
{
|
||||
info.chmuxlist[i]=opb.read(4);
|
||||
if(info.chmuxlist[i]>=info.submaps)
|
||||
{
|
||||
//goto err_out;
|
||||
info.free();
|
||||
return(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0;i<info.submaps;i++)
|
||||
{
|
||||
info.timesubmap[i]=opb.read(8);
|
||||
if(info.timesubmap[i]>=vi.times)
|
||||
{
|
||||
//goto err_out;
|
||||
info.free();
|
||||
return(null);
|
||||
}
|
||||
info.floorsubmap[i]=opb.read(8);
|
||||
if(info.floorsubmap[i]>=vi.floors)
|
||||
{
|
||||
//goto err_out;
|
||||
info.free();
|
||||
return(null);
|
||||
}
|
||||
info.residuesubmap[i]=opb.read(8);
|
||||
if(info.residuesubmap[i]>=vi.residues)
|
||||
{
|
||||
//goto err_out;
|
||||
info.free();
|
||||
return(null);
|
||||
}
|
||||
}
|
||||
return info;
|
||||
//err_out:
|
||||
//free_info(info);
|
||||
//return(NULL);
|
||||
}
|
||||
|
||||
|
||||
float[][] pcmbundle=null;
|
||||
int[] zerobundle=null;
|
||||
int[] nonzero=null;
|
||||
Object[] floormemo=null;
|
||||
|
||||
int inverse(Block vb, Object l)
|
||||
{
|
||||
lock(this)
|
||||
{
|
||||
//System.err.println("Mapping0.inverse");
|
||||
DspState vd=vb.vd;
|
||||
Console.Error.WriteLine("Mapping0");
|
||||
Info vi=vd.vi;
|
||||
LookMapping0 look=(LookMapping0)l;
|
||||
InfoMapping0 info=look.map;
|
||||
InfoMode mode=look.mode;
|
||||
int n=vb.pcmend=vi.blocksizes[vb.W];
|
||||
LookMapping0 looks=new LookMapping0();
|
||||
InfoMapping0 info=looks.map=(InfoMapping0)m;
|
||||
looks.mode=vm;
|
||||
|
||||
looks.time_look=new Object[info.submaps];
|
||||
looks.floor_look=new Object[info.submaps];
|
||||
looks.residue_look=new Object[info.submaps];
|
||||
|
||||
float[] window=vd.window[vb.W][vb.lW][vb.nW][mode.windowtype];
|
||||
// float[][] pcmbundle=new float[vi.channels][];
|
||||
// int[] nonzero=new int[vi.channels];
|
||||
if(pcmbundle==null || pcmbundle.length<vi.channels)
|
||||
looks.time_func=new FuncTime[info.submaps];
|
||||
looks.floor_func=new FuncFloor[info.submaps];
|
||||
looks.residue_func=new FuncResidue[info.submaps];
|
||||
|
||||
Console.Error.WriteLine("info.submaps: "+info.submaps);
|
||||
for(int i=0;i<info.submaps;i++)
|
||||
{
|
||||
pcmbundle=new float[vi.channels][];
|
||||
nonzero=new int[vi.channels];
|
||||
zerobundle=new int[vi.channels];
|
||||
floormemo=new Object[vi.channels];
|
||||
int timenum=info.timesubmap[i];
|
||||
int floornum=info.floorsubmap[i];
|
||||
int resnum=info.residuesubmap[i];
|
||||
|
||||
looks.time_func[i]=FuncTime.time_P[vi.time_type[timenum]];
|
||||
looks.time_look[i]=looks.time_func[i].look(vd,vm,vi.time_param[timenum]);
|
||||
Console.Error.WriteLine("TIME");
|
||||
looks.floor_func[i]=FuncFloor.floor_P[vi.floor_type[floornum]];
|
||||
Console.Error.WriteLine("FLO: floornum:" + floornum);
|
||||
looks.floor_look[i]=looks.floor_func[i].
|
||||
look(vd,vm,vi.floor_param[floornum]);
|
||||
Console.Error.WriteLine("FLOOR");
|
||||
looks.residue_func[i]=FuncResidue.residue_P[vi.residue_type[resnum]];
|
||||
looks.residue_look[i]=looks.residue_func[i].
|
||||
look(vd,vm,vi.residue_param[resnum]);
|
||||
Console.Error.WriteLine("RESIDUE");
|
||||
|
||||
}
|
||||
|
||||
if(vi.psys!=0 && vd.analysisp!=0)
|
||||
{
|
||||
}
|
||||
|
||||
looks.ch=vi.channels;
|
||||
|
||||
return(looks);
|
||||
}
|
||||
|
||||
override public void pack(Info vi, Object imap, csBuffer opb)
|
||||
{
|
||||
InfoMapping0 info=(InfoMapping0)imap;
|
||||
|
||||
/* another 'we meant to do it this way' hack... up to beta 4, we
|
||||
packed 4 binary zeros here to signify one submapping in use. We
|
||||
now redefine that to mean four bitflags that indicate use of
|
||||
deeper features; bit0:submappings, bit1:coupling,
|
||||
bit2,3:reserved. This is backward compatable with all actual uses
|
||||
of the beta code. */
|
||||
|
||||
if(info.submaps>1)
|
||||
{
|
||||
opb.write(1,1);
|
||||
opb.write(info.submaps-1,4);
|
||||
}
|
||||
else
|
||||
{
|
||||
opb.write(0,1);
|
||||
}
|
||||
|
||||
if(info.coupling_steps>0)
|
||||
{
|
||||
opb.write(1,1);
|
||||
opb.write(info.coupling_steps-1,8);
|
||||
for(int i=0;i<info.coupling_steps;i++)
|
||||
{
|
||||
opb.write(info.coupling_mag[i],ilog2(vi.channels));
|
||||
opb.write(info.coupling_ang[i],ilog2(vi.channels));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
opb.write(0,1);
|
||||
}
|
||||
|
||||
// time domain information decode (note that applying the
|
||||
// information would have to happen later; we'll probably add a
|
||||
// function entry to the harness for that later
|
||||
// NOT IMPLEMENTED
|
||||
opb.write(0,2); /* 2,3:reserved */
|
||||
|
||||
// recover the spectral envelope; store it in the PCM vector for now
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
/* we don't write the channel submappings if we only have one... */
|
||||
if(info.submaps>1)
|
||||
{
|
||||
float[] pcm=vb.pcm[i];
|
||||
int submap=info.chmuxlist[i];
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
opb.write(info.chmuxlist[i],4);
|
||||
}
|
||||
for(int i=0;i<info.submaps;i++)
|
||||
{
|
||||
opb.write(info.timesubmap[i],8);
|
||||
opb.write(info.floorsubmap[i],8);
|
||||
opb.write(info.residuesubmap[i],8);
|
||||
}
|
||||
}
|
||||
|
||||
floormemo[i]=look.floor_func[submap].inverse1(vb,look.
|
||||
floor_look[submap],
|
||||
floormemo[i]
|
||||
);
|
||||
if(floormemo[i]!=null){ nonzero[i]=1; }
|
||||
else{ nonzero[i]=0; }
|
||||
for(int j=0; j<n/2; j++)
|
||||
{
|
||||
pcm[j]=0;
|
||||
}
|
||||
override public Object unpack(Info vi, csBuffer opb)
|
||||
{
|
||||
// also responsible for range checking
|
||||
InfoMapping0 info=new InfoMapping0();
|
||||
|
||||
//_analysis_output("ifloor",seq+i,pcm,n/2,0,1);
|
||||
// !!!!
|
||||
if(opb.read(1)!=0)
|
||||
{
|
||||
info.submaps=opb.read(4)+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
info.submaps=1;
|
||||
}
|
||||
|
||||
for(int i=0; i<info.coupling_steps; i++)
|
||||
if(opb.read(1)!=0)
|
||||
{
|
||||
if(nonzero[info.coupling_mag[i]]!=0 ||
|
||||
nonzero[info.coupling_ang[i]]!=0)
|
||||
info.coupling_steps=opb.read(8)+1;
|
||||
|
||||
for(int i=0;i<info.coupling_steps;i++)
|
||||
{
|
||||
nonzero[info.coupling_mag[i]]=1;
|
||||
nonzero[info.coupling_ang[i]]=1;
|
||||
int testM=info.coupling_mag[i]=opb.read(ilog2(vi.channels));
|
||||
int testA=info.coupling_ang[i]=opb.read(ilog2(vi.channels));
|
||||
|
||||
if(testM<0 ||
|
||||
testA<0 ||
|
||||
testM==testA ||
|
||||
testM>=vi.channels ||
|
||||
testA>=vi.channels)
|
||||
{
|
||||
//goto err_out;
|
||||
info.free();
|
||||
return(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// recover the residue, apply directly to the spectral envelope
|
||||
if(opb.read(2)>0)
|
||||
{ /* 2,3:reserved */
|
||||
//goto err_out;
|
||||
info.free();
|
||||
return(null);
|
||||
}
|
||||
|
||||
if(info.submaps>1)
|
||||
{
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
{
|
||||
info.chmuxlist[i]=opb.read(4);
|
||||
if(info.chmuxlist[i]>=info.submaps)
|
||||
{
|
||||
//goto err_out;
|
||||
info.free();
|
||||
return(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0;i<info.submaps;i++)
|
||||
{
|
||||
int ch_in_bundle=0;
|
||||
for(int j=0;j<vi.channels;j++)
|
||||
info.timesubmap[i]=opb.read(8);
|
||||
if(info.timesubmap[i]>=vi.times)
|
||||
{
|
||||
if(info.chmuxlist[j]==i)
|
||||
//goto err_out;
|
||||
info.free();
|
||||
return(null);
|
||||
}
|
||||
info.floorsubmap[i]=opb.read(8);
|
||||
if(info.floorsubmap[i]>=vi.floors)
|
||||
{
|
||||
//goto err_out;
|
||||
info.free();
|
||||
return(null);
|
||||
}
|
||||
info.residuesubmap[i]=opb.read(8);
|
||||
if(info.residuesubmap[i]>=vi.residues)
|
||||
{
|
||||
//goto err_out;
|
||||
info.free();
|
||||
return(null);
|
||||
}
|
||||
}
|
||||
return info;
|
||||
//err_out:
|
||||
//free_info(info);
|
||||
//return(NULL);
|
||||
}
|
||||
|
||||
|
||||
float[][] pcmbundle=null;
|
||||
int[] zerobundle=null;
|
||||
int[] nonzero=null;
|
||||
Object[] floormemo=null;
|
||||
|
||||
override public int inverse(Block vb, Object l)
|
||||
{
|
||||
lock(this)
|
||||
{
|
||||
//System.err.println("Mapping0.inverse");
|
||||
DspState vd=vb.vd;
|
||||
Info vi=vd.vi;
|
||||
LookMapping0 look=(LookMapping0)l;
|
||||
InfoMapping0 info=look.map;
|
||||
InfoMode mode=look.mode;
|
||||
int n=vb.pcmend=vi.blocksizes[vb.W];
|
||||
|
||||
float[] window=vd.wnd[vb.W][vb.lW][vb.nW][mode.windowtype];
|
||||
// float[][] pcmbundle=new float[vi.channels][];
|
||||
// int[] nonzero=new int[vi.channels];
|
||||
if(pcmbundle==null || pcmbundle.Length<vi.channels)
|
||||
{
|
||||
pcmbundle=new float[vi.channels][];
|
||||
nonzero=new int[vi.channels];
|
||||
zerobundle=new int[vi.channels];
|
||||
floormemo=new Object[vi.channels];
|
||||
}
|
||||
|
||||
// time domain information decode (note that applying the
|
||||
// information would have to happen later; we'll probably add a
|
||||
// function entry to the harness for that later
|
||||
// NOT IMPLEMENTED
|
||||
|
||||
// recover the spectral envelope; store it in the PCM vector for now
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
{
|
||||
float[] pcm=vb.pcm[i];
|
||||
int submap=info.chmuxlist[i];
|
||||
|
||||
floormemo[i]=look.floor_func[submap].inverse1(vb,look.
|
||||
floor_look[submap],
|
||||
floormemo[i]
|
||||
);
|
||||
if(floormemo[i]!=null){ nonzero[i]=1; }
|
||||
else{ nonzero[i]=0; }
|
||||
for(int j=0; j<n/2; j++)
|
||||
{
|
||||
if(nonzero[j]!=0)
|
||||
{
|
||||
zerobundle[ch_in_bundle]=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
zerobundle[ch_in_bundle]=0;
|
||||
}
|
||||
pcmbundle[ch_in_bundle++]=vb.pcm[j];
|
||||
pcm[j]=0;
|
||||
}
|
||||
|
||||
//_analysis_output("ifloor",seq+i,pcm,n/2,0,1);
|
||||
}
|
||||
|
||||
for(int i=0; i<info.coupling_steps; i++)
|
||||
{
|
||||
if(nonzero[info.coupling_mag[i]]!=0 ||
|
||||
nonzero[info.coupling_ang[i]]!=0)
|
||||
{
|
||||
nonzero[info.coupling_mag[i]]=1;
|
||||
nonzero[info.coupling_ang[i]]=1;
|
||||
}
|
||||
}
|
||||
|
||||
look.residue_func[i].inverse(vb,look.residue_look[i],
|
||||
pcmbundle,zerobundle,ch_in_bundle);
|
||||
}
|
||||
// recover the residue, apply directly to the spectral envelope
|
||||
|
||||
|
||||
for(int i=info.coupling_steps-1;i>=0;i--)
|
||||
{
|
||||
float[] pcmM=vb.pcm[info.coupling_mag[i]];
|
||||
float[] pcmA=vb.pcm[info.coupling_ang[i]];
|
||||
|
||||
for(int j=0;j<n/2;j++)
|
||||
for(int i=0;i<info.submaps;i++)
|
||||
{
|
||||
float mag=pcmM[j];
|
||||
float ang=pcmA[j];
|
||||
|
||||
if(mag>0)
|
||||
int ch_in_bundle=0;
|
||||
for(int j=0;j<vi.channels;j++)
|
||||
{
|
||||
if(ang>0)
|
||||
if(info.chmuxlist[j]==i)
|
||||
{
|
||||
pcmM[j]=mag;
|
||||
pcmA[j]=mag-ang;
|
||||
if(nonzero[j]!=0)
|
||||
{
|
||||
zerobundle[ch_in_bundle]=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
zerobundle[ch_in_bundle]=0;
|
||||
}
|
||||
pcmbundle[ch_in_bundle++]=vb.pcm[j];
|
||||
}
|
||||
}
|
||||
|
||||
look.residue_func[i].inverse(vb,look.residue_look[i],
|
||||
pcmbundle,zerobundle,ch_in_bundle);
|
||||
}
|
||||
|
||||
|
||||
for(int i=info.coupling_steps-1;i>=0;i--)
|
||||
{
|
||||
float[] pcmM=vb.pcm[info.coupling_mag[i]];
|
||||
float[] pcmA=vb.pcm[info.coupling_ang[i]];
|
||||
|
||||
for(int j=0;j<n/2;j++)
|
||||
{
|
||||
float mag=pcmM[j];
|
||||
float ang=pcmA[j];
|
||||
|
||||
if(mag>0)
|
||||
{
|
||||
if(ang>0)
|
||||
{
|
||||
pcmM[j]=mag;
|
||||
pcmA[j]=mag-ang;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcmA[j]=mag;
|
||||
pcmM[j]=mag+ang;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pcmA[j]=mag;
|
||||
pcmM[j]=mag+ang;
|
||||
if(ang>0)
|
||||
{
|
||||
pcmM[j]=mag;
|
||||
pcmA[j]=mag+ang;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcmA[j]=mag;
|
||||
pcmM[j]=mag-ang;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// /* compute and apply spectral envelope */
|
||||
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
{
|
||||
float[] pcm=vb.pcm[i];
|
||||
int submap=info.chmuxlist[i];
|
||||
look.floor_func[submap].inverse2(vb,look.floor_look[submap],floormemo[i],pcm);
|
||||
}
|
||||
|
||||
// transform the PCM data; takes PCM vector, vb; modifies PCM vector
|
||||
// only MDCT right now....
|
||||
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
{
|
||||
float[] pcm=vb.pcm[i];
|
||||
//_analysis_output("out",seq+i,pcm,n/2,0,0);
|
||||
((Mdct)vd.transform[vb.W][0]).backward(pcm,pcm);
|
||||
}
|
||||
|
||||
// now apply the decoded pre-window time information
|
||||
// NOT IMPLEMENTED
|
||||
|
||||
// window the data
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
{
|
||||
float[] pcm=vb.pcm[i];
|
||||
if(nonzero[i]!=0)
|
||||
{
|
||||
for(int j=0;j<n;j++)
|
||||
{
|
||||
pcm[j]*=window[j];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ang>0)
|
||||
for(int j=0;j<n;j++)
|
||||
{
|
||||
pcmM[j]=mag;
|
||||
pcmA[j]=mag+ang;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcmA[j]=mag;
|
||||
pcmM[j]=mag-ang;
|
||||
pcm[j]=0.0f;
|
||||
}
|
||||
}
|
||||
//_analysis_output("final",seq++,pcm,n,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
// /* compute and apply spectral envelope */
|
||||
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
{
|
||||
float[] pcm=vb.pcm[i];
|
||||
int submap=info.chmuxlist[i];
|
||||
look.floor_func[submap].inverse2(vb,look.floor_look[submap],floormemo[i],pcm);
|
||||
}
|
||||
|
||||
// transform the PCM data; takes PCM vector, vb; modifies PCM vector
|
||||
// only MDCT right now....
|
||||
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
{
|
||||
float[] pcm=vb.pcm[i];
|
||||
//_analysis_output("out",seq+i,pcm,n/2,0,0);
|
||||
((Mdct)vd.transform[vb.W][0]).backward(pcm,pcm);
|
||||
}
|
||||
|
||||
// now apply the decoded pre-window time information
|
||||
// NOT IMPLEMENTED
|
||||
|
||||
// window the data
|
||||
for(int i=0;i<vi.channels;i++)
|
||||
{
|
||||
float[] pcm=vb.pcm[i];
|
||||
if(nonzero[i]!=0)
|
||||
{
|
||||
for(int j=0;j<n;j++)
|
||||
{
|
||||
pcm[j]*=window[j];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int j=0;j<n;j++)
|
||||
{
|
||||
pcm[j]=0.f;
|
||||
}
|
||||
}
|
||||
//_analysis_output("final",seq++,pcm,n,0,0);
|
||||
}
|
||||
|
||||
// now apply the decoded post-window time information
|
||||
// NOT IMPLEMENTED
|
||||
// all done!
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int ilog2(int v)
|
||||
{
|
||||
int ret=0;
|
||||
while(v>1)
|
||||
{
|
||||
ret++;
|
||||
(uint)v >>= 1;
|
||||
// now apply the decoded post-window time information
|
||||
// NOT IMPLEMENTED
|
||||
// all done!
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int ilog2(int v)
|
||||
{
|
||||
int ret=0;
|
||||
while(v>1)
|
||||
{
|
||||
ret++;
|
||||
v = (int)((uint)v >> 1);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
}
|
||||
|
||||
class InfoMapping0
|
||||
{
|
||||
int submaps; // <= 16
|
||||
int[] chmuxlist=new int[256]; // up to 256 channels in a Vorbis stream
|
||||
|
||||
int[] timesubmap=new int[16]; // [mux]
|
||||
int[] floorsubmap=new int[16]; // [mux] submap to floors
|
||||
int[] residuesubmap=new int[16];// [mux] submap to residue
|
||||
int[] psysubmap=new int[16]; // [mux]; encode only
|
||||
|
||||
int coupling_steps;
|
||||
int[] coupling_mag=new int[256];
|
||||
int[] coupling_ang=new int[256];
|
||||
|
||||
void free()
|
||||
class InfoMapping0
|
||||
{
|
||||
chmuxlist=null;
|
||||
timesubmap=null;
|
||||
floorsubmap=null;
|
||||
residuesubmap=null;
|
||||
psysubmap=null;
|
||||
internal int submaps; // <= 16
|
||||
internal int[] chmuxlist=new int[256]; // up to 256 channels in a Vorbis stream
|
||||
|
||||
internal int[] timesubmap=new int[16]; // [mux]
|
||||
internal int[] floorsubmap=new int[16]; // [mux] submap to floors
|
||||
internal int[] residuesubmap=new int[16];// [mux] submap to residue
|
||||
internal int[] psysubmap=new int[16]; // [mux]; encode only
|
||||
|
||||
coupling_mag=null;
|
||||
coupling_ang=null;
|
||||
internal int coupling_steps;
|
||||
internal int[] coupling_mag=new int[256];
|
||||
internal int[] coupling_ang=new int[256];
|
||||
|
||||
internal void free()
|
||||
{
|
||||
chmuxlist=null;
|
||||
timesubmap=null;
|
||||
floorsubmap=null;
|
||||
residuesubmap=null;
|
||||
psysubmap=null;
|
||||
|
||||
coupling_mag=null;
|
||||
coupling_ang=null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LookMapping0
|
||||
{
|
||||
InfoMode mode;
|
||||
InfoMapping0 map;
|
||||
Object[] time_look;
|
||||
Object[] floor_look;
|
||||
Object[] floor_state;
|
||||
Object[] residue_look;
|
||||
PsyLook[] psy_look;
|
||||
class LookMapping0
|
||||
{
|
||||
internal InfoMode mode;
|
||||
internal InfoMapping0 map;
|
||||
internal Object[] time_look;
|
||||
internal Object[] floor_look;
|
||||
//Object[] floor_state;
|
||||
internal Object[] residue_look;
|
||||
//PsyLook[] psy_look;
|
||||
|
||||
FuncTime[] time_func;
|
||||
FuncFloor[] floor_func;
|
||||
FuncResidue[] residue_func;
|
||||
internal FuncTime[] time_func;
|
||||
internal FuncFloor[] floor_func;
|
||||
internal FuncResidue[] residue_func;
|
||||
|
||||
int ch;
|
||||
float[][] decay;
|
||||
int lastframe; // if a different mode is called, we need to
|
||||
// invalidate decay and floor state
|
||||
}
|
||||
internal int ch;
|
||||
//float[][] decay;
|
||||
//int lastframe; // if a different mode is called, we need to
|
||||
// invalidate decay and floor state
|
||||
}
|
||||
}
|
413
csvorbis/Mdct.cs
413
csvorbis/Mdct.cs
|
@ -26,246 +26,249 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
class Mdct
|
||||
namespace csvorbis
|
||||
{
|
||||
class Mdct
|
||||
{
|
||||
|
||||
static private float cPI3_8=0.38268343236508977175f;
|
||||
static private float cPI2_8=0.70710678118654752441f;
|
||||
static private float cPI1_8=0.92387953251128675613f;
|
||||
//static private float cPI3_8=0.38268343236508977175f;
|
||||
//static private float cPI2_8=0.70710678118654752441f;
|
||||
//static private float cPI1_8=0.92387953251128675613f;
|
||||
|
||||
int n;
|
||||
int log2n;
|
||||
int n;
|
||||
int log2n;
|
||||
|
||||
float[] trig;
|
||||
int[] bitrev;
|
||||
float[] trig;
|
||||
int[] bitrev;
|
||||
|
||||
float scale;
|
||||
float scale;
|
||||
|
||||
void init(int n)
|
||||
{
|
||||
bitrev=new int[n/4];
|
||||
trig=new float[n+n/4];
|
||||
|
||||
int n2=(uint)n >> 1;
|
||||
log2n=(int)Math.rint(Math.log(n)/Math.log(2));
|
||||
this.n=n;
|
||||
|
||||
|
||||
int AE=0;
|
||||
int AO=1;
|
||||
int BE=AE+n/2;
|
||||
int BO=BE+1;
|
||||
int CE=BE+n/2;
|
||||
int CO=CE+1;
|
||||
// trig lookups...
|
||||
for(int i=0;i<n/4;i++)
|
||||
internal void init(int n)
|
||||
{
|
||||
trig[AE+i*2]=(float)Math.cos((Math.PI/n)*(4*i));
|
||||
trig[AO+i*2]=(float)-Math.sin((Math.PI/n)*(4*i));
|
||||
trig[BE+i*2]=(float)Math.cos((Math.PI/(2*n))*(2*i+1));
|
||||
trig[BO+i*2]=(float)Math.sin((Math.PI/(2*n))*(2*i+1));
|
||||
bitrev=new int[n/4];
|
||||
trig=new float[n+n/4];
|
||||
|
||||
int n2=(int)((uint)n >> 1);
|
||||
log2n=(int)Math.Round(Math.Log(n)/Math.Log(2));
|
||||
this.n=n;
|
||||
|
||||
|
||||
int AE=0;
|
||||
int AO=1;
|
||||
int BE=AE+n/2;
|
||||
int BO=BE+1;
|
||||
int CE=BE+n/2;
|
||||
int CO=CE+1;
|
||||
// trig lookups...
|
||||
for(int i=0;i<n/4;i++)
|
||||
{
|
||||
trig[AE+i*2]=(float)Math.Cos((Math.PI/n)*(4*i));
|
||||
trig[AO+i*2]=(float)-Math.Sin((Math.PI/n)*(4*i));
|
||||
trig[BE+i*2]=(float)Math.Cos((Math.PI/(2*n))*(2*i+1));
|
||||
trig[BO+i*2]=(float)Math.Sin((Math.PI/(2*n))*(2*i+1));
|
||||
}
|
||||
for(int i=0;i<n/8;i++)
|
||||
{
|
||||
trig[CE+i*2]=(float)Math.Cos((Math.PI/n)*(4*i+2));
|
||||
trig[CO+i*2]=(float)-Math.Sin((Math.PI/n)*(4*i+2));
|
||||
}
|
||||
|
||||
{
|
||||
int mask=(1<<(log2n-1))-1;
|
||||
int msb=1<<(log2n-2);
|
||||
for(int i=0;i<n/8;i++)
|
||||
{
|
||||
int acc=0;
|
||||
for(int j=0; (((uint)msb) >> j) != 0; j++)
|
||||
if(((((uint)msb>>j))&i) != 0)
|
||||
acc |= 1 << j;
|
||||
bitrev[i*2]=((~acc)&mask);
|
||||
// bitrev[i*2]=((~acc)&mask)-1;
|
||||
bitrev[i*2+1]=acc;
|
||||
}
|
||||
}
|
||||
for(int i=0;i<n/8;i++)
|
||||
{
|
||||
trig[CE+i*2]=(float)Math.cos((Math.PI/n)*(4*i+2));
|
||||
trig[CO+i*2]=(float)-Math.sin((Math.PI/n)*(4*i+2));
|
||||
scale=4.0f/n;
|
||||
}
|
||||
|
||||
{
|
||||
int mask=(1<<(log2n-1))-1;
|
||||
int msb=1<<(log2n-2);
|
||||
for(int i=0;i<n/8;i++)
|
||||
internal void clear()
|
||||
{
|
||||
int acc=0;
|
||||
for(int j=0; (((uint)msb) >> j) != 0; j++)
|
||||
if(((((uint)msb>>j))&i) != 0)
|
||||
acc |= 1 << j;
|
||||
bitrev[i*2]=((~acc)&mask);
|
||||
// bitrev[i*2]=((~acc)&mask)-1;
|
||||
bitrev[i*2+1]=acc;
|
||||
}
|
||||
}
|
||||
scale=4.f/n;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
}
|
||||
|
||||
void forward(float[] fin, float[] fout)
|
||||
{
|
||||
}
|
||||
|
||||
float[] _x=new float[1024];
|
||||
float[] _w=new float[1024];
|
||||
|
||||
void backward(float[] fin, float[] fout)
|
||||
{
|
||||
lock(this)
|
||||
{
|
||||
if(_x.length < n/2){_x=new float[n/2];}
|
||||
if(_w.length < n/2){_w=new float[n/2];}
|
||||
float[] x=_x;
|
||||
float[] w=_w;
|
||||
int n2=(uint)n >> 1;
|
||||
int n4=(uint)n >> 2;
|
||||
int n8=(uint)n >> 3;
|
||||
|
||||
// rotate + step 1
|
||||
internal void forward(float[] fin, float[] fout)
|
||||
{
|
||||
int inO=1;
|
||||
int xO=0;
|
||||
}
|
||||
|
||||
float[] _x=new float[1024];
|
||||
float[] _w=new float[1024];
|
||||
|
||||
internal void backward(float[] fin, float[] fout)
|
||||
{
|
||||
lock(this)
|
||||
{
|
||||
if(_x.Length < n/2){_x=new float[n/2];}
|
||||
if(_w.Length < n/2){_w=new float[n/2];}
|
||||
float[] x=_x;
|
||||
float[] w=_w;
|
||||
int n2=(int)((uint)n >> 1);
|
||||
int n4=(int)((uint)n >> 2);
|
||||
int n8=(int)((uint)n >> 3);
|
||||
|
||||
// rotate + step 1
|
||||
{
|
||||
int inO=1;
|
||||
int xO=0;
|
||||
int A=n2;
|
||||
|
||||
int i;
|
||||
for(i=0;i<n8;i++)
|
||||
{
|
||||
A-=2;
|
||||
x[xO++]=-fin[inO+2]*trig[A+1] - fin[inO]*trig[A];
|
||||
x[xO++]= fin[inO]*trig[A+1] - fin[inO+2]*trig[A];
|
||||
inO+=4;
|
||||
}
|
||||
|
||||
inO=n2-4;
|
||||
|
||||
for(i=0;i<n8;i++)
|
||||
{
|
||||
A-=2;
|
||||
x[xO++]=fin[inO]*trig[A+1] + fin[inO+2]*trig[A];
|
||||
x[xO++]=fin[inO]*trig[A] - fin[inO+2]*trig[A+1];
|
||||
inO-=4;
|
||||
}
|
||||
}
|
||||
|
||||
float[] xxx=mdct_kernel(x,w,n,n2,n4,n8);
|
||||
int xx=0;
|
||||
|
||||
// step 8
|
||||
|
||||
{
|
||||
int B=n2;
|
||||
int o1=n4,o2=o1-1;
|
||||
int o3=n4+n2,o4=o3-1;
|
||||
|
||||
for(int i=0;i<n4;i++)
|
||||
{
|
||||
float temp1= (xxx[xx] * trig[B+1] - xxx[xx+1] * trig[B]);
|
||||
float temp2=-(xxx[xx] * trig[B] + xxx[xx+1] * trig[B+1]);
|
||||
|
||||
fout[o1]=-temp1;
|
||||
fout[o2]= temp1;
|
||||
fout[o3]= temp2;
|
||||
fout[o4]= temp2;
|
||||
|
||||
o1++;
|
||||
o2--;
|
||||
o3++;
|
||||
o4--;
|
||||
xx+=2;
|
||||
B+=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
internal float[] mdct_kernel(float[] x, float[] w,
|
||||
int n, int n2, int n4, int n8)
|
||||
{
|
||||
// step 2
|
||||
|
||||
int xA=n4;
|
||||
int xB=0;
|
||||
int w2=n4;
|
||||
int A=n2;
|
||||
|
||||
int i;
|
||||
for(i=0;i<n8;i++)
|
||||
for(int i=0;i<n4;)
|
||||
{
|
||||
A-=2;
|
||||
x[xO++]=-fin[inO+2]*trig[A+1] - fin[inO]*trig[A];
|
||||
x[xO++]= fin[inO]*trig[A+1] - fin[inO+2]*trig[A];
|
||||
inO+=4;
|
||||
float x0=x[xA] - x[xB];
|
||||
float x1;
|
||||
w[w2+i]=x[xA++]+x[xB++];
|
||||
|
||||
x1=x[xA]-x[xB];
|
||||
A-=4;
|
||||
|
||||
w[i++]= x0 * trig[A] + x1 * trig[A+1];
|
||||
w[i]= x1 * trig[A] - x0 * trig[A+1];
|
||||
|
||||
w[w2+i]=x[xA++]+x[xB++];
|
||||
i++;
|
||||
}
|
||||
|
||||
inO=n2-4;
|
||||
|
||||
for(i=0;i<n8;i++)
|
||||
{
|
||||
A-=2;
|
||||
x[xO++]=fin[inO]*trig[A+1] + fin[inO+2]*trig[A];
|
||||
x[xO++]=fin[inO]*trig[A] - fin[inO+2]*trig[A+1];
|
||||
inO-=4;
|
||||
}
|
||||
}
|
||||
|
||||
float[] xxx=mdct_kernel(x,w,n,n2,n4,n8);
|
||||
int xx=0;
|
||||
|
||||
// step 8
|
||||
// step 3
|
||||
|
||||
{
|
||||
int B=n2;
|
||||
int o1=n4,o2=o1-1;
|
||||
int o3=n4+n2,o4=o3-1;
|
||||
|
||||
for(int i=0;i<n4;i++)
|
||||
for(int i=0;i<log2n-3;i++)
|
||||
{
|
||||
float temp1= (xxx[xx] * trig[B+1] - xxx[xx+1] * trig[B]);
|
||||
float temp2=-(xxx[xx] * trig[B] + xxx[xx+1] * trig[B+1]);
|
||||
|
||||
fout[o1]=-temp1;
|
||||
fout[o2]= temp1;
|
||||
fout[o3]= temp2;
|
||||
fout[o4]= temp2;
|
||||
int k0=(int)((uint)n >> (i+2));
|
||||
int k1=1 << (i+3);
|
||||
int wbase=n2-2;
|
||||
|
||||
o1++;
|
||||
o2--;
|
||||
o3++;
|
||||
o4--;
|
||||
xx+=2;
|
||||
B+=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private float[] mdct_kernel(float[] x, float[] w,
|
||||
int n, int n2, int n4, int n8)
|
||||
{
|
||||
// step 2
|
||||
A=0;
|
||||
float[] temp;
|
||||
|
||||
int xA=n4;
|
||||
int xB=0;
|
||||
int w2=n4;
|
||||
int A=n2;
|
||||
|
||||
for(int i=0;i<n4;)
|
||||
{
|
||||
float x0=x[xA] - x[xB];
|
||||
float x1;
|
||||
w[w2+i]=x[xA++]+x[xB++];
|
||||
|
||||
x1=x[xA]-x[xB];
|
||||
A-=4;
|
||||
|
||||
w[i++]= x0 * trig[A] + x1 * trig[A+1];
|
||||
w[i]= x1 * trig[A] - x0 * trig[A+1];
|
||||
|
||||
w[w2+i]=x[xA++]+x[xB++];
|
||||
i++;
|
||||
}
|
||||
|
||||
// step 3
|
||||
|
||||
{
|
||||
for(int i=0;i<log2n-3;i++)
|
||||
{
|
||||
int k0=(uint)n >> (i+2);
|
||||
int k1=1 << (i+3);
|
||||
int wbase=n2-2;
|
||||
|
||||
A=0;
|
||||
float[] temp;
|
||||
|
||||
for(int r=0; r<((uint)k0>>2); r++)
|
||||
{
|
||||
int w1=wbase;
|
||||
w2=w1-(k0>>1);
|
||||
float AEv= trig[A],wA;
|
||||
float AOv= trig[A+1],wB;
|
||||
wbase-=2;
|
||||
|
||||
k0++;
|
||||
for(int s=0;s<(2<<i);s++)
|
||||
for(int r=0; r<((uint)k0>>2); r++)
|
||||
{
|
||||
wB =w[w1] -w[w2];
|
||||
x[w1] =w[w1] +w[w2];
|
||||
int w1=wbase;
|
||||
w2=w1-(k0>>1);
|
||||
float AEv= trig[A],wA;
|
||||
float AOv= trig[A+1],wB;
|
||||
wbase-=2;
|
||||
|
||||
k0++;
|
||||
for(int s=0;s<(2<<i);s++)
|
||||
{
|
||||
wB =w[w1] -w[w2];
|
||||
x[w1] =w[w1] +w[w2];
|
||||
|
||||
wA =w[++w1] -w[++w2];
|
||||
x[w1] =w[w1] +w[w2];
|
||||
wA =w[++w1] -w[++w2];
|
||||
x[w1] =w[w1] +w[w2];
|
||||
|
||||
x[w2] =wA*AEv - wB*AOv;
|
||||
x[w2-1]=wB*AEv + wA*AOv;
|
||||
x[w2] =wA*AEv - wB*AOv;
|
||||
x[w2-1]=wB*AEv + wA*AOv;
|
||||
|
||||
w1-=k0;
|
||||
w2-=k0;
|
||||
w1-=k0;
|
||||
w2-=k0;
|
||||
}
|
||||
k0--;
|
||||
A+=k1;
|
||||
}
|
||||
k0--;
|
||||
A+=k1;
|
||||
|
||||
temp=w;
|
||||
w=x;
|
||||
x=temp;
|
||||
}
|
||||
|
||||
temp=w;
|
||||
w=x;
|
||||
x=temp;
|
||||
}
|
||||
}
|
||||
|
||||
// step 4, 5, 6, 7
|
||||
{
|
||||
int C=n;
|
||||
int bit=0;
|
||||
int x1=0;
|
||||
int x2=n2-1;
|
||||
|
||||
for(int i=0;i<n8;i++)
|
||||
// step 4, 5, 6, 7
|
||||
{
|
||||
int t1=bitrev[bit++];
|
||||
int t2=bitrev[bit++];
|
||||
int C=n;
|
||||
int bit=0;
|
||||
int x1=0;
|
||||
int x2=n2-1;
|
||||
|
||||
float wA=w[t1]-w[t2+1];
|
||||
float wB=w[t1-1]+w[t2];
|
||||
float wC=w[t1]+w[t2+1];
|
||||
float wD=w[t1-1]-w[t2];
|
||||
for(int i=0;i<n8;i++)
|
||||
{
|
||||
int t1=bitrev[bit++];
|
||||
int t2=bitrev[bit++];
|
||||
|
||||
float wACE=wA* trig[C];
|
||||
float wBCE=wB* trig[C++];
|
||||
float wACO=wA* trig[C];
|
||||
float wBCO=wB* trig[C++];
|
||||
float wA=w[t1]-w[t2+1];
|
||||
float wB=w[t1-1]+w[t2];
|
||||
float wC=w[t1]+w[t2+1];
|
||||
float wD=w[t1-1]-w[t2];
|
||||
|
||||
float wACE=wA* trig[C];
|
||||
float wBCE=wB* trig[C++];
|
||||
float wACO=wA* trig[C];
|
||||
float wBCO=wB* trig[C++];
|
||||
|
||||
x[x1++]=( wC+wACO+wBCE)*.5f;
|
||||
x[x2--]=(-wD+wBCO-wACE)*.5f;
|
||||
x[x1++]=( wD+wBCO-wACE)*.5f;
|
||||
x[x2--]=( wC-wACO-wBCE)*.5f;
|
||||
x[x1++]=( wC+wACO+wBCE)*.5f;
|
||||
x[x2--]=(-wD+wBCO-wACE)*.5f;
|
||||
x[x1++]=( wD+wBCO-wACE)*.5f;
|
||||
x[x2--]=( wC-wACO-wBCE)*.5f;
|
||||
}
|
||||
}
|
||||
return(x);
|
||||
}
|
||||
}
|
||||
return(x);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,49 +26,52 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
// psychoacoustic setup
|
||||
class PsyInfo
|
||||
{
|
||||
int athp;
|
||||
int decayp;
|
||||
int smoothp;
|
||||
int noisefitp;
|
||||
int noisefit_subblock;
|
||||
float noisefit_threshdB;
|
||||
namespace csvorbis
|
||||
{
|
||||
// psychoacoustic setup
|
||||
class PsyInfo
|
||||
{
|
||||
//int athp;
|
||||
//int decayp;
|
||||
//int smoothp;
|
||||
//int noisefitp;
|
||||
//int noisefit_subblock;
|
||||
//float noisefit_threshdB;
|
||||
|
||||
float ath_att;
|
||||
//float ath_att;
|
||||
|
||||
int tonemaskp;
|
||||
float[] toneatt_125Hz=new float[5];
|
||||
float[] toneatt_250Hz=new float[5];
|
||||
float[] toneatt_500Hz=new float[5];
|
||||
float[] toneatt_1000Hz=new float[5];
|
||||
float[] toneatt_2000Hz=new float[5];
|
||||
float[] toneatt_4000Hz=new float[5];
|
||||
float[] toneatt_8000Hz=new float[5];
|
||||
//int tonemaskp;
|
||||
float[] toneatt_125Hz=new float[5];
|
||||
float[] toneatt_250Hz=new float[5];
|
||||
float[] toneatt_500Hz=new float[5];
|
||||
float[] toneatt_1000Hz=new float[5];
|
||||
float[] toneatt_2000Hz=new float[5];
|
||||
float[] toneatt_4000Hz=new float[5];
|
||||
float[] toneatt_8000Hz=new float[5];
|
||||
|
||||
int peakattp;
|
||||
float[] peakatt_125Hz=new float[5];
|
||||
float[] peakatt_250Hz=new float[5];
|
||||
float[] peakatt_500Hz=new float[5];
|
||||
float[] peakatt_1000Hz=new float[5];
|
||||
float[] peakatt_2000Hz=new float[5];
|
||||
float[] peakatt_4000Hz=new float[5];
|
||||
float[] peakatt_8000Hz=new float[5];
|
||||
//int peakattp;
|
||||
float[] peakatt_125Hz=new float[5];
|
||||
float[] peakatt_250Hz=new float[5];
|
||||
float[] peakatt_500Hz=new float[5];
|
||||
float[] peakatt_1000Hz=new float[5];
|
||||
float[] peakatt_2000Hz=new float[5];
|
||||
float[] peakatt_4000Hz=new float[5];
|
||||
float[] peakatt_8000Hz=new float[5];
|
||||
|
||||
int noisemaskp;
|
||||
float[] noiseatt_125Hz=new float[5];
|
||||
float[] noiseatt_250Hz=new float[5];
|
||||
float[] noiseatt_500Hz=new float[5];
|
||||
float[] noiseatt_1000Hz=new float[5];
|
||||
float[] noiseatt_2000Hz=new float[5];
|
||||
float[] noiseatt_4000Hz=new float[5];
|
||||
float[] noiseatt_8000Hz=new float[5];
|
||||
//int noisemaskp;
|
||||
float[] noiseatt_125Hz=new float[5];
|
||||
float[] noiseatt_250Hz=new float[5];
|
||||
float[] noiseatt_500Hz=new float[5];
|
||||
float[] noiseatt_1000Hz=new float[5];
|
||||
float[] noiseatt_2000Hz=new float[5];
|
||||
float[] noiseatt_4000Hz=new float[5];
|
||||
float[] noiseatt_8000Hz=new float[5];
|
||||
|
||||
float max_curve_dB;
|
||||
//float max_curve_dB;
|
||||
|
||||
float attack_coeff;
|
||||
float decay_coeff;
|
||||
//float attack_coeff;
|
||||
//float decay_coeff;
|
||||
|
||||
void free(){}
|
||||
}
|
||||
internal void free(){}
|
||||
}
|
||||
}
|
|
@ -26,19 +26,22 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
class PsyLook
|
||||
namespace csvorbis
|
||||
{
|
||||
int n;
|
||||
PsyInfo vi;
|
||||
|
||||
float[][][] tonecurves;
|
||||
float[][] peakatt;
|
||||
float[][][] noisecurves;
|
||||
|
||||
float[] ath;
|
||||
int[] octave;
|
||||
|
||||
void init(PsyInfo vi, int n, int rate)
|
||||
class PsyLook
|
||||
{
|
||||
//int n;
|
||||
//PsyInfo vi;
|
||||
|
||||
//float[][][] tonecurves;
|
||||
//float[][] peakatt;
|
||||
//float[][][] noisecurves;
|
||||
|
||||
//float[] ath;
|
||||
//int[] octave;
|
||||
|
||||
void init(PsyInfo vi, int n, int rate)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,350 +24,393 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using csogg;
|
||||
|
||||
class Residue0 : FuncResidue{
|
||||
void pack(Object vr, csBuffer opb){
|
||||
InfoResidue0 info=(InfoResidue0)vr;
|
||||
int acc=0;
|
||||
opb.write(info.begin,24);
|
||||
opb.write(info.end,24);
|
||||
|
||||
opb.write(info.grouping-1,24); /* residue vectors to group and
|
||||
code with a partitioned book */
|
||||
opb.write(info.partitions-1,6); /* possible partition choices */
|
||||
opb.write(info.groupbook,8); /* group huffman book */
|
||||
|
||||
/* secondstages is a bitmask; as encoding progresses pass by pass, a
|
||||
bitmask of one indicates this partition class has bits to write
|
||||
this pass */
|
||||
for(int j=0;j<info.partitions;j++){
|
||||
if(ilog(info.secondstages[j])>3){
|
||||
/* yes, this is a minor hack due to not thinking ahead */
|
||||
opb.write(info.secondstages[j],3);
|
||||
opb.write(1,1);
|
||||
opb.write(info.secondstages[j] >> 3,5);
|
||||
}
|
||||
else{
|
||||
opb.write(info.secondstages[j],4); /* trailing zero */
|
||||
}
|
||||
acc+=icount(info.secondstages[j]);
|
||||
}
|
||||
for(int j=0;j<acc;j++){
|
||||
opb.write(info.booklist[j],8);
|
||||
}
|
||||
}
|
||||
|
||||
Object unpack(Info vi, csBuffer opb){
|
||||
int acc=0;
|
||||
InfoResidue0 info=new InfoResidue0();
|
||||
|
||||
info.begin=opb.read(24);
|
||||
info.end=opb.read(24);
|
||||
info.grouping=opb.read(24)+1;
|
||||
info.partitions=opb.read(6)+1;
|
||||
info.groupbook=opb.read(8);
|
||||
|
||||
for(int j=0;j<info.partitions;j++){
|
||||
int cascade=opb.read(3);
|
||||
if(opb.read(1)!=0){
|
||||
cascade|=(opb.read(5)<<3);
|
||||
}
|
||||
info.secondstages[j]=cascade;
|
||||
acc+=icount(cascade);
|
||||
}
|
||||
|
||||
for(int j=0;j<acc;j++){
|
||||
info.booklist[j]=opb.read(8);
|
||||
// if(info.booklist[j]==255)info.booklist[j]=-1;
|
||||
}
|
||||
|
||||
if(info.groupbook>=vi.books){
|
||||
free_info(info);
|
||||
return(null);
|
||||
}
|
||||
|
||||
for(int j=0;j<acc;j++){
|
||||
if(info.booklist[j]>=vi.books){
|
||||
free_info(info);
|
||||
return(null);
|
||||
}
|
||||
}
|
||||
return(info);
|
||||
// errout:
|
||||
// free_info(info);
|
||||
// return(NULL);
|
||||
}
|
||||
|
||||
Object look(DspState vd, InfoMode vm, Object vr){
|
||||
InfoResidue0 info=(InfoResidue0)vr;
|
||||
LookResidue0 look=new LookResidue0();
|
||||
int acc=0;
|
||||
int dim;
|
||||
int maxstage=0;
|
||||
look.info=info;
|
||||
look.map=vm.mapping;
|
||||
|
||||
look.parts=info.partitions;
|
||||
look.fullbooks=vd.fullbooks;
|
||||
look.phrasebook=vd.fullbooks[info.groupbook];
|
||||
|
||||
dim=look.phrasebook.dim;
|
||||
|
||||
look.partbooks=new int[look.parts][];
|
||||
|
||||
for(int j=0;j<look.parts;j++){
|
||||
int stages=ilog(info.secondstages[j]);
|
||||
if(stages!=0){
|
||||
if(stages>maxstage)maxstage=stages;
|
||||
look.partbooks[j]=new int[stages];
|
||||
for(int k=0; k<stages; k++){
|
||||
if((info.secondstages[j]&(1<<k))!=0){
|
||||
look.partbooks[j][k]=info.booklist[acc++];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
look.partvals=(int)Math.rint(Math.pow(look.parts,dim));
|
||||
look.stages=maxstage;
|
||||
look.decodemap=new int[look.partvals][];
|
||||
for(int j=0;j<look.partvals;j++){
|
||||
int val=j;
|
||||
int mult=look.partvals/look.parts;
|
||||
look.decodemap[j]=new int[dim];
|
||||
|
||||
for(int k=0;k<dim;k++){
|
||||
int deco=val/mult;
|
||||
val-=deco*mult;
|
||||
mult/=look.parts;
|
||||
look.decodemap[j][k]=deco;
|
||||
}
|
||||
}
|
||||
return(look);
|
||||
}
|
||||
|
||||
void free_info(Object i){}
|
||||
void free_look(Object i){}
|
||||
int forward(Block vb,Object vl, float[][] fin, int ch){
|
||||
System.err.println("Residue0.forward: not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int[][][] partword=new int[2][][]; // _01inverse is synchronized for
|
||||
// re-using partword
|
||||
static int _01inverse(Block vb, Object vl, float[][] fin, int ch, int decodepart)
|
||||
namespace csvorbis
|
||||
{
|
||||
class Residue0 : FuncResidue
|
||||
{
|
||||
lock(this)
|
||||
{
|
||||
int i,j,k,l,s;
|
||||
LookResidue0 look=(LookResidue0 )vl;
|
||||
InfoResidue0 info=look.info;
|
||||
override public void pack(Object vr, csBuffer opb)
|
||||
{
|
||||
InfoResidue0 info=(InfoResidue0)vr;
|
||||
int acc=0;
|
||||
opb.write(info.begin,24);
|
||||
opb.write(info.end,24);
|
||||
|
||||
// move all this setup out later
|
||||
int samples_per_partition=info.grouping;
|
||||
int partitions_per_word=look.phrasebook.dim;
|
||||
int n=info.end-info.begin;
|
||||
opb.write(info.grouping-1,24); /* residue vectors to group and
|
||||
code with a partitioned book */
|
||||
opb.write(info.partitions-1,6); /* possible partition choices */
|
||||
opb.write(info.groupbook,8); /* group huffman book */
|
||||
|
||||
/* secondstages is a bitmask; as encoding progresses pass by pass, a
|
||||
bitmask of one indicates this partition class has bits to write
|
||||
this pass */
|
||||
for(int j=0;j<info.partitions;j++)
|
||||
{
|
||||
if(ilog(info.secondstages[j])>3)
|
||||
{
|
||||
/* yes, this is a minor hack due to not thinking ahead */
|
||||
opb.write(info.secondstages[j],3);
|
||||
opb.write(1,1);
|
||||
opb.write(info.secondstages[j] >> 3,5);
|
||||
}
|
||||
else
|
||||
{
|
||||
opb.write(info.secondstages[j],4); /* trailing zero */
|
||||
}
|
||||
acc+=icount(info.secondstages[j]);
|
||||
}
|
||||
for(int j=0;j<acc;j++)
|
||||
{
|
||||
opb.write(info.booklist[j],8);
|
||||
}
|
||||
}
|
||||
|
||||
override public Object unpack(Info vi, csBuffer opb)
|
||||
{
|
||||
int acc=0;
|
||||
InfoResidue0 info=new InfoResidue0();
|
||||
|
||||
info.begin=opb.read(24);
|
||||
info.end=opb.read(24);
|
||||
info.grouping=opb.read(24)+1;
|
||||
info.partitions=opb.read(6)+1;
|
||||
info.groupbook=opb.read(8);
|
||||
|
||||
for(int j=0;j<info.partitions;j++)
|
||||
{
|
||||
int cascade=opb.read(3);
|
||||
if(opb.read(1)!=0)
|
||||
{
|
||||
cascade|=(opb.read(5)<<3);
|
||||
}
|
||||
info.secondstages[j]=cascade;
|
||||
acc+=icount(cascade);
|
||||
}
|
||||
|
||||
for(int j=0;j<acc;j++)
|
||||
{
|
||||
info.booklist[j]=opb.read(8);
|
||||
// if(info.booklist[j]==255)info.booklist[j]=-1;
|
||||
}
|
||||
|
||||
if(info.groupbook>=vi.books)
|
||||
{
|
||||
free_info(info);
|
||||
return(null);
|
||||
}
|
||||
|
||||
for(int j=0;j<acc;j++)
|
||||
{
|
||||
if(info.booklist[j]>=vi.books)
|
||||
{
|
||||
free_info(info);
|
||||
return(null);
|
||||
}
|
||||
}
|
||||
return(info);
|
||||
// errout:
|
||||
// free_info(info);
|
||||
// return(NULL);
|
||||
}
|
||||
|
||||
override public Object look(DspState vd, InfoMode vm, Object vr)
|
||||
{
|
||||
InfoResidue0 info=(InfoResidue0)vr;
|
||||
LookResidue0 look=new LookResidue0();
|
||||
int acc=0;
|
||||
int dim;
|
||||
int maxstage=0;
|
||||
look.info=info;
|
||||
look.map=vm.mapping;
|
||||
|
||||
look.parts=info.partitions;
|
||||
look.fullbooks=vd.fullbooks;
|
||||
look.phrasebook=vd.fullbooks[info.groupbook];
|
||||
|
||||
dim=look.phrasebook.dim;
|
||||
|
||||
look.partbooks=new int[look.parts][];
|
||||
|
||||
for(int j=0;j<look.parts;j++)
|
||||
{
|
||||
int stages=ilog(info.secondstages[j]);
|
||||
if(stages!=0)
|
||||
{
|
||||
if(stages>maxstage)maxstage=stages;
|
||||
look.partbooks[j]=new int[stages];
|
||||
for(int k=0; k<stages; k++)
|
||||
{
|
||||
if((info.secondstages[j]&(1<<k))!=0)
|
||||
{
|
||||
look.partbooks[j][k]=info.booklist[acc++];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
look.partvals=(int)Math.Round(Math.Pow(look.parts,dim));
|
||||
look.stages=maxstage;
|
||||
look.decodemap=new int[look.partvals][];
|
||||
for(int j=0;j<look.partvals;j++)
|
||||
{
|
||||
int val=j;
|
||||
int mult=look.partvals/look.parts;
|
||||
look.decodemap[j]=new int[dim];
|
||||
|
||||
for(int k=0;k<dim;k++)
|
||||
{
|
||||
int deco=val/mult;
|
||||
val-=deco*mult;
|
||||
mult/=look.parts;
|
||||
look.decodemap[j][k]=deco;
|
||||
}
|
||||
}
|
||||
return(look);
|
||||
}
|
||||
|
||||
override public void free_info(Object i){}
|
||||
override public void free_look(Object i){}
|
||||
override public int forward(Block vb,Object vl, float[][] fin, int ch)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int[][][] partword=new int[2][][]; // _01inverse is synchronized for
|
||||
// re-using partword
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
internal static int _01inverse(Block vb, Object vl, float[][] fin, int ch, int decodepart)
|
||||
{
|
||||
{
|
||||
int i,j,k,l,s;
|
||||
LookResidue0 look=(LookResidue0 )vl;
|
||||
InfoResidue0 info=look.info;
|
||||
|
||||
// move all this setup out later
|
||||
int samples_per_partition=info.grouping;
|
||||
int partitions_per_word=look.phrasebook.dim;
|
||||
int n=info.end-info.begin;
|
||||
|
||||
int partvals=n/samples_per_partition;
|
||||
int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
|
||||
int partvals=n/samples_per_partition;
|
||||
int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
|
||||
|
||||
if(partword.length<ch)
|
||||
{
|
||||
partword=new int[ch][][];
|
||||
for(j=0;j<ch;j++)
|
||||
{
|
||||
partword[j]=new int[partwords][];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(j=0;j<ch;j++)
|
||||
{
|
||||
if(partword[j]==null || partword[j].length<partwords)
|
||||
partword[j]=new int[partwords][];
|
||||
}
|
||||
}
|
||||
if(partword.Length<ch)
|
||||
{
|
||||
partword=new int[ch][][];
|
||||
for(j=0;j<ch;j++)
|
||||
{
|
||||
partword[j]=new int[partwords][];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(j=0;j<ch;j++)
|
||||
{
|
||||
if(partword[j]==null || partword[j].Length<partwords)
|
||||
partword[j]=new int[partwords][];
|
||||
}
|
||||
}
|
||||
|
||||
for(s=0;s<look.stages;s++)
|
||||
{
|
||||
// each loop decodes on partition codeword containing
|
||||
// partitions_pre_word partitions
|
||||
for(i=0,l=0;i<partvals;l++)
|
||||
{
|
||||
if(s==0)
|
||||
{
|
||||
// fetch the partition word for each channel
|
||||
for(j=0;j<ch;j++)
|
||||
{
|
||||
int temp=look.phrasebook.decode(vb.opb);
|
||||
if(temp==-1)
|
||||
{
|
||||
//goto eopbreak;
|
||||
return(0);
|
||||
}
|
||||
partword[j][l]=look.decodemap[temp];
|
||||
if(partword[j][l]==null)
|
||||
{
|
||||
// goto errout;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(s=0;s<look.stages;s++)
|
||||
{
|
||||
// each loop decodes on partition codeword containing
|
||||
// partitions_pre_word partitions
|
||||
for(i=0,l=0;i<partvals;l++)
|
||||
{
|
||||
if(s==0)
|
||||
{
|
||||
// fetch the partition word for each channel
|
||||
for(j=0;j<ch;j++)
|
||||
{
|
||||
int temp=look.phrasebook.decode(vb.opb);
|
||||
if(temp==-1)
|
||||
{
|
||||
//goto eopbreak;
|
||||
return(0);
|
||||
}
|
||||
partword[j][l]=look.decodemap[temp];
|
||||
if(partword[j][l]==null)
|
||||
{
|
||||
// goto errout;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now we decode residual values for the partitions
|
||||
for(k=0;k<partitions_per_word && i<partvals;k++,i++)
|
||||
for(j=0;j<ch;j++)
|
||||
{
|
||||
int offset=info.begin+i*samples_per_partition;
|
||||
if((info.secondstages[partword[j][l][k]]&(1<<s))!=0)
|
||||
{
|
||||
CodeBook stagebook=look.fullbooks[look.partbooks[partword[j][l][k]][s]];
|
||||
// CodeBook stagebook=look.partbooks[partword[j][l][k]][s];
|
||||
if(stagebook!=null)
|
||||
{
|
||||
if(decodepart==0)
|
||||
{
|
||||
if(stagebook.decodevs_add(fin[j],offset,vb.opb,samples_per_partition)==-1)
|
||||
{
|
||||
// goto errout;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
else if(decodepart==1)
|
||||
{
|
||||
if(stagebook.decodev_add(fin[j], offset, vb.opb,samples_per_partition)==-1)
|
||||
{
|
||||
// goto errout;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
// now we decode residual values for the partitions
|
||||
for(k=0;k<partitions_per_word && i<partvals;k++,i++)
|
||||
for(j=0;j<ch;j++)
|
||||
{
|
||||
int offset=info.begin+i*samples_per_partition;
|
||||
if((info.secondstages[partword[j][l][k]]&(1<<s))!=0)
|
||||
{
|
||||
CodeBook stagebook=look.fullbooks[look.partbooks[partword[j][l][k]][s]];
|
||||
// CodeBook stagebook=look.partbooks[partword[j][l][k]][s];
|
||||
if(stagebook!=null)
|
||||
{
|
||||
if(decodepart==0)
|
||||
{
|
||||
if(stagebook.decodevs_add(fin[j],offset,vb.opb,samples_per_partition)==-1)
|
||||
{
|
||||
// goto errout;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
else if(decodepart==1)
|
||||
{
|
||||
if(stagebook.decodev_add(fin[j], offset, vb.opb,samples_per_partition)==-1)
|
||||
{
|
||||
// goto errout;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
static int _2inverse(Block vb, Object vl, float[][] fin, int ch){
|
||||
int i,j,k,l,s;
|
||||
LookResidue0 look=(LookResidue0 )vl;
|
||||
InfoResidue0 info=look.info;
|
||||
internal static int _2inverse(Block vb, Object vl, float[][] fin, int ch)
|
||||
{
|
||||
int i,k,l,s;
|
||||
LookResidue0 look=(LookResidue0 )vl;
|
||||
InfoResidue0 info=look.info;
|
||||
|
||||
// move all this setup out later
|
||||
int samples_per_partition=info.grouping;
|
||||
int partitions_per_word=look.phrasebook.dim;
|
||||
int n=info.end-info.begin;
|
||||
// move all this setup out later
|
||||
int samples_per_partition=info.grouping;
|
||||
int partitions_per_word=look.phrasebook.dim;
|
||||
int n=info.end-info.begin;
|
||||
|
||||
int partvals=n/samples_per_partition;
|
||||
int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
|
||||
int partvals=n/samples_per_partition;
|
||||
int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
|
||||
|
||||
int[][] partword=new int[partwords][];
|
||||
for(s=0;s<look.stages;s++){
|
||||
for(i=0,l=0;i<partvals;l++){
|
||||
if(s==0){
|
||||
// fetch the partition word for each channel
|
||||
int temp=look.phrasebook.decode(vb.opb);
|
||||
if(temp==-1){
|
||||
// goto eopbreak;
|
||||
return(0);
|
||||
}
|
||||
partword[l]=look.decodemap[temp];
|
||||
if(partword[l]==null){
|
||||
// goto errout;
|
||||
return(0);
|
||||
}
|
||||
int[][] partword=new int[partwords][];
|
||||
for(s=0;s<look.stages;s++)
|
||||
{
|
||||
for(i=0,l=0;i<partvals;l++)
|
||||
{
|
||||
if(s==0)
|
||||
{
|
||||
// fetch the partition word for each channel
|
||||
int temp=look.phrasebook.decode(vb.opb);
|
||||
if(temp==-1)
|
||||
{
|
||||
// goto eopbreak;
|
||||
return(0);
|
||||
}
|
||||
partword[l]=look.decodemap[temp];
|
||||
if(partword[l]==null)
|
||||
{
|
||||
// goto errout;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
// now we decode residual values for the partitions
|
||||
for(k=0;k<partitions_per_word && i<partvals;k++,i++)
|
||||
{
|
||||
int offset=info.begin+i*samples_per_partition;
|
||||
if((info.secondstages[partword[l][k]]&(1<<s))!=0)
|
||||
{
|
||||
CodeBook stagebook=look.fullbooks[look.partbooks[partword[l][k]][s]];
|
||||
if(stagebook!=null)
|
||||
{
|
||||
if(stagebook.decodevv_add(fin, offset, ch, vb.opb,samples_per_partition)==-1)
|
||||
{
|
||||
// goto errout;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// errout:
|
||||
// eopbreak:
|
||||
return(0);
|
||||
}
|
||||
|
||||
override public int inverse(Block vb, Object vl, float[][] fin, int[] nonzero, int ch)
|
||||
{
|
||||
//System.err.println("Residue0.inverse");
|
||||
int used=0;
|
||||
for(int i=0;i<ch;i++)
|
||||
{
|
||||
if(nonzero[i]!=0)
|
||||
{
|
||||
fin[used++]=fin[i];
|
||||
}
|
||||
}
|
||||
if(used!=0)
|
||||
return(_01inverse(vb, vl, fin, used, 0));
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
internal static int ilog(int v)
|
||||
{
|
||||
int ret=0;
|
||||
while(v!=0)
|
||||
{
|
||||
ret++;
|
||||
v = (int)((uint)v >> 1);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
internal static int icount(int v)
|
||||
{
|
||||
int ret=0;
|
||||
while(v!=0)
|
||||
{
|
||||
ret+=(v&1);
|
||||
v = (int)((uint)v >> 1);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
}
|
||||
|
||||
// now we decode residual values for the partitions
|
||||
for(k=0;k<partitions_per_word && i<partvals;k++,i++){
|
||||
int offset=info.begin+i*samples_per_partition;
|
||||
if((info.secondstages[partword[l][k]]&(1<<s))!=0){
|
||||
CodeBook stagebook=look.fullbooks[look.partbooks[partword[l][k]][s]];
|
||||
if(stagebook!=null){
|
||||
if(stagebook.decodevv_add(fin, offset, ch, vb.opb,samples_per_partition)==-1){
|
||||
// goto errout;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// errout:
|
||||
// eopbreak:
|
||||
return(0);
|
||||
}
|
||||
|
||||
int inverse(Block vb, Object vl, float[][] fin, int[] nonzero, int ch){
|
||||
//System.err.println("Residue0.inverse");
|
||||
int used=0;
|
||||
for(int i=0;i<ch;i++){
|
||||
if(nonzero[i]!=0){
|
||||
fin[used++]=fin[i];
|
||||
}
|
||||
}
|
||||
if(used!=0)
|
||||
return(_01inverse(vb, vl, fin, used, 0));
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
private static int ilog(int v){
|
||||
int ret=0;
|
||||
while(v!=0){
|
||||
ret++;
|
||||
(uint)v >>= 1;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
private static int icount(int v){
|
||||
int ret=0;
|
||||
while(v!=0){
|
||||
ret+=(v&1);
|
||||
(uint)v >>= 1;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
}
|
||||
|
||||
class LookResidue0 {
|
||||
InfoResidue0 info;
|
||||
int map;
|
||||
class LookResidue0
|
||||
{
|
||||
internal InfoResidue0 info;
|
||||
internal int map;
|
||||
|
||||
int parts;
|
||||
int stages;
|
||||
CodeBook[] fullbooks;
|
||||
CodeBook phrasebook;
|
||||
int[][] partbooks;
|
||||
// CodeBook[][] partbooks;
|
||||
internal int parts;
|
||||
internal int stages;
|
||||
internal CodeBook[] fullbooks;
|
||||
internal CodeBook phrasebook;
|
||||
internal int[][] partbooks;
|
||||
// CodeBook[][] partbooks;
|
||||
|
||||
int partvals;
|
||||
int[][] decodemap;
|
||||
internal int partvals;
|
||||
internal int[][] decodemap;
|
||||
|
||||
int postbits;
|
||||
int phrasebits;
|
||||
// int[][] frames;
|
||||
int frames;
|
||||
}
|
||||
//internal int postbits;
|
||||
//internal int phrasebits;
|
||||
// int[][] frames;
|
||||
//internal int frames;
|
||||
}
|
||||
|
||||
class InfoResidue0{
|
||||
// block-partitioned VQ coded straight residue
|
||||
int begin;
|
||||
int end;
|
||||
class InfoResidue0
|
||||
{
|
||||
// block-partitioned VQ coded straight residue
|
||||
internal int begin;
|
||||
internal int end;
|
||||
|
||||
// first stage (lossless partitioning)
|
||||
int grouping; // group n vectors per partition
|
||||
int partitions; // possible codebooks for a partition
|
||||
int groupbook; // huffbook for partitioning
|
||||
int[] secondstages=new int[64]; // expanded out to pointers in lookup
|
||||
int[] booklist=new int[256]; // list of second stage books
|
||||
// first stage (lossless partitioning)
|
||||
internal int grouping; // group n vectors per partition
|
||||
internal int partitions; // possible codebooks for a partition
|
||||
internal int groupbook; // huffbook for partitioning
|
||||
internal int[] secondstages=new int[64]; // expanded out to pointers in lookup
|
||||
internal int[] booklist=new int[256]; // list of second stage books
|
||||
|
||||
// encode-only heuristic settings
|
||||
float[] entmax=new float[64]; // book entropy threshholds
|
||||
float[] ampmax=new float[64]; // book amp threshholds
|
||||
int[] subgrp=new int[64]; // book heuristic subgroup size
|
||||
int[] blimit=new int[64]; // subgroup position limits
|
||||
}
|
||||
// encode-only heuristic settings
|
||||
internal float[] entmax=new float[64]; // book entropy threshholds
|
||||
internal float[] ampmax=new float[64]; // book amp threshholds
|
||||
internal int[] subgrp=new int[64]; // book heuristic subgroup size
|
||||
internal int[] blimit=new int[64]; // subgroup position limits
|
||||
}
|
||||
}
|
|
@ -26,25 +26,34 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
class Residue1 : Residue0{
|
||||
int forward(Block vb,Object vl, float[][] fin, int ch){
|
||||
System.err.println("Residue0.forward: not implemented");
|
||||
return 0;
|
||||
}
|
||||
namespace csvorbis
|
||||
{
|
||||
class Residue1 : Residue0
|
||||
{
|
||||
new int forward(Block vb,Object vl, float[][] fin, int ch)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int inverse(Block vb, Object vl, float[][] fin, int[] nonzero, int ch){
|
||||
//System.err.println("Residue0.inverse");
|
||||
int used=0;
|
||||
for(int i=0; i<ch; i++){
|
||||
if(nonzero[i]!=0){
|
||||
fin[used++]=fin[i];
|
||||
}
|
||||
}
|
||||
if(used!=0){
|
||||
return(_01inverse(vb, vl, fin, used, 1));
|
||||
}
|
||||
else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
override public int inverse(Block vb, Object vl, float[][] fin, int[] nonzero, int ch)
|
||||
{
|
||||
//System.err.println("Residue0.inverse");
|
||||
int used=0;
|
||||
for(int i=0; i<ch; i++)
|
||||
{
|
||||
if(nonzero[i]!=0)
|
||||
{
|
||||
fin[used++]=fin[i];
|
||||
}
|
||||
}
|
||||
if(used!=0)
|
||||
{
|
||||
return(_01inverse(vb, vl, fin, used, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,21 +26,23 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
class Residue2 : Residue0
|
||||
namespace csvorbis
|
||||
{
|
||||
int forward(Block vb,Object vl, float[][] fin, int ch)
|
||||
class Residue2 : Residue0
|
||||
{
|
||||
System.err.println("Residue0.forward: not implemented");
|
||||
return 0;
|
||||
}
|
||||
override public int forward(Block vb,Object vl, float[][] fin, int ch)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int inverse(Block vb, Object vl, float[][] fin, int[] nonzero, int ch)
|
||||
{
|
||||
//System.err.println("Residue0.inverse");
|
||||
int i=0;
|
||||
for(i=0;i<ch;i++)if(nonzero[i]!=0)break;
|
||||
if(i==ch)return(0); /* no nonzero vectors */
|
||||
override public int inverse(Block vb, Object vl, float[][] fin, int[] nonzero, int ch)
|
||||
{
|
||||
//System.err.println("Residue0.inverse");
|
||||
int i=0;
|
||||
for(i=0;i<ch;i++)if(nonzero[i]!=0)break;
|
||||
if(i==ch)return(0); /* no nonzero vectors */
|
||||
|
||||
return(_2inverse(vb, vl, fin, ch));
|
||||
return(_2inverse(vb, vl, fin, ch));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,512 +26,517 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
class StaticCodeBook
|
||||
namespace csvorbis
|
||||
{
|
||||
int dim; // codebook dimensions (elements per vector)
|
||||
int entries; // codebook entries
|
||||
int[] lengthlist; // codeword lengths in bits
|
||||
|
||||
// mapping
|
||||
int maptype; // 0=none
|
||||
// 1=implicitly populated values from map column
|
||||
// 2=listed arbitrary values
|
||||
|
||||
// The below does a linear, single monotonic sequence mapping.
|
||||
int q_min; // packed 32 bit float; quant value 0 maps to minval
|
||||
int q_delta; // packed 32 bit float; val 1 - val 0 == delta
|
||||
int q_quant; // bits: 0 < quant <= 16
|
||||
int q_sequencep; // bitflag
|
||||
|
||||
// additional information for log (dB) mapping; the linear mapping
|
||||
// is assumed to actually be values in dB. encodebias is used to
|
||||
// assign an error weight to 0 dB. We have two additional flags:
|
||||
// zeroflag indicates if entry zero is to represent -Inf dB; negflag
|
||||
// indicates if we're to represent negative linear values in a
|
||||
// mirror of the positive mapping.
|
||||
|
||||
int[] quantlist; // map == 1: (int)(entries/dim) element column map
|
||||
// map == 2: list of dim*entries quantized entry vals
|
||||
|
||||
// encode helpers
|
||||
EncodeAuxNearestMatch nearest_tree;
|
||||
EncodeAuxThreshMatch thresh_tree;
|
||||
|
||||
StaticCodeBook(){}
|
||||
StaticCodeBook(int dim, int entries, int[] lengthlist,
|
||||
int maptype, int q_min, int q_delta,
|
||||
int q_quant, int q_sequencep, int[] quantlist,
|
||||
//EncodeAuxNearestmatch nearest_tree,
|
||||
Object nearest_tree,
|
||||
// EncodeAuxThreshmatch thresh_tree,
|
||||
Object thresh_tree
|
||||
)
|
||||
class StaticCodeBook
|
||||
{
|
||||
this();
|
||||
this.dim=dim; this.entries=entries; this.lengthlist=lengthlist;
|
||||
this.maptype=maptype; this.q_min=q_min; this.q_delta=q_delta;
|
||||
this.q_quant=q_quant; this.q_sequencep=q_sequencep;
|
||||
this.quantlist=quantlist;
|
||||
}
|
||||
internal int dim; // codebook dimensions (elements per vector)
|
||||
internal int entries; // codebook entries
|
||||
internal int[] lengthlist; // codeword lengths in bits
|
||||
|
||||
int pack(csBuffer opb)
|
||||
{
|
||||
int i;
|
||||
boolean ordered=false;
|
||||
// mapping
|
||||
internal int maptype; // 0=none
|
||||
// 1=implicitly populated values from map column
|
||||
// 2=listed arbitrary values
|
||||
|
||||
opb.write(0x564342,24);
|
||||
opb.write(dim, 16);
|
||||
opb.write(entries, 24);
|
||||
// The below does a linear, single monotonic sequence mapping.
|
||||
internal int q_min; // packed 32 bit float; quant value 0 maps to minval
|
||||
internal int q_delta; // packed 32 bit float; val 1 - val 0 == delta
|
||||
internal int q_quant; // bits: 0 < quant <= 16
|
||||
internal int q_sequencep; // bitflag
|
||||
|
||||
// pack the codewords. There are two packings; length ordered and
|
||||
// length random. Decide between the two now.
|
||||
|
||||
for(i=1;i<entries;i++)
|
||||
// additional information for log (dB) mapping; the linear mapping
|
||||
// is assumed to actually be values in dB. encodebias is used to
|
||||
// assign an error weight to 0 dB. We have two additional flags:
|
||||
// zeroflag indicates if entry zero is to represent -Inf dB; negflag
|
||||
// indicates if we're to represent negative linear values in a
|
||||
// mirror of the positive mapping.
|
||||
|
||||
internal int[] quantlist; // map == 1: (int)(entries/dim) element column map
|
||||
// map == 2: list of dim*entries quantized entry vals
|
||||
|
||||
// encode helpers
|
||||
internal EncodeAuxNearestMatch nearest_tree;
|
||||
internal EncodeAuxThreshMatch thresh_tree;
|
||||
|
||||
internal StaticCodeBook(){}
|
||||
internal StaticCodeBook(int dim, int entries, int[] lengthlist,
|
||||
int maptype, int q_min, int q_delta,
|
||||
int q_quant, int q_sequencep, int[] quantlist,
|
||||
//EncodeAuxNearestmatch nearest_tree,
|
||||
Object nearest_tree,
|
||||
// EncodeAuxThreshmatch thresh_tree,
|
||||
Object thresh_tree
|
||||
) : this()
|
||||
{
|
||||
if(lengthlist[i]<lengthlist[i-1])break;
|
||||
this.dim=dim; this.entries=entries; this.lengthlist=lengthlist;
|
||||
this.maptype=maptype; this.q_min=q_min; this.q_delta=q_delta;
|
||||
this.q_quant=q_quant; this.q_sequencep=q_sequencep;
|
||||
this.quantlist=quantlist;
|
||||
}
|
||||
if(i==entries)ordered=true;
|
||||
|
||||
if(ordered)
|
||||
|
||||
internal int pack(csBuffer opb)
|
||||
{
|
||||
// length ordered. We only need to say how many codewords of
|
||||
// each length. The actual codewords are generated
|
||||
// deterministically
|
||||
int i;
|
||||
bool ordered=false;
|
||||
|
||||
int count=0;
|
||||
opb.write(1,1); // ordered
|
||||
opb.write(lengthlist[0]-1,5); // 1 to 32
|
||||
opb.write(0x564342,24);
|
||||
opb.write(dim, 16);
|
||||
opb.write(entries, 24);
|
||||
|
||||
// pack the codewords. There are two packings; length ordered and
|
||||
// length random. Decide between the two now.
|
||||
|
||||
for(i=1;i<entries;i++)
|
||||
{
|
||||
int _this=lengthlist[i];
|
||||
int _last=lengthlist[i-1];
|
||||
if(_this>_last)
|
||||
if(lengthlist[i]<lengthlist[i-1])break;
|
||||
}
|
||||
if(i==entries)ordered=true;
|
||||
|
||||
if(ordered)
|
||||
{
|
||||
// length ordered. We only need to say how many codewords of
|
||||
// each length. The actual codewords are generated
|
||||
// deterministically
|
||||
|
||||
int count=0;
|
||||
opb.write(1,1); // ordered
|
||||
opb.write(lengthlist[0]-1,5); // 1 to 32
|
||||
|
||||
for(i=1;i<entries;i++)
|
||||
{
|
||||
for(int j=_last;j<_this;j++)
|
||||
int _this=lengthlist[i];
|
||||
int _last=lengthlist[i-1];
|
||||
if(_this>_last)
|
||||
{
|
||||
opb.write(i-count,ilog(entries-count));
|
||||
count=i;
|
||||
for(int j=_last;j<_this;j++)
|
||||
{
|
||||
opb.write(i-count,ilog(entries-count));
|
||||
count=i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
opb.write(i-count,ilog(entries-count));
|
||||
}
|
||||
else
|
||||
{
|
||||
// length random. Again, we don't code the codeword itself, just
|
||||
// the length. This time, though, we have to encode each length
|
||||
opb.write(0,1); // unordered
|
||||
|
||||
// algortihmic mapping has use for 'unused entries', which we tag
|
||||
// here. The algorithmic mapping happens as usual, but the unused
|
||||
// entry has no codeword.
|
||||
for(i=0;i<entries;i++)
|
||||
{
|
||||
if(lengthlist[i]==0)break;
|
||||
}
|
||||
|
||||
if(i==entries)
|
||||
{
|
||||
opb.write(0,1); // no unused entries
|
||||
for(i=0;i<entries;i++)
|
||||
{
|
||||
opb.write(lengthlist[i]-1,5);
|
||||
}
|
||||
opb.write(i-count,ilog(entries-count));
|
||||
}
|
||||
else
|
||||
{
|
||||
opb.write(1,1); // we have unused entries; thus we tag
|
||||
// length random. Again, we don't code the codeword itself, just
|
||||
// the length. This time, though, we have to encode each length
|
||||
opb.write(0,1); // unordered
|
||||
|
||||
// algortihmic mapping has use for 'unused entries', which we tag
|
||||
// here. The algorithmic mapping happens as usual, but the unused
|
||||
// entry has no codeword.
|
||||
for(i=0;i<entries;i++)
|
||||
{
|
||||
if(lengthlist[i]==0)
|
||||
if(lengthlist[i]==0)break;
|
||||
}
|
||||
|
||||
if(i==entries)
|
||||
{
|
||||
opb.write(0,1); // no unused entries
|
||||
for(i=0;i<entries;i++)
|
||||
{
|
||||
opb.write(0,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
opb.write(1,1);
|
||||
opb.write(lengthlist[i]-1,5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// is the entry number the desired return value, or do we have a
|
||||
// mapping? If we have a mapping, what type?
|
||||
opb.write(maptype,4);
|
||||
switch(maptype)
|
||||
{
|
||||
case 0:
|
||||
// no mapping
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
// implicitly populated value mapping
|
||||
// explicitly populated value mapping
|
||||
if(quantlist==null)
|
||||
else
|
||||
{
|
||||
// no quantlist? error
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// values that define the dequantization
|
||||
opb.write(q_min,32);
|
||||
opb.write(q_delta,32);
|
||||
opb.write(q_quant-1,4);
|
||||
opb.write(q_sequencep,1);
|
||||
|
||||
{
|
||||
int quantvals=0;
|
||||
switch(maptype)
|
||||
{
|
||||
case 1:
|
||||
// a single column of (c->entries/c->dim) quantized values for
|
||||
// building a full value list algorithmically (square lattice)
|
||||
quantvals=maptype1_quantvals();
|
||||
break;
|
||||
case 2:
|
||||
// every value (c->entries*c->dim total) specified explicitly
|
||||
quantvals=entries*dim;
|
||||
break;
|
||||
}
|
||||
|
||||
// quantized values
|
||||
for(i=0;i<quantvals;i++)
|
||||
{
|
||||
opb.write(Math.abs(quantlist[i]),q_quant);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// error case; we don't have any other map types now
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
/*
|
||||
*/
|
||||
|
||||
// unpacks a codebook from the packet buffer into the codebook struct,
|
||||
// readies the codebook auxiliary structures for decode
|
||||
int unpack(csBuffer opb)
|
||||
{
|
||||
int i;
|
||||
//memset(s,0,sizeof(static_codebook));
|
||||
|
||||
// make sure alignment is correct
|
||||
if(opb.read(24)!=0x564342)
|
||||
{
|
||||
// goto _eofout;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// first the basic parameters
|
||||
dim=opb.read(16);
|
||||
entries=opb.read(24);
|
||||
if(entries==-1)
|
||||
{
|
||||
// goto _eofout;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// codeword ordering.... length ordered or unordered?
|
||||
switch(opb.read(1))
|
||||
{
|
||||
case 0:
|
||||
// unordered
|
||||
lengthlist=new int[entries];
|
||||
|
||||
// allocated but unused entries?
|
||||
if(opb.read(1)!=0)
|
||||
{
|
||||
// yes, unused entries
|
||||
|
||||
opb.write(1,1); // we have unused entries; thus we tag
|
||||
for(i=0;i<entries;i++)
|
||||
{
|
||||
if(opb.read(1)!=0)
|
||||
if(lengthlist[i]==0)
|
||||
{
|
||||
opb.write(0,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
opb.write(1,1);
|
||||
opb.write(lengthlist[i]-1,5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// is the entry number the desired return value, or do we have a
|
||||
// mapping? If we have a mapping, what type?
|
||||
opb.write(maptype,4);
|
||||
switch(maptype)
|
||||
{
|
||||
case 0:
|
||||
// no mapping
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
// implicitly populated value mapping
|
||||
// explicitly populated value mapping
|
||||
if(quantlist==null)
|
||||
{
|
||||
// no quantlist? error
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// values that define the dequantization
|
||||
opb.write(q_min,32);
|
||||
opb.write(q_delta,32);
|
||||
opb.write(q_quant-1,4);
|
||||
opb.write(q_sequencep,1);
|
||||
|
||||
{
|
||||
int quantvals=0;
|
||||
switch(maptype)
|
||||
{
|
||||
case 1:
|
||||
// a single column of (c->entries/c->dim) quantized values for
|
||||
// building a full value list algorithmically (square lattice)
|
||||
quantvals=maptype1_quantvals();
|
||||
break;
|
||||
case 2:
|
||||
// every value (c->entries*c->dim total) specified explicitly
|
||||
quantvals=entries*dim;
|
||||
break;
|
||||
}
|
||||
|
||||
// quantized values
|
||||
for(i=0;i<quantvals;i++)
|
||||
{
|
||||
opb.write(Math.Abs(quantlist[i]),q_quant);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// error case; we don't have any other map types now
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
/*
|
||||
*/
|
||||
|
||||
// unpacks a codebook from the packet buffer into the codebook struct,
|
||||
// readies the codebook auxiliary structures for decode
|
||||
internal int unpack(csBuffer opb)
|
||||
{
|
||||
int i;
|
||||
//memset(s,0,sizeof(static_codebook));
|
||||
|
||||
// make sure alignment is correct
|
||||
if(opb.read(24)!=0x564342)
|
||||
{
|
||||
// goto _eofout;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// first the basic parameters
|
||||
dim=opb.read(16);
|
||||
entries=opb.read(24);
|
||||
if(entries==-1)
|
||||
{
|
||||
// goto _eofout;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// codeword ordering.... length ordered or unordered?
|
||||
switch(opb.read(1))
|
||||
{
|
||||
case 0:
|
||||
// unordered
|
||||
lengthlist=new int[entries];
|
||||
|
||||
// allocated but unused entries?
|
||||
if(opb.read(1)!=0)
|
||||
{
|
||||
// yes, unused entries
|
||||
|
||||
for(i=0;i<entries;i++)
|
||||
{
|
||||
if(opb.read(1)!=0)
|
||||
{
|
||||
int num=opb.read(5);
|
||||
if(num==-1)
|
||||
{
|
||||
// goto _eofout;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
lengthlist[i]=num+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
lengthlist[i]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// all entries used; no tagging
|
||||
for(i=0;i<entries;i++)
|
||||
{
|
||||
int num=opb.read(5);
|
||||
if(num==-1)
|
||||
{
|
||||
// goto _eofout;
|
||||
// goto _eofout;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
lengthlist[i]=num+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
lengthlist[i]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
case 1:
|
||||
// ordered
|
||||
{
|
||||
// all entries used; no tagging
|
||||
for(i=0;i<entries;i++)
|
||||
int length=opb.read(5)+1;
|
||||
lengthlist=new int[entries];
|
||||
|
||||
for(i=0;i<entries;)
|
||||
{
|
||||
int num=opb.read(5);
|
||||
int num=opb.read(ilog(entries-i));
|
||||
if(num==-1)
|
||||
{
|
||||
// goto _eofout;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
lengthlist[i]=num+1;
|
||||
for(int j=0;j<num;j++,i++)
|
||||
{
|
||||
lengthlist[i]=length;
|
||||
}
|
||||
length++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
// ordered
|
||||
break;
|
||||
default:
|
||||
// EOF
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// Do we have a mapping to unpack?
|
||||
switch((maptype=opb.read(4)))
|
||||
{
|
||||
int length=opb.read(5)+1;
|
||||
lengthlist=new int[entries];
|
||||
case 0:
|
||||
// no mapping
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
// implicitly populated value mapping
|
||||
// explicitly populated value mapping
|
||||
q_min=opb.read(32);
|
||||
q_delta=opb.read(32);
|
||||
q_quant=opb.read(4)+1;
|
||||
q_sequencep=opb.read(1);
|
||||
|
||||
for(i=0;i<entries;)
|
||||
{
|
||||
int num=opb.read(ilog(entries-i));
|
||||
if(num==-1)
|
||||
int quantvals=0;
|
||||
switch(maptype)
|
||||
{
|
||||
// goto _eofout;
|
||||
case 1:
|
||||
quantvals=maptype1_quantvals();
|
||||
break;
|
||||
case 2:
|
||||
quantvals=entries*dim;
|
||||
break;
|
||||
}
|
||||
|
||||
// quantized values
|
||||
quantlist=new int[quantvals];
|
||||
for(i=0;i<quantvals;i++)
|
||||
{
|
||||
quantlist[i]=opb.read(q_quant);
|
||||
}
|
||||
if(quantlist[quantvals-1]==-1)
|
||||
{
|
||||
// goto _eofout;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
for(int j=0;j<num;j++,i++)
|
||||
{
|
||||
lengthlist[i]=length;
|
||||
}
|
||||
length++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// goto _eofout;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
// all set
|
||||
return(0);
|
||||
// _errout:
|
||||
// _eofout:
|
||||
// vorbis_staticbook_clear(s);
|
||||
// return(-1);
|
||||
}
|
||||
|
||||
// there might be a straightforward one-line way to do the below
|
||||
// that's portable and totally safe against roundoff, but I haven't
|
||||
// thought of it. Therefore, we opt on the side of caution
|
||||
internal int maptype1_quantvals()
|
||||
{
|
||||
int vals=(int)(Math.Floor(Math.Pow(entries,1.0/dim)));
|
||||
|
||||
// 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;
|
||||
for(int i=0;i<dim;i++)
|
||||
{
|
||||
acc*=vals;
|
||||
acc1*=vals+1;
|
||||
}
|
||||
if(acc<=entries && acc1>entries){ return(vals); }
|
||||
else
|
||||
{
|
||||
if(acc>entries){ vals--; }
|
||||
else{ vals++; }
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// EOF
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// Do we have a mapping to unpack?
|
||||
switch((maptype=opb.read(4)))
|
||||
|
||||
internal void clear()
|
||||
{
|
||||
case 0:
|
||||
// no mapping
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
// implicitly populated value mapping
|
||||
// explicitly populated value mapping
|
||||
q_min=opb.read(32);
|
||||
q_delta=opb.read(32);
|
||||
q_quant=opb.read(4)+1;
|
||||
q_sequencep=opb.read(1);
|
||||
// if(quantlist!=null)free(b->quantlist);
|
||||
// if(lengthlist!=null)free(b->lengthlist);
|
||||
// if(nearest_tree!=null){
|
||||
// free(b->nearest_tree->ptr0);
|
||||
// free(b->nearest_tree->ptr1);
|
||||
// free(b->nearest_tree->p);
|
||||
// free(b->nearest_tree->q);
|
||||
// memset(b->nearest_tree,0,sizeof(encode_aux_nearestmatch));
|
||||
// free(b->nearest_tree);
|
||||
// }
|
||||
// if(thresh_tree!=null){
|
||||
// free(b->thresh_tree->quantthresh);
|
||||
// free(b->thresh_tree->quantmap);
|
||||
// memset(b->thresh_tree,0,sizeof(encode_aux_threshmatch));
|
||||
// free(b->thresh_tree);
|
||||
// }
|
||||
// memset(b,0,sizeof(static_codebook));
|
||||
}
|
||||
|
||||
// unpack the quantized list of values for encode/decode
|
||||
// we need to deal with two map types: in map type 1, the values are
|
||||
// generated algorithmically (each column of the vector counts through
|
||||
// the values in the quant vector). in map type 2, all the values came
|
||||
// in in an explicit list. Both value lists must be unpacked
|
||||
internal float[] unquantize()
|
||||
{
|
||||
|
||||
if(maptype==1 || maptype==2)
|
||||
{
|
||||
int quantvals=0;
|
||||
int quantvals;
|
||||
float mindel=float32_unpack(q_min);
|
||||
float delta=float32_unpack(q_delta);
|
||||
float[] r=new float[entries*dim];
|
||||
|
||||
//System.err.println("q_min="+q_min+", mindel="+mindel);
|
||||
|
||||
// maptype 1 and 2 both use a quantized value vector, but
|
||||
// different sizes
|
||||
switch(maptype)
|
||||
{
|
||||
case 1:
|
||||
// most of the time, entries%dimensions == 0, but we need to be
|
||||
// well defined. We define that the possible vales at each
|
||||
// scalar is values == entries/dim. If entries%dim != 0, we'll
|
||||
// have 'too few' values (values*dim<entries), which means that
|
||||
// we'll have 'left over' entries; left over entries use zeroed
|
||||
// values (and are wasted). So don't generate codebooks like that
|
||||
quantvals=maptype1_quantvals();
|
||||
for(int j=0;j<entries;j++)
|
||||
{
|
||||
float last=0.0f;
|
||||
int indexdiv=1;
|
||||
for(int k=0;k<dim;k++)
|
||||
{
|
||||
int index=(j/indexdiv)%quantvals;
|
||||
float val=quantlist[index];
|
||||
val=Math.Abs(val)*delta+mindel+last;
|
||||
if(q_sequencep!=0)last=val;
|
||||
r[j*dim+k]=val;
|
||||
indexdiv*=quantvals;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
quantvals=entries*dim;
|
||||
for(int j=0;j<entries;j++)
|
||||
{
|
||||
float last=0.0f;
|
||||
for(int k=0;k<dim;k++)
|
||||
{
|
||||
float val=quantlist[j*dim+k];
|
||||
//if((j*dim+k)==0){System.err.println(" | 0 -> "+val+" | ");}
|
||||
val=Math.Abs(val)*delta+mindel+last;
|
||||
if(q_sequencep!=0)last=val;
|
||||
r[j*dim+k]=val;
|
||||
//if((j*dim+k)==0){System.err.println(" $ r[0] -> "+r[0]+" | ");}
|
||||
}
|
||||
}
|
||||
//System.err.println("\nr[0]="+r[0]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// quantized values
|
||||
quantlist=new int[quantvals];
|
||||
for(i=0;i<quantvals;i++)
|
||||
{
|
||||
quantlist[i]=opb.read(q_quant);
|
||||
}
|
||||
if(quantlist[quantvals-1]==-1)
|
||||
{
|
||||
// goto _eofout;
|
||||
clear();
|
||||
return(-1);
|
||||
}
|
||||
return(r);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// goto _eofout;
|
||||
clear();
|
||||
return(-1);
|
||||
return(null);
|
||||
}
|
||||
// all set
|
||||
return(0);
|
||||
// _errout:
|
||||
// _eofout:
|
||||
// vorbis_staticbook_clear(s);
|
||||
// return(-1);
|
||||
}
|
||||
|
||||
// there might be a straightforward one-line way to do the below
|
||||
// that's portable and totally safe against roundoff, but I haven't
|
||||
// thought of it. Therefore, we opt on the side of caution
|
||||
private int maptype1_quantvals()
|
||||
{
|
||||
int vals=(int)(Math.floor(Math.pow(entries,1.0/dim)));
|
||||
|
||||
// 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)
|
||||
internal static int ilog(int v)
|
||||
{
|
||||
int acc=1;
|
||||
int acc1=1;
|
||||
for(int i=0;i<dim;i++)
|
||||
int ret=0;
|
||||
while(v!=0)
|
||||
{
|
||||
acc*=vals;
|
||||
acc1*=vals+1;
|
||||
ret++;
|
||||
v = (int)((uint)v >> 1);
|
||||
}
|
||||
if(acc<=entries && acc1>entries){ return(vals); }
|
||||
else
|
||||
return(ret);
|
||||
}
|
||||
|
||||
// 32 bit float (not IEEE; nonnormalized mantissa +
|
||||
// biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm
|
||||
// Why not IEEE? It's just not that important here.
|
||||
|
||||
//static int VQ_FEXP=10;
|
||||
static int VQ_FMAN=21;
|
||||
static int VQ_FEXP_BIAS=768; // bias toward values smaller than 1.
|
||||
|
||||
// doesn't currently guard under/overflow
|
||||
internal static long float32_pack(float val)
|
||||
{
|
||||
uint sign=0;
|
||||
int exp;
|
||||
int mant;
|
||||
if(val<0)
|
||||
{
|
||||
if(acc>entries){ vals--; }
|
||||
else{ vals++; }
|
||||
sign = 0x80000000;
|
||||
val = -val;
|
||||
}
|
||||
exp=(int)Math.Floor(Math.Log(val)/Math.Log(2));
|
||||
mant=(int)Math.Round(Math.Pow(val,(VQ_FMAN-1)-exp));
|
||||
exp=(exp+VQ_FEXP_BIAS)<<VQ_FMAN;
|
||||
return((int)sign | exp | mant);
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
// if(quantlist!=null)free(b->quantlist);
|
||||
// if(lengthlist!=null)free(b->lengthlist);
|
||||
// if(nearest_tree!=null){
|
||||
// free(b->nearest_tree->ptr0);
|
||||
// free(b->nearest_tree->ptr1);
|
||||
// free(b->nearest_tree->p);
|
||||
// free(b->nearest_tree->q);
|
||||
// memset(b->nearest_tree,0,sizeof(encode_aux_nearestmatch));
|
||||
// free(b->nearest_tree);
|
||||
// }
|
||||
// if(thresh_tree!=null){
|
||||
// free(b->thresh_tree->quantthresh);
|
||||
// free(b->thresh_tree->quantmap);
|
||||
// memset(b->thresh_tree,0,sizeof(encode_aux_threshmatch));
|
||||
// free(b->thresh_tree);
|
||||
// }
|
||||
// memset(b,0,sizeof(static_codebook));
|
||||
}
|
||||
|
||||
// unpack the quantized list of values for encode/decode
|
||||
// we need to deal with two map types: in map type 1, the values are
|
||||
// generated algorithmically (each column of the vector counts through
|
||||
// the values in the quant vector). in map type 2, all the values came
|
||||
// in in an explicit list. Both value lists must be unpacked
|
||||
float[] unquantize()
|
||||
{
|
||||
|
||||
if(maptype==1 || maptype==2)
|
||||
internal static float float32_unpack(int val)
|
||||
{
|
||||
int quantvals;
|
||||
float mindel=float32_unpack(q_min);
|
||||
float delta=float32_unpack(q_delta);
|
||||
float[] r=new float[entries*dim];
|
||||
|
||||
//System.err.println("q_min="+q_min+", mindel="+mindel);
|
||||
|
||||
// maptype 1 and 2 both use a quantized value vector, but
|
||||
// different sizes
|
||||
switch(maptype)
|
||||
{
|
||||
case 1:
|
||||
// most of the time, entries%dimensions == 0, but we need to be
|
||||
// well defined. We define that the possible vales at each
|
||||
// scalar is values == entries/dim. If entries%dim != 0, we'll
|
||||
// have 'too few' values (values*dim<entries), which means that
|
||||
// we'll have 'left over' entries; left over entries use zeroed
|
||||
// values (and are wasted). So don't generate codebooks like that
|
||||
quantvals=maptype1_quantvals();
|
||||
for(int j=0;j<entries;j++)
|
||||
{
|
||||
float last=0.f;
|
||||
int indexdiv=1;
|
||||
for(int k=0;k<dim;k++)
|
||||
{
|
||||
int index=(j/indexdiv)%quantvals;
|
||||
float val=quantlist[index];
|
||||
val=Math.abs(val)*delta+mindel+last;
|
||||
if(q_sequencep!=0)last=val;
|
||||
r[j*dim+k]=val;
|
||||
indexdiv*=quantvals;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for(int j=0;j<entries;j++)
|
||||
{
|
||||
float last=0.f;
|
||||
for(int k=0;k<dim;k++)
|
||||
{
|
||||
float val=quantlist[j*dim+k];
|
||||
//if((j*dim+k)==0){System.err.println(" | 0 -> "+val+" | ");}
|
||||
val=Math.abs(val)*delta+mindel+last;
|
||||
if(q_sequencep!=0)last=val;
|
||||
r[j*dim+k]=val;
|
||||
//if((j*dim+k)==0){System.err.println(" $ r[0] -> "+r[0]+" | ");}
|
||||
}
|
||||
}
|
||||
//System.err.println("\nr[0]="+r[0]);
|
||||
}
|
||||
return(r);
|
||||
float mant=val&0x1fffff;
|
||||
float sign=val&0x80000000;
|
||||
float exp =(uint)(val&0x7fe00000) >> VQ_FMAN;
|
||||
//System.err.println("mant="+mant+", sign="+sign+", exp="+exp);
|
||||
//if(sign!=0.0)mant= -mant;
|
||||
if((val&0x80000000)!=0)mant= -mant;
|
||||
//System.err.println("mant="+mant);
|
||||
return(ldexp(mant,((int)exp)-(VQ_FMAN-1)-VQ_FEXP_BIAS));
|
||||
}
|
||||
return(null);
|
||||
}
|
||||
|
||||
private static int ilog(int v)
|
||||
{
|
||||
int ret=0;
|
||||
while(v!=0)
|
||||
internal static float ldexp(float foo, int e)
|
||||
{
|
||||
ret++;
|
||||
(uint)v >>= 1;
|
||||
return (float)(foo*Math.Pow(2, e));
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
// 32 bit float (not IEEE; nonnormalized mantissa +
|
||||
// biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm
|
||||
// Why not IEEE? It's just not that important here.
|
||||
|
||||
static int VQ_FEXP=10;
|
||||
static int VQ_FMAN=21;
|
||||
static int VQ_FEXP_BIAS=768; // bias toward values smaller than 1.
|
||||
|
||||
// doesn't currently guard under/overflow
|
||||
static long float32_pack(float val)
|
||||
{
|
||||
int sign=0;
|
||||
int exp;
|
||||
int mant;
|
||||
if(val<0)
|
||||
{
|
||||
sign=0x80000000;
|
||||
val= -val;
|
||||
}
|
||||
exp=(int)Math.floor(Math.log(val)/Math.log(2));
|
||||
mant=(int)Math.rint(Math.pow(val,(VQ_FMAN-1)-exp));
|
||||
exp=(exp+VQ_FEXP_BIAS)<<VQ_FMAN;
|
||||
return(sign|exp|mant);
|
||||
}
|
||||
|
||||
static float float32_unpack(int val)
|
||||
{
|
||||
float mant=val&0x1fffff;
|
||||
float sign=val&0x80000000;
|
||||
float exp =(uint)(val&0x7fe00000) >> VQ_FMAN;
|
||||
//System.err.println("mant="+mant+", sign="+sign+", exp="+exp);
|
||||
//if(sign!=0.0)mant= -mant;
|
||||
if((val&0x80000000)!=0)mant= -mant;
|
||||
//System.err.println("mant="+mant);
|
||||
return(ldexp(mant,((int)exp)-(VQ_FMAN-1)-VQ_FEXP_BIAS));
|
||||
}
|
||||
|
||||
static float ldexp(float foo, int e)
|
||||
{
|
||||
return (float)(foo*Math.pow(2, e));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,13 +26,16 @@
|
|||
using System;
|
||||
using csogg;
|
||||
|
||||
class Time0 : FuncTime
|
||||
namespace csvorbis
|
||||
{
|
||||
void pack(Object i, csBuffer opb){}
|
||||
Object unpack(Info vi , csBuffer opb){return "";}
|
||||
Object look(DspState vd, InfoMode mi, Object i){return "";}
|
||||
void free_info(Object i){}
|
||||
void free_look(Object i){}
|
||||
int forward(Block vb, Object i){return 0;}
|
||||
int inverse(Block vb, Object i, float[] fin, float[] fout){return 0;}
|
||||
class Time0 : FuncTime
|
||||
{
|
||||
override public void pack(Object i, csBuffer opb){}
|
||||
override public Object unpack(Info vi , csBuffer opb){return "";}
|
||||
override public Object look(DspState vd, InfoMode mi, Object i){return "";}
|
||||
override public void free_info(Object i){}
|
||||
override public void free_look(Object i){}
|
||||
override public int forward(Block vb, Object i){return 0;}
|
||||
override public int inverse(Block vb, Object i, float[] fin, float[] fout){return 0;}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,10 +25,13 @@
|
|||
|
||||
using System;
|
||||
|
||||
public class csorbisException : Exception
|
||||
namespace csvorbis
|
||||
{
|
||||
public csorbisException ()
|
||||
:base(){}
|
||||
public csorbisException (String s)
|
||||
:base("csorbis: "+s){}
|
||||
public class csorbisException : Exception
|
||||
{
|
||||
public csorbisException ()
|
||||
:base(){}
|
||||
public csorbisException (String s)
|
||||
:base("csorbis: "+s){}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче