Commit 938f4699 authored by Monty's avatar Monty
Browse files

Vorbisfile API addition for game and mod coders;

Do a 'free' sample rate conversion from source rate to half source
rate by calling ov_halfrate() after ov_open(); Although this is solid
for immediately desired usage, I want to clean it up a bit before
advertising it's existence, so no doc addition yet.

Does not break binary API.

Monty

svn path=/trunk/vorbis/; revision=5222
parent 9a2fc5d1
......@@ -11,7 +11,7 @@
********************************************************************
function: libvorbis codec headers
last mod: $Id: codec.h,v 1.43 2003/03/04 21:23:37 xiphmont Exp $
last mod: $Id: codec.h,v 1.44 2003/08/18 05:34:01 xiphmont Exp $
********************************************************************/
......@@ -212,6 +212,9 @@ extern int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm);
extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples);
extern long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op);
extern int vorbis_synthesis_halfrate(vorbis_info *v,int flag);
extern int vorbis_synthesis_halfrate_p(vorbis_info *v);
/* Vorbis ERRORS and return codes ***********************************/
#define OV_FALSE -1
......
......@@ -11,7 +11,7 @@
********************************************************************
function: stdio-based convenience library for opening/seeking/decoding
last mod: $Id: vorbisfile.h,v 1.19 2003/03/06 22:03:42 xiphmont Exp $
last mod: $Id: vorbisfile.h,v 1.20 2003/08/18 05:34:01 xiphmont Exp $
********************************************************************/
......@@ -131,6 +131,9 @@ extern long ov_read(OggVorbis_File *vf,char *buffer,int length,
int bigendianp,int word,int sgned,int *bitstream);
extern int ov_crosslap(OggVorbis_File *vf1,OggVorbis_File *vf2);
extern int ov_halfrate(OggVorbis_File *vf,int flag);
extern int ov_halfrate_p(OggVorbis_File *vf);
#ifdef __cplusplus
}
#endif /* __cplusplus */
......
......@@ -5,13 +5,13 @@
* 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 *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2003 *
* by the XIPHOPHORUS Company http://www.xiph.org/ *
* *
********************************************************************
function: PCM data vector blocking, windowing and dis/reassembly
last mod: $Id: block.c,v 1.72 2003/03/06 22:05:26 xiphmont Exp $
last mod: $Id: block.c,v 1.73 2003/08/18 05:34:01 xiphmont Exp $
Handle windowing, overlap-add, etc of the PCM vectors. This is made
more amusing by Vorbis' current two allowed block sizes.
......@@ -168,6 +168,7 @@ static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){
int i;
codec_setup_info *ci=vi->codec_setup;
private_state *b=NULL;
int hs=ci->halfrate_flag;
memset(v,0,sizeof(*v));
b=v->backend_state=_ogg_calloc(1,sizeof(*b));
......@@ -182,12 +183,12 @@ static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){
b->transform[0][0]=_ogg_calloc(1,sizeof(mdct_lookup));
b->transform[1][0]=_ogg_calloc(1,sizeof(mdct_lookup));
mdct_init(b->transform[0][0],ci->blocksizes[0]);
mdct_init(b->transform[1][0],ci->blocksizes[1]);
mdct_init(b->transform[0][0],ci->blocksizes[0]>>hs);
mdct_init(b->transform[1][0],ci->blocksizes[1]>>hs);
/* Vorbis I uses only window type 0 */
b->window[0]=_vorbis_window_get(0,ci->blocksizes[0]/2);
b->window[1]=_vorbis_window_get(0,ci->blocksizes[1]/2);
b->window[0]=ilog2(ci->blocksizes[0])-6;
b->window[1]=ilog2(ci->blocksizes[1])-6;
if(encp){ /* encode/decode differ here */
......@@ -636,14 +637,16 @@ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){
int vorbis_synthesis_restart(vorbis_dsp_state *v){
vorbis_info *vi=v->vi;
codec_setup_info *ci;
int hs;
if(!v->backend_state)return -1;
if(!vi)return -1;
ci=vi->codec_setup;
if(!ci)return -1;
hs=ci->halfrate_flag;
v->centerW=ci->blocksizes[1]/2;
v->pcm_current=v->centerW;
v->centerW=ci->blocksizes[1]>>(hs+1);
v->pcm_current=v->centerW>>hs;
v->pcm_returned=-1;
v->granulepos=-1;
......@@ -669,6 +672,7 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
vorbis_info *vi=v->vi;
codec_setup_info *ci=vi->codec_setup;
private_state *b=v->backend_state;
int hs=ci->halfrate_flag;
int i,j;
if(!vb)return(OV_EINVAL);
......@@ -688,10 +692,10 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly
was called on block */
int n=ci->blocksizes[v->W]/2;
int n0=ci->blocksizes[0]/2;
int n1=ci->blocksizes[1]/2;
int n=ci->blocksizes[v->W]>>(hs+1);
int n0=ci->blocksizes[0]>>(hs+1);
int n1=ci->blocksizes[1]>>(hs+1);
int thisCenter;
int prevCenter;
......@@ -712,21 +716,19 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
to have to constantly shift *or* adjust memory usage. Don't
accept a new block until the old is shifted out */
/* overlap/add PCM */
for(j=0;j<vi->channels;j++){
/* the overlap/add section */
if(v->lW){
if(v->W){
/* large/large */
float *w=b->window[1];
float *w=_vorbis_window_get(b->window[1]-hs);
float *pcm=v->pcm[j]+prevCenter;
float *p=vb->pcm[j];
for(i=0;i<n1;i++)
pcm[i]=pcm[i]*w[n1-i-1] + p[i]*w[i];
}else{
/* large/small */
float *w=b->window[0];
float *w=_vorbis_window_get(b->window[0]-hs);
float *pcm=v->pcm[j]+prevCenter+n1/2-n0/2;
float *p=vb->pcm[j];
for(i=0;i<n0;i++)
......@@ -735,7 +737,7 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
}else{
if(v->W){
/* small/large */
float *w=b->window[0];
float *w=_vorbis_window_get(b->window[0]-hs);
float *pcm=v->pcm[j]+prevCenter;
float *p=vb->pcm[j]+n1/2-n0/2;
for(i=0;i<n0;i++)
......@@ -744,7 +746,7 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
pcm[i]=p[i];
}else{
/* small/small */
float *w=b->window[0];
float *w=_vorbis_window_get(b->window[0]-hs);
float *pcm=v->pcm[j]+prevCenter;
float *p=vb->pcm[j];
for(i=0;i<n0;i++)
......@@ -776,8 +778,8 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
}else{
v->pcm_returned=prevCenter;
v->pcm_current=prevCenter+
ci->blocksizes[v->lW]/4+
ci->blocksizes[v->W]/4;
((ci->blocksizes[v->lW]/4+
ci->blocksizes[v->W]/4)>>hs);
}
}
......@@ -815,10 +817,10 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
/* granulepos could be -1 due to a seek, but that would result
in a long count, not short count */
v->pcm_current-=(b->sample_count-v->granulepos);
v->pcm_current-=(b->sample_count-v->granulepos)>>hs;
}else{
/* trim the beginning */
v->pcm_returned+=(b->sample_count-v->granulepos);
v->pcm_returned+=(b->sample_count-v->granulepos)>>hs;
if(v->pcm_returned>v->pcm_current)
v->pcm_returned=v->pcm_current;
}
......@@ -836,7 +838,7 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
if(extra)
if(vb->eofflag){
/* partial last frame. Strip the extra samples off */
v->pcm_current-=extra;
v->pcm_current-=extra>>hs;
} /* else {Shouldn't happen *unless* the bitstream is out of
spec. Either way, believe the bitstream } */
} /* else {Shouldn't happen *unless* the bitstream is out of
......@@ -855,6 +857,7 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
/* pcm==NULL indicates we just want the pending samples, no more */
int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm){
vorbis_info *vi=v->vi;
if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){
if(pcm){
int i;
......@@ -881,10 +884,11 @@ int vorbis_synthesis_read(vorbis_dsp_state *v,int n){
int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm){
vorbis_info *vi=v->vi;
codec_setup_info *ci=vi->codec_setup;
int hs=ci->halfrate_flag;
int n=ci->blocksizes[v->W]/2;
int n0=ci->blocksizes[0]/2;
int n1=ci->blocksizes[1]/2;
int n=ci->blocksizes[v->W]>>(hs+1);
int n0=ci->blocksizes[0]>>(hs+1);
int n1=ci->blocksizes[1]>>(hs+1);
int i,j;
if(v->pcm_returned<0)return 0;
......@@ -916,6 +920,7 @@ int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm){
v->centerW=0;
}
/* solidify buffer into contiguous space */
if((v->lW^v->W)==1){
/* long/short or short/long */
for(j=0;j<vi->channels;j++){
......@@ -953,6 +958,6 @@ int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm){
float *vorbis_window(vorbis_dsp_state *v,int W){
private_state *b=v->backend_state;
return b->window[W];
return _vorbis_window_get(b->window[W]);
}
......@@ -11,7 +11,7 @@
********************************************************************
function: libvorbis codec headers
last mod: $Id: codec_internal.h,v 1.16 2002/10/11 11:14:41 xiphmont Exp $
last mod: $Id: codec_internal.h,v 1.17 2003/08/18 05:34:01 xiphmont Exp $
********************************************************************/
......@@ -58,7 +58,7 @@ typedef void vorbis_info_mapping;
typedef struct private_state {
/* local lookup storage */
envelope_lookup *ve; /* envelope lookup */
float *window[2];
int window[2];
vorbis_look_transform **transform[2]; /* block, type */
drft_lookup fft_look[2];
......@@ -79,7 +79,6 @@ typedef struct private_state {
bitrate_manager_state bms;
ogg_int64_t sample_count;
} private_state;
/* codec_setup_info contains all the setup information specific to the
......@@ -125,7 +124,7 @@ typedef struct codec_setup_info {
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(vorbis_info *vi);
......
......@@ -11,7 +11,7 @@
********************************************************************
function: channel mapping 0 implementation
last mod: $Id: mapping0.c,v 1.57 2003/03/02 11:45:17 xiphmont Exp $
last mod: $Id: mapping0.c,v 1.58 2003/08/18 05:34:01 xiphmont Exp $
********************************************************************/
......@@ -654,6 +654,7 @@ static int mapping0_inverse(vorbis_block *vb,vorbis_info_mapping *l){
codec_setup_info *ci=vi->codec_setup;
private_state *b=vd->backend_state;
vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)l;
int hs=ci->halfrate_flag;
int i,j;
long n=vb->pcmend=ci->blocksizes[vb->W];
......
......@@ -11,7 +11,7 @@
********************************************************************
function: single-block PCM synthesis
last mod: $Id: synthesis.c,v 1.29 2002/10/11 11:14:41 xiphmont Exp $
last mod: $Id: synthesis.c,v 1.30 2003/08/18 05:34:01 xiphmont Exp $
********************************************************************/
......@@ -152,4 +152,19 @@ long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){
return(ci->blocksizes[ci->mode_param[mode]->blockflag]);
}
int 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 vorbis_synthesis_halfrate_p(vorbis_info *vi){
codec_setup_info *ci=vi->codec_setup;
return ci->halfrate_flag;
}
......@@ -11,7 +11,7 @@
********************************************************************
function: stdio-based convenience library for opening/seeking/decoding
last mod: $Id: vorbisfile.c,v 1.69 2003/03/11 23:52:02 xiphmont Exp $
last mod: $Id: vorbisfile.c,v 1.70 2003/08/18 05:34:01 xiphmont Exp $
********************************************************************/
......@@ -735,7 +735,35 @@ int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
}
/* cheap hack for game usage where downsampling is desirable; there's
no need for SRC as we can just do it cheaply in libvorbis. */
int ov_halfrate(OggVorbis_File *vf,int flag){
int i;
if(vf->vi==NULL)return OV_EINVAL;
if(!vf->seekable)return OV_EINVAL;
if(vf->ready_state>=STREAMSET)
_decode_clear(vf); /* clear out stream state; later on libvorbis
will be able to swap this on the fly, but
for now dumping the decode machine is needed
to reinit the MDCT lookups. 1.1 libvorbis
is planned to be able to switch on the fly */
for(i=0;i<vf->links;i++){
if(vorbis_synthesis_halfrate(vf->vi+i,flag)){
ov_halfrate(vf,0);
return OV_EINVAL;
}
}
return 0;
}
int ov_halfrate_p(OggVorbis_File *vf){
if(vf->vi==NULL)return OV_EINVAL;
return vorbis_synthesis_halfrate_p(vf->vi);
}
/* Only partially open the vorbis file; test for Vorbisness, and load
the headers for the first chain. Do not seek (although test for
seekability). Use ov_test_open to finish opening the file, else
......
......@@ -11,7 +11,7 @@
********************************************************************
function: window functions
last mod: $Id: window.c,v 1.21 2003/03/06 22:05:26 xiphmont Exp $
last mod: $Id: window.c,v 1.22 2003/08/18 05:34:01 xiphmont Exp $
********************************************************************/
......@@ -2084,35 +2084,26 @@ static float vwin8192[4096] = {
1.0000000000F, 1.0000000000F, 1.0000000000F, 1.0000000000F,
};
float *_vorbis_window_get(int type, int left){
switch(type){
case 0:
/* The 'vorbis window' (window 0) is sin(sin(x)*sin(x)*pi*.5) */
switch(left){
case 32:
return(vwin64);
case 64:
return(vwin128);
case 128:
return(vwin256);
case 256:
return(vwin512);
case 512:
return(vwin1024);
case 1024:
return(vwin2048);
case 2048:
return(vwin4096);
case 4096:
return(vwin8192);
}
default:
return(NULL);
}
static float *vwin[8] = {
vwin64,
vwin128,
vwin256,
vwin512,
vwin1024,
vwin2048,
vwin4096,
vwin8192,
};
float *_vorbis_window_get(int n){
return vwin[n];
}
void _vorbis_apply_window(float *d,float *window[2],long *blocksizes,
void _vorbis_apply_window(float *d,int *winno,long *blocksizes,
int lW,int W,int nW){
float *windowLW=vwin[winno[lW]];
float *windowNW=vwin[winno[nW]];
lW=(W?lW:0);
nW=(W?nW:0);
......@@ -2133,10 +2124,10 @@ void _vorbis_apply_window(float *d,float *window[2],long *blocksizes,
d[i]=0.f;
for(p=0;i<leftend;i++,p++)
d[i]*=window[lW][p];
d[i]*=windowLW[p];
for(i=rightbegin,p=rn/2-1;i<rightend;i++,p--)
d[i]*=window[nW][p];
d[i]*=windowNW[p];
for(;i<n;i++)
d[i]=0.f;
......
......@@ -11,14 +11,14 @@
********************************************************************
function: window functions
last mod: $Id: window.h,v 1.12 2003/03/06 22:05:26 xiphmont Exp $
last mod: $Id: window.h,v 1.13 2003/08/18 05:34:01 xiphmont Exp $
********************************************************************/
#ifndef _V_WINDOW_
#define _V_WINDOW_
extern float *_vorbis_window_get(int type,int left);
extern float *_vorbis_window_get(int n);
extern void _vorbis_apply_window(float *d,float *window[2],long *blocksizes,
int lW,int W,int nW);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment