1 /************************************************************************ 2 * Copyright (C) 2002-2009, Xiph.org Foundation 3 * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above 13 * copyright notice, this list of conditions and the following disclaimer 14 * in the documentation and/or other materials provided with the 15 * distribution. 16 * * Neither the names of the Xiph.org Foundation nor Pinknoise 17 * Productions Ltd nor the names of its contributors may be used to 18 * endorse or promote products derived from this software without 19 * specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 ************************************************************************ 33 34 function: PCM data vector blocking, windowing and dis/reassembly 35 36 ************************************************************************/ 37 38 #include <stdlib.h> 39 #include "ogg.h" 40 #include "mdct.h" 41 #include "ivorbiscodec.h" 42 #include "codec_internal.h" 43 #include "misc.h" 44 #include "window_lookup.h" 45 46 int vorbis_dsp_restart(vorbis_dsp_state *v){ 47 if(!v)return -1; 48 { 49 vorbis_info *vi=v->vi; 50 codec_setup_info *ci; 51 52 if(!vi)return -1; 53 ci=vi->codec_setup; 54 if(!ci)return -1; 55 56 v->out_end=-1; 57 v->out_begin=-1; 58 59 v->granulepos=-1; 60 v->sequence=-1; 61 v->sample_count=-1; 62 } 63 return 0; 64 } 65 66 int vorbis_dsp_init(vorbis_dsp_state *v,vorbis_info *vi){ 67 int i; 68 69 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 70 71 v->vi=vi; 72 73 v->work=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->work)); 74 v->mdctright=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->mdctright)); 75 for(i=0;i<vi->channels;i++){ 76 v->work[i]=(ogg_int32_t *)_ogg_calloc(1,(ci->blocksizes[1]>>1)* 77 sizeof(*v->work[i])); 78 v->mdctright[i]=(ogg_int32_t *)_ogg_calloc(1,(ci->blocksizes[1]>>2)* 79 sizeof(*v->mdctright[i])); 80 } 81 82 v->lW=0; /* previous window size */ 83 v->W=0; /* current window size */ 84 85 vorbis_dsp_restart(v); 86 return 0; 87 } 88 89 vorbis_dsp_state *vorbis_dsp_create(vorbis_info *vi){ 90 vorbis_dsp_state *v=_ogg_calloc(1,sizeof(*v)); 91 vorbis_dsp_init(v,vi); 92 return v; 93 } 94 95 void vorbis_dsp_clear(vorbis_dsp_state *v){ 96 int i; 97 if(v){ 98 vorbis_info *vi=v->vi; 99 100 if(v->work){ 101 for(i=0;i<vi->channels;i++) 102 if(v->work[i])_ogg_free(v->work[i]); 103 _ogg_free(v->work); 104 } 105 if(v->mdctright){ 106 for(i=0;i<vi->channels;i++) 107 if(v->mdctright[i])_ogg_free(v->mdctright[i]); 108 _ogg_free(v->mdctright); 109 } 110 } 111 } 112 113 void vorbis_dsp_destroy(vorbis_dsp_state *v){ 114 vorbis_dsp_clear(v); 115 _ogg_free(v); 116 } 117 118 static LOOKUP_T *_vorbis_window(int left){ 119 switch(left){ 120 case 32: 121 return vwin64; 122 case 64: 123 return vwin128; 124 case 128: 125 return vwin256; 126 case 256: 127 return vwin512; 128 case 512: 129 return vwin1024; 130 case 1024: 131 return vwin2048; 132 case 2048: 133 return vwin4096; 134 #ifndef LIMIT_TO_64kHz 135 case 4096: 136 return vwin8192; 137 #endif 138 default: 139 return(0); 140 } 141 } 142 143 /* pcm==0 indicates we just want the pending samples, no more */ 144 int vorbis_dsp_pcmout(vorbis_dsp_state *v,ogg_int16_t *pcm,int samples){ 145 vorbis_info *vi=v->vi; 146 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 147 if(v->out_begin>-1 && v->out_begin<v->out_end){ 148 int n=v->out_end-v->out_begin; 149 if(pcm){ 150 int i; 151 if(n>samples)n=samples; 152 for(i=0;i<vi->channels;i++) 153 mdct_unroll_lap(ci->blocksizes[0],ci->blocksizes[1], 154 v->lW,v->W,v->work[i],v->mdctright[i], 155 _vorbis_window(ci->blocksizes[0]>>1), 156 _vorbis_window(ci->blocksizes[1]>>1), 157 pcm+i,vi->channels, 158 v->out_begin,v->out_begin+n); 159 } 160 return(n); 161 } 162 return(0); 163 } 164 165 int vorbis_dsp_read(vorbis_dsp_state *v,int s){ 166 if(s && v->out_begin+s>v->out_end)return(OV_EINVAL); 167 v->out_begin+=s; 168 return(0); 169 } 170 171 long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){ 172 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 173 oggpack_buffer opb; 174 int mode; 175 int modebits=0; 176 int v=ci->modes; 177 178 oggpack_readinit(&opb,op->packet); 179 180 /* Check the packet type */ 181 if(oggpack_read(&opb,1)!=0){ 182 /* Oops. This is not an audio data packet */ 183 return(OV_ENOTAUDIO); 184 } 185 186 while(v>1){ 187 modebits++; 188 v>>=1; 189 } 190 191 /* read our mode and pre/post windowsize */ 192 mode=oggpack_read(&opb,modebits); 193 if(mode==-1)return(OV_EBADPACKET); 194 return(ci->blocksizes[ci->mode_param[mode].blockflag]); 195 } 196 197 198 static int ilog(ogg_uint32_t v){ 199 int ret=0; 200 if(v)--v; 201 while(v){ 202 ret++; 203 v>>=1; 204 } 205 return(ret); 206 } 207 208 int vorbis_dsp_synthesis(vorbis_dsp_state *vd,ogg_packet *op,int decodep){ 209 vorbis_info *vi=vd->vi; 210 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 211 int mode,i; 212 213 oggpack_readinit(&vd->opb,op->packet); 214 215 /* Check the packet type */ 216 if(oggpack_read(&vd->opb,1)!=0){ 217 /* Oops. This is not an audio data packet */ 218 return OV_ENOTAUDIO ; 219 } 220 221 /* read our mode and pre/post windowsize */ 222 mode=oggpack_read(&vd->opb,ilog(ci->modes)); 223 if(mode==-1 || mode>=ci->modes) return OV_EBADPACKET; 224 225 /* shift information we still need from last window */ 226 vd->lW=vd->W; 227 vd->W=ci->mode_param[mode].blockflag; 228 for(i=0;i<vi->channels;i++) 229 mdct_shift_right(ci->blocksizes[vd->lW],vd->work[i],vd->mdctright[i]); 230 231 if(vd->W){ 232 int temp; 233 oggpack_read(&vd->opb,1); 234 temp=oggpack_read(&vd->opb,1); 235 if(temp==-1) return OV_EBADPACKET; 236 } 237 238 /* packet decode and portions of synthesis that rely on only this block */ 239 if(decodep){ 240 mapping_inverse(vd,ci->map_param+ci->mode_param[mode].mapping); 241 242 if(vd->out_begin==-1){ 243 vd->out_begin=0; 244 vd->out_end=0; 245 }else{ 246 vd->out_begin=0; 247 vd->out_end=ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4; 248 } 249 } 250 251 /* track the frame number... This is for convenience, but also 252 making sure our last packet doesn't end with added padding. 253 254 This is not foolproof! It will be confused if we begin 255 decoding at the last page after a seek or hole. In that case, 256 we don't have a starting point to judge where the last frame 257 is. For this reason, vorbisfile will always try to make sure 258 it reads the last two marked pages in proper sequence */ 259 260 /* if we're out of sequence, dump granpos tracking until we sync back up */ 261 if(vd->sequence==-1 || vd->sequence+1 != op->packetno-3){ 262 /* out of sequence; lose count */ 263 vd->granulepos=-1; 264 vd->sample_count=-1; 265 } 266 267 vd->sequence=op->packetno; 268 vd->sequence=vd->sequence-3; 269 270 if(vd->sample_count==-1){ 271 vd->sample_count=0; 272 }else{ 273 vd->sample_count+= 274 ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4; 275 } 276 277 if(vd->granulepos==-1){ 278 if(op->granulepos!=-1){ /* only set if we have a 279 position to set to */ 280 281 vd->granulepos=op->granulepos; 282 283 /* is this a short page? */ 284 if(vd->sample_count>vd->granulepos){ 285 /* corner case; if this is both the first and last audio page, 286 then spec says the end is cut, not beginning */ 287 if(op->e_o_s){ 288 /* trim the end */ 289 /* no preceeding granulepos; assume we started at zero (we'd 290 have to in a short single-page stream) */ 291 /* granulepos could be -1 due to a seek, but that would result 292 in a long coun t, not short count */ 293 294 vd->out_end-=(int)(vd->sample_count-vd->granulepos); 295 }else{ 296 /* trim the beginning */ 297 vd->out_begin+=(int)(vd->sample_count-vd->granulepos); 298 if(vd->out_begin>vd->out_end) 299 vd->out_begin=vd->out_end; 300 } 301 302 } 303 304 } 305 }else{ 306 vd->granulepos+= 307 ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4; 308 if(op->granulepos!=-1 && vd->granulepos!=op->granulepos){ 309 310 if(vd->granulepos>op->granulepos){ 311 long extra=(long)(vd->granulepos-op->granulepos); 312 313 if(extra) 314 if(op->e_o_s){ 315 /* partial last frame. Strip the extra samples off */ 316 vd->out_end-=extra; 317 } /* else {Shouldn't happen *unless* the bitstream is out of 318 spec. Either way, believe the bitstream } */ 319 } /* else {Shouldn't happen *unless* the bitstream is out of 320 spec. Either way, believe the bitstream } */ 321 vd->granulepos=op->granulepos; 322 } 323 } 324 325 return(0); 326 } 327