6 #include "mixer_defs.h"
9 SampleConverter
*CreateSampleConverter(enum DevFmtType srcType
, enum DevFmtType dstType
, ALsizei numchans
, ALsizei srcRate
, ALsizei dstRate
)
11 SampleConverter
*converter
;
13 if(numchans
<= 0 || srcRate
<= 0 || dstRate
<= 0)
16 converter
= al_calloc(16, FAM_SIZE(SampleConverter
, Chan
, numchans
));
17 converter
->mSrcType
= srcType
;
18 converter
->mDstType
= dstType
;
19 converter
->mNumChannels
= numchans
;
20 converter
->mSrcTypeSize
= BytesFromDevFmt(srcType
);
21 converter
->mDstTypeSize
= BytesFromDevFmt(dstType
);
23 converter
->mSrcPrepCount
= 0;
25 converter
->mFracOffset
= 0;
26 converter
->mIncrement
= (ALsizei
)clampu64((ALuint64
)srcRate
*FRACTIONONE
/dstRate
,
27 1, MAX_PITCH
*FRACTIONONE
);
28 if(converter
->mIncrement
== FRACTIONONE
)
29 converter
->mResample
= Resample_copy32_C
;
32 /* TODO: Allow other resamplers. */
33 converter
->mResample
= SelectResampler(LinearResampler
);
39 void DestroySampleConverter(SampleConverter
**converter
)
49 static inline ALfloat
Sample_ALbyte(ALbyte val
)
50 { return val
* (1.0f
/128.0f
); }
51 static inline ALfloat
Sample_ALubyte(ALubyte val
)
52 { return Sample_ALbyte((ALint
)val
- 128); }
54 static inline ALfloat
Sample_ALshort(ALshort val
)
55 { return val
* (1.0f
/32768.0f
); }
56 static inline ALfloat
Sample_ALushort(ALushort val
)
57 { return Sample_ALshort((ALint
)val
- 32768); }
59 static inline ALfloat
Sample_ALint(ALint val
)
60 { return (val
>>7) * (1.0f
/16777216.0f
); }
61 static inline ALfloat
Sample_ALuint(ALuint val
)
62 { return ((ALint
)(val
>>7) - 16777216) * (1.0f
/16777216.0f
); }
64 static inline ALfloat
Sample_ALfloat(ALfloat val
)
67 #define DECL_TEMPLATE(T) \
68 static inline void Load_##T(ALfloat *restrict dst, const T *restrict src, \
69 ALint srcstep, ALsizei samples) \
72 for(i = 0;i < samples;i++) \
73 dst[i] = Sample_##T(src[i*srcstep]); \
77 DECL_TEMPLATE(ALubyte
)
78 DECL_TEMPLATE(ALshort
)
79 DECL_TEMPLATE(ALushort
)
82 DECL_TEMPLATE(ALfloat
)
86 static void LoadSamples(ALfloat
*dst
, const ALvoid
*src
, ALint srcstep
, enum DevFmtType srctype
, ALsizei samples
)
91 Load_ALbyte(dst
, src
, srcstep
, samples
);
94 Load_ALubyte(dst
, src
, srcstep
, samples
);
97 Load_ALshort(dst
, src
, srcstep
, samples
);
100 Load_ALushort(dst
, src
, srcstep
, samples
);
103 Load_ALint(dst
, src
, srcstep
, samples
);
106 Load_ALuint(dst
, src
, srcstep
, samples
);
109 Load_ALfloat(dst
, src
, srcstep
, samples
);
115 static inline ALbyte
ALbyte_Sample(ALfloat val
)
116 { return (ALbyte
)clampf(val
*128.0f
, -128.0f
, 127.0f
); }
117 static inline ALubyte
ALubyte_Sample(ALfloat val
)
118 { return ALbyte_Sample(val
)+128; }
120 static inline ALshort
ALshort_Sample(ALfloat val
)
121 { return (ALshort
)clampf(val
*32768.0f
, -32768.0f
, 32767.0f
); }
122 static inline ALushort
ALushort_Sample(ALfloat val
)
123 { return ALshort_Sample(val
)+32768; }
125 static inline ALint
ALint_Sample(ALfloat val
)
126 { return (ALint
)clampf(val
*16777216.0f
, -16777216.0f
, 16777215.0f
) << 7; }
127 static inline ALuint
ALuint_Sample(ALfloat val
)
128 { return ALint_Sample(val
)+INT_MAX
+1; }
130 static inline ALfloat
ALfloat_Sample(ALfloat val
)
133 #define DECL_TEMPLATE(T) \
134 static inline void Store_##T(T *restrict dst, const ALfloat *restrict src, \
135 ALint dststep, ALsizei samples) \
138 for(i = 0;i < samples;i++) \
139 dst[i*dststep] = T##_Sample(src[i]); \
142 DECL_TEMPLATE(ALbyte
)
143 DECL_TEMPLATE(ALubyte
)
144 DECL_TEMPLATE(ALshort
)
145 DECL_TEMPLATE(ALushort
)
147 DECL_TEMPLATE(ALuint
)
148 DECL_TEMPLATE(ALfloat
)
152 static void StoreSamples(ALvoid
*dst
, const ALfloat
*src
, ALint dststep
, enum DevFmtType dsttype
, ALsizei samples
)
157 Store_ALbyte(dst
, src
, dststep
, samples
);
160 Store_ALubyte(dst
, src
, dststep
, samples
);
163 Store_ALshort(dst
, src
, dststep
, samples
);
166 Store_ALushort(dst
, src
, dststep
, samples
);
169 Store_ALint(dst
, src
, dststep
, samples
);
172 Store_ALuint(dst
, src
, dststep
, samples
);
175 Store_ALfloat(dst
, src
, dststep
, samples
);
181 ALsizei
SampleConverterAvailableOut(SampleConverter
*converter
, ALsizei srcframes
)
183 ALint prepcount
= converter
->mSrcPrepCount
;
184 ALsizei increment
= converter
->mIncrement
;
185 ALsizei DataPosFrac
= converter
->mFracOffset
;
190 /* Negative prepcount means we need to skip that many input samples. */
191 if(-prepcount
>= srcframes
)
193 srcframes
+= prepcount
;
197 if(prepcount
< MAX_POST_SAMPLES
+MAX_PRE_SAMPLES
&&
198 MAX_POST_SAMPLES
+MAX_PRE_SAMPLES
-prepcount
>= srcframes
)
200 /* Not enough input samples to generate an output sample. */
204 DataSize64
= prepcount
;
205 DataSize64
+= srcframes
;
206 DataSize64
-= MAX_POST_SAMPLES
+MAX_PRE_SAMPLES
;
207 DataSize64
<<= FRACTIONBITS
;
208 DataSize64
-= DataPosFrac
;
210 /* If we have a full prep, we can generate at least one sample. */
211 return (ALsizei
)clampu64(DataSize64
/increment
, 1, INT_MAX
);
215 ALsizei
SampleConverterInput(SampleConverter
*converter
, const ALvoid
**src
, ALsizei
*srcframes
, ALvoid
*dst
, ALsizei dstframes
)
217 const ALsizei SrcFrameSize
= converter
->mNumChannels
* converter
->mSrcTypeSize
;
218 const ALsizei DstFrameSize
= converter
->mNumChannels
* converter
->mDstTypeSize
;
219 const ALsizei increment
= converter
->mIncrement
;
222 while(pos
< dstframes
)
224 ALfloat
*restrict SrcData
= ASSUME_ALIGNED(converter
->mSrcSamples
, 16);
225 ALfloat
*restrict DstData
= ASSUME_ALIGNED(converter
->mDstSamples
, 16);
226 ALint prepcount
= converter
->mSrcPrepCount
;
227 ALsizei DataPosFrac
= converter
->mFracOffset
;
235 /* Negative prepcount means we need to skip that many input samples. */
236 if(-prepcount
>= *srcframes
)
238 converter
->mSrcPrepCount
= prepcount
+ *srcframes
;
242 *src
= (const ALbyte
*)*src
+ SrcFrameSize
*-prepcount
;
243 *srcframes
+= prepcount
;
246 toread
= mini(*srcframes
, BUFFERSIZE
-(MAX_POST_SAMPLES
+MAX_PRE_SAMPLES
));
248 if(prepcount
< MAX_POST_SAMPLES
+MAX_PRE_SAMPLES
&&
249 MAX_POST_SAMPLES
+MAX_PRE_SAMPLES
-prepcount
>= toread
)
251 /* Not enough input samples to generate an output sample. Store
252 * what we're given for later.
254 for(chan
= 0;chan
< converter
->mNumChannels
;chan
++)
255 LoadSamples(&converter
->Chan
[chan
].mPrevSamples
[prepcount
],
256 (const ALbyte
*)src
+ converter
->mSrcTypeSize
*chan
,
257 converter
->mNumChannels
, converter
->mSrcType
, toread
260 converter
->mSrcPrepCount
= prepcount
+ toread
;
265 DataSize64
= prepcount
;
266 DataSize64
+= toread
;
267 DataSize64
-= MAX_POST_SAMPLES
+MAX_PRE_SAMPLES
;
268 DataSize64
<<= FRACTIONBITS
;
269 DataSize64
-= DataPosFrac
;
271 /* If we have a full prep, we can generate at least one sample. */
272 DstSize
= (ALsizei
)clampu64(DataSize64
/increment
, 1, BUFFERSIZE
);
273 DstSize
= mini(DstSize
, dstframes
-pos
);
275 for(chan
= 0;chan
< converter
->mNumChannels
;chan
++)
277 const ALbyte
*SrcSamples
= (const ALbyte
*)*src
+ converter
->mSrcTypeSize
*chan
;
278 ALbyte
*DstSamples
= (ALbyte
*)dst
+ converter
->mSrcTypeSize
*chan
;
279 const ALfloat
*ResampledData
;
282 /* Load the previous samples into the source data first, then the
283 * new samples from the input buffer.
285 memcpy(SrcData
, converter
->Chan
[chan
].mPrevSamples
,
286 prepcount
*sizeof(ALfloat
));
287 LoadSamples(SrcData
+ prepcount
, SrcSamples
,
288 converter
->mNumChannels
, converter
->mSrcType
, toread
291 /* Store as many prep samples for next time as possible, given the
292 * number of output samples being generated.
294 SrcDataEnd
= (DataPosFrac
+ increment
*DstSize
)>>FRACTIONBITS
;
295 if(SrcDataEnd
>= prepcount
+toread
)
296 memset(converter
->Chan
[chan
].mPrevSamples
, 0,
297 sizeof(converter
->Chan
[chan
].mPrevSamples
));
300 size_t len
= mini(MAX_PRE_SAMPLES
+MAX_POST_SAMPLES
, prepcount
+toread
-SrcDataEnd
);
301 memcpy(converter
->Chan
[chan
].mPrevSamples
, &SrcData
[SrcDataEnd
],
302 len
*sizeof(ALfloat
));
303 memset(converter
->Chan
[chan
].mPrevSamples
+len
, 0,
304 sizeof(converter
->Chan
[chan
].mPrevSamples
) - len
*sizeof(ALfloat
));
307 /* Now resample, and store the result in the output buffer. */
308 ResampledData
= converter
->mResample(NULL
,
309 SrcData
+MAX_PRE_SAMPLES
, DataPosFrac
, increment
,
313 StoreSamples(DstSamples
, ResampledData
, converter
->mNumChannels
,
314 converter
->mDstType
, DstSize
);
317 /* Update the number of prep samples still available, as well as the
320 DataPosFrac
+= increment
*DstSize
;
321 converter
->mSrcPrepCount
= mini(MAX_PRE_SAMPLES
+MAX_POST_SAMPLES
,
322 prepcount
+toread
-(DataPosFrac
>>FRACTIONBITS
));
323 converter
->mFracOffset
= DataPosFrac
& FRACTIONMASK
;
325 /* Update the src and dst pointers in case there's still more to do. */
326 *src
= (const ALbyte
*)*src
+ SrcFrameSize
*(DataPosFrac
>>FRACTIONBITS
);
327 *srcframes
-= mini(*srcframes
, (DataPosFrac
>>FRACTIONBITS
));
329 dst
= (ALbyte
*)dst
+ DstFrameSize
*DstSize
;
337 ChannelConverter
*CreateChannelConverter(enum DevFmtType srcType
, enum DevFmtChannels srcChans
, enum DevFmtChannels dstChans
)
339 ChannelConverter
*converter
;
341 if(srcChans
!= dstChans
&& !((srcChans
== DevFmtMono
&& dstChans
== DevFmtStereo
) ||
342 (srcChans
== DevFmtStereo
&& dstChans
== DevFmtMono
)))
345 converter
= al_calloc(DEF_ALIGN
, sizeof(*converter
));
346 converter
->mSrcType
= srcType
;
347 converter
->mSrcChans
= srcChans
;
348 converter
->mDstChans
= dstChans
;
353 void DestroyChannelConverter(ChannelConverter
**converter
)
363 #define DECL_TEMPLATE(T) \
364 static void Mono2Stereo##T(ALfloat *restrict dst, const T *src, ALsizei frames)\
367 for(i = 0;i < frames;i++) \
368 dst[i*2 + 1] = dst[i*2 + 0] = Sample_##T(src[i]) * 0.707106781187f; \
371 static void Stereo2Mono##T(ALfloat *restrict dst, const T *src, ALsizei frames)\
374 for(i = 0;i < frames;i++) \
375 dst[i] = (Sample_##T(src[i*2 + 0])+Sample_##T(src[i*2 + 1])) * \
379 DECL_TEMPLATE(ALbyte
)
380 DECL_TEMPLATE(ALubyte
)
381 DECL_TEMPLATE(ALshort
)
382 DECL_TEMPLATE(ALushort
)
384 DECL_TEMPLATE(ALuint
)
385 DECL_TEMPLATE(ALfloat
)
389 void ChannelConverterInput(ChannelConverter
*converter
, const ALvoid
*src
, ALfloat
*dst
, ALsizei frames
)
391 if(converter
->mSrcChans
== converter
->mDstChans
)
393 LoadSamples(dst
, src
, 1, converter
->mSrcType
,
394 frames
*ChannelsFromDevFmt(converter
->mSrcChans
, 0));
398 if(converter
->mSrcChans
== DevFmtStereo
&& converter
->mDstChans
== DevFmtMono
)
400 switch(converter
->mSrcType
)
403 Stereo2MonoALbyte(dst
, src
, frames
);
406 Stereo2MonoALubyte(dst
, src
, frames
);
409 Stereo2MonoALshort(dst
, src
, frames
);
412 Stereo2MonoALushort(dst
, src
, frames
);
415 Stereo2MonoALint(dst
, src
, frames
);
418 Stereo2MonoALuint(dst
, src
, frames
);
421 Stereo2MonoALfloat(dst
, src
, frames
);
425 else /*if(converter->mSrcChans == DevFmtMono && converter->mDstChans == DevFmtStereo)*/
427 switch(converter
->mSrcType
)
430 Mono2StereoALbyte(dst
, src
, frames
);
433 Mono2StereoALubyte(dst
, src
, frames
);
436 Mono2StereoALshort(dst
, src
, frames
);
439 Mono2StereoALushort(dst
, src
, frames
);
442 Mono2StereoALint(dst
, src
, frames
);
445 Mono2StereoALuint(dst
, src
, frames
);
448 Mono2StereoALfloat(dst
, src
, frames
);