14276
|
1 #include <stdio.h>
|
|
2 #include <stdlib.h>
|
|
3 #include <unistd.h>
|
|
4 #include "config.h"
|
|
5
|
|
6 #ifdef USE_WIN32DLL
|
|
7
|
|
8 #include "ad_internal.h"
|
|
9 #include "vqf.h"
|
17012
|
10 #include "loader/ldt_keeper.h"
|
14276
|
11 #include "wine/windef.h"
|
17012
|
12 #include "libaf/af_format.h"
|
14276
|
13
|
|
14 #include "help_mp.h"
|
|
15
|
|
16 static ad_info_t info =
|
|
17 {
|
|
18 "TWinVQ decoder",
|
|
19 "vqf",
|
|
20 "Roberto Togni",
|
|
21 "Nick Kurshev",
|
|
22 "Ported from MPlayerXP"
|
|
23 };
|
|
24
|
|
25 LIBAD_EXTERN(twin)
|
|
26
|
|
27 void* WINAPI LoadLibraryA(char* name);
|
|
28 void* WINAPI GetProcAddress(void* handle, char* func);
|
|
29 int WINAPI FreeLibrary(void* handle);
|
|
30
|
|
31 static int (*TvqInitialize)( headerInfo *setupInfo, INDEX *index, int dispErrorMessageBox );
|
|
32 static void (*TvqTerminate)( INDEX *index );
|
|
33 static void (*TvqGetVectorInfo)(int *bits0[], int *bits1[]);
|
|
34
|
|
35 static void (*TvqDecodeFrame)(INDEX *indexp, float out[]);
|
|
36 static int (*TvqWtypeToBtype)( int w_type, int *btype );
|
|
37 static void (*TvqUpdateVectorInfo)(int varbits, int *ndiv, int bits0[], int bits1[]);
|
|
38
|
|
39 static int (*TvqCheckVersion)(char *versionID);
|
|
40 static void (*TvqGetConfInfo)(tvqConfInfo *cf);
|
|
41 static int (*TvqGetFrameSize)();
|
|
42 static int (*TvqGetNumFixedBitsPerFrame)();
|
|
43
|
|
44 #define BYTE_BIT 8
|
|
45 #define BBUFSIZ 1024 /* Bit buffer size (bytes) */
|
|
46 #define BBUFLEN (BBUFSIZ*BYTE_BIT) /* Bit buffer length (bits) */
|
|
47 typedef struct vqf_priv_s
|
|
48 {
|
|
49 float pts;
|
|
50 WAVEFORMATEX o_wf; // out format
|
|
51 INDEX index;
|
|
52 tvqConfInfo cf;
|
|
53 headerInfo hi;
|
|
54 int *bits_0[N_INTR_TYPE], *bits_1[N_INTR_TYPE];
|
|
55 unsigned framesize;
|
|
56 /* stream related */
|
|
57 int readable;
|
|
58 int ptr; /* current point in the bit buffer */
|
|
59 int nbuf; /* bit buffer size */
|
|
60 char buf[BBUFSIZ]; /* the bit buffer */
|
|
61 int skip_cnt;
|
|
62 }vqf_priv_t;
|
|
63
|
|
64 static void* vqf_dll;
|
|
65
|
|
66 static int load_dll( char *libname )
|
|
67 {
|
|
68 #ifdef WIN32_LOADER
|
|
69 Setup_LDT_Keeper();
|
|
70 #endif
|
|
71 vqf_dll = LoadLibraryA(libname);
|
|
72 if( vqf_dll == NULL )
|
|
73 {
|
|
74 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "failed loading dll\n" );
|
|
75 return 0;
|
|
76 }
|
|
77 TvqInitialize = GetProcAddress(vqf_dll,"TvqInitialize");
|
|
78 TvqTerminate = GetProcAddress(vqf_dll,"TvqTerminate");
|
|
79 TvqGetVectorInfo = GetProcAddress(vqf_dll,"TvqGetVectorInfo");
|
|
80 TvqDecodeFrame = GetProcAddress(vqf_dll,"TvqDecodeFrame");
|
|
81 TvqWtypeToBtype = GetProcAddress(vqf_dll,"TvqWtypeToBtype");
|
|
82 TvqUpdateVectorInfo = GetProcAddress(vqf_dll,"TvqUpdateVectorInfo");
|
|
83 TvqCheckVersion = GetProcAddress(vqf_dll,"TvqCheckVersion");
|
|
84 TvqGetConfInfo = GetProcAddress(vqf_dll,"TvqGetConfInfo");
|
|
85 TvqGetFrameSize = GetProcAddress(vqf_dll,"TvqGetFrameSize");
|
|
86 TvqGetNumFixedBitsPerFrame = GetProcAddress(vqf_dll,"TvqGetNumFixedBitsPerFrame");
|
|
87 return TvqInitialize && TvqTerminate && TvqGetVectorInfo &&
|
|
88 TvqDecodeFrame && TvqWtypeToBtype && TvqUpdateVectorInfo &&
|
|
89 TvqCheckVersion && TvqGetConfInfo && TvqGetFrameSize &&
|
|
90 TvqGetNumFixedBitsPerFrame;
|
|
91 }
|
|
92
|
|
93 extern void print_wave_header(WAVEFORMATEX *h);
|
|
94 static int init_vqf_audio_codec(sh_audio_t *sh_audio){
|
|
95 WAVEFORMATEX *in_fmt=sh_audio->wf;
|
|
96 vqf_priv_t*priv=sh_audio->context;
|
|
97 int ver;
|
|
98 mp_msg(MSGT_DECAUDIO, MSGL_INFO, "======= Win32 (TWinVQ) AUDIO Codec init =======\n");
|
|
99
|
|
100 sh_audio->channels=in_fmt->nChannels;
|
|
101 sh_audio->samplerate=in_fmt->nSamplesPerSec;
|
|
102 sh_audio->sample_format=AF_FORMAT_S16_NE;
|
|
103 // sh_audio->sample_format=AF_FORMAT_FLOAT_NE;
|
|
104 sh_audio->samplesize=af_fmt2bits(sh_audio->sample_format)/8;
|
|
105 priv->o_wf.nChannels=in_fmt->nChannels;
|
|
106 priv->o_wf.nSamplesPerSec=in_fmt->nSamplesPerSec;
|
|
107 priv->o_wf.nBlockAlign=sh_audio->samplesize*in_fmt->nChannels;
|
|
108 priv->o_wf.nAvgBytesPerSec=in_fmt->nBlockAlign*in_fmt->nChannels;
|
|
109 priv->o_wf.wFormatTag=0x01;
|
|
110 priv->o_wf.wBitsPerSample=in_fmt->wBitsPerSample;
|
|
111 priv->o_wf.cbSize=0;
|
|
112
|
|
113 if(verbose)
|
|
114 {
|
|
115 mp_msg(MSGT_DECAUDIO, MSGL_INFO, "Input format:\n");
|
|
116 print_wave_header(in_fmt);
|
|
117 mp_msg(MSGT_DECAUDIO, MSGL_INFO, "Output fmt:\n");
|
|
118 print_wave_header(&priv->o_wf);
|
|
119 }
|
|
120 memcpy(&priv->hi,&in_fmt[1],sizeof(headerInfo));
|
|
121 if((ver=TvqInitialize(&priv->hi,&priv->index,0))){
|
|
122 const char *tvqe[]={
|
|
123 "No errors",
|
|
124 "General error",
|
|
125 "Wrong version",
|
|
126 "Channel setting error",
|
|
127 "Wrong coding mode",
|
|
128 "Inner parameter setting error",
|
|
129 "Wrong number of VQ pre-selection candidates, used only in encoder" };
|
|
130 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Tvq initialization error: %s\n",ver>=0&&ver<7?tvqe[ver]:"Unknown");
|
|
131 return 0;
|
|
132 }
|
|
133 ver=TvqCheckVersion(priv->hi.ID);
|
|
134 if(ver==TVQ_UNKNOWN_VERSION){
|
|
135 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Tvq unknown version of stream\n" );
|
|
136 return 0;
|
|
137 }
|
|
138 TvqGetConfInfo(&priv->cf);
|
|
139 TvqGetVectorInfo(priv->bits_0,priv->bits_1);
|
|
140 priv->framesize=TvqGetFrameSize();
|
|
141 sh_audio->audio_in_minsize=priv->framesize*in_fmt->nChannels;
|
|
142 sh_audio->a_in_buffer_size=4*sh_audio->audio_in_minsize;
|
|
143 sh_audio->a_in_buffer=malloc(sh_audio->a_in_buffer_size);
|
|
144 sh_audio->a_in_buffer_len=0;
|
|
145
|
|
146
|
|
147 return 1;
|
|
148 }
|
|
149
|
|
150 static int close_vqf_audio_codec(sh_audio_t *sh_audio)
|
|
151 {
|
|
152 vqf_priv_t*priv=sh_audio->context;
|
|
153 TvqTerminate(&priv->index);
|
|
154 return 1;
|
|
155 }
|
|
156
|
|
157 int init(sh_audio_t *sh_audio)
|
|
158 {
|
|
159 return 1;
|
|
160 }
|
|
161
|
|
162 int preinit(sh_audio_t *sh_audio)
|
|
163 {
|
|
164 /* Win32 VQF audio codec: */
|
|
165 vqf_priv_t *priv;
|
|
166 if(!(sh_audio->context=malloc(sizeof(vqf_priv_t)))) return 0;
|
|
167 priv=sh_audio->context;
|
|
168 if(!load_dll(sh_audio->codec->dll))
|
|
169 {
|
|
170 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "win32.dll looks broken :(\n");
|
|
171 return 0;
|
|
172 }
|
|
173 if(!init_vqf_audio_codec(sh_audio)){
|
|
174 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "TWinVQ initialization fail\n");
|
|
175 return 0;
|
|
176 }
|
|
177 mp_msg(MSGT_DECAUDIO, MSGL_INFO, "INFO: TWinVQ (%s) audio codec init OK!\n",sh_audio->codec->dll);
|
|
178 priv->skip_cnt = 2;
|
|
179 return 1;
|
|
180 }
|
|
181
|
|
182 void uninit(sh_audio_t *sh)
|
|
183 {
|
|
184 close_vqf_audio_codec(sh);
|
|
185 free(sh->context);
|
|
186 FreeLibrary(vqf_dll);
|
|
187 }
|
|
188
|
|
189 int control(sh_audio_t *sh_audio,int cmd,void* arg, ...)
|
|
190 {
|
|
191 switch(cmd) {
|
|
192 case ADCTRL_QUERY_FORMAT:
|
|
193 return CONTROL_TRUE;
|
|
194 default:
|
|
195 return CONTROL_UNKNOWN;
|
|
196 }
|
|
197 }
|
|
198
|
|
199 static int bread(char *data, /* Output: Output data array */
|
|
200 int size, /* Input: Length of each data */
|
|
201 int nbits, /* Input: Number of bits to write */
|
|
202 sh_audio_t *sh) /* Input: File pointer */
|
|
203 {
|
|
204 /*--- Variables ---*/
|
|
205 int ibits, iptr, idata, ibufadr, ibufbit, icl;
|
|
206 unsigned char mask, tmpdat;
|
|
207 int retval;
|
|
208 vqf_priv_t *priv=sh->context;
|
|
209
|
|
210 /*--- Main operation ---*/
|
|
211 retval = 0;
|
|
212 mask = 0x1;
|
|
213 for ( ibits=0; ibits<nbits; ibits++ ){
|
|
214 if ( priv->readable == 0 ){ /* when the file data buffer is empty */
|
|
215 priv->nbuf = demux_read_data(sh->ds, priv->buf, BBUFSIZ);
|
|
216 priv->nbuf *= 8;
|
|
217 priv->readable = 1;
|
|
218 }
|
|
219 iptr = priv->ptr; /* current file data buffer pointer */
|
|
220 if ( iptr >= priv->nbuf ) /* If data file is empty then return */
|
|
221 return(retval);
|
|
222 ibufadr = iptr/BYTE_BIT; /* current file data buffer address */
|
|
223 ibufbit = iptr%BYTE_BIT; /* current file data buffer bit */
|
|
224 /* tmpdat = stream->buf[ibufadr] >> (BYTE_BIT-ibufbit-1); */
|
|
225 tmpdat = (unsigned char)priv->buf[ibufadr];
|
|
226 tmpdat >>= (BYTE_BIT-ibufbit-1);
|
|
227 /* current data bit */
|
|
228
|
|
229 idata = ibits*size; /* output data address */
|
|
230 data[idata] = (char)(tmpdat & mask); /* set output data */
|
|
231 for (icl=1; icl<size; icl++)
|
|
232 data[idata+icl] = 0; /* clear the rest output data buffer */
|
|
233 priv->ptr += 1; /* update data buffer pointer */
|
|
234 if (priv->ptr == BBUFLEN){
|
|
235 priv->ptr = 0;
|
|
236 priv->readable = 0;
|
|
237 }
|
|
238 ++retval;
|
|
239 }
|
|
240 return(retval);
|
|
241 }
|
|
242
|
|
243 #define BITS_INT (sizeof(int)*8)
|
|
244
|
|
245 static int get_bstm(int *data, /* Input: input data */
|
|
246 unsigned nbits, /* Input: number of bits */
|
|
247 sh_audio_t *sh) /* Input: bit file pointer */
|
|
248 {
|
|
249 unsigned ibit;
|
|
250 unsigned mask;
|
|
251 unsigned work;
|
|
252 char tmpbit[BITS_INT];
|
|
253 int retval;
|
|
254
|
|
255 if ( nbits > BITS_INT ){
|
|
256 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "get_bstm(): %d: %d Error.\n",
|
|
257 nbits, BITS_INT);
|
|
258 exit(1);
|
|
259 }
|
|
260 retval = bread(tmpbit, sizeof(*tmpbit), nbits, sh);
|
|
261 for (ibit=retval; ibit<nbits; ibit++){
|
|
262 tmpbit[ibit] = 0;
|
|
263 }
|
|
264 mask = 0x1<<(nbits-1);
|
|
265 work=0;
|
|
266 for ( ibit=0; ibit<nbits; ibit++ ){
|
|
267 work += mask*tmpbit[ibit];
|
|
268 mask >>= 1;
|
|
269 }
|
|
270 *data = work;
|
|
271 return(retval);
|
|
272 }
|
|
273
|
|
274 static int GetVqInfo( tvqConfInfoSubBlock *cfg,
|
|
275 int bits0[],
|
|
276 int bits1[],
|
|
277 int variableBits,
|
|
278 INDEX *index,
|
|
279 sh_audio_t *sh)
|
|
280 {
|
|
281 int idiv;
|
|
282 int bitcount = 0;
|
|
283
|
|
284 if ( index->btype == BLK_LONG ){
|
|
285 TvqUpdateVectorInfo( variableBits, &cfg->ndiv, bits0, bits1 ); // re-calculate VQ bits
|
|
286 }
|
|
287 for ( idiv=0; idiv<cfg->ndiv; idiv++ ){
|
|
288 bitcount += get_bstm(&index->wvq[idiv],bits0[idiv],sh); /* CB 0 */
|
|
289 bitcount += get_bstm(&index->wvq[idiv+cfg->ndiv],bits1[idiv],sh); /* CB 1 */
|
|
290 }
|
|
291 return bitcount;
|
|
292 }
|
|
293
|
|
294 static int GetBseInfo( tvqConfInfo *cf, tvqConfInfoSubBlock *cfg, INDEX *index, sh_audio_t *sh)
|
|
295 {
|
|
296 int i_sup, isf, itmp, idiv;
|
|
297 int bitcount = 0;
|
|
298
|
|
299 for ( i_sup=0; i_sup<cf->N_CH; i_sup++ ){
|
|
300 for ( isf=0; isf<cfg->nsf; isf++ ){
|
|
301 for ( idiv=0; idiv<cfg->fw_ndiv; idiv++ ){
|
|
302 itmp = idiv + ( isf + i_sup * cfg->nsf ) * cfg->fw_ndiv;
|
|
303 bitcount += get_bstm(&index->fw[itmp],cfg->fw_nbit,sh);
|
|
304 }
|
|
305 }
|
|
306 }
|
|
307 for ( i_sup=0; i_sup<cf->N_CH; i_sup++ ){
|
|
308 for ( isf=0; isf<cfg->nsf; isf++ ){
|
|
309 bitcount += get_bstm(&index->fw_alf[i_sup * cfg->nsf + isf],cf->FW_ARSW_BITS,sh);
|
|
310 }
|
|
311 }
|
|
312 return bitcount;
|
|
313 }
|
|
314
|
|
315 static int GetGainInfo(tvqConfInfo *cf, tvqConfInfoSubBlock *cfg, INDEX *index, sh_audio_t *sh )
|
|
316 {
|
|
317 int i_sup, iptop, isf;
|
|
318 int bitcount = 0;
|
|
319
|
|
320 for ( i_sup=0; i_sup<cf->N_CH; i_sup++ ){
|
|
321 iptop = ( cfg->nsubg + 1 ) * i_sup;
|
|
322 bitcount += get_bstm(&index->pow[iptop], cf->GAIN_BITS,sh);
|
|
323 for ( isf=0; isf<cfg->nsubg; isf++ ){
|
|
324 bitcount += get_bstm(&index->pow[iptop+isf+1], cf->SUB_GAIN_BITS,sh);
|
|
325 }
|
|
326 }
|
|
327 return bitcount;
|
|
328 }
|
|
329
|
|
330 static int GetLspInfo( tvqConfInfo *cf, INDEX *index, sh_audio_t *sh )
|
|
331 {
|
|
332 int i_sup, itmp;
|
|
333 int bitcount = 0;
|
|
334
|
|
335 for ( i_sup=0; i_sup<cf->N_CH; i_sup++ ){
|
|
336 bitcount += get_bstm(&index->lsp[i_sup][0], cf->LSP_BIT0,sh); /* pred. switch */
|
|
337 bitcount += get_bstm(&index->lsp[i_sup][1], cf->LSP_BIT1,sh); /* first stage */
|
|
338 for ( itmp=0; itmp<cf->LSP_SPLIT; itmp++ ){ /* second stage */
|
|
339 bitcount += get_bstm(&index->lsp[i_sup][itmp+2], cf->LSP_BIT2,sh);
|
|
340 }
|
|
341 }
|
|
342
|
|
343 return bitcount;
|
|
344 }
|
|
345
|
|
346 static int GetPpcInfo( tvqConfInfo *cf, INDEX *index, sh_audio_t *sh)
|
|
347 {
|
|
348 int idiv, i_sup;
|
|
349 int bitcount = 0;
|
|
350 vqf_priv_t*priv=sh->context;
|
|
351
|
|
352 for ( idiv=0; idiv<cf->N_DIV_P; idiv++ ){
|
|
353 bitcount += get_bstm(&(index->pls[idiv]), priv->bits_0[BLK_PPC][idiv],sh); /*CB0*/
|
|
354 bitcount += get_bstm(&(index->pls[idiv+cf->N_DIV_P]), priv->bits_1[BLK_PPC][idiv],sh);/*CB1*/
|
|
355 }
|
|
356 for (i_sup=0; i_sup<cf->N_CH; i_sup++){
|
|
357 bitcount += get_bstm(&(index->pit[i_sup]), cf->BASF_BIT,sh);
|
|
358 bitcount += get_bstm(&(index->pgain[i_sup]), cf->PGAIN_BIT,sh);
|
|
359 }
|
|
360
|
|
361 return bitcount;
|
|
362 }
|
|
363
|
|
364 static int GetEbcInfo( tvqConfInfo *cf, tvqConfInfoSubBlock *cfg, INDEX *index, sh_audio_t *sh)
|
|
365 {
|
|
366 int i_sup, isf, itmp;
|
|
367 int bitcount = 0;
|
|
368
|
|
369 for ( i_sup=0; i_sup<cf->N_CH; i_sup++ ){
|
|
370 for ( isf=0; isf<cfg->nsf; isf++){
|
|
371 int indexSfOffset = isf * ( cfg->ncrb - cfg->ebc_crb_base ) - cfg->ebc_crb_base;
|
|
372 for ( itmp=cfg->ebc_crb_base; itmp<cfg->ncrb; itmp++ ){
|
|
373 bitcount += get_bstm(&index->bc[i_sup][itmp+indexSfOffset], cfg->ebc_bits,sh);
|
|
374 }
|
|
375 }
|
|
376 }
|
|
377
|
|
378 return bitcount;
|
|
379 }
|
|
380
|
|
381 static int vqf_read_frame(sh_audio_t *sh,INDEX *index)
|
|
382 {
|
|
383 /*--- Variables ---*/
|
|
384 tvqConfInfoSubBlock *cfg;
|
|
385 int variableBits;
|
|
386 int bitcount;
|
|
387 int numFixedBitsPerFrame = TvqGetNumFixedBitsPerFrame();
|
|
388 int btype;
|
|
389 vqf_priv_t *priv=sh->context;
|
|
390
|
|
391 /*--- Initialization ---*/
|
|
392 variableBits = 0;
|
|
393 bitcount = 0;
|
|
394
|
|
395 /*--- read block independent factors ---*/
|
|
396 /* Window type */
|
|
397 bitcount += get_bstm( &index->w_type, priv->cf.BITS_WTYPE, sh );
|
|
398 if ( TvqWtypeToBtype( index->w_type, &index->btype ) ) {
|
|
399 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Error: unknown window type: %d\n", index->w_type);
|
|
400 return 0;
|
|
401 }
|
|
402 btype = index->btype;
|
|
403
|
|
404 /*--- read block dependent factors ---*/
|
|
405 cfg = &priv->cf.cfg[btype]; // set the block dependent paremeters table
|
|
406
|
|
407 bitcount += variableBits;
|
|
408
|
|
409 /* Interleaved vector quantization */
|
|
410 bitcount += GetVqInfo( cfg, priv->bits_0[btype], priv->bits_1[btype], variableBits, index, sh );
|
|
411
|
|
412 /* Bark-scale envelope */
|
|
413 bitcount += GetBseInfo( &priv->cf, cfg, index, sh );
|
|
414 /* Gain */
|
|
415 bitcount += GetGainInfo( &priv->cf, cfg, index, sh );
|
|
416 /* LSP */
|
|
417 bitcount += GetLspInfo( &priv->cf, index, sh );
|
|
418 /* PPC */
|
|
419 if ( cfg->ppc_enable ){
|
|
420 bitcount += GetPpcInfo( &priv->cf, index, sh );
|
|
421 }
|
|
422 /* Energy Balance Calibration */
|
|
423 if ( cfg->ebc_enable ){
|
|
424 bitcount += GetEbcInfo( &priv->cf, cfg, index, sh );
|
|
425 }
|
|
426
|
|
427 return bitcount == numFixedBitsPerFrame ? bitcount/8 : 0;
|
|
428 }
|
|
429
|
|
430 static void frtobuf_s16(float out[], /* Input --- input data frame */
|
|
431 short bufout[], /* Output --- output data buffer array */
|
|
432 unsigned frameSize, /* Input --- frame size */
|
|
433 unsigned numChannels) /* Input --- number of channels */
|
|
434 {
|
|
435 /*--- Variables ---*/
|
|
436 unsigned ismp, ich;
|
|
437 float *ptr;
|
|
438 float dtmp;
|
|
439
|
|
440 for ( ich=0; ich<numChannels; ich++ ){
|
|
441 ptr = out+ich*frameSize;
|
|
442 for ( ismp=0; ismp<frameSize; ismp++ ){
|
|
443 dtmp = ptr[ismp];
|
|
444 if ( dtmp >= 0. ) {
|
|
445 if ( dtmp > 32700. )
|
|
446 dtmp = 32700.;
|
|
447 bufout[ismp*numChannels+ich] = (short)(dtmp+0.5);
|
|
448 } else {
|
|
449 if ( dtmp < -32700. )
|
|
450 dtmp = -32700.;
|
|
451 bufout[ismp*numChannels+ich] = (short)(dtmp-0.5);
|
|
452 }
|
|
453 }
|
|
454 }
|
|
455 }
|
|
456
|
|
457 static void frtobuf_float(float out[], /* Input --- input data frame */
|
|
458 float bufout[], /* Output --- output data buffer array */
|
|
459 unsigned frameSize, /* Input --- frame size */
|
|
460 unsigned numChannels) /* Input --- number of channels */
|
|
461 {
|
|
462 /*--- Variables ---*/
|
|
463 unsigned ismp, ich;
|
|
464 float *ptr;
|
|
465 float dtmp;
|
|
466
|
|
467 for ( ich=0; ich<numChannels; ich++ ){
|
|
468 ptr = out+ich*frameSize;
|
|
469 for ( ismp=0; ismp<frameSize; ismp++ ){
|
|
470 dtmp = ptr[ismp];
|
|
471 if ( dtmp >= 0. ) {
|
|
472 if ( dtmp > 32700. )
|
|
473 dtmp = 32700.;
|
|
474 bufout[ismp*numChannels+ich] = dtmp/32767.;
|
|
475 } else {
|
|
476 if ( dtmp < -32700. )
|
|
477 dtmp = -32700.;
|
|
478 bufout[ismp*numChannels+ich] = dtmp/32767.;
|
|
479 }
|
|
480 }
|
|
481 }
|
|
482 }
|
|
483
|
|
484 int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen)
|
|
485 {
|
|
486 int l, len=0;
|
|
487 vqf_priv_t *priv=sh_audio->context;
|
|
488 while(len<minlen)
|
|
489 {
|
|
490 float out[priv->framesize*sh_audio->channels];
|
|
491 l=vqf_read_frame(sh_audio,&priv->index);
|
|
492 if(!l) break;
|
|
493 TvqDecodeFrame(&priv->index, out);
|
|
494 if (priv->skip_cnt) {
|
|
495 // Ingnore first two frames, replace them with silence
|
|
496 priv->skip_cnt--;
|
|
497 memset(buf, 0, priv->framesize*sh_audio->channels*sh_audio->samplesize);
|
|
498 } else {
|
|
499 if (sh_audio->sample_format == AF_FORMAT_S16_NE)
|
|
500 frtobuf_s16(out, (short *)buf, priv->framesize, sh_audio->channels);
|
|
501 else
|
|
502 frtobuf_float(out, (float *)buf, priv->framesize, sh_audio->channels);
|
|
503 }
|
|
504 len += priv->framesize*sh_audio->channels*sh_audio->samplesize;
|
|
505 buf += priv->framesize*sh_audio->channels*sh_audio->samplesize;
|
|
506 }
|
|
507 return len;
|
|
508 }
|
|
509
|
|
510 #endif
|