Switch to the lowmem tremor branch

in addition to using slightly less memory, this branch also doesn't seem
to have the same issues with `-O2` builds that the main branch has.
This commit is contained in:
jacqueline
2024-02-14 12:21:33 +11:00
parent b31bc07555
commit 7ec0ff2589
51 changed files with 5712 additions and 7148 deletions
+166 -178
View File
@@ -1,12 +1,12 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
* THIS FILE IS PART OF THE TremorOggVorbis 'TREMOR' 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 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
* THE TremorOggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 *
* BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
* *
********************************************************************
@@ -18,26 +18,15 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ogg/ogg.h>
#include "tremor_ogg.h"
#include "ivorbiscodec.h"
#include "codec_internal.h"
#include "registry.h"
#include "codebook.h"
#include "misc.h"
#include "block.h"
#include "os.h"
#define LSP_FRACBITS 14
typedef struct {
long n;
int ln;
int m;
int *linearmap;
vorbis_info_floor0 *vi;
ogg_int32_t *lsp_look;
} vorbis_look_floor0;
extern const tremor_ogg_int32_t FLOOR_fromdB_LOOKUP[];
/*************** LSP decode ********************/
@@ -48,7 +37,7 @@ typedef struct {
returns in m.8 format */
static long ADJUST_SQRT2[2]={8192,5792};
STIN ogg_int32_t vorbis_invsqlook_i(long a,long e){
static inline tremor_ogg_int32_t vorbis_invsqlook_i(long a,long e){
long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1);
long d=a&INVSQ_LOOKUP_I_MASK; /* 0.10 */
long val=INVSQ_LOOKUP_I[i]- /* 1.16 */
@@ -60,60 +49,60 @@ STIN ogg_int32_t vorbis_invsqlook_i(long a,long e){
/* interpolated lookup based fromdB function, domain -140dB to 0dB only */
/* a is in n.12 format */
STIN ogg_int32_t vorbis_fromdBlook_i(long a){
int i=(-a)>>(12-FROMdB2_SHIFT);
if(i<0) return 0x7fffffff;
if(i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))return 0;
return FROMdB_LOOKUP[i>>FROMdB_SHIFT] * FROMdB2_LOOKUP[i&FROMdB2_MASK];
#ifdef _LOW_ACCURACY_
static inline tremor_ogg_int32_t vorbis_fromdBlook_i(long a){
if(a>0) return 0x7fffffff;
if(a<(-140<<12)) return 0;
return FLOOR_fromdB_LOOKUP[((a+140)*467)>>20]<<9;
}
#else
static inline tremor_ogg_int32_t vorbis_fromdBlook_i(long a){
if(a>0) return 0x7fffffff;
if(a<(-140<<12)) return 0;
return FLOOR_fromdB_LOOKUP[((a+(140<<12))*467)>>20];
}
#endif
/* interpolated lookup based cos function, domain 0 to PI only */
/* a is in 0.16 format, where 0==0, 2^^16-1==PI, return 0.14 */
STIN ogg_int32_t vorbis_coslook_i(long a){
static inline tremor_ogg_int32_t vorbis_coslook_i(long a){
int i=a>>COS_LOOKUP_I_SHIFT;
int d=a&COS_LOOKUP_I_MASK;
return COS_LOOKUP_I[i]- ((d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
COS_LOOKUP_I_SHIFT);
}
/* interpolated lookup based cos function */
/* interpolated half-wave lookup based cos function */
/* a is in 0.16 format, where 0==0, 2^^16==PI, return .LSP_FRACBITS */
STIN ogg_int32_t vorbis_coslook2_i(long a){
a=a&0x1ffff;
if(a>0x10000)a=0x20000-a;
{
int i=a>>COS_LOOKUP_I_SHIFT;
int d=a&COS_LOOKUP_I_MASK;
a=((COS_LOOKUP_I[i]<<COS_LOOKUP_I_SHIFT)-
d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
(COS_LOOKUP_I_SHIFT-LSP_FRACBITS+14);
}
return(a);
static inline tremor_ogg_int32_t vorbis_coslook2_i(long a){
int i=a>>COS_LOOKUP_I_SHIFT;
int d=a&COS_LOOKUP_I_MASK;
return ((COS_LOOKUP_I[i]<<COS_LOOKUP_I_SHIFT)-
d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
(COS_LOOKUP_I_SHIFT-LSP_FRACBITS+14);
}
static const int barklook[28]={
0,100,200,301, 405,516,635,766,
912,1077,1263,1476, 1720,2003,2333,2721,
3184,3742,4428,5285, 6376,7791,9662,12181,
15624,20397,27087,36554
static const tremor_ogg_uint16_t barklook[54]={
0,51,102,154, 206,258,311,365,
420,477,535,594, 656,719,785,854,
926,1002,1082,1166, 1256,1352,1454,1564,
1683,1812,1953,2107, 2276,2463,2670,2900,
3155,3440,3756,4106, 4493,4919,5387,5901,
6466,7094,7798,8599, 9528,10623,11935,13524,
15453,17775,20517,23667, 27183,31004
};
/* used in init only; interpolate the long way */
STIN ogg_int32_t toBARK(int n){
static inline tremor_ogg_int32_t toBARK(int n){
int i;
for(i=0;i<27;i++)
for(i=0;i<54;i++)
if(n>=barklook[i] && n<barklook[i+1])break;
if(i==27){
return 27<<15;
if(i==54){
return 54<<14;
}else{
int gap=barklook[i+1]-barklook[i];
int del=n-barklook[i];
return((i<<15)+((del<<15)/gap));
return (i<<14)+(((n-barklook[i])*
((1UL<<31)/(barklook[i+1]-barklook[i])))>>17);
}
}
@@ -133,11 +122,11 @@ static const unsigned char MLOOP_2[64]={
static const unsigned char MLOOP_3[8]={0,1,2,2,3,3,3,3};
void vorbis_lsp_to_curve(ogg_int32_t *curve,int *map,int n,int ln,
ogg_int32_t *lsp,int m,
ogg_int32_t amp,
ogg_int32_t ampoffset,
ogg_int32_t *icos){
void vorbis_lsp_to_curve(tremor_ogg_int32_t *curve,int n,int ln,
tremor_ogg_int32_t *lsp,int m,
tremor_ogg_int32_t amp,
tremor_ogg_int32_t ampoffset,
tremor_ogg_int32_t nyq){
/* 0 <= m < 256 */
@@ -145,13 +134,34 @@ void vorbis_lsp_to_curve(ogg_int32_t *curve,int *map,int n,int ln,
int i;
int ampoffseti=ampoffset*4096;
int ampi=amp;
ogg_int32_t *ilsp=(ogg_int32_t *)alloca(m*sizeof(*ilsp));
tremor_ogg_int32_t *ilsp=(tremor_ogg_int32_t *)alloca(m*sizeof(*ilsp));
tremor_ogg_uint32_t inyq= (1UL<<31) / toBARK(nyq);
tremor_ogg_uint32_t imap= (1UL<<31) / ln;
tremor_ogg_uint32_t tBnyq1 = toBARK(nyq)<<1;
/* Besenham for frequency scale to avoid a division */
int f=0;
int fdx=n;
int fbase=nyq/fdx;
int ferr=0;
int fdy=nyq-fbase*fdx;
int map=0;
#ifdef _LOW_ACCURACY_
tremor_ogg_uint32_t nextbark=((tBnyq1<<11)/ln)>>12;
#else
tremor_ogg_uint32_t nextbark=MULT31(imap>>1,tBnyq1);
#endif
int nextf=barklook[nextbark>>14]+(((nextbark&0x3fff)*
(barklook[(nextbark>>14)+1]-barklook[nextbark>>14]))>>14);
/* lsp is in 8.24, range 0 to PI; coslook wants it in .16 0 to 1*/
for(i=0;i<m;i++){
#ifndef _LOW_ACCURACY_
ogg_int32_t val=MULT32(lsp[i],0x517cc2);
tremor_ogg_int32_t val=MULT32(lsp[i],0x517cc2);
#else
ogg_int32_t val=((lsp[i]>>10)*0x517d)>>14;
tremor_ogg_int32_t val=((lsp[i]>>10)*0x517d)>>14;
#endif
/* safeguard against a malicious stream */
@@ -165,11 +175,14 @@ void vorbis_lsp_to_curve(ogg_int32_t *curve,int *map,int n,int ln,
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;
ogg_int32_t qexp=0,shift;
ogg_int32_t wi=icos[k];
int j;
tremor_ogg_uint32_t pi=46341; /* 2**-.5 in 0.16 */
tremor_ogg_uint32_t qi=46341;
tremor_ogg_int32_t qexp=0,shift;
tremor_ogg_int32_t wi;
wi=vorbis_coslook2_i((map*imap)>>15);
#ifdef _V_LSP_MATH_ASM
lsp_loop_asm(&qi,&pi,&qexp,ilsp,wi,m);
@@ -197,24 +210,22 @@ void vorbis_lsp_to_curve(ogg_int32_t *curve,int *map,int n,int ln,
#else
j=1;
if(m>1){
qi*=labs(ilsp[0]-wi);
pi*=labs(ilsp[1]-wi);
qi*=labs(ilsp[0]-wi);
pi*=labs(ilsp[1]-wi);
for(j+=2;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;
}
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){
@@ -282,54 +293,78 @@ void vorbis_lsp_to_curve(ogg_int32_t *curve,int *map,int n,int ln,
amp>>=9;
#endif
curve[i]= MULT31_SHIFT15(curve[i],amp);
while(map[++i]==k) curve[i]= MULT31_SHIFT15(curve[i],amp);
while(++i<n){
/* line plot to get new f */
ferr+=fdy;
if(ferr>=fdx){
ferr-=fdx;
f++;
}
f+=fbase;
if(f>=nextf)break;
curve[i]= MULT31_SHIFT15(curve[i],amp);
}
while(1){
map++;
if(map+1<ln){
#ifdef _LOW_ACCURACY_
nextbark=((tBnyq1<<11)/ln*(map+1))>>12;
#else
nextbark=MULT31((map+1)*(imap>>1),tBnyq1);
#endif
nextf=barklook[nextbark>>14]+
(((nextbark&0x3fff)*
(barklook[(nextbark>>14)+1]-barklook[nextbark>>14]))>>14);
if(f<=nextf)break;
}else{
nextf=9999999;
break;
}
}
if(map>=ln){
map=ln-1; /* guard against the approximation */
nextf=9999999;
}
}
}
/*************** vorbis decode glue ************/
static void floor0_free_info(vorbis_info_floor *i){
void floor0_free_info(vorbis_info_floor *i){
vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
if(info){
memset(info,0,sizeof(*info));
_ogg_free(info);
}
if(info)_tremor_ogg_free(info);
}
static void floor0_free_look(vorbis_look_floor *i){
vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
if(look){
if(look->linearmap)_ogg_free(look->linearmap);
if(look->lsp_look)_ogg_free(look->lsp_look);
memset(look,0,sizeof(*look));
_ogg_free(look);
}
}
static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
vorbis_info_floor *floor0_info_unpack (vorbis_info *vi,tremor_oggpack_buffer *opb){
codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
int j;
vorbis_info_floor0 *info=(vorbis_info_floor0 *)_ogg_malloc(sizeof(*info));
info->order=oggpack_read(opb,8);
info->rate=oggpack_read(opb,16);
info->barkmap=oggpack_read(opb,16);
info->ampbits=oggpack_read(opb,6);
info->ampdB=oggpack_read(opb,8);
info->numbooks=oggpack_read(opb,4)+1;
vorbis_info_floor0 *info=(vorbis_info_floor0 *)_tremor_ogg_malloc(sizeof(*info));
info->order=tremor_oggpack_read(opb,8);
info->rate=tremor_oggpack_read(opb,16);
info->barkmap=tremor_oggpack_read(opb,16);
info->ampbits=tremor_oggpack_read(opb,6);
info->ampdB=tremor_oggpack_read(opb,8);
info->numbooks=tremor_oggpack_read(opb,4)+1;
if(info->order<1)goto err_out;
if(info->rate<1)goto err_out;
if(info->barkmap<1)goto err_out;
if(info->numbooks<1)goto err_out;
for(j=0;j<info->numbooks;j++){
info->books[j]=oggpack_read(opb,8);
if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
if(ci->book_param[info->books[j]]->maptype==0)goto err_out;
if(ci->book_param[info->books[j]]->dim<1)goto err_out;
info->books[j]=tremor_oggpack_read(opb,8);
if(info->books[j]>=ci->books)goto err_out;
}
if(tremor_oggpack_eop(opb))goto err_out;
return(info);
err_out:
@@ -337,74 +372,34 @@ static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
return(NULL);
}
/* initialize Bark scale and normalization lookups. We could do this
with static tables, but Vorbis allows a number of possible
combinations, so it's best to do it computationally.
The below is authoritative in terms of defining scale mapping.
Note that the scale depends on the sampling rate as well as the
linear block and mapping sizes */
static vorbis_look_floor *floor0_look (vorbis_dsp_state *vd,vorbis_info_mode *mi,
vorbis_info_floor *i){
int j;
vorbis_info *vi=vd->vi;
codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
int floor0_memosize(vorbis_info_floor *i){
vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
vorbis_look_floor0 *look=(vorbis_look_floor0 *)_ogg_calloc(1,sizeof(*look));
look->m=info->order;
look->n=ci->blocksizes[mi->blockflag]/2;
look->ln=info->barkmap;
look->vi=info;
/* the mapping from a linear scale to a smaller bark scale is
straightforward. We do *not* make sure that the linear mapping
does not skip bark-scale bins; the decoder simply skips them and
the encoder may do what it wishes in filling them. They're
necessary in some mapping combinations to keep the scale spacing
accurate */
look->linearmap=(int *)_ogg_malloc((look->n+1)*sizeof(*look->linearmap));
for(j=0;j<look->n;j++){
int val=(look->ln*
((toBARK(info->rate/2*j/look->n)<<11)/toBARK(info->rate/2)))>>11;
if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
look->linearmap[j]=val;
}
look->linearmap[j]=-1;
look->lsp_look=(ogg_int32_t *)_ogg_malloc(look->ln*sizeof(*look->lsp_look));
for(j=0;j<look->ln;j++)
look->lsp_look[j]=vorbis_coslook2_i(0x10000*j/look->ln);
return look;
return info->order+1;
}
static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
vorbis_info_floor0 *info=look->vi;
tremor_ogg_int32_t *floor0_inverse1(vorbis_dsp_state *vd,vorbis_info_floor *i,
tremor_ogg_int32_t *lsp){
vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
int j,k;
int ampraw=oggpack_read(&vb->opb,info->ampbits);
int ampraw=tremor_oggpack_read(&vd->opb,info->ampbits);
if(ampraw>0){ /* also handles the -1 out of data case */
long maxval=(1<<info->ampbits)-1;
int amp=((ampraw*info->ampdB)<<4)/maxval;
int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
int booknum=tremor_oggpack_read(&vd->opb,_ilog(info->numbooks));
if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup;
codebook *b=ci->fullbooks+info->books[booknum];
ogg_int32_t last=0;
ogg_int32_t *lsp=(ogg_int32_t *)_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+1));
codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup;
codebook *b=ci->book_param+info->books[booknum];
tremor_ogg_int32_t last=0;
if(vorbis_book_decodev_set(b,lsp,&vb->opb,look->m,-24)==-1)goto eop;
for(j=0;j<look->m;){
for(k=0;j<look->m && k<b->dim;k++,j++)lsp[j]+=last;
if(vorbis_book_decodev_set(b,lsp,&vd->opb,info->order,-24)==-1)goto eop;
for(j=0;j<info->order;){
for(k=0;j<info->order && k<b->dim;k++,j++)lsp[j]+=last;
last=lsp[j-1];
}
lsp[look->m]=amp;
lsp[info->order]=amp;
return(lsp);
}
}
@@ -412,28 +407,21 @@ static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
return(NULL);
}
static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
void *memo,ogg_int32_t *out){
vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
vorbis_info_floor0 *info=look->vi;
int floor0_inverse2(vorbis_dsp_state *vd,vorbis_info_floor *i,
tremor_ogg_int32_t *lsp,tremor_ogg_int32_t *out){
vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup;
if(memo){
ogg_int32_t *lsp=(ogg_int32_t *)memo;
ogg_int32_t amp=lsp[look->m];
if(lsp){
tremor_ogg_int32_t amp=lsp[info->order];
/* take the coefficients back to a spectral envelope curve */
vorbis_lsp_to_curve(out,look->linearmap,look->n,look->ln,
lsp,look->m,amp,info->ampdB,look->lsp_look);
vorbis_lsp_to_curve(out,ci->blocksizes[vd->W]/2,info->barkmap,
lsp,info->order,amp,info->ampdB,
info->rate>>1);
return(1);
}
memset(out,0,sizeof(*out)*look->n);
memset(out,0,sizeof(*out)*ci->blocksizes[vd->W]/2);
return(0);
}
/* export hooks */
vorbis_func_floor floor0_exportbundle={
&floor0_unpack,&floor0_look,&floor0_free_info,
&floor0_free_look,&floor0_inverse1,&floor0_inverse2
};