1/*	Copyright: 	© Copyright 2005-2010 Apple Computer, Inc. All rights reserved.
2
3 Disclaimer:	IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
4 ("Apple") in consideration of your agreement to the following terms, and your
5 use, installation, modification or redistribution of this Apple software
6 constitutes acceptance of these terms.  If you do not agree with these terms,
7 please do not use, install, modify or redistribute this Apple software.
8
9 In consideration of your agreement to abide by the following terms, and subject
10 to these terms, Apple grants you a personal, non-exclusive license, under Apple’s
11 copyrights in this original Apple software (the "Apple Software"), to use,
12 reproduce, modify and redistribute the Apple Software, with or without
13 modifications, in source and/or binary forms; provided that if you redistribute
14 the Apple Software in its entirety and without modifications, you must retain
15 this notice and the following text and disclaimers in all such redistributions of
16 the Apple Software.  Neither the name, trademarks, service marks or logos of
17 Apple Computer, Inc. may be used to endorse or promote products derived from the
18 Apple Software without specific prior written permission from Apple.  Except as
19 expressly stated in this notice, no other rights or licenses, express or implied,
20 are granted by Apple herein, including but not limited to any patent rights that
21 may be infringed by your derivative works or by other works in which the Apple
22 Software may be incorporated.
23
24 The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
25 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
26 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
28 COMBINATION WITH YOUR PRODUCTS.
29
30 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
31 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
32 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
34 OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
35 (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
36 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38/*=============================================================================
39 IOAudioBlitterLib.h
40
41 =============================================================================*/
42
43#ifndef __IOAudioBlitterLib_h__
44#define __IOAudioBlitterLib_h__
45
46#include <TargetConditionals.h>
47#include <libkern/OSTypes.h>
48#include <libkern/OSByteOrder.h>
49
50typedef float	Float32;
51typedef double	Float64;
52
53#define NO_EXPORT			__attribute__((visibility("hidden")))
54
55// ============================================================================
56//
57// N.B. These functions should not be called directly; use the interfaces in
58//	PCMBlitterLibDispatch.h.
59//
60// ============================================================================
61
62// can turn these off for debugging
63#define PCMBLIT_PPC	TARGET_CPU_PPC
64#define PCMBLIT_X86 (__i386__ || __LP64__)
65
66#if TARGET_CPU_PPC && !PCMBLIT_PPC
67#warning "PPC optimizations turned off"
68#endif
69
70#if __i386__ && !PCMBLIT_X86
71#warning "X86 optimizations turned off"
72#endif
73
74#define PCMBLIT_INTERLEAVE_SUPPORT TARGET_CPU_PPC	// uses Altivec
75
76typedef const void *ConstVoidPtr;
77
78#pragma mark -
79#pragma mark Utilities
80#if TARGET_OS_MAC && TARGET_CPU_PPC
81#define SET_ROUNDMODE \
82double oldSetting; \
83/* Set the FPSCR to round to -Inf mode */ \
84{ \
85union { \
86double	d; \
87int		i[2]; \
88} setting; \
89register double newSetting; \
90/* Read the the current FPSCR value */ \
91__asm__ __volatile__ ( "mffs %0" : "=f" ( oldSetting ) ); \
92/* Store it to the stack */ \
93setting.d = oldSetting; \
94/* Read in the low 32 bits and mask off the last two bits so they are zero      */ \
95/* in the integer unit. These two bits set to zero means round to nearest mode. */ \
96/* Finally, then store the result back */ \
97setting.i[1] |= 3; \
98/* Load the new FPSCR setting into the FP register file again */ \
99newSetting = setting.d; \
100/* Change the volatile to the new setting */ \
101__asm__ __volatile__( "mtfsf 7, %0" : : "f" (newSetting ) ); \
102}
103
104#define RESTORE_ROUNDMODE \
105/* restore the old FPSCR setting */ \
106__asm__ __volatile__ ( "mtfsf 7, %0" : : "f" (oldSetting) );
107#define DISABLE_DENORMALS
108#define RESTORE_DENORMALS
109
110#elif TARGET_OS_MAC && __i386__
111// our compiler does ALL floating point with SSE
112#define GETCSR()    ({ int _result; asm volatile ("stmxcsr %0" : "=m" (*&_result) ); /*return*/ _result; })
113#define SETCSR( a )    { int _temp = a; asm volatile( "ldmxcsr %0" : : "m" (*&_temp ) ); }
114
115#define DISABLE_DENORMALS int _savemxcsr = GETCSR(); SETCSR(_savemxcsr | 0x8040);
116#define RESTORE_DENORMALS SETCSR(_savemxcsr);
117
118#define ROUNDMODE_NEG_INF int _savemxcsr = GETCSR(); SETCSR((_savemxcsr & ~0x6000) | 0x2000);
119#define ROUNDMODE_NEAREST int _savemxcsr = GETCSR(); SETCSR((_savemxcsr & ~0x6000));
120
121#define RESTORE_ROUNDMODE SETCSR(_savemxcsr);
122#define SET_ROUNDMODE 		ROUNDMODE_NEG_INF
123#elif TARGET_OS_MAC && __LP64__
124// our compiler does ALL floating point with SSE
125#define GETCSR()    ({ int _result; asm volatile ("stmxcsr %0" : "=m" (*&_result) ); /*return*/ _result; })
126#define SETCSR( a )    { int _temp = a; asm volatile( "ldmxcsr %0" : : "m" (*&_temp ) ); }
127
128#define DISABLE_DENORMALS int _savemxcsr = GETCSR(); SETCSR(_savemxcsr | 0x8040);
129#define RESTORE_DENORMALS SETCSR(_savemxcsr);
130
131#define ROUNDMODE_NEG_INF int _savemxcsr = GETCSR(); SETCSR((_savemxcsr & ~0x6000) | 0x2000);
132#define ROUNDMODE_NEAREST int _savemxcsr = GETCSR(); SETCSR((_savemxcsr & ~0x6000));
133
134#define RESTORE_ROUNDMODE SETCSR(_savemxcsr);
135#define SET_ROUNDMODE 		ROUNDMODE_NEG_INF
136#else
137#define DISABLE_DENORMALS
138#define RESTORE_DENORMALS
139
140#define ROUNDMODE_NEG_INF
141#define RESTORE_ROUNDMODE
142#endif
143
144// ____________________________________________________________________________
145//
146// FloatToInt
147// N.B. Functions which use this should invoke SET_ROUNDMODE / RESTORE_ROUNDMODE.
148static inline SInt32 FloatToInt(double inf, double min32, double max32)
149{
150#if TARGET_CPU_PPC
151#pragma unused ( min32,max32)
152	SInt32 i;
153	union {
154		Float64	d;
155		UInt32	i[2];
156	} u;
157	// fctiw rounds, doesn't truncate towards zero like fctiwz
158	__asm__ ("fctiw %0, %1"
159			 /* outputs:  */ : "=f" (u.d)
160			 /* inputs:   */ : "f" (inf));
161	i = u.i[1];
162	return i;
163#elif defined( __i386__ )  || defined( __LP64__ )
164#pragma unused ( min32 )
165
166	if (inf >= max32) return 0x7FFFFFFF;
167	return (SInt32)inf;
168#else
169	if (inf >= max32) return 0x7FFFFFFF;
170	else if (inf <= min32) return 0x80000000;
171	return (SInt32)inf;
172#endif
173}
174
175#ifdef __cplusplus
176#pragma mark -
177#pragma mark C++ templates
178// ____________________________________________________________________________
179//
180//	PCMBlitter
181class PCMBlitter {
182public:
183	virtual void	Convert(const void *vsrc, void *vdest, unsigned int nSamples) = 0;
184	// nSamples = nFrames * nChannels
185	virtual ~PCMBlitter() { }
186
187#if PCMBLIT_INTERLEAVE_SUPPORT
188	// optional methods
189	virtual void	Interleave(ConstVoidPtr , void *, int , unsigned int ) { }
190	virtual void	Deinterleave(ConstVoidPtr , void *, int , unsigned int ) {  }
191#endif
192};
193
194// ____________________________________________________________________________
195//
196//	Types for use in templates
197class PCMFloat32 {
198public:
199	typedef Float32 value_type;
200
201	static value_type load(const value_type *p) { return *p; }
202	static void store(value_type *p, float val)	{ *p = val; }
203};
204
205class PCMFloat64 {
206public:
207	typedef Float64 value_type;
208
209	static value_type load(const value_type *p) { return *p; }
210	static void store(value_type *p, value_type val) { *p = val; }
211};
212
213class PCMSInt8 {
214public:
215	typedef SInt8 value_type;
216
217	static value_type load(const value_type *p) { return *p; }
218	static void store(value_type *p, int val)	{ *p = val; }
219};
220
221class PCMUInt8 {
222public:
223	typedef SInt8 value_type;	// signed so that sign-extending works right
224
225	static value_type load(const value_type *p) { return *p ^ 0x80; }
226	static void store(value_type *p, int val)	{ *p = val ^ 0x80; }
227};
228
229class PCMSInt16Native {
230public:
231	typedef SInt16 value_type;
232
233	static value_type load(const value_type *p) { return *p; }
234	static void store(value_type *p, int val)	{ *p = val; }
235};
236
237class PCMSInt16Swap {
238public:
239	typedef SInt16 value_type;
240
241	static value_type load(const value_type *p)
242	{
243#if PCMBLIT_PPC
244		register SInt32 result;
245		__asm__ volatile("lhbrx %0, %1, %2"
246						 /* outputs:  */ : "=r" (result)
247						 /* inputs:   */ : "b%" (0), "r" (p)
248						 /* clobbers: */ : "memory");
249		return result;
250#elif PCMBLIT_X86 && !TARGET_OS_WIN32
251		return OSReadSwapInt16(p, 0);
252#else
253		return Endian16_Swap(*p);
254#endif
255	}
256	static void store(value_type *p, int val)
257	{
258#if PCMBLIT_PPC
259		__asm__ volatile("sthbrx %0, %1, %2" : : "r" (val), "b%" (0), "r" (p) : "memory");
260#elif PCMBLIT_X86 && !TARGET_OS_WIN32
261		OSWriteSwapInt16(p, 0, val);
262#else
263		*p = Endian16_Swap(val);
264#endif
265	}
266};
267
268class PCMSInt32Native {
269public:
270	typedef SInt32 value_type;
271
272	static value_type load(const value_type *p) { return *p; }
273	static void store(value_type *p, int val)	{ *p = val; }
274};
275
276class PCMSInt32Swap {
277public:
278	typedef UInt32 value_type;
279
280	static value_type load(const value_type *p)
281	{
282#if PCMBLIT_PPC
283		register long lwbrxResult;
284		__asm__ volatile("lwbrx %0, %1, %2" : "=r" (lwbrxResult) : "b%" (0), "r" (p) : "memory");
285		return lwbrxResult;
286#elif PCMBLIT_X86 && !TARGET_OS_WIN32
287		return OSReadSwapInt32(p, 0);
288#else
289		return Endian32_Swap(*p);
290#endif
291	}
292	static void store(value_type *p, int val)
293	{
294		*p = val;
295#if PCMBLIT_PPC
296		__asm__ volatile("stwbrx %0, %1, %2" : : "r" (val), "b%" (0), "r" (p) : "memory");
297#elif PCMBLIT_X86 && !TARGET_OS_WIN32
298		OSWriteSwapInt32(p, 0, val);
299#else
300		*p = Endian32_Swap(val);
301#endif
302	}
303};
304
305class PCMFloat64Swap {
306public:
307	typedef Float64 value_type;
308
309	static value_type load(const value_type *vp) {
310		union {
311			Float64 d;
312			UInt32	i[2];
313		} u;
314		UInt32 *p = (UInt32 *)vp;
315		u.i[0] = PCMSInt32Swap::load(p + 1);
316		u.i[1] = PCMSInt32Swap::load(p + 0);
317		return u.d;
318	}
319	static void store(value_type *vp, value_type val) {
320		union {
321			Float64 d;
322			UInt32	i[2];
323		} u;
324		u.d = val;
325		UInt32 *p = (UInt32 *)vp;
326		PCMSInt32Swap::store(p + 1, u.i[0]);
327		PCMSInt32Swap::store(p + 0, u.i[1]);
328	}
329};
330
331// ____________________________________________________________________________
332//
333// FloatToIntBlitter
334class FloatToIntBlitter : public PCMBlitter {
335public:
336	FloatToIntBlitter(int bitDepth)
337	{
338		int rightShift = 32 - bitDepth;
339		mShift = rightShift;
340		mRound = (rightShift > 0) ? double(1L << (rightShift - 1)) : 0.;
341	}
342
343protected:
344	double	mRound;
345	int		mShift;	// how far to shift a 32 bit value right
346};
347
348// ____________________________________________________________________________
349//
350// TFloatToIntBlitter
351// only used for: 8-bit, low-aligned, or non-PPC
352template <class FloatType, class IntType>
353class TFloatToIntBlitter : public FloatToIntBlitter {
354public:
355	typedef typename FloatType::value_type float_val;
356	typedef typename IntType::value_type int_val;
357
358	TFloatToIntBlitter(int bitDepth) : FloatToIntBlitter(bitDepth) { }
359
360	virtual void	Convert(const void *vsrc, void *vdest, unsigned int nSamples)
361	{
362		const float_val *src = (const float_val *)vsrc;
363		int_val *dest = (int_val *)vdest;
364		double maxInt32 = 2147483648.0;	// 1 << 31
365		double round = mRound;
366		double max32 = maxInt32 - 1.0 - round;
367		double min32 = -2147483648.0;
368		int shift = mShift, count;
369		double f1, f2, f3, f4;
370		int i1, i2, i3, i4;
371
372		SET_ROUNDMODE
373
374		if (nSamples >= 8) {
375			f1 = FloatType::load(src + 0);
376
377			f2 = FloatType::load(src + 1);
378			f1 = f1 * maxInt32 + round;
379
380			f3 = FloatType::load(src + 2);
381			f2 = f2 * maxInt32 + round;
382			i1 = FloatToInt(f1, min32, max32);
383
384			src += 3;
385
386			nSamples -= 4;
387			count = nSamples >> 2;
388			nSamples &= 3;
389
390			while (count--) {
391				f4 = FloatType::load(src + 0);
392				f3 = f3 * maxInt32 + round;
393				i2 = FloatToInt(f2, min32, max32);
394				IntType::store(dest + 0, i1 >> shift);
395
396				f1 = FloatType::load(src + 1);
397				f4 = f4 * maxInt32 + round;
398				i3 = FloatToInt(f3, min32, max32);
399				IntType::store(dest + 1, i2 >> shift);
400
401				f2 = FloatType::load(src + 2);
402				f1 = f1 * maxInt32 + round;
403				i4 = FloatToInt(f4, min32, max32);
404				IntType::store(dest + 2, i3 >> shift);
405
406				f3 = FloatType::load(src + 3);
407				f2 = f2 * maxInt32 + round;
408				i1 = FloatToInt(f1, min32, max32);
409				IntType::store(dest + 3, i4 >> shift);
410
411				src += 4;
412				dest += 4;
413			}
414
415			f4 = FloatType::load(src);
416			f3 = f3 * maxInt32 + round;
417			i2 = FloatToInt(f2, min32, max32);
418			IntType::store(dest + 0, i1 >> shift);
419
420			f4 = f4 * maxInt32 + round;
421			i3 = FloatToInt(f3, min32, max32);
422			IntType::store(dest + 1, i2 >> shift);
423
424			i4 = FloatToInt(f4, min32, max32);
425			IntType::store(dest + 2, i3 >> shift);
426
427			IntType::store(dest + 3, i4 >> shift);
428
429			src += 1;
430			dest += 4;
431		}
432
433		count = nSamples;
434		while (count--) {
435			f1 = FloatType::load(src) * maxInt32 + round;
436			i1 = FloatToInt(f1, min32, max32) >> shift;
437			IntType::store(dest, i1);
438			src += 1;
439			dest += 1;
440		}
441		RESTORE_ROUNDMODE
442	}
443
444#if 0//PCMBLIT_INTERLEAVE_SUPPORT
445	virtual void	Interleave(ConstVoidPtr vsrc[], void *vdest, int nChannels, unsigned int nFrames)
446	{
447		verify_action(nChannels == 2, return);
448
449		const float_val *srcA = (const float_val *)vsrc[0];
450		const float_val *srcB = (const float_val *)vsrc[1];
451		int_val *dest = (int_val *)vdest;
452		double maxInt32 = 2147483648.0;	// 1 << 31
453		double round = mRound;
454		double max32 = maxInt32 - 1.0 - round;
455		double min32 = -2147483648.0;
456		int shift = mShift, count;
457		double f1, f2, f3, f4;
458		int i1, i2, i3, i4;
459
460		SET_ROUNDMODE
461		// two at a time
462		count = nFrames >> 1;
463		while (count--) {
464			f1 = FloatType::load(srcA);
465			f2 = FloatType::load(srcB);
466			f3 = FloatType::load(srcA+1);
467			f4 = FloatType::load(srcB+1);
468			f1 = f1 * maxInt32 + round;
469			f2 = f2 * maxInt32 + round;
470			f3 = f3 * maxInt32 + round;
471			f4 = f4 * maxInt32 + round;
472			i1 = FloatToInt(f1, min32, max32) >> shift;
473			i2 = FloatToInt(f2, min32, max32) >> shift;
474			i3 = FloatToInt(f3, min32, max32) >> shift;
475			i4 = FloatToInt(f4, min32, max32) >> shift;
476			IntType::store(dest, i1);
477			IntType::store(dest+1, i2);
478			IntType::store(dest+2, i3);
479			IntType::store(dest+3, i4);
480			srcA += 2;
481			srcB += 2;
482			dest += 4;
483		}
484		// leftover
485		count = nFrames & 1;
486		while (count--) {
487			f1 = FloatType::load(srcA);
488			f2 = FloatType::load(srcB);
489			f1 = f1 * maxInt32 + round;
490			f2 = f2 * maxInt32 + round;
491			i1 = FloatToInt(f1, min32, max32) >> shift;
492			i2 = FloatToInt(f2, min32, max32) >> shift;
493			IntType::store(dest, i1);
494			IntType::store(dest+1, i2);
495			srcA += 1;
496			srcB += 1;
497			dest += 2;
498		}
499		RESTORE_ROUNDMODE
500	}
501#endif // PCMBLIT_INTERLEAVE_SUPPORT
502};
503
504// ____________________________________________________________________________
505//
506// IntToFloatBlitter
507class IntToFloatBlitter : public PCMBlitter {
508public:
509	IntToFloatBlitter(int bitDepth) :
510	mBitDepth(bitDepth)
511	{
512		mScale = static_cast<Float32>(1.0 / float(1UL << (bitDepth - 1)));
513	}
514
515	Float32		mScale;
516	UInt32		mBitDepth;
517};
518
519// ____________________________________________________________________________
520//
521// TIntToFloatBlitter - only used for non-PPC
522// On PPC these are roughly only half as fast as the optimized versions
523template <class IntType, class FloatType>
524class TIntToFloatBlitter : public IntToFloatBlitter {
525public:
526	typedef typename FloatType::value_type float_val;
527	typedef typename IntType::value_type int_val;
528
529	TIntToFloatBlitter(int bitDepth) : IntToFloatBlitter(bitDepth) { }
530
531	virtual void	Convert(const void *vsrc, void *vdest, unsigned int nSamples)
532	{
533		const int_val *src = (const int_val *)vsrc;
534		float_val *dest = (float_val *)vdest;
535		int count = nSamples;
536		Float32 scale = mScale;
537		int_val i0, i1, i2, i3;
538		float_val f0, f1, f2, f3;
539
540		/*
541		 $i = IntType::load(src); ++src;
542		 $f = $i;
543		 $f *= scale;
544		 FloatType::store(dest, $f); ++dest;
545		 */
546
547		if (count >= 4) {
548			// Cycle 1
549			i0 = IntType::load(src); ++src;
550
551			// Cycle 2
552			i1 = IntType::load(src); ++src;
553			f0 = i0;
554
555			// Cycle 3
556			i2 = IntType::load(src); ++src;
557			f1 = i1;
558			f0 *= scale;
559
560			// Cycle 4
561			i3 = IntType::load(src); ++src;
562			f2 = i2;
563			f1 *= scale;
564			FloatType::store(dest, f0); ++dest;
565
566			count -= 4;
567			int loopCount = count / 4;
568			count -= 4 * loopCount;
569
570			while (loopCount--) {
571				// Cycle A
572				i0 = IntType::load(src); ++src;
573				f3 = i3;
574				f2 *= scale;
575				FloatType::store(dest, f1); ++dest;
576
577				// Cycle B
578				i1 = IntType::load(src); ++src;
579				f0 = i0;
580				f3 *= scale;
581				FloatType::store(dest, f2); ++dest;
582
583				// Cycle C
584				i2 = IntType::load(src); ++src;
585				f1 = i1;
586				f0 *= scale;
587				FloatType::store(dest, f3); ++dest;
588
589				// Cycle D
590				i3 = IntType::load(src); ++src;
591				f2 = i2;
592				f1 *= scale;
593				FloatType::store(dest, f0); ++dest;
594			}
595
596			// Cycle 3
597			f3 = i3;
598			f2 *= scale;
599			FloatType::store(dest, f1); ++dest;
600
601			// Cycle 2
602			f3 *= scale;
603			FloatType::store(dest, f2); ++dest;
604
605			// Cycle 1
606			FloatType::store(dest, f3); ++dest;
607		}
608
609		while (count--) {
610			i0 = IntType::load(src); ++src;
611			f0 = i0;
612			f0 *= scale;
613			FloatType::store(dest, f0); ++dest;
614		}
615	}
616
617#if 0//PCMBLIT_INTERLEAVE_SUPPORT
618	virtual void	Deinterleave(ConstVoidPtr vsrc, void *vdest[], int nChannels, unsigned int nFrames)
619	{
620		verify_action(nChannels == 2, return);
621
622		const int_val *src = (const int_val *)vsrc;
623		float_val *destA = (float_val *)vdest[0];
624		float_val *destB = (float_val *)vdest[1];
625		int count;
626		Float32 scale = mScale;
627
628		count = nFrames;
629		while (count--) {
630			int i1 = IntType::load(src);
631			int i2 = IntType::load(src+1);
632			float_val f1 = i1 * scale;
633			float_val f2 = i2 * scale;
634			FloatType::store(destA, f1);
635			FloatType::store(destB, f2);
636
637			src += 2;
638			destA += 1;
639			destB += 1;
640		}
641	}
642#endif // PCMBLIT_INTERLEAVE_SUPPORT
643};
644#endif // __cplusplus
645
646#ifdef __cplusplus
647extern "C" {
648#endif
649
650#if TARGET_CPU_PPC
651#pragma mark -
652#pragma mark PPC scalar
653
654	// ____________________________________________________________________________________
655	// PPC scalar
656	NO_EXPORT void	NativeInt16ToFloat32_Scalar( const SInt16 *src, Float32 *dest, unsigned int count );
657	NO_EXPORT void	SwapInt16ToFloat32_Scalar( const SInt16 *src, Float32 *dest, unsigned int count );
658	NO_EXPORT void	NativeInt24ToFloat32_Scalar( const SInt32 *src, Float32 *dest, unsigned int count );
659	NO_EXPORT void	SwapInt24ToFloat32_Scalar( const SInt32 *src, Float32 *dest, unsigned int count );
660	NO_EXPORT void	NativeInt32ToFloat32_Scalar( const SInt32 *src, Float32 *dest, unsigned int count );
661	NO_EXPORT void	SwapInt32ToFloat32_Scalar( const SInt32 *src, Float32 *dest, unsigned int count );
662
663	NO_EXPORT void	Float32ToNativeInt16_Scalar( const Float32 *src, SInt16 *dest, unsigned int count );
664	NO_EXPORT void	Float32ToSwapInt16_Scalar( const Float32 *src, SInt16 *dest, unsigned int count );
665	NO_EXPORT void	Float32ToNativeInt24_Scalar( const Float32 *src, SInt32 *dest, unsigned int count );
666	NO_EXPORT void	Float32ToSwapInt24_Scalar( const Float32 *src, SInt32 *dest, unsigned int count );
667	NO_EXPORT void	Float32ToNativeInt32_Scalar( const Float32 *src, SInt32 *dest, unsigned int count );
668	NO_EXPORT void	Float32ToSwapInt32_Scalar( const Float32 *src, SInt32 *dest, unsigned int count );
669
670#pragma mark -
671#pragma mark PPC Altivec
672	// ____________________________________________________________________________________
673	// PPC Altivec
674	NO_EXPORT void	Float32ToInt16_Altivec(const Float32 *fsrc, SInt16 *idst, unsigned int numToConvert, int bigEndian);
675	NO_EXPORT void	Float32ToInt24_Altivec(const Float32 *fsrc, UInt8 *dst, unsigned int numToConvert, int bigEndian);
676	NO_EXPORT void	Float32ToInt32_Altivec(const Float32 *fsrc, SInt32 *dst, unsigned int numToConvert, int bigEndian);
677	NO_EXPORT void	Int16ToFloat32_Altivec(const SInt16 *isrc, Float32 *fdst, unsigned int numToConvert, int bigEndian);
678	NO_EXPORT void	Int24ToFloat32_Altivec(const UInt8 *isrc, Float32 *fdst, unsigned int numToConvert, int bigEndian);
679	NO_EXPORT void	Int32ToFloat32_Altivec(const SInt32 *isrc, Float32 *fdst, unsigned int numToConvert, int bigEndian);
680
681	// These don't have wrappers; check their implementations for limitations
682	NO_EXPORT void	DeinterleaveInt16ToFloat32_Altivec(const SInt16 *isrc, Float32 *dstA, Float32 *dstB, unsigned int numFrames, int bigEndian);
683	//void	Deinterleave32_Altivec(const void *vsrc, void *vdstA, void *vdstB, unsigned int numFrames); untested
684	NO_EXPORT void	Interleave32_Altivec(const void *vsrcA, const void *vsrcB, void *vdst, unsigned int numFrames);
685
686#elif defined( __i386__ ) || defined( __LP64__ )
687#pragma mark -
688#pragma mark X86 SSE2
689	// ____________________________________________________________________________________
690	// X86 SSE2
691	NO_EXPORT void	NativeInt16ToFloat32_X86( const SInt16 *src, Float32 *dest, unsigned int count );
692	NO_EXPORT void	SwapInt16ToFloat32_X86( const SInt16 *src, Float32 *dest, unsigned int count );
693	NO_EXPORT void	Float32ToNativeInt16_X86( const Float32 *src, SInt16 *dest, unsigned int count );
694	NO_EXPORT void	Float32ToSwapInt16_X86( const Float32 *src, SInt16 *dest, unsigned int count );
695
696	NO_EXPORT void	Float32ToNativeInt24_X86( const Float32 *src, UInt8 *dst, unsigned int numToConvert );
697	NO_EXPORT void	Float32ToSwapInt24_X86( const Float32 *src, UInt8 *dst, unsigned int numToConvert );
698
699	NO_EXPORT void	NativeInt32ToFloat32_X86( const SInt32 *src, Float32 *dest, unsigned int count );
700	NO_EXPORT void	SwapInt32ToFloat32_X86( const SInt32 *src, Float32 *dest, unsigned int count );
701	NO_EXPORT void	Float32ToNativeInt32_X86( const Float32 *src, SInt32 *dest, unsigned int count );
702	NO_EXPORT void	Float32ToSwapInt32_X86( const Float32 *src, SInt32 *dest, unsigned int count );
703#elif __LP64__
704#pragma mark -
705#pragma mark X86 SSE2
706	// ____________________________________________________________________________________
707	// X86 SSE2
708	NO_EXPORT void	NativeInt16ToFloat32_X86( const SInt16 *src, Float32 *dest, unsigned int count );
709	NO_EXPORT void	SwapInt16ToFloat32_X86( const SInt16 *src, Float32 *dest, unsigned int count );
710	NO_EXPORT void	Float32ToNativeInt16_X86( const Float32 *src, SInt16 *dest, unsigned int count );
711	NO_EXPORT void	Float32ToSwapInt16_X86( const Float32 *src, SInt16 *dest, unsigned int count );
712
713	NO_EXPORT void	Float32ToNativeInt24_X86( const Float32 *src, UInt8 *dst, unsigned int numToConvert );
714	NO_EXPORT void	Float32ToSwapInt24_X86( const Float32 *src, UInt8 *dst, unsigned int numToConvert );
715
716	NO_EXPORT void	NativeInt32ToFloat32_X86( const SInt32 *src, Float32 *dest, unsigned int count );
717	NO_EXPORT void	SwapInt32ToFloat32_X86( const SInt32 *src, Float32 *dest, unsigned int count );
718	NO_EXPORT void	Float32ToNativeInt32_X86( const Float32 *src, SInt32 *dest, unsigned int count );
719	NO_EXPORT void	Float32ToSwapInt32_X86( const Float32 *src, SInt32 *dest, unsigned int count );
720
721
722#endif
723
724#pragma mark -
725#pragma mark Portable
726	// ____________________________________________________________________________________
727	// Portable
728	NO_EXPORT void	Float32ToNativeInt16_Portable( const Float32 *src, SInt16 *dest, unsigned int count );
729	NO_EXPORT void	Float32ToSwapInt16_Portable( const Float32 *src, SInt16 *dest, unsigned int count );
730	NO_EXPORT void	NativeInt16ToFloat32_Portable( const SInt16 *src, Float32 *dest, unsigned int count );
731	NO_EXPORT void	SwapInt16ToFloat32_Portable( const SInt16 *src, Float32 *dest, unsigned int count );
732
733	NO_EXPORT void	Float32ToNativeInt24_Portable( const Float32 *src, UInt8 *dest, unsigned int count );
734	NO_EXPORT void	Float32ToSwapInt24_Portable( const Float32 *src, UInt8 *dest, unsigned int count );
735	NO_EXPORT void	NativeInt24ToFloat32_Portable( const UInt8 *src, Float32 *dest, unsigned int count );
736	NO_EXPORT void	SwapInt24ToFloat32_Portable( const UInt8 *src, Float32 *dest, unsigned int count );
737
738	NO_EXPORT void	Float32ToNativeInt32_Portable( const Float32 *src, SInt32 *dest, unsigned int count );
739	NO_EXPORT void	Float32ToSwapInt32_Portable( const Float32 *src, SInt32 *dest, unsigned int count );
740	NO_EXPORT void	NativeInt32ToFloat32_Portable( const SInt32 *src, Float32 *dest, unsigned int count );
741	NO_EXPORT void	SwapInt32ToFloat32_Portable( const SInt32 *src, Float32 *dest, unsigned int count );
742
743#ifdef __cplusplus
744};
745#endif
746
747#endif // __IOAudioBlitterLib_h__
748