2 optimize: get a grip on the different optimizations
4 copyright 2006-9 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, inspired by 3DNow stuff in mpg123.[hc]
8 Currently, this file contains the struct and function to choose an optimization variant and works only when OPT_MULTI is in effect.
11 #include "mpg123lib_intern.h" /* includes optimize.h */
14 /* Must match the enum dectype! */
17 It SUCKS having to define these names that way, but compile-time intialization of string arrays is a bitch.
18 GCC doesn't see constant stuff when it's wiggling in front of it!
19 Anyhow: Have a script for that:
20 names="generic generic_dither i386 i486 i586 i586_dither MMX 3DNow 3DNowExt AltiVec SSE x86-64"
21 for i in $names; do echo "##define dn_${i/-/_} \"$i\""; done
22 echo -n "static const char* decname[] =
26 for i in $names; do echo -n ", dn_${i/-/_}"; done
31 #define dn_generic "generic"
32 #define dn_generic_dither "generic_dither"
33 #define dn_i386 "i386"
34 #define dn_i486 "i486"
35 #define dn_i586 "i586"
36 #define dn_i586_dither "i586_dither"
38 #define dn_3DNow "3DNow"
39 #define dn_3DNowExt "3DNowExt"
40 #define dn_AltiVec "AltiVec"
42 #define dn_x86_64 "x86-64"
44 static const char* decname
[] =
47 , dn_generic
, dn_generic_dither
, dn_i386
, dn_i486
, dn_i586
, dn_i586_dither
, dn_MMX
, dn_3DNow
, dn_3DNowExt
, dn_AltiVec
, dn_SSE
, dn_x86_64
, dn_ARM
51 #if (defined OPT_X86) && (defined OPT_MULTI)
52 #include "getcpuflags.h"
53 struct cpuflags cpu_flags
;
55 /* Faking stuff for non-multi builds. The same code for synth function choice is used.
56 Just no runtime dependency of result... */
61 #define cpu_3dnow(s) 1
62 #define cpu_3dnowext(s) 1
68 /* Ugly macros to build conditional synth function array values. */
71 #define IF8(synth) synth,
77 #define IFREAL(synth) synth,
83 #define IF32(synth) synth
89 # define OUT_SYNTHS(synth_16, synth_8, synth_real, synth_32) { synth_16, IF8(synth_8) IFREAL(synth_real) IF32(synth_32) }
91 # define OUT_SYNTHS(synth_16, synth_8, synth_real, synth_32) { IF8(synth_8) IFREAL(synth_real) IF32(synth_32) }
94 /* The call of left and right plain synth, wrapped.
95 This may be replaced by a direct stereo optimized synth. */
96 int synth_stereo_wrap(real
*bandPtr_l
, real
*bandPtr_r
, mpg123_handle
*fr
)
99 clip
= (fr
->synth
)(bandPtr_l
, 0, fr
, 0);
100 clip
+= (fr
->synth
)(bandPtr_r
, 1, fr
, 1);
104 const struct synth_s synth_base
=
107 OUT_SYNTHS(synth_1to1
, synth_1to1_8bit
, synth_1to1_real
, synth_1to1_s32
)
108 # ifndef NO_DOWNSAMPLE
109 ,OUT_SYNTHS(synth_2to1
, synth_2to1_8bit
, synth_2to1_real
, synth_2to1_s32
)
110 ,OUT_SYNTHS(synth_4to1
, synth_4to1_8bit
, synth_4to1_real
, synth_4to1_s32
)
113 ,OUT_SYNTHS(synth_ntom
, synth_ntom_8bit
, synth_ntom_real
, synth_ntom_s32
)
116 { /* stereo, by default only wrappers over plain synth */
117 OUT_SYNTHS(synth_stereo_wrap
, synth_stereo_wrap
, synth_stereo_wrap
, synth_stereo_wrap
)
118 # ifndef NO_DOWNSAMPLE
119 ,OUT_SYNTHS(synth_stereo_wrap
, synth_stereo_wrap
, synth_stereo_wrap
, synth_stereo_wrap
)
120 ,OUT_SYNTHS(synth_stereo_wrap
, synth_stereo_wrap
, synth_stereo_wrap
, synth_stereo_wrap
)
123 ,OUT_SYNTHS(synth_stereo_wrap
, synth_stereo_wrap
, synth_stereo_wrap
, synth_stereo_wrap
)
127 OUT_SYNTHS(synth_1to1_mono2stereo
, synth_1to1_8bit_mono2stereo
, synth_1to1_real_mono2stereo
, synth_1to1_s32_mono2stereo
)
128 # ifndef NO_DOWNSAMPLE
129 ,OUT_SYNTHS(synth_2to1_mono2stereo
, synth_2to1_8bit_mono2stereo
, synth_2to1_real_mono2stereo
, synth_2to1_s32_mono2stereo
)
130 ,OUT_SYNTHS(synth_4to1_mono2stereo
, synth_4to1_8bit_mono2stereo
, synth_4to1_real_mono2stereo
, synth_4to1_s32_mono2stereo
)
133 ,OUT_SYNTHS(synth_ntom_mono2stereo
, synth_ntom_8bit_mono2stereo
, synth_ntom_real_mono2stereo
, synth_ntom_s32_mono2stereo
)
137 OUT_SYNTHS(synth_1to1_mono
, synth_1to1_8bit_mono
, synth_1to1_real_mono
, synth_1to1_s32_mono
)
138 # ifndef NO_DOWNSAMPLE
139 ,OUT_SYNTHS(synth_2to1_mono
, synth_2to1_8bit_mono
, synth_2to1_real_mono
, synth_2to1_s32_mono
)
140 ,OUT_SYNTHS(synth_4to1_mono
, synth_4to1_8bit_mono
, synth_4to1_real_mono
, synth_4to1_s32_mono
)
143 ,OUT_SYNTHS(synth_ntom_mono
, synth_ntom_8bit_mono
, synth_ntom_real_mono
, synth_ntom_s32_mono
)
149 /* More plain synths for i386 */
150 const func_synth plain_i386
[r_limit
][f_limit
] =
152 OUT_SYNTHS(synth_1to1_i386
, synth_1to1_8bit_i386
, synth_1to1_real_i386
, synth_1to1_s32_i386
)
153 # ifndef NO_DOWNSAMPLE
154 ,OUT_SYNTHS(synth_2to1_i386
, synth_2to1_8bit_i386
, synth_2to1_real_i386
, synth_2to1_s32_i386
)
155 ,OUT_SYNTHS(synth_4to1_i386
, synth_4to1_8bit_i386
, synth_4to1_real_i386
, synth_4to1_s32_i386
)
158 ,OUT_SYNTHS(synth_ntom
, synth_ntom_8bit
, synth_ntom_real
, synth_ntom_s32
)
164 enum optdec
defdec(void){ return defopt
; }
166 enum optcla
decclass(const enum optdec type
)
168 return (type
== mmx
|| type
== sse
|| type
== dreidnowext
|| type
== x86_64
) ? mmxsse
: normal
;
172 static int find_synth(func_synth synth
, const func_synth synths
[r_limit
][f_limit
])
174 enum synth_resample ri
;
175 enum synth_format fi
;
176 for(ri
=0; ri
<r_limit
; ++ri
)
177 for(fi
=0; fi
<f_limit
; ++fi
)
178 if(synth
== synths
[ri
][fi
])
184 /* Determine what kind of decoder is actually active
185 This depends on runtime choices which may cause fallback to i386 or generic code. */
186 static int find_dectype(mpg123_handle
*fr
)
188 enum optdec type
= nodec
;
189 /* Direct and indirect usage, 1to1 stereo decoding.
190 Concentrating on the plain stereo synth should be fine, mono stuff is derived. */
191 func_synth basic_synth
= fr
->synth
;
194 if(basic_synth
== synth_1to1_8bit_wrap
)
195 basic_synth
= fr
->synths
.plain
[r_1to1
][f_16
]; /* That is what's really below the surface. */
199 if(FALSE
) ; /* Just to initialize the else if ladder. */
202 else if(basic_synth
== synth_1to1_3dnowext
) type
= dreidnowext
;
205 else if(basic_synth
== synth_1to1_sse
) type
= sse
;
208 else if(basic_synth
== synth_1to1_3dnow
) type
= dreidnow
;
211 else if(basic_synth
== synth_1to1_mmx
) type
= mmx
;
213 #ifdef OPT_I586_DITHER
214 else if(basic_synth
== synth_1to1_i586_dither
) type
= ifuenf_dither
;
217 else if(basic_synth
== synth_1to1_i586
) type
= ifuenf
;
220 else if(basic_synth
== synth_1to1_altivec
) type
= altivec
;
223 else if(basic_synth
== synth_1to1_x86_64
) type
= x86_64
;
226 else if(basic_synth
== synth_1to1_arm
) type
= arm
;
228 #ifdef OPT_GENERIC_DITHER
229 else if(basic_synth
== synth_1to1_dither
) type
= generic_dither
;
231 #ifdef OPT_DITHER /* either i586 or generic! */
232 #ifndef NO_DOWNSAMPLE
235 basic_synth
== synth_2to1_dither
236 || basic_synth
== synth_4to1_dither
237 ) type
= generic_dither
;
244 else if(basic_synth
== synth_1to1_real_sse
) type
= sse
;
247 else if(basic_synth
== synth_1to1_real_x86_64
) type
= x86_64
;
250 else if(basic_synth
== synth_1to1_real_altivec
) type
= altivec
;
257 else if(basic_synth
== synth_1to1_s32_sse
) type
= sse
;
260 else if(basic_synth
== synth_1to1_s32_x86_64
) type
= x86_64
;
263 else if(basic_synth
== synth_1to1_s32_altivec
) type
= altivec
;
268 else if(find_synth(basic_synth
, plain_i386
))
272 else if(find_synth(basic_synth
, synth_base
.plain
))
278 /* i486 is special ... the specific code is in use for 16bit 1to1 stereo
279 otherwise we have i386 active... but still, the distinction doesn't matter*/
285 fr
->cpu_opts
.type
= type
;
286 fr
->cpu_opts
.class = decclass(type
);
288 debug3("determined active decoder type %i (%s) of class %i", type
, decname
[type
], fr
->cpu_opts
.class);
293 if(NOQUIET
) error("Unable to determine active decoder type -- this is SERIOUS b0rkage!");
295 fr
->err
= MPG123_BAD_DECODER_SETUP
;
300 /* set synth functions for current frame, optimizations handled by opt_* macros */
301 int set_synth_functions(mpg123_handle
*fr
)
303 enum synth_resample resample
= r_none
;
304 enum synth_format basic_format
= f_none
; /* Default is always 16bit, or whatever. */
306 /* Select the basic output format, different from 16bit: 8bit, real. */
309 else if(fr
->af
.encoding
& MPG123_ENC_16
)
313 else if(fr
->af
.encoding
& MPG123_ENC_8
)
317 else if(fr
->af
.encoding
& MPG123_ENC_FLOAT
)
318 basic_format
= f_real
;
321 else if(fr
->af
.encoding
& MPG123_ENC_32
)
325 /* Make sure the chosen format is compiled into this lib. */
326 if(basic_format
== f_none
)
328 if(NOQUIET
) error("set_synth_functions: This output format is disabled in this build!");
333 /* Be explicit about downsampling variant. */
334 switch(fr
->down_sample
)
336 case 0: resample
= r_1to1
; break;
337 #ifndef NO_DOWNSAMPLE
338 case 1: resample
= r_2to1
; break;
339 case 2: resample
= r_4to1
; break;
342 case 3: resample
= r_ntom
; break;
346 if(resample
== r_none
)
348 if(NOQUIET
) error("set_synth_functions: This resampling mode is not supported in this build!");
353 debug2("selecting synth: resample=%i format=%i", resample
, basic_format
);
354 /* Finally selecting the synth functions for stereo / mono. */
355 fr
->synth
= fr
->synths
.plain
[resample
][basic_format
];
356 fr
->synth_stereo
= fr
->synths
.stereo
[resample
][basic_format
];
357 fr
->synth_mono
= fr
->af
.channels
==2
358 ? fr
->synths
.mono2stereo
[resample
][basic_format
] /* Mono MPEG file decoded to stereo. */
359 : fr
->synths
.mono
[resample
][basic_format
]; /* Mono MPEG file decoded to mono. */
361 if(find_dectype(fr
) != MPG123_OK
) /* Actually determine the currently active decoder breed. */
363 fr
->err
= MPG123_BAD_DECODER_SETUP
;
367 if(frame_buffers(fr
) != 0)
369 fr
->err
= MPG123_NO_BUFFERS
;
370 if(NOQUIET
) error("Failed to set up decoder buffers!");
376 if(basic_format
== f_8
)
378 if(make_conv16to8_table(fr
) != 0)
380 if(NOQUIET
) error("Failed to set up conv16to8 table!");
381 /* it's a bit more work to get proper error propagation up */
388 /* Special treatment for MMX, SSE and 3DNowExt stuff.
389 The real-decoding SSE for x86-64 uses normal tables! */
390 if(fr
->cpu_opts
.class == mmxsse
392 && basic_format
!= f_real
395 && basic_format
!= f_32
397 # ifdef ACCURATE_ROUNDING
398 && fr
->cpu_opts
.type
!= sse
399 && fr
->cpu_opts
.type
!= x86_64
404 init_layer3_stuff(fr
, init_layer3_gainpow2_mmx
);
407 init_layer12_stuff(fr
, init_layer12_table_mmx
);
409 fr
->make_decode_tables
= make_decode_tables_mmx
;
415 init_layer3_stuff(fr
, init_layer3_gainpow2
);
418 init_layer12_stuff(fr
, init_layer12_table
);
420 fr
->make_decode_tables
= make_decode_tables
;
423 /* We allocated the table buffers just now, so (re)create the tables. */
424 fr
->make_decode_tables(fr
);
429 int frame_cpu_opt(mpg123_handle
*fr
, const char* cpu
)
431 const char* chosen
= ""; /* the chosen decoder opt as string */
432 enum optdec want_dec
= nodec
;
436 int dithered
= FALSE
; /* If some dithered decoder is chosen. */
439 want_dec
= dectype(cpu
);
440 auto_choose
= want_dec
== autodec
;
441 /* Fill whole array of synth functions with generic code first. */
442 fr
->synths
= synth_base
;
446 if(!auto_choose
&& want_dec
!= defopt
)
448 if(NOQUIET
) error2("you wanted decoder type %i, I only have %i", want_dec
, defopt
);
450 auto_choose
= TRUE
; /* There will be only one choice anyway. */
454 fr
->cpu_opts
.type
= nodec
;
455 /* covers any i386+ cpu; they actually differ only in the synth_1to1 function, mostly... */
460 #if (defined OPT_3DNOW || defined OPT_3DNOWEXT)
461 fr
->cpu_opts
.the_dct36
= dct36
;
466 if(cpu_i586(cpu_flags
))
469 debug2("standard flags: 0x%08x\textended flags: 0x%08x", cpu_flags
.std
, cpu_flags
.ext
);
472 if( !done
&& (auto_choose
|| want_dec
== sse
)
473 && cpu_sse(cpu_flags
) && cpu_mmx(cpu_flags
) )
476 fr
->cpu_opts
.type
= sse
;
478 fr
->synths
.plain
[r_1to1
][f_16
] = synth_1to1_sse
;
479 # ifdef ACCURATE_ROUNDING
480 fr
->synths
.stereo
[r_1to1
][f_16
] = synth_1to1_stereo_sse
;
484 fr
->synths
.plain
[r_1to1
][f_real
] = synth_1to1_real_sse
;
485 fr
->synths
.stereo
[r_1to1
][f_real
] = synth_1to1_real_stereo_sse
;
488 fr
->synths
.plain
[r_1to1
][f_32
] = synth_1to1_s32_sse
;
489 fr
->synths
.stereo
[r_1to1
][f_32
] = synth_1to1_s32_stereo_sse
;
495 if( !done
&& (auto_choose
|| want_dec
== dreidnowext
)
496 && cpu_3dnow(cpu_flags
)
497 && cpu_3dnowext(cpu_flags
)
498 && cpu_mmx(cpu_flags
) )
501 fr
->cpu_opts
.type
= dreidnowext
;
504 fr
->cpu_opts
.the_dct36
= dct36_3dnowext
;
508 fr
->synths
.plain
[r_1to1
][f_16
] = synth_1to1_3dnowext
;
514 if( !done
&& (auto_choose
|| want_dec
== dreidnow
)
515 && cpu_3dnow(cpu_flags
) && cpu_mmx(cpu_flags
) )
518 fr
->cpu_opts
.type
= dreidnow
;
521 fr
->cpu_opts
.the_dct36
= dct36_3dnow
;
525 fr
->synths
.plain
[r_1to1
][f_16
] = synth_1to1_3dnow
;
531 if( !done
&& (auto_choose
|| want_dec
== mmx
)
532 && cpu_mmx(cpu_flags
) )
535 fr
->cpu_opts
.type
= mmx
;
537 fr
->synths
.plain
[r_1to1
][f_16
] = synth_1to1_mmx
;
543 if(!done
&& (auto_choose
|| want_dec
== ifuenf
))
545 chosen
= "i586/pentium";
546 fr
->cpu_opts
.type
= ifuenf
;
548 fr
->synths
.plain
[r_1to1
][f_16
] = synth_1to1_i586
;
553 #ifdef OPT_I586_DITHER
554 if(!done
&& (auto_choose
|| want_dec
== ifuenf_dither
))
556 chosen
= "dithered i586/pentium";
557 fr
->cpu_opts
.type
= ifuenf_dither
;
560 fr
->synths
.plain
[r_1to1
][f_16
] = synth_1to1_i586_dither
;
561 # ifndef NO_DOWNSAMPLE
562 fr
->synths
.plain
[r_2to1
][f_16
] = synth_2to1_dither
;
563 fr
->synths
.plain
[r_4to1
][f_16
] = synth_4to1_dither
;
571 /* That won't cooperate in multi opt mode - forcing i486 in layer3.c
572 But still... here it is... maybe for real use in future. */
573 if(!done
&& (auto_choose
|| want_dec
== ivier
))
576 fr
->cpu_opts
.type
= ivier
;
581 if(!done
&& (auto_choose
|| want_dec
== idrei
))
584 fr
->cpu_opts
.type
= idrei
;
592 We have chosen some x86 decoder... fillup some i386 stuff.
593 There is an open question about using dithered synth_1to1 for 8bit wrappers.
594 For quality it won't make sense, but wrapped i586_dither wrapped may still be faster...
596 enum synth_resample ri
;
597 enum synth_format fi
;
599 # ifndef NO_16BIT /* possibility to use a 16->8 wrapper... */
600 if(fr
->synths
.plain
[r_1to1
][f_16
] != synth_base
.plain
[r_1to1
][f_16
])
602 fr
->synths
.plain
[r_1to1
][f_8
] = synth_1to1_8bit_wrap
;
603 fr
->synths
.mono
[r_1to1
][f_8
] = synth_1to1_8bit_wrap_mono
;
604 fr
->synths
.mono2stereo
[r_1to1
][f_8
] = synth_1to1_8bit_wrap_mono2stereo
;
608 for(ri
=0; ri
<r_limit
; ++ri
)
609 for(fi
=0; fi
<f_limit
; ++fi
)
611 if(fr
->synths
.plain
[ri
][fi
] == synth_base
.plain
[ri
][fi
])
612 fr
->synths
.plain
[ri
][fi
] = plain_i386
[ri
][fi
];
619 if(!done
&& (auto_choose
|| want_dec
== x86_64
))
621 chosen
= "x86-64 (SSE)";
622 fr
->cpu_opts
.type
= x86_64
;
624 fr
->synths
.plain
[r_1to1
][f_16
] = synth_1to1_x86_64
;
625 fr
->synths
.stereo
[r_1to1
][f_16
] = synth_1to1_stereo_x86_64
;
628 fr
->synths
.plain
[r_1to1
][f_real
] = synth_1to1_real_x86_64
;
629 fr
->synths
.stereo
[r_1to1
][f_real
] = synth_1to1_real_stereo_x86_64
;
632 fr
->synths
.plain
[r_1to1
][f_32
] = synth_1to1_s32_x86_64
;
633 fr
->synths
.stereo
[r_1to1
][f_32
] = synth_1to1_s32_stereo_x86_64
;
639 #ifdef OPT_GENERIC_DITHER
640 if(!done
&& (auto_choose
|| want_dec
== generic_dither
))
642 chosen
= "dithered generic";
643 fr
->cpu_opts
.type
= generic_dither
;
646 fr
->synths
.plain
[r_1to1
][f_16
] = synth_1to1_dither
;
647 # ifndef NO_DOWNSAMPLE
648 fr
->synths
.plain
[r_2to1
][f_16
] = synth_2to1_dither
;
649 fr
->synths
.plain
[r_4to1
][f_16
] = synth_4to1_dither
;
657 if(!done
&& (auto_choose
|| want_dec
== altivec
))
660 fr
->cpu_opts
.type
= altivec
;
662 fr
->synths
.plain
[r_1to1
][f_16
] = synth_1to1_altivec
;
663 fr
->synths
.stereo
[r_1to1
][f_16
] = synth_1to1_stereo_altivec
;
666 fr
->synths
.plain
[r_1to1
][f_real
] = synth_1to1_real_altivec
;
667 fr
->synths
.stereo
[r_1to1
][f_real
] = synth_1to1_real_stereo_altivec
;
670 fr
->synths
.plain
[r_1to1
][f_32
] = synth_1to1_s32_altivec
;
671 fr
->synths
.stereo
[r_1to1
][f_32
] = synth_1to1_s32_stereo_altivec
;
678 if(!done
&& (auto_choose
|| want_dec
== arm
))
681 fr
->cpu_opts
.type
= arm
;
683 fr
->synths
.plain
[r_1to1
][f_16
] = synth_1to1_arm
;
690 if(!done
&& (auto_choose
|| want_dec
== generic
))
693 fr
->cpu_opts
.type
= generic
;
698 fr
->cpu_opts
.class = decclass(fr
->cpu_opts
.type
);
701 # ifndef NO_16BIT /* possibility to use a 16->8 wrapper... */
702 /* Last chance to use some optimized routine via generic wrappers (for 8bit). */
703 if( fr
->cpu_opts
.type
!= ifuenf_dither
704 && fr
->cpu_opts
.type
!= generic_dither
705 && fr
->synths
.plain
[r_1to1
][f_16
] != synth_base
.plain
[r_1to1
][f_16
] )
707 fr
->synths
.plain
[r_1to1
][f_8
] = synth_1to1_8bit_wrap
;
708 fr
->synths
.mono
[r_1to1
][f_8
] = synth_1to1_8bit_wrap_mono
;
709 fr
->synths
.mono2stereo
[r_1to1
][f_8
] = synth_1to1_8bit_wrap_mono2stereo
;
717 /* run-time dither noise table generation */
718 if(!frame_dither_init(fr
))
720 if(NOQUIET
) error("Dither noise setup failed!");
728 if(VERBOSE
) fprintf(stderr
, "Decoder: %s\n", chosen
);
733 if(NOQUIET
) error("Could not set optimization!");
738 enum optdec
dectype(const char* decoder
)
741 if( (decoder
== NULL
)
742 || (decoder
[0] == 0) )
745 for(dt
=autodec
; dt
<nodec
; ++dt
)
746 if(!strcasecmp(decoder
, decname
[dt
])) return dt
;
748 return nodec
; /* If we found nothing... */
753 /* same number of entries as full list, but empty at beginning */
754 static const char *mpg123_supported_decoder_list
[] =
771 #ifdef OPT_I586_DITHER
789 #ifdef OPT_GENERIC_FLOAT
795 # ifdef OPT_GENERIC_DITHER
802 static const char *mpg123_decoder_list
[] =
819 #ifdef OPT_I586_DITHER
840 #ifdef OPT_GENERIC_DITHER
846 void check_decoders(void )
849 /* In non-multi mode, only the full list (one entry) is used. */
852 const char **d
= mpg123_supported_decoder_list
;
854 getcpuflags(&cpu_flags
);
855 if(cpu_i586(cpu_flags
))
857 /* not yet: if(cpu_sse2(cpu_flags)) printf(" SSE2");
858 if(cpu_sse3(cpu_flags)) printf(" SSE3"); */
860 if(cpu_sse(cpu_flags
)) *(d
++) = decname
[sse
];
863 if(cpu_3dnowext(cpu_flags
)) *(d
++) = decname
[dreidnowext
];
866 if(cpu_3dnow(cpu_flags
)) *(d
++) = decname
[dreidnow
];
869 if(cpu_mmx(cpu_flags
)) *(d
++) = decname
[mmx
];
872 *(d
++) = decname
[ifuenf
];
874 #ifdef OPT_I586_DITHER
875 *(d
++) = decname
[ifuenf_dither
];
879 /* just assume that the i486 built is run on a i486 cpu... */
881 *(d
++) = decname
[ivier
];
884 *(d
++) = decname
[altivec
];
886 /* every supported x86 can do i386, any cpu can do generic */
888 *(d
++) = decname
[idrei
];
891 *(d
++) = decname
[x86_64
];
894 *(d
++) = decname
[arm
];
897 *(d
++) = decname
[generic
];
899 #ifdef OPT_GENERIC_DITHER
900 *(d
++) = decname
[generic_dither
];
902 #endif /* ndef OPT_MULTI */
905 const char* attribute_align_arg
mpg123_current_decoder(mpg123_handle
*mh
)
907 if(mh
== NULL
) return NULL
;
909 return decname
[mh
->cpu_opts
.type
];
912 const char attribute_align_arg
**mpg123_decoders(void){ return mpg123_decoder_list
; }
913 const char attribute_align_arg
**mpg123_supported_decoders(void)
916 return mpg123_supported_decoder_list
;
918 return mpg123_decoder_list
;