7 #include "mixer/defs.h"
10 SampleConverter
*CreateSampleConverter(enum DevFmtType srcType
, enum DevFmtType dstType
, ALsizei numchans
, ALsizei srcRate
, ALsizei dstRate
)
12 SampleConverter
*converter
;
15 if(numchans
<= 0 || srcRate
<= 0 || dstRate
<= 0)
18 converter
= al_calloc(16, FAM_SIZE(SampleConverter
, Chan
, numchans
));
19 converter
->mSrcType
= srcType
;
20 converter
->mDstType
= dstType
;
21 converter
->mNumChannels
= numchans
;
22 converter
->mSrcTypeSize
= BytesFromDevFmt(srcType
);
23 converter
->mDstTypeSize
= BytesFromDevFmt(dstType
);
25 converter
->mSrcPrepCount
= 0;
26 converter
->mFracOffset
= 0;
28 /* Have to set the mixer FPU mode since that's what the resampler code expects. */
30 step
= (ALsizei
)mind(((ALdouble
)srcRate
/dstRate
*FRACTIONONE
) + 0.5,
31 MAX_PITCH
* FRACTIONONE
);
32 converter
->mIncrement
= maxi(step
, 1);
33 if(converter
->mIncrement
== FRACTIONONE
)
34 converter
->mResample
= Resample_copy_C
;
37 /* TODO: Allow other resamplers. */
38 BsincPrepare(converter
->mIncrement
, &converter
->mState
.bsinc
, &bsinc12
);
39 converter
->mResample
= SelectResampler(BSinc12Resampler
);
46 void DestroySampleConverter(SampleConverter
**converter
)
56 static inline ALfloat
Sample_ALbyte(ALbyte val
)
57 { return val
* (1.0f
/128.0f
); }
58 static inline ALfloat
Sample_ALubyte(ALubyte val
)
59 { return Sample_ALbyte((ALint
)val
- 128); }
61 static inline ALfloat
Sample_ALshort(ALshort val
)
62 { return val
* (1.0f
/32768.0f
); }
63 static inline ALfloat
Sample_ALushort(ALushort val
)
64 { return Sample_ALshort((ALint
)val
- 32768); }
66 static inline ALfloat
Sample_ALint(ALint val
)
67 { return (val
>>7) * (1.0f
/16777216.0f
); }
68 static inline ALfloat
Sample_ALuint(ALuint val
)
69 { return Sample_ALint(val
- INT_MAX
- 1); }
71 static inline ALfloat
Sample_ALfloat(ALfloat val
)
74 #define DECL_TEMPLATE(T) \
75 static inline void Load_##T(ALfloat *restrict dst, const T *restrict src, \
76 ALint srcstep, ALsizei samples) \
79 for(i = 0;i < samples;i++) \
80 dst[i] = Sample_##T(src[i*srcstep]); \
84 DECL_TEMPLATE(ALubyte
)
85 DECL_TEMPLATE(ALshort
)
86 DECL_TEMPLATE(ALushort
)
89 DECL_TEMPLATE(ALfloat
)
93 static void LoadSamples(ALfloat
*dst
, const ALvoid
*src
, ALint srcstep
, enum DevFmtType srctype
, ALsizei samples
)
98 Load_ALbyte(dst
, src
, srcstep
, samples
);
101 Load_ALubyte(dst
, src
, srcstep
, samples
);
104 Load_ALshort(dst
, src
, srcstep
, samples
);
107 Load_ALushort(dst
, src
, srcstep
, samples
);
110 Load_ALint(dst
, src
, srcstep
, samples
);
113 Load_ALuint(dst
, src
, srcstep
, samples
);
116 Load_ALfloat(dst
, src
, srcstep
, samples
);
122 static inline ALbyte
ALbyte_Sample(ALfloat val
)
123 { return fastf2i(clampf(val
*128.0f
, -128.0f
, 127.0f
)); }
124 static inline ALubyte
ALubyte_Sample(ALfloat val
)
125 { return ALbyte_Sample(val
)+128; }
127 static inline ALshort
ALshort_Sample(ALfloat val
)
128 { return fastf2i(clampf(val
*32768.0f
, -32768.0f
, 32767.0f
)); }
129 static inline ALushort
ALushort_Sample(ALfloat val
)
130 { return ALshort_Sample(val
)+32768; }
132 static inline ALint
ALint_Sample(ALfloat val
)
133 { return fastf2i(clampf(val
*16777216.0f
, -16777216.0f
, 16777215.0f
)) << 7; }
134 static inline ALuint
ALuint_Sample(ALfloat val
)
135 { return ALint_Sample(val
)+INT_MAX
+1; }
137 static inline ALfloat
ALfloat_Sample(ALfloat val
)
140 #define DECL_TEMPLATE(T) \
141 static inline void Store_##T(T *restrict dst, const ALfloat *restrict src, \
142 ALint dststep, ALsizei samples) \
145 for(i = 0;i < samples;i++) \
146 dst[i*dststep] = T##_Sample(src[i]); \
149 DECL_TEMPLATE(ALbyte
)
150 DECL_TEMPLATE(ALubyte
)
151 DECL_TEMPLATE(ALshort
)
152 DECL_TEMPLATE(ALushort
)
154 DECL_TEMPLATE(ALuint
)
155 DECL_TEMPLATE(ALfloat
)
159 static void StoreSamples(ALvoid
*dst
, const ALfloat
*src
, ALint dststep
, enum DevFmtType dsttype
, ALsizei samples
)
164 Store_ALbyte(dst
, src
, dststep
, samples
);
167 Store_ALubyte(dst
, src
, dststep
, samples
);
170 Store_ALshort(dst
, src
, dststep
, samples
);
173 Store_ALushort(dst
, src
, dststep
, samples
);
176 Store_ALint(dst
, src
, dststep
, samples
);
179 Store_ALuint(dst
, src
, dststep
, samples
);
182 Store_ALfloat(dst
, src
, dststep
, samples
);
188 ALsizei
SampleConverterAvailableOut(SampleConverter
*converter
, ALsizei srcframes
)
190 ALint prepcount
= converter
->mSrcPrepCount
;
191 ALsizei increment
= converter
->mIncrement
;
192 ALsizei DataPosFrac
= converter
->mFracOffset
;
197 /* Negative prepcount means we need to skip that many input samples. */
198 if(-prepcount
>= srcframes
)
200 srcframes
+= prepcount
;
206 /* No output samples if there's no input samples. */
210 if(prepcount
< MAX_RESAMPLE_PADDING
*2 &&
211 MAX_RESAMPLE_PADDING
*2 - prepcount
>= srcframes
)
213 /* Not enough input samples to generate an output sample. */
217 DataSize64
= prepcount
;
218 DataSize64
+= srcframes
;
219 DataSize64
-= MAX_RESAMPLE_PADDING
*2;
220 DataSize64
<<= FRACTIONBITS
;
221 DataSize64
-= DataPosFrac
;
223 /* If we have a full prep, we can generate at least one sample. */
224 return (ALsizei
)clampu64((DataSize64
+ increment
-1)/increment
, 1, BUFFERSIZE
);
228 ALsizei
SampleConverterInput(SampleConverter
*converter
, const ALvoid
**src
, ALsizei
*srcframes
, ALvoid
*dst
, ALsizei dstframes
)
230 const ALsizei SrcFrameSize
= converter
->mNumChannels
* converter
->mSrcTypeSize
;
231 const ALsizei DstFrameSize
= converter
->mNumChannels
* converter
->mDstTypeSize
;
232 const ALsizei increment
= converter
->mIncrement
;
236 while(pos
< dstframes
&& *srcframes
> 0)
238 ALfloat
*restrict SrcData
= ASSUME_ALIGNED(converter
->mSrcSamples
, 16);
239 ALfloat
*restrict DstData
= ASSUME_ALIGNED(converter
->mDstSamples
, 16);
240 ALint prepcount
= converter
->mSrcPrepCount
;
241 ALsizei DataPosFrac
= converter
->mFracOffset
;
249 /* Negative prepcount means we need to skip that many input samples. */
250 if(-prepcount
>= *srcframes
)
252 converter
->mSrcPrepCount
= prepcount
+ *srcframes
;
256 *src
= (const ALbyte
*)*src
+ SrcFrameSize
*-prepcount
;
257 *srcframes
+= prepcount
;
258 converter
->mSrcPrepCount
= 0;
261 toread
= mini(*srcframes
, BUFFERSIZE
- MAX_RESAMPLE_PADDING
*2);
263 if(prepcount
< MAX_RESAMPLE_PADDING
*2 &&
264 MAX_RESAMPLE_PADDING
*2 - prepcount
>= toread
)
266 /* Not enough input samples to generate an output sample. Store
267 * what we're given for later.
269 for(chan
= 0;chan
< converter
->mNumChannels
;chan
++)
270 LoadSamples(&converter
->Chan
[chan
].mPrevSamples
[prepcount
],
271 (const ALbyte
*)*src
+ converter
->mSrcTypeSize
*chan
,
272 converter
->mNumChannels
, converter
->mSrcType
, toread
275 converter
->mSrcPrepCount
= prepcount
+ toread
;
280 DataSize64
= prepcount
;
281 DataSize64
+= toread
;
282 DataSize64
-= MAX_RESAMPLE_PADDING
*2;
283 DataSize64
<<= FRACTIONBITS
;
284 DataSize64
-= DataPosFrac
;
286 /* If we have a full prep, we can generate at least one sample. */
287 DstSize
= (ALsizei
)clampu64((DataSize64
+ increment
-1)/increment
, 1, BUFFERSIZE
);
288 DstSize
= mini(DstSize
, dstframes
-pos
);
290 for(chan
= 0;chan
< converter
->mNumChannels
;chan
++)
292 const ALbyte
*SrcSamples
= (const ALbyte
*)*src
+ converter
->mSrcTypeSize
*chan
;
293 ALbyte
*DstSamples
= (ALbyte
*)dst
+ converter
->mDstTypeSize
*chan
;
294 const ALfloat
*ResampledData
;
297 /* Load the previous samples into the source data first, then the
298 * new samples from the input buffer.
300 memcpy(SrcData
, converter
->Chan
[chan
].mPrevSamples
,
301 prepcount
*sizeof(ALfloat
));
302 LoadSamples(SrcData
+ prepcount
, SrcSamples
,
303 converter
->mNumChannels
, converter
->mSrcType
, toread
306 /* Store as many prep samples for next time as possible, given the
307 * number of output samples being generated.
309 SrcDataEnd
= (DataPosFrac
+ increment
*DstSize
)>>FRACTIONBITS
;
310 if(SrcDataEnd
>= prepcount
+toread
)
311 memset(converter
->Chan
[chan
].mPrevSamples
, 0,
312 sizeof(converter
->Chan
[chan
].mPrevSamples
));
315 size_t len
= mini(MAX_RESAMPLE_PADDING
*2, prepcount
+toread
-SrcDataEnd
);
316 memcpy(converter
->Chan
[chan
].mPrevSamples
, &SrcData
[SrcDataEnd
],
317 len
*sizeof(ALfloat
));
318 memset(converter
->Chan
[chan
].mPrevSamples
+len
, 0,
319 sizeof(converter
->Chan
[chan
].mPrevSamples
) - len
*sizeof(ALfloat
));
322 /* Now resample, and store the result in the output buffer. */
323 ResampledData
= converter
->mResample(&converter
->mState
,
324 SrcData
+MAX_RESAMPLE_PADDING
, DataPosFrac
, increment
,
328 StoreSamples(DstSamples
, ResampledData
, converter
->mNumChannels
,
329 converter
->mDstType
, DstSize
);
332 /* Update the number of prep samples still available, as well as the
335 DataPosFrac
+= increment
*DstSize
;
336 converter
->mSrcPrepCount
= mini(prepcount
+ toread
- (DataPosFrac
>>FRACTIONBITS
),
337 MAX_RESAMPLE_PADDING
*2);
338 converter
->mFracOffset
= DataPosFrac
& FRACTIONMASK
;
340 /* Update the src and dst pointers in case there's still more to do. */
341 *src
= (const ALbyte
*)*src
+ SrcFrameSize
*(DataPosFrac
>>FRACTIONBITS
);
342 *srcframes
-= mini(*srcframes
, (DataPosFrac
>>FRACTIONBITS
));
344 dst
= (ALbyte
*)dst
+ DstFrameSize
*DstSize
;
353 ChannelConverter
*CreateChannelConverter(enum DevFmtType srcType
, enum DevFmtChannels srcChans
, enum DevFmtChannels dstChans
)
355 ChannelConverter
*converter
;
357 if(srcChans
!= dstChans
&& !((srcChans
== DevFmtMono
&& dstChans
== DevFmtStereo
) ||
358 (srcChans
== DevFmtStereo
&& dstChans
== DevFmtMono
)))
361 converter
= al_calloc(DEF_ALIGN
, sizeof(*converter
));
362 converter
->mSrcType
= srcType
;
363 converter
->mSrcChans
= srcChans
;
364 converter
->mDstChans
= dstChans
;
369 void DestroyChannelConverter(ChannelConverter
**converter
)
379 #define DECL_TEMPLATE(T) \
380 static void Mono2Stereo##T(ALfloat *restrict dst, const T *src, ALsizei frames)\
383 for(i = 0;i < frames;i++) \
384 dst[i*2 + 1] = dst[i*2 + 0] = Sample_##T(src[i]) * 0.707106781187f; \
387 static void Stereo2Mono##T(ALfloat *restrict dst, const T *src, ALsizei frames)\
390 for(i = 0;i < frames;i++) \
391 dst[i] = (Sample_##T(src[i*2 + 0])+Sample_##T(src[i*2 + 1])) * \
395 DECL_TEMPLATE(ALbyte
)
396 DECL_TEMPLATE(ALubyte
)
397 DECL_TEMPLATE(ALshort
)
398 DECL_TEMPLATE(ALushort
)
400 DECL_TEMPLATE(ALuint
)
401 DECL_TEMPLATE(ALfloat
)
405 void ChannelConverterInput(ChannelConverter
*converter
, const ALvoid
*src
, ALfloat
*dst
, ALsizei frames
)
407 if(converter
->mSrcChans
== converter
->mDstChans
)
409 LoadSamples(dst
, src
, 1, converter
->mSrcType
,
410 frames
*ChannelsFromDevFmt(converter
->mSrcChans
, 0));
414 if(converter
->mSrcChans
== DevFmtStereo
&& converter
->mDstChans
== DevFmtMono
)
416 switch(converter
->mSrcType
)
419 Stereo2MonoALbyte(dst
, src
, frames
);
422 Stereo2MonoALubyte(dst
, src
, frames
);
425 Stereo2MonoALshort(dst
, src
, frames
);
428 Stereo2MonoALushort(dst
, src
, frames
);
431 Stereo2MonoALint(dst
, src
, frames
);
434 Stereo2MonoALuint(dst
, src
, frames
);
437 Stereo2MonoALfloat(dst
, src
, frames
);
441 else /*if(converter->mSrcChans == DevFmtMono && converter->mDstChans == DevFmtStereo)*/
443 switch(converter
->mSrcType
)
446 Mono2StereoALbyte(dst
, src
, frames
);
449 Mono2StereoALubyte(dst
, src
, frames
);
452 Mono2StereoALshort(dst
, src
, frames
);
455 Mono2StereoALushort(dst
, src
, frames
);
458 Mono2StereoALint(dst
, src
, frames
);
461 Mono2StereoALuint(dst
, src
, frames
);
464 Mono2StereoALfloat(dst
, src
, frames
);