chore(fmod): add files from Chensne/DragonNest

This commit is contained in:
phaneron 2025-08-19 10:12:56 -04:00
commit 50fb3c6b1c
544 changed files with 315778 additions and 0 deletions

View file

@ -0,0 +1,208 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: toplevel libogg include
last mod: $Id: ogg.h 16051 2009-05-27 05:00:06Z xiphmont $
********************************************************************/
#ifndef _OGG_H
#define _OGG_H
#ifdef __cplusplus
extern "C" {
#endif
#include <ogg/os_types.h>
#include <stddef.h>
typedef struct {
void *iov_base;
size_t iov_len;
} ogg_iovec_t;
typedef struct {
ogg_int32_t endbyte;
int endbit;
unsigned char *buffer;
unsigned char *ptr;
ogg_int32_t storage;
} oggpack_buffer;
/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/
typedef struct {
unsigned char *header;
ogg_int32_t header_len;
unsigned char *body;
ogg_int32_t body_len;
} ogg_page;
/* ogg_stream_state contains the current encode/decode state of a logical
Ogg bitstream **********************************************************/
typedef struct {
unsigned char *body_data; /* bytes from packet bodies */
ogg_int32_t body_storage; /* storage elements allocated */
ogg_int32_t body_fill; /* elements stored; fill mark */
ogg_int32_t body_returned; /* elements of fill returned */
int *lacing_vals; /* The values that will go to the segment table */
ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact
this way, but it is simple coupled to the
lacing fifo */
ogg_int32_t lacing_storage;
ogg_int32_t lacing_fill;
ogg_int32_t lacing_packet;
ogg_int32_t lacing_returned;
unsigned char header[282]; /* working space for header encode */
int header_fill;
int e_o_s; /* set when we have buffered the last packet in the
logical bitstream */
int b_o_s; /* set after we've written the initial page
of a logical bitstream */
ogg_int32_t serialno;
ogg_int32_t pageno;
ogg_int64_t packetno; /* sequence number for decode; the framing
knows where there's a hole in the data,
but we need coupling so that the codec
(which is in a seperate abstraction
layer) also knows about the gap */
ogg_int64_t granulepos;
} ogg_stream_state;
/* ogg_packet is used to encapsulate the data and metadata beogg_int32_ting
to a single raw Ogg/Vorbis packet *************************************/
typedef struct {
unsigned char *packet;
ogg_int32_t bytes;
ogg_int32_t b_o_s;
ogg_int32_t e_o_s;
ogg_int64_t granulepos;
ogg_int64_t packetno; /* sequence number for decode; the framing
knows where there's a hole in the data,
but we need coupling so that the codec
(which is in a seperate abstraction
layer) also knows about the gap */
} ogg_packet;
typedef struct {
unsigned char *data;
int storage;
int fill;
int returned;
int unsynced;
int headerbytes;
int bodybytes;
} ogg_sync_state;
/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/
//extern void FMOD_oggpack_writeinit(void *context, oggpack_buffer *b);
//extern int FMOD_oggpack_writecheck(oggpack_buffer *b);
//extern void FMOD_oggpack_writetrunc(oggpack_buffer *b,ogg_int32_t bits);
//extern void FMOD_oggpack_writealign(oggpack_buffer *b);
//extern void FMOD_oggpack_writecopy(oggpack_buffer *b,void *source,ogg_int32_t bits);
extern void FMOD_oggpack_reset(oggpack_buffer *b);
//extern void FMOD_oggpack_writeclear(oggpack_buffer *b);
extern void FMOD_oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
//extern void FMOD_oggpack_write(oggpack_buffer *b, ogg_uint32_t value,int bits);
extern ogg_int32_t FMOD_oggpack_look(oggpack_buffer *b,int bits);
extern ogg_int32_t FMOD_oggpack_look1(oggpack_buffer *b);
extern void FMOD_oggpack_adv(oggpack_buffer *b,int bits);
extern void FMOD_oggpack_adv1(oggpack_buffer *b);
extern ogg_int32_t FMOD_oggpack_read(oggpack_buffer *b,int bits);
extern ogg_int32_t FMOD_oggpack_read1(oggpack_buffer *b);
extern ogg_int32_t FMOD_oggpack_bytes(oggpack_buffer *b);
extern ogg_int32_t FMOD_oggpack_bits(oggpack_buffer *b);
extern unsigned char *FMOD_oggpack_get_buffer(oggpack_buffer *b);
//extern void FMOD_oggpackB_writeinit(oggpack_buffer *b);
//extern int FMOD_oggpackB_writecheck(oggpack_buffer *b);
//extern void FMOD_oggpackB_writetrunc(oggpack_buffer *b,ogg_int32_t bits);
//extern void FMOD_oggpackB_writealign(oggpack_buffer *b);
//extern void FMOD_oggpackB_writecopy(oggpack_buffer *b,void *source,ogg_int32_t bits);
extern void FMOD_oggpackB_reset(oggpack_buffer *b);
//extern void FMOD_oggpackB_writeclear(oggpack_buffer *b);
extern void FMOD_oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
//extern void FMOD_oggpackB_write(oggpack_buffer *b, ogg_uint32_t value,int bits);
extern ogg_int32_t FMOD_oggpackB_look(oggpack_buffer *b,int bits);
extern ogg_int32_t FMOD_oggpackB_look1(oggpack_buffer *b);
extern void FMOD_oggpackB_adv(oggpack_buffer *b,int bits);
extern void FMOD_oggpackB_adv1(oggpack_buffer *b);
extern ogg_int32_t FMOD_oggpackB_read(oggpack_buffer *b,int bits);
extern ogg_int32_t FMOD_oggpackB_read1(oggpack_buffer *b);
extern ogg_int32_t FMOD_oggpackB_bytes(oggpack_buffer *b);
extern ogg_int32_t FMOD_oggpackB_bits(oggpack_buffer *b);
extern unsigned char *FMOD_oggpackB_get_buffer(oggpack_buffer *b);
/* Ogg BITSTREAM PRIMITIVES: encoding **************************/
//extern int FMOD_ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op);
//extern int FMOD_ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov,
// int count, ogg_int32_t e_o_s, ogg_int64_t granulepos);
//extern int FMOD_ogg_stream_pageout(ogg_stream_state *os, ogg_page *og);
//extern int FMOD_ogg_stream_flush(ogg_stream_state *os, ogg_page *og);
/* Ogg BITSTREAM PRIMITIVES: decoding **************************/
extern int FMOD_ogg_sync_init(ogg_sync_state *oy);
extern int FMOD_ogg_sync_clear(void *context, ogg_sync_state *oy);
extern int FMOD_ogg_sync_reset(ogg_sync_state *oy);
extern int FMOD_ogg_sync_destroy(void *context, ogg_sync_state *oy);
extern int FMOD_ogg_sync_check(ogg_sync_state *oy);
extern char *FMOD_ogg_sync_buffer(void *context, ogg_sync_state *oy, ogg_int32_t size);
extern int FMOD_ogg_sync_wrote(ogg_sync_state *oy, ogg_int32_t bytes);
extern ogg_int32_t FMOD_ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og);
extern int FMOD_ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og);
extern int FMOD_ogg_stream_pagein(void *context, ogg_stream_state *os, ogg_page *og);
extern int FMOD_ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op);
extern int FMOD_ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op);
/* Ogg BITSTREAM PRIMITIVES: general ***************************/
extern int FMOD_ogg_stream_init(void *context, ogg_stream_state *os,int serialno);
extern int FMOD_ogg_stream_clear(void *context, ogg_stream_state *os);
extern int FMOD_ogg_stream_reset(ogg_stream_state *os);
extern int FMOD_ogg_stream_reset_serialno(ogg_stream_state *os,int serialno);
extern int FMOD_ogg_stream_destroy(void *context, ogg_stream_state *os);
extern int FMOD_ogg_stream_check(ogg_stream_state *os);
extern int FMOD_ogg_stream_eos(ogg_stream_state *os);
extern void FMOD_ogg_page_checksum_set(ogg_page *og);
extern int FMOD_ogg_page_version(const ogg_page *og);
extern int FMOD_ogg_page_continued(const ogg_page *og);
extern int FMOD_ogg_page_bos(const ogg_page *og);
extern int FMOD_ogg_page_eos(const ogg_page *og);
extern ogg_int64_t FMOD_ogg_page_granulepos(const ogg_page *og);
extern int FMOD_ogg_page_serialno(const ogg_page *og);
extern ogg_int32_t FMOD_ogg_page_pageno(const ogg_page *og);
extern int FMOD_ogg_page_packets(const ogg_page *og);
extern void FMOD_ogg_packet_clear(void *context, ogg_packet *op);
#ifdef __cplusplus
}
#endif
#endif /* _OGG_H */

View file

@ -0,0 +1,201 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: #ifdef jail to whip a few platforms into the UNIX ideal.
last mod: $Id: os_types.h 14997 2008-06-04 03:27:18Z ivo $
********************************************************************/
#ifndef _OS_TYPES_H
#define _OS_TYPES_H
/* make it easy on the folks that want to compile the libs with a
different malloc than stdlib */
#if 1
extern void * FMOD_OggVorbis_Malloc(void *context, int size);
extern void * FMOD_OggVorbis_Calloc(void *context, int count, int size);
extern void * FMOD_OggVorbis_ReAlloc(void *context, void *ptr, int size);
extern void FMOD_OggVorbis_Free(void *context, void *ptr);
#define _ogg_malloc(_x) FMOD_OggVorbis_Malloc(context, _x)
#define _ogg_calloc(_x, _y) FMOD_OggVorbis_Calloc(context, _x, _y)
#define _ogg_realloc(_x, _y) FMOD_OggVorbis_ReAlloc(context, _x, _y)
#define _ogg_free(_x) FMOD_OggVorbis_Free(context, _x)
#include "../../../../../src/fmod_types.h" /* For FMOD_memset/memcpy */
#else
#define _ogg_malloc malloc
#define _ogg_calloc calloc
#define _ogg_realloc realloc
#define _ogg_free free
#endif
#if defined(WIN32) || defined(_XENON)
# if defined(__CYGWIN__)
# include <stdint.h>
typedef int16_t ogg_int16_t;
typedef uint16_t ogg_uint16_t;
typedef int32_t ogg_int32_t;
typedef uint32_t ogg_uint32_t;
typedef int64_t ogg_int64_t;
typedef uint64_t ogg_uint64_t;
# elif defined(__MINGW32__)
# include <sys/types.h>
typedef short ogg_int16_t;
typedef unsigned short ogg_uint16_t;
typedef int ogg_int32_t;
typedef unsigned int ogg_uint32_t;
typedef long long ogg_int64_t;
typedef unsigned long long ogg_uint64_t;
# elif defined(__MWERKS__)
typedef long long ogg_int64_t;
typedef int ogg_int32_t;
typedef unsigned int ogg_uint32_t;
typedef short ogg_int16_t;
typedef unsigned short ogg_uint16_t;
# else
/* MSVC/Borland */
typedef __int64 ogg_int64_t;
typedef __int32 ogg_int32_t;
typedef unsigned __int32 ogg_uint32_t;
typedef __int16 ogg_int16_t;
typedef unsigned __int16 ogg_uint16_t;
# endif
#elif defined(__MACOS__)
# include <sys/types.h>
typedef SInt16 ogg_int16_t;
typedef UInt16 ogg_uint16_t;
typedef SInt32 ogg_int32_t;
typedef UInt32 ogg_uint32_t;
typedef SInt64 ogg_int64_t;
#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
# include <sys/types.h>
typedef int16_t ogg_int16_t;
typedef u_int16_t ogg_uint16_t;
typedef int32_t ogg_int32_t;
typedef u_int32_t ogg_uint32_t;
typedef int64_t ogg_int64_t;
#elif defined(__HAIKU__)
/* Haiku */
# include <sys/types.h>
typedef short ogg_int16_t;
typedef unsigned short ogg_uint16_t;
typedef int ogg_int32_t;
typedef unsigned int ogg_uint32_t;
typedef long long ogg_int64_t;
#elif defined(__BEOS__)
/* Be */
# include <inttypes.h>
typedef int16_t ogg_int16_t;
typedef u_int16_t ogg_uint16_t;
typedef int32_t ogg_int32_t;
typedef u_int32_t ogg_uint32_t;
typedef int64_t ogg_int64_t;
#elif defined (__EMX__)
/* OS/2 GCC */
typedef short ogg_int16_t;
typedef unsigned short ogg_uint16_t;
typedef int ogg_int32_t;
typedef unsigned int ogg_uint32_t;
typedef long long ogg_int64_t;
#elif defined (R5900)
/* PS2 */
typedef short ogg_int16_t;
typedef int ogg_int32_t;
typedef unsigned int ogg_uint32_t;
typedef long ogg_int64_t;
#if defined(__MWERKS__)
#define alloca __alloca
#endif
#elif defined (DJGPP)
/* DJGPP */
typedef short ogg_int16_t;
typedef int ogg_int32_t;
typedef unsigned int ogg_uint32_t;
typedef long long ogg_int64_t;
#elif defined(__SYMBIAN32__)
/* Symbian GCC */
typedef signed short ogg_int16_t;
typedef unsigned short ogg_uint16_t;
typedef signed int ogg_int32_t;
typedef unsigned int ogg_uint32_t;
typedef long long int ogg_int64_t;
#elif defined(SN_TARGET_PS3) || defined(_PS3)
#include <alloca.h>
typedef signed short ogg_int16_t;
typedef signed int ogg_int32_t;
typedef unsigned int ogg_uint32_t;
typedef signed long long ogg_int64_t;
#elif defined (GEKKO)
#if defined(PLATFORM_WII)
#include <alloca.h>
#else
#if defined(__MWERKS__)
#define alloca __alloca
#endif
#endif
/* Gamecube */
typedef short ogg_int16_t;
typedef int ogg_int32_t;
typedef unsigned int ogg_uint32_t;
typedef long long ogg_int64_t;
#elif defined (__psp__)
typedef short ogg_int16_t;
typedef int ogg_int32_t;
typedef unsigned int ogg_uint32_t;
typedef long long ogg_int64_t;
#elif defined (__sun) || defined (__linux__)
typedef short ogg_int16_t;
typedef int ogg_int32_t;
typedef unsigned int ogg_uint32_t;
typedef long long ogg_int64_t;
#else
# include <sys/types.h>
# include <ogg/config_types.h>
#endif
#endif /* _OS_TYPES_H */

286
lib/ogg_vorbis/ogg/src/bitwise.c Executable file
View file

@ -0,0 +1,286 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: packing variable sized words into an octet stream
last mod: $Id: bitwise.c 16051 2009-05-27 05:00:06Z xiphmont $
********************************************************************/
/* We're 'LSb' endian; if we write a word but read individual bits,
then we'll read the lsb first */
#include <string.h>
#include <stdlib.h>
#include <ogg/ogg.h>
#define BUFFER_INCREMENT 256
static const ogg_uint32_t mask[]=
{0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
0x3fffffff,0x7fffffff,0xffffffff };
void FMOD_oggpack_reset(oggpack_buffer *b){
if(!b->ptr)return;
b->ptr=b->buffer;
b->buffer[0]=0;
b->endbit=b->endbyte=0;
}
void FMOD_oggpackB_reset(oggpack_buffer *b){
FMOD_oggpack_reset(b);
}
void FMOD_oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
FMOD_memset(b,0,sizeof(*b));
b->buffer=b->ptr=buf;
b->storage=bytes;
}
void FMOD_oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
FMOD_oggpack_readinit(b,buf,bytes);
}
/* Read in bits without advancing the bitptr; bits <= 32 */
ogg_int32_t FMOD_oggpack_look(oggpack_buffer *b,int bits){
ogg_uint32_t ret;
ogg_uint32_t m=mask[bits];
bits+=b->endbit;
if(b->endbyte+4>=b->storage){
/* not the main path */
if(b->endbyte*8+bits>b->storage*8)return(-1);
}
ret=b->ptr[0]>>b->endbit;
if(bits>8){
ret|=b->ptr[1]<<(8-b->endbit);
if(bits>16){
ret|=b->ptr[2]<<(16-b->endbit);
if(bits>24){
ret|=b->ptr[3]<<(24-b->endbit);
if(bits>32 && b->endbit)
ret|=b->ptr[4]<<(32-b->endbit);
}
}
}
return(m&ret);
}
/* Read in bits without advancing the bitptr; bits <= 32 */
ogg_int32_t FMOD_oggpackB_look(oggpack_buffer *b,int bits){
ogg_uint32_t ret;
int m=32-bits;
bits+=b->endbit;
if(b->endbyte+4>=b->storage){
/* not the main path */
if(b->endbyte*8+bits>b->storage*8)return(-1);
}
ret=b->ptr[0]<<(24+b->endbit);
if(bits>8){
ret|=b->ptr[1]<<(16+b->endbit);
if(bits>16){
ret|=b->ptr[2]<<(8+b->endbit);
if(bits>24){
ret|=b->ptr[3]<<(b->endbit);
if(bits>32 && b->endbit)
ret|=b->ptr[4]>>(8-b->endbit);
}
}
}
return ((ret&0xffffffff)>>(m>>1))>>((m+1)>>1);
}
ogg_int32_t FMOD_oggpack_look1(oggpack_buffer *b){
if(b->endbyte>=b->storage)return(-1);
return((b->ptr[0]>>b->endbit)&1);
}
ogg_int32_t FMOD_oggpackB_look1(oggpack_buffer *b){
if(b->endbyte>=b->storage)return(-1);
return((b->ptr[0]>>(7-b->endbit))&1);
}
void FMOD_oggpack_adv(oggpack_buffer *b,int bits){
bits+=b->endbit;
b->ptr+=bits/8;
b->endbyte+=bits/8;
b->endbit=bits&7;
}
void FMOD_oggpackB_adv(oggpack_buffer *b,int bits){
FMOD_oggpack_adv(b,bits);
}
void FMOD_oggpack_adv1(oggpack_buffer *b){
if(++(b->endbit)>7){
b->endbit=0;
b->ptr++;
b->endbyte++;
}
}
void FMOD_oggpackB_adv1(oggpack_buffer *b){
FMOD_oggpack_adv1(b);
}
/* bits <= 32 */
ogg_int32_t FMOD_oggpack_read(oggpack_buffer *b,int bits){
ogg_int32_t ret;
ogg_uint32_t m=mask[bits];
bits+=b->endbit;
if(b->endbyte+4>=b->storage){
/* not the main path */
ret=-1;
if(b->endbyte*8+bits>b->storage*8)goto overflow;
}
ret=b->ptr[0]>>b->endbit;
if(bits>8){
ret|=b->ptr[1]<<(8-b->endbit);
if(bits>16){
ret|=b->ptr[2]<<(16-b->endbit);
if(bits>24){
ret|=b->ptr[3]<<(24-b->endbit);
if(bits>32 && b->endbit){
ret|=b->ptr[4]<<(32-b->endbit);
}
}
}
}
ret&=m;
overflow:
b->ptr+=bits/8;
b->endbyte+=bits/8;
b->endbit=bits&7;
return(ret);
}
/* bits <= 32 */
ogg_int32_t FMOD_oggpackB_read(oggpack_buffer *b,int bits){
ogg_int32_t ret;
ogg_int32_t m=32-bits;
bits+=b->endbit;
if(b->endbyte+4>=b->storage){
/* not the main path */
ret=-1;
if(b->endbyte*8+bits>b->storage*8)goto overflow;
/* special case to avoid reading b->ptr[0], which might be past the end of
the buffer; also skips some useless accounting */
else if(!bits)return(0);
}
ret=b->ptr[0]<<(24+b->endbit);
if(bits>8){
ret|=b->ptr[1]<<(16+b->endbit);
if(bits>16){
ret|=b->ptr[2]<<(8+b->endbit);
if(bits>24){
ret|=b->ptr[3]<<(b->endbit);
if(bits>32 && b->endbit)
ret|=b->ptr[4]>>(8-b->endbit);
}
}
}
ret=((ret&0xffffffff)>>(m>>1))>>((m+1)>>1);
overflow:
b->ptr+=bits/8;
b->endbyte+=bits/8;
b->endbit=bits&7;
return(ret);
}
ogg_int32_t FMOD_oggpack_read1(oggpack_buffer *b){
ogg_int32_t ret;
if(b->endbyte>=b->storage){
/* not the main path */
ret=-1;
goto overflow;
}
ret=(b->ptr[0]>>b->endbit)&1;
overflow:
b->endbit++;
if(b->endbit>7){
b->endbit=0;
b->ptr++;
b->endbyte++;
}
return(ret);
}
ogg_int32_t FMOD_oggpackB_read1(oggpack_buffer *b){
ogg_int32_t ret;
if(b->endbyte>=b->storage){
/* not the main path */
ret=-1;
goto overflow;
}
ret=(b->ptr[0]>>(7-b->endbit))&1;
overflow:
b->endbit++;
if(b->endbit>7){
b->endbit=0;
b->ptr++;
b->endbyte++;
}
return(ret);
}
ogg_int32_t FMOD_oggpack_bytes(oggpack_buffer *b){
return(b->endbyte+(b->endbit+7)/8);
}
ogg_int32_t FMOD_oggpack_bits(oggpack_buffer *b){
return(b->endbyte*8+b->endbit);
}
ogg_int32_t FMOD_oggpackB_bytes(oggpack_buffer *b){
return FMOD_oggpack_bytes(b);
}
ogg_int32_t FMOD_oggpackB_bits(oggpack_buffer *b){
return FMOD_oggpack_bits(b);
}
unsigned char *FMOD_oggpack_get_buffer(oggpack_buffer *b){
return(b->buffer);
}
unsigned char *FMOD_oggpackB_get_buffer(oggpack_buffer *b){
return FMOD_oggpack_get_buffer(b);
}
#undef BUFFER_INCREMENT

964
lib/ogg_vorbis/ogg/src/framing.c Executable file
View file

@ -0,0 +1,964 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: code raw packets into framed OggSquish stream and
decode Ogg streams back into raw packets
last mod: $Id: framing.c 16051 2009-05-27 05:00:06Z xiphmont $
note: The CRC code is directly derived from public domain code by
Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html
for details.
********************************************************************/
#include <stdlib.h>
#include <string.h>
#include <ogg/ogg.h>
/* A complete description of Ogg framing exists in docs/framing.html */
int FMOD_ogg_page_version(const ogg_page *og){
return((int)(og->header[4]));
}
int FMOD_ogg_page_continued(const ogg_page *og){
return((int)(og->header[5]&0x01));
}
int FMOD_ogg_page_bos(const ogg_page *og){
return((int)(og->header[5]&0x02));
}
int FMOD_ogg_page_eos(const ogg_page *og){
return((int)(og->header[5]&0x04));
}
ogg_int64_t FMOD_ogg_page_granulepos(const ogg_page *og){
unsigned char *page=og->header;
ogg_int64_t granulepos=page[13]&(0xff);
granulepos= (granulepos<<8)|(page[12]&0xff);
granulepos= (granulepos<<8)|(page[11]&0xff);
granulepos= (granulepos<<8)|(page[10]&0xff);
granulepos= (granulepos<<8)|(page[9]&0xff);
granulepos= (granulepos<<8)|(page[8]&0xff);
granulepos= (granulepos<<8)|(page[7]&0xff);
granulepos= (granulepos<<8)|(page[6]&0xff);
return(granulepos);
}
int FMOD_ogg_page_serialno(const ogg_page *og){
return(og->header[14] |
(og->header[15]<<8) |
(og->header[16]<<16) |
(og->header[17]<<24));
}
ogg_int32_t FMOD_ogg_page_pageno(const ogg_page *og){
return(og->header[18] |
(og->header[19]<<8) |
(og->header[20]<<16) |
(og->header[21]<<24));
}
/* returns the number of packets that are completed on this page (if
the leading packet is begun on a previous page, but ends on this
page, it's counted */
/* NOTE:
If a page consists of a packet begun on a previous page, and a new
packet begun (but not completed) on this page, the return will be:
ogg_page_packets(page) ==1,
ogg_page_continued(page) !=0
If a page happens to be a single packet that was begun on a
previous page, and spans to the next page (in the case of a three or
more page packet), the return will be:
ogg_page_packets(page) ==0,
ogg_page_continued(page) !=0
*/
int FMOD_ogg_page_packets(const ogg_page *og){
int i,n=og->header[26],count=0;
for(i=0;i<n;i++)
if(og->header[27+i]<255)count++;
return(count);
}
static const ogg_uint32_t crc_lookup[256]={
0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,
0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,
0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,
0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,
0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,
0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,
0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,
0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,
0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,
0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,
0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,
0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,
0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,
0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,
0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,
0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,
0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,
0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,
0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,
0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,
0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,
0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,
0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,
0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,
0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,
0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,
0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,
0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,
0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,
0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,
0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,
0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4};
/* init the encode/decode logical stream state */
int FMOD_ogg_stream_init(void *context, ogg_stream_state *os,int serialno){
if(os){
FMOD_memset(os,0,sizeof(*os));
#if 1
os->body_storage=(4*1024) + 512;
os->lacing_storage=64;
#else
os->body_storage=16*1024;
os->lacing_storage=1024;
#endif
os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
if(!os->body_data || !os->lacing_vals || !os->granule_vals){
FMOD_ogg_stream_clear(context, os);
return -1;
}
os->serialno=serialno;
return(0);
}
return(-1);
}
/* async/delayed error detection for the ogg_stream_state */
int FMOD_ogg_stream_check(ogg_stream_state *os){
if(!os || !os->body_data) return -1;
return 0;
}
/* _clear does not free os, only the non-flat storage within */
int FMOD_ogg_stream_clear(void *context, ogg_stream_state *os){
if(os){
if(os->body_data)_ogg_free(os->body_data);
if(os->lacing_vals)_ogg_free(os->lacing_vals);
if(os->granule_vals)_ogg_free(os->granule_vals);
FMOD_memset(os,0,sizeof(*os));
}
return(0);
}
int FMOD_ogg_stream_destroy(void *context, ogg_stream_state *os){
if(os){
FMOD_ogg_stream_clear(context, os);
_ogg_free(os);
}
return(0);
}
/* Helpers for ogg_stream_encode; this keeps the structure and
what's happening fairly clear */
static int _os_body_expand(void *context, ogg_stream_state *os,int needed){
if(os->body_storage<=os->body_fill+needed){
void *ret;
ret=_ogg_realloc(os->body_data,(os->body_storage+needed+1024)*
sizeof(*os->body_data));
if(!ret){
FMOD_ogg_stream_clear(context, os);
return -1;
}
os->body_storage+=(needed+1024);
os->body_data=ret;
}
return 0;
}
static int _os_lacing_expand(void *context, ogg_stream_state *os,int needed){
if(os->lacing_storage<=os->lacing_fill+needed){
void *ret;
ret=_ogg_realloc(os->lacing_vals,(os->lacing_storage+needed+32)*
sizeof(*os->lacing_vals));
if(!ret){
FMOD_ogg_stream_clear(context, os);
return -1;
}
os->lacing_vals=ret;
ret=_ogg_realloc(os->granule_vals,(os->lacing_storage+needed+32)*
sizeof(*os->granule_vals));
if(!ret){
FMOD_ogg_stream_clear(context, os);
return -1;
}
os->granule_vals=ret;
os->lacing_storage+=(needed+32);
}
return 0;
}
/* checksum the page */
/* Direct table CRC; note that this will be faster in the future if we
perform the checksum silmultaneously with other copies */
void FMOD_ogg_page_checksum_set(ogg_page *og){
if(og){
ogg_uint32_t crc_reg=0;
int i;
/* safety; needed for API behavior, but not framing code */
og->header[22]=0;
og->header[23]=0;
og->header[24]=0;
og->header[25]=0;
for(i=0;i<og->header_len;i++)
crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]];
for(i=0;i<og->body_len;i++)
crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
og->header[22]=(unsigned char)(crc_reg&0xff);
og->header[23]=(unsigned char)((crc_reg>>8)&0xff);
og->header[24]=(unsigned char)((crc_reg>>16)&0xff);
og->header[25]=(unsigned char)((crc_reg>>24)&0xff);
}
}
/* submit data to the internal buffer of the framing engine */
//int ogg_stream_iovecin(void *context, ogg_stream_state *os, ogg_iovec_t *iov, int count,
// ogg_int32_t e_o_s, ogg_int64_t granulepos){
//
// int bytes = 0, lacing_vals, i;
//
// if(FMOD_ogg_stream_check(os)) return -1;
// if(!iov) return 0;
//
// for (i = 0; i < count; ++i) bytes += (int)iov[i].iov_len;
// lacing_vals=bytes/255+1;
//
// if(os->body_returned){
// /* advance packet data according to the body_returned pointer. We
// had to keep it around to return a pointer into the buffer last
// call */
//
// os->body_fill-=os->body_returned;
// if(os->body_fill)
// memmove(os->body_data,os->body_data+os->body_returned,
// os->body_fill);
// os->body_returned=0;
// }
//
// /* make sure we have the buffer storage */
// if(_os_body_expand(context, os,bytes) || _os_lacing_expand(context, os,lacing_vals))
// return -1;
//
// /* Copy in the submitted packet. Yes, the copy is a waste; this is
// the liability of overly clean abstraction for the time being. It
// will actually be fairly easy to eliminate the extra copy in the
// future */
//
// for (i = 0; i < count; ++i) {
// FMOD_memcpy(os->body_data+os->body_fill, iov[i].iov_base, iov[i].iov_len);
// os->body_fill += (int)iov[i].iov_len;
// }
//
// /* Store lacing vals for this packet */
// for(i=0;i<lacing_vals-1;i++){
// os->lacing_vals[os->lacing_fill+i]=255;
// os->granule_vals[os->lacing_fill+i]=os->granulepos;
// }
// os->lacing_vals[os->lacing_fill+i]=bytes%255;
// os->granulepos=os->granule_vals[os->lacing_fill+i]=granulepos;
//
// /* flag the first segment as the beginning of the packet */
// os->lacing_vals[os->lacing_fill]|= 0x100;
//
// os->lacing_fill+=lacing_vals;
//
// /* for the sake of completeness */
// os->packetno++;
//
// if(e_o_s)os->e_o_s=1;
//
// return(0);
//}
//
//int FMOD_ogg_stream_packetin(void *context, ogg_stream_state *os,ogg_packet *op){
// ogg_iovec_t iov;
// iov.iov_base = op->packet;
// iov.iov_len = op->bytes;
// return ogg_stream_iovecin(context, os, &iov, 1, op->e_o_s, op->granulepos);
//}
//
///* This will flush remaining packets into a page (returning nonzero),
// even if there is not enough data to trigger a flush normally
// (undersized page). If there are no packets or partial packets to
// flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will
// try to flush a normal sized page like ogg_stream_pageout; a call to
// ogg_stream_flush does not guarantee that all packets have flushed.
// Only a return value of 0 from ogg_stream_flush indicates all packet
// data is flushed into pages.
//
// since ogg_stream_flush will flush the last page in a stream even if
// it's undersized, you almost certainly want to use ogg_stream_pageout
// (and *not* ogg_stream_flush) unless you specifically need to flush
// an page regardless of size in the middle of a stream. */
//
//int FMOD_ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
// int i;
// int vals=0;
// int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
// int bytes=0;
// ogg_int32_t acc=0;
// ogg_int64_t granule_pos=-1;
//
// if(FMOD_ogg_stream_check(os)) return 0;
// if(maxvals==0)return 0;
//
// /* construct a page */
// /* decide how many segments to include */
//
// /* If this is the initial header case, the first page must only include
// the initial header packet */
// if(os->b_o_s==0){ /* 'initial header page' case */
// granule_pos=0;
// for(vals=0;vals<maxvals;vals++){
// if((os->lacing_vals[vals]&0x0ff)<255){
// vals++;
// break;
// }
// }
// }else{
// for(vals=0;vals<maxvals;vals++){
// if(acc>4096)break;
// acc+=os->lacing_vals[vals]&0x0ff;
// if((os->lacing_vals[vals]&0xff)<255)
// granule_pos=os->granule_vals[vals];
// }
// }
//
// /* construct the header in temp storage */
// FMOD_memcpy(os->header,"OggS",4);
//
// /* stream structure version */
// os->header[4]=0x00;
//
// /* continued packet flag? */
// os->header[5]=0x00;
// if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
// /* first page flag? */
// if(os->b_o_s==0)os->header[5]|=0x02;
// /* last page flag? */
// if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
// os->b_o_s=1;
//
// /* 64 bits of PCM position */
// for(i=6;i<14;i++){
// os->header[i]=(unsigned char)(granule_pos&0xff);
// granule_pos>>=8;
// }
//
// /* 32 bits of stream serial number */
// {
// ogg_int32_t serialno=os->serialno;
// for(i=14;i<18;i++){
// os->header[i]=(unsigned char)(serialno&0xff);
// serialno>>=8;
// }
// }
//
// /* 32 bits of page counter (we have both counter and page header
// because this val can roll over) */
// if(os->pageno==-1)os->pageno=0; /* because someone called
// stream_reset; this would be a
// strange thing to do in an
// encode stream, but it has
// plausible uses */
// {
// ogg_int32_t pageno=os->pageno++;
// for(i=18;i<22;i++){
// os->header[i]=(unsigned char)(pageno&0xff);
// pageno>>=8;
// }
// }
//
// /* zero for computation; filled in later */
// os->header[22]=0;
// os->header[23]=0;
// os->header[24]=0;
// os->header[25]=0;
//
// /* segment table */
// os->header[26]=(unsigned char)(vals&0xff);
// for(i=0;i<vals;i++)
// bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff);
//
// /* set pointers in the ogg_page struct */
// og->header=os->header;
// og->header_len=os->header_fill=vals+27;
// og->body=os->body_data+os->body_returned;
// og->body_len=bytes;
//
// /* advance the lacing data and set the body_returned pointer */
//
// os->lacing_fill-=vals;
// memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
// memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
// os->body_returned+=bytes;
//
// /* calculate the checksum */
//
// ogg_page_checksum_set(og);
//
// /* done */
// return(1);
//}
//
//
///* This constructs pages from buffered packet segments. The pointers
//returned are to static buffers; do not free. The returned buffers are
//good only until the next call (using the same ogg_stream_state) */
//
//int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
// if(FMOD_ogg_stream_check(os)) return 0;
//
// if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
// os->body_fill-os->body_returned > 4096 ||/* 'page nominal size' case */
// os->lacing_fill>=255 || /* 'segment table full' case */
// (os->lacing_fill&&!os->b_o_s)){ /* 'initial header page' case */
//
// return(ogg_stream_flush(os,og));
// }
//
// /* not enough data to construct a page and not end of stream */
// return 0;
//}
int FMOD_ogg_stream_eos(ogg_stream_state *os){
if(FMOD_ogg_stream_check(os)) return 1;
return os->e_o_s;
}
/* DECODING PRIMITIVES: packet streaming layer **********************/
/* This has two layers to place more of the multi-serialno and paging
control in the application's hands. First, we expose a data buffer
using ogg_sync_buffer(). The app either copies into the
buffer, or passes it directly to read(), etc. We then call
ogg_sync_wrote() to tell how many bytes we just added.
Pages are returned (pointers into the buffer in ogg_sync_state)
by ogg_sync_pageout(). The page is then submitted to
ogg_stream_pagein() along with the appropriate
ogg_stream_state* (ie, matching serialno). We then get raw
packets out calling ogg_stream_packetout() with a
ogg_stream_state. */
/* initialize the struct to a known state */
int FMOD_ogg_sync_init(ogg_sync_state *oy){
if(oy){
oy->storage = -1; /* used as a readiness flag */
FMOD_memset(oy,0,sizeof(*oy));
}
return(0);
}
/* clear non-flat storage within */
int FMOD_ogg_sync_clear(void *context, ogg_sync_state *oy){
if(oy){
if(oy->data)_ogg_free(oy->data);
FMOD_memset(oy,0,sizeof(*oy));
}
return(0);
}
int FMOD_ogg_sync_destroy(void *context, ogg_sync_state *oy){
if(oy){
FMOD_ogg_sync_clear(context, oy);
_ogg_free(oy);
}
return(0);
}
int FMOD_ogg_sync_check(ogg_sync_state *oy){
if(oy->storage<0) return -1;
return 0;
}
char *FMOD_ogg_sync_buffer(void *context, ogg_sync_state *oy, ogg_int32_t size){
if(FMOD_ogg_sync_check(oy)) return NULL;
/* first, clear out any space that has been previously returned */
if(oy->returned){
oy->fill-=oy->returned;
if(oy->fill>0)
memmove(oy->data,oy->data+oy->returned,oy->fill);
oy->returned=0;
}
if(size>oy->storage-oy->fill){
/* We need to extend the internal buffer */
ogg_int32_t newsize=size+oy->fill+4096; /* an extra page to be nice */
void *ret;
if(oy->data)
ret=_ogg_realloc(oy->data,newsize);
else
ret=_ogg_malloc(newsize);
oy->data = 0; /* Null out old pointer so clear doesnt fall over on bad/released data? */
if(!ret){
FMOD_ogg_sync_clear(context, oy);
return NULL;
}
oy->data=ret;
oy->storage=newsize;
}
/* expose a segment at least as large as requested at the fill mark */
return((char *)oy->data+oy->fill);
}
int FMOD_ogg_sync_wrote(ogg_sync_state *oy, ogg_int32_t bytes){
if(FMOD_ogg_sync_check(oy))return -1;
if(oy->fill+bytes>oy->storage)return -1;
oy->fill+=bytes;
return(0);
}
/* sync the stream. This is meant to be useful for finding page
boundaries.
return values for this:
-n) skipped n bytes
0) page not ready; more data (no bytes skipped)
n) page synced at current location; page length n bytes
*/
ogg_int32_t FMOD_ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
unsigned char *page=oy->data+oy->returned;
unsigned char *next;
ogg_int32_t bytes=oy->fill-oy->returned;
if(FMOD_ogg_sync_check(oy))return 0;
if(oy->headerbytes==0){
int headerbytes,i;
if(bytes<27)return(0); /* not enough for a header */
/* verify capture pattern */
if(memcmp(page,"OggS",4))goto sync_fail;
headerbytes=page[26]+27;
if(bytes<headerbytes)return(0); /* not enough for header + seg table */
/* count up body length in the segment table */
for(i=0;i<page[26];i++)
oy->bodybytes+=page[27+i];
oy->headerbytes=headerbytes;
}
if(oy->bodybytes+oy->headerbytes>bytes)return(0);
/* The whole test page is buffered. Verify the checksum */
{
/* Grab the checksum bytes, set the header field to zero */
char chksum[4];
ogg_page log;
FMOD_memcpy(chksum,page+22,4);
FMOD_memset(page+22,0,4);
/* set up a temp page struct and recompute the checksum */
log.header=page;
log.header_len=oy->headerbytes;
log.body=page+oy->headerbytes;
log.body_len=oy->bodybytes;
FMOD_ogg_page_checksum_set(&log);
/* Compare */
if(memcmp(chksum,page+22,4)){
/* D'oh. Mismatch! Corrupt page (or miscapture and not a page
at all) */
/* replace the computed checksum with the one actually read in */
FMOD_memcpy(page+22,chksum,4);
/* Bad checksum. Lose sync */
goto sync_fail;
}
}
/* yes, have a whole page all ready to go */
{
unsigned char *page=oy->data+oy->returned;
ogg_int32_t bytes;
if(og){
og->header=page;
og->header_len=oy->headerbytes;
og->body=page+oy->headerbytes;
og->body_len=oy->bodybytes;
}
oy->unsynced=0;
oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
oy->headerbytes=0;
oy->bodybytes=0;
return(bytes);
}
sync_fail:
oy->headerbytes=0;
oy->bodybytes=0;
/* search for possible capture */
next=memchr(page+1,'O',bytes-1);
if(!next)
next=oy->data+oy->fill;
oy->returned=(int)(next-oy->data);
return((ogg_int32_t)-(next-page));
}
/* sync the stream and get a page. Keep trying until we find a page.
Supress 'sync errors' after reporting the first.
return values:
-1) recapture (hole in data)
0) need more data
1) page returned
Returns pointers into buffered data; invalidated by next call to
_stream, _clear, _init, or _buffer */
int FMOD_ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
if(FMOD_ogg_sync_check(oy))return 0;
/* all we need to do is verify a page at the head of the stream
buffer. If it doesn't verify, we look for the next potential
frame */
for(;;){
ogg_int32_t ret=FMOD_ogg_sync_pageseek(oy,og);
if(ret>0){
/* have a page */
return(1);
}
if(ret==0){
/* need more data */
return(0);
}
/* head did not start a synced page... skipped some bytes */
if(!oy->unsynced){
oy->unsynced=1;
return(-1);
}
/* loop. keep looking */
}
}
/* add the incoming page to the stream state; we decompose the page
into packet segments here as well. */
int FMOD_ogg_stream_pagein(void *context, ogg_stream_state *os, ogg_page *og){
unsigned char *header=og->header;
unsigned char *body=og->body;
ogg_int32_t bodysize=og->body_len;
int segptr=0;
int version=FMOD_ogg_page_version(og);
int continued=FMOD_ogg_page_continued(og);
int bos=FMOD_ogg_page_bos(og);
int eos=FMOD_ogg_page_eos(og);
ogg_int64_t granulepos=FMOD_ogg_page_granulepos(og);
int serialno=FMOD_ogg_page_serialno(og);
ogg_int32_t pageno=FMOD_ogg_page_pageno(og);
int segments=header[26];
if(FMOD_ogg_stream_check(os)) return -1;
/* clean up 'returned data' */
{
ogg_int32_t lr=os->lacing_returned;
ogg_int32_t br=os->body_returned;
/* body data */
if(br){
os->body_fill-=br;
if(os->body_fill)
memmove(os->body_data,os->body_data+br,os->body_fill);
os->body_returned=0;
}
if(lr){
/* segment table */
if(os->lacing_fill-lr){
memmove(os->lacing_vals,os->lacing_vals+lr,
(os->lacing_fill-lr)*sizeof(*os->lacing_vals));
memmove(os->granule_vals,os->granule_vals+lr,
(os->lacing_fill-lr)*sizeof(*os->granule_vals));
}
os->lacing_fill-=lr;
os->lacing_packet-=lr;
os->lacing_returned=0;
}
}
/* check the serial number */
if(serialno!=os->serialno)return(-1);
if(version>0)return(-1);
if(_os_lacing_expand(context, os,segments+1)) return -1;
/* are we in sequence? */
if(pageno!=os->pageno){
int i;
/* unroll previous partial packet (if any) */
for(i=os->lacing_packet;i<os->lacing_fill;i++)
os->body_fill-=os->lacing_vals[i]&0xff;
os->lacing_fill=os->lacing_packet;
/* make a note of dropped data in segment table */
if(os->pageno!=-1){
os->lacing_vals[os->lacing_fill++]=0x400;
os->lacing_packet++;
}
}
/* are we a 'continued packet' page? If so, we may need to skip
some segments */
if(continued){
if(os->lacing_fill<1 ||
os->lacing_vals[os->lacing_fill-1]==0x400){
bos=0;
for(;segptr<segments;segptr++){
int val=header[27+segptr];
body+=val;
bodysize-=val;
if(val<255){
segptr++;
break;
}
}
}
}
if(bodysize){
if(_os_body_expand(context, os,bodysize)) return -1;
FMOD_memcpy(os->body_data+os->body_fill,body,bodysize);
os->body_fill+=bodysize;
}
{
int saved=-1;
while(segptr<segments){
int val=header[27+segptr];
os->lacing_vals[os->lacing_fill]=val;
os->granule_vals[os->lacing_fill]=-1;
if(bos){
os->lacing_vals[os->lacing_fill]|=0x100;
bos=0;
}
if(val<255)saved=os->lacing_fill;
os->lacing_fill++;
segptr++;
if(val<255)os->lacing_packet=os->lacing_fill;
}
/* set the granulepos on the last granuleval of the last full packet */
if(saved!=-1){
os->granule_vals[saved]=granulepos;
}
}
if(eos){
os->e_o_s=1;
if(os->lacing_fill>0)
os->lacing_vals[os->lacing_fill-1]|=0x200;
}
os->pageno=pageno+1;
return(0);
}
/* clear things to an initial state. Good to call, eg, before seeking */
int FMOD_ogg_sync_reset(ogg_sync_state *oy){
if(FMOD_ogg_sync_check(oy))return -1;
oy->fill=0;
oy->returned=0;
oy->unsynced=0;
oy->headerbytes=0;
oy->bodybytes=0;
return(0);
}
int FMOD_ogg_stream_reset(ogg_stream_state *os){
if(FMOD_ogg_stream_check(os)) return -1;
os->body_fill=0;
os->body_returned=0;
os->lacing_fill=0;
os->lacing_packet=0;
os->lacing_returned=0;
os->header_fill=0;
os->e_o_s=0;
os->b_o_s=0;
os->pageno=-1;
os->packetno=0;
os->granulepos=0;
return(0);
}
int FMOD_ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
if(FMOD_ogg_stream_check(os)) return -1;
FMOD_ogg_stream_reset(os);
os->serialno=serialno;
return(0);
}
static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
/* The last part of decode. We have the stream broken into packet
segments. Now we need to group them into packets (or return the
out of sync markers) */
int ptr=os->lacing_returned;
if(os->lacing_packet<=ptr)return(0);
if(os->lacing_vals[ptr]&0x400){
/* we need to tell the codec there's a gap; it might need to
handle previous packet dependencies. */
os->lacing_returned++;
os->packetno++;
return(-1);
}
if(!op && !adv)return(1); /* just using peek as an inexpensive way
to ask if there's a whole packet
waiting */
/* Gather the whole packet. We'll have no holes or a partial packet */
{
int size=os->lacing_vals[ptr]&0xff;
int bytes=size;
int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
while(size==255){
int val=os->lacing_vals[++ptr];
size=val&0xff;
if(val&0x200)eos=0x200;
bytes+=size;
}
if(op){
op->e_o_s=eos;
op->b_o_s=bos;
op->packet=os->body_data+os->body_returned;
op->packetno=os->packetno;
op->granulepos=os->granule_vals[ptr];
op->bytes=bytes;
}
if(adv){
os->body_returned+=bytes;
os->lacing_returned=ptr+1;
os->packetno++;
}
}
return(1);
}
int FMOD_ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
if(FMOD_ogg_stream_check(os)) return 0;
return _packetout(os,op,1);
}
int FMOD_ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
if(FMOD_ogg_stream_check(os)) return 0;
return _packetout(os,op,0);
}
void FMOD_ogg_packet_clear(void *context, ogg_packet *op) {
_ogg_free(op->packet);
FMOD_memset(op, 0, sizeof(*op));
}

View file

@ -0,0 +1,242 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
********************************************************************
function: libvorbis codec headers
last mod: $Id: codec.h 16037 2009-05-26 21:10:58Z xiphmont $
********************************************************************/
#ifndef _vorbis_codec_h_
#define _vorbis_codec_h_
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#include <ogg/ogg.h>
typedef struct vorbis_info{
int version;
int channels;
ogg_int32_t 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.
*/
ogg_int32_t bitrate_upper;
ogg_int32_t bitrate_nominal;
ogg_int32_t bitrate_lower;
ogg_int32_t bitrate_window;
void *codec_setup;
} vorbis_info;
/* vorbis_dsp_state buffers the current vorbis audio
analysis/synthesis state. The DSP state belongs to a specific
logical bitstream ****************************************************/
typedef struct vorbis_dsp_state{
// int analysisp;
vorbis_info *vi;
float **pcm;
float **pcmret;
int pcm_storage;
int pcm_current;
int pcm_returned;
int preextrapolate;
int eofflag;
ogg_int32_t lW;
ogg_int32_t W;
ogg_int32_t nW;
ogg_int32_t centerW;
ogg_int64_t granulepos;
ogg_int64_t sequence;
ogg_int64_t glue_bits;
ogg_int64_t time_bits;
ogg_int64_t floor_bits;
ogg_int64_t res_bits;
void *backend_state;
} vorbis_dsp_state;
typedef struct vorbis_block{
/* necessary stream state for linking to the framing abstraction */
float **pcm; /* this is a pointer into local storage */
oggpack_buffer opb;
ogg_int32_t lW;
ogg_int32_t W;
ogg_int32_t nW;
int pcmend;
int mode;
int eofflag;
ogg_int64_t granulepos;
ogg_int64_t sequence;
vorbis_dsp_state *vd; /* For read-only access of configuration */
/* local storage to avoid remallocing; it's up to the mapping to
structure it */
void *localstore;
ogg_int32_t localtop;
ogg_int32_t localalloc;
ogg_int32_t totaluse;
struct alloc_chain *reap;
/* bitmetrics for the frame */
ogg_int32_t glue_bits;
ogg_int32_t time_bits;
ogg_int32_t floor_bits;
ogg_int32_t res_bits;
//void *internal;
} vorbis_block;
/* vorbis_block is a single block of data to be processed as part of
the analysis/synthesis stream; it belongs to a specific logical
bitstream, but is independant from other vorbis_blocks belonging to
that logical bitstream. *************************************************/
struct alloc_chain{
void *ptr;
struct alloc_chain *next;
};
/* vorbis_info contains all the setup information specific to the
specific compression/decompression mode in progress (eg,
psychoacoustic settings, channel setup, options, codebook
etc). vorbis_info and substructures are in backends.h.
*********************************************************************/
/* the comments are not part of vorbis_info so that vorbis_info can be
static storage */
typedef struct vorbis_comment{
/* unlimited user comment fields. libvorbis writes 'libvorbis'
whatever vendor is set to in encode */
char **user_comments;
int *comment_lengths;
int comments;
char *vendor;
} vorbis_comment;
/* libvorbis encodes in two abstraction layers; first we perform DSP
and produce a packet (see docs/analysis.txt). The packet is then
coded into a framed OggSquish bitstream by the second layer (see
docs/framing.txt). Decode is the reverse process; we sync/frame
the bitstream and extract individual packets, then decode the
packet back into PCM audio.
The extra framing/packetizing is used in streaming formats, such as
files. Over the net (such as with UDP), the framing and
packetization aren't necessary as they're provided by the transport
and the streaming layer is not used */
/* Vorbis PRIMITIVES: general ***************************************/
extern int FMOD_vorbis_info_init(void *context, vorbis_info *vi);
extern void FMOD_vorbis_info_clear(void *context, vorbis_info *vi);
extern int FMOD_vorbis_info_blocksize(vorbis_info *vi,int zo);
extern void FMOD_vorbis_comment_init(vorbis_comment *vc);
//extern void FMOD_vorbis_comment_add(void *context, vorbis_comment *vc, const char *comment);
//extern void FMOD_vorbis_comment_add_tag(void *context, vorbis_comment *vc,
// const char *tag, const char *contents);
//extern char *FMOD_vorbis_comment_query(vorbis_comment *vc, const char *tag, int count);
//extern int FMOD_vorbis_comment_query_count(vorbis_comment *vc, const char *tag);
extern void FMOD_vorbis_comment_clear(void *context, vorbis_comment *vc);
extern int FMOD_vorbis_block_init(void *context, vorbis_dsp_state *v, vorbis_block *vb);
extern int FMOD_vorbis_block_clear(void *context, vorbis_block *vb);
extern void FMOD_vorbis_dsp_clear(void *context, vorbis_dsp_state *v);
extern float FMOD_vorbis_granule_time(vorbis_dsp_state *v,
ogg_int64_t granulepos);
extern const char *FMOD_vorbis_version_string(void);
/* Vorbis PRIMITIVES: analysis/DSP layer ****************************/
//extern int FMOD_vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi);
//extern int FMOD_vorbis_commentheader_out(vorbis_comment *vc, ogg_packet *op);
//extern int FMOD_vorbis_analysis_headerout(vorbis_dsp_state *v,
// vorbis_comment *vc,
// ogg_packet *op,
// ogg_packet *op_comm,
// ogg_packet *op_code);
//extern float **FMOD_vorbis_analysis_buffer(void *context, vorbis_dsp_state *v,int vals);
//extern int FMOD_vorbis_analysis_wrote(void *context, vorbis_dsp_state *v,int vals);
//extern int FMOD_vorbis_analysis_blockout(void *context, vorbis_dsp_state *v,vorbis_block *vb);
//extern int FMOD_vorbis_analysis(vorbis_block *vb,ogg_packet *op);
extern int FMOD_vorbis_bitrate_addblock(vorbis_block *vb);
extern int FMOD_vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,
ogg_packet *op);
/* Vorbis PRIMITIVES: synthesis layer *******************************/
extern int FMOD_vorbis_synthesis_idheader(ogg_packet *op);
extern int FMOD_vorbis_synthesis_headerin(void *context, vorbis_info *vi,vorbis_comment *vc,
ogg_packet *op);
extern int FMOD_vorbis_synthesis_init(void *context, vorbis_dsp_state *v,vorbis_info *vi);
extern int FMOD_vorbis_synthesis_restart(vorbis_dsp_state *v);
extern int FMOD_vorbis_synthesis(void *context, vorbis_block *vb,ogg_packet *op);
extern int FMOD_vorbis_synthesis_trackonly(void *context, vorbis_block *vb,ogg_packet *op);
extern int FMOD_vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb);
extern int FMOD_vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm);
extern int FMOD_vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm);
extern int FMOD_vorbis_synthesis_read(vorbis_dsp_state *v,int samples);
extern ogg_int32_t FMOD_vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op);
extern int FMOD_vorbis_synthesis_halfrate(vorbis_info *v,int flag);
extern int FMOD_vorbis_synthesis_halfrate_p(vorbis_info *v);
/* Vorbis ERRORS and return codes ***********************************/
#define OV_FALSE -1
#define OV_EOF -2
#define OV_HOLE -3
#define OV_EREAD -128
#define OV_EFAULT -129
#define OV_EIMPL -130
#define OV_EINVAL -131
#define OV_ENOTVORBIS -132
#define OV_EBADHEADER -133
#define OV_EVERSION -134
#define OV_ENOTAUDIO -135
#define OV_EBADPACKET -136
#define OV_EBADLINK -137
#define OV_ENOSEEK -138
#define OV_EMEMORY -139
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View file

@ -0,0 +1,208 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: stdio-based convenience library for opening/seeking/decoding
last mod: $Id: vorbisfile.h 16243 2009-07-10 02:49:31Z xiphmont $
********************************************************************/
#ifndef _OV_FILE_H_
#define _OV_FILE_H_
#define OV_EXCLUDE_STATIC_CALLBACKS
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#include <stdio.h>
#include "codec.h"
/* The function prototypes for the callbacks are basically the same as for
* the stdio functions fread, fseek, fclose, ftell.
* The one difference is that the FILE * arguments have been replaced with
* a void * - this is to be used as a pointer to whatever internal data these
* functions might need. In the stdio case, it's just a FILE * cast to a void *
*
* If you use other functions, check the docs for these functions and return
* the right values. For seek_func(), you *MUST* return -1 if the stream is
* unseekable
*/
typedef struct {
size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource);
int (*seek_func) (void *datasource, ogg_int64_t offset, int whence);
int (*close_func) (void *datasource);
ogg_int32_t (*tell_func) (void *datasource);
} ov_callbacks;
#ifndef OV_EXCLUDE_STATIC_CALLBACKS
/* a few sets of convenient callbacks, especially for use under
* Windows where ov_open_callbacks() should always be used instead of
* ov_open() to avoid problems with incompatable crt.o version linking
* issues. */
static int _ov_header_fseek_wrap(FILE *f,ogg_int64_t off,int whence){
if(f==NULL)return(-1);
#ifdef __MINGW32__
return fseeko64(f,off,whence);
#elif defined (_WIN32)
return _fseeki64(f,off,whence);
#else
return fseek(f,off,whence);
#endif
}
/* These structs below (OV_CALLBACKS_DEFAULT etc) are defined here as
* static data. That means that every file which includes this header
* will get its own copy of these structs whether it uses them or
* not unless it #defines OV_EXCLUDE_STATIC_CALLBACKS.
* These static symbols are essential on platforms such as Windows on
* which several different versions of stdio support may be linked to
* by different DLLs, and we need to be certain we know which one
* we're using (the same one as the main application).
*/
static ov_callbacks OV_CALLBACKS_DEFAULT = {
(size_t (*)(void *, size_t, size_t, void *)) fread,
(int (*)(void *, ogg_int64_t, int)) _ov_header_fseek_wrap,
(int (*)(void *)) fclose,
(ogg_int32_t (*)(void *)) ftell
};
static ov_callbacks OV_CALLBACKS_NOCLOSE = {
(size_t (*)(void *, size_t, size_t, void *)) fread,
(int (*)(void *, ogg_int64_t, int)) _ov_header_fseek_wrap,
(int (*)(void *)) NULL,
(ogg_int32_t (*)(void *)) ftell
};
static ov_callbacks OV_CALLBACKS_STREAMONLY = {
(size_t (*)(void *, size_t, size_t, void *)) fread,
(int (*)(void *, ogg_int64_t, int)) NULL,
(int (*)(void *)) fclose,
(ogg_int32_t (*)(void *)) NULL
};
static ov_callbacks OV_CALLBACKS_STREAMONLY_NOCLOSE = {
(size_t (*)(void *, size_t, size_t, void *)) fread,
(int (*)(void *, ogg_int64_t, int)) NULL,
(int (*)(void *)) NULL,
(ogg_int32_t (*)(void *)) NULL
};
#endif
#define NOTOPEN 0
#define PARTOPEN 1
#define OPENED 2
#define STREAMSET 3
#define INITSET 4
typedef struct OggVorbis_File {
void *datasource; /* Pointer to a FILE *, etc. */
int seekable;
ogg_int64_t offset;
ogg_int64_t end;
ogg_sync_state oy;
/* If the FILE handle isn't seekable (eg, a pipe), only the current
stream appears */
int links;
ogg_int64_t *offsets;
ogg_int64_t *dataoffsets;
ogg_int32_t *serialnos;
ogg_int64_t *pcmlengths; /* overloaded to maintain binary
compatability; x2 size, stores both
beginning and end values */
vorbis_info *vi;
vorbis_comment *vc;
/* Decoding working state local storage */
ogg_int64_t pcm_offset;
int ready_state;
ogg_int32_t current_serialno;
int current_link;
float bittrack;
float samptrack;
ogg_stream_state os; /* take physical pages, weld into a logical
stream of packets */
vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
vorbis_block vb; /* local working space for packet->PCM decode */
ov_callbacks callbacks;
} OggVorbis_File;
extern int ov_clear(void *context, OggVorbis_File *vf);
extern int ov_fopen(void *context, char *path,OggVorbis_File *vf);
extern int ov_open(void *context, FILE *f,OggVorbis_File *vf,char *initial,ogg_int32_t ibytes);
extern int ov_open_callbacks(void *context, void *datasource, OggVorbis_File *vf,
char *initial, ogg_int32_t ibytes, ov_callbacks callbacks);
extern int ov_test(void *context, FILE *f,OggVorbis_File *vf,char *initial,ogg_int32_t ibytes);
extern int ov_test_callbacks(void *context, void *datasource, OggVorbis_File *vf,
char *initial, ogg_int32_t ibytes, ov_callbacks callbacks);
extern int ov_test_open(void *context, OggVorbis_File *vf);
extern ogg_int32_t ov_bitrate(OggVorbis_File *vf,int i);
extern ogg_int32_t ov_bitrate_instant(OggVorbis_File *vf);
extern ogg_int32_t ov_streams(OggVorbis_File *vf);
extern ogg_int32_t ov_seekable(OggVorbis_File *vf);
extern ogg_int32_t ov_serialnumber(OggVorbis_File *vf,int i);
extern ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i);
extern ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i);
extern float ov_time_total(OggVorbis_File *vf,int i);
extern int ov_raw_seek(void *context, OggVorbis_File *vf,ogg_int64_t pos);
extern int ov_pcm_seek(void *context, OggVorbis_File *vf,ogg_int64_t pos);
extern int ov_pcm_seek_page(void *context, OggVorbis_File *vf,ogg_int64_t pos);
extern int ov_time_seek(void *context, OggVorbis_File *vf,float pos);
extern int ov_time_seek_page(void *context, OggVorbis_File *vf,float pos);
extern int ov_raw_seek_lap(void *context, OggVorbis_File *vf,ogg_int64_t pos);
extern int ov_pcm_seek_lap(void *context, OggVorbis_File *vf,ogg_int64_t pos);
extern int ov_pcm_seek_page_lap(void *context, OggVorbis_File *vf,ogg_int64_t pos);
extern int ov_time_seek_lap(void *context, OggVorbis_File *vf,float pos);
extern int ov_time_seek_page_lap(void *context, OggVorbis_File *vf,float pos);
extern ogg_int64_t ov_raw_tell(OggVorbis_File *vf);
extern ogg_int64_t ov_pcm_tell(OggVorbis_File *vf);
extern float ov_time_tell(OggVorbis_File *vf);
extern vorbis_info *ov_info(OggVorbis_File *vf,int link);
extern vorbis_comment *ov_comment(OggVorbis_File *vf,int link);
extern ogg_int32_t ov_read_float(void *context, OggVorbis_File *vf,float ***pcm_channels,int samples,
int *bitstream);
extern ogg_int32_t ov_read_filter(void *context, OggVorbis_File *vf,char *buffer,int length,
int bigendianp,int word,int sgned,int *bitstream,
void (*filter)(float **pcm,ogg_int32_t channels,ogg_int32_t samples,void *filter_param),void *filter_param);
extern ogg_int32_t ov_read(void *context, OggVorbis_File *vf,char *buffer,int length,
int bigendianp,int word,int sgned,int *bitstream);
extern int ov_crosslap(void *context, OggVorbis_File *vf1,OggVorbis_File *vf2);
extern int ov_halfrate(void *context, OggVorbis_File *vf,int flag);
extern int ov_halfrate_p(OggVorbis_File *vf);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View file

@ -0,0 +1,143 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: libvorbis backend and mapping structures; needed for
static mode headers
last mod: $Id: backends.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
/* this is exposed up here because we need it for static modes.
Lookups for each backend aren't exposed because there's no reason
to do so */
#ifndef _vorbis_backend_h_
#define _vorbis_backend_h_
#include "codec_internal.h"
/* this would all be simpler/shorter with templates, but.... */
/* Floor backend generic *****************************************/
typedef struct{
void (*pack) (vorbis_info_floor *,oggpack_buffer *);
vorbis_info_floor *(*unpack)(void *context, vorbis_info *,oggpack_buffer *);
vorbis_look_floor *(*look) (void *context, vorbis_dsp_state *,vorbis_info_floor *);
void (*free_info) (void *context, vorbis_info_floor *);
void (*free_look) (void *context, vorbis_look_floor *);
void *(*inverse1) (void *context, struct vorbis_block *,vorbis_look_floor *);
int (*inverse2) (void *context, struct vorbis_block *,vorbis_look_floor *,
void *buffer,float *);
} vorbis_func_floor;
typedef struct{
int order;
ogg_int32_t rate;
ogg_int32_t barkmap;
int ampbits;
int ampdB;
int numbooks; /* <= 16 */
int books[16];
// float lessthan; /* encode-only config setting hacks for libvorbis */
// float greaterthan; /* encode-only config setting hacks for libvorbis */
} vorbis_info_floor0;
#define VIF_POSIT 63
#define VIF_CLASS 16
#define VIF_PARTS 31
typedef struct{
int partitions; /* 0 to 31 */
int partitionclass[VIF_PARTS]; /* 0 to 15 */
int class_dim[VIF_CLASS]; /* 1 to 8 */
int class_subs[VIF_CLASS]; /* 0,1,2,3 (bits: 1<<n poss) */
int class_book[VIF_CLASS]; /* subs ^ dim entries */
int class_subbook[VIF_CLASS][8]; /* [VIF_CLASS][subs] */
int mult; /* 1 2 3 or 4 */
int postlist[VIF_POSIT+2]; /* first two implicit */
/* encode side analysis parameters */
float maxover;
float maxunder;
float maxerr;
float twofitweight;
float twofitatten;
int n;
} vorbis_info_floor1;
/* Residue backend generic *****************************************/
typedef struct{
void (*pack) (void *context, vorbis_info_residue *,oggpack_buffer *);
vorbis_info_residue *(*unpack)(void *context, vorbis_info *,oggpack_buffer *);
vorbis_look_residue *(*look) (void *context, vorbis_dsp_state *,
vorbis_info_residue *);
void (*free_info) (void *context, vorbis_info_residue *);
void (*free_look) (void *context, vorbis_look_residue *);
ogg_int32_t **(*class) (void *context, struct vorbis_block *,vorbis_look_residue *,
float **,int *,int);
int (*forward) (void *context, oggpack_buffer *,struct vorbis_block *,
vorbis_look_residue *,
float **,float **,int *,int,ogg_int32_t **);
int (*inverse) (void *context, struct vorbis_block *,vorbis_look_residue *,
float **,int *,int);
} vorbis_func_residue;
typedef struct vorbis_info_residue0{
/* block-partitioned VQ coded straight residue */
ogg_int32_t begin;
ogg_int32_t 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[64]; /* expanded out to pointers in lookup */
int booklist[256]; /* list of second stage books */
const float classmetric1[64];
const float classmetric2[64];
} vorbis_info_residue0;
/* Mapping backend generic *****************************************/
typedef struct{
void (*pack) (vorbis_info *,vorbis_info_mapping *,
oggpack_buffer *);
vorbis_info_mapping *(*unpack)(void *context, vorbis_info *,oggpack_buffer *);
void (*free_info) (void *context, vorbis_info_mapping *);
int (*forward) (void *context, struct vorbis_block *vb);
int (*inverse) (void *context, struct vorbis_block *vb,vorbis_info_mapping *);
} vorbis_func_mapping;
typedef struct vorbis_info_mapping0{
int submaps; /* <= 16 */
int chmuxlist[256]; /* up to 256 channels in a Vorbis stream */
int floorsubmap[16]; /* [mux] submap to floors */
int residuesubmap[16]; /* [mux] submap to residue */
int coupling_steps;
int coupling_mag[256];
int coupling_ang[256];
} vorbis_info_mapping0;
#endif

1094
lib/ogg_vorbis/vorbis/lib/block.c Executable file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,656 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: basic codebook pack/unpack/code/decode operations
last mod: $Id: codebook.c 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ogg/ogg.h>
#include "vorbis/codec.h"
#include "codebook.h"
#include "scales.h"
#include "misc.h"
#include "os.h"
/* packs the given codebook into the bitstream **************************/
#if 0
int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *opb){
ogg_int32_t i,j;
int ordered=0;
/* first the basic parameters */
FMOD_oggpack_write(opb,0x564342,24);
FMOD_oggpack_write(opb,c->dim,16);
FMOD_oggpack_write(opb,c->entries,24);
/* pack the codewords. There are two packings; length ordered and
length random. Decide between the two now. */
for(i=1;i<c->entries;i++)
if(c->lengthlist[i-1]==0 || c->lengthlist[i]<c->lengthlist[i-1])break;
if(i==c->entries)ordered=1;
if(ordered){
/* length ordered. We only need to say how many codewords of
each length. The actual codewords are generated
deterministically */
ogg_int32_t count=0;
FMOD_oggpack_write(opb,1,1); /* ordered */
FMOD_oggpack_write(opb,c->lengthlist[0]-1,5); /* 1 to 32 */
for(i=1;i<c->entries;i++){
ogg_int32_t this=c->lengthlist[i];
ogg_int32_t last=c->lengthlist[i-1];
if(this>last){
for(j=last;j<this;j++){
FMOD_oggpack_write(opb,i-count,_FMOD_ilog(c->entries-count));
count=i;
}
}
}
FMOD_oggpack_write(opb,i-count,_FMOD_ilog(c->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 */
FMOD_oggpack_write(opb,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<c->entries;i++)
if(c->lengthlist[i]==0)break;
if(i==c->entries){
FMOD_oggpack_write(opb,0,1); /* no unused entries */
for(i=0;i<c->entries;i++)
FMOD_oggpack_write(opb,c->lengthlist[i]-1,5);
}else{
FMOD_oggpack_write(opb,1,1); /* we have unused entries; thus we tag */
for(i=0;i<c->entries;i++){
if(c->lengthlist[i]==0){
FMOD_oggpack_write(opb,0,1);
}else{
FMOD_oggpack_write(opb,1,1);
FMOD_oggpack_write(opb,c->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? */
FMOD_oggpack_write(opb,c->maptype,4);
switch(c->maptype){
case 0:
/* no mapping */
break;
case 1:case 2:
/* implicitly populated value mapping */
/* explicitly populated value mapping */
if(!c->quantlist){
/* no quantlist? error */
return(-1);
}
/* values that define the dequantization */
FMOD_oggpack_write(opb,c->q_min,32);
FMOD_oggpack_write(opb,c->q_delta,32);
FMOD_oggpack_write(opb,c->q_quant-1,4);
FMOD_oggpack_write(opb,c->q_sequencep,1);
{
int quantvals;
switch(c->maptype){
case 1:
/* a single column of (c->entries/c->dim) quantized values for
building a full value list algorithmically (square lattice) */
quantvals=_FMOD_book_maptype1_quantvals(c);
break;
case 2:
/* every value (c->entries*c->dim total) specified explicitly */
quantvals=c->entries*c->dim;
break;
default: /* NOT_REACHABLE */
quantvals=-1;
}
/* quantized values */
for(i=0;i<quantvals;i++)
FMOD_oggpack_write(opb,labs(c->quantlist[i]),c->q_quant);
}
break;
default:
/* error case; we don't have any other map types now */
return(-1);
}
return(0);
}
#endif
/* unpacks a codebook from the packet buffer into the codebook struct,
readies the codebook auxiliary structures for decode *************/
int FMOD_vorbis_staticbook_unpack(void *context, oggpack_buffer *opb,static_codebook *s){
ogg_int32_t i,j;
int err = -1;
FMOD_memset(s,0,sizeof(*s));
s->allocedp=1;
/* make sure alignment is correct */
if(FMOD_oggpack_read(opb,24)!=0x564342)goto _eofout;
/* first the basic parameters */
s->dim=FMOD_oggpack_read(opb,16);
s->entries=FMOD_oggpack_read(opb,24);
if(s->entries==-1)goto _eofout;
if(_FMOD_ilog(s->dim)+_FMOD_ilog(s->entries)>24)goto _eofout;
/* codeword ordering.... length ordered or unordered? */
switch((int)FMOD_oggpack_read(opb,1)){
case 0:
/* unordered */
s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
if (!s->lengthlist)
{
err = OV_EMEMORY;
goto _errout;
}
/* allocated but unused entries? */
if(FMOD_oggpack_read(opb,1)){
/* yes, unused entries */
for(i=0;i<s->entries;i++){
if(FMOD_oggpack_read(opb,1)){
ogg_int32_t num=FMOD_oggpack_read(opb,5);
if(num==-1)goto _eofout;
s->lengthlist[i]=num+1;
}else
s->lengthlist[i]=0;
}
}else{
/* all entries used; no tagging */
for(i=0;i<s->entries;i++){
ogg_int32_t num=FMOD_oggpack_read(opb,5);
if(num==-1)goto _eofout;
s->lengthlist[i]=num+1;
}
}
break;
case 1:
/* ordered */
{
ogg_int32_t length=FMOD_oggpack_read(opb,5)+1;
s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
if (!s->lengthlist)
{
err = OV_EMEMORY;
goto _errout;
}
for(i=0;i<s->entries;){
ogg_int32_t num=FMOD_oggpack_read(opb,_FMOD_ilog(s->entries-i));
if(num==-1)goto _eofout;
for(j=0;j<num && i<s->entries;j++,i++)
s->lengthlist[i]=length;
length++;
}
}
break;
default:
/* EOF */
return(-1);
}
/* Do we have a mapping to unpack? */
switch((s->maptype=FMOD_oggpack_read(opb,4))){
case 0:
/* no mapping */
break;
case 1: case 2:
/* implicitly populated value mapping */
/* explicitly populated value mapping */
s->q_min=FMOD_oggpack_read(opb,32);
s->q_delta=FMOD_oggpack_read(opb,32);
s->q_quant=FMOD_oggpack_read(opb,4)+1;
s->q_sequencep=FMOD_oggpack_read(opb,1);
if(s->q_sequencep==-1)goto _eofout;
{
int quantvals=0;
switch(s->maptype){
case 1:
quantvals=(s->dim==0?0:_FMOD_book_maptype1_quantvals(s));
break;
case 2:
quantvals=s->entries*s->dim;
break;
}
/* quantized values */
s->quantlist=_ogg_malloc(sizeof(*s->quantlist)*quantvals);
if (!s->quantlist)
{
err = OV_EMEMORY;
goto _errout;
}
for(i=0;i<quantvals;i++)
s->quantlist[i]=FMOD_oggpack_read(opb,s->q_quant);
if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout;
}
break;
default:
goto _errout;
}
/* all set */
return(0);
_errout:
_eofout:
FMOD_vorbis_staticbook_clear(context, s);
return err;
}
/* returns the number of bits ************************************************/
#if 0
int FMOD_vorbis_book_encode(codebook *book, int a, oggpack_buffer *b){
if(a<0 || a>=book->c->entries)return(0);
FMOD_oggpack_write(b,book->codelist[a],book->c->lengthlist[a]);
return(book->c->lengthlist[a]);
}
/* One the encode side, our vector writers are each designed for a
specific purpose, and the encoder is not flexible without modification:
The LSP vector coder uses a single stage nearest-match with no
interleave, so no step and no error return. This is specced by floor0
and doesn't change.
Residue0 encoding interleaves, uses multiple stages, and each stage
peels of a specific amount of resolution from a lattice (thus we want
to match by threshold, not nearest match). Residue doesn't *have* to
be encoded that way, but to change it, one will need to add more
infrastructure on the encode side (decode side is specced and simpler) */
/* floor0 LSP (single stage, non interleaved, nearest match) */
/* returns entry number and *modifies a* to the quantization value *****/
int vorbis_book_errorv(codebook *book,float *a){
int dim=book->dim,k;
int best=_FMOD_best(book,a,1);
for(k=0;k<dim;k++)
a[k]=(book->valuelist+best*dim)[k];
return(best);
}
/* returns the number of bits and *modifies a* to the quantization value *****/
int FMOD_vorbis_book_encodev(codebook *book,int best,float *a,oggpack_buffer *b){
int k,dim=book->dim;
for(k=0;k<dim;k++)
a[k]=(book->valuelist+best*dim)[k];
return(FMOD_vorbis_book_encode(book,best,b));
}
#endif
/* the 'eliminate the decode tree' optimization actually requires the
codewords to be MSb first, not LSb. This is an annoying inelegancy
(and one of the first places where carefully thought out design
turned out to be wrong; Vorbis II and future Ogg codecs should go
to an MSb bitpacker), but not actually the huge hit it appears to
be. The first-stage decode table catches most words so that
bitreverse is not in the main execution path. */
static ogg_uint32_t bitreverse(ogg_uint32_t x){
x= ((x>>16)&0x0000ffff) | ((x<<16)&0xffff0000);
x= ((x>> 8)&0x00ff00ff) | ((x<< 8)&0xff00ff00);
x= ((x>> 4)&0x0f0f0f0f) | ((x<< 4)&0xf0f0f0f0);
x= ((x>> 2)&0x33333333) | ((x<< 2)&0xcccccccc);
return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa);
}
STIN ogg_int32_t decode_packed_entry_number(codebook *book, oggpack_buffer *b){
int read=book->dec_maxlength;
ogg_int32_t lo,hi;
ogg_int32_t lok = FMOD_oggpack_look(b,book->dec_firsttablen);
if (lok >= 0) {
ogg_int32_t entry = book->dec_firsttable[lok];
if(entry&0x80000000){
lo=(entry>>15)&0x7fff;
hi=book->used_entries-(entry&0x7fff);
}else{
FMOD_oggpack_adv(b, book->dec_codelengths[entry-1]);
return(entry-1);
}
}else{
lo=0;
hi=book->used_entries;
}
lok = FMOD_oggpack_look(b, read);
while(lok<0 && read>1)
lok = FMOD_oggpack_look(b, --read);
if(lok<0)return -1;
/* bisect search for the codeword in the ordered list */
{
ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok);
while(hi-lo>1){
ogg_int32_t p=(hi-lo)>>1;
ogg_int32_t test=book->codelist[lo+p]>testword;
lo+=p&(test-1);
hi-=p&(-test);
}
if(book->dec_codelengths[lo]<=read){
FMOD_oggpack_adv(b, book->dec_codelengths[lo]);
return(lo);
}
}
FMOD_oggpack_adv(b, read);
return(-1);
}
/* Decode side is specced and easier, because we don't need to find
matches using different criteria; we simply read and map. There are
two things we need to do 'depending':
We may need to support interleave. We don't really, but it's
convenient to do it here rather than rebuild the vector later.
Cascades may be additive or multiplicitive; this is not inherent in
the codebook, but set in the code using the codebook. Like
interleaving, it's easiest to do it here.
addmul==0 -> declarative (set the value)
addmul==1 -> additive
addmul==2 -> multiplicitive */
/* returns the [original, not compacted] entry number or -1 on eof *********/
ogg_int32_t FMOD_vorbis_book_decode(codebook *book, oggpack_buffer *b){
if(book->used_entries>0){
ogg_int32_t packed_entry=decode_packed_entry_number(book,b);
if(packed_entry>=0)
return(book->dec_index[packed_entry]);
}
/* if there's no dec_index, the codebook unpacking isn't collapsed */
return(-1);
}
/* returns 0 on OK or -1 on eof *************************************/
ogg_int32_t FMOD_vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){
if(book->used_entries>0){
int step=n/book->dim;
ogg_int32_t *entry = alloca(sizeof(*entry)*step);
float **t = alloca(sizeof(*t)*step);
int i,j,o;
for (i = 0; i < step; i++) {
entry[i]=decode_packed_entry_number(book,b);
if(entry[i]==-1)return(-1);
t[i] = book->valuelist+entry[i]*book->dim;
}
for(i=0,o=0;i<book->dim;i++,o+=step)
for (j=0;j<step;j++)
a[o+j]+=t[j][i];
}
return(0);
}
ogg_int32_t FMOD_vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){
if(book->used_entries>0){
int i,j,entry;
float *t;
if(book->dim>8){
for(i=0;i<n;){
entry = decode_packed_entry_number(book,b);
if(entry==-1)return(-1);
t = book->valuelist+entry*book->dim;
for (j=0;j<book->dim;)
a[i++]+=t[j++];
}
}else{
for(i=0;i<n;){
entry = decode_packed_entry_number(book,b);
if(entry==-1)return(-1);
t = book->valuelist+entry*book->dim;
j=0;
switch((int)book->dim){
case 8:
a[i++]+=t[j++];
case 7:
a[i++]+=t[j++];
case 6:
a[i++]+=t[j++];
case 5:
a[i++]+=t[j++];
case 4:
a[i++]+=t[j++];
case 3:
a[i++]+=t[j++];
case 2:
a[i++]+=t[j++];
case 1:
a[i++]+=t[j++];
case 0:
break;
}
}
}
}
return(0);
}
ogg_int32_t FMOD_vorbis_book_decodev_set(codebook *book,float *a,oggpack_buffer *b,int n){
if(book->used_entries>0){
int i,j,entry;
float *t;
for(i=0;i<n;){
entry = decode_packed_entry_number(book,b);
if(entry==-1)return(-1);
t = book->valuelist+entry*book->dim;
for (j=0;j<book->dim;)
a[i++]=t[j++];
}
}else{
int i,j;
for(i=0;i<n;){
for (j=0;j<book->dim;)
a[i++]=0.f;
}
}
return(0);
}
ogg_int32_t FMOD_vorbis_book_decodevv_add(codebook *book,float **a,ogg_int32_t offset,int ch,
oggpack_buffer *b,int n){
ogg_int32_t i,j,entry;
int chptr=0;
if(book->used_entries>0){
for(i=offset/ch;i<(offset+n)/ch;){
entry = decode_packed_entry_number(book,b);
if(entry==-1)return(-1);
{
const float *t = book->valuelist+entry*book->dim;
for (j=0;j<book->dim;j++){
a[chptr++][i]+=t[j];
if(chptr==ch){
chptr=0;
i++;
}
}
}
}
}
return(0);
}
#ifdef _V_SELFTEST
/* Simple enough; pack a few candidate codebooks, unpack them. Code a
number of vectors through (keeping track of the quantized values),
and decode using the unpacked book. quantized version of in should
exactly equal out */
#include <stdio.h>
#include "vorbis/book/lsp20_0.vqh"
#include "vorbis/book/res0a_13.vqh"
#define TESTSIZE 40
float test1[TESTSIZE]={
0.105939f,
0.215373f,
0.429117f,
0.587974f,
0.181173f,
0.296583f,
0.515707f,
0.715261f,
0.162327f,
0.263834f,
0.342876f,
0.406025f,
0.103571f,
0.223561f,
0.368513f,
0.540313f,
0.136672f,
0.395882f,
0.587183f,
0.652476f,
0.114338f,
0.417300f,
0.525486f,
0.698679f,
0.147492f,
0.324481f,
0.643089f,
0.757582f,
0.139556f,
0.215795f,
0.324559f,
0.399387f,
0.120236f,
0.267420f,
0.446940f,
0.608760f,
0.115587f,
0.287234f,
0.571081f,
0.708603f,
};
float test3[TESTSIZE]={
0,1,-2,3,4,-5,6,7,8,9,
8,-2,7,-1,4,6,8,3,1,-9,
10,11,12,13,14,15,26,17,18,19,
30,-25,-30,-1,-5,-32,4,3,-2,0};
static_codebook *testlist[]={&_vq_book_lsp20_0,
&_vq_book_res0a_13,NULL};
float *testvec[]={test1,test3};
int main(){
oggpack_buffer write;
oggpack_buffer read;
ogg_int32_t ptr=0,i;
FMOD_oggpack_writeinit(context, &write);
fprintf(stderr,"Testing codebook abstraction...:\n");
while(testlist[ptr]){
codebook c;
static_codebook s;
float *qv=alloca(sizeof(*qv)*TESTSIZE);
float *iv=alloca(sizeof(*iv)*TESTSIZE);
FMOD_memcpy(qv,testvec[ptr],sizeof(*qv)*TESTSIZE);
FMOD_memset(iv,0,sizeof(*iv)*TESTSIZE);
fprintf(stderr,"\tpacking/coding %ld... ",ptr);
/* pack the codebook, write the testvector */
oggpack_reset(&write);
vorbis_book_init_encode(&c,testlist[ptr]); /* get it into memory
we can write */
vorbis_staticbook_pack(testlist[ptr],&write);
fprintf(stderr,"Codebook size %ld bytes... ",oggpack_bytes(&write));
for(i=0;i<TESTSIZE;i+=c.dim){
int best=_FMOD_best(&c,qv+i,1);
FMOD_vorbis_book_encodev(&c,best,qv+i,&write);
}
vorbis_book_clear(&c);
fprintf(stderr,"OK.\n");
fprintf(stderr,"\tunpacking/decoding %ld... ",ptr);
/* transfer the write data to a read buffer and unpack/read */
FMOD_oggpack_readinit(&read,oggpack_get_buffer(&write),oggpack_bytes(&write));
if(FMOD_vorbis_staticbook_unpack(&read,&s)){
fprintf(stderr,"Error unpacking codebook.\n");
exit(1);
}
if(vorbis_book_init_decode(&c,&s)){
fprintf(stderr,"Error initializing codebook.\n");
exit(1);
}
for(i=0;i<TESTSIZE;i+=c.dim)
if(vorbis_book_decodev_set(&c,iv+i,&read,c.dim)==-1){
fprintf(stderr,"Error reading codebook test data (EOP).\n");
exit(1);
}
for(i=0;i<TESTSIZE;i++)
if(fabs(qv[i]-iv[i])>.000001){
fprintf(stderr,"read (%g) != written (%g) at position (%ld)\n",
iv[i],qv[i],i);
exit(1);
}
fprintf(stderr,"OK\n");
ptr++;
}
/* The above is the trivial stuff; now try unquantizing a log scale codebook */
exit(0);
}
#endif

View file

@ -0,0 +1,160 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: basic shared codebook operations
last mod: $Id: codebook.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
#ifndef _V_CODEBOOK_H_
#define _V_CODEBOOK_H_
#include <ogg/ogg.h>
/* This structure encapsulates huffman and VQ style encoding books; it
doesn't do anything specific to either.
valuelist/quantlist are nonNULL (and q_* significant) only if
there's entry->value mapping to be done.
If encode-side mapping must be done (and thus the entry needs to be
hunted), the auxiliary encode pointer will point to a decision
tree. This is true of both VQ and huffman, but is mostly useful
with VQ.
*/
typedef struct static_codebook{
ogg_int32_t dim; /* codebook dimensions (elements per vector) */
ogg_int32_t entries; /* codebook entries */
ogg_int32_t *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. */
ogg_int32_t q_min; /* packed 32 bit float; quant value 0 maps to minval */
ogg_int32_t q_delta; /* packed 32 bit float; val 1 - val 0 == delta */
int q_quant; /* bits: 0 < quant <= 16 */
int q_sequencep; /* bitflag */
ogg_int32_t *quantlist; /* map == 1: (int)(entries^(1/dim)) element column map
map == 2: list of dim*entries quantized entry vals
*/
/* encode helpers ********************************************************/
// struct encode_aux_nearestmatch *nearest_tree;
// struct encode_aux_threshmatch *thresh_tree;
// struct encode_aux_pigeonhole *pigeon_tree;
int allocedp;
} static_codebook;
/* this structures an arbitrary trained book to quickly find the
nearest cell match */
//typedef struct encode_aux_nearestmatch{
// /* pre-calculated partitioning tree */
// ogg_int32_t *ptr0;
// ogg_int32_t *ptr1;
//
// ogg_int32_t *p; /* decision points (each is an entry) */
// ogg_int32_t *q; /* decision points (each is an entry) */
// ogg_int32_t aux; /* number of tree entries */
// ogg_int32_t alloc;
//} encode_aux_nearestmatch;
/* assumes a maptype of 1; encode side only, so that's OK */
//typedef struct encode_aux_threshmatch{
// float *quantthresh;
// ogg_int32_t *quantmap;
// int quantvals;
// int threshvals;
//} encode_aux_threshmatch;
//typedef struct encode_aux_pigeonhole{
// float min;
// float del;
//
// int mapentries;
// int quantvals;
// ogg_int32_t *pigeonmap;
//
// ogg_int32_t fittotal;
// ogg_int32_t *fitlist;
// ogg_int32_t *fitmap;
// ogg_int32_t *fitlength;
//} encode_aux_pigeonhole;
typedef struct codebook{
ogg_int32_t dim; /* codebook dimensions (elements per vector) */
ogg_int32_t entries; /* codebook entries */
ogg_int32_t used_entries; /* populated codebook entries */
const static_codebook *c;
/* for encode, the below are entry-ordered, fully populated */
/* for decode, the below are ordered by bitreversed codeword and only
used entries are populated */
float *valuelist; /* list of dim*entries actual entry values */
ogg_uint32_t *codelist; /* list of bitstream codewords for each entry */
int *dec_index; /* only used if sparseness collapsed */
char *dec_codelengths;
ogg_uint32_t *dec_firsttable;
int dec_firsttablen;
int dec_maxlength;
} codebook;
extern void FMOD_vorbis_staticbook_clear(void *context, static_codebook *b);
extern void FMOD_vorbis_staticbook_destroy(void *context, static_codebook *b);
//extern int FMOD_vorbis_book_init_encode(void *context, codebook *dest,const static_codebook *source);
extern int FMOD_vorbis_book_init_decode(void *context, codebook *dest,const static_codebook *source);
extern void FMOD_vorbis_book_clear(void *context, codebook *b);
extern float *_FMOD_book_unquantize(void *context, const static_codebook *b,int n,int *map);
extern float *_FMOD_book_logdist(const static_codebook *b,float *vals);
extern float _FMOD_float32_unpack(ogg_int32_t val);
extern ogg_int32_t _FMOD_float32_pack(float val);
extern int _FMOD_best(codebook *book, float *a, int step);
extern int _FMOD_ilog(unsigned int v);
extern ogg_int32_t _FMOD_book_maptype1_quantvals(const static_codebook *b);
extern int FMOD_vorbis_book_besterror(codebook *book,float *a,int step,int addmul);
extern ogg_int32_t FMOD_vorbis_book_codeword(codebook *book,int entry);
extern ogg_int32_t FMOD_vorbis_book_codelen(codebook *book,int entry);
extern int FMOD_vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *b);
extern int FMOD_vorbis_staticbook_unpack(void *context, oggpack_buffer *b,static_codebook *c);
//extern int FMOD_vorbis_book_encode(codebook *book, int a, oggpack_buffer *b);
extern int FMOD_vorbis_book_errorv(codebook *book, float *a);
//extern int FMOD_vorbis_book_encodev(codebook *book, int best,float *a,
// oggpack_buffer *b);
extern ogg_int32_t FMOD_vorbis_book_decode(codebook *book, oggpack_buffer *b);
extern ogg_int32_t FMOD_vorbis_book_decodevs_add(codebook *book, float *a,
oggpack_buffer *b,int n);
extern ogg_int32_t FMOD_vorbis_book_decodev_set(codebook *book, float *a,
oggpack_buffer *b,int n);
extern ogg_int32_t FMOD_vorbis_book_decodev_add(codebook *book, float *a,
oggpack_buffer *b,int n);
extern ogg_int32_t FMOD_vorbis_book_decodevv_add(codebook *book, float **a,
ogg_int32_t off,int ch,
oggpack_buffer *b,int n);
#endif

View file

@ -0,0 +1,166 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: libvorbis codec headers
last mod: $Id: codec_internal.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
#ifndef _V_CODECI_H_
#define _V_CODECI_H_
//#include "envelope.h"
#include "codebook.h"
#define BLOCKTYPE_IMPULSE 0
#define BLOCKTYPE_PADDING 1
#define BLOCKTYPE_TRANSITION 0
#define BLOCKTYPE_LONG 1
#define PACKETBLOBS 15
typedef struct vorbis_block_internal{
float **pcmdelay; /* this is a pointer into local storage */
float ampmax;
int blocktype;
oggpack_buffer *packetblob[PACKETBLOBS]; /* initialized, must be freed;
blob [PACKETBLOBS/2] points to
the oggpack_buffer in the
main vorbis_block */
} vorbis_block_internal;
typedef void vorbis_look_floor;
typedef void vorbis_look_residue;
typedef void vorbis_look_transform;
/* mode ************************************************************/
typedef struct {
int blockflag;
int windowtype;
int transformtype;
int mapping;
} vorbis_info_mode;
typedef void vorbis_info_floor;
typedef void vorbis_info_residue;
typedef void vorbis_info_mapping;
#include "psy.h"
//#include "bitrate.h"
typedef struct private_state {
/* local lookup storage */
//envelope_lookup *ve; /* envelope lookup */
int window[2];
vorbis_look_transform **transform[2]; /* block, type */
// drft_lookup fft_look[2];
int modebits;
vorbis_look_floor **flr;
vorbis_look_residue **residue;
// vorbis_look_psy *psy;
// vorbis_look_psy_global *psy_g_look;
/* 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 */
// unsigned char *header;
// unsigned char *header1;
// unsigned char *header2;
// bitrate_manager_state bms;
ogg_int64_t sample_count;
} private_state;
/* codec_setup_info contains all the setup information specific to the
specific compression/decompression mode in progress (eg,
psychoacoustic settings, channel setup, options, codebook
etc).
*********************************************************************/
#include "highlevel.h"
typedef struct codec_setup_info {
/* Vorbis supports only short and long blocks, but allows the
encoder to choose the sizes */
ogg_int32_t blocksizes[2];
/* modes are the primary means of supporting on-the-fly different
blocksizes, different channel mappings (LR or M/A),
different residue backends, etc. Each mode consists of a
blocksize flag and a mapping (along with the mapping setup */
int modes;
int maps;
int floors;
int residues;
int books;
// int psys; /* encode only */
vorbis_info_mode *mode_param[64];
int map_type[64];
vorbis_info_mapping *map_param[64];
int floor_type[64];
vorbis_info_floor *floor_param[64];
int residue_type[64];
vorbis_info_residue *residue_param[64];
static_codebook *book_param[256];
codebook *fullbooks;
// vorbis_info_psy *psy_param[4]; /* encode only */
// vorbis_info_psy_global psy_g_param;
// bitrate_manager_info bi;
// highlevel_encode_setup hi; /* used only by vorbisenc.c. It's a
// highly redundant structure, but
// improves clarity of program flow. */
int halfrate_flag; /* painless downsample for decode */
} codec_setup_info;
//extern vorbis_look_psy_global *_vp_global_look(void *context, vorbis_info *vi);
//extern void _vp_global_free(void *context, vorbis_look_psy_global *look);
typedef struct {
// int sorted_index[VIF_POSIT+2];
int forward_index[VIF_POSIT+2];
int reverse_index[VIF_POSIT+2];
int hineighbor[VIF_POSIT];
int loneighbor[VIF_POSIT];
int posts;
int n;
int quant_q;
vorbis_info_floor1 *vi;
ogg_int32_t phrasebits;
ogg_int32_t postbits;
ogg_int32_t frames;
} vorbis_look_floor1;
//extern int *floor1_fit(void *context, vorbis_block *vb,vorbis_look_floor1 *look,
// const float *logmdct, /* in */
// const float *logmask);
//extern int *floor1_interpolate_fit(void *context, vorbis_block *vb,vorbis_look_floor1 *look,
// int *A,int *B,
// int del);
//extern int floor1_encode(oggpack_buffer *opb,vorbis_block *vb,
// vorbis_look_floor1 *look,
// int *post,int *ilogmask);
#endif

1106
lib/ogg_vorbis/vorbis/lib/floor1.c Executable file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,57 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: highlevel encoder setup struct seperated out for vorbisenc clarity
last mod: $Id: highlevel.h 13293 2007-07-24 00:09:47Z xiphmont $
********************************************************************/
typedef struct highlevel_byblocktype {
float tone_mask_setting;
float tone_peaklimit_setting;
float noise_bias_setting;
float noise_compand_setting;
} highlevel_byblocktype;
typedef struct highlevel_encode_setup {
void *setup;
int set_in_stone;
float base_setting;
float long_setting;
float short_setting;
float impulse_noisetune;
int managed;
ogg_int32_t bitrate_min;
ogg_int32_t bitrate_av;
float bitrate_av_damp;
ogg_int32_t bitrate_max;
ogg_int32_t bitrate_reservoir;
float bitrate_reservoir_bias;
int impulse_block_p;
int noise_normalize_p;
float stereo_point_setting;
float lowpass_kHz;
float ath_floating_dB;
float ath_absolute_dB;
float amplitude_track_dBpersec;
float trigger_setting;
highlevel_byblocktype block[4]; /* padding, impulse, transition, ogg_int32_t */
} highlevel_encode_setup;

716
lib/ogg_vorbis/vorbis/lib/info.c Executable file
View file

@ -0,0 +1,716 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: maintain the info structure, info <-> header packets
last mod: $Id: info.c 16243 2009-07-10 02:49:31Z xiphmont $
********************************************************************/
/* general handling of the header and the vorbis_info structure (and
substructures) */
#include <stdlib.h>
#include <string.h>
//#include <ctype.h>
#include <ogg/ogg.h>
#include "vorbis/codec.h"
#include "codec_internal.h"
#include "codebook.h"
#include "registry.h"
#include "window.h"
#include "psy.h"
#include "misc.h"
#include "os.h"
#define GENERAL_VENDOR_STRING "Xiph.Org libVorbis 1.2.3"
#define ENCODE_VENDOR_STRING "Xiph.Org libVorbis I 20090709"
/* helpers */
static int ilog2(unsigned int v){
int ret=0;
if(v)--v;
while(v){
ret++;
v>>=1;
}
return(ret);
}
char FMOD_ogg_toupper(char in)
{
if (in >= 'a' && in <= 'z')
{
in += 'A' - 'a';
}
return in;
}
#if 0
static void _v_writestring(oggpack_buffer *o,const char *s, int bytes){
while(bytes--){
FMOD_oggpack_write(o,*s++,8);
}
}
#endif
static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
while(bytes--){
*buf++=(char)FMOD_oggpack_read(o,8);
}
}
void FMOD_vorbis_comment_init(vorbis_comment *vc){
FMOD_memset(vc,0,sizeof(*vc));
}
//void FMOD_vorbis_comment_add(void *context, vorbis_comment *vc,const char *comment){
// vc->user_comments=_ogg_realloc(vc->user_comments,
// (vc->comments+2)*sizeof(*vc->user_comments));
// vc->comment_lengths=_ogg_realloc(vc->comment_lengths,
// (vc->comments+2)*sizeof(*vc->comment_lengths));
// vc->comment_lengths[vc->comments]=ogg_strlen(comment);
// vc->user_comments[vc->comments]=_ogg_malloc(vc->comment_lengths[vc->comments]+1);
// ogg_strcpy(vc->user_comments[vc->comments], comment);
// vc->comments++;
// vc->user_comments[vc->comments]=NULL;
//}
//
//void vorbis_comment_add_tag(void *context, vorbis_comment *vc, const char *tag, const char *contents){
// char *comment=alloca(ogg_strlen(tag)+ogg_strlen(contents)+2); /* +2 for = and \0 */
// ogg_strcpy(comment, tag);
// ogg_strcat(comment, "=");
// ogg_strcat(comment, contents);
// FMOD_vorbis_comment_add(context, vc, comment);
//}
/* 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(const char *s1, const char *s2, int n){
int c=0;
while(c < n){
if(FMOD_ogg_toupper(s1[c]) != FMOD_ogg_toupper(s2[c]))
return !0;
c++;
}
return 0;
}
//char *FMOD_vorbis_comment_query(vorbis_comment *vc, const char *tag, int count){
// ogg_int32_t i;
// int found = 0;
// int taglen = ogg_strlen(tag)+1; /* +1 for the = we append */
// char *fulltag = alloca(taglen+ 1);
//
// ogg_strcpy(fulltag, tag);
// ogg_strcat(fulltag, "=");
//
// for(i=0;i<vc->comments;i++){
// if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
// if(count == found)
// /* We return a pointer to the data, not a copy */
// return vc->user_comments[i] + taglen;
// else
// found++;
// }
// }
// return NULL; /* didn't find anything */
//}
//
//int FMOD_vorbis_comment_query_count(vorbis_comment *vc, const char *tag){
// int i,count=0;
// int taglen = ogg_strlen(tag)+1; /* +1 for the = we append */
// char *fulltag = alloca(taglen+1);
// ogg_strcpy(fulltag,tag);
// ogg_strcat(fulltag, "=");
//
// for(i=0;i<vc->comments;i++){
// if(!tagcompare(vc->user_comments[i], fulltag, taglen))
// count++;
// }
//
// return count;
//}
void FMOD_vorbis_comment_clear(void *context, vorbis_comment *vc){
if(vc){
ogg_int32_t i;
if(vc->user_comments){
for(i=0;i<vc->comments;i++)
if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
_ogg_free(vc->user_comments);
}
if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
if(vc->vendor)_ogg_free(vc->vendor);
FMOD_memset(vc,0,sizeof(*vc));
}
}
/* blocksize 0 is guaranteed to be short, 1 is guaranteed to be long.
They may be equal, but short will never ge greater than long */
int FMOD_vorbis_info_blocksize(vorbis_info *vi,int zo){
codec_setup_info *ci = vi->codec_setup;
return ci ? ci->blocksizes[zo] : -1;
}
/* used by synthesis, which has a full, alloced vi */
int FMOD_vorbis_info_init(void *context, vorbis_info *vi){
FMOD_memset(vi,0,sizeof(*vi));
vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info));
if(!vi->codec_setup)
{
return(OV_EMEMORY);
}
return 0;
}
void FMOD_vorbis_info_clear(void *context, vorbis_info *vi){
codec_setup_info *ci=vi->codec_setup;
int i;
if(ci){
for(i=0;i<ci->modes;i++)
if(ci->mode_param[i])_ogg_free(ci->mode_param[i]);
for(i=0;i<ci->maps;i++) /* unpack does the range checking */
if(ci->map_param[i]) /* this may be cleaning up an aborted
unpack, in which case the below type
cannot be trusted */
_FMOD_mapping_P[ci->map_type[i]]->free_info(context, ci->map_param[i]);
for(i=0;i<ci->floors;i++) /* unpack does the range checking */
if(ci->floor_param[i]) /* this may be cleaning up an aborted
unpack, in which case the below type
cannot be trusted */
_FMOD_floor_P[ci->floor_type[i]]->free_info(context, ci->floor_param[i]);
for(i=0;i<ci->residues;i++) /* unpack does the range checking */
if(ci->residue_param[i]) /* this may be cleaning up an aborted
unpack, in which case the below type
cannot be trusted */
_FMOD_residue_P[ci->residue_type[i]]->free_info(context, ci->residue_param[i]);
for(i=0;i<ci->books;i++){
if(ci->book_param[i]){
/* knows if the book was not alloced */
FMOD_vorbis_staticbook_destroy(context, ci->book_param[i]);
}
if(ci->fullbooks)
FMOD_vorbis_book_clear(context, ci->fullbooks+i);
}
if(ci->fullbooks)
_ogg_free(ci->fullbooks);
// for(i=0;i<ci->psys;i++)
// _vi_psy_free(context, ci->psy_param[i]);
_ogg_free(ci);
}
FMOD_memset(vi,0,sizeof(*vi));
}
/* Header packing/unpacking ********************************************/
static int _FMOD_vorbis_unpack_info(void *context, vorbis_info *vi,oggpack_buffer *opb){
codec_setup_info *ci=vi->codec_setup;
if(!ci)return(OV_EFAULT);
vi->version=FMOD_oggpack_read(opb,32);
if(vi->version!=0)return(OV_EVERSION);
vi->channels=FMOD_oggpack_read(opb,8);
vi->rate=FMOD_oggpack_read(opb,32);
vi->bitrate_upper=FMOD_oggpack_read(opb,32);
vi->bitrate_nominal=FMOD_oggpack_read(opb,32);
vi->bitrate_lower=FMOD_oggpack_read(opb,32);
ci->blocksizes[0]=1<<FMOD_oggpack_read(opb,4);
ci->blocksizes[1]=1<<FMOD_oggpack_read(opb,4);
if(vi->rate<1)goto err_out;
if(vi->channels<1)goto err_out;
if(ci->blocksizes[0]<64)goto err_out;
if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
if(ci->blocksizes[1]>8192)goto err_out;
if(FMOD_oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
return(0);
err_out:
FMOD_vorbis_info_clear(context, vi);
return(OV_EBADHEADER);
}
static int _vorbis_unpack_comment(void *context, vorbis_comment *vc,oggpack_buffer *opb){
int i,err = OV_EBADHEADER;
int vendorlen=FMOD_oggpack_read(opb,32);
if(vendorlen<0)goto err_out;
if(vendorlen>opb->storage-8)goto err_out;
vc->vendor=_ogg_calloc(vendorlen+1,1);
if (!vc->vendor)
{
err = OV_EMEMORY;
goto err_out;
}
_v_readstring(opb,vc->vendor,vendorlen);
i=FMOD_oggpack_read(opb,32);
if(i<0)goto err_out;
if(i>((opb->storage-FMOD_oggpack_bytes(opb))>>2))goto err_out;
vc->comments=i;
vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
if (!vc->user_comments)
{
err = OV_EMEMORY;
goto err_out;
}
vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
if (!vc->comment_lengths)
{
err = OV_EMEMORY;
goto err_out;
}
for(i=0;i<vc->comments;i++){
int len=FMOD_oggpack_read(opb,32);
if(len<0)goto err_out;
if(len>opb->storage-FMOD_oggpack_bytes(opb))goto err_out;
vc->comment_lengths[i]=len;
vc->user_comments[i]=_ogg_calloc(len+1,1);
if (!vc->user_comments[i])
{
err = OV_EMEMORY;
goto err_out;
}
_v_readstring(opb,vc->user_comments[i],len);
}
if(FMOD_oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
return(0);
err_out:
FMOD_vorbis_comment_clear(context, vc);
return err;
}
/* all of the real encoding details are here. The modes, books,
everything */
static int _vorbis_unpack_books(void *context, vorbis_info *vi,oggpack_buffer *opb){
codec_setup_info *ci=vi->codec_setup;
int i,err = OV_EBADHEADER;
if(!ci)return(OV_EFAULT);
/* codebooks */
ci->books=FMOD_oggpack_read(opb,8)+1;
if(ci->books<=0)goto err_out;
for(i=0;i<ci->books;i++){
int ret;
ci->book_param[i]=_ogg_calloc(1,sizeof(*ci->book_param[i]));
if (!ci->book_param[i])
{
err = OV_EMEMORY;
goto err_out;
}
ret = FMOD_vorbis_staticbook_unpack(context, opb,ci->book_param[i]);
if(ret)
{
err = ret;
goto err_out;
}
}
/* time backend settings; hooks are unused */
{
int times=FMOD_oggpack_read(opb,6)+1;
if(times<=0)goto err_out;
for(i=0;i<times;i++){
int test=FMOD_oggpack_read(opb,16);
if(test<0 || test>=VI_TIMEB)goto err_out;
}
}
/* floor backend settings */
ci->floors=FMOD_oggpack_read(opb,6)+1;
if(ci->floors<=0)goto err_out;
for(i=0;i<ci->floors;i++){
ci->floor_type[i]=FMOD_oggpack_read(opb,16);
if (ci->floor_type[i] == 0)
{
err = OV_EVERSION;
goto err_out; /* FMOD ADDED - NOT SUPPORTING FLOOR 0! */
}
if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
ci->floor_param[i]=_FMOD_floor_P[ci->floor_type[i]]->unpack(context, vi,opb);
if(!ci->floor_param[i])goto err_out;
}
/* residue backend settings */
ci->residues=FMOD_oggpack_read(opb,6)+1;
if(ci->residues<=0)goto err_out;
for(i=0;i<ci->residues;i++){
ci->residue_type[i]=FMOD_oggpack_read(opb,16);
if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
ci->residue_param[i]=_FMOD_residue_P[ci->residue_type[i]]->unpack(context, vi,opb);
if(!ci->residue_param[i])goto err_out;
}
/* map backend settings */
ci->maps=FMOD_oggpack_read(opb,6)+1;
if(ci->maps<=0)goto err_out;
for(i=0;i<ci->maps;i++){
ci->map_type[i]=FMOD_oggpack_read(opb,16);
if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
ci->map_param[i]=_FMOD_mapping_P[ci->map_type[i]]->unpack(context, vi,opb);
if(!ci->map_param[i])goto err_out;
}
/* mode settings */
ci->modes=FMOD_oggpack_read(opb,6)+1;
if(ci->modes<=0)goto err_out;
for(i=0;i<ci->modes;i++){
ci->mode_param[i]=_ogg_calloc(1,sizeof(*ci->mode_param[i]));
if (!ci->mode_param[i])
{
err = OV_EMEMORY;
goto err_out;
}
ci->mode_param[i]->blockflag=FMOD_oggpack_read(opb,1);
ci->mode_param[i]->windowtype=FMOD_oggpack_read(opb,16);
ci->mode_param[i]->transformtype=FMOD_oggpack_read(opb,16);
ci->mode_param[i]->mapping=FMOD_oggpack_read(opb,8);
if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
if(ci->mode_param[i]->mapping>=ci->maps)goto err_out;
if(ci->mode_param[i]->mapping<0)goto err_out;
}
if(FMOD_oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
return(0);
err_out:
FMOD_vorbis_info_clear(context, vi);
return err;
}
/* Is this packet a vorbis ID header? */
int FMOD_vorbis_synthesis_idheader(ogg_packet *op){
oggpack_buffer opb;
char buffer[6];
if(op){
FMOD_oggpack_readinit(&opb,op->packet,op->bytes);
if(!op->b_o_s)
return(0); /* Not the initial packet */
if(FMOD_oggpack_read(&opb,8) != 1)
return 0; /* not an ID header */
FMOD_memset(buffer,0,6);
_v_readstring(&opb,buffer,6);
if(memcmp(buffer,"vorbis",6))
return 0; /* not vorbis */
return 1;
}
return 0;
}
/* 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. */
int FMOD_vorbis_synthesis_headerin(void *context, vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){
oggpack_buffer opb;
if(op){
FMOD_oggpack_readinit(&opb,op->packet,op->bytes);
/* Which of the three types of header is this? */
/* Also verify header-ness, vorbis */
{
char buffer[6];
int packtype=FMOD_oggpack_read(&opb,8);
FMOD_memset(buffer,0,6);
_v_readstring(&opb,buffer,6);
if(memcmp(buffer,"vorbis",6)){
/* not a vorbis header */
return(OV_ENOTVORBIS);
}
switch(packtype){
case 0x01: /* least significant *bit* is read first */
if(!op->b_o_s){
/* Not the initial packet */
return(OV_EBADHEADER);
}
if(vi->rate!=0){
/* previously initialized info header */
return(OV_EBADHEADER);
}
return(_FMOD_vorbis_unpack_info(context, vi,&opb));
case 0x03: /* least significant *bit* is read first */
if(vi->rate==0){
/* um... we didn't get the initial header */
return(OV_EBADHEADER);
}
return(_vorbis_unpack_comment(context, vc,&opb));
case 0x05: /* least significant *bit* is read first */
if(vi->rate==0 || vc->vendor==NULL){
/* um... we didn;t get the initial header or comments yet */
return(OV_EBADHEADER);
}
return(_vorbis_unpack_books(context, vi,&opb));
default:
/* Not a valid vorbis header type */
return(OV_EBADHEADER);
break;
}
}
}
return(OV_EBADHEADER);
}
///* pack side **********************************************************/
//
//static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){
// codec_setup_info *ci=vi->codec_setup;
// if(!ci)return(OV_EFAULT);
//
// /* preamble */
// FMOD_oggpack_write(opb,0x01,8);
// _v_writestring(opb,"vorbis", 6);
//
// /* basic information about the stream */
// FMOD_oggpack_write(opb,0x00,32);
// FMOD_oggpack_write(opb,vi->channels,8);
// FMOD_oggpack_write(opb,vi->rate,32);
//
// FMOD_oggpack_write(opb,vi->bitrate_upper,32);
// FMOD_oggpack_write(opb,vi->bitrate_nominal,32);
// FMOD_oggpack_write(opb,vi->bitrate_lower,32);
//
// FMOD_oggpack_write(opb,ilog2(ci->blocksizes[0]),4);
// FMOD_oggpack_write(opb,ilog2(ci->blocksizes[1]),4);
// FMOD_oggpack_write(opb,1,1);
//
// return(0);
//}
//
//static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){
// int bytes = ogg_strlen(ENCODE_VENDOR_STRING);
//
// /* preamble */
// FMOD_oggpack_write(opb,0x03,8);
// _v_writestring(opb,"vorbis", 6);
//
// /* vendor */
// FMOD_oggpack_write(opb,bytes,32);
// _v_writestring(opb,ENCODE_VENDOR_STRING, bytes);
//
// /* comments */
//
// FMOD_oggpack_write(opb,vc->comments,32);
// if(vc->comments){
// int i;
// for(i=0;i<vc->comments;i++){
// if(vc->user_comments[i]){
// FMOD_oggpack_write(opb,vc->comment_lengths[i],32);
// _v_writestring(opb,vc->user_comments[i], vc->comment_lengths[i]);
// }else{
// FMOD_oggpack_write(opb,0,32);
// }
// }
// }
// FMOD_oggpack_write(opb,1,1);
//
// return(0);
//}
//
//static int _vorbis_pack_books(void *context, oggpack_buffer *opb,vorbis_info *vi){
// codec_setup_info *ci=vi->codec_setup;
// int i;
// if(!ci)return(OV_EFAULT);
//
// FMOD_oggpack_write(opb,0x05,8);
// _v_writestring(opb,"vorbis", 6);
//
// /* books */
// FMOD_oggpack_write(opb,ci->books-1,8);
// for(i=0;i<ci->books;i++)
// if(FMOD_vorbis_staticbook_pack(ci->book_param[i],opb))goto err_out;
//
// /* times; hook placeholders */
// FMOD_oggpack_write(opb,0,6);
// FMOD_oggpack_write(opb,0,16);
//
// /* floors */
// FMOD_oggpack_write(opb,ci->floors-1,6);
// for(i=0;i<ci->floors;i++){
// FMOD_oggpack_write(opb,ci->floor_type[i],16);
// if(_floor_P[ci->floor_type[i]]->pack)
// _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb);
// else
// goto err_out;
// }
//
// /* residues */
// FMOD_oggpack_write(opb,ci->residues-1,6);
// for(i=0;i<ci->residues;i++){
// FMOD_oggpack_write(opb,ci->residue_type[i],16);
// _FMOD_residue_P[ci->residue_type[i]]->pack(ci->residue_param[i],opb);
// }
//
// /* maps */
// FMOD_oggpack_write(opb,ci->maps-1,6);
// for(i=0;i<ci->maps;i++){
// FMOD_oggpack_write(opb,ci->map_type[i],16);
// _FMOD_mapping_P[ci->map_type[i]]->pack(vi,ci->map_param[i],opb);
// }
//
// /* modes */
// FMOD_oggpack_write(opb,ci->modes-1,6);
// for(i=0;i<ci->modes;i++){
// FMOD_oggpack_write(opb,ci->mode_param[i]->blockflag,1);
// FMOD_oggpack_write(opb,ci->mode_param[i]->windowtype,16);
// FMOD_oggpack_write(opb,ci->mode_param[i]->transformtype,16);
// FMOD_oggpack_write(opb,ci->mode_param[i]->mapping,8);
// }
// FMOD_oggpack_write(opb,1,1);
//
// return(0);
//err_out:
// return(-1);
//}
//
//int vorbis_commentheader_out(void *context, vorbis_comment *vc,
// ogg_packet *op){
//
// oggpack_buffer opb;
//
// FMOD_oggpack_writeinit(context, &opb);
// if(_vorbis_pack_comment(&opb,vc)) return OV_EIMPL;
//
// op->packet = _ogg_malloc(FMOD_oggpack_bytes(&opb));
// FMOD_memcpy(op->packet, opb.buffer, FMOD_oggpack_bytes(&opb));
//
// op->bytes=FMOD_oggpack_bytes(&opb);
// op->b_o_s=0;
// op->e_o_s=0;
// op->granulepos=0;
// op->packetno=1;
//
// return 0;
//}
//
//int vorbis_analysis_headerout(vorbis_dsp_state *v,
// vorbis_comment *vc,
// ogg_packet *op,
// ogg_packet *op_comm,
// ogg_packet *op_code){
// int ret=OV_EIMPL;
// vorbis_info *vi=v->vi;
// oggpack_buffer opb;
// private_state *b=v->backend_state;
//
// if(!b){
// ret=OV_EFAULT;
// goto err_out;
// }
//
// /* first header packet **********************************************/
//
// FMOD_oggpack_writeinit(context, &opb);
// if(_vorbis_pack_info(&opb,vi))goto err_out;
//
// /* build the packet */
// if(b->header)_ogg_free(b->header);
// b->header=_ogg_malloc(FMOD_oggpack_bytes(&opb));
// FMOD_memcpy(b->header,opb.buffer,FMOD_oggpack_bytes(&opb));
// op->packet=b->header;
// op->bytes=FMOD_oggpack_bytes(&opb);
// op->b_o_s=1;
// op->e_o_s=0;
// op->granulepos=0;
// op->packetno=0;
//
// /* second header packet (comments) **********************************/
//
// oggpack_reset(&opb);
// if(_vorbis_pack_comment(&opb,vc))goto err_out;
//
// if(b->header1)_ogg_free(b->header1);
// b->header1=_ogg_malloc(FMOD_oggpack_bytes(&opb));
// FMOD_memcpy(b->header1,opb.buffer,FMOD_oggpack_bytes(&opb));
// op_comm->packet=b->header1;
// op_comm->bytes=FMOD_oggpack_bytes(&opb);
// op_comm->b_o_s=0;
// op_comm->e_o_s=0;
// op_comm->granulepos=0;
// op_comm->packetno=1;
//
// /* third header packet (modes/codebooks) ****************************/
//
// oggpack_reset(&opb);
// if(_vorbis_pack_books(&opb,vi))goto err_out;
//
// if(b->header2)_ogg_free(b->header2);
// b->header2=_ogg_malloc(FMOD_oggpack_bytes(&opb));
// FMOD_memcpy(b->header2,opb.buffer,FMOD_oggpack_bytes(&opb));
// op_code->packet=b->header2;
// op_code->bytes=FMOD_oggpack_bytes(&opb);
// op_code->b_o_s=0;
// op_code->e_o_s=0;
// op_code->granulepos=0;
// op_code->packetno=2;
//
// FMOD_oggpack_writeclear(&opb);
// return(0);
// err_out:
// FMOD_oggpack_writeclear(&opb);
// FMOD_memset(op,0,sizeof(*op));
// FMOD_memset(op_comm,0,sizeof(*op_comm));
// FMOD_memset(op_code,0,sizeof(*op_code));
//
// if(b){
// if(b->header)_ogg_free(b->header);
// if(b->header1)_ogg_free(b->header1);
// if(b->header2)_ogg_free(b->header2);
// b->header=NULL;
// b->header1=NULL;
// b->header2=NULL;
// }
// return(ret);
//}
//
//double vorbis_granule_time(vorbis_dsp_state *v,ogg_int64_t granulepos){
// if(granulepos>=0)
// return((double)granulepos/v->vi->rate);
// return(-1);
//}
//
//const char *vorbis_version_string(void){
// return GENERAL_VENDOR_STRING;
//}

View file

@ -0,0 +1,32 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: lookup based functions
last mod: $Id: lookup.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
#ifndef _V_LOOKUP_H_
#ifdef FLOAT_LOOKUP
extern float FMOD_vorbis_coslook(float a);
extern float FMOD_vorbis_invsqlook(float a);
extern float FMOD_vorbis_invsq2explook(int a);
extern float FMOD_vorbis_fromdBlook(float a);
#endif
#ifdef INT_LOOKUP
extern ogg_int32_t FMOD_vorbis_invsqlook_i(ogg_int32_t a,ogg_int32_t e);
extern ogg_int32_t FMOD_vorbis_coslook_i(ogg_int32_t a);
extern float FMOD_vorbis_fromdBlook_i(ogg_int32_t a);
#endif
#endif

View file

@ -0,0 +1,192 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: lookup data; generated by lookups.pl; edit there
last mod: $Id: lookup_data.h 16037 2009-05-26 21:10:58Z xiphmont $
********************************************************************/
#ifndef _V_LOOKUP_DATA_H_
#ifdef FLOAT_LOOKUP
#define COS_LOOKUP_SZ 128
static const float COS_LOOKUP[COS_LOOKUP_SZ+1]={
+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,
};
#define INVSQ_LOOKUP_SZ 32
static const float INVSQ_LOOKUP[INVSQ_LOOKUP_SZ+1]={
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,
};
#define INVSQ2EXP_LOOKUP_MIN (-32)
#define INVSQ2EXP_LOOKUP_MAX 32
static const float INVSQ2EXP_LOOKUP[INVSQ2EXP_LOOKUP_MAX-\
INVSQ2EXP_LOOKUP_MIN+1]={
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,
};
#endif
#define FROMdB_LOOKUP_SZ 35
#define FROMdB2_LOOKUP_SZ 32
#define FROMdB_SHIFT 5
#define FROMdB2_SHIFT 3
#define FROMdB2_MASK 31
#ifdef FLOAT_LOOKUP
static const float FROMdB_LOOKUP[FROMdB_LOOKUP_SZ]={
1.f, 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 const float FROMdB2_LOOKUP[FROMdB2_LOOKUP_SZ]={
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,
};
#endif
#ifdef INT_LOOKUP
#define INVSQ_LOOKUP_I_SHIFT 10
#define INVSQ_LOOKUP_I_MASK 1023
static const ogg_int32_t INVSQ_LOOKUP_I[64+1]={
92682l, 91966l, 91267l, 90583l,
89915l, 89261l, 88621l, 87995l,
87381l, 86781l, 86192l, 85616l,
85051l, 84497l, 83953l, 83420l,
82897l, 82384l, 81880l, 81385l,
80899l, 80422l, 79953l, 79492l,
79039l, 78594l, 78156l, 77726l,
77302l, 76885l, 76475l, 76072l,
75674l, 75283l, 74898l, 74519l,
74146l, 73778l, 73415l, 73058l,
72706l, 72359l, 72016l, 71679l,
71347l, 71019l, 70695l, 70376l,
70061l, 69750l, 69444l, 69141l,
68842l, 68548l, 68256l, 67969l,
67685l, 67405l, 67128l, 66855l,
66585l, 66318l, 66054l, 65794l,
65536l,
};
#define COS_LOOKUP_I_SHIFT 9
#define COS_LOOKUP_I_MASK 511
#define COS_LOOKUP_I_SZ 128
static const ogg_int32_t COS_LOOKUP_I[COS_LOOKUP_I_SZ+1]={
16384l, 16379l, 16364l, 16340l,
16305l, 16261l, 16207l, 16143l,
16069l, 15986l, 15893l, 15791l,
15679l, 15557l, 15426l, 15286l,
15137l, 14978l, 14811l, 14635l,
14449l, 14256l, 14053l, 13842l,
13623l, 13395l, 13160l, 12916l,
12665l, 12406l, 12140l, 11866l,
11585l, 11297l, 11003l, 10702l,
10394l, 10080l, 9760l, 9434l,
9102l, 8765l, 8423l, 8076l,
7723l, 7366l, 7005l, 6639l,
6270l, 5897l, 5520l, 5139l,
4756l, 4370l, 3981l, 3590l,
3196l, 2801l, 2404l, 2006l,
1606l, 1205l, 804l, 402l,
0l, -401l, -803l, -1204l,
-1605l, -2005l, -2403l, -2800l,
-3195l, -3589l, -3980l, -4369l,
-4755l, -5138l, -5519l, -5896l,
-6269l, -6638l, -7004l, -7365l,
-7722l, -8075l, -8422l, -8764l,
-9101l, -9433l, -9759l, -10079l,
-10393l, -10701l, -11002l, -11296l,
-11584l, -11865l, -12139l, -12405l,
-12664l, -12915l, -13159l, -13394l,
-13622l, -13841l, -14052l, -14255l,
-14448l, -14634l, -14810l, -14977l,
-15136l, -15285l, -15425l, -15556l,
-15678l, -15790l, -15892l, -15985l,
-16068l, -16142l, -16206l, -16260l,
-16304l, -16339l, -16363l, -16378l,
-16383l,
};
#endif
#endif

160
lib/ogg_vorbis/vorbis/lib/lpc.c Executable file
View file

@ -0,0 +1,160 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: LPC low level routines
last mod: $Id: lpc.c 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
/* Some of these routines (autocorrelator, LPC coefficient estimator)
are derived from code written by Jutta Degener and Carsten Bormann;
thus we include their copyright below. The entirety of this file
is freely redistributable on the condition that both of these
copyright notices are preserved without modification. */
/* Preserved Copyright: *********************************************/
/* Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
Technische Universita"t Berlin
Any use of this software is permitted provided that this notice is not
removed and that neither the authors nor the Technische Universita"t
Berlin are deemed to have made any representations as to the
suitability of this software for any purpose nor are held responsible
for any defects of this software. THERE IS ABSOLUTELY NO WARRANTY FOR
THIS SOFTWARE.
As a matter of courtesy, the authors request to be informed about uses
this software has found, about bugs in this software, and about any
improvements that may be of general interest.
Berlin, 28.11.1994
Jutta Degener
Carsten Bormann
*********************************************************************/
#include <stdlib.h>
#include <string.h>
//#include <math.h>
#include "os.h"
#include "smallft.h"
#include "lpc.h"
#include "scales.h"
#include "misc.h"
/* 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 */
float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){
float *aut=alloca(sizeof(*aut)*(m+1));
float *lpc=alloca(sizeof(*lpc)*(m));
float error;
float epsilon;
int i,j;
/* autocorrelation, p+1 lag coefficients */
j=m+1;
while(j--){
float d=0; /* float needed for accumulator depth */
for(i=j;i<n;i++)d+=(float)data[i]*data[i-j];
aut[j]=d;
}
/* Generate lpc coefficients from autocorr values */
/* set our noise floor to about -100dB */
error=aut[0] * (1.f + 1e-10f);
epsilon=(float)1e-9*aut[0]+1e-10f;
for(i=0;i<m;i++){
float r= -aut[i+1];
if(error<epsilon){
FMOD_memset(lpc+i,0,(m-i)*sizeof(*lpc));
goto done;
}
/* 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;
/* 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&1)lpc[j]+=lpc[j]*r;
error*=1.f-r*r;
}
done:
/* slightly damp the filter */
{
float g = .99f;
float damp = g;
for(j=0;j<m;j++){
lpc[j]*=damp;
damp*=g;
}
}
for(j=0;j<m;j++)lpci[j]=(float)lpc[j];
/* we need the error value to know how big an impulse to hit the
filter with later */
return error;
}
void vorbis_lpc_predict(float *coeff,float *prime,int m,
float *data,ogg_int32_t n){
/* in: coeff[0...m-1] LPC coefficients
prime[0...m-1] initial values (allocated size of n+m-1)
out: data[0...n-1] data samples */
ogg_int32_t i,j,o,p;
float y;
float *work=alloca(sizeof(*work)*(m+n));
if(!prime)
for(i=0;i<m;i++)
work[i]=0.f;
else
for(i=0;i<m;i++)
work[i]=prime[i];
for(i=0;i<n;i++){
y=0;
o=i;
p=m;
for(j=0;j<m;j++)
y-=work[o++]*coeff[--p];
data[i]=work[o]=y;
}
}

29
lib/ogg_vorbis/vorbis/lib/lpc.h Executable file
View file

@ -0,0 +1,29 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: LPC low level routines
last mod: $Id: lpc.h 16037 2009-05-26 21:10:58Z xiphmont $
********************************************************************/
#ifndef _V_LPC_H_
#define _V_LPC_H_
#include "vorbis/codec.h"
/* simple linear scale LPC code */
extern float vorbis_lpc_from_data(float *data,float *lpc,int n,int m);
extern void vorbis_lpc_predict(float *coeff,float *prime,int m,
float *data,ogg_int32_t n);
#endif

456
lib/ogg_vorbis/vorbis/lib/lsp.c Executable file
View file

@ -0,0 +1,456 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: LSP (also called LSF) conversion routines
last mod: $Id: lsp.c 16227 2009-07-08 06:58:46Z xiphmont $
The LSP generation code is taken (with minimal modification and a
few bugfixes) from "On the Computation of the LSP Frequencies" by
Joseph Rothweiler (see http://www.rothweiler.us for contact info).
The paper is available at:
http://www.myown1.com/joe/lsf
********************************************************************/
/* Note that the lpc-lsp conversion finds the roots of polynomial with
an iterative root polisher (CACM algorithm 283). It *is* possible
to confuse this algorithm into not converging; that should only
happen with absurdly closely spaced roots (very sharp peaks in the
LPC f response) which in turn should be impossible in our use of
the code. If this *does* happen anyway, it's a bug in the floor
finder; find the cause of the confusion (probably a single bin
spike or accidental near-float-limit resolution problems) and
correct it. */
//#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "lsp.h"
#include "os.h"
#include "misc.h"
#include "lookup.h"
#include "scales.h"
/* three possible LSP to f curve functions; the exact computation
(float), a lookup based float implementation, and an integer
implementation. The float lookup is likely the optimal choice on
any machine with an FPU. The integer implementation is *not* fixed
point (due to the need for a large dynamic range and thus a
seperately tracked exponent) and thus much more complex than the
relatively simple float implementations. It's mostly for future
work on a fully fixed point implementation for processors like the
ARM family. */
/* define either of these (preferably FLOAT_LOOKUP) to have faster
but less precise implementation. */
#undef FLOAT_LOOKUP
#undef INT_LOOKUP
#ifdef FLOAT_LOOKUP
#include "lookup.c" /* catch this in the build system; we #include for
compilers (like gcc) that can't inline across
modules */
/* side effect: changes *lsp to cosines of lsp */
void FMOD_vorbis_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;
vorbis_fpu_control fpu;
FMOD_vorbis_fpu_setround(&fpu);
for(i=0;i<m;i++)lsp[i]=FMOD_vorbis_coslook(lsp[i]);
i=0;
while(i<n){
int k=map[i];
int qexp;
float p=.7071067812f;
float q=.7071067812f;
float w=FMOD_vorbis_coslook(wdel*k);
float *ftmp=lsp;
int c=m>>1;
do{
q*=ftmp[0]-w;
p*=ftmp[1]-w;
ftmp+=2;
}while(--c);
if(m&1){
/* odd order filter; slightly assymetric */
/* the last coefficient */
q*=ftmp[0]-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);
}
q=FMOD_ogg_frexp(p+q,&qexp);
q=FMOD_vorbis_fromdBlook(amp*
vorbis_invsqlook(q)*
vorbis_invsq2explook(qexp+m)-
ampoffset);
do{
curve[i++]*=q;
}while(map[i]==k);
}
FMOD_vorbis_fpu_restore(fpu);
}
#else
#ifdef INT_LOOKUP
#include "lookup.c" /* catch this in the build system; we #include for
compilers (like gcc) that can't inline across
modules */
static const int MLOOP_1[64]={
0,10,11,11, 12,12,12,12, 13,13,13,13, 13,13,13,13,
14,14,14,14, 14,14,14,14, 14,14,14,14, 14,14,14,14,
15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
};
static const int MLOOP_2[64]={
0,4,5,5, 6,6,6,6, 7,7,7,7, 7,7,7,7,
8,8,8,8, 8,8,8,8, 8,8,8,8, 8,8,8,8,
9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
};
static const int MLOOP_3[8]={0,1,2,2,3,3,3,3};
/* side effect: changes *lsp to cosines of lsp */
void FMOD_vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m,
float amp,float ampoffset){
/* 0 <= m < 256 */
/* set up for using all int later */
int i;
int ampoffseti=FMOD_ogg_rint(ampoffset*4096.f);
int ampi=FMOD_ogg_rint(amp*16.f);
ogg_int32_t *ilsp=alloca(m*sizeof(*ilsp));
for(i=0;i<m;i++)ilsp[i]=FMOD_vorbis_coslook_i(lsp[i]/M_PI*65536.f+.5f);
i=0;
while(i<n){
int j,k=map[i];
ogg_uint32_t pi=46341; /* 2**-.5 in 0.16 */
ogg_uint32_t qi=46341;
int qexp=0,shift;
ogg_int32_t wi=FMOD_vorbis_coslook_i(k*65536/ln);
qi*=labs(ilsp[0]-wi);
pi*=labs(ilsp[1]-wi);
for(j=3;j<m;j+=2){
if(!(shift=MLOOP_1[(pi|qi)>>25]))
if(!(shift=MLOOP_2[(pi|qi)>>19]))
shift=MLOOP_3[(pi|qi)>>16];
qi=(qi>>shift)*labs(ilsp[j-1]-wi);
pi=(pi>>shift)*labs(ilsp[j]-wi);
qexp+=shift;
}
if(!(shift=MLOOP_1[(pi|qi)>>25]))
if(!(shift=MLOOP_2[(pi|qi)>>19]))
shift=MLOOP_3[(pi|qi)>>16];
/* pi,qi normalized collectively, both tracked using qexp */
if(m&1){
/* odd order filter; slightly assymetric */
/* the last coefficient */
qi=(qi>>shift)*labs(ilsp[j-1]-wi);
pi=(pi>>shift)<<14;
qexp+=shift;
if(!(shift=MLOOP_1[(pi|qi)>>25]))
if(!(shift=MLOOP_2[(pi|qi)>>19]))
shift=MLOOP_3[(pi|qi)>>16];
pi>>=shift;
qi>>=shift;
qexp+=shift-14*((m+1)>>1);
pi=((pi*pi)>>16);
qi=((qi*qi)>>16);
qexp=qexp*2+m;
pi*=(1<<14)-((wi*wi)>>14);
qi+=pi>>14;
}else{
/* even order filter; still symmetric */
/* p*=p(1-w), q*=q(1+w), let normalization drift because it isn't
worth tracking step by step */
pi>>=shift;
qi>>=shift;
qexp+=shift-7*m;
pi=((pi*pi)>>16);
qi=((qi*qi)>>16);
qexp=qexp*2+m;
pi*=(1<<14)-wi;
qi*=(1<<14)+wi;
qi=(qi+pi)>>14;
}
/* we've let the normalization drift because it wasn't important;
however, for the lookup, things must be normalized again. We
need at most one right shift or a number of left shifts */
if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
qi>>=1; qexp++;
}else
while(qi && !(qi&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/
qi<<=1; qexp--;
}
amp=FMOD_vorbis_fromdBlook_i(ampi* /* n.4 */
vorbis_invsqlook_i(qi,qexp)-
/* m.8, m+n<=8 */
ampoffseti); /* 8.12[0] */
curve[i]*=amp;
while(map[++i]==k)curve[i]*=amp;
}
}
#else
/* old, nonoptimized but simple version for any poor sap who needs to
figure out what the hell this code does, or wants the other
fraction of a dB precision */
/* side effect: changes *lsp to cosines of lsp */
void FMOD_vorbis_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]=2.f*FMOD_ogg_cos(lsp[i]);
i=0;
while(i<n){
int j,k=map[i];
float p=.5f;
float q=.5f;
float w=2.f*FMOD_ogg_cos(wdel*k);
for(j=1;j<m;j+=2){
q *= w-lsp[j-1];
p *= w-lsp[j];
}
if(j==m){
/* odd order filter; slightly assymetric */
/* the last coefficient */
q*=w-lsp[j-1];
p*=p*(4.f-w*w);
q*=q;
}else{
/* even order filter; still symmetric */
p*=p*(2.f-w);
q*=q*(2.f+w);
}
q=fromdB(amp/FMOD_ogg_sqrt(p+q)-ampoffset);
curve[i]*=q;
while(map[++i]==k)curve[i]*=q;
}
}
#endif
#endif
static void cheby(float *g, int ord) {
int i, j;
g[0] *= .5f;
for(i=2; i<= ord; i++) {
for(j=ord; j >= i; j--) {
g[j-2] -= g[j];
g[j] += g[j];
}
}
}
static int comp(const void *a,const void *b){
return (*(float *)a<*(float *)b)-(*(float *)a>*(float *)b);
}
/* Newton-Raphson-Maehly actually functioned as a decent root finder,
but there are root sets for which it gets into limit cycles
(exacerbated by zero suppression) and fails. We can't afford to
fail, even if the failure is 1 in 100,000,000, so we now use
Laguerre and later polish with Newton-Raphson (which can then
afford to fail) */
#define EPSILON 10e-7
static int Laguerre_With_Deflation(float *a,int ord,float *r){
int i,m;
double lastdelta=0.f;
double *defl=alloca(sizeof(*defl)*(ord+1));
for(i=0;i<=ord;i++)defl[i]=a[i];
for(m=ord;m>0;m--){
double new=0.f,delta;
/* iterate a root */
while(1){
double p=defl[m],pp=0.f,ppp=0.f,denom;
/* eval the polynomial and its first two derivatives */
for(i=m;i>0;i--){
ppp = new*ppp + pp;
pp = new*pp + p;
p = new*p + defl[i-1];
}
/* Laguerre's method */
denom=(m-1) * ((m-1)*pp*pp - m*p*ppp);
if(denom<0)
return(-1); /* complex root! The LPC generator handed us a bad filter */
if(pp>0){
denom = pp + FMOD_ogg_sqrt(denom);
if(denom<EPSILON)denom=EPSILON;
}else{
denom = pp - FMOD_ogg_sqrt(denom);
if(denom>-(EPSILON))denom=-(EPSILON);
}
delta = m*p/denom;
new -= delta;
if(delta<0.f)delta*=-1;
if(fabs(delta/new)<10e-12)break;
lastdelta=delta;
}
r[m-1]=(float)new;
/* forward deflation */
for(i=m;i>0;i--)
defl[i-1]+=new*defl[i];
defl++;
}
return(0);
}
/* for spit-and-polish only */
static int Newton_Raphson(float *a,int ord,float *r){
int i, k, count=0;
double error=1.f;
double *root=alloca(ord*sizeof(*root));
for(i=0; i<ord;i++) root[i] = r[i];
while(error>1e-20){
error=0;
for(i=0; i<ord; i++) { /* Update each point. */
double pp=0.,delta;
double rooti=root[i];
double p=a[ord];
for(k=ord-1; k>= 0; k--) {
pp= pp* rooti + p;
p = p * rooti + a[k];
}
delta = p/pp;
root[i] -= delta;
error+= delta*delta;
}
if(count>40)return(-1);
count++;
}
/* Replaced the original bubble sort with a real sort. With your
help, we can eliminate the bubble sort in our lifetime. --Monty */
for(i=0; i<ord;i++) r[i] = (float)root[i];
return(0);
}
/* Convert lpc coefficients to lsp coefficients */
int vorbis_lpc_to_lsp(float *lpc,float *lsp,int m){
int order2=(m+1)>>1;
int g1_order,g2_order;
float *g1=alloca(sizeof(*g1)*(order2+1));
float *g2=alloca(sizeof(*g2)*(order2+1));
float *g1r=alloca(sizeof(*g1r)*(order2+1));
float *g2r=alloca(sizeof(*g2r)*(order2+1));
int i;
/* even and odd are slightly different base cases */
g1_order=(m+1)>>1;
g2_order=(m) >>1;
/* Compute the lengths of the x polynomials. */
/* Compute the first half of K & R F1 & F2 polynomials. */
/* Compute half of the symmetric and antisymmetric polynomials. */
/* Remove the roots at +1 and -1. */
g1[g1_order] = 1.f;
for(i=1;i<=g1_order;i++) g1[g1_order-i] = lpc[i-1]+lpc[m-i];
g2[g2_order] = 1.f;
for(i=1;i<=g2_order;i++) g2[g2_order-i] = lpc[i-1]-lpc[m-i];
if(g1_order>g2_order){
for(i=2; i<=g2_order;i++) g2[g2_order-i] += g2[g2_order-i+2];
}else{
for(i=1; i<=g1_order;i++) g1[g1_order-i] -= g1[g1_order-i+1];
for(i=1; i<=g2_order;i++) g2[g2_order-i] += g2[g2_order-i+1];
}
/* Convert into polynomials in cos(alpha) */
cheby(g1,g1_order);
cheby(g2,g2_order);
/* Find the roots of the 2 even polynomials.*/
if(Laguerre_With_Deflation(g1,g1_order,g1r) ||
Laguerre_With_Deflation(g2,g2_order,g2r))
return(-1);
Newton_Raphson(g1,g1_order,g1r); /* if it fails, it leaves g1r alone */
Newton_Raphson(g2,g2_order,g2r); /* if it fails, it leaves g2r alone */
qsort(g1r,g1_order,sizeof(*g1r),comp);
qsort(g2r,g2_order,sizeof(*g2r),comp);
for(i=0;i<g1_order;i++)
lsp[i*2] = FMOD_ogg_acos(g1r[i]);
for(i=0;i<g2_order;i++)
lsp[i*2+1] = FMOD_ogg_acos(g2r[i]);
return(0);
}

28
lib/ogg_vorbis/vorbis/lib/lsp.h Executable file
View file

@ -0,0 +1,28 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: LSP (also called LSF) conversion routines
last mod: $Id: lsp.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
#ifndef _V_LSP_H_
#define _V_LSP_H_
extern int FMOD_vorbis_lpc_to_lsp(float *lpc,float *lsp,int m);
extern void FMOD_vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,
float *lsp,int m,
float amp,float ampoffset);
#endif

View file

@ -0,0 +1,867 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: channel mapping 0 implementation
last mod: $Id: mapping0.c 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ogg/ogg.h>
#include "vorbis/codec.h"
#include "codec_internal.h"
#include "codebook.h"
#include "window.h"
#include "registry.h"
#include "psy.h"
#include "misc.h"
/* simplistic, wasteful way of doing this (unique lookup for each
mode/submapping); there should be a central repository for
identical lookups. That will require minor work, so I'm putting it
off as low priority.
Why a lookup for each backend in a given mode? Because the
blocksize is set by the mode, and low backend lookups may require
parameters from other areas of the mode/mapping */
static void mapping0_free_info(void *context, vorbis_info_mapping *i){
vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)i;
if(info){
FMOD_memset(info,0,sizeof(*info));
_ogg_free(info);
}
}
static int ilog(unsigned int v){
int ret=0;
if(v)--v;
while(v){
ret++;
v>>=1;
}
return(ret);
}
#if 0
static void mapping0_pack(vorbis_info *vi,vorbis_info_mapping *vm,
oggpack_buffer *opb){
int i;
vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)vm;
/* 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){
FMOD_oggpack_write(opb,1,1);
FMOD_oggpack_write(opb,info->submaps-1,4);
}else
FMOD_oggpack_write(opb,0,1);
if(info->coupling_steps>0){
FMOD_oggpack_write(opb,1,1);
FMOD_oggpack_write(opb,info->coupling_steps-1,8);
for(i=0;i<info->coupling_steps;i++){
FMOD_oggpack_write(opb,info->coupling_mag[i],ilog(vi->channels));
FMOD_oggpack_write(opb,info->coupling_ang[i],ilog(vi->channels));
}
}else
FMOD_oggpack_write(opb,0,1);
FMOD_oggpack_write(opb,0,2); /* 2,3:reserved */
/* we don't write the channel submappings if we only have one... */
if(info->submaps>1){
for(i=0;i<vi->channels;i++)
FMOD_oggpack_write(opb,info->chmuxlist[i],4);
}
for(i=0;i<info->submaps;i++){
FMOD_oggpack_write(opb,0,8); /* time submap unused */
FMOD_oggpack_write(opb,info->floorsubmap[i],8);
FMOD_oggpack_write(opb,info->residuesubmap[i],8);
}
}
#endif
/* also responsible for range checking */
static vorbis_info_mapping *mapping0_unpack(void *context, vorbis_info *vi,oggpack_buffer *opb){
int i,b;
vorbis_info_mapping0 *info=_ogg_calloc(1,sizeof(*info));
codec_setup_info *ci=vi->codec_setup;
FMOD_memset(info,0,sizeof(*info));
b=FMOD_oggpack_read(opb,1);
if(b<0)goto err_out;
if(b){
info->submaps=FMOD_oggpack_read(opb,4)+1;
if(info->submaps<=0)goto err_out;
}else
info->submaps=1;
b=FMOD_oggpack_read(opb,1);
if(b<0)goto err_out;
if(b){
info->coupling_steps=FMOD_oggpack_read(opb,8)+1;
if(info->coupling_steps<=0)goto err_out;
for(i=0;i<info->coupling_steps;i++){
int testM=info->coupling_mag[i]=FMOD_oggpack_read(opb,ilog(vi->channels));
int testA=info->coupling_ang[i]=FMOD_oggpack_read(opb,ilog(vi->channels));
if(testM<0 ||
testA<0 ||
testM==testA ||
testM>=vi->channels ||
testA>=vi->channels) goto err_out;
}
}
if(FMOD_oggpack_read(opb,2)!=0)goto err_out; /* 2,3:reserved */
if(info->submaps>1){
for(i=0;i<vi->channels;i++){
info->chmuxlist[i]=FMOD_oggpack_read(opb,4);
if(info->chmuxlist[i]>=info->submaps || info->chmuxlist[i]<0)goto err_out;
}
}
for(i=0;i<info->submaps;i++){
FMOD_oggpack_read(opb,8); /* time submap unused */
info->floorsubmap[i]=FMOD_oggpack_read(opb,8);
if(info->floorsubmap[i]>=ci->floors || info->floorsubmap[i]<0)goto err_out;
info->residuesubmap[i]=FMOD_oggpack_read(opb,8);
if(info->residuesubmap[i]>=ci->residues || info->residuesubmap[i]<0)goto err_out;
}
return info;
err_out:
mapping0_free_info(context, info);
return(NULL);
}
#include "os.h"
#include "lpc.h"
#include "lsp.h"
//#include "envelope.h"
#include "mdct.h"
#include "psy.h"
#include "scales.h"
#if 0
static ogg_int32_t seq=0;
static ogg_int64_t total=0;
static float FLOOR1_fromdB_LOOKUP[256]={
1.0649863e-07F, 1.1341951e-07F, 1.2079015e-07F, 1.2863978e-07F,
1.3699951e-07F, 1.4590251e-07F, 1.5538408e-07F, 1.6548181e-07F,
1.7623575e-07F, 1.8768855e-07F, 1.9988561e-07F, 2.128753e-07F,
2.2670913e-07F, 2.4144197e-07F, 2.5713223e-07F, 2.7384213e-07F,
2.9163793e-07F, 3.1059021e-07F, 3.3077411e-07F, 3.5226968e-07F,
3.7516214e-07F, 3.9954229e-07F, 4.2550680e-07F, 4.5315863e-07F,
4.8260743e-07F, 5.1396998e-07F, 5.4737065e-07F, 5.8294187e-07F,
6.2082472e-07F, 6.6116941e-07F, 7.0413592e-07F, 7.4989464e-07F,
7.9862701e-07F, 8.5052630e-07F, 9.0579828e-07F, 9.6466216e-07F,
1.0273513e-06F, 1.0941144e-06F, 1.1652161e-06F, 1.2409384e-06F,
1.3215816e-06F, 1.4074654e-06F, 1.4989305e-06F, 1.5963394e-06F,
1.7000785e-06F, 1.8105592e-06F, 1.9282195e-06F, 2.0535261e-06F,
2.1869758e-06F, 2.3290978e-06F, 2.4804557e-06F, 2.6416497e-06F,
2.8133190e-06F, 2.9961443e-06F, 3.1908506e-06F, 3.3982101e-06F,
3.6190449e-06F, 3.8542308e-06F, 4.1047004e-06F, 4.3714470e-06F,
4.6555282e-06F, 4.9580707e-06F, 5.2802740e-06F, 5.6234160e-06F,
5.9888572e-06F, 6.3780469e-06F, 6.7925283e-06F, 7.2339451e-06F,
7.7040476e-06F, 8.2047000e-06F, 8.7378876e-06F, 9.3057248e-06F,
9.9104632e-06F, 1.0554501e-05F, 1.1240392e-05F, 1.1970856e-05F,
1.2748789e-05F, 1.3577278e-05F, 1.4459606e-05F, 1.5399272e-05F,
1.6400004e-05F, 1.7465768e-05F, 1.8600792e-05F, 1.9809576e-05F,
2.1096914e-05F, 2.2467911e-05F, 2.3928002e-05F, 2.5482978e-05F,
2.7139006e-05F, 2.8902651e-05F, 3.0780908e-05F, 3.2781225e-05F,
3.4911534e-05F, 3.7180282e-05F, 3.9596466e-05F, 4.2169667e-05F,
4.4910090e-05F, 4.7828601e-05F, 5.0936773e-05F, 5.4246931e-05F,
5.7772202e-05F, 6.1526565e-05F, 6.5524908e-05F, 6.9783085e-05F,
7.4317983e-05F, 7.9147585e-05F, 8.4291040e-05F, 8.9768747e-05F,
9.5602426e-05F, 0.00010181521F, 0.00010843174F, 0.00011547824F,
0.00012298267F, 0.00013097477F, 0.00013948625F, 0.00014855085F,
0.00015820453F, 0.00016848555F, 0.00017943469F, 0.00019109536F,
0.00020351382F, 0.00021673929F, 0.00023082423F, 0.00024582449F,
0.00026179955F, 0.00027881276F, 0.00029693158F, 0.00031622787F,
0.00033677814F, 0.00035866388F, 0.00038197188F, 0.00040679456F,
0.00043323036F, 0.00046138411F, 0.00049136745F, 0.00052329927F,
0.00055730621F, 0.00059352311F, 0.00063209358F, 0.00067317058F,
0.00071691700F, 0.00076350630F, 0.00081312324F, 0.00086596457F,
0.00092223983F, 0.00098217216F, 0.0010459992F, 0.0011139742F,
0.0011863665F, 0.0012634633F, 0.0013455702F, 0.0014330129F,
0.0015261382F, 0.0016253153F, 0.0017309374F, 0.0018434235F,
0.0019632195F, 0.0020908006F, 0.0022266726F, 0.0023713743F,
0.0025254795F, 0.0026895994F, 0.0028643847F, 0.0030505286F,
0.0032487691F, 0.0034598925F, 0.0036847358F, 0.0039241906F,
0.0041792066F, 0.0044507950F, 0.0047400328F, 0.0050480668F,
0.0053761186F, 0.0057254891F, 0.0060975636F, 0.0064938176F,
0.0069158225F, 0.0073652516F, 0.0078438871F, 0.0083536271F,
0.0088964928F, 0.009474637F, 0.010090352F, 0.010746080F,
0.011444421F, 0.012188144F, 0.012980198F, 0.013823725F,
0.014722068F, 0.015678791F, 0.016697687F, 0.017782797F,
0.018938423F, 0.020169149F, 0.021479854F, 0.022875735F,
0.024362330F, 0.025945531F, 0.027631618F, 0.029427276F,
0.031339626F, 0.033376252F, 0.035545228F, 0.037855157F,
0.040315199F, 0.042935108F, 0.045725273F, 0.048696758F,
0.051861348F, 0.055231591F, 0.058820850F, 0.062643361F,
0.066714279F, 0.071049749F, 0.075666962F, 0.080584227F,
0.085821044F, 0.091398179F, 0.097337747F, 0.10366330F,
0.11039993F, 0.11757434F, 0.12521498F, 0.13335215F,
0.14201813F, 0.15124727F, 0.16107617F, 0.17154380F,
0.18269168F, 0.19456402F, 0.20720788F, 0.22067342F,
0.23501402F, 0.25028656F, 0.26655159F, 0.28387361F,
0.30232132F, 0.32196786F, 0.34289114F, 0.36517414F,
0.38890521F, 0.41417847F, 0.44109412F, 0.46975890F,
0.50028648F, 0.53279791F, 0.56742212F, 0.60429640F,
0.64356699F, 0.68538959F, 0.72993007F, 0.77736504F,
0.82788260F, 0.88168307F, 0.9389798F, 1.F,
};
#endif
//static int mapping0_forward(void *context, vorbis_block *vb){
// vorbis_dsp_state *vd=vb->vd;
// vorbis_info *vi=vd->vi;
// codec_setup_info *ci=vi->codec_setup;
// private_state *b=vb->vd->backend_state;
// vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal;
// int n=vb->pcmend;
// int i,j,k;
//
// int *nonzero = alloca(sizeof(*nonzero)*vi->channels);
// float **gmdct = _FMOD_vorbis_block_alloc(context, vb,vi->channels*sizeof(*gmdct));
// int **ilogmaskch= _FMOD_vorbis_block_alloc(context, vb,vi->channels*sizeof(*ilogmaskch));
// int ***floor_posts = _FMOD_vorbis_block_alloc(context, vb,vi->channels*sizeof(*floor_posts));
//
// float global_ampmax=vbi->ampmax;
// float *local_ampmax=alloca(sizeof(*local_ampmax)*vi->channels);
// int blocktype=vbi->blocktype;
//
// int modenumber=vb->W;
// vorbis_info_mapping0 *info=ci->map_param[modenumber];
// vorbis_look_psy *psy_look=
// b->psy+blocktype+(vb->W?2:0);
//
// vb->mode=modenumber;
//
// for(i=0;i<vi->channels;i++){
// float scale=4.f/n;
// float scale_dB;
//
// float *pcm =vb->pcm[i];
// float *logfft =pcm;
//
// gmdct[i]=_FMOD_vorbis_block_alloc(context, vb,n/2*sizeof(**gmdct));
//
// scale_dB=todB(&scale) + .345f; /* + .345 is a hack; the original
// todB estimation used on IEEE 754
// compliant machines had a bug that
// returned dB values about a third
// of a decibel too high. The bug
// was harmless because tunings
// implicitly took that into
// account. However, fixing the bug
// in the estimator requires
// changing all the tunings as well.
// For now, it's easier to sync
// things back up here, and
// recalibrate the tunings in the
// next major model upgrade. */
//
//#if 0
// if(vi->channels==2){
// if(i==0)
// _analysis_output("pcmL",seq,pcm,n,0,0,total-n/2);
// else
// _analysis_output("pcmR",seq,pcm,n,0,0,total-n/2);
// }else{
// _analysis_output("pcm",seq,pcm,n,0,0,total-n/2);
// }
//#endif
//
// /* window the PCM data */
// _FMOD_vorbis_apply_window(pcm,b->window,ci->blocksizes,vb->lW,vb->W,vb->nW);
//
//#if 0
// if(vi->channels==2){
// if(i==0)
// _analysis_output("windowedL",seq,pcm,n,0,0,total-n/2);
// else
// _analysis_output("windowedR",seq,pcm,n,0,0,total-n/2);
// }else{
// _analysis_output("windowed",seq,pcm,n,0,0,total-n/2);
// }
//#endif
//
// /* transform the PCM data */
// /* only MDCT right now.... */
// FMOD_mdct_forward(b->transform[vb->W][0],pcm,gmdct[i]);
//
// /* FFT yields more accurate tonal estimation (not phase sensitive) */
// drft_forward(&b->fft_look[vb->W],pcm);
// logfft[0]=scale_dB+todB(pcm) + .345f; /* + .345 is a hack; the
// original todB estimation used on
// IEEE 754 compliant machines had a
// bug that returned dB values about
// a third of a decibel too high.
// The bug was harmless because
// tunings implicitly took that into
// account. However, fixing the bug
// in the estimator requires
// changing all the tunings as well.
// For now, it's easier to sync
// things back up here, and
// recalibrate the tunings in the
// next major model upgrade. */
// local_ampmax[i]=logfft[0];
// for(j=1;j<n-1;j+=2){
// float temp=pcm[j]*pcm[j]+pcm[j+1]*pcm[j+1];
// temp=logfft[(j+1)>>1]=scale_dB+.5f*todB(&temp) + .345f; /* +
// .345 is a hack; the original todB
// estimation used on IEEE 754
// compliant machines had a bug that
// returned dB values about a third
// of a decibel too high. The bug
// was harmless because tunings
// implicitly took that into
// account. However, fixing the bug
// in the estimator requires
// changing all the tunings as well.
// For now, it's easier to sync
// things back up here, and
// recalibrate the tunings in the
// next major model upgrade. */
// if(temp>local_ampmax[i])local_ampmax[i]=temp;
// }
//
// if(local_ampmax[i]>0.f)local_ampmax[i]=0.f;
// if(local_ampmax[i]>global_ampmax)global_ampmax=local_ampmax[i];
//
//#if 0
// if(vi->channels==2){
// if(i==0){
// _analysis_output("fftL",seq,logfft,n/2,1,0,0);
// }else{
// _analysis_output("fftR",seq,logfft,n/2,1,0,0);
// }
// }else{
// _analysis_output("fft",seq,logfft,n/2,1,0,0);
// }
//#endif
//
// }
//
// {
// float *noise = _FMOD_vorbis_block_alloc(context, vb,n/2*sizeof(*noise));
// float *tone = _FMOD_vorbis_block_alloc(context, vb,n/2*sizeof(*tone));
//
// for(i=0;i<vi->channels;i++){
// /* the encoder setup assumes that all the modes used by any
// specific bitrate tweaking use the same floor */
//
// int submap=info->chmuxlist[i];
//
// /* the following makes things clearer to *me* anyway */
// float *mdct =gmdct[i];
// float *logfft =vb->pcm[i];
//
// float *logmdct =logfft+n/2;
// float *logmask =logfft;
//
// vb->mode=modenumber;
//
// floor_posts[i]=_FMOD_vorbis_block_alloc(context, vb,PACKETBLOBS*sizeof(**floor_posts));
// FMOD_memset(floor_posts[i],0,sizeof(**floor_posts)*PACKETBLOBS);
//
// for(j=0;j<n/2;j++)
// logmdct[j]=todB(mdct+j) + .345f; /* + .345 is a hack; the original
// todB estimation used on IEEE 754
// compliant machines had a bug that
// returned dB values about a third
// of a decibel too high. The bug
// was harmless because tunings
// implicitly took that into
// account. However, fixing the bug
// in the estimator requires
// changing all the tunings as well.
// For now, it's easier to sync
// things back up here, and
// recalibrate the tunings in the
// next major model upgrade. */
//
//#if 0
// if(vi->channels==2){
// if(i==0)
// _analysis_output("mdctL",seq,logmdct,n/2,1,0,0);
// else
// _analysis_output("mdctR",seq,logmdct,n/2,1,0,0);
// }else{
// _analysis_output("mdct",seq,logmdct,n/2,1,0,0);
// }
//#endif
//
// /* first step; noise masking. Not only does 'noise masking'
// give us curves from which we can decide how much resolution
// to give noise parts of the spectrum, it also implicitly hands
// us a tonality estimate (the larger the value in the
// 'noise_depth' vector, the more tonal that area is) */
//
// _vp_noisemask(psy_look,
// logmdct,
// noise); /* noise does not have by-frequency offset
// bias applied yet */
//#if 0
// if(vi->channels==2){
// if(i==0)
// _analysis_output("noiseL",seq,noise,n/2,1,0,0);
// else
// _analysis_output("noiseR",seq,noise,n/2,1,0,0);
// }else{
// _analysis_output("noise",seq,noise,n/2,1,0,0);
// }
//#endif
//
// /* second step: 'all the other crap'; all the stuff that isn't
// computed/fit for bitrate management goes in the second psy
// vector. This includes tone masking, peak limiting and ATH */
//
// _vp_tonemask(psy_look,
// logfft,
// tone,
// global_ampmax,
// local_ampmax[i]);
//
//#if 0
// if(vi->channels==2){
// if(i==0)
// _analysis_output("toneL",seq,tone,n/2,1,0,0);
// else
// _analysis_output("toneR",seq,tone,n/2,1,0,0);
// }else{
// _analysis_output("tone",seq,tone,n/2,1,0,0);
// }
//#endif
//
// /* third step; we offset the noise vectors, overlay tone
// masking. We then do a floor1-specific line fit. If we're
// performing bitrate management, the line fit is performed
// multiple times for up/down tweakage on demand. */
//
//#if 0
// {
// float aotuv[psy_look->n];
//#endif
//
// _vp_offset_and_mix(psy_look,
// noise,
// tone,
// 1,
// logmask,
// mdct,
// logmdct);
//
//#if 0
// if(vi->channels==2){
// if(i==0)
// _analysis_output("aotuvM1_L",seq,aotuv,psy_look->n,1,1,0);
// else
// _analysis_output("aotuvM1_R",seq,aotuv,psy_look->n,1,1,0);
// }else{
// _analysis_output("aotuvM1",seq,aotuv,psy_look->n,1,1,0);
// }
// }
//#endif
//
//
//#if 0
// if(vi->channels==2){
// if(i==0)
// _analysis_output("mask1L",seq,logmask,n/2,1,0,0);
// else
// _analysis_output("mask1R",seq,logmask,n/2,1,0,0);
// }else{
// _analysis_output("mask1",seq,logmask,n/2,1,0,0);
// }
//#endif
//
// /* this algorithm is hardwired to floor 1 for now; abort out if
// we're *not* floor1. This won't happen unless someone has
// broken the encode setup lib. Guard it anyway. */
// if(ci->floor_type[info->floorsubmap[submap]]!=1)return(-1);
//
// floor_posts[i][PACKETBLOBS/2]=
// floor1_fit(context, vb,b->flr[info->floorsubmap[submap]],
// logmdct,
// logmask);
//
// /* are we managing bitrate? If so, perform two more fits for
// later rate tweaking (fits represent hi/lo) */
// if(FMOD_vorbis_bitrate_managed(vb) && floor_posts[i][PACKETBLOBS/2]){
// /* higher rate by way of lower noise curve */
//
// _vp_offset_and_mix(psy_look,
// noise,
// tone,
// 2,
// logmask,
// mdct,
// logmdct);
//
//#if 0
// if(vi->channels==2){
// if(i==0)
// _analysis_output("mask2L",seq,logmask,n/2,1,0,0);
// else
// _analysis_output("mask2R",seq,logmask,n/2,1,0,0);
// }else{
// _analysis_output("mask2",seq,logmask,n/2,1,0,0);
// }
//#endif
//
// floor_posts[i][PACKETBLOBS-1]=
// floor1_fit(context, vb,b->flr[info->floorsubmap[submap]],
// logmdct,
// logmask);
//
// /* lower rate by way of higher noise curve */
// _vp_offset_and_mix(psy_look,
// noise,
// tone,
// 0,
// logmask,
// mdct,
// logmdct);
//
//#if 0
// if(vi->channels==2){
// if(i==0)
// _analysis_output("mask0L",seq,logmask,n/2,1,0,0);
// else
// _analysis_output("mask0R",seq,logmask,n/2,1,0,0);
// }else{
// _analysis_output("mask0",seq,logmask,n/2,1,0,0);
// }
//#endif
//
// floor_posts[i][0]=
// floor1_fit(context, vb,b->flr[info->floorsubmap[submap]],
// logmdct,
// logmask);
//
// /* we also interpolate a range of intermediate curves for
// intermediate rates */
// for(k=1;k<PACKETBLOBS/2;k++)
// floor_posts[i][k]=
// floor1_interpolate_fit(context, vb,b->flr[info->floorsubmap[submap]],
// floor_posts[i][0],
// floor_posts[i][PACKETBLOBS/2],
// k*65536/(PACKETBLOBS/2));
// for(k=PACKETBLOBS/2+1;k<PACKETBLOBS-1;k++)
// floor_posts[i][k]=
// floor1_interpolate_fit(context, vb,b->flr[info->floorsubmap[submap]],
// floor_posts[i][PACKETBLOBS/2],
// floor_posts[i][PACKETBLOBS-1],
// (k-PACKETBLOBS/2)*65536/(PACKETBLOBS/2));
// }
// }
// }
// vbi->ampmax=global_ampmax;
//
// /*
// the next phases are performed once for vbr-only and PACKETBLOB
// times for bitrate managed modes.
//
// 1) encode actual mode being used
// 2) encode the floor for each channel, compute coded mask curve/res
// 3) normalize and couple.
// 4) encode residue
// 5) save packet bytes to the packetblob vector
//
// */
//
// /* iterate over the many masking curve fits we've created */
//
// {
// float **res_bundle=alloca(sizeof(*res_bundle)*vi->channels);
// float **couple_bundle=alloca(sizeof(*couple_bundle)*vi->channels);
// int *zerobundle=alloca(sizeof(*zerobundle)*vi->channels);
// int **sortindex=alloca(sizeof(*sortindex)*vi->channels);
// float **mag_memo=NULL;
// int **mag_sort=NULL;
//
// if(info->coupling_steps){
// mag_memo=_vp_quantize_couple_memo(context, vb,
// &ci->psy_g_param,
// psy_look,
// info,
// gmdct);
//
// mag_sort=_vp_quantize_couple_sort(context, vb,
// psy_look,
// info,
// mag_memo);
//
// hf_reduction(&ci->psy_g_param,
// psy_look,
// info,
// mag_memo);
// }
//
// FMOD_memset(sortindex,0,sizeof(*sortindex)*vi->channels);
// if(psy_look->vi->normal_channel_p){
// for(i=0;i<vi->channels;i++){
// float *mdct =gmdct[i];
// sortindex[i]=alloca(sizeof(**sortindex)*n/2);
// _vp_noise_normalize_sort(psy_look,mdct,sortindex[i]);
// }
// }
//
// for(k=(FMOD_vorbis_bitrate_managed(vb)?0:PACKETBLOBS/2);
// k<=(FMOD_vorbis_bitrate_managed(vb)?PACKETBLOBS-1:PACKETBLOBS/2);
// k++){
// oggpack_buffer *opb=vbi->packetblob[k];
//
// /* start out our new packet blob with packet type and mode */
// /* Encode the packet type */
// FMOD_oggpack_write(opb,0,1);
// /* Encode the modenumber */
// /* Encode frame mode, pre,post windowsize, then dispatch */
// FMOD_oggpack_write(opb,modenumber,b->modebits);
// if(vb->W){
// FMOD_oggpack_write(opb,vb->lW,1);
// FMOD_oggpack_write(opb,vb->nW,1);
// }
//
// /* encode floor, compute masking curve, sep out residue */
// for(i=0;i<vi->channels;i++){
// int submap=info->chmuxlist[i];
// float *mdct =gmdct[i];
// float *res =vb->pcm[i];
// int *ilogmask=ilogmaskch[i]=
// _FMOD_vorbis_block_alloc(context, vb,n/2*sizeof(**gmdct));
//
// nonzero[i]=floor1_encode(opb,vb,b->flr[info->floorsubmap[submap]],
// floor_posts[i][k],
// ilogmask);
//#if 0
// {
// char buf[80];
// sprintf(buf,"maskI%c%d",i?'R':'L',k);
// float work[n/2];
// for(j=0;j<n/2;j++)
// work[j]=FLOOR1_fromdB_LOOKUP[ilogmask[j]];
// _analysis_output(buf,seq,work,n/2,1,1,0);
// }
//#endif
// _vp_remove_floor(psy_look,
// mdct,
// ilogmask,
// res,
// ci->psy_g_param.sliding_lowpass[vb->W][k]);
//
// _vp_noise_normalize(psy_look,res,res+n/2,sortindex[i]);
//
//
//#if 0
// {
// char buf[80];
// float work[n/2];
// for(j=0;j<n/2;j++)
// work[j]=FLOOR1_fromdB_LOOKUP[ilogmask[j]]*(res+n/2)[j];
// sprintf(buf,"resI%c%d",i?'R':'L',k);
// _analysis_output(buf,seq,work,n/2,1,1,0);
//
// }
//#endif
// }
//
// /* our iteration is now based on masking curve, not prequant and
// coupling. Only one prequant/coupling step */
//
// /* quantize/couple */
// /* incomplete implementation that assumes the tree is all depth
// one, or no tree at all */
// if(info->coupling_steps){
// _vp_couple(k,
// &ci->psy_g_param,
// psy_look,
// info,
// vb->pcm,
// mag_memo,
// mag_sort,
// ilogmaskch,
// nonzero,
// ci->psy_g_param.sliding_lowpass[vb->W][k]);
// }
//
// /* classify and encode by submap */
// for(i=0;i<info->submaps;i++){
// int ch_in_bundle=0;
// ogg_int32_t **classifications;
// int resnum=info->residuesubmap[i];
//
// for(j=0;j<vi->channels;j++){
// if(info->chmuxlist[j]==i){
// zerobundle[ch_in_bundle]=0;
// if(nonzero[j])zerobundle[ch_in_bundle]=1;
// res_bundle[ch_in_bundle]=vb->pcm[j];
// couple_bundle[ch_in_bundle++]=vb->pcm[j]+n/2;
// }
// }
//
// classifications=_FMOD_residue_P[ci->residue_type[resnum]]->
// class(context, vb,b->residue[resnum],couple_bundle,zerobundle,ch_in_bundle);
//
// /* couple_bundle is destructively overwritten by
// the class function if some but not all of the channels are
// marked as silence; build a fresh copy */
// ch_in_bundle=0;
// for(j=0;j<vi->channels;j++)
// if(info->chmuxlist[j]==i)
// couple_bundle[ch_in_bundle++]=vb->pcm[j]+n/2;
//
// _FMOD_residue_P[ci->residue_type[resnum]]->
// forward(context, opb,vb,b->residue[resnum],
// couple_bundle,NULL,zerobundle,ch_in_bundle,classifications);
// }
//
// /* ok, done encoding. Next protopacket. */
// }
//
// }
//
//#if 0
// seq++;
// total+=ci->blocksizes[vb->W]/4+ci->blocksizes[vb->nW]/4;
//#endif
// return(0);
//}
static int mapping0_inverse(void *context, vorbis_block *vb,vorbis_info_mapping *l){
vorbis_dsp_state *vd=vb->vd;
vorbis_info *vi=vd->vi;
codec_setup_info *ci=vi->codec_setup;
private_state *b=vd->backend_state;
vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)l;
int i,j;
ogg_int32_t n=vb->pcmend=ci->blocksizes[vb->W];
float **pcmbundle=alloca(sizeof(*pcmbundle)*vi->channels);
int *zerobundle=alloca(sizeof(*zerobundle)*vi->channels);
int *nonzero =alloca(sizeof(*nonzero)*vi->channels);
void **floormemo=alloca(sizeof(*floormemo)*vi->channels);
/* recover the spectral envelope; store it in the PCM vector for now */
for(i=0;i<vi->channels;i++){
int submap=info->chmuxlist[i];
floormemo[i]=_FMOD_floor_P[ci->floor_type[info->floorsubmap[submap]]]->
inverse1(context, vb,b->flr[info->floorsubmap[submap]]);
if(floormemo[i])
nonzero[i]=1;
else
nonzero[i]=0;
FMOD_memset(vb->pcm[i],0,sizeof(*vb->pcm[i])*n/2);
}
/* channel coupling can 'dirty' the nonzero listing */
for(i=0;i<info->coupling_steps;i++){
if(nonzero[info->coupling_mag[i]] ||
nonzero[info->coupling_ang[i]]){
nonzero[info->coupling_mag[i]]=1;
nonzero[info->coupling_ang[i]]=1;
}
}
/* recover the residue into our working vectors */
for(i=0;i<info->submaps;i++){
int ch_in_bundle=0;
for(j=0;j<vi->channels;j++){
if(info->chmuxlist[j]==i){
if(nonzero[j])
zerobundle[ch_in_bundle]=1;
else
zerobundle[ch_in_bundle]=0;
pcmbundle[ch_in_bundle++]=vb->pcm[j];
}
}
_FMOD_residue_P[ci->residue_type[info->residuesubmap[i]]]->
inverse(context, vb,b->residue[info->residuesubmap[i]],
pcmbundle,zerobundle,ch_in_bundle);
}
/* channel coupling */
for(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(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
if(ang>0){
pcmM[j]=mag;
pcmA[j]=mag+ang;
}else{
pcmA[j]=mag;
pcmM[j]=mag-ang;
}
}
}
/* compute and apply spectral envelope */
for(i=0;i<vi->channels;i++){
float *pcm=vb->pcm[i];
int submap=info->chmuxlist[i];
_FMOD_floor_P[ci->floor_type[info->floorsubmap[submap]]]->
inverse2(context, vb,b->flr[info->floorsubmap[submap]],
floormemo[i],pcm);
}
/* transform the PCM data; takes PCM vector, vb; modifies PCM vector */
/* only MDCT right now.... */
for(i=0;i<vi->channels;i++){
float *pcm=vb->pcm[i];
FMOD_mdct_backward(b->transform[vb->W][0],pcm,pcm);
}
/* all done! */
return(0);
}
/* export hooks */
const vorbis_func_mapping FMOD_mapping0_exportbundle={
NULL, /* &mapping0_pack, */
&mapping0_unpack,
&mapping0_free_info,
NULL, /* &mapping0_forward, */
&mapping0_inverse
};

View file

@ -0,0 +1,785 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: masking curve data for psychoacoustics
last mod: $Id: masking.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
#ifndef _V_MASKING_H_
#define _V_MASKING_H_
/* more detailed ATH; the bass if flat to save stressing the floor
overly for only a bin or two of savings. */
#define MAX_ATH 88
static const float ATH[]={
/*15*/ -51, -52, -53, -54, -55, -56, -57, -58,
/*31*/ -59, -60, -61, -62, -63, -64, -65, -66,
/*63*/ -67, -68, -69, -70, -71, -72, -73, -74,
/*125*/ -75, -76, -77, -78, -80, -81, -82, -83,
/*250*/ -84, -85, -86, -87, -88, -88, -89, -89,
/*500*/ -90, -91, -91, -92, -93, -94, -95, -96,
/*1k*/ -96, -97, -98, -98, -99, -99,-100,-100,
/*2k*/ -101,-102,-103,-104,-106,-107,-107,-107,
/*4k*/ -107,-105,-103,-102,-101, -99, -98, -96,
/*8k*/ -95, -95, -96, -97, -96, -95, -93, -90,
/*16k*/ -80, -70, -50, -40, -30, -30, -30, -30
};
/* The tone masking curves from Ehmer's and Fielder's papers have been
replaced by an empirically collected data set. The previously
published values were, far too often, simply on crack. */
#define EHMER_OFFSET 16
#define EHMER_MAX 56
/* masking tones from -50 to 0dB, 62.5 through 16kHz at half octaves
test tones from -2 octaves to +5 octaves sampled at eighth octaves */
/* (Vorbis 0dB, the loudest possible tone, is assumed to be ~100dB SPL
for collection of these curves) */
static const float tonemasks[P_BANDS][6][EHMER_MAX]={
/* 62.5 Hz */
{{ -60, -60, -60, -60, -60, -60, -60, -60,
-60, -60, -60, -60, -62, -62, -65, -73,
-69, -68, -68, -67, -70, -70, -72, -74,
-75, -79, -79, -80, -83, -88, -93, -100,
-110, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{ -48, -48, -48, -48, -48, -48, -48, -48,
-48, -48, -48, -48, -48, -53, -61, -66,
-66, -68, -67, -70, -76, -76, -72, -73,
-75, -76, -78, -79, -83, -88, -93, -100,
-110, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{ -37, -37, -37, -37, -37, -37, -37, -37,
-38, -40, -42, -46, -48, -53, -55, -62,
-65, -58, -56, -56, -61, -60, -65, -67,
-69, -71, -77, -77, -78, -80, -82, -84,
-88, -93, -98, -106, -112, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{ -25, -25, -25, -25, -25, -25, -25, -25,
-25, -26, -27, -29, -32, -38, -48, -52,
-52, -50, -48, -48, -51, -52, -54, -60,
-67, -67, -66, -68, -69, -73, -73, -76,
-80, -81, -81, -85, -85, -86, -88, -93,
-100, -110, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{ -16, -16, -16, -16, -16, -16, -16, -16,
-17, -19, -20, -22, -26, -28, -31, -40,
-47, -39, -39, -40, -42, -43, -47, -51,
-57, -52, -55, -55, -60, -58, -62, -63,
-70, -67, -69, -72, -73, -77, -80, -82,
-83, -87, -90, -94, -98, -104, -115, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{ -8, -8, -8, -8, -8, -8, -8, -8,
-8, -8, -10, -11, -15, -19, -25, -30,
-34, -31, -30, -31, -29, -32, -35, -42,
-48, -42, -44, -46, -50, -50, -51, -52,
-59, -54, -55, -55, -58, -62, -63, -66,
-72, -73, -76, -75, -78, -80, -80, -81,
-84, -88, -90, -94, -98, -101, -106, -110}},
/* 88Hz */
{{ -66, -66, -66, -66, -66, -66, -66, -66,
-66, -66, -66, -66, -66, -67, -67, -67,
-76, -72, -71, -74, -76, -76, -75, -78,
-79, -79, -81, -83, -86, -89, -93, -97,
-100, -105, -110, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{ -47, -47, -47, -47, -47, -47, -47, -47,
-47, -47, -47, -48, -51, -55, -59, -66,
-66, -66, -67, -66, -68, -69, -70, -74,
-79, -77, -77, -78, -80, -81, -82, -84,
-86, -88, -91, -95, -100, -108, -116, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{ -36, -36, -36, -36, -36, -36, -36, -36,
-36, -37, -37, -41, -44, -48, -51, -58,
-62, -60, -57, -59, -59, -60, -63, -65,
-72, -71, -70, -72, -74, -77, -76, -78,
-81, -81, -80, -83, -86, -91, -96, -100,
-105, -110, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{ -28, -28, -28, -28, -28, -28, -28, -28,
-28, -30, -32, -32, -33, -35, -41, -49,
-50, -49, -47, -48, -48, -52, -51, -57,
-65, -61, -59, -61, -64, -69, -70, -74,
-77, -77, -78, -81, -84, -85, -87, -90,
-92, -96, -100, -107, -112, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{ -19, -19, -19, -19, -19, -19, -19, -19,
-20, -21, -23, -27, -30, -35, -36, -41,
-46, -44, -42, -40, -41, -41, -43, -48,
-55, -53, -52, -53, -56, -59, -58, -60,
-67, -66, -69, -71, -72, -75, -79, -81,
-84, -87, -90, -93, -97, -101, -107, -114,
-999, -999, -999, -999, -999, -999, -999, -999},
{ -9, -9, -9, -9, -9, -9, -9, -9,
-11, -12, -12, -15, -16, -20, -23, -30,
-37, -34, -33, -34, -31, -32, -32, -38,
-47, -44, -41, -40, -47, -49, -46, -46,
-58, -50, -50, -54, -58, -62, -64, -67,
-67, -70, -72, -76, -79, -83, -87, -91,
-96, -100, -104, -110, -999, -999, -999, -999}},
/* 125 Hz */
{{ -62, -62, -62, -62, -62, -62, -62, -62,
-62, -62, -63, -64, -66, -67, -66, -68,
-75, -72, -76, -75, -76, -78, -79, -82,
-84, -85, -90, -94, -101, -110, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{ -59, -59, -59, -59, -59, -59, -59, -59,
-59, -59, -59, -60, -60, -61, -63, -66,
-71, -68, -70, -70, -71, -72, -72, -75,
-81, -78, -79, -82, -83, -86, -90, -97,
-103, -113, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{ -53, -53, -53, -53, -53, -53, -53, -53,
-53, -54, -55, -57, -56, -57, -55, -61,
-65, -60, -60, -62, -63, -63, -66, -68,
-74, -73, -75, -75, -78, -80, -80, -82,
-85, -90, -96, -101, -108, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{ -46, -46, -46, -46, -46, -46, -46, -46,
-46, -46, -47, -47, -47, -47, -48, -51,
-57, -51, -49, -50, -51, -53, -54, -59,
-66, -60, -62, -67, -67, -70, -72, -75,
-76, -78, -81, -85, -88, -94, -97, -104,
-112, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{ -36, -36, -36, -36, -36, -36, -36, -36,
-39, -41, -42, -42, -39, -38, -41, -43,
-52, -44, -40, -39, -37, -37, -40, -47,
-54, -50, -48, -50, -55, -61, -59, -62,
-66, -66, -66, -69, -69, -73, -74, -74,
-75, -77, -79, -82, -87, -91, -95, -100,
-108, -115, -999, -999, -999, -999, -999, -999},
{ -28, -26, -24, -22, -20, -20, -23, -29,
-30, -31, -28, -27, -28, -28, -28, -35,
-40, -33, -32, -29, -30, -30, -30, -37,
-45, -41, -37, -38, -45, -47, -47, -48,
-53, -49, -48, -50, -49, -49, -51, -52,
-58, -56, -57, -56, -60, -61, -62, -70,
-72, -74, -78, -83, -88, -93, -100, -106}},
/* 177 Hz */
{{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -110, -105, -100, -95, -91, -87, -83,
-80, -78, -76, -78, -78, -81, -83, -85,
-86, -85, -86, -87, -90, -97, -107, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -110, -105, -100, -95, -90,
-85, -81, -77, -73, -70, -67, -67, -68,
-75, -73, -70, -69, -70, -72, -75, -79,
-84, -83, -84, -86, -88, -89, -89, -93,
-98, -105, -112, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-105, -100, -95, -90, -85, -80, -76, -71,
-68, -68, -65, -63, -63, -62, -62, -64,
-65, -64, -61, -62, -63, -64, -66, -68,
-73, -73, -74, -75, -76, -81, -83, -85,
-88, -89, -92, -95, -100, -108, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{ -80, -75, -71, -68, -65, -63, -62, -61,
-61, -61, -61, -59, -56, -57, -53, -50,
-58, -52, -50, -50, -52, -53, -54, -58,
-67, -63, -67, -68, -72, -75, -78, -80,
-81, -81, -82, -85, -89, -90, -93, -97,
-101, -107, -114, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{ -65, -61, -59, -57, -56, -55, -55, -56,
-56, -57, -55, -53, -52, -47, -44, -44,
-50, -44, -41, -39, -39, -42, -40, -46,
-51, -49, -50, -53, -54, -63, -60, -61,
-62, -66, -66, -66, -70, -73, -74, -75,
-76, -75, -79, -85, -89, -91, -96, -102,
-110, -999, -999, -999, -999, -999, -999, -999},
{ -52, -50, -49, -49, -48, -48, -48, -49,
-50, -50, -49, -46, -43, -39, -35, -33,
-38, -36, -32, -29, -32, -32, -32, -35,
-44, -39, -38, -38, -46, -50, -45, -46,
-53, -50, -50, -50, -54, -54, -53, -53,
-56, -57, -59, -66, -70, -72, -74, -79,
-83, -85, -90, -97, -114, -999, -999, -999}},
/* 250 Hz */
{{-999, -999, -999, -999, -999, -999, -110, -105,
-100, -95, -90, -86, -80, -75, -75, -79,
-80, -79, -80, -81, -82, -88, -95, -103,
-110, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -108, -103, -98, -93,
-88, -83, -79, -78, -75, -71, -67, -68,
-73, -73, -72, -73, -75, -77, -80, -82,
-88, -93, -100, -107, -114, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -110, -105, -101, -96, -90,
-86, -81, -77, -73, -69, -66, -61, -62,
-66, -64, -62, -65, -66, -70, -72, -76,
-81, -80, -84, -90, -95, -102, -110, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -107, -103, -97, -92, -88,
-83, -79, -74, -70, -66, -59, -53, -58,
-62, -55, -54, -54, -54, -58, -61, -62,
-72, -70, -72, -75, -78, -80, -81, -80,
-83, -83, -88, -93, -100, -107, -115, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -105, -100, -95, -90, -85,
-80, -75, -70, -66, -62, -56, -48, -44,
-48, -46, -46, -43, -46, -48, -48, -51,
-58, -58, -59, -60, -62, -62, -61, -61,
-65, -64, -65, -68, -70, -74, -75, -78,
-81, -86, -95, -110, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -105, -100, -95, -90, -85, -80,
-75, -70, -65, -61, -55, -49, -39, -33,
-40, -35, -32, -38, -40, -33, -35, -37,
-46, -41, -45, -44, -46, -42, -45, -46,
-52, -50, -50, -50, -54, -54, -55, -57,
-62, -64, -66, -68, -70, -76, -81, -90,
-100, -110, -999, -999, -999, -999, -999, -999}},
/* 354 hz */
{{-999, -999, -999, -999, -999, -999, -999, -999,
-105, -98, -90, -85, -82, -83, -80, -78,
-84, -79, -80, -83, -87, -89, -91, -93,
-99, -106, -117, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-105, -98, -90, -85, -80, -75, -70, -68,
-74, -72, -74, -77, -80, -82, -85, -87,
-92, -89, -91, -95, -100, -106, -112, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-105, -98, -90, -83, -75, -71, -63, -64,
-67, -62, -64, -67, -70, -73, -77, -81,
-84, -83, -85, -89, -90, -93, -98, -104,
-109, -114, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-103, -96, -88, -81, -75, -68, -58, -54,
-56, -54, -56, -56, -58, -60, -63, -66,
-74, -69, -72, -72, -75, -74, -77, -81,
-81, -82, -84, -87, -93, -96, -99, -104,
-110, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -108, -102, -96,
-91, -85, -80, -74, -68, -60, -51, -46,
-48, -46, -43, -45, -47, -47, -49, -48,
-56, -53, -55, -58, -57, -63, -58, -60,
-66, -64, -67, -70, -70, -74, -77, -84,
-86, -89, -91, -93, -94, -101, -109, -118,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -108, -103, -98, -93, -88,
-83, -78, -73, -68, -60, -53, -44, -35,
-38, -38, -34, -34, -36, -40, -41, -44,
-51, -45, -46, -47, -46, -54, -50, -49,
-50, -50, -50, -51, -54, -57, -58, -60,
-66, -66, -66, -64, -65, -68, -77, -82,
-87, -95, -110, -999, -999, -999, -999, -999}},
/* 500 Hz */
{{-999, -999, -999, -999, -999, -999, -999, -999,
-107, -102, -97, -92, -87, -83, -78, -75,
-82, -79, -83, -85, -89, -92, -95, -98,
-101, -105, -109, -113, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -106,
-100, -95, -90, -86, -81, -78, -74, -69,
-74, -74, -76, -79, -83, -84, -86, -89,
-92, -97, -93, -100, -103, -107, -110, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -106, -100,
-95, -90, -87, -83, -80, -75, -69, -60,
-66, -66, -68, -70, -74, -78, -79, -81,
-81, -83, -84, -87, -93, -96, -99, -103,
-107, -110, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -108, -103, -98,
-93, -89, -85, -82, -78, -71, -62, -55,
-58, -58, -54, -54, -55, -59, -61, -62,
-70, -66, -66, -67, -70, -72, -75, -78,
-84, -84, -84, -88, -91, -90, -95, -98,
-102, -103, -106, -110, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -108, -103, -98, -94,
-90, -87, -82, -79, -73, -67, -58, -47,
-50, -45, -41, -45, -48, -44, -44, -49,
-54, -51, -48, -47, -49, -50, -51, -57,
-58, -60, -63, -69, -70, -69, -71, -74,
-78, -82, -90, -95, -101, -105, -110, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -105, -101, -97, -93, -90,
-85, -80, -77, -72, -65, -56, -48, -37,
-40, -36, -34, -40, -50, -47, -38, -41,
-47, -38, -35, -39, -38, -43, -40, -45,
-50, -45, -44, -47, -50, -55, -48, -48,
-52, -66, -70, -76, -82, -90, -97, -105,
-110, -999, -999, -999, -999, -999, -999, -999}},
/* 707 Hz */
{{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -108, -103, -98, -93, -86, -79, -76,
-83, -81, -85, -87, -89, -93, -98, -102,
-107, -112, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -108, -103, -98, -93, -86, -79, -71,
-77, -74, -77, -79, -81, -84, -85, -90,
-92, -93, -92, -98, -101, -108, -112, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-108, -103, -98, -93, -87, -78, -68, -65,
-66, -62, -65, -67, -70, -73, -75, -78,
-82, -82, -83, -84, -91, -93, -98, -102,
-106, -110, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-105, -100, -95, -90, -82, -74, -62, -57,
-58, -56, -51, -52, -52, -54, -54, -58,
-66, -59, -60, -63, -66, -69, -73, -79,
-83, -84, -80, -81, -81, -82, -88, -92,
-98, -105, -113, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -107,
-102, -97, -92, -84, -79, -69, -57, -47,
-52, -47, -44, -45, -50, -52, -42, -42,
-53, -43, -43, -48, -51, -56, -55, -52,
-57, -59, -61, -62, -67, -71, -78, -83,
-86, -94, -98, -103, -110, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -105, -100,
-95, -90, -84, -78, -70, -61, -51, -41,
-40, -38, -40, -46, -52, -51, -41, -40,
-46, -40, -38, -38, -41, -46, -41, -46,
-47, -43, -43, -45, -41, -45, -56, -67,
-68, -83, -87, -90, -95, -102, -107, -113,
-999, -999, -999, -999, -999, -999, -999, -999}},
/* 1000 Hz */
{{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -109, -105, -101, -96, -91, -84, -77,
-82, -82, -85, -89, -94, -100, -106, -110,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -106, -103, -98, -92, -85, -80, -71,
-75, -72, -76, -80, -84, -86, -89, -93,
-100, -107, -113, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -107,
-104, -101, -97, -92, -88, -84, -80, -64,
-66, -63, -64, -66, -69, -73, -77, -83,
-83, -86, -91, -98, -104, -111, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -107,
-104, -101, -97, -92, -90, -84, -74, -57,
-58, -52, -55, -54, -50, -52, -50, -52,
-63, -62, -69, -76, -77, -78, -78, -79,
-82, -88, -94, -100, -106, -111, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -106, -102,
-98, -95, -90, -85, -83, -78, -70, -50,
-50, -41, -44, -49, -47, -50, -50, -44,
-55, -46, -47, -48, -48, -54, -49, -49,
-58, -62, -71, -81, -87, -92, -97, -102,
-108, -114, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -106, -102,
-98, -95, -90, -85, -83, -78, -70, -45,
-43, -41, -47, -50, -51, -50, -49, -45,
-47, -41, -44, -41, -39, -43, -38, -37,
-40, -41, -44, -50, -58, -65, -73, -79,
-85, -92, -97, -101, -105, -109, -113, -999,
-999, -999, -999, -999, -999, -999, -999, -999}},
/* 1414 Hz */
{{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -107, -100, -95, -87, -81,
-85, -83, -88, -93, -100, -107, -114, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -107, -101, -95, -88, -83, -76,
-73, -72, -79, -84, -90, -95, -100, -105,
-110, -115, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -104, -98, -92, -87, -81, -70,
-65, -62, -67, -71, -74, -80, -85, -91,
-95, -99, -103, -108, -111, -114, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -103, -97, -90, -85, -76, -60,
-56, -54, -60, -62, -61, -56, -63, -65,
-73, -74, -77, -75, -78, -81, -86, -87,
-88, -91, -94, -98, -103, -110, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -105,
-100, -97, -92, -86, -81, -79, -70, -57,
-51, -47, -51, -58, -60, -56, -53, -50,
-58, -52, -50, -50, -53, -55, -64, -69,
-71, -85, -82, -78, -81, -85, -95, -102,
-112, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -105,
-100, -97, -92, -85, -83, -79, -72, -49,
-40, -43, -43, -54, -56, -51, -50, -40,
-43, -38, -36, -35, -37, -38, -37, -44,
-54, -60, -57, -60, -70, -75, -84, -92,
-103, -112, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999}},
/* 2000 Hz */
{{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -110, -102, -95, -89, -82,
-83, -84, -90, -92, -99, -107, -113, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -107, -101, -95, -89, -83, -72,
-74, -78, -85, -88, -88, -90, -92, -98,
-105, -111, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -109, -103, -97, -93, -87, -81, -70,
-70, -67, -75, -73, -76, -79, -81, -83,
-88, -89, -97, -103, -110, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -107, -100, -94, -88, -83, -75, -63,
-59, -59, -63, -66, -60, -62, -67, -67,
-77, -76, -81, -88, -86, -92, -96, -102,
-109, -116, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -105, -98, -92, -86, -81, -73, -56,
-52, -47, -55, -60, -58, -52, -51, -45,
-49, -50, -53, -54, -61, -71, -70, -69,
-78, -79, -87, -90, -96, -104, -112, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -103, -96, -90, -86, -78, -70, -51,
-42, -47, -48, -55, -54, -54, -53, -42,
-35, -28, -33, -38, -37, -44, -47, -49,
-54, -63, -68, -78, -82, -89, -94, -99,
-104, -109, -114, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999}},
/* 2828 Hz */
{{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -110, -100, -90, -79,
-85, -81, -82, -82, -89, -94, -99, -103,
-109, -115, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -105, -97, -85, -72,
-74, -70, -70, -70, -76, -85, -91, -93,
-97, -103, -109, -115, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -112, -93, -81, -68,
-62, -60, -60, -57, -63, -70, -77, -82,
-90, -93, -98, -104, -109, -113, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -113, -100, -93, -84, -63,
-58, -48, -53, -54, -52, -52, -57, -64,
-66, -76, -83, -81, -85, -85, -90, -95,
-98, -101, -103, -106, -108, -111, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -105, -95, -86, -74, -53,
-50, -38, -43, -49, -43, -42, -39, -39,
-46, -52, -57, -56, -72, -69, -74, -81,
-87, -92, -94, -97, -99, -102, -105, -108,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -108, -99, -90, -76, -66, -45,
-43, -41, -44, -47, -43, -47, -40, -30,
-31, -31, -39, -33, -40, -41, -43, -53,
-59, -70, -73, -77, -79, -82, -84, -87,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999}},
/* 4000 Hz */
{{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -110, -91, -76,
-75, -85, -93, -98, -104, -110, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -110, -91, -70,
-70, -75, -86, -89, -94, -98, -101, -106,
-110, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -110, -95, -80, -60,
-65, -64, -74, -83, -88, -91, -95, -99,
-103, -107, -110, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -110, -95, -80, -58,
-55, -49, -66, -68, -71, -78, -78, -80,
-88, -85, -89, -97, -100, -105, -110, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -110, -95, -80, -53,
-52, -41, -59, -59, -49, -58, -56, -63,
-86, -79, -90, -93, -98, -103, -107, -112,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -110, -97, -91, -73, -45,
-40, -33, -53, -61, -49, -54, -50, -50,
-60, -52, -67, -74, -81, -92, -96, -100,
-105, -110, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999}},
/* 5657 Hz */
{{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -113, -106, -99, -92, -77,
-80, -88, -97, -106, -115, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -116, -109, -102, -95, -89, -74,
-72, -88, -87, -95, -102, -109, -116, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -116, -109, -102, -95, -89, -75,
-66, -74, -77, -78, -86, -87, -90, -96,
-105, -115, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -115, -108, -101, -94, -88, -66,
-56, -61, -70, -65, -78, -72, -83, -84,
-93, -98, -105, -110, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -110, -105, -95, -89, -82, -57,
-52, -52, -59, -56, -59, -58, -69, -67,
-88, -82, -82, -89, -94, -100, -108, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -110, -101, -96, -90, -83, -77, -54,
-43, -38, -50, -48, -52, -48, -42, -42,
-51, -52, -53, -59, -65, -71, -78, -85,
-95, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999}},
/* 8000 Hz */
{{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -120, -105, -86, -68,
-78, -79, -90, -100, -110, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -120, -105, -86, -66,
-73, -77, -88, -96, -105, -115, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -120, -105, -92, -80, -61,
-64, -68, -80, -87, -92, -100, -110, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -120, -104, -91, -79, -52,
-60, -54, -64, -69, -77, -80, -82, -84,
-85, -87, -88, -90, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -118, -100, -87, -77, -49,
-50, -44, -58, -61, -61, -67, -65, -62,
-62, -62, -65, -68, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -115, -98, -84, -62, -49,
-44, -38, -46, -49, -49, -46, -39, -37,
-39, -40, -42, -43, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999}},
/* 11314 Hz */
{{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -110, -88, -74,
-77, -82, -82, -85, -90, -94, -99, -104,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -110, -88, -66,
-70, -81, -80, -81, -84, -88, -91, -93,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -110, -88, -61,
-63, -70, -71, -74, -77, -80, -83, -85,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -110, -86, -62,
-63, -62, -62, -58, -52, -50, -50, -52,
-54, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -118, -108, -84, -53,
-50, -50, -50, -55, -47, -45, -40, -40,
-40, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -118, -100, -73, -43,
-37, -42, -43, -53, -38, -37, -35, -35,
-38, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999}},
/* 16000 Hz */
{{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -110, -100, -91, -84, -74,
-80, -80, -80, -80, -80, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -110, -100, -91, -84, -74,
-68, -68, -68, -68, -68, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -110, -100, -86, -78, -70,
-60, -45, -30, -21, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -110, -100, -87, -78, -67,
-48, -38, -29, -21, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -110, -100, -86, -69, -56,
-45, -35, -33, -29, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999},
{-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -110, -100, -83, -71, -48,
-27, -38, -37, -34, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999,
-999, -999, -999, -999, -999, -999, -999, -999}}
};
#endif

570
lib/ogg_vorbis/vorbis/lib/mdct.c Executable file
View file

@ -0,0 +1,570 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: normalized modified discrete cosine transform
power of two length transform only [64 <= n ]
last mod: $Id: mdct.c 16227 2009-07-08 06:58:46Z xiphmont $
Original algorithm adapted long ago from _The use of multirate filter
banks for coding of high quality digital audio_, by T. Sporer,
K. Brandenburg and B. Edler, collection of the European Signal
Processing Conference (EUSIPCO), Amsterdam, June 1992, Vol.1, pp
211-214
The below code implements an algorithm that no longer looks much like
that presented in the paper, but the basic structure remains if you
dig deep enough to see it.
This module DOES NOT INCLUDE code to generate/apply the window
function. Everybody has their own weird favorite including me... I
happen to like the properties of y=sin(.5PI*sin^2(x)), but others may
vehemently disagree.
********************************************************************/
/* this can also be run as an integer transform by uncommenting a
define in mdct.h; the integerization is a first pass and although
it's likely stable for Vorbis, the dynamic range is constrained and
roundoff isn't done (so it's noisy). Consider it functional, but
only a starting point. There's no point on a machine with an FPU */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "vorbis/codec.h"
#include "mdct.h"
#include "os.h"
#include "misc.h"
/* build lookups for trig functions; also pre-figure scaling and
some window function algebra. */
int FMOD_mdct_init(void *context, mdct_lookup *lookup,int n){
int *bitrev=_ogg_malloc(sizeof(*bitrev)*(n/4));
DATA_TYPE *T=_ogg_malloc(sizeof(*T)*(n+n/4));
int i;
int n2=n>>1;
int log2n=lookup->log2n=(int)(FMOD_ogg_rint(FMOD_ogg_log((float)n)/FMOD_ogg_log(2.f)));
if (!bitrev || !T)
{
return(OV_EMEMORY);
}
lookup->n=n;
lookup->trig=T;
lookup->bitrev=bitrev;
/* trig lookups... */
for(i=0;i<n/4;i++){
T[i*2]=FLOAT_CONV(FMOD_ogg_cos((M_PI/n)*(4*i)));
T[i*2+1]=FLOAT_CONV(-FMOD_ogg_sin((M_PI/n)*(4*i)));
T[n2+i*2]=FLOAT_CONV(FMOD_ogg_cos((M_PI/(2*n))*(2*i+1)));
T[n2+i*2+1]=FLOAT_CONV(FMOD_ogg_sin((M_PI/(2*n))*(2*i+1)));
}
for(i=0;i<n/8;i++){
T[n+i*2]=FLOAT_CONV(FMOD_ogg_cos((M_PI/n)*(4*i+2))*.5f);
T[n+i*2+1]=FLOAT_CONV(-FMOD_ogg_sin((M_PI/n)*(4*i+2))*.5f);
}
/* bitreverse lookup... */
{
int mask=(1<<(log2n-1))-1,i,j;
int msb=1<<(log2n-2);
for(i=0;i<n/8;i++){
int acc=0;
for(j=0;msb>>j;j++)
if((msb>>j)&i)acc|=1<<j;
bitrev[i*2]=((~acc)&mask)-1;
bitrev[i*2+1]=acc;
}
}
lookup->scale=FLOAT_CONV(4.f/n);
return 0;
}
/* 8 point butterfly (in place, 4 register) */
STIN void mdct_butterfly_8(DATA_TYPE *x){
REG_TYPE r0 = x[6] + x[2];
REG_TYPE r1 = x[6] - x[2];
REG_TYPE r2 = x[4] + x[0];
REG_TYPE r3 = x[4] - x[0];
x[6] = r0 + r2;
x[4] = r0 - r2;
r0 = x[5] - x[1];
r2 = x[7] - x[3];
x[0] = r1 + r0;
x[2] = r1 - r0;
r0 = x[5] + x[1];
r1 = x[7] + x[3];
x[3] = r2 + r3;
x[1] = r2 - r3;
x[7] = r1 + r0;
x[5] = r1 - r0;
}
/* 16 point butterfly (in place, 4 register) */
STIN void mdct_butterfly_16(DATA_TYPE *x){
REG_TYPE r0 = x[1] - x[9];
REG_TYPE r1 = x[0] - x[8];
x[8] += x[0];
x[9] += x[1];
x[0] = MULT_NORM((r0 + r1) * cPI2_8);
x[1] = MULT_NORM((r0 - r1) * cPI2_8);
r0 = x[3] - x[11];
r1 = x[10] - x[2];
x[10] += x[2];
x[11] += x[3];
x[2] = r0;
x[3] = r1;
r0 = x[12] - x[4];
r1 = x[13] - x[5];
x[12] += x[4];
x[13] += x[5];
x[4] = MULT_NORM((r0 - r1) * cPI2_8);
x[5] = MULT_NORM((r0 + r1) * cPI2_8);
r0 = x[14] - x[6];
r1 = x[15] - x[7];
x[14] += x[6];
x[15] += x[7];
x[6] = r0;
x[7] = r1;
mdct_butterfly_8(x);
mdct_butterfly_8(x+8);
}
/* 32 point butterfly (in place, 4 register) */
STIN void mdct_butterfly_32(DATA_TYPE *x){
REG_TYPE r0 = x[30] - x[14];
REG_TYPE r1 = x[31] - x[15];
x[30] += x[14];
x[31] += x[15];
x[14] = r0;
x[15] = r1;
r0 = x[28] - x[12];
r1 = x[29] - x[13];
x[28] += x[12];
x[29] += x[13];
x[12] = MULT_NORM( r0 * cPI1_8 - r1 * cPI3_8 );
x[13] = MULT_NORM( r0 * cPI3_8 + r1 * cPI1_8 );
r0 = x[26] - x[10];
r1 = x[27] - x[11];
x[26] += x[10];
x[27] += x[11];
x[10] = MULT_NORM(( r0 - r1 ) * cPI2_8);
x[11] = MULT_NORM(( r0 + r1 ) * cPI2_8);
r0 = x[24] - x[8];
r1 = x[25] - x[9];
x[24] += x[8];
x[25] += x[9];
x[8] = MULT_NORM( r0 * cPI3_8 - r1 * cPI1_8 );
x[9] = MULT_NORM( r1 * cPI3_8 + r0 * cPI1_8 );
r0 = x[22] - x[6];
r1 = x[7] - x[23];
x[22] += x[6];
x[23] += x[7];
x[6] = r1;
x[7] = r0;
r0 = x[4] - x[20];
r1 = x[5] - x[21];
x[20] += x[4];
x[21] += x[5];
x[4] = MULT_NORM( r1 * cPI1_8 + r0 * cPI3_8 );
x[5] = MULT_NORM( r1 * cPI3_8 - r0 * cPI1_8 );
r0 = x[2] - x[18];
r1 = x[3] - x[19];
x[18] += x[2];
x[19] += x[3];
x[2] = MULT_NORM(( r1 + r0 ) * cPI2_8);
x[3] = MULT_NORM(( r1 - r0 ) * cPI2_8);
r0 = x[0] - x[16];
r1 = x[1] - x[17];
x[16] += x[0];
x[17] += x[1];
x[0] = MULT_NORM( r1 * cPI3_8 + r0 * cPI1_8 );
x[1] = MULT_NORM( r1 * cPI1_8 - r0 * cPI3_8 );
mdct_butterfly_16(x);
mdct_butterfly_16(x+16);
}
/* N point first stage butterfly (in place, 2 register) */
STIN void mdct_butterfly_first(DATA_TYPE *T,
DATA_TYPE *x,
int points){
DATA_TYPE *x1 = x + points - 8;
DATA_TYPE *x2 = x + (points>>1) - 8;
REG_TYPE r0;
REG_TYPE r1;
do{
r0 = x1[6] - x2[6];
r1 = x1[7] - x2[7];
x1[6] += x2[6];
x1[7] += x2[7];
x2[6] = MULT_NORM(r1 * T[1] + r0 * T[0]);
x2[7] = MULT_NORM(r1 * T[0] - r0 * T[1]);
r0 = x1[4] - x2[4];
r1 = x1[5] - x2[5];
x1[4] += x2[4];
x1[5] += x2[5];
x2[4] = MULT_NORM(r1 * T[5] + r0 * T[4]);
x2[5] = MULT_NORM(r1 * T[4] - r0 * T[5]);
r0 = x1[2] - x2[2];
r1 = x1[3] - x2[3];
x1[2] += x2[2];
x1[3] += x2[3];
x2[2] = MULT_NORM(r1 * T[9] + r0 * T[8]);
x2[3] = MULT_NORM(r1 * T[8] - r0 * T[9]);
r0 = x1[0] - x2[0];
r1 = x1[1] - x2[1];
x1[0] += x2[0];
x1[1] += x2[1];
x2[0] = MULT_NORM(r1 * T[13] + r0 * T[12]);
x2[1] = MULT_NORM(r1 * T[12] - r0 * T[13]);
x1-=8;
x2-=8;
T+=16;
}while(x2>=x);
}
/* N/stage point generic N stage butterfly (in place, 2 register) */
STIN void mdct_butterfly_generic(DATA_TYPE *T,
DATA_TYPE *x,
int points,
int trigint){
DATA_TYPE *x1 = x + points - 8;
DATA_TYPE *x2 = x + (points>>1) - 8;
REG_TYPE r0;
REG_TYPE r1;
do{
r0 = x1[6] - x2[6];
r1 = x1[7] - x2[7];
x1[6] += x2[6];
x1[7] += x2[7];
x2[6] = MULT_NORM(r1 * T[1] + r0 * T[0]);
x2[7] = MULT_NORM(r1 * T[0] - r0 * T[1]);
T+=trigint;
r0 = x1[4] - x2[4];
r1 = x1[5] - x2[5];
x1[4] += x2[4];
x1[5] += x2[5];
x2[4] = MULT_NORM(r1 * T[1] + r0 * T[0]);
x2[5] = MULT_NORM(r1 * T[0] - r0 * T[1]);
T+=trigint;
r0 = x1[2] - x2[2];
r1 = x1[3] - x2[3];
x1[2] += x2[2];
x1[3] += x2[3];
x2[2] = MULT_NORM(r1 * T[1] + r0 * T[0]);
x2[3] = MULT_NORM(r1 * T[0] - r0 * T[1]);
T+=trigint;
r0 = x1[0] - x2[0];
r1 = x1[1] - x2[1];
x1[0] += x2[0];
x1[1] += x2[1];
x2[0] = MULT_NORM(r1 * T[1] + r0 * T[0]);
x2[1] = MULT_NORM(r1 * T[0] - r0 * T[1]);
T+=trigint;
x1-=8;
x2-=8;
}while(x2>=x);
}
STIN void mdct_butterflies(mdct_lookup *init,
DATA_TYPE *x,
int points){
DATA_TYPE *T=init->trig;
int stages=init->log2n-5;
int i,j;
if(--stages>0){
mdct_butterfly_first(T,x,points);
}
for(i=1;--stages>0;i++){
for(j=0;j<(1<<i);j++)
mdct_butterfly_generic(T,x+(points>>i)*j,points>>i,4<<i);
}
for(j=0;j<points;j+=32)
mdct_butterfly_32(x+j);
}
void FMOD_mdct_clear(void *context, mdct_lookup *l){
if(l){
if(l->trig)_ogg_free(l->trig);
if(l->bitrev)_ogg_free(l->bitrev);
FMOD_memset(l,0,sizeof(*l));
}
}
STIN void mdct_bitreverse(mdct_lookup *init,
DATA_TYPE *x){
int n = init->n;
int *bit = init->bitrev;
DATA_TYPE *w0 = x;
DATA_TYPE *w1 = x = w0+(n>>1);
DATA_TYPE *T = init->trig+n;
do{
DATA_TYPE *x0 = x+bit[0];
DATA_TYPE *x1 = x+bit[1];
REG_TYPE r0 = x0[1] - x1[1];
REG_TYPE r1 = x0[0] + x1[0];
REG_TYPE r2 = MULT_NORM(r1 * T[0] + r0 * T[1]);
REG_TYPE r3 = MULT_NORM(r1 * T[1] - r0 * T[0]);
w1 -= 4;
r0 = HALVE(x0[1] + x1[1]);
r1 = HALVE(x0[0] - x1[0]);
w0[0] = r0 + r2;
w1[2] = r0 - r2;
w0[1] = r1 + r3;
w1[3] = r3 - r1;
x0 = x+bit[2];
x1 = x+bit[3];
r0 = x0[1] - x1[1];
r1 = x0[0] + x1[0];
r2 = MULT_NORM(r1 * T[2] + r0 * T[3]);
r3 = MULT_NORM(r1 * T[3] - r0 * T[2]);
r0 = HALVE(x0[1] + x1[1]);
r1 = HALVE(x0[0] - x1[0]);
w0[2] = r0 + r2;
w1[0] = r0 - r2;
w0[3] = r1 + r3;
w1[1] = r3 - r1;
T += 4;
bit += 4;
w0 += 4;
}while(w0<w1);
}
void FMOD_mdct_backward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out){
int n=init->n;
int n2=n>>1;
int n4=n>>2;
/* rotate */
DATA_TYPE *iX = in+n2-7;
DATA_TYPE *oX = out+n2+n4;
DATA_TYPE *T = init->trig+n4;
do{
oX -= 4;
oX[0] = MULT_NORM(-iX[2] * T[3] - iX[0] * T[2]);
oX[1] = MULT_NORM (iX[0] * T[3] - iX[2] * T[2]);
oX[2] = MULT_NORM(-iX[6] * T[1] - iX[4] * T[0]);
oX[3] = MULT_NORM (iX[4] * T[1] - iX[6] * T[0]);
iX -= 8;
T += 4;
}while(iX>=in);
iX = in+n2-8;
oX = out+n2+n4;
T = init->trig+n4;
do{
T -= 4;
oX[0] = MULT_NORM (iX[4] * T[3] + iX[6] * T[2]);
oX[1] = MULT_NORM (iX[4] * T[2] - iX[6] * T[3]);
oX[2] = MULT_NORM (iX[0] * T[1] + iX[2] * T[0]);
oX[3] = MULT_NORM (iX[0] * T[0] - iX[2] * T[1]);
iX -= 8;
oX += 4;
}while(iX>=in);
mdct_butterflies(init,out+n2,n2);
mdct_bitreverse(init,out);
/* roatate + window */
{
DATA_TYPE *oX1=out+n2+n4;
DATA_TYPE *oX2=out+n2+n4;
DATA_TYPE *iX =out;
T =init->trig+n2;
do{
oX1-=4;
oX1[3] = MULT_NORM (iX[0] * T[1] - iX[1] * T[0]);
oX2[0] = -MULT_NORM (iX[0] * T[0] + iX[1] * T[1]);
oX1[2] = MULT_NORM (iX[2] * T[3] - iX[3] * T[2]);
oX2[1] = -MULT_NORM (iX[2] * T[2] + iX[3] * T[3]);
oX1[1] = MULT_NORM (iX[4] * T[5] - iX[5] * T[4]);
oX2[2] = -MULT_NORM (iX[4] * T[4] + iX[5] * T[5]);
oX1[0] = MULT_NORM (iX[6] * T[7] - iX[7] * T[6]);
oX2[3] = -MULT_NORM (iX[6] * T[6] + iX[7] * T[7]);
oX2+=4;
iX += 8;
T += 8;
}while(iX<oX1);
iX=out+n2+n4;
oX1=out+n4;
oX2=oX1;
do{
oX1-=4;
iX-=4;
oX2[0] = -(oX1[3] = iX[3]);
oX2[1] = -(oX1[2] = iX[2]);
oX2[2] = -(oX1[1] = iX[1]);
oX2[3] = -(oX1[0] = iX[0]);
oX2+=4;
}while(oX2<iX);
iX=out+n2+n4;
oX1=out+n2+n4;
oX2=out+n2;
do{
oX1-=4;
oX1[0]= iX[3];
oX1[1]= iX[2];
oX1[2]= iX[1];
oX1[3]= iX[0];
iX+=4;
}while(oX1>oX2);
}
}
void FMOD_mdct_forward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out){
int n=init->n;
int n2=n>>1;
int n4=n>>2;
int n8=n>>3;
DATA_TYPE *w=alloca(n*sizeof(*w)); /* forward needs working space */
DATA_TYPE *w2=w+n2;
/* rotate */
/* window + rotate + step 1 */
REG_TYPE r0;
REG_TYPE r1;
DATA_TYPE *x0=in+n2+n4;
DATA_TYPE *x1=x0+1;
DATA_TYPE *T=init->trig+n2;
int i=0;
for(i=0;i<n8;i+=2){
x0 -=4;
T-=2;
r0= x0[2] + x1[0];
r1= x0[0] + x1[2];
w2[i]= MULT_NORM(r1*T[1] + r0*T[0]);
w2[i+1]= MULT_NORM(r1*T[0] - r0*T[1]);
x1 +=4;
}
x1=in+1;
for(;i<n2-n8;i+=2){
T-=2;
x0 -=4;
r0= x0[2] - x1[0];
r1= x0[0] - x1[2];
w2[i]= MULT_NORM(r1*T[1] + r0*T[0]);
w2[i+1]= MULT_NORM(r1*T[0] - r0*T[1]);
x1 +=4;
}
x0=in+n;
for(;i<n2;i+=2){
T-=2;
x0 -=4;
r0= -x0[2] - x1[0];
r1= -x0[0] - x1[2];
w2[i]= MULT_NORM(r1*T[1] + r0*T[0]);
w2[i+1]= MULT_NORM(r1*T[0] - r0*T[1]);
x1 +=4;
}
mdct_butterflies(init,w+n2,n2);
mdct_bitreverse(init,w);
/* roatate + window */
T=init->trig+n2;
x0=out+n2;
for(i=0;i<n4;i++){
x0--;
out[i] =MULT_NORM((w[0]*T[0]+w[1]*T[1])*init->scale);
x0[0] =MULT_NORM((w[0]*T[1]-w[1]*T[0])*init->scale);
w+=2;
T+=2;
}
}

View file

@ -0,0 +1,71 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: modified discrete cosine transform prototypes
last mod: $Id: mdct.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
#ifndef _OGG_mdct_H_
#define _OGG_mdct_H_
#include "vorbis/codec.h"
/*#define MDCT_INTEGERIZED <- be warned there could be some hurt left here*/
#ifdef MDCT_INTEGERIZED
#define DATA_TYPE int
#define REG_TYPE register int
#define TRIGBITS 14
#define cPI3_8 6270
#define cPI2_8 11585
#define cPI1_8 15137
#define FLOAT_CONV(x) ((int)((x)*(1<<TRIGBITS)+.5))
#define MULT_NORM(x) ((x)>>TRIGBITS)
#define HALVE(x) ((x)>>1)
#else
#define DATA_TYPE float
#define REG_TYPE float
#define cPI3_8 .38268343236508977175F
#define cPI2_8 .70710678118654752441F
#define cPI1_8 .92387953251128675613F
#define FLOAT_CONV(x) (x)
#define MULT_NORM(x) (x)
#define HALVE(x) ((x)*.5f)
#endif
typedef struct {
int n;
int log2n;
DATA_TYPE *trig;
int *bitrev;
DATA_TYPE scale;
} mdct_lookup;
extern int FMOD_mdct_init(void *context, mdct_lookup *lookup,int n);
extern void FMOD_mdct_clear(void *context, mdct_lookup *l);
extern void FMOD_mdct_forward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out);
extern void FMOD_mdct_backward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out);
#endif

View file

@ -0,0 +1,57 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: miscellaneous prototypes
last mod: $Id: misc.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
#ifndef _V_RANDOM_H_
#define _V_RANDOM_H_
#include "vorbis/codec.h"
extern void *_FMOD_vorbis_block_alloc(void *context, vorbis_block *vb,ogg_int32_t bytes);
extern int _FMOD_vorbis_block_ripcord(void *context, vorbis_block *vb);
#ifdef ANALYSIS
extern int analysis_noisy;
extern void _analysis_output(char *base,int i,float *v,int n,int bark,int dB,
ogg_int64_t off);
extern void _analysis_output_always(char *base,int i,float *v,int n,int bark,int dB,
ogg_int64_t off);
#endif
#ifdef DEBUG_MALLOC
#define _VDBG_GRAPHFILE "malloc.m"
#undef _VDBG_GRAPHFILE
extern void *_VDBG_malloc(void *ptr,ogg_int32_t bytes,char *file,ogg_int32_t line);
extern void _VDBG_free(void *ptr,char *file,ogg_int32_t line);
#ifndef MISC_C
#undef _ogg_malloc
#undef _ogg_calloc
#undef _ogg_realloc
#undef _ogg_free
#define _ogg_malloc(x) _VDBG_malloc(NULL,(x),__FILE__,__LINE__)
#define _ogg_calloc(x,y) _VDBG_malloc(NULL,(x)*(y),__FILE__,__LINE__)
#define _ogg_realloc(x,y) _VDBG_malloc((x),(y),__FILE__,__LINE__)
#define _ogg_free(x) _VDBG_free((x),__FILE__,__LINE__)
#endif
#endif
#endif

306
lib/ogg_vorbis/vorbis/lib/os.h Executable file
View file

@ -0,0 +1,306 @@
#ifndef _OS_H
#define _OS_H
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: #ifdef jail to whip a few platforms into the UNIX ideal.
last mod: $Id: os.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <math.h>
#include <ogg/os_types.h>
#include "misc.h"
#ifndef _V_IFDEFJAIL_H_
# define _V_IFDEFJAIL_H_
# ifdef __GNUC__
# define STIN static __inline__
# elif _WIN32
# define STIN static __inline
# else
# define STIN static
# endif
#ifdef DJGPP
# define rint(x) (FMOD_ogg_floor((x)+0.5f))
#endif
#ifndef M_PI
# define M_PI (3.1415926536f)
#endif
#if (defined(_WIN32) && !defined(__SYMBIAN32__)) || defined(_XENON)
# include <malloc.h>
# define rint(x) (FMOD_ogg_floor((x)+0.5f))
# define NO_FLOAT_MATH_LIB
# define FAST_HYPOT(a, b) FMOD_ogg_sqrt((a)*(a) + (b)*(b))
#endif
#if defined(__SYMBIAN32__) && defined(__WINS__)
void *_alloca(size_t size);
# define alloca _alloca
#endif
#ifndef FAST_HYPOT
# define FAST_HYPOT hypot
#endif
#endif
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#endif
#ifdef USE_MEMORY_H
# include <memory.h>
#endif
#ifndef min
# define min(x,y) ((x)>(y)?(y):(x))
#endif
#ifndef max
# define max(x,y) ((x)<(y)?(y):(x))
#endif
/* Special i386 GCC implementation */
#if defined(__i386__) && defined(__GNUC__) && !defined(__BEOS__)
# define VORBIS_FPU_CONTROL
/* both GCC and MSVC are kinda stupid about rounding/casting to int.
Because of encapsulation constraints (GCC can't see inside the asm
block and so we end up doing stupid things like a store/load that
is collectively a noop), we do it this way */
/* we must set up the fpu before this works!! */
typedef ogg_int16_t vorbis_fpu_control;
static inline void FMOD_vorbis_fpu_setround(vorbis_fpu_control *fpu){
ogg_int16_t ret;
ogg_int16_t temp;
__asm__ __volatile__("fnstcw %0\n\t"
"movw %0,%%dx\n\t"
"andw $62463,%%dx\n\t"
"movw %%dx,%1\n\t"
"fldcw %1\n\t":"=m"(ret):"m"(temp): "dx");
*fpu=ret;
}
static inline void FMOD_vorbis_fpu_restore(vorbis_fpu_control fpu){
__asm__ __volatile__("fldcw %0":: "m"(fpu));
}
/* assumes the FPU is in round mode! */
static inline int FMOD_vorbis_ftoi(double f){ /* yes, double! Otherwise,
we get extra fst/fld to
truncate precision */
int i;
__asm__("fistl %0": "=m"(i) : "t"(f));
return(i);
}
#ifdef __MACH__
#define FMOD_ogg_ldexp (float)ldexp
#else
#define FMOD_ogg_ldexp ldexpf
#endif
#define FMOD_ogg_cos cosf
#define FMOD_ogg_acos acosf
#define FMOD_ogg_sin sinf
#define FMOD_ogg_sqrt sqrtf
#define FMOD_ogg_fabs fabsf
#define FMOD_ogg_ceil ceilf
#define FMOD_ogg_floor floorf
#define FMOD_ogg_exp expf
#define FMOD_ogg_log logf
#define FMOD_ogg_frexp frexpf
#define FMOD_ogg_atan atanf
#define FMOD_ogg_pow powf
#define FMOD_ogg_rint(_x) (FMOD_ogg_floor((_x)+0.5f)) /* rintf doesnt work. causes horrible corruption. bug in compiler i think */
#endif /* Special i386 GCC implementation */
#if defined(R5900)
# define VORBIS_FPU_CONTROL
typedef int vorbis_fpu_control;
static __inline int FMOD_vorbis_ftoi(float val)
{
register int result;
register float tmp = 0;
__asm__ volatile (
"cvt.w.s %2,%1\n"
"mfc1 %0,%2\n"
: "=r" (result)
: "f" (val),"f" (tmp)
);
return result;
}
static __inline int FMOD_vorbis_ftoipcm(float val)
{
register int result;
register float tmp = 0;
__asm__ volatile (
"addi $4, $0, -32768\n"
"addi $5, $0, 32767\n"
"cvt.w.s %2,%1\n"
"mfc1 %0,%2\n"
"pmaxw %0, %0, $4\n"
"pminw %0, %0, $5\n"
: "=r" (result)
: "f" (val),"f" (tmp)
: "$4", "$5"
);
return result;
}
# define FMOD_vorbis_fpu_setround(vorbis_fpu_control) {}
# define FMOD_vorbis_fpu_restore(vorbis_fpu_control) {}
#define FMOD_ogg_cos cosf
#define FMOD_ogg_acos acosf
#define FMOD_ogg_sin sinf
#define FMOD_ogg_sqrt sqrtf
#define FMOD_ogg_fabs fabsf
#define FMOD_ogg_ceil ceilf
#define FMOD_ogg_floor floorf
#define FMOD_ogg_exp expf
#define FMOD_ogg_log logf
#define FMOD_ogg_ldexp ldexpf
#define FMOD_ogg_frexp frexpf
#define FMOD_ogg_atan atanf
#define FMOD_ogg_pow powf
#define FMOD_ogg_rint(_x) (FMOD_ogg_floor((_x)+0.5f)) /* rintf doesnt work. causes horrible corruption. bug in compiler i think */
#endif
/* MSVC inline assembly. 32 bit only; inline ASM isn't implemented in the
* 64 bit compiler */
#if defined(_MSC_VER) && !defined(_WIN64) && !defined(_WIN32_WCE) && !defined(_XENON)
# define VORBIS_FPU_CONTROL
typedef ogg_int16_t vorbis_fpu_control;
static __inline int FMOD_vorbis_ftoi(double f){
int i;
__asm{
fld f
fistp i
}
return i;
}
static __inline void FMOD_vorbis_fpu_setround(vorbis_fpu_control *fpu){
}
static __inline void FMOD_vorbis_fpu_restore(vorbis_fpu_control fpu){
}
#define FMOD_ogg_cos (float)cos
#define FMOD_ogg_acos (float)acos
#define FMOD_ogg_sin (float)sin
#define FMOD_ogg_sqrt (float)sqrt
#define FMOD_ogg_fabs (float)fabs
#define FMOD_ogg_ceil (float)ceil
#define FMOD_ogg_floor (float)floor
#define FMOD_ogg_exp (float)exp
#define FMOD_ogg_log (float)log
#define FMOD_ogg_ldexp (float)ldexp
#define FMOD_ogg_frexp (float)frexp
#define FMOD_ogg_atan (float)atan
#define FMOD_ogg_pow (float)pow
#define FMOD_ogg_rint (float)rint
#endif /* Special MSVC 32 bit implementation */
/* Optimized code path for x86_64 builds. Uses SSE2 intrinsics. This can be
done safely because all x86_64 CPUs supports SSE2. */
#if (defined(_MSC_VER) && defined(_WIN64)) || (defined(__GNUC__) && defined (__x86_64__))
# define VORBIS_FPU_CONTROL
typedef ogg_int16_t vorbis_fpu_control;
#include <emmintrin.h>
static __inline int FMOD_vorbis_ftoi(double f){
return _mm_cvtsd_si32(_mm_load_sd(&f));
}
static __inline void FMOD_vorbis_fpu_setround(vorbis_fpu_control *fpu){
}
static __inline void FMOD_vorbis_fpu_restore(vorbis_fpu_control fpu){
}
#define FMOD_ogg_cos (float)cos
#define FMOD_ogg_acos (float)acos
#define FMOD_ogg_sin (float)sin
#define FMOD_ogg_sqrt (float)sqrt
#define FMOD_ogg_fabs (float)fabs
#define FMOD_ogg_ceil (float)ceil
#define FMOD_ogg_floor (float)floor
#define FMOD_ogg_exp (float)exp
#define FMOD_ogg_log (float)log
#define FMOD_ogg_ldexp (float)ldexp
#define FMOD_ogg_frexp (float)frexp
#define FMOD_ogg_atan (float)atan
#define FMOD_ogg_pow (float)pow
#define FMOD_ogg_rint (float)rint
#endif /* Special MSVC x64 implementation */
/* If no special implementation was found for the current compiler / platform,
use the default implementation here: */
#ifndef VORBIS_FPU_CONTROL
typedef int vorbis_fpu_control;
#define FMOD_ogg_cos (float)cos
#define FMOD_ogg_acos (float)acos
#define FMOD_ogg_sin (float)sin
#define FMOD_ogg_sqrt (float)sqrt
#define FMOD_ogg_fabs (float)fabs
#define FMOD_ogg_ceil (float)ceil
#define FMOD_ogg_floor (float)floor
#define FMOD_ogg_exp (float)exp
#define FMOD_ogg_log (float)log
#define FMOD_ogg_ldexp (float)ldexp
#define FMOD_ogg_frexp (float)frexp
#define FMOD_ogg_atan (float)atan
#define FMOD_ogg_pow (float)pow
#define FMOD_ogg_rint (float)rint
static int FMOD_vorbis_ftoi(double f){
/* Note: MSVC and GCC (at least on some systems) round towards zero, thus,
the FMOD_ogg_floor() call is required to ensure correct roudning of
negative numbers */
return (int)FMOD_ogg_floor(f+.5f);
}
/* We don't have special code for this compiler/arch, so do it the slow way */
# define FMOD_vorbis_fpu_setround(vorbis_fpu_control) {}
# define FMOD_vorbis_fpu_restore(vorbis_fpu_control) {}
#endif /* default implementation */
#include <string.h>
#define ogg_strlen strlen
#define ogg_strcpy strcpy
#define ogg_strcat strcat
#endif /* _OS_H */

185
lib/ogg_vorbis/vorbis/lib/psy.h Executable file
View file

@ -0,0 +1,185 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: random psychoacoustics (not including preecho)
last mod: $Id: psy.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
#ifndef _V_PSY_H_
#define _V_PSY_H_
#include "smallft.h"
#include "backends.h"
//#include "envelope.h"
#ifndef EHMER_MAX
#define EHMER_MAX 56
#endif
/* psychoacoustic setup ********************************************/
#define P_BANDS 17 /* 62Hz to 16kHz */
#define P_LEVELS 8 /* 30dB to 100dB */
#define P_LEVEL_0 30. /* 30 dB */
#define P_NOISECURVES 3
//#define NOISE_COMPAND_LEVELS 40
//typedef struct vorbis_info_psy{
// int blockflag;
//
// float ath_adjatt;
// float ath_maxatt;
//
// float tone_masteratt[P_NOISECURVES];
// float tone_centerboost;
// float tone_decay;
// float tone_abs_limit;
// float toneatt[P_BANDS];
//
// int noisemaskp;
// float noisemaxsupp;
// float noisewindowlo;
// float noisewindowhi;
// int noisewindowlomin;
// int noisewindowhimin;
// int noisewindowfixed;
// float noiseoff[P_NOISECURVES][P_BANDS];
// float noisecompand[NOISE_COMPAND_LEVELS];
//
// float max_curve_dB;
//
// int normal_channel_p;
// int normal_point_p;
// int normal_start;
// int normal_partition;
// double normal_thresh;
//} vorbis_info_psy;
//
//typedef struct{
// int eighth_octave_lines;
//
// /* for block long/short tuning; encode only */
// float preecho_thresh[VE_BANDS];
// float postecho_thresh[VE_BANDS];
// float stretch_penalty;
// float preecho_minenergy;
//
// float ampmax_att_per_sec;
//
// /* channel coupling config */
// int coupling_pkHz[PACKETBLOBS];
// int coupling_pointlimit[2][PACKETBLOBS];
// int coupling_prepointamp[PACKETBLOBS];
// int coupling_postpointamp[PACKETBLOBS];
// int sliding_lowpass[2][PACKETBLOBS];
//
//} vorbis_info_psy_global;
//
//typedef struct {
// float ampmax;
// int channels;
//
// vorbis_info_psy_global *gi;
// int coupling_pointlimit[2][P_NOISECURVES];
//} vorbis_look_psy_global;
//
//
//typedef struct {
// int n;
// struct vorbis_info_psy *vi;
//
// float ***tonecurves;
// float **noiseoffset;
//
// float *ath;
// long *octave; /* in n.ocshift format */
// long *bark;
//
// long firstoc;
// long shiftoc;
// int eighth_octave_lines; /* power of two, please */
// int total_octave_lines;
// long rate; /* cache it */
//
// float m_val; /* Masking compensation value */
//
//} vorbis_look_psy;
//
//extern void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi,
// vorbis_info_psy_global *gi,int n,long rate);
//extern void _vp_psy_clear(vorbis_look_psy *p);
//extern void *_vi_psy_dup(void *source);
//
//extern void _vi_psy_free(vorbis_info_psy *i);
//extern vorbis_info_psy *_vi_psy_copy(vorbis_info_psy *i);
//
//extern void _vp_remove_floor(vorbis_look_psy *p,
// float *mdct,
// int *icodedflr,
// float *residue,
// int sliding_lowpass);
//
//extern void _vp_noisemask(vorbis_look_psy *p,
// float *logmdct,
// float *logmask);
//
//extern void _vp_tonemask(vorbis_look_psy *p,
// float *logfft,
// float *logmask,
// float global_specmax,
// float local_specmax);
//
//extern void _vp_offset_and_mix(vorbis_look_psy *p,
// float *noise,
// float *tone,
// int offset_select,
// float *logmask,
// float *mdct,
// float *logmdct);
//
//extern float _vp_ampmax_decay(float amp,vorbis_dsp_state *vd);
//
//extern float **_vp_quantize_couple_memo(vorbis_block *vb,
// vorbis_info_psy_global *g,
// vorbis_look_psy *p,
// vorbis_info_mapping0 *vi,
// float **mdct);
//
//extern void _vp_couple(int blobno,
// vorbis_info_psy_global *g,
// vorbis_look_psy *p,
// vorbis_info_mapping0 *vi,
// float **res,
// float **mag_memo,
// int **mag_sort,
// int **ifloor,
// int *nonzero,
// int sliding_lowpass);
//
//extern void _vp_noise_normalize(vorbis_look_psy *p,
// float *in,float *out,int *sortedindex);
//
//extern void _vp_noise_normalize_sort(vorbis_look_psy *p,
// float *magnitudes,int *sortedindex);
//
//extern int **_vp_quantize_couple_sort(vorbis_block *vb,
// vorbis_look_psy *p,
// vorbis_info_mapping0 *vi,
// float **mags);
//
//extern void hf_reduction(vorbis_info_psy_global *g,
// vorbis_look_psy *p,
// vorbis_info_mapping0 *vi,
// float **mdct);
#endif

View file

@ -0,0 +1,45 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: registry for time, floor, res backends and channel mappings
last mod: $Id: registry.c 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
#include "vorbis/codec.h"
#include "codec_internal.h"
#include "registry.h"
#include "misc.h"
/* seems like major overkill now; the backend numbers will grow into
the infrastructure soon enough */
extern const vorbis_func_floor FMOD_floor0_exportbundle;
extern const vorbis_func_floor FMOD_floor1_exportbundle;
extern const vorbis_func_residue FMOD_residue0_exportbundle;
extern const vorbis_func_residue FMOD_residue1_exportbundle;
extern const vorbis_func_residue FMOD_residue2_exportbundle;
extern const vorbis_func_mapping FMOD_mapping0_exportbundle;
const vorbis_func_floor *const _FMOD_floor_P[]={
0, //&FMOD_floor0_exportbundle, // REMOVED BY FMOD - OBSOLETE FORMAT - error check is in info.c
&FMOD_floor1_exportbundle,
};
const vorbis_func_residue *const _FMOD_residue_P[]={
&FMOD_residue0_exportbundle,
&FMOD_residue1_exportbundle,
&FMOD_residue2_exportbundle,
};
const vorbis_func_mapping *const _FMOD_mapping_P[]={
&FMOD_mapping0_exportbundle,
};

View file

@ -0,0 +1,32 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: registry for time, floor, res backends and channel mappings
last mod: $Id: registry.h 15531 2008-11-24 23:50:06Z xiphmont $
********************************************************************/
#ifndef _V_REG_H_
#define _V_REG_H_
#define VI_TRANSFORMB 1
#define VI_WINDOWB 1
#define VI_TIMEB 1
#define VI_FLOORB 2
#define VI_RESB 3
#define VI_MAPB 1
extern const vorbis_func_floor *const _FMOD_floor_P[];
extern const vorbis_func_residue *const _FMOD_residue_P[];
extern const vorbis_func_mapping *const _FMOD_mapping_P[];
#endif

998
lib/ogg_vorbis/vorbis/lib/res0.c Executable file
View file

@ -0,0 +1,998 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: residue backend 0, 1 and 2 implementation
last mod: $Id: res0.c 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
/* Slow, slow, slow, simpleminded and did I mention it was slow? The
encode/decode loops are coded for clarity and performance is not
yet even a nagging little idea lurking in the shadows. Oh and BTW,
it's slow. */
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ogg/ogg.h>
#include "vorbis/codec.h"
#include "codec_internal.h"
#include "registry.h"
#include "codebook.h"
#include "misc.h"
#include "os.h"
#if defined(TRAIN_RES) || defined (TRAIN_RESAUX)
#include <stdio.h>
#endif
typedef struct {
vorbis_info_residue0 *info;
int parts;
int stages;
codebook *fullbooks;
codebook *phrasebook;
codebook ***partbooks;
int partvals;
int **decodemap;
ogg_int32_t postbits;
ogg_int32_t phrasebits;
ogg_int32_t frames;
#if defined(TRAIN_RES) || defined(TRAIN_RESAUX)
int train_seq;
ogg_int32_t *training_data[8][64];
float training_max[8][64];
float training_min[8][64];
float tmin;
float tmax;
#endif
} vorbis_look_residue0;
void FMOD_res0_free_info(void *context, vorbis_info_residue *i){
vorbis_info_residue0 *info=(vorbis_info_residue0 *)i;
if(info){
FMOD_memset(info,0,sizeof(*info));
_ogg_free(info);
}
}
void FMOD_res0_free_look(void *context, vorbis_look_residue *i){
int j;
if(i){
vorbis_look_residue0 *look=(vorbis_look_residue0 *)i;
#ifdef TRAIN_RES
{
int j,k,l;
for(j=0;j<look->parts;j++){
/*fprintf(stderr,"partition %d: ",j);*/
for(k=0;k<8;k++)
if(look->training_data[k][j]){
char buffer[80];
FILE *of;
codebook *statebook=look->partbooks[j][k];
/* long and short into the same bucket by current convention */
sprintf(buffer,"res_part%d_pass%d.vqd",j,k);
of=fopen(buffer,"a");
for(l=0;l<statebook->entries;l++)
fprintf(of,"%d:%ld\n",l,look->training_data[k][j][l]);
fclose(of);
/*fprintf(stderr,"%d(%.2f|%.2f) ",k,
look->training_min[k][j],look->training_max[k][j]);*/
_ogg_free(look->training_data[k][j]);
look->training_data[k][j]=NULL;
}
/*fprintf(stderr,"\n");*/
}
}
fprintf(stderr,"min/max residue: %g::%g\n",look->tmin,look->tmax);
/*fprintf(stderr,"residue bit usage %f:%f (%f total)\n",
(float)look->phrasebits/look->frames,
(float)look->postbits/look->frames,
(float)(look->postbits+look->phrasebits)/look->frames);*/
#endif
/*vorbis_info_residue0 *info=look->info;
fprintf(stderr,
"%ld frames encoded in %ld phrasebits and %ld residue bits "
"(%g/frame) \n",look->frames,look->phrasebits,
look->resbitsflat,
(look->phrasebits+look->resbitsflat)/(float)look->frames);
for(j=0;j<look->parts;j++){
ogg_int32_t acc=0;
fprintf(stderr,"\t[%d] == ",j);
for(k=0;k<look->stages;k++)
if((info->secondstages[j]>>k)&1){
fprintf(stderr,"%ld,",look->resbits[j][k]);
acc+=look->resbits[j][k];
}
fprintf(stderr,":: (%ld vals) %1.2fbits/sample\n",look->resvals[j],
acc?(float)acc/(look->resvals[j]*info->grouping):0);
}
fprintf(stderr,"\n");*/
for(j=0;j<look->parts;j++)
if(look->partbooks[j])_ogg_free(look->partbooks[j]);
_ogg_free(look->partbooks);
for(j=0;j<look->partvals;j++)
_ogg_free(look->decodemap[j]);
_ogg_free(look->decodemap);
FMOD_memset(look,0,sizeof(*look));
_ogg_free(look);
}
}
static int ilog(unsigned int v){
int ret=0;
while(v){
ret++;
v>>=1;
}
return(ret);
}
static int icount(unsigned int v){
int ret=0;
while(v){
ret+=v&1;
v>>=1;
}
return(ret);
}
#if 0
void FMOD_res0_pack(void *context, vorbis_info_residue *vr,oggpack_buffer *opb){
vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr;
int j,acc=0;
FMOD_oggpack_write(opb,info->begin,24);
FMOD_oggpack_write(opb,info->end,24);
FMOD_oggpack_write(opb,info->grouping-1,24); /* residue vectors to group and
code with a partitioned book */
FMOD_oggpack_write(opb,info->partitions-1,6); /* possible partition choices */
FMOD_oggpack_write(opb,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(j=0;j<info->partitions;j++){
if(ilog(info->secondstages[j])>3){
/* yes, this is a minor hack due to not thinking ahead */
FMOD_oggpack_write(opb,info->secondstages[j],3);
FMOD_oggpack_write(opb,1,1);
FMOD_oggpack_write(opb,info->secondstages[j]>>3,5);
}else
FMOD_oggpack_write(opb,info->secondstages[j],4); /* trailing zero */
acc+=icount(info->secondstages[j]);
}
for(j=0;j<acc;j++)
FMOD_oggpack_write(opb,info->booklist[j],8);
}
#endif
/* vorbis_info is for range checking */
vorbis_info_residue *FMOD_res0_unpack(void *context, vorbis_info *vi,oggpack_buffer *opb){
int j,acc=0;
vorbis_info_residue0 *info=_ogg_calloc(1,sizeof(*info));
codec_setup_info *ci=vi->codec_setup;
if (!info)
{
goto errout;
}
info->begin=FMOD_oggpack_read(opb,24);
info->end=FMOD_oggpack_read(opb,24);
info->grouping=FMOD_oggpack_read(opb,24)+1;
info->partitions=FMOD_oggpack_read(opb,6)+1;
info->groupbook=FMOD_oggpack_read(opb,8);
/* check for premature EOP */
if(info->groupbook<0)goto errout;
for(j=0;j<info->partitions;j++){
int cascade=FMOD_oggpack_read(opb,3);
int cflag=FMOD_oggpack_read(opb,1);
if(cflag<0) goto errout;
if(cflag){
int c=FMOD_oggpack_read(opb,5);
if(c<0) goto errout;
cascade|=(c<<3);
}
info->secondstages[j]=cascade;
acc+=icount(cascade);
}
for(j=0;j<acc;j++){
int book=FMOD_oggpack_read(opb,8);
if(book<0) goto errout;
info->booklist[j]=book;
}
if(info->groupbook>=ci->books)goto errout;
for(j=0;j<acc;j++){
if(info->booklist[j]>=ci->books)goto errout;
if(ci->book_param[info->booklist[j]]->maptype==0)goto errout;
}
/* verify the phrasebook is not specifying an impossible or
inconsistent partitioning scheme. */
{
int entries = ci->book_param[info->groupbook]->entries;
int dim = ci->book_param[info->groupbook]->dim;
int partvals = 1;
while(dim>0){
partvals *= info->partitions;
if(partvals > entries) goto errout;
dim--;
}
}
return(info);
errout:
FMOD_res0_free_info(context, info);
return(NULL);
}
vorbis_look_residue *FMOD_res0_look(void *context, vorbis_dsp_state *vd,
vorbis_info_residue *vr){
vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr;
vorbis_look_residue0 *look=_ogg_calloc(1,sizeof(*look));
codec_setup_info *ci=vd->vi->codec_setup;
int j,k,acc=0;
int dim;
int maxstage=0;
if (!look)
{
return(NULL);
}
look->info=info;
look->parts=info->partitions;
look->fullbooks=ci->fullbooks;
look->phrasebook=ci->fullbooks+info->groupbook;
dim=look->phrasebook->dim;
look->partbooks=_ogg_calloc(look->parts,sizeof(*look->partbooks));
if (!look->partbooks)
{
return(NULL);
}
for(j=0;j<look->parts;j++){
int stages=ilog(info->secondstages[j]);
if(stages){
if(stages>maxstage)maxstage=stages;
look->partbooks[j]=_ogg_calloc(stages,sizeof(*look->partbooks[j]));
if (!look->partbooks[j])
{
return 0;
}
for(k=0;k<stages;k++)
if(info->secondstages[j]&(1<<k)){
look->partbooks[j][k]=ci->fullbooks+info->booklist[acc++];
#ifdef TRAIN_RES
look->training_data[k][j]=_ogg_calloc(look->partbooks[j][k]->entries,
sizeof(***look->training_data));
#endif
}
}
}
look->partvals=1;
for(j=0;j<dim;j++)
look->partvals*=look->parts;
look->stages=maxstage;
look->decodemap=_ogg_malloc(look->partvals*sizeof(*look->decodemap));
if (!look->decodemap)
{
return 0;
}
for(j=0;j<look->partvals;j++){
ogg_int32_t val=j;
ogg_int32_t mult=look->partvals/look->parts;
look->decodemap[j]=_ogg_malloc(dim*sizeof(*look->decodemap[j]));
if (!look->decodemap[j])
{
return 0;
}
for(k=0;k<dim;k++){
ogg_int32_t deco=val/mult;
val-=deco*mult;
mult/=look->parts;
look->decodemap[j][k]=deco;
}
}
#if defined(TRAIN_RES) || defined (TRAIN_RESAUX)
{
static int train_seq=0;
look->train_seq=train_seq++;
}
#endif
return(look);
}
#if 0
/* break an abstraction and copy some code for performance purposes */
static int local_book_besterror(codebook *book,float *a){
int dim=book->dim,i,k,o;
int best=0;
encode_aux_threshmatch *tt=book->c->thresh_tree;
/* find the quant val of each scalar */
for(k=0,o=dim;k<dim;++k){
float val=a[--o];
i=tt->threshvals>>1;
if(val<tt->quantthresh[i]){
if(val<tt->quantthresh[i-1]){
for(--i;i>0;--i)
if(val>=tt->quantthresh[i-1])
break;
}
}else{
for(++i;i<tt->threshvals-1;++i)
if(val<tt->quantthresh[i])break;
}
best=(best*tt->quantvals)+tt->quantmap[i];
}
/* regular lattices are easy :-) */
if(book->c->lengthlist[best]<=0){
const static_codebook *c=book->c;
int i,j;
float bestf=0.f;
float *e=book->valuelist;
best=-1;
for(i=0;i<book->entries;i++){
if(c->lengthlist[i]>0){
float this=0.f;
for(j=0;j<dim;j++){
float val=(e[j]-a[j]);
this+=val*val;
}
if(best==-1 || this<bestf){
bestf=this;
best=i;
}
}
e+=dim;
}
}
if(best>-1){
float *ptr=book->valuelist+best*dim;
for(i=0;i<dim;i++)
*a++ -= *ptr++;
}
return(best);
}
static int _encodepart(oggpack_buffer *opb,float *vec, int n,
codebook *book,ogg_int32_t *acc){
int i,bits=0;
int dim=book->dim;
int step=n/dim;
for(i=0;i<step;i++){
int entry=local_book_besterror(book,vec+i*dim);
#ifdef TRAIN_RES
if(entry>0)
acc[entry]++;
#endif
bits+=FMOD_vorbis_book_encode(book,entry,opb);
}
return(bits);
}
#endif
static ogg_int32_t **_FMOD_01class(void *context, vorbis_block *vb,vorbis_look_residue *vl,
float **in,int ch){
ogg_int32_t i,j,k;
vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
vorbis_info_residue0 *info=look->info;
/* move all this setup out later */
int samples_per_partition=info->grouping;
int possible_partitions=info->partitions;
int n=info->end-info->begin;
int partvals=n/samples_per_partition;
ogg_int32_t **partword=_FMOD_vorbis_block_alloc(context, vb,ch*sizeof(*partword));
float scale=100.0f/samples_per_partition;
if (!partword)
{
return(NULL);
}
/* we find the partition type for each partition of each
channel. We'll go back and do the interleaved encoding in a
bit. For now, clarity */
for(i=0;i<ch;i++){
partword[i]=_FMOD_vorbis_block_alloc(context, vb,n/samples_per_partition*sizeof(*partword[i]));
if (!partword[i])
{
return(NULL);
}
FMOD_memset(partword[i],0,n/samples_per_partition*sizeof(*partword[i]));
}
for(i=0;i<partvals;i++){
int offset=i*samples_per_partition+info->begin;
for(j=0;j<ch;j++){
float max=0.;
float ent=0.;
for(k=0;k<samples_per_partition;k++){
if(FMOD_ogg_fabs(in[j][offset+k])>max)max=FMOD_ogg_fabs(in[j][offset+k]);
ent+=FMOD_ogg_fabs(FMOD_ogg_rint(in[j][offset+k]));
}
ent*=scale;
for(k=0;k<possible_partitions-1;k++)
if(max<=info->classmetric1[k] &&
(info->classmetric2[k]<0 || (int)ent<info->classmetric2[k]))
break;
partword[j][i]=k;
}
}
#ifdef TRAIN_RESAUX
{
FILE *of;
char buffer[80];
for(i=0;i<ch;i++){
sprintf(buffer,"resaux_%d.vqd",look->train_seq);
of=fopen(buffer,"a");
for(j=0;j<partvals;j++)
fprintf(of,"%ld, ",partword[i][j]);
fprintf(of,"\n");
fclose(of);
}
}
#endif
look->frames++;
return(partword);
}
#if 0
/* designed for stereo or other modes where the partition size is an
integer multiple of the number of channels encoded in the current
submap */
static ogg_int32_t **_2class(void *context, vorbis_block *vb,vorbis_look_residue *vl,float **in,
int ch){
ogg_int32_t i,j,k,l;
vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
vorbis_info_residue0 *info=look->info;
/* move all this setup out later */
int samples_per_partition=info->grouping;
int possible_partitions=info->partitions;
int n=info->end-info->begin;
int partvals=n/samples_per_partition;
ogg_int32_t **partword=_FMOD_vorbis_block_alloc(context, vb,sizeof(*partword));
#if defined(TRAIN_RES) || defined (TRAIN_RESAUX)
FILE *of;
char buffer[80];
#endif
partword[0]=_FMOD_vorbis_block_alloc(context, vb,n*ch/samples_per_partition*sizeof(*partword[0]));
FMOD_memset(partword[0],0,n*ch/samples_per_partition*sizeof(*partword[0]));
for(i=0,l=info->begin/ch;i<partvals;i++){
float magmax=0.f;
float angmax=0.f;
for(j=0;j<samples_per_partition;j+=ch){
if(FMOD_ogg_fabs(in[0][l])>magmax)magmax=FMOD_ogg_fabs(in[0][l]);
for(k=1;k<ch;k++)
if(FMOD_ogg_fabs(in[k][l])>angmax)angmax=FMOD_ogg_fabs(in[k][l]);
l++;
}
for(j=0;j<possible_partitions-1;j++)
if(magmax<=info->classmetric1[j] &&
angmax<=info->classmetric2[j])
break;
partword[0][i]=j;
}
#ifdef TRAIN_RESAUX
sprintf(buffer,"resaux_%d.vqd",look->train_seq);
of=fopen(buffer,"a");
for(i=0;i<partvals;i++)
fprintf(of,"%ld, ",partword[0][i]);
fprintf(of,"\n");
fclose(of);
#endif
look->frames++;
return(partword);
}
static int _01forward(oggpack_buffer *opb,
vorbis_block *vb,vorbis_look_residue *vl,
float **in,int ch,
ogg_int32_t **partword,
int (*encode)(oggpack_buffer *,float *,int,
codebook *,ogg_int32_t *)){
ogg_int32_t i,j,k,s;
vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
vorbis_info_residue0 *info=look->info;
/* move all this setup out later */
int samples_per_partition=info->grouping;
int possible_partitions=info->partitions;
int partitions_per_word=look->phrasebook->dim;
int n=info->end-info->begin;
int partvals=n/samples_per_partition;
ogg_int32_t resbits[128];
ogg_int32_t resvals[128];
#ifdef TRAIN_RES
for(i=0;i<ch;i++)
for(j=info->begin;j<end;j++){
if(in[i][j]>look->tmax)look->tmax=in[i][j];
if(in[i][j]<look->tmin)look->tmin=in[i][j];
}
#endif
FMOD_memset(resbits,0,sizeof(resbits));
FMOD_memset(resvals,0,sizeof(resvals));
/* we code the partition words for each channel, then the residual
words for a partition per channel until we've written all the
residual words for that partition word. Then write the next
partition channel words... */
for(s=0;s<look->stages;s++){
for(i=0;i<partvals;){
/* first we encode a partition codeword for each channel */
if(s==0){
for(j=0;j<ch;j++){
ogg_int32_t val=partword[j][i];
for(k=1;k<partitions_per_word;k++){
val*=possible_partitions;
if(i+k<partvals)
val+=partword[j][i+k];
}
/* training hack */
if(val<look->phrasebook->entries)
look->phrasebits+=FMOD_vorbis_book_encode(look->phrasebook,val,opb);
#if 0 /*def TRAIN_RES*/
else
fprintf(stderr,"!");
#endif
}
}
/* now we encode interleaved residual values for the partitions */
for(k=0;k<partitions_per_word && i<partvals;k++,i++){
ogg_int32_t offset=i*samples_per_partition+info->begin;
for(j=0;j<ch;j++){
if(s==0)resvals[partword[j][i]]+=samples_per_partition;
if(info->secondstages[partword[j][i]]&(1<<s)){
codebook *statebook=look->partbooks[partword[j][i]][s];
if(statebook){
int ret;
ogg_int32_t *accumulator=NULL;
#ifdef TRAIN_RES
accumulator=look->training_data[s][partword[j][i]];
{
int l;
float *samples=in[j]+offset;
for(l=0;l<samples_per_partition;l++){
if(samples[l]<look->training_min[s][partword[j][i]])
look->training_min[s][partword[j][i]]=samples[l];
if(samples[l]>look->training_max[s][partword[j][i]])
look->training_max[s][partword[j][i]]=samples[l];
}
}
#endif
ret=encode(opb,in[j]+offset,samples_per_partition,
statebook,accumulator);
look->postbits+=ret;
resbits[partword[j][i]]+=ret;
}
}
}
}
}
}
/*{
ogg_int32_t total=0;
ogg_int32_t totalbits=0;
fprintf(stderr,"%d :: ",vb->mode);
for(k=0;k<possible_partitions;k++){
fprintf(stderr,"%ld/%1.2g, ",resvals[k],(float)resbits[k]/resvals[k]);
total+=resvals[k];
totalbits+=resbits[k];
}
fprintf(stderr,":: %ld:%1.2g\n",total,(double)totalbits/total);
}*/
return(0);
}
#endif
/* a truncated packet here just means 'stop working'; it's not an error */
static int _FMOD_01inverse(void *context, vorbis_block *vb,vorbis_look_residue *vl,
float **in,int ch,
ogg_int32_t (*decodepart)(codebook *, float *,
oggpack_buffer *,int)){
ogg_int32_t i,j,k,l,s;
vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
vorbis_info_residue0 *info=look->info;
/* move all this setup out later */
int samples_per_partition=info->grouping;
int partitions_per_word=look->phrasebook->dim;
int max=vb->pcmend>>1;
int end=(info->end<max?info->end:max);
int n=end-info->begin;
if(n>0){
int partvals=n/samples_per_partition;
int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
int ***partword=alloca(ch*sizeof(*partword));
for(j=0;j<ch;j++)
{
partword[j]=_FMOD_vorbis_block_alloc(context, vb,partwords*sizeof(*partword[j]));
if (!partword[j])
{
return(OV_EMEMORY);
}
}
for(s=0;s<look->stages;s++){
/* each loop decodes on partition codeword containing
partitions_per_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=FMOD_vorbis_book_decode(look->phrasebook,&vb->opb);
if(temp==-1)goto eopbreak;
partword[j][l]=look->decodemap[temp];
if(partword[j][l]==NULL)goto errout;
}
}
/* 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++){
ogg_int32_t offset=info->begin+i*samples_per_partition;
if(info->secondstages[partword[j][l][k]]&(1<<s)){
codebook *stagebook=look->partbooks[partword[j][l][k]][s];
if(stagebook){
if(decodepart(stagebook,in[j]+offset,&vb->opb,
samples_per_partition)==-1)goto eopbreak;
}
}
}
}
}
}
errout:
eopbreak:
return(0);
}
#if 0
/* residue 0 and 1 are just slight variants of one another. 0 is
interleaved, 1 is not */
ogg_int32_t **FMOD_res0_class(vorbis_block *vb,vorbis_look_residue *vl,
float **in,int *nonzero,int ch){
/* we encode only the nonzero parts of a bundle */
int i,used=0;
for(i=0;i<ch;i++)
if(nonzero[i])
in[used++]=in[i];
if(used)
/*return(_FMOD_01class(vb,vl,in,used,_interleaved_testhack));*/
return(_FMOD_01class(vb,vl,in,used));
else
return(0);
}
int FMOD_res0_forward(vorbis_block *vb,vorbis_look_residue *vl,
float **in,float **out,int *nonzero,int ch,
ogg_int32_t **partword){
/* we encode only the nonzero parts of a bundle */
int i,j,used=0,n=vb->pcmend/2;
for(i=0;i<ch;i++)
if(nonzero[i]){
if(out)
for(j=0;j<n;j++)
out[i][j]+=in[i][j];
in[used++]=in[i];
}
if(used){
int ret=_01forward(vb,vl,in,used,partword,
_interleaved_encodepart);
if(out){
used=0;
for(i=0;i<ch;i++)
if(nonzero[i]){
for(j=0;j<n;j++)
out[i][j]-=in[used][j];
used++;
}
}
return(ret);
}else{
return(0);
}
}
#endif
int FMOD_res0_inverse(void *context, vorbis_block *vb,vorbis_look_residue *vl,
float **in,int *nonzero,int ch){
int i,used=0;
for(i=0;i<ch;i++)
if(nonzero[i])
in[used++]=in[i];
if(used)
return(_FMOD_01inverse(context, vb,vl,in,used,FMOD_vorbis_book_decodevs_add));
else
return(0);
}
#if 0
int FMOD_res1_forward(void *context, oggpack_buffer *opb,vorbis_block *vb,vorbis_look_residue *vl,
float **in,float **out,int *nonzero,int ch,
ogg_int32_t **partword){
int i,j,used=0,n=vb->pcmend/2;
for(i=0;i<ch;i++)
if(nonzero[i]){
if(out)
for(j=0;j<n;j++)
out[i][j]+=in[i][j];
in[used++]=in[i];
}
if(used){
int ret=_01forward(opb,vb,vl,in,used,partword,_encodepart);
if(out){
used=0;
for(i=0;i<ch;i++)
if(nonzero[i]){
for(j=0;j<n;j++)
out[i][j]-=in[used][j];
used++;
}
}
return(ret);
}else{
return(0);
}
}
#endif
ogg_int32_t **FMOD_res1_class(void *context, vorbis_block *vb,vorbis_look_residue *vl,
float **in,int *nonzero,int ch){
int i,used=0;
for(i=0;i<ch;i++)
if(nonzero[i])
in[used++]=in[i];
if(used)
return(_FMOD_01class(context, vb,vl,in,used));
else
return(0);
}
int FMOD_res1_inverse(void *context, vorbis_block *vb,vorbis_look_residue *vl,
float **in,int *nonzero,int ch){
int i,used=0;
for(i=0;i<ch;i++)
if(nonzero[i])
in[used++]=in[i];
if(used)
return(_FMOD_01inverse(context, vb,vl,in,used,FMOD_vorbis_book_decodev_add));
else
return(0);
}
#if 0
ogg_int32_t **FMOD_res2_class(void *context, vorbis_block *vb,vorbis_look_residue *vl,
float **in,int *nonzero,int ch){
int i,used=0;
for(i=0;i<ch;i++)
if(nonzero[i])used++;
if(used)
return(_2class(context, vb,vl,in,ch));
else
return(0);
}
/* res2 is slightly more different; all the channels are interleaved
into a single vector and encoded. */
int FMOD_res2_forward(void *context, oggpack_buffer *opb,
vorbis_block *vb,vorbis_look_residue *vl,
float **in,float **out,int *nonzero,int ch,
ogg_int32_t **partword){
ogg_int32_t i,j,k,n=vb->pcmend/2,used=0;
/* don't duplicate the code; use a working vector hack for now and
reshape ourselves into a single channel res1 */
/* ugly; reallocs for each coupling pass :-( */
float *work=_FMOD_vorbis_block_alloc(context, vb,ch*n*sizeof(*work));
for(i=0;i<ch;i++){
float *pcm=in[i];
if(nonzero[i])used++;
for(j=0,k=i;j<n;j++,k+=ch)
work[k]=pcm[j];
}
if(used){
int ret=_01forward(opb,vb,vl,&work,1,partword,_encodepart);
/* update the sofar vector */
if(out){
for(i=0;i<ch;i++){
float *pcm=in[i];
float *sofar=out[i];
for(j=0,k=i;j<n;j++,k+=ch)
sofar[j]+=pcm[j]-work[k];
}
}
return(ret);
}else{
return(0);
}
}
#endif
/* duplicate code here as speed is somewhat more important */
int FMOD_res2_inverse(void *context, vorbis_block *vb,vorbis_look_residue *vl,
float **in,int *nonzero,int ch){
ogg_int32_t i,k,l,s;
vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
vorbis_info_residue0 *info=look->info;
/* move all this setup out later */
int samples_per_partition=info->grouping;
int partitions_per_word=look->phrasebook->dim;
int max=(vb->pcmend*ch)>>1;
int end=(info->end<max?info->end:max);
int n=end-info->begin;
if(n>0){
int partvals=n/samples_per_partition;
int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
int **partword=_FMOD_vorbis_block_alloc(context, vb,partwords*sizeof(*partword));
if (!partword)
{
return -1;
}
for(i=0;i<ch;i++)if(nonzero[i])break;
if(i==ch)return(0); /* no nonzero vectors */
for(s=0;s<look->stages;s++){
for(i=0,l=0;i<partvals;l++){
if(s==0){
/* fetch the partition word */
int temp=FMOD_vorbis_book_decode(look->phrasebook,&vb->opb);
if(temp==-1)goto eopbreak;
partword[l]=look->decodemap[temp];
if(partword[l]==NULL)goto errout;
}
/* now we decode residual values for the partitions */
for(k=0;k<partitions_per_word && i<partvals;k++,i++)
if(info->secondstages[partword[l][k]]&(1<<s)){
codebook *stagebook=look->partbooks[partword[l][k]][s];
if(stagebook){
if(FMOD_vorbis_book_decodevv_add(stagebook,in,
i*samples_per_partition+info->begin,ch,
&vb->opb,samples_per_partition)==-1)
goto eopbreak;
}
}
}
}
}
errout:
eopbreak:
return(0);
}
const vorbis_func_residue FMOD_residue0_exportbundle={
NULL,
&FMOD_res0_unpack,
&FMOD_res0_look,
&FMOD_res0_free_info,
&FMOD_res0_free_look,
NULL,
NULL,
&FMOD_res0_inverse
};
const vorbis_func_residue FMOD_residue1_exportbundle={
NULL, //&res0_pack,
&FMOD_res0_unpack,
&FMOD_res0_look,
&FMOD_res0_free_info,
&FMOD_res0_free_look,
NULL, //&res1_class,
NULL, //&res1_forward,
&FMOD_res1_inverse
};
const vorbis_func_residue FMOD_residue2_exportbundle={
NULL, //&res0_pack,
&FMOD_res0_unpack,
&FMOD_res0_look,
&FMOD_res0_free_info,
&FMOD_res0_free_look,
NULL, //&res2_class,
NULL, //&res2_forward,
&FMOD_res2_inverse
};

View file

@ -0,0 +1,90 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: linear scale -> dB, Bark and Mel scales
last mod: $Id: scales.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
#ifndef _V_SCALES_H_
#define _V_SCALES_H_
#include <math.h>
#include "os.h"
#ifdef _MSC_VER
/* MS Visual Studio doesn't have C99 inline keyword. */
#define inline __inline
#endif
/* 20log10(x) */
#define VORBIS_IEEE_FLOAT32 1
#ifdef VORBIS_IEEE_FLOAT32
static inline float unitnorm(float x){
union {
ogg_uint32_t i;
float f;
} ix;
ix.f = x;
ix.i = (ix.i & 0x80000000U) | (0x3f800000U);
return ix.f;
}
/* Segher was off (too high) by ~ .3 decibel. Center the conversion correctly. */
static inline float todB(const float *x){
union {
ogg_uint32_t i;
float f;
} ix;
ix.f = *x;
ix.i = ix.i&0x7fffffff;
return (float)(ix.i * 7.17711438e-7f -764.6161886f);
}
#define todB_nn(x) todB(x)
#else
static float unitnorm(float x){
if(x<0)return(-1.f);
return(1.f);
}
#define todB(x) (*(x)==0?-400.f:FMOD_ogg_log(*(x)**(x))*4.34294480f)
#define todB_nn(x) (*(x)==0.f?-400.f:FMOD_ogg_log(*(x))*8.6858896f)
#endif
#define fromdB(x) (FMOD_ogg_exp((x)*.11512925f))
/* The bark scale equations are approximations, since the original
table was somewhat hand rolled. The below are chosen to have the
best possible fit to the rolled tables, thus their somewhat odd
appearance (these are more accurate and over a longer range than
the oft-quoted bark equations found in the texts I have). The
approximations are valid from 0 - 30kHz (nyquist) or so.
all f in Hz, z in Bark */
#define toBARK(n) (13.1f*FMOD_ogg_atan(.00074f*(n))+2.24f*FMOD_ogg_atan((n)*(n)*1.85e-8f)+1e-4f*(n))
#define fromBARK(z) (102.f*(z)-2.f*FMOD_ogg_pow(z,2.f)+.4f*FMOD_ogg_pow(z,3.f)+FMOD_ogg_pow(1.46f,z)-1.f)
#define toMEL(n) (FMOD_ogg_log(1.f+(n)*.001f)*1442.695f)
#define fromMEL(m) (1000.f*FMOD_ogg_exp((m)/1442.695f)-1000.f)
/* Frequency to octave. We arbitrarily declare 63.5 Hz to be octave
0.0 */
#define toOC(n) (FMOD_ogg_log(n)*1.442695f-5.965784f)
#define fromOC(o) (FMOD_ogg_exp(((o)+5.965784f)*.693147f))
#endif

View file

@ -0,0 +1,782 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: basic shared codebook operations
last mod: $Id: sharedbook.c 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ogg/ogg.h>
#include "os.h"
#include "misc.h"
#include "vorbis/codec.h"
#include "codebook.h"
#include "scales.h"
/**** pack/unpack helpers ******************************************/
int _FMOD_ilog(unsigned int v){
int ret=0;
while(v){
ret++;
v>>=1;
}
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. */
#define VQ_FEXP 10
#define VQ_FMAN 21
#define VQ_FEXP_BIAS 768 /* bias toward values smaller than 1. */
/* doesn't currently guard under/overflow */
ogg_int32_t _FMOD_float32_pack(float val){
int sign=0;
ogg_int32_t exp;
ogg_int32_t mant;
if(val<0){
sign=0x80000000;
val= -val;
}
exp= (ogg_int32_t)FMOD_ogg_floor(FMOD_ogg_log(val)/log(2.f));
mant=(ogg_int32_t)FMOD_ogg_rint(FMOD_ogg_ldexp(val,(VQ_FMAN-1)-exp));
exp=(exp+VQ_FEXP_BIAS)<<VQ_FMAN;
return(sign|exp|mant);
}
float _FMOD_float32_unpack(ogg_int32_t val){
double mant=val&0x1fffff;
int sign=val&0x80000000;
ogg_int32_t exp =(val&0x7fe00000L)>>VQ_FMAN;
if(sign)mant= -mant;
return(FMOD_ogg_ldexp(mant,exp-(VQ_FMAN-1)-VQ_FEXP_BIAS));
}
/* given a list of word lengths, generate a list of codewords. Works
for length ordered or unordered, always assigns the lowest valued
codewords first. Extended to handle unused entries (length 0) */
ogg_uint32_t *_FMOD_make_words(void *context, ogg_int32_t *l,ogg_int32_t n,ogg_int32_t sparsecount){
ogg_int32_t i,j,count=0;
ogg_uint32_t marker[33];
ogg_uint32_t *r=_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r));
if (!r)
{
return(NULL);
}
FMOD_memset(marker,0,sizeof(marker));
for(i=0;i<n;i++){
ogg_int32_t length=l[i];
if(length>0){
ogg_uint32_t entry=marker[length];
/* when we claim a node for an entry, we also claim the nodes
below it (pruning off the imagined tree that may have dangled
from it) as well as blocking the use of any nodes directly
above for leaves */
/* update ourself */
if(length<32 && (entry>>length)){
/* error condition; the lengths must specify an overpopulated tree */
_ogg_free(r);
return(NULL);
}
r[count++]=entry;
/* Look to see if the next shorter marker points to the node
above. if so, update it and repeat. */
{
for(j=length;j>0;j--){
if(marker[j]&1){
/* have to jump branches */
if(j==1)
marker[1]++;
else
marker[j]=marker[j-1]<<1;
break; /* invariant says next upper marker would already
have been moved if it was on the same path */
}
marker[j]++;
}
}
/* prune the tree; the implicit invariant says all the longer
markers were dangling from our just-taken node. Dangle them
from our *new* node. */
for(j=length+1;j<33;j++)
if((marker[j]>>1) == entry){
entry=marker[j];
marker[j]=marker[j-1]<<1;
}else
break;
}else
if(sparsecount==0)count++;
}
/* sanity check the huffman tree; an underpopulated tree must be
rejected. The only exception is the one-node pseudo-nil tree,
which appears to be underpopulated because the tree doesn't
really exist; there's only one possible 'codeword' or zero bits,
but the above tree-gen code doesn't mark that. */
if(sparsecount != 1){
for(i=1;i<33;i++)
if(marker[i] & (0xffffffffUL>>(32-i))){
_ogg_free(r);
return(NULL);
}
}
/* bitreverse the words because our bitwise packer/unpacker is LSb
endian */
for(i=0,count=0;i<n;i++){
ogg_uint32_t temp=0;
for(j=0;j<l[i];j++){
temp<<=1;
temp|=(r[count]>>j)&1;
}
if(sparsecount){
if(l[i])
r[count++]=temp;
}else
r[count++]=temp;
}
return(r);
}
/* 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 */
ogg_int32_t _FMOD_book_maptype1_quantvals(const static_codebook *b){
ogg_int32_t vals=(ogg_int32_t)FMOD_ogg_floor(FMOD_ogg_pow((float)b->entries,1.f/b->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(1){
ogg_int32_t acc=1;
ogg_int32_t acc1=1;
int i;
for(i=0;i<b->dim;i++){
acc*=vals;
acc1*=vals+1;
}
if(acc<=b->entries && acc1>b->entries){
return(vals);
}else{
if(acc>b->entries){
vals--;
}else{
vals++;
}
}
}
}
/* 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 *_FMOD_book_unquantize(void *context, const static_codebook *b,int n,int *sparsemap){
ogg_int32_t j,k,count=0;
if(b->maptype==1 || b->maptype==2){
int quantvals;
float mindel=_FMOD_float32_unpack(b->q_min);
float delta=_FMOD_float32_unpack(b->q_delta);
float *r=_ogg_calloc(n*b->dim,sizeof(*r));
if (!r)
{
return(NULL);
}
/* maptype 1 and 2 both use a quantized value vector, but
different sizes */
switch(b->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=_FMOD_book_maptype1_quantvals(b);
for(j=0;j<b->entries;j++){
if((sparsemap && b->lengthlist[j]) || !sparsemap){
float last=0.f;
int indexdiv=1;
for(k=0;k<b->dim;k++){
int index= (j/indexdiv)%quantvals;
float val=(float)b->quantlist[index];
val=FMOD_ogg_fabs(val)*delta+mindel+last;
if(b->q_sequencep)last=val;
if(sparsemap)
r[sparsemap[count]*b->dim+k]=val;
else
r[count*b->dim+k]=val;
indexdiv*=quantvals;
}
count++;
}
}
break;
case 2:
for(j=0;j<b->entries;j++){
if((sparsemap && b->lengthlist[j]) || !sparsemap){
float last=0.f;
for(k=0;k<b->dim;k++){
float val=(float)b->quantlist[j*b->dim+k];
val=FMOD_ogg_fabs(val)*delta+mindel+last;
if(b->q_sequencep)last=val;
if(sparsemap)
r[sparsemap[count]*b->dim+k]=val;
else
r[count*b->dim+k]=val;
}
count++;
}
}
break;
}
return(r);
}
return(NULL);
}
void FMOD_vorbis_staticbook_clear(void *context, static_codebook *b){
if(b->allocedp){
if(b->quantlist)_ogg_free(b->quantlist);
if(b->lengthlist)_ogg_free(b->lengthlist);
//if(b->nearest_tree){
// _ogg_free(b->nearest_tree->ptr0);
// _ogg_free(b->nearest_tree->ptr1);
// _ogg_free(b->nearest_tree->p);
// _ogg_free(b->nearest_tree->q);
// FMOD_memset(b->nearest_tree,0,sizeof(*b->nearest_tree));
// _ogg_free(b->nearest_tree);
//}
//if(b->thresh_tree){
// _ogg_free(b->thresh_tree->quantthresh);
// _ogg_free(b->thresh_tree->quantmap);
// FMOD_memset(b->thresh_tree,0,sizeof(*b->thresh_tree));
// _ogg_free(b->thresh_tree);
//}
FMOD_memset(b,0,sizeof(*b));
}
}
void FMOD_vorbis_staticbook_destroy(void *context, static_codebook *b){
if(b->allocedp){
FMOD_vorbis_staticbook_clear(context, b);
_ogg_free(b);
}
}
void FMOD_vorbis_book_clear(void *context, codebook *b){
/* static book is not cleared; we're likely called on the lookup and
the static codebook belongs to the info struct */
if(b->valuelist)_ogg_free(b->valuelist);
if(b->codelist)_ogg_free(b->codelist);
if(b->dec_index)_ogg_free(b->dec_index);
if(b->dec_codelengths)_ogg_free(b->dec_codelengths);
if(b->dec_firsttable)_ogg_free(b->dec_firsttable);
FMOD_memset(b,0,sizeof(*b));
}
#if 0
int FMOD_vorbis_book_init_encode(void *context, codebook *c,const static_codebook *s){
FMOD_memset(c,0,sizeof(*c));
c->c=s;
c->entries=s->entries;
c->used_entries=s->entries;
c->dim=s->dim;
c->codelist=_FMOD_make_words(context, s->lengthlist,s->entries,0);
c->valuelist=_FMOD_book_unquantize(context, s,s->entries,NULL);
return(0);
}
#endif
static ogg_uint32_t bitreverse(ogg_uint32_t x){
x= ((x>>16)&0x0000ffff) | ((x<<16)&0xffff0000);
x= ((x>> 8)&0x00ff00ff) | ((x<< 8)&0xff00ff00);
x= ((x>> 4)&0x0f0f0f0f) | ((x<< 4)&0xf0f0f0f0);
x= ((x>> 2)&0x33333333) | ((x<< 2)&0xcccccccc);
return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa);
}
static int sort32a(const void *a,const void *b){
return ( **(ogg_uint32_t **)a>**(ogg_uint32_t **)b)-
( **(ogg_uint32_t **)a<**(ogg_uint32_t **)b);
}
/* decode codebook arrangement is more heavily optimized than encode */
int FMOD_vorbis_book_init_decode(void *context, codebook *c,const static_codebook *s){
int i,j,n=0,tabn;
int *sortindex;
FMOD_memset(c,0,sizeof(*c));
/* count actually used entries */
for(i=0;i<s->entries;i++)
if(s->lengthlist[i]>0)
n++;
c->entries=s->entries;
c->used_entries=n;
c->dim=s->dim;
if(n>0){
/* two different remappings go on here.
First, we collapse the likely sparse codebook down only to
actually represented values/words. This collapsing needs to be
indexed as map-valueless books are used to encode original entry
positions as integers.
Second, we reorder all vectors, including the entry index above,
by sorted bitreversed codeword to allow treeless decode. */
/* perform sort */
ogg_uint32_t *codes=_FMOD_make_words(context, s->lengthlist,s->entries,c->used_entries);
ogg_uint32_t **codep=alloca(sizeof(*codep)*n);
if(codes==NULL)goto err_out;
for(i=0;i<n;i++){
codes[i]=bitreverse(codes[i]);
codep[i]=codes+i;
}
qsort(codep,n,sizeof(*codep),sort32a);
sortindex=alloca(n*sizeof(*sortindex));
c->codelist=_ogg_malloc(n*sizeof(*c->codelist));
if (!c->codelist)
{
goto err_out;
}
/* the index is a reverse index */
for(i=0;i<n;i++){
int position=codep[i]-codes;
sortindex[position]=i;
}
for(i=0;i<n;i++)
c->codelist[sortindex[i]]=codes[i];
_ogg_free(codes);
c->valuelist=_FMOD_book_unquantize(context, s,n,sortindex);
c->dec_index=_ogg_malloc(n*sizeof(*c->dec_index));
if (!c->dec_index)
{
goto err_out;
}
for(n=0,i=0;i<s->entries;i++)
if(s->lengthlist[i]>0)
c->dec_index[sortindex[n++]]=i;
c->dec_codelengths=_ogg_malloc(n*sizeof(*c->dec_codelengths));
if (!c->dec_codelengths)
{
goto err_out;
}
for(n=0,i=0;i<s->entries;i++)
if(s->lengthlist[i]>0)
c->dec_codelengths[sortindex[n++]]=s->lengthlist[i];
c->dec_firsttablen=_FMOD_ilog(c->used_entries)-4; /* this is magic */
if(c->dec_firsttablen<5)c->dec_firsttablen=5;
if(c->dec_firsttablen>8)c->dec_firsttablen=8;
tabn=1<<c->dec_firsttablen;
c->dec_firsttable=_ogg_calloc(tabn,sizeof(*c->dec_firsttable));
if (!c->dec_firsttable)
{
goto err_out;
}
c->dec_maxlength=0;
for(i=0;i<n;i++){
if(c->dec_maxlength<c->dec_codelengths[i])
c->dec_maxlength=c->dec_codelengths[i];
if(c->dec_codelengths[i]<=c->dec_firsttablen){
ogg_uint32_t orig=bitreverse(c->codelist[i]);
for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++)
c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1;
}
}
/* now fill in 'unused' entries in the firsttable with hi/lo search
hints for the non-direct-hits */
{
ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen);
ogg_int32_t lo=0,hi=0;
for(i=0;i<tabn;i++){
ogg_uint32_t word=i<<(32-c->dec_firsttablen);
if(c->dec_firsttable[bitreverse(word)]==0){
while((lo+1)<n && c->codelist[lo+1]<=word)lo++;
while( hi<n && word>=(c->codelist[hi]&mask))hi++;
/* we only actually have 15 bits per hint to play with here.
In order to overflow gracefully (nothing breaks, efficiency
just drops), encode as the difference from the extremes. */
{
ogg_uint32_t loval=lo;
ogg_uint32_t hival=n-hi;
if(loval>0x7fff)loval=0x7fff;
if(hival>0x7fff)hival=0x7fff;
c->dec_firsttable[bitreverse(word)]=
0x80000000UL | (loval<<15) | hival;
}
}
}
}
}
return(0);
err_out:
FMOD_vorbis_book_clear(context, c);
return(-1);
}
static float _dist(int el,float *ref, float *b,int step){
int i;
float acc=0.f;
for(i=0;i<el;i++){
float val=(ref[i]-b[i*step]);
acc+=val*val;
}
return(acc);
}
#if 0
int _FMOD_best(codebook *book, float *a, int step){
encode_aux_threshmatch *tt=book->c->thresh_tree;
#if 0
encode_aux_nearestmatch *nt=book->c->nearest_tree;
encode_aux_pigeonhole *pt=book->c->pigeon_tree;
#endif
int dim=book->dim;
int k,o;
/*int savebest=-1;
float saverr;*/
/* do we have a threshhold encode hint? */
if(tt){
int index=0,i;
/* find the quant val of each scalar */
for(k=0,o=step*(dim-1);k<dim;k++,o-=step){
i=tt->threshvals>>1;
if(a[o]<tt->quantthresh[i]){
for(;i>0;i--)
if(a[o]>=tt->quantthresh[i-1])
break;
}else{
for(i++;i<tt->threshvals-1;i++)
if(a[o]<tt->quantthresh[i])break;
}
index=(index*tt->quantvals)+tt->quantmap[i];
}
/* regular lattices are easy :-) */
if(book->c->lengthlist[index]>0) /* is this unused? If so, we'll
use a decision tree after all
and fall through*/
return(index);
}
#if 0
/* do we have a pigeonhole encode hint? */
if(pt){
const static_codebook *c=book->c;
int i,besti=-1;
float best=0.f;
int entry=0;
/* dealing with sequentialness is a pain in the ass */
if(c->q_sequencep){
int pv;
ogg_int32_t mul=1;
float qlast=0;
for(k=0,o=0;k<dim;k++,o+=step){
pv=(int)((a[o]-qlast-pt->min)/pt->del);
if(pv<0 || pv>=pt->mapentries)break;
entry+=pt->pigeonmap[pv]*mul;
mul*=pt->quantvals;
qlast+=pv*pt->del+pt->min;
}
}else{
for(k=0,o=step*(dim-1);k<dim;k++,o-=step){
int pv=(int)((a[o]-pt->min)/pt->del);
if(pv<0 || pv>=pt->mapentries)break;
entry=entry*pt->quantvals+pt->pigeonmap[pv];
}
}
/* must be within the pigeonholable range; if we quant outside (or
in an entry that we define no list for), brute force it */
if(k==dim && pt->fitlength[entry]){
/* search the abbreviated list */
ogg_int32_t *list=pt->fitlist+pt->fitmap[entry];
for(i=0;i<pt->fitlength[entry];i++){
float this=_dist(dim,book->valuelist+list[i]*dim,a,step);
if(besti==-1 || this<best){
best=this;
besti=list[i];
}
}
return(besti);
}
}
if(nt){
/* optimized using the decision tree */
while(1){
float c=0.f;
float *p=book->valuelist+nt->p[ptr];
float *q=book->valuelist+nt->q[ptr];
for(k=0,o=0;k<dim;k++,o+=step)
c+=(p[k]-q[k])*(a[o]-(p[k]+q[k])*.5);
if(c>0.f) /* in A */
ptr= -nt->ptr0[ptr];
else /* in B */
ptr= -nt->ptr1[ptr];
if(ptr<=0)break;
}
return(-ptr);
}
#endif
/* brute force it! */
{
const static_codebook *c=book->c;
int i,besti=-1;
float best=0.f;
float *e=book->valuelist;
for(i=0;i<book->entries;i++){
if(c->lengthlist[i]>0){
float this=_dist(dim,e,a,step);
if(besti==-1 || this<best){
best=this;
besti=i;
}
}
e+=dim;
}
/*if(savebest!=-1 && savebest!=besti){
fprintf(stderr,"brute force/pigeonhole disagreement:\n"
"original:");
for(i=0;i<dim*step;i+=step)fprintf(stderr,"%g,",a[i]);
fprintf(stderr,"\n"
"pigeonhole (entry %d, err %g):",savebest,saverr);
for(i=0;i<dim;i++)fprintf(stderr,"%g,",
(book->valuelist+savebest*dim)[i]);
fprintf(stderr,"\n"
"bruteforce (entry %d, err %g):",besti,best);
for(i=0;i<dim;i++)fprintf(stderr,"%g,",
(book->valuelist+besti*dim)[i]);
fprintf(stderr,"\n");
}*/
return(besti);
}
}
ogg_int32_t vorbis_book_codeword(codebook *book,int entry){
if(book->c) /* only use with encode; decode optimizations are
allowed to break this */
return book->codelist[entry];
return -1;
}
ogg_int32_t vorbis_book_codelen(codebook *book,int entry){
if(book->c) /* only use with encode; decode optimizations are
allowed to break this */
return book->c->lengthlist[entry];
return -1;
}
#endif
#ifdef _V_SELFTEST
/* Unit tests of the dequantizer; this stuff will be OK
cross-platform, I simply want to be sure that special mapping cases
actually work properly; a bug could go unnoticed for a while */
#include <stdio.h>
/* cases:
no mapping
full, explicit mapping
algorithmic mapping
nonsequential
sequential
*/
static ogg_int32_t full_quantlist1[]={0,1,2,3, 4,5,6,7, 8,3,6,1};
static ogg_int32_t partial_quantlist1[]={0,7,2};
/* no mapping */
static_codebook test1={
4,16,
NULL,
0,
0,0,0,0,
NULL,
NULL,NULL,NULL,
0
};
static float *test1_result=NULL;
/* linear, full mapping, nonsequential */
static_codebook test2={
4,3,
NULL,
2,
-533200896,1611661312,4,0,
full_quantlist1,
NULL,NULL,NULL,
0
};
static float test2_result[]={-3,-2,-1,0, 1,2,3,4, 5,0,3,-2};
/* linear, full mapping, sequential */
static_codebook test3={
4,3,
NULL,
2,
-533200896,1611661312,4,1,
full_quantlist1,
NULL,NULL,NULL,
0
};
static float test3_result[]={-3,-5,-6,-6, 1,3,6,10, 5,5,8,6};
/* linear, algorithmic mapping, nonsequential */
static_codebook test4={
3,27,
NULL,
1,
-533200896,1611661312,4,0,
partial_quantlist1,
NULL,NULL,NULL,
0
};
static float test4_result[]={-3,-3,-3, 4,-3,-3, -1,-3,-3,
-3, 4,-3, 4, 4,-3, -1, 4,-3,
-3,-1,-3, 4,-1,-3, -1,-1,-3,
-3,-3, 4, 4,-3, 4, -1,-3, 4,
-3, 4, 4, 4, 4, 4, -1, 4, 4,
-3,-1, 4, 4,-1, 4, -1,-1, 4,
-3,-3,-1, 4,-3,-1, -1,-3,-1,
-3, 4,-1, 4, 4,-1, -1, 4,-1,
-3,-1,-1, 4,-1,-1, -1,-1,-1};
/* linear, algorithmic mapping, sequential */
static_codebook test5={
3,27,
NULL,
1,
-533200896,1611661312,4,1,
partial_quantlist1,
NULL,NULL,NULL,
0
};
static float test5_result[]={-3,-6,-9, 4, 1,-2, -1,-4,-7,
-3, 1,-2, 4, 8, 5, -1, 3, 0,
-3,-4,-7, 4, 3, 0, -1,-2,-5,
-3,-6,-2, 4, 1, 5, -1,-4, 0,
-3, 1, 5, 4, 8,12, -1, 3, 7,
-3,-4, 0, 4, 3, 7, -1,-2, 2,
-3,-6,-7, 4, 1, 0, -1,-4,-5,
-3, 1, 0, 4, 8, 7, -1, 3, 2,
-3,-4,-5, 4, 3, 2, -1,-2,-3};
void run_test(static_codebook *b,float *comp){
float *out=_FMOD_book_unquantize(context, b,b->entries,NULL);
int i;
if(comp){
if(!out){
fprintf(stderr,"_book_unquantize incorrectly returned NULL\n");
exit(1);
}
for(i=0;i<b->entries*b->dim;i++)
if(FMOD_ogg_fabs(out[i]-comp[i])>.0001f){
fprintf(stderr,"disagreement in unquantized and reference data:\n"
"position %d, %g != %g\n",i,out[i],comp[i]);
exit(1);
}
}else{
if(out){
fprintf(stderr,"_book_unquantize returned a value array: \n"
" correct result should have been NULL\n");
exit(1);
}
}
}
int main(){
/* run the nine dequant tests, and compare to the hand-rolled results */
fprintf(stderr,"Dequant test 1... ");
run_test(&test1,test1_result);
fprintf(stderr,"OK\nDequant test 2... ");
run_test(&test2,test2_result);
fprintf(stderr,"OK\nDequant test 3... ");
run_test(&test3,test3_result);
fprintf(stderr,"OK\nDequant test 4... ");
run_test(&test4,test4_result);
fprintf(stderr,"OK\nDequant test 5... ");
run_test(&test5,test5_result);
fprintf(stderr,"OK\n\n");
return(0);
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,34 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: fft transform
last mod: $Id: smallft.h 13293 2007-07-24 00:09:47Z xiphmont $
********************************************************************/
#ifndef _V_SMFT_H_
#define _V_SMFT_H_
#include "vorbis/codec.h"
typedef struct {
int n;
float *trigcache;
int *splitcache;
} drft_lookup;
extern void drft_forward(drft_lookup *l,float *data);
extern void drft_backward(drft_lookup *l,float *data);
extern void drft_init(void *context, drft_lookup *l,int n);
extern void drft_clear(void *context, drft_lookup *l);
#endif

View file

@ -0,0 +1,189 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: single-block PCM synthesis
last mod: $Id: synthesis.c 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
#include <stdio.h>
#include <ogg/ogg.h>
#include "vorbis/codec.h"
#include "codec_internal.h"
#include "registry.h"
#include "misc.h"
#include "os.h"
int FMOD_vorbis_synthesis(void *context, vorbis_block *vb,ogg_packet *op){
vorbis_dsp_state *vd=vb->vd;
private_state *b=vd->backend_state;
vorbis_info *vi=vd->vi;
codec_setup_info *ci=vi->codec_setup;
oggpack_buffer *opb=&vb->opb;
int type,mode,i,ret;
/* first things first. Make sure decode is ready */
ret = _FMOD_vorbis_block_ripcord(context, vb);
if (ret)
{
return ret;
}
FMOD_oggpack_readinit(opb,op->packet,op->bytes);
/* Check the packet type */
if(FMOD_oggpack_read(opb,1)!=0){
/* Oops. This is not an audio data packet */
return(OV_ENOTAUDIO);
}
/* read our mode and pre/post windowsize */
mode=FMOD_oggpack_read(opb,b->modebits);
if(mode==-1)return(OV_EBADPACKET);
vb->mode=mode;
vb->W=ci->mode_param[mode]->blockflag;
if(vb->W){
/* this doesn;t get mapped through mode selection as it's used
only for window selection */
vb->lW=FMOD_oggpack_read(opb,1);
vb->nW=FMOD_oggpack_read(opb,1);
if(vb->nW==-1) return(OV_EBADPACKET);
}else{
vb->lW=0;
vb->nW=0;
}
/* more setup */
vb->granulepos=op->granulepos;
vb->sequence=op->packetno;
vb->eofflag=op->e_o_s;
/* alloc pcm passback storage */
vb->pcmend=ci->blocksizes[vb->W];
vb->pcm=_FMOD_vorbis_block_alloc(context, vb,sizeof(*vb->pcm)*vi->channels);
if (!vb->pcm)
{
return(OV_EMEMORY);
}
for(i=0;i<vi->channels;i++)
{
vb->pcm[i]=_FMOD_vorbis_block_alloc(context, vb,vb->pcmend*sizeof(*vb->pcm[i]));
if (!vb->pcm[i])
{
return(OV_EMEMORY);
}
}
/* unpack_header enforces range checking */
type=ci->map_type[ci->mode_param[mode]->mapping];
return(_FMOD_mapping_P[type]->inverse(context, vb,ci->map_param[ci->mode_param[mode]->
mapping]));
}
/* used to track pcm position without actually performing decode.
Useful for sequential 'fast forward' */
int FMOD_vorbis_synthesis_trackonly(void *context, vorbis_block *vb,ogg_packet *op){
vorbis_dsp_state *vd=vb->vd;
private_state *b=vd->backend_state;
vorbis_info *vi=vd->vi;
codec_setup_info *ci=vi->codec_setup;
oggpack_buffer *opb=&vb->opb;
int mode,ret;
/* first things first. Make sure decode is ready */
ret = _FMOD_vorbis_block_ripcord(context, vb);
if (ret)
{
return ret;
}
FMOD_oggpack_readinit(opb,op->packet,op->bytes);
/* Check the packet type */
if(FMOD_oggpack_read(opb,1)!=0){
/* Oops. This is not an audio data packet */
return(OV_ENOTAUDIO);
}
/* read our mode and pre/post windowsize */
mode=FMOD_oggpack_read(opb,b->modebits);
if(mode==-1)return(OV_EBADPACKET);
vb->mode=mode;
vb->W=ci->mode_param[mode]->blockflag;
if(vb->W){
vb->lW=FMOD_oggpack_read(opb,1);
vb->nW=FMOD_oggpack_read(opb,1);
if(vb->nW==-1) return(OV_EBADPACKET);
}else{
vb->lW=0;
vb->nW=0;
}
/* more setup */
vb->granulepos=op->granulepos;
vb->sequence=op->packetno;
vb->eofflag=op->e_o_s;
/* no pcm */
vb->pcmend=0;
vb->pcm=NULL;
return(0);
}
ogg_int32_t FMOD_vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){
codec_setup_info *ci=vi->codec_setup;
oggpack_buffer opb;
int mode;
FMOD_oggpack_readinit(&opb,op->packet,op->bytes);
/* Check the packet type */
if(FMOD_oggpack_read(&opb,1)!=0){
/* Oops. This is not an audio data packet */
return(OV_ENOTAUDIO);
}
{
int modebits=0;
int v=ci->modes;
while(v>1){
modebits++;
v>>=1;
}
/* read our mode and pre/post windowsize */
mode=FMOD_oggpack_read(&opb,modebits);
}
if(mode==-1)return(OV_EBADPACKET);
return(ci->blocksizes[ci->mode_param[mode]->blockflag]);
}
int FMOD_vorbis_synthesis_halfrate(vorbis_info *vi,int flag){
/* set / clear half-sample-rate mode */
codec_setup_info *ci=vi->codec_setup;
/* right now, our MDCT can't handle < 64 sample windows. */
if(ci->blocksizes[0]<=64 && flag)return -1;
ci->halfrate_flag=(flag?1:0);
return 0;
}
int FMOD_vorbis_synthesis_halfrate_p(vorbis_info *vi){
codec_setup_info *ci=vi->codec_setup;
return ci->halfrate_flag;
}

File diff suppressed because it is too large Load diff

2193
lib/ogg_vorbis/vorbis/lib/window.c Executable file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,33 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: window functions
last mod: $Id: window.h 13293 2007-07-24 00:09:47Z xiphmont $
********************************************************************/
#ifndef _V_WINDOW_
#define _V_WINDOW_
#ifdef __cplusplus
extern "C" {
#endif
extern void _FMOD_vorbis_window_init(); /* Added by brett */
extern float *_FMOD_vorbis_window_get(int n);
extern void _FMOD_vorbis_apply_window(float *d,int *winno,ogg_int32_t *blocksizes,
int lW,int W,int nW);
#ifdef __cplusplus
}
#endif
#endif