1 | /******************************************************************** |
2 | * * |
3 | * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * |
4 | * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * |
5 | * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * |
6 | * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * |
7 | * * |
8 | * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015 * |
9 | * by the Xiph.Org Foundation https://xiph.org/ * |
10 | * * |
11 | ******************************************************************** |
12 | |
13 | function: single-block PCM synthesis |
14 | |
15 | ********************************************************************/ |
16 | |
17 | #include <stdio.h> |
18 | #include <ogg/ogg.h> |
19 | #include "vorbis/codec.h" |
20 | #include "codec_internal.h" |
21 | #include "registry.h" |
22 | #include "misc.h" |
23 | #include "os.h" |
24 | |
25 | int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){ |
26 | vorbis_dsp_state *vd= vb ? vb->vd : 0; |
27 | private_state *b= vd ? vd->backend_state : 0; |
28 | vorbis_info *vi= vd ? vd->vi : 0; |
29 | codec_setup_info *ci= vi ? vi->codec_setup : 0; |
30 | oggpack_buffer *opb=vb ? &vb->opb : 0; |
31 | int type,mode,i; |
32 | |
33 | if (!vd || !b || !vi || !ci || !opb) { |
34 | return OV_EBADPACKET; |
35 | } |
36 | |
37 | /* first things first. Make sure decode is ready */ |
38 | _vorbis_block_ripcord(vb); |
39 | oggpack_readinit(opb,op->packet,op->bytes); |
40 | |
41 | /* Check the packet type */ |
42 | if(oggpack_read(opb,1)!=0){ |
43 | /* Oops. This is not an audio data packet */ |
44 | return(OV_ENOTAUDIO); |
45 | } |
46 | |
47 | /* read our mode and pre/post windowsize */ |
48 | mode=oggpack_read(opb,b->modebits); |
49 | if(mode==-1){ |
50 | return(OV_EBADPACKET); |
51 | } |
52 | |
53 | vb->mode=mode; |
54 | if(!ci->mode_param[mode]){ |
55 | return(OV_EBADPACKET); |
56 | } |
57 | |
58 | vb->W=ci->mode_param[mode]->blockflag; |
59 | if(vb->W){ |
60 | |
61 | /* this doesn;t get mapped through mode selection as it's used |
62 | only for window selection */ |
63 | vb->lW=oggpack_read(opb,1); |
64 | vb->nW=oggpack_read(opb,1); |
65 | if(vb->nW==-1){ |
66 | return(OV_EBADPACKET); |
67 | } |
68 | }else{ |
69 | vb->lW=0; |
70 | vb->nW=0; |
71 | } |
72 | |
73 | /* more setup */ |
74 | vb->granulepos=op->granulepos; |
75 | vb->sequence=op->packetno; |
76 | vb->eofflag=op->e_o_s; |
77 | |
78 | /* alloc pcm passback storage */ |
79 | vb->pcmend=ci->blocksizes[vb->W]; |
80 | vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels); |
81 | for(i=0;i<vi->channels;i++) |
82 | vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i])); |
83 | |
84 | /* unpack_header enforces range checking */ |
85 | type=ci->map_type[ci->mode_param[mode]->mapping]; |
86 | |
87 | return(_mapping_P[type]->inverse(vb,ci->map_param[ci->mode_param[mode]-> |
88 | mapping])); |
89 | } |
90 | |
91 | /* used to track pcm position without actually performing decode. |
92 | Useful for sequential 'fast forward' */ |
93 | int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){ |
94 | vorbis_dsp_state *vd=vb->vd; |
95 | private_state *b=vd->backend_state; |
96 | vorbis_info *vi=vd->vi; |
97 | codec_setup_info *ci=vi->codec_setup; |
98 | oggpack_buffer *opb=&vb->opb; |
99 | int mode; |
100 | |
101 | /* first things first. Make sure decode is ready */ |
102 | _vorbis_block_ripcord(vb); |
103 | oggpack_readinit(opb,op->packet,op->bytes); |
104 | |
105 | /* Check the packet type */ |
106 | if(oggpack_read(opb,1)!=0){ |
107 | /* Oops. This is not an audio data packet */ |
108 | return(OV_ENOTAUDIO); |
109 | } |
110 | |
111 | /* read our mode and pre/post windowsize */ |
112 | mode=oggpack_read(opb,b->modebits); |
113 | if(mode==-1)return(OV_EBADPACKET); |
114 | |
115 | vb->mode=mode; |
116 | if(!ci->mode_param[mode]){ |
117 | return(OV_EBADPACKET); |
118 | } |
119 | |
120 | vb->W=ci->mode_param[mode]->blockflag; |
121 | if(vb->W){ |
122 | vb->lW=oggpack_read(opb,1); |
123 | vb->nW=oggpack_read(opb,1); |
124 | if(vb->nW==-1) return(OV_EBADPACKET); |
125 | }else{ |
126 | vb->lW=0; |
127 | vb->nW=0; |
128 | } |
129 | |
130 | /* more setup */ |
131 | vb->granulepos=op->granulepos; |
132 | vb->sequence=op->packetno; |
133 | vb->eofflag=op->e_o_s; |
134 | |
135 | /* no pcm */ |
136 | vb->pcmend=0; |
137 | vb->pcm=NULL; |
138 | |
139 | return(0); |
140 | } |
141 | |
142 | long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){ |
143 | codec_setup_info *ci=vi->codec_setup; |
144 | oggpack_buffer opb; |
145 | int mode; |
146 | |
147 | if(ci==NULL || ci->modes<=0){ |
148 | /* codec setup not properly intialized */ |
149 | return(OV_EFAULT); |
150 | } |
151 | |
152 | oggpack_readinit(&opb,op->packet,op->bytes); |
153 | |
154 | /* Check the packet type */ |
155 | if(oggpack_read(&opb,1)!=0){ |
156 | /* Oops. This is not an audio data packet */ |
157 | return(OV_ENOTAUDIO); |
158 | } |
159 | |
160 | /* read our mode and pre/post windowsize */ |
161 | mode=oggpack_read(&opb,ov_ilog(ci->modes-1)); |
162 | if(mode==-1 || !ci->mode_param[mode])return(OV_EBADPACKET); |
163 | return(ci->blocksizes[ci->mode_param[mode]->blockflag]); |
164 | } |
165 | |
166 | int vorbis_synthesis_halfrate(vorbis_info *vi,int flag){ |
167 | /* set / clear half-sample-rate mode */ |
168 | codec_setup_info *ci=vi->codec_setup; |
169 | |
170 | /* right now, our MDCT can't handle < 64 sample windows. */ |
171 | if(ci->blocksizes[0]<=64 && flag)return -1; |
172 | ci->halfrate_flag=(flag?1:0); |
173 | return 0; |
174 | } |
175 | |
176 | int vorbis_synthesis_halfrate_p(vorbis_info *vi){ |
177 | codec_setup_info *ci=vi->codec_setup; |
178 | return ci->halfrate_flag; |
179 | } |
180 | |