d9a291f641
Took the opportunity to undo the Godot changed made to the opus source. The opus module should eventually be built in its own environment to avoid polluting others with too many include dirs and defines. TODO: Fix the platform/ stuff for opus.
525 lines
16 KiB
C
525 lines
16 KiB
C
/********************************************************************
|
|
* *
|
|
* 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: simple utility that runs audio through the psychoacoustics
|
|
without encoding
|
|
last mod: $Id: psytune.c 16037 2009-05-26 21:10:58Z xiphmont $
|
|
|
|
********************************************************************/
|
|
|
|
/* NB: this is dead code, retained purely for doc and reference value
|
|
don't try to compile it */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#include "vorbis/codec.h"
|
|
#include "codec_internal.h"
|
|
#include "os.h"
|
|
#include "misc.h"
|
|
#include "psy.h"
|
|
#include "mdct.h"
|
|
#include "smallft.h"
|
|
#include "window.h"
|
|
#include "scales.h"
|
|
#include "lpc.h"
|
|
#include "lsp.h"
|
|
#include "masking.h"
|
|
#include "registry.h"
|
|
|
|
static vorbis_info_psy_global _psy_set0G={
|
|
0, /* decaydBpms */
|
|
8, /* lines per eighth octave */
|
|
|
|
/* thresh sample period, preecho clamp trigger threshhold, range, minenergy */
|
|
256, {26.f,26.f,26.f,30.f}, {-90.f,-90.f,-90.f,-90.f}, -90.f,
|
|
-6.f,
|
|
|
|
0,
|
|
|
|
0.,
|
|
0.,
|
|
};
|
|
|
|
static vp_part _vp_part0[]={
|
|
{ 1,9e10f, 9e10f, 1.f,9999.f},
|
|
{ 9999, .75f, 9e10f, .5f,9999.f},
|
|
/*{ 9999, 1.5f, 9e10f, .5f,9999.f},*/
|
|
{ 18,9e10f, 9e10f, .5f, 30.f},
|
|
{ 9999,9e10f, 9e10f, .5f, 30.f}
|
|
};
|
|
|
|
static vp_couple _vp_couple0[]={
|
|
{ 1, {9e10f,9e10f,0}, { 0.f, 0.f,0}, { 0.f, 0.f,0}, {0.f,0.f,0}},
|
|
{ 18, {9e10f,9e10f,0}, { 0.f, 0.f,0}, { 0.f, 0.f,0}, {0.f,0.f,0}},
|
|
{ 9999, {9e10f,9e10f,0}, { 0.f, 9e10f,0}, { 0.f,22.f,1}, {0.f,0.f,0}}
|
|
};
|
|
|
|
static vorbis_info_psy _psy_set0={
|
|
ATH_Bark_dB_lineaggressive,
|
|
|
|
-100.f,
|
|
-140.f,
|
|
6.f, /* floor master att */
|
|
|
|
/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */
|
|
/* x: 63 88 125 175 250 350 500 700 1k 1.4k 2k 2.8k 4k 5.6k 8k 11.5k 16k Hz */
|
|
/* y: 0 10 20 30 40 50 60 70 80 90 100 dB */
|
|
1, /* tonemaskp */
|
|
0.f, /* tone master att */
|
|
/* 0 10 20 30 40 50 60 70 80 90 100 */
|
|
{
|
|
{-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f}, /*63*/
|
|
{-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f}, /*88*/
|
|
{-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f}, /*125*/
|
|
|
|
{-30.f,-30.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*175*/
|
|
{-30.f,-30.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*250*/
|
|
{-30.f,-30.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*350*/
|
|
{-30.f,-30.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*500*/
|
|
{-30.f,-30.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*700*/
|
|
{-30.f,-30.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*1000*/
|
|
{-30.f,-30.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*1400*/
|
|
{-40.f,-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*2000*/
|
|
{-40.f,-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*2800*/
|
|
{-40.f,-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*4000*/
|
|
|
|
{-30.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*5600*/
|
|
|
|
{-30.f,-30.f,-33.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*8000*/
|
|
{-30.f,-30.f,-33.f,-35.f,-40.f,-45.f,-50.f,-60.f,-70.f,-85.f,-100.f}, /*11500*/
|
|
{-24.f,-24.f,-26.f,-32.f,-32.f,-42.f,-50.f,-60.f,-70.f,-85.f,-100.f}, /*16000*/
|
|
|
|
},
|
|
|
|
1,/* peakattp */
|
|
{{-14.f,-20.f,-20.f,-20.f,-26.f,-32.f,-40.f,-40.f,-40.f,-40.f,-40.f},/*63*/
|
|
{-14.f,-20.f,-20.f,-20.f,-26.f,-32.f,-40.f,-40.f,-40.f,-40.f,-40.f},/*88*/
|
|
{-14.f,-20.f,-20.f,-20.f,-26.f,-32.f,-40.f,-40.f,-40.f,-40.f,-40.f},/*125*/
|
|
{-14.f,-20.f,-20.f,-20.f,-26.f,-32.f,-40.f,-40.f,-40.f,-40.f,-40.f},/*175*/
|
|
{-14.f,-20.f,-20.f,-20.f,-26.f,-32.f,-40.f,-40.f,-40.f,-40.f,-40.f},/*250*/
|
|
{-14.f,-20.f,-20.f,-20.f,-26.f,-32.f,-40.f,-40.f,-40.f,-40.f,-40.f},/*350*/
|
|
{-14.f,-20.f,-20.f,-20.f,-26.f,-32.f,-40.f,-40.f,-40.f,-40.f,-40.f},/*500*/
|
|
{-14.f,-20.f,-20.f,-20.f,-26.f,-32.f,-40.f,-40.f,-40.f,-40.f,-40.f},/*700*/
|
|
{-14.f,-20.f,-20.f,-20.f,-26.f,-32.f,-40.f,-40.f,-40.f,-40.f,-40.f},/*1000*/
|
|
{-14.f,-20.f,-20.f,-20.f,-26.f,-32.f,-40.f,-40.f,-40.f,-40.f,-40.f},/*1400*/
|
|
{-14.f,-20.f,-20.f,-20.f,-26.f,-32.f,-40.f,-40.f,-40.f,-40.f,-40.f},/*2000*/
|
|
{-14.f,-20.f,-20.f,-20.f,-26.f,-32.f,-40.f,-40.f,-40.f,-40.f,-40.f},/*2800*/
|
|
{-14.f,-20.f,-20.f,-20.f,-26.f,-32.f,-40.f,-40.f,-40.f,-40.f,-40.f},/*4000*/
|
|
{-10.f,-12.f,-14.f,-16.f,-16.f,-20.f,-24.f,-30.f,-32.f,-40.f,-40.f},/*5600*/
|
|
{-10.f,-12.f,-14.f,-16.f,-16.f,-20.f,-24.f,-30.f,-32.f,-40.f,-40.f},/*8000*/
|
|
{-10.f,-10.f,-10.f,-12.f,-14.f,-18.f,-22.f,-28.f,-32.f,-40.f,-40.f},/*11500*/
|
|
{-10.f,-10.f,-10.f,-12.f,-14.f,-18.f,-22.f,-28.f,-32.f,-40.f,-40.f},/*16000*/
|
|
},
|
|
|
|
1,/*noisemaskp */
|
|
-10.f, /* suppress any noise curve over maxspec+n */
|
|
.5f, /* low window */
|
|
.5f, /* high window */
|
|
10,
|
|
10,
|
|
25,
|
|
{.000f, 0.f, /*63*/
|
|
.000f, 0.f, /*88*/
|
|
.000f, 0.f, /*125*/
|
|
.000f, 0.f, /*175*/
|
|
.000f, 0.f, /*250*/
|
|
.000f, 0.f, /*350*/
|
|
.000f, 0.f, /*500*/
|
|
.000f, 0.f, /*700*/
|
|
.000f, 0.f, /*1000*/
|
|
.300f, 0.f, /*1400*/
|
|
.300f, 0.f, /*2000*/
|
|
.300f, 0.f, /*2800*/
|
|
.500f, 0.f, /*4000*/
|
|
.700f, 0.f, /*5600*/
|
|
.850f, 0.f, /*8000*/
|
|
.900f, 0.f, /*11500*/
|
|
.900f, 1.f, /*16000*/
|
|
},
|
|
|
|
95.f, /* even decade + 5 is important; saves an rint() later in a
|
|
tight loop) */
|
|
-44.,
|
|
|
|
32,
|
|
_vp_part0,_vp_couple0
|
|
};
|
|
|
|
static vorbis_info_floor1 _floor_set0={1,
|
|
{0},
|
|
|
|
{32},
|
|
{0},
|
|
{0},
|
|
{{-1}},
|
|
|
|
2,
|
|
{0,1024,
|
|
|
|
88,31,243,
|
|
|
|
14,54,143,460,
|
|
|
|
6,3,10, 22,18,26, 41,36,47,
|
|
69,61,78, 112,99,126, 185,162,211,
|
|
329,282,387, 672,553,825
|
|
},
|
|
|
|
60,30,400,
|
|
20,8,1,18.,
|
|
20,600,
|
|
960};
|
|
|
|
|
|
static vorbis_info_mapping0 mapping_info={1,{0,1},{0},{0},{0},0, 1, {0},{1}};
|
|
static codec_setup_info codec_setup0={ {0,0},
|
|
1,1,1,1,1,0,1,
|
|
{NULL},
|
|
{0},{&mapping_info},
|
|
{0},{NULL},
|
|
{1},{&_floor_set0},
|
|
{2},{NULL},
|
|
{NULL},
|
|
{&_psy_set0},
|
|
&_psy_set0G};
|
|
|
|
static int noisy=0;
|
|
void analysis(char *base,int i,float *v,int n,int bark,int dB){
|
|
if(noisy){
|
|
int j;
|
|
FILE *of;
|
|
char buffer[80];
|
|
sprintf(buffer,"%s_%d.m",base,i);
|
|
of=fopen(buffer,"w");
|
|
|
|
for(j=0;j<n;j++){
|
|
if(dB && v[j]==0)
|
|
fprintf(of,"\n\n");
|
|
else{
|
|
if(bark)
|
|
fprintf(of,"%g ",toBARK(22050.f*j/n));
|
|
else
|
|
fprintf(of,"%g ",(float)j);
|
|
|
|
if(dB){
|
|
fprintf(of,"%g\n",todB(v+j));
|
|
}else{
|
|
fprintf(of,"%g\n",v[j]);
|
|
}
|
|
}
|
|
}
|
|
fclose(of);
|
|
}
|
|
}
|
|
|
|
long frameno=0;
|
|
|
|
/****************************************************************/
|
|
|
|
int main(int argc,char *argv[]){
|
|
int eos=0;
|
|
float nonz=0.f;
|
|
float acc=0.f;
|
|
float tot=0.f;
|
|
float ampmax=-9999,newmax;
|
|
float local_ampmax[2];
|
|
|
|
int framesize=2048;
|
|
float ampmax_att_per_sec=-6.;
|
|
|
|
float *pcm[2],*out[2],*window,*flr[2],*mask[2],*work[2];
|
|
signed char *buffer,*buffer2;
|
|
mdct_lookup m_look;
|
|
drft_lookup f_look;
|
|
vorbis_look_psy p_look;
|
|
vorbis_look_psy_global *pg_look;
|
|
vorbis_look_floor *floor_look;
|
|
vorbis_info vi;
|
|
long i,j,k;
|
|
|
|
int ath=0;
|
|
int decayp=0;
|
|
|
|
argv++;
|
|
while(*argv){
|
|
if(*argv[0]=='-'){
|
|
/* option */
|
|
if(argv[0][1]=='v'){
|
|
noisy=0;
|
|
}
|
|
}else
|
|
if(*argv[0]=='+'){
|
|
/* option */
|
|
if(argv[0][1]=='v'){
|
|
noisy=1;
|
|
}
|
|
}else
|
|
framesize=atoi(argv[0]);
|
|
argv++;
|
|
}
|
|
|
|
vi.channels=2;
|
|
vi.codec_setup=&codec_setup0;
|
|
|
|
pcm[0]=_ogg_malloc(framesize*sizeof(float));
|
|
pcm[1]=_ogg_malloc(framesize*sizeof(float));
|
|
out[0]=_ogg_calloc(framesize/2,sizeof(float));
|
|
out[1]=_ogg_calloc(framesize/2,sizeof(float));
|
|
work[0]=_ogg_calloc(framesize,sizeof(float));
|
|
work[1]=_ogg_calloc(framesize,sizeof(float));
|
|
flr[0]=_ogg_calloc(framesize/2,sizeof(float));
|
|
flr[1]=_ogg_calloc(framesize/2,sizeof(float));
|
|
buffer=_ogg_malloc(framesize*4);
|
|
buffer2=buffer+framesize*2;
|
|
window=_vorbis_window_create(0,framesize,framesize/2,framesize/2);
|
|
mdct_init(&m_look,framesize);
|
|
drft_init(&f_look,framesize);
|
|
_vp_psy_init(&p_look,&_psy_set0,&_psy_set0G,framesize/2,44100);
|
|
pg_look=_vp_global_look(&vi);
|
|
floor_look=_floor_P[1]->look(NULL,NULL,&_floor_set0);
|
|
|
|
/* we cheat on the WAV header; we just bypass 44 bytes and never
|
|
verify that it matches 16bit/stereo/44.1kHz. */
|
|
|
|
fread(buffer,1,44,stdin);
|
|
fwrite(buffer,1,44,stdout);
|
|
memset(buffer,0,framesize*2);
|
|
|
|
analysis("window",0,window,framesize,0,0);
|
|
|
|
fprintf(stderr,"Processing for frame size %d...\n",framesize);
|
|
|
|
while(!eos){
|
|
long bytes=fread(buffer2,1,framesize*2,stdin);
|
|
if(bytes<framesize*2)
|
|
memset(buffer2+bytes,0,framesize*2-bytes);
|
|
|
|
if(bytes!=0){
|
|
int nonzero[2];
|
|
|
|
/* uninterleave samples */
|
|
for(i=0;i<framesize;i++){
|
|
pcm[0][i]=((buffer[i*4+1]<<8)|
|
|
(0x00ff&(int)buffer[i*4]))/32768.f;
|
|
pcm[1][i]=((buffer[i*4+3]<<8)|
|
|
(0x00ff&(int)buffer[i*4+2]))/32768.f;
|
|
}
|
|
|
|
{
|
|
float secs=framesize/44100.;
|
|
|
|
ampmax+=secs*ampmax_att_per_sec;
|
|
if(ampmax<-9999)ampmax=-9999;
|
|
}
|
|
|
|
for(i=0;i<2;i++){
|
|
float scale=4.f/framesize;
|
|
float *fft=work[i];
|
|
float *mdct=pcm[i];
|
|
float *logmdct=mdct+framesize/2;
|
|
|
|
analysis("pre",frameno+i,pcm[i],framesize,0,0);
|
|
|
|
/* fft and mdct transforms */
|
|
for(j=0;j<framesize;j++)
|
|
fft[j]=pcm[i][j]*=window[j];
|
|
|
|
drft_forward(&f_look,fft);
|
|
|
|
local_ampmax[i]=-9999.f;
|
|
fft[0]*=scale;
|
|
fft[0]=todB(fft);
|
|
for(j=1;j<framesize-1;j+=2){
|
|
float temp=scale*FAST_HYPOT(fft[j],fft[j+1]);
|
|
temp=fft[(j+1)>>1]=todB(&temp);
|
|
if(temp>local_ampmax[i])local_ampmax[i]=temp;
|
|
}
|
|
if(local_ampmax[i]>ampmax)ampmax=local_ampmax[i];
|
|
|
|
mdct_forward(&m_look,pcm[i],mdct);
|
|
for(j=0;j<framesize/2;j++)
|
|
logmdct[j]=todB(mdct+j);
|
|
|
|
analysis("mdct",frameno+i,logmdct,framesize/2,1,0);
|
|
analysis("fft",frameno+i,fft,framesize/2,1,0);
|
|
}
|
|
|
|
for(i=0;i<2;i++){
|
|
float amp;
|
|
float *fft=work[i];
|
|
float *logmax=fft;
|
|
float *mdct=pcm[i];
|
|
float *logmdct=mdct+framesize/2;
|
|
float *mask=fft+framesize/2;
|
|
|
|
/* floor psychoacoustics */
|
|
_vp_compute_mask(&p_look,
|
|
pg_look,
|
|
i,
|
|
fft,
|
|
logmdct,
|
|
mask,
|
|
ampmax,
|
|
local_ampmax[i],
|
|
framesize/2);
|
|
|
|
analysis("mask",frameno+i,mask,framesize/2,1,0);
|
|
|
|
{
|
|
vorbis_block vb;
|
|
vorbis_dsp_state vd;
|
|
memset(&vd,0,sizeof(vd));
|
|
vd.vi=&vi;
|
|
vb.vd=&vd;
|
|
vb.pcmend=framesize;
|
|
|
|
/* floor quantization/application */
|
|
nonzero[i]=_floor_P[1]->forward(&vb,floor_look,
|
|
mdct,
|
|
logmdct,
|
|
mask,
|
|
logmax,
|
|
|
|
flr[i]);
|
|
}
|
|
|
|
_vp_remove_floor(&p_look,
|
|
pg_look,
|
|
logmdct,
|
|
mdct,
|
|
flr[i],
|
|
pcm[i],
|
|
local_ampmax[i]);
|
|
|
|
for(j=0;j<framesize/2;j++)
|
|
if(fabs(pcm[i][j])>1500)
|
|
fprintf(stderr,"%ld ",frameno+i);
|
|
|
|
analysis("res",frameno+i,pcm[i],framesize/2,1,0);
|
|
analysis("codedflr",frameno+i,flr[i],framesize/2,1,1);
|
|
}
|
|
|
|
/* residue prequantization */
|
|
_vp_partition_prequant(&p_look,
|
|
&vi,
|
|
pcm,
|
|
nonzero);
|
|
|
|
for(i=0;i<2;i++)
|
|
analysis("quant",frameno+i,pcm[i],framesize/2,1,0);
|
|
|
|
/* channel coupling / stereo quantization */
|
|
|
|
_vp_couple(&p_look,
|
|
&mapping_info,
|
|
pcm,
|
|
nonzero);
|
|
|
|
for(i=0;i<2;i++)
|
|
analysis("coupled",frameno+i,pcm[i],framesize/2,1,0);
|
|
|
|
/* decoupling */
|
|
for(i=mapping_info.coupling_steps-1;i>=0;i--){
|
|
float *pcmM=pcm[mapping_info.coupling_mag[i]];
|
|
float *pcmA=pcm[mapping_info.coupling_ang[i]];
|
|
|
|
for(j=0;j<framesize/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;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(i=0;i<2;i++)
|
|
analysis("decoupled",frameno+i,pcm[i],framesize/2,1,0);
|
|
|
|
for(i=0;i<2;i++){
|
|
float amp;
|
|
|
|
for(j=0;j<framesize/2;j++)
|
|
pcm[i][j]*=flr[i][j];
|
|
|
|
analysis("final",frameno+i,pcm[i],framesize/2,1,1);
|
|
|
|
/* take it back to time */
|
|
mdct_backward(&m_look,pcm[i],pcm[i]);
|
|
|
|
for(j=0;j<framesize/2;j++)
|
|
out[i][j]+=pcm[i][j]*window[j];
|
|
|
|
analysis("out",frameno+i,out[i],framesize/2,0,0);
|
|
|
|
|
|
}
|
|
|
|
/* write data. Use the part of buffer we're about to shift out */
|
|
for(i=0;i<2;i++){
|
|
char *ptr=buffer+i*2;
|
|
float *mono=out[i];
|
|
int flag=0;
|
|
for(j=0;j<framesize/2;j++){
|
|
int val=mono[j]*32767.;
|
|
/* might as well guard against clipping */
|
|
if(val>32767){
|
|
if(!flag)fprintf(stderr,"clipping in frame %ld ",frameno+i);
|
|
flag=1;
|
|
val=32767;
|
|
}
|
|
if(val<-32768){
|
|
if(!flag)fprintf(stderr,"clipping in frame %ld ",frameno+i);
|
|
flag=1;
|
|
val=-32768;
|
|
}
|
|
ptr[0]=val&0xff;
|
|
ptr[1]=(val>>8)&0xff;
|
|
ptr+=4;
|
|
}
|
|
}
|
|
|
|
fprintf(stderr,"*");
|
|
fwrite(buffer,1,framesize*2,stdout);
|
|
memmove(buffer,buffer2,framesize*2);
|
|
|
|
for(i=0;i<2;i++){
|
|
for(j=0,k=framesize/2;j<framesize/2;j++,k++)
|
|
out[i][j]=pcm[i][k]*window[k];
|
|
}
|
|
frameno+=2;
|
|
}else
|
|
eos=1;
|
|
}
|
|
fprintf(stderr,"average raw bits of entropy: %.03g/sample\n",acc/tot);
|
|
fprintf(stderr,"average nonzero samples: %.03g/%d\n",nonz/tot*framesize/2,
|
|
framesize/2);
|
|
fprintf(stderr,"Done\n\n");
|
|
return 0;
|
|
}
|