Mercurial > SDL_sound_CoreAudio
comparison decoders/libmpg123/frame.c @ 562:7e08477b0fc1
MP3 decoder upgrade work.
Ripped out SMPEG and mpglib support, replaced it with "mpg123.c" and libmpg123.
libmpg123 is a much better version of mpglib, so it should solve all the
problems about MP3's not seeking, or most modern MP3's not playing at all,
etc. Since you no longer have to make a tradeoff with SMPEG for features, and
SMPEG is basically rotting, I removed it from the project.
There is still work to be done with libmpg123...there are MMX, 3DNow, SSE,
Altivec, etc decoders which we don't have enabled at the moment, and the
build system could use some work to make this compile more cleanly, etc.
Still: huge win.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Fri, 30 Jan 2009 02:44:47 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
561:f2985e08589c | 562:7e08477b0fc1 |
---|---|
1 /* | |
2 frame: Heap of routines dealing with the core mpg123 data structure. | |
3 | |
4 copyright 2008 by the mpg123 project - free software under the terms of the LGPL 2.1 | |
5 see COPYING and AUTHORS files in distribution or http://mpg123.org | |
6 initially written by Thomas Orgis | |
7 */ | |
8 | |
9 #include "mpg123lib_intern.h" | |
10 #include "getcpuflags.h" | |
11 #include "debug.h" | |
12 | |
13 #define IGNORESHIFT 2 | |
14 | |
15 static void frame_fixed_reset(mpg123_handle *fr); | |
16 | |
17 /* that's doubled in decode_ntom.c */ | |
18 #define NTOM_MUL (32768) | |
19 #define aligned_pointer(p,type,alignment) \ | |
20 (((char*)(p)-(char*)NULL) % (alignment)) \ | |
21 ? (type*)((char*)(p) + (alignment) - (((char*)(p)-(char*)NULL) % (alignment))) \ | |
22 : (type*)(p) | |
23 void frame_default_pars(mpg123_pars *mp) | |
24 { | |
25 mp->outscale = MAXOUTBURST; | |
26 #ifdef GAPLESS | |
27 mp->flags = MPG123_GAPLESS; | |
28 #else | |
29 mp->flags = 0; | |
30 #endif | |
31 mp->force_rate = 0; | |
32 mp->down_sample = 0; | |
33 mp->rva = 0; | |
34 mp->halfspeed = 0; | |
35 mp->doublespeed = 0; | |
36 mp->verbose = 0; | |
37 mp->icy_interval = 0; | |
38 #ifndef WIN32 | |
39 mp->timeout = 0; | |
40 #endif | |
41 mp->resync_limit = 1024; | |
42 #ifdef FRAME_INDEX | |
43 mp->index_size = INDEX_SIZE; | |
44 #endif | |
45 mpg123_fmt_all(mp); | |
46 } | |
47 | |
48 void frame_init(mpg123_handle *fr) | |
49 { | |
50 frame_init_par(fr, NULL); | |
51 } | |
52 | |
53 void frame_init_par(mpg123_handle *fr, mpg123_pars *mp) | |
54 { | |
55 fr->own_buffer = FALSE; | |
56 fr->buffer.data = NULL; | |
57 fr->rawbuffs = NULL; | |
58 fr->rawdecwin = NULL; | |
59 fr->conv16to8_buf = NULL; | |
60 fr->xing_toc = NULL; | |
61 fr->cpu_opts.type = defopt; | |
62 fr->cpu_opts.class = (defopt == mmx || defopt == sse || defopt == dreidnowext) ? mmxsse : normal; | |
63 /* these two look unnecessary, check guarantee for synth_ntom_set_step (in control_generic, even)! */ | |
64 fr->ntom_val[0] = NTOM_MUL>>1; | |
65 fr->ntom_val[1] = NTOM_MUL>>1; | |
66 fr->ntom_step = NTOM_MUL; | |
67 /* unnecessary: fr->buffer.size = fr->buffer.fill = 0; */ | |
68 mpg123_reset_eq(fr); | |
69 init_icy(&fr->icy); | |
70 init_id3(fr); | |
71 /* frame_outbuffer is missing... */ | |
72 /* frame_buffers is missing... that one needs cpu opt setting! */ | |
73 /* after these... frame_reset is needed before starting full decode */ | |
74 invalidate_format(&fr->af); | |
75 fr->rdat.r_read = NULL; | |
76 fr->rdat.r_lseek = NULL; | |
77 fr->decoder_change = 1; | |
78 fr->err = MPG123_OK; | |
79 if(mp == NULL) frame_default_pars(&fr->p); | |
80 else memcpy(&fr->p, mp, sizeof(struct mpg123_pars_struct)); | |
81 | |
82 fr->down_sample = 0; /* Initialize to silence harmless errors when debugging. */ | |
83 frame_fixed_reset(fr); /* Reset only the fixed data, dynamic buffers are not there yet! */ | |
84 #ifdef FRAME_INDEX | |
85 fi_init(&fr->index); | |
86 frame_index_setup(fr); /* Apply the size setting. */ | |
87 #endif | |
88 } | |
89 | |
90 mpg123_pars attribute_align_arg *mpg123_new_pars(int *error) | |
91 { | |
92 mpg123_pars *mp = malloc(sizeof(struct mpg123_pars_struct)); | |
93 if(mp != NULL){ frame_default_pars(mp); if(error != NULL) *error = MPG123_OK; } | |
94 else if(error != NULL) *error = MPG123_OUT_OF_MEM; | |
95 return mp; | |
96 } | |
97 | |
98 void attribute_align_arg mpg123_delete_pars(mpg123_pars* mp) | |
99 { | |
100 if(mp != NULL) free(mp); | |
101 } | |
102 | |
103 int attribute_align_arg mpg123_reset_eq(mpg123_handle *mh) | |
104 { | |
105 int i; | |
106 mh->have_eq_settings = 0; | |
107 for(i=0; i < 32; ++i) mh->equalizer[0][i] = mh->equalizer[1][i] = DOUBLE_TO_REAL(1.0); | |
108 | |
109 return MPG123_OK; | |
110 } | |
111 | |
112 int frame_outbuffer(mpg123_handle *fr) | |
113 { | |
114 size_t size = mpg123_safe_buffer()*AUDIOBUFSIZE; | |
115 if(!fr->own_buffer) fr->buffer.data = NULL; | |
116 if(fr->buffer.data != NULL && fr->buffer.size != size) | |
117 { | |
118 free(fr->buffer.data); | |
119 fr->buffer.data = NULL; | |
120 } | |
121 fr->buffer.size = size; | |
122 if(fr->buffer.data == NULL) fr->buffer.data = (unsigned char*) malloc(fr->buffer.size); | |
123 if(fr->buffer.data == NULL) | |
124 { | |
125 fr->err = MPG123_OUT_OF_MEM; | |
126 return -1; | |
127 } | |
128 fr->own_buffer = TRUE; | |
129 fr->buffer.fill = 0; | |
130 return 0; | |
131 } | |
132 | |
133 int attribute_align_arg mpg123_replace_buffer(mpg123_handle *mh, unsigned char *data, size_t size) | |
134 { | |
135 if(data == NULL || size < mpg123_safe_buffer()) | |
136 { | |
137 mh->err = MPG123_BAD_BUFFER; | |
138 return MPG123_ERR; | |
139 } | |
140 if(mh->own_buffer && mh->buffer.data != NULL) free(mh->buffer.data); | |
141 mh->own_buffer = FALSE; | |
142 mh->buffer.data = data; | |
143 mh->buffer.size = size; | |
144 mh->buffer.fill = 0; | |
145 return MPG123_OK; | |
146 } | |
147 | |
148 #ifdef FRAME_INDEX | |
149 int frame_index_setup(mpg123_handle *fr) | |
150 { | |
151 int ret = MPG123_ERR; | |
152 if(fr->p.index_size >= 0) | |
153 { /* Simple fixed index. */ | |
154 fr->index.grow_size = 0; | |
155 debug1("resizing index to %li", fr->p.index_size); | |
156 ret = fi_resize(&fr->index, (size_t)fr->p.index_size); | |
157 debug2("index resized... %lu at %p", (unsigned long)fr->index.size, (void*)fr->index.data); | |
158 } | |
159 else | |
160 { /* A growing index. We give it a start, though. */ | |
161 fr->index.grow_size = (size_t)(- fr->p.index_size); | |
162 if(fr->index.size < fr->index.grow_size) | |
163 ret = fi_resize(&fr->index, fr->index.grow_size); | |
164 else | |
165 ret = MPG123_OK; /* We have minimal size already... and since growing is OK... */ | |
166 } | |
167 debug2("set up frame index of size %lu (ret=%i)", (unsigned long)fr->index.size, ret); | |
168 | |
169 return ret; | |
170 } | |
171 #endif | |
172 | |
173 int frame_buffers(mpg123_handle *fr) | |
174 { | |
175 int buffssize = 0; | |
176 debug1("frame %p buffer", (void*)fr); | |
177 /* | |
178 the used-to-be-static buffer of the synth functions, has some subtly different types/sizes | |
179 | |
180 2to1, 4to1, ntom, generic, i386: real[2][2][0x110] | |
181 mmx, sse: short[2][2][0x110] | |
182 i586(_dither): 4352 bytes; int/long[2][2][0x110] | |
183 i486: int[2][2][17*FIR_BUFFER_SIZE] | |
184 altivec: static real __attribute__ ((aligned (16))) buffs[4][4][0x110] | |
185 | |
186 Huh, altivec looks like fun. Well, let it be large... then, the 16 byte alignment seems to be implicit on MacOSX malloc anyway. | |
187 Let's make a reasonable attempt to allocate enough memory... | |
188 Keep in mind: biggest ones are i486 and altivec (mutually exclusive!), then follows i586 and normal real. | |
189 mmx/sse use short but also real for resampling. | |
190 Thus, minimum is 2*2*0x110*sizeof(real). | |
191 */ | |
192 if(fr->cpu_opts.type == altivec) buffssize = 4*4*0x110*sizeof(real); | |
193 #ifdef OPT_I486 | |
194 else if(fr->cpu_opts.type == ivier) buffssize = 2*2*17*FIR_BUFFER_SIZE*sizeof(int); | |
195 #endif | |
196 else if(fr->cpu_opts.type == ifuenf || fr->cpu_opts.type == ifuenf_dither || fr->cpu_opts.type == dreidnow) | |
197 buffssize = 2*2*0x110*4; /* don't rely on type real, we need 4352 bytes */ | |
198 | |
199 if(2*2*0x110*sizeof(real) > buffssize) | |
200 buffssize = 2*2*0x110*sizeof(real); | |
201 buffssize += 15; /* For 16-byte alignment (SSE likes that). */ | |
202 | |
203 if(fr->rawbuffs != NULL && fr->rawbuffss != buffssize) | |
204 { | |
205 free(fr->rawbuffs); | |
206 fr->rawbuffs = NULL; | |
207 } | |
208 | |
209 if(fr->rawbuffs == NULL) fr->rawbuffs = (unsigned char*) malloc(buffssize); | |
210 if(fr->rawbuffs == NULL) return -1; | |
211 fr->rawbuffss = buffssize; | |
212 fr->short_buffs[0][0] = aligned_pointer(fr->rawbuffs,short,16); | |
213 fr->short_buffs[0][1] = fr->short_buffs[0][0] + 0x110; | |
214 fr->short_buffs[1][0] = fr->short_buffs[0][1] + 0x110; | |
215 fr->short_buffs[1][1] = fr->short_buffs[1][0] + 0x110; | |
216 fr->real_buffs[0][0] = aligned_pointer(fr->rawbuffs,real,16); | |
217 fr->real_buffs[0][1] = fr->real_buffs[0][0] + 0x110; | |
218 fr->real_buffs[1][0] = fr->real_buffs[0][1] + 0x110; | |
219 fr->real_buffs[1][1] = fr->real_buffs[1][0] + 0x110; | |
220 #ifdef OPT_I486 | |
221 if(fr->cpu_opts.type == ivier) | |
222 { | |
223 fr->int_buffs[0][0] = (int*) fr->rawbuffs; | |
224 fr->int_buffs[0][1] = fr->int_buffs[0][0] + 17*FIR_BUFFER_SIZE; | |
225 fr->int_buffs[1][0] = fr->int_buffs[0][1] + 17*FIR_BUFFER_SIZE; | |
226 fr->int_buffs[1][1] = fr->int_buffs[1][0] + 17*FIR_BUFFER_SIZE; | |
227 } | |
228 #endif | |
229 #ifdef OPT_ALTIVEC | |
230 if(fr->cpu_opts.type == altivec) | |
231 { | |
232 int i,j; | |
233 fr->areal_buffs[0][0] = (real*) fr->rawbuffs; | |
234 for(i=0; i<4; ++i) for(j=0; j<4; ++j) | |
235 fr->areal_buffs[i][j] = fr->areal_buffs[0][0] + (i*4+j)*0x110; | |
236 } | |
237 #endif | |
238 /* now the different decwins... all of the same size, actually */ | |
239 /* The MMX ones want 32byte alignment, which I'll try to ensure manually */ | |
240 { | |
241 int decwin_size = (512+32)*sizeof(real); | |
242 if(fr->rawdecwin != NULL) free(fr->rawdecwin); | |
243 #ifdef OPT_MMXORSSE | |
244 #ifdef OPT_MULTI | |
245 if(fr->cpu_opts.class == mmxsse) | |
246 { | |
247 #endif | |
248 /* decwin_mmx will share, decwins will be appended ... sizeof(float)==4 */ | |
249 if(decwin_size < (512+32)*4) decwin_size = (512+32)*4; | |
250 decwin_size += (512+32)*4 + 31; /* the second window + alignment zone */ | |
251 /* (512+32)*4/32 == 2176/32 == 68, so one decwin block retains alignment */ | |
252 #ifdef OPT_MULTI | |
253 } | |
254 #endif | |
255 #endif | |
256 fr->rawdecwin = (unsigned char*) malloc(decwin_size); | |
257 if(fr->rawdecwin == NULL) return -1; | |
258 fr->decwin = (real*) fr->rawdecwin; | |
259 #ifdef OPT_MMXORSSE | |
260 #ifdef OPT_MULTI | |
261 if(fr->cpu_opts.class == mmxsse) | |
262 { | |
263 #endif | |
264 /* align decwin, assign that to decwin_mmx, append decwins */ | |
265 /* I need to add to decwin what is missing to the next full 32 byte -- also I want to make gcc -pedantic happy... */ | |
266 fr->decwin = aligned_pointer(fr->rawdecwin,real,32); | |
267 debug1("aligned decwin: %p", (void*)fr->decwin); | |
268 fr->decwin_mmx = (float*)fr->decwin; | |
269 fr->decwins = fr->decwin_mmx+512+32; | |
270 #ifdef OPT_MULTI | |
271 } | |
272 else debug("no decwins/decwin_mmx for that class"); | |
273 #endif | |
274 #endif | |
275 } | |
276 frame_buffers_reset(fr); | |
277 debug1("frame %p buffer done", (void*)fr); | |
278 return 0; | |
279 } | |
280 | |
281 int frame_buffers_reset(mpg123_handle *fr) | |
282 { | |
283 fr->buffer.fill = 0; /* hm, reset buffer fill... did we do a flush? */ | |
284 fr->bsnum = 0; | |
285 /* Wondering: could it be actually _wanted_ to retain buffer contents over different files? (special gapless / cut stuff) */ | |
286 fr->bsbuf = fr->bsspace[1]; | |
287 fr->bsbufold = fr->bsbuf; | |
288 fr->bitreservoir = 0; /* Not entirely sure if this is the right place for that counter. */ | |
289 memset(fr->bsspace, 0, 2*(MAXFRAMESIZE+512)); | |
290 memset(fr->ssave, 0, 34); | |
291 memset(fr->rawbuffs, 0, fr->rawbuffss); | |
292 fr->hybrid_blc[0] = fr->hybrid_blc[1] = 0; | |
293 memset(fr->hybrid_block, 0, sizeof(real)*2*2*SBLIMIT*SSLIMIT); | |
294 /* Not totally, but quite, sure that decwin(s) doesn't need cleaning. */ | |
295 return 0; | |
296 } | |
297 | |
298 void frame_icy_reset(mpg123_handle* fr) | |
299 { | |
300 if(fr->icy.data != NULL) free(fr->icy.data); | |
301 fr->icy.data = NULL; | |
302 fr->icy.interval = 0; | |
303 fr->icy.next = 0; | |
304 } | |
305 | |
306 void frame_free_toc(mpg123_handle *fr) | |
307 { | |
308 if(fr->xing_toc != NULL){ free(fr->xing_toc); fr->xing_toc = NULL; } | |
309 } | |
310 | |
311 /* Just copy the Xing TOC over... */ | |
312 int frame_fill_toc(mpg123_handle *fr, unsigned char* in) | |
313 { | |
314 if(fr->xing_toc == NULL) fr->xing_toc = malloc(100); | |
315 if(fr->xing_toc != NULL) | |
316 { | |
317 memcpy(fr->xing_toc, in, 100); | |
318 #ifdef DEBUG | |
319 debug("Got a TOC! Showing the values..."); | |
320 { | |
321 int i; | |
322 for(i=0; i<100; ++i) | |
323 debug2("entry %i = %i", i, fr->xing_toc[i]); | |
324 } | |
325 #endif | |
326 return TRUE; | |
327 } | |
328 return FALSE; | |
329 } | |
330 | |
331 /* Prepare the handle for a new track. | |
332 Reset variables, buffers... */ | |
333 int frame_reset(mpg123_handle* fr) | |
334 { | |
335 frame_buffers_reset(fr); | |
336 frame_fixed_reset(fr); | |
337 frame_free_toc(fr); | |
338 #ifdef FRAME_INDEX | |
339 fi_reset(&fr->index); | |
340 #endif | |
341 | |
342 return 0; | |
343 } | |
344 | |
345 /* Reset everythign except dynamic memory. */ | |
346 static void frame_fixed_reset(mpg123_handle *fr) | |
347 { | |
348 frame_icy_reset(fr); | |
349 open_bad(fr); | |
350 fr->to_decode = FALSE; | |
351 fr->to_ignore = FALSE; | |
352 fr->metaflags = 0; | |
353 fr->outblock = mpg123_safe_buffer(); | |
354 fr->num = -1; | |
355 fr->accurate = TRUE; | |
356 fr->silent_resync = 0; | |
357 fr->audio_start = 0; | |
358 fr->clip = 0; | |
359 fr->oldhead = 0; | |
360 fr->firsthead = 0; | |
361 fr->vbr = MPG123_CBR; | |
362 fr->abr_rate = 0; | |
363 fr->track_frames = 0; | |
364 fr->track_samples = -1; | |
365 fr->framesize=0; | |
366 fr->mean_frames = 0; | |
367 fr->mean_framesize = 0; | |
368 fr->freesize = 0; | |
369 fr->lastscale = -1; | |
370 fr->rva.level[0] = -1; | |
371 fr->rva.level[1] = -1; | |
372 fr->rva.gain[0] = 0; | |
373 fr->rva.gain[1] = 0; | |
374 fr->rva.peak[0] = 0; | |
375 fr->rva.peak[1] = 0; | |
376 fr->fsizeold = 0; | |
377 fr->firstframe = 0; | |
378 fr->ignoreframe = fr->firstframe-IGNORESHIFT; | |
379 fr->lastframe = -1; | |
380 fr->fresh = 1; | |
381 fr->new_format = 0; | |
382 #ifdef GAPLESS | |
383 frame_gapless_init(fr,0,0); | |
384 fr->lastoff = 0; | |
385 fr->firstoff = 0; | |
386 #endif | |
387 fr->bo[0] = 1; /* the usual bo */ | |
388 fr->bo[1] = 0; /* ditherindex */ | |
389 #ifdef OPT_I486 | |
390 fr->bo[0] = fr->bo[1] = FIR_SIZE-1; | |
391 #endif | |
392 reset_id3(fr); | |
393 reset_icy(&fr->icy); | |
394 /* ICY stuff should go into icy.c, eh? */ | |
395 fr->icy.interval = 0; | |
396 fr->icy.next = 0; | |
397 fr->halfphase = 0; /* here or indeed only on first-time init? */ | |
398 } | |
399 | |
400 void frame_free_buffers(mpg123_handle *fr) | |
401 { | |
402 if(fr->rawbuffs != NULL) free(fr->rawbuffs); | |
403 fr->rawbuffs = NULL; | |
404 if(fr->rawdecwin != NULL) free(fr->rawdecwin); | |
405 fr->rawdecwin = NULL; | |
406 if(fr->conv16to8_buf != NULL) free(fr->conv16to8_buf); | |
407 fr->conv16to8_buf = NULL; | |
408 } | |
409 | |
410 void frame_exit(mpg123_handle *fr) | |
411 { | |
412 if(fr->own_buffer && fr->buffer.data != NULL) | |
413 { | |
414 debug1("freeing buffer at %p", (void*)fr->buffer.data); | |
415 free(fr->buffer.data); | |
416 } | |
417 fr->buffer.data = NULL; | |
418 frame_free_buffers(fr); | |
419 frame_free_toc(fr); | |
420 #ifdef FRAME_INDEX | |
421 fi_exit(&fr->index); | |
422 #endif | |
423 exit_id3(fr); | |
424 clear_icy(&fr->icy); | |
425 } | |
426 | |
427 int attribute_align_arg mpg123_info(mpg123_handle *mh, struct mpg123_frameinfo *mi) | |
428 { | |
429 if(mh == NULL) return MPG123_ERR; | |
430 if(mi == NULL) | |
431 { | |
432 mh->err = MPG123_ERR_NULL; | |
433 return MPG123_ERR; | |
434 } | |
435 mi->version = mh->mpeg25 ? MPG123_2_5 : (mh->lsf ? MPG123_2_0 : MPG123_1_0); | |
436 mi->layer = mh->lay; | |
437 mi->rate = frame_freq(mh); | |
438 switch(mh->mode) | |
439 { | |
440 case 0: mi->mode = MPG123_M_STEREO; break; | |
441 case 1: mi->mode = MPG123_M_JOINT; break; | |
442 case 2: mi->mode = MPG123_M_DUAL; break; | |
443 case 3: mi->mode = MPG123_M_MONO; break; | |
444 default: error("That mode cannot be!"); | |
445 } | |
446 mi->mode_ext = mh->mode_ext; | |
447 mi->framesize = mh->framesize+4; /* Include header. */ | |
448 mi->flags = 0; | |
449 if(mh->error_protection) mi->flags |= MPG123_CRC; | |
450 if(mh->copyright) mi->flags |= MPG123_COPYRIGHT; | |
451 if(mh->extension) mi->flags |= MPG123_PRIVATE; | |
452 if(mh->original) mi->flags |= MPG123_ORIGINAL; | |
453 mi->emphasis = mh->emphasis; | |
454 mi->bitrate = frame_bitrate(mh); | |
455 mi->abr_rate = mh->abr_rate; | |
456 mi->vbr = mh->vbr; | |
457 return MPG123_OK; | |
458 } | |
459 | |
460 | |
461 /* | |
462 Fuzzy frame offset searching (guessing). | |
463 When we don't have an accurate position, we may use an inaccurate one. | |
464 Possibilities: | |
465 - use approximate positions from Xing TOC (not yet parsed) | |
466 - guess wildly from mean framesize and offset of first frame / beginning of file. | |
467 */ | |
468 | |
469 off_t frame_fuzzy_find(mpg123_handle *fr, off_t want_frame, off_t* get_frame) | |
470 { | |
471 /* Default is to go to the beginning. */ | |
472 off_t ret = fr->audio_start; | |
473 *get_frame = 0; | |
474 | |
475 /* But we try to find something better. */ | |
476 /* Xing VBR TOC works with relative positions, both in terms of audio frames and stream bytes. | |
477 Thus, it only works when whe know the length of things. | |
478 Oh... I assume the offsets are relative to the _total_ file length. */ | |
479 if(fr->xing_toc != NULL && fr->track_frames > 0 && fr->rdat.filelen > 0) | |
480 { | |
481 /* One could round... */ | |
482 int toc_entry = (int) ((double)want_frame*100./fr->track_frames); | |
483 /* It is an index in the 100-entry table. */ | |
484 if(toc_entry < 0) toc_entry = 0; | |
485 if(toc_entry > 99) toc_entry = 99; | |
486 | |
487 /* Now estimate back what frame we get. */ | |
488 *get_frame = (off_t) ((double)toc_entry/100. * fr->track_frames); | |
489 fr->accurate = FALSE; | |
490 fr->silent_resync = 1; | |
491 /* Question: Is the TOC for whole file size (with/without ID3) or the "real" audio data only? | |
492 ID3v1 info could also matter. */ | |
493 ret = (off_t) ((double)fr->xing_toc[toc_entry]/256.* fr->rdat.filelen); | |
494 } | |
495 else if(fr->mean_framesize > 0) | |
496 { /* Just guess with mean framesize (may be exact with CBR files). */ | |
497 /* Query filelen here or not? */ | |
498 fr->accurate = FALSE; /* Fuzzy! */ | |
499 fr->silent_resync = 1; | |
500 *get_frame = want_frame; | |
501 ret = fr->audio_start+fr->mean_framesize*want_frame; | |
502 } | |
503 debug5("fuzzy: want %li of %li, get %li at %li B of %li B", | |
504 (long)want_frame, (long)fr->track_frames, (long)*get_frame, (long)ret, (long)(fr->rdat.filelen-fr->audio_start)); | |
505 return ret; | |
506 } | |
507 | |
508 /* | |
509 find the best frame in index just before the wanted one, seek to there | |
510 then step to just before wanted one with read_frame | |
511 do not care tabout the stuff that was in buffer but not played back | |
512 everything that left the decoder is counted as played | |
513 | |
514 Decide if you want low latency reaction and accurate timing info or stable long-time playback with buffer! | |
515 */ | |
516 | |
517 off_t frame_index_find(mpg123_handle *fr, off_t want_frame, off_t* get_frame) | |
518 { | |
519 /* default is file start if no index position */ | |
520 off_t gopos = 0; | |
521 *get_frame = 0; | |
522 #ifdef FRAME_INDEX | |
523 /* Possibly use VBRI index, too? I'd need an example for this... */ | |
524 if(fr->index.fill) | |
525 { | |
526 /* find in index */ | |
527 size_t fi; | |
528 /* at index fi there is frame step*fi... */ | |
529 fi = want_frame/fr->index.step; | |
530 if(fi >= fr->index.fill) /* If we are beyond the end of frame index...*/ | |
531 { | |
532 /* When fuzzy seek is allowed, we have some limited tolerance for the frames we want to read rather then jump over. */ | |
533 if(fr->p.flags & MPG123_FUZZY && want_frame - (fr->index.fill-1)*fr->index.step > 10) | |
534 { | |
535 gopos = frame_fuzzy_find(fr, want_frame, get_frame); | |
536 if(gopos > fr->audio_start) return gopos; /* Only in that case, we have a useful guess. */ | |
537 /* Else... just continue, fuzzyness didn't help. */ | |
538 } | |
539 /* Use the last available position, slowly advancing from that one. */ | |
540 fi = fr->index.fill - 1; | |
541 } | |
542 /* We have index position, that yields frame and byte offsets. */ | |
543 *get_frame = fi*fr->index.step; | |
544 gopos = fr->index.data[fi]; | |
545 fr->accurate = TRUE; /* When using the frame index, we are accurate. */ | |
546 } | |
547 else | |
548 { | |
549 #endif | |
550 if(fr->p.flags & MPG123_FUZZY) | |
551 return frame_fuzzy_find(fr, want_frame, get_frame); | |
552 /* A bit hackish here... but we need to be fresh when looking for the first header again. */ | |
553 fr->firsthead = 0; | |
554 fr->oldhead = 0; | |
555 #ifdef FRAME_INDEX | |
556 } | |
557 #endif | |
558 debug2("index: 0x%lx for frame %li", (unsigned long)gopos, (long) *get_frame); | |
559 return gopos; | |
560 } | |
561 | |
562 off_t frame_ins2outs(mpg123_handle *fr, off_t ins) | |
563 { | |
564 off_t outs = 0; | |
565 switch(fr->down_sample) | |
566 { | |
567 case 0: | |
568 case 1: | |
569 case 2: outs = ins>>fr->down_sample; break; | |
570 case 3: outs = ntom_ins2outs(fr, ins); break; | |
571 default: error1("Bad down_sample (%i) ... should not be possible!!", fr->down_sample); | |
572 } | |
573 return outs; | |
574 } | |
575 | |
576 off_t frame_outs(mpg123_handle *fr, off_t num) | |
577 { | |
578 off_t outs = 0; | |
579 switch(fr->down_sample) | |
580 { | |
581 case 0: | |
582 case 1: | |
583 case 2: outs = (spf(fr)>>fr->down_sample)*num; break; | |
584 case 3: outs = ntom_frmouts(fr, num); break; | |
585 default: error1("Bad down_sample (%i) ... should not be possible!!", fr->down_sample); | |
586 } | |
587 return outs; | |
588 } | |
589 | |
590 off_t frame_offset(mpg123_handle *fr, off_t outs) | |
591 { | |
592 off_t num = 0; | |
593 switch(fr->down_sample) | |
594 { | |
595 case 0: | |
596 case 1: | |
597 case 2: num = outs/(spf(fr)>>fr->down_sample); break; | |
598 case 3: num = ntom_frameoff(fr, outs); break; | |
599 default: error("Bad down_sample ... should not be possible!!"); | |
600 } | |
601 return num; | |
602 } | |
603 | |
604 #ifdef GAPLESS | |
605 /* input in _input_ samples */ | |
606 void frame_gapless_init(mpg123_handle *fr, off_t b, off_t e) | |
607 { | |
608 fr->begin_s = b; | |
609 fr->end_s = e; | |
610 /* These will get proper values later, from above plus resampling info. */ | |
611 fr->begin_os = 0; | |
612 fr->end_os = 0; | |
613 debug2("frame_gapless_init: from %lu to %lu samples", (long unsigned)fr->begin_s, (long unsigned)fr->end_s); | |
614 } | |
615 | |
616 void frame_gapless_realinit(mpg123_handle *fr) | |
617 { | |
618 fr->begin_os = frame_ins2outs(fr, fr->begin_s); | |
619 fr->end_os = frame_ins2outs(fr, fr->end_s); | |
620 debug2("frame_gapless_realinit: from %lu to %lu samples", (long unsigned)fr->begin_os, (long unsigned)fr->end_os); | |
621 } | |
622 #endif | |
623 | |
624 /* The frame seek... This is not simply the seek to fe*spf(fr) samples in output because we think of _input_ frames here. | |
625 Seek to frame offset 1 may be just seek to 200 samples offset in output since the beginning of first frame is delay/padding. | |
626 Hm, is that right? OK for the padding stuff, but actually, should the decoder delay be better totally hidden or not? | |
627 With gapless, even the whole frame position could be advanced further than requested (since Homey don't play dat). */ | |
628 void frame_set_frameseek(mpg123_handle *fr, off_t fe) | |
629 { | |
630 fr->firstframe = fe; | |
631 #ifdef GAPLESS | |
632 if(fr->p.flags & MPG123_GAPLESS) | |
633 { | |
634 /* Take care of the beginning... */ | |
635 off_t beg_f = frame_offset(fr, fr->begin_os); | |
636 if(fe <= beg_f) | |
637 { | |
638 fr->firstframe = beg_f; | |
639 fr->firstoff = fr->begin_os - frame_outs(fr, beg_f); | |
640 } | |
641 else fr->firstoff = 0; | |
642 /* The end is set once for a track at least, on the frame_set_frameseek called in get_next_frame() */ | |
643 if(fr->end_os > 0) | |
644 { | |
645 fr->lastframe = frame_offset(fr,fr->end_os); | |
646 fr->lastoff = fr->end_os - frame_outs(fr, fr->lastframe); | |
647 } else fr->lastoff = 0; | |
648 } else { fr->firstoff = fr->lastoff = 0; fr->lastframe = -1; } | |
649 #endif | |
650 fr->ignoreframe = fr->lay == 3 ? fr->firstframe-IGNORESHIFT : fr->firstframe; | |
651 #ifdef GAPLESS | |
652 debug5("frame_set_frameseek: begin at %li frames and %li samples, end at %li and %li; ignore from %li", | |
653 (long) fr->firstframe, (long) fr->firstoff, | |
654 (long) fr->lastframe, (long) fr->lastoff, (long) fr->ignoreframe); | |
655 #else | |
656 debug3("frame_set_frameseek: begin at %li frames, end at %li; ignore from %li", | |
657 (long) fr->firstframe, (long) fr->lastframe, (long) fr->ignoreframe); | |
658 #endif | |
659 } | |
660 | |
661 /* Sample accurate seek prepare for decoder. */ | |
662 /* This gets unadjusted output samples and takes resampling into account */ | |
663 void frame_set_seek(mpg123_handle *fr, off_t sp) | |
664 { | |
665 fr->firstframe = frame_offset(fr, sp); | |
666 fr->ignoreframe = fr->lay == 3 ? fr->firstframe-IGNORESHIFT : fr->firstframe; | |
667 #ifdef GAPLESS /* The sample offset is used for non-gapless mode, too! */ | |
668 fr->firstoff = sp - frame_outs(fr, fr->firstframe); | |
669 debug5("frame_set_seek: begin at %li frames and %li samples, end at %li and %li; ignore from %li", | |
670 (long) fr->firstframe, (long) fr->firstoff, | |
671 (long) fr->lastframe, (long) fr->lastoff, (long) fr->ignoreframe); | |
672 #else | |
673 debug3("frame_set_seek: begin at %li frames, end at %li; ignore from %li", | |
674 (long) fr->firstframe, (long) fr->lastframe, (long) fr->ignoreframe); | |
675 #endif | |
676 } | |
677 | |
678 /* to vanish */ | |
679 void frame_outformat(mpg123_handle *fr, int format, int channels, long rate) | |
680 { | |
681 fr->af.encoding = format; | |
682 fr->af.rate = rate; | |
683 fr->af.channels = channels; | |
684 } | |
685 | |
686 /* set synth functions for current frame, optimizations handled by opt_* macros */ | |
687 int set_synth_functions(mpg123_handle *fr) | |
688 { | |
689 int ds = fr->down_sample; | |
690 int p8=0; | |
691 static func_synth funcs[2][4] = { | |
692 { NULL, | |
693 synth_2to1, | |
694 synth_4to1, | |
695 synth_ntom } , | |
696 { NULL, | |
697 synth_2to1_8bit, | |
698 synth_4to1_8bit, | |
699 synth_ntom_8bit } | |
700 }; | |
701 static func_synth_mono funcs_mono[2][2][4] = { | |
702 { { NULL , | |
703 synth_2to1_mono2stereo , | |
704 synth_4to1_mono2stereo , | |
705 synth_ntom_mono2stereo } , | |
706 { NULL , | |
707 synth_2to1_8bit_mono2stereo , | |
708 synth_4to1_8bit_mono2stereo , | |
709 synth_ntom_8bit_mono2stereo } } , | |
710 { { NULL , | |
711 synth_2to1_mono , | |
712 synth_4to1_mono , | |
713 synth_ntom_mono } , | |
714 { NULL , | |
715 synth_2to1_8bit_mono , | |
716 synth_4to1_8bit_mono , | |
717 synth_ntom_8bit_mono } } | |
718 }; | |
719 | |
720 /* possibly non-constand entries filled here */ | |
721 funcs[0][0] = (func_synth) opt_synth_1to1(fr); | |
722 funcs[1][0] = (func_synth) opt_synth_1to1_8bit(fr); | |
723 funcs_mono[0][0][0] = (func_synth_mono) opt_synth_1to1_mono2stereo(fr); | |
724 funcs_mono[0][1][0] = (func_synth_mono) opt_synth_1to1_8bit_mono2stereo(fr); | |
725 funcs_mono[1][0][0] = (func_synth_mono) opt_synth_1to1_mono(fr); | |
726 funcs_mono[1][1][0] = (func_synth_mono) opt_synth_1to1_8bit_mono(fr); | |
727 | |
728 if(fr->af.encoding & MPG123_ENC_8) p8 = 1; | |
729 fr->synth = funcs[p8][ds]; | |
730 fr->synth_mono = funcs_mono[fr->af.channels==2 ? 0 : 1][p8][ds]; | |
731 | |
732 if(p8) | |
733 { | |
734 if(make_conv16to8_table(fr) != 0) | |
735 { | |
736 /* it's a bit more work to get proper error propagation up */ | |
737 return -1; | |
738 } | |
739 } | |
740 return 0; | |
741 } | |
742 | |
743 int attribute_align_arg mpg123_volume_change(mpg123_handle *mh, double change) | |
744 { | |
745 if(mh == NULL) return MPG123_ERR; | |
746 return mpg123_volume(mh, change + (double) mh->p.outscale / MAXOUTBURST); | |
747 } | |
748 | |
749 int attribute_align_arg mpg123_volume(mpg123_handle *mh, double vol) | |
750 { | |
751 if(mh == NULL) return MPG123_ERR; | |
752 if(vol >= 0) mh->p.outscale = (double) MAXOUTBURST * vol; | |
753 do_rva(mh); | |
754 return MPG123_OK; | |
755 } | |
756 | |
757 static int get_rva(mpg123_handle *fr, double *peak, double *gain) | |
758 { | |
759 double p = -1; | |
760 double g = 0; | |
761 int ret = 0; | |
762 if(fr->p.rva) | |
763 { | |
764 int rt = 0; | |
765 /* Should one assume a zero RVA as no RVA? */ | |
766 if(fr->p.rva == 2 && fr->rva.level[1] != -1) rt = 1; | |
767 if(fr->rva.level[rt] != -1) | |
768 { | |
769 p = fr->rva.peak[rt]; | |
770 g = fr->rva.gain[rt]; | |
771 ret = 1; /* Success. */ | |
772 } | |
773 } | |
774 if(peak != NULL) *peak = p; | |
775 if(gain != NULL) *gain = g; | |
776 return ret; | |
777 } | |
778 | |
779 /* adjust the volume, taking both fr->outscale and rva values into account */ | |
780 void do_rva(mpg123_handle *fr) | |
781 { | |
782 double peak = 0; | |
783 double gain = 0; | |
784 scale_t newscale; | |
785 double rvafact = 1; | |
786 if(get_rva(fr, &peak, &gain)) | |
787 { | |
788 if(NOQUIET && fr->p.verbose > 1) fprintf(stderr, "Note: doing RVA with gain %f\n", gain); | |
789 rvafact = pow(10,gain/20); | |
790 } | |
791 | |
792 newscale = fr->p.outscale*rvafact; | |
793 | |
794 /* if peak is unknown (== 0) this check won't hurt */ | |
795 if((peak*newscale) > MAXOUTBURST) | |
796 { | |
797 newscale = (scale_t) ((double) MAXOUTBURST/peak); | |
798 #ifdef FLOATOUT | |
799 warning2("limiting scale value to %f to prevent clipping with indicated peak factor of %f", newscale, peak); | |
800 #else | |
801 warning2("limiting scale value to %li to prevent clipping with indicated peak factor of %f", newscale, peak); | |
802 #endif | |
803 } | |
804 /* first rva setting is forced with fr->lastscale < 0 */ | |
805 if(newscale != fr->lastscale) | |
806 { | |
807 #ifdef FLOATOUT | |
808 debug3("changing scale value from %f to %f (peak estimated to %f)", fr->lastscale != -1 ? fr->lastscale : fr->p.outscale, newscale, (double) (newscale*peak)); | |
809 #else | |
810 debug3("changing scale value from %li to %li (peak estimated to %li)", fr->lastscale != -1 ? fr->lastscale : fr->p.outscale, newscale, (long) (newscale*peak)); | |
811 #endif | |
812 fr->lastscale = newscale; | |
813 opt_make_decode_tables(fr); /* the actual work */ | |
814 } | |
815 } | |
816 | |
817 int attribute_align_arg mpg123_getvolume(mpg123_handle *mh, double *base, double *really, double *rva_db) | |
818 { | |
819 if(mh == NULL) return MPG123_ERR; | |
820 if(base) *base = (double)mh->p.outscale/MAXOUTBURST; | |
821 if(really) *really = (double)mh->lastscale/MAXOUTBURST; | |
822 get_rva(mh, NULL, rva_db); | |
823 return MPG123_OK; | |
824 } | |
825 | |
826 int frame_cpu_opt(mpg123_handle *fr, const char* cpu) | |
827 { | |
828 char* chosen = ""; /* the chosed decoder opt as string */ | |
829 int auto_choose = 0; | |
830 int done = 0; | |
831 if( (cpu == NULL) | |
832 || (cpu[0] == 0) | |
833 || !strcasecmp(cpu, "auto") ) | |
834 auto_choose = 1; | |
835 #ifndef OPT_MULTI | |
836 { | |
837 char **sd = mpg123_decoders(); /* this contains _one_ decoder */ | |
838 if(!auto_choose && strcasecmp(cpu, sd[0])) done = 0; | |
839 else | |
840 { | |
841 chosen = sd[0]; | |
842 done = 1; | |
843 } | |
844 } | |
845 #else | |
846 fr->cpu_opts.type = nodec; | |
847 /* covers any i386+ cpu; they actually differ only in the synth_1to1 function... */ | |
848 #ifdef OPT_X86 | |
849 | |
850 #ifdef OPT_MMXORSSE | |
851 fr->cpu_opts.make_decode_tables = make_decode_tables; | |
852 fr->cpu_opts.init_layer3_gainpow2 = init_layer3_gainpow2; | |
853 fr->cpu_opts.init_layer2_table = init_layer2_table; | |
854 #endif | |
855 #ifdef OPT_3DNOW | |
856 fr->cpu_opts.dct36 = dct36; | |
857 #endif | |
858 #ifdef OPT_3DNOWEXT | |
859 fr->cpu_opts.dct36 = dct36; | |
860 #endif | |
861 | |
862 if(cpu_i586(cpu_flags)) | |
863 { | |
864 debug2("standard flags: 0x%08x\textended flags: 0x%08x", cpu_flags.std, cpu_flags.ext); | |
865 #ifdef OPT_3DNOWEXT | |
866 if( !done && (auto_choose || !strcasecmp(cpu, "3dnowext")) | |
867 && cpu_3dnow(cpu_flags) | |
868 && cpu_3dnowext(cpu_flags) | |
869 && cpu_mmx(cpu_flags) ) | |
870 { | |
871 int go = 1; | |
872 if(fr->p.force_rate) | |
873 { | |
874 #if defined(K6_FALLBACK) || defined(PENTIUM_FALLBACK) | |
875 if(!auto_choose){ if(NOQUIET) error("I refuse to choose 3DNowExt as this will screw up with forced rate!"); } | |
876 else if(VERBOSE) fprintf(stderr, "Note: Not choosing 3DNowExt because flexible rate not supported.\n"); | |
877 | |
878 go = 0; | |
879 #else | |
880 if(NOQUIET) error("You will hear some awful sound because of flexible rate being chosen with 3DNowExt decoder!"); | |
881 #endif | |
882 } | |
883 if(go){ /* temporary hack for flexible rate bug, not going indent this - fix it instead! */ | |
884 chosen = "3DNowExt"; | |
885 fr->cpu_opts.type = dreidnowext; | |
886 fr->cpu_opts.class = mmxsse; | |
887 fr->cpu_opts.dct36 = dct36_3dnowext; | |
888 fr->cpu_opts.synth_1to1 = synth_1to1_3dnowext; | |
889 fr->cpu_opts.dct64 = dct64_mmx; /* only use the 3dnow version in the synth_1to1_sse */ | |
890 fr->cpu_opts.make_decode_tables = make_decode_tables_mmx; | |
891 fr->cpu_opts.init_layer3_gainpow2 = init_layer3_gainpow2_mmx; | |
892 fr->cpu_opts.init_layer2_table = init_layer2_table_mmx; | |
893 fr->cpu_opts.mpl_dct64 = dct64_3dnowext; | |
894 done = 1; | |
895 } | |
896 } | |
897 #endif | |
898 #ifdef OPT_SSE | |
899 if( !done && (auto_choose || !strcasecmp(cpu, "sse")) | |
900 && cpu_sse(cpu_flags) && cpu_mmx(cpu_flags) ) | |
901 { | |
902 int go = 1; | |
903 if(fr->p.force_rate) | |
904 { | |
905 #ifdef PENTIUM_FALLBACK | |
906 if(!auto_choose){ if(NOQUIET) error("I refuse to choose SSE as this will screw up with forced rate!"); } | |
907 else if(VERBOSE) fprintf(stderr, "Note: Not choosing SSE because flexible rate not supported.\n"); | |
908 | |
909 go = 0; | |
910 #else | |
911 if(NOQUIET) error("You will hear some awful sound because of flexible rate being chosen with SSE decoder!"); | |
912 #endif | |
913 } | |
914 if(go){ /* temporary hack for flexible rate bug, not going indent this - fix it instead! */ | |
915 chosen = "SSE"; | |
916 fr->cpu_opts.type = sse; | |
917 fr->cpu_opts.class = mmxsse; | |
918 fr->cpu_opts.synth_1to1 = synth_1to1_sse; | |
919 fr->cpu_opts.dct64 = dct64_mmx; /* only use the sse version in the synth_1to1_sse */ | |
920 fr->cpu_opts.make_decode_tables = make_decode_tables_mmx; | |
921 fr->cpu_opts.init_layer3_gainpow2 = init_layer3_gainpow2_mmx; | |
922 fr->cpu_opts.init_layer2_table = init_layer2_table_mmx; | |
923 fr->cpu_opts.mpl_dct64 = dct64_sse; | |
924 done = 1; | |
925 } | |
926 } | |
927 #endif | |
928 #ifdef OPT_3DNOW | |
929 fr->cpu_opts.dct36 = dct36; | |
930 /* TODO: make autodetection for _all_ x86 optimizations (maybe just for i586+ and keep separate 486 build?) */ | |
931 /* check cpuflags bit 31 (3DNow!) and 23 (MMX) */ | |
932 if( !done && (auto_choose || !strcasecmp(cpu, "3dnow")) | |
933 && cpu_3dnow(cpu_flags) && cpu_mmx(cpu_flags) ) | |
934 { | |
935 chosen = "3DNow"; | |
936 fr->cpu_opts.type = dreidnow; | |
937 fr->cpu_opts.dct36 = dct36_3dnow; /* 3DNow! optimized dct36() */ | |
938 fr->cpu_opts.synth_1to1 = synth_1to1_3dnow; | |
939 fr->cpu_opts.dct64 = dct64_i386; /* use the 3dnow one? */ | |
940 done = 1; | |
941 } | |
942 #endif | |
943 #ifdef OPT_MMX | |
944 if( !done && (auto_choose || !strcasecmp(cpu, "mmx")) | |
945 && cpu_mmx(cpu_flags) ) | |
946 { | |
947 int go = 1; | |
948 if(fr->p.force_rate) | |
949 { | |
950 #ifdef PENTIUM_FALLBACK | |
951 if(!auto_choose){ if(NOQUIET) error("I refuse to choose MMX as this will screw up with forced rate!"); } | |
952 else if(VERBOSE) fprintf(stderr, "Note: Not choosing MMX because flexible rate not supported.\n"); | |
953 | |
954 go = 0; | |
955 #else | |
956 error("You will hear some awful sound because of flexible rate being chosen with MMX decoder!"); | |
957 #endif | |
958 } | |
959 if(go){ /* temporary hack for flexible rate bug, not going indent this - fix it instead! */ | |
960 chosen = "MMX"; | |
961 fr->cpu_opts.type = mmx; | |
962 fr->cpu_opts.class = mmxsse; | |
963 fr->cpu_opts.synth_1to1 = synth_1to1_mmx; | |
964 fr->cpu_opts.dct64 = dct64_mmx; | |
965 fr->cpu_opts.make_decode_tables = make_decode_tables_mmx; | |
966 fr->cpu_opts.init_layer3_gainpow2 = init_layer3_gainpow2_mmx; | |
967 fr->cpu_opts.init_layer2_table = init_layer2_table_mmx; | |
968 done = 1; | |
969 } | |
970 } | |
971 #endif | |
972 #ifdef OPT_I586 | |
973 if(!done && (auto_choose || !strcasecmp(cpu, "i586"))) | |
974 { | |
975 chosen = "i586/pentium"; | |
976 fr->cpu_opts.type = ifuenf; | |
977 fr->cpu_opts.synth_1to1 = synth_1to1_i586; | |
978 fr->cpu_opts.synth_1to1_i586_asm = synth_1to1_i586_asm; | |
979 fr->cpu_opts.dct64 = dct64_i386; | |
980 done = 1; | |
981 } | |
982 #endif | |
983 #ifdef OPT_I586_DITHER | |
984 if(!done && (auto_choose || !strcasecmp(cpu, "i586_dither"))) | |
985 { | |
986 chosen = "dithered i586/pentium"; | |
987 fr->cpu_opts.type = ifuenf_dither; | |
988 fr->cpu_opts.synth_1to1 = synth_1to1_i586; | |
989 fr->cpu_opts.dct64 = dct64_i386; | |
990 fr->cpu_opts.synth_1to1_i586_asm = synth_1to1_i586_asm_dither; | |
991 done = 1; | |
992 } | |
993 #endif | |
994 } | |
995 #ifdef OPT_I486 /* that won't cooperate nicely in multi opt mode - forcing i486 in layer3.c */ | |
996 if(!done && (auto_choose || !strcasecmp(cpu, "i486"))) | |
997 { | |
998 chosen = "i486"; | |
999 fr->cpu_opts.type = ivier; | |
1000 fr->cpu_opts.synth_1to1 = synth_1to1_i386; /* i486 function is special */ | |
1001 fr->cpu_opts.dct64 = dct64_i386; | |
1002 done = 1; | |
1003 } | |
1004 #endif | |
1005 #ifdef OPT_I386 | |
1006 if(!done && (auto_choose || !strcasecmp(cpu, "i386"))) | |
1007 { | |
1008 chosen = "i386"; | |
1009 fr->cpu_opts.type = idrei; | |
1010 fr->cpu_opts.synth_1to1 = synth_1to1_i386; | |
1011 fr->cpu_opts.dct64 = dct64_i386; | |
1012 done = 1; | |
1013 } | |
1014 #endif | |
1015 | |
1016 if(done) /* set common x86 functions */ | |
1017 { | |
1018 fr->cpu_opts.synth_1to1_mono = synth_1to1_mono_i386; | |
1019 fr->cpu_opts.synth_1to1_mono2stereo = synth_1to1_mono2stereo_i386; | |
1020 fr->cpu_opts.synth_1to1_8bit = synth_1to1_8bit_i386; | |
1021 fr->cpu_opts.synth_1to1_8bit_mono = synth_1to1_8bit_mono_i386; | |
1022 fr->cpu_opts.synth_1to1_8bit_mono2stereo = synth_1to1_8bit_mono2stereo_i386; | |
1023 } | |
1024 #endif /* OPT_X86 */ | |
1025 | |
1026 #ifdef OPT_ALTIVEC | |
1027 if(!done && (auto_choose || !strcasecmp(cpu, "altivec"))) | |
1028 { | |
1029 chosen = "AltiVec"; | |
1030 fr->cpu_opts.type = altivec; | |
1031 fr->cpu_opts.dct64 = dct64_altivec; | |
1032 fr->cpu_opts.synth_1to1 = synth_1to1_altivec; | |
1033 fr->cpu_opts.synth_1to1_mono = synth_1to1_mono_altivec; | |
1034 fr->cpu_opts.synth_1to1_mono2stereo = synth_1to1_mono2stereo_altivec; | |
1035 fr->cpu_opts.synth_1to1_8bit = synth_1to1_8bit_altivec; | |
1036 fr->cpu_opts.synth_1to1_8bit_mono = synth_1to1_8bit_mono_altivec; | |
1037 fr->cpu_opts.synth_1to1_8bit_mono2stereo = synth_1to1_8bit_mono2stereo_altivec; | |
1038 done = 1; | |
1039 } | |
1040 #endif | |
1041 | |
1042 #ifdef OPT_GENERIC | |
1043 if(!done && (auto_choose || !strcasecmp(cpu, "generic"))) | |
1044 { | |
1045 chosen = "generic"; | |
1046 fr->cpu_opts.type = generic; | |
1047 fr->cpu_opts.dct64 = dct64; | |
1048 fr->cpu_opts.synth_1to1 = synth_1to1; | |
1049 fr->cpu_opts.synth_1to1_mono = synth_1to1_mono; | |
1050 fr->cpu_opts.synth_1to1_mono2stereo = synth_1to1_mono2stereo; | |
1051 fr->cpu_opts.synth_1to1_8bit = synth_1to1_8bit; | |
1052 fr->cpu_opts.synth_1to1_8bit_mono = synth_1to1_8bit_mono; | |
1053 fr->cpu_opts.synth_1to1_8bit_mono2stereo = synth_1to1_8bit_mono2stereo; | |
1054 done = 1; | |
1055 } | |
1056 #endif | |
1057 #endif | |
1058 if(done) | |
1059 { | |
1060 if(VERBOSE) fprintf(stderr, "Decoder: %s\n", chosen); | |
1061 return 1; | |
1062 } | |
1063 else | |
1064 { | |
1065 if(NOQUIET) error("Could not set optimization!"); | |
1066 return 0; | |
1067 } | |
1068 } | |
1069 | |
1070 enum optdec dectype(const char* decoder) | |
1071 { | |
1072 if(decoder == NULL) return autodec; | |
1073 if(!strcasecmp(decoder, "3dnowext")) return dreidnowext; | |
1074 if(!strcasecmp(decoder, "3dnow")) return dreidnow; | |
1075 if(!strcasecmp(decoder, "sse")) return sse; | |
1076 if(!strcasecmp(decoder, "mmx")) return mmx; | |
1077 if(!strcasecmp(decoder, "generic")) return generic; | |
1078 if(!strcasecmp(decoder, "altivec")) return altivec; | |
1079 if(!strcasecmp(decoder, "i386")) return idrei; | |
1080 if(!strcasecmp(decoder, "i486")) return ivier; | |
1081 if(!strcasecmp(decoder, "i586")) return ifuenf; | |
1082 if(!strcasecmp(decoder, "i586_dither")) return ifuenf_dither; | |
1083 return nodec; | |
1084 } | |
1085 |