9 #include "mixer/defs.h"
14 /* Base template left undefined. Should be marked =delete, but Clang 3.8.1
15 * chokes on that given the inline specializations.
17 template<DevFmtType T
>
18 inline ALfloat
LoadSample(typename DevFmtTypeTraits
<T
>::Type val
);
20 template<> inline ALfloat LoadSample
<DevFmtByte
>(DevFmtTypeTraits
<DevFmtByte
>::Type val
)
21 { return val
* (1.0f
/128.0f
); }
22 template<> inline ALfloat LoadSample
<DevFmtShort
>(DevFmtTypeTraits
<DevFmtShort
>::Type val
)
23 { return val
* (1.0f
/32768.0f
); }
24 template<> inline ALfloat LoadSample
<DevFmtInt
>(DevFmtTypeTraits
<DevFmtInt
>::Type val
)
25 { return (val
>>7) * (1.0f
/16777216.0f
); }
26 template<> inline ALfloat LoadSample
<DevFmtFloat
>(DevFmtTypeTraits
<DevFmtFloat
>::Type val
)
29 template<> inline ALfloat LoadSample
<DevFmtUByte
>(DevFmtTypeTraits
<DevFmtUByte
>::Type val
)
30 { return LoadSample
<DevFmtByte
>(val
- 128); }
31 template<> inline ALfloat LoadSample
<DevFmtUShort
>(DevFmtTypeTraits
<DevFmtUShort
>::Type val
)
32 { return LoadSample
<DevFmtByte
>(val
- 32768); }
33 template<> inline ALfloat LoadSample
<DevFmtUInt
>(DevFmtTypeTraits
<DevFmtUInt
>::Type val
)
34 { return LoadSample
<DevFmtByte
>(val
- 2147483648u); }
37 template<DevFmtType T
>
38 inline void LoadSampleArray(ALfloat
*RESTRICT dst
, const void *src
, size_t srcstep
, ALsizei samples
)
40 using SampleType
= typename DevFmtTypeTraits
<T
>::Type
;
42 const SampleType
*ssrc
= static_cast<const SampleType
*>(src
);
43 for(ALsizei i
{0};i
< samples
;i
++)
44 dst
[i
] = LoadSample
<T
>(ssrc
[i
*srcstep
]);
47 void LoadSamples(ALfloat
*dst
, const ALvoid
*src
, size_t srcstep
, DevFmtType srctype
, ALsizei samples
)
49 #define HANDLE_FMT(T) \
50 case T: LoadSampleArray<T>(dst, src, srcstep, samples); break
53 HANDLE_FMT(DevFmtByte
);
54 HANDLE_FMT(DevFmtUByte
);
55 HANDLE_FMT(DevFmtShort
);
56 HANDLE_FMT(DevFmtUShort
);
57 HANDLE_FMT(DevFmtInt
);
58 HANDLE_FMT(DevFmtUInt
);
59 HANDLE_FMT(DevFmtFloat
);
65 template<DevFmtType T
>
66 inline typename DevFmtTypeTraits
<T
>::Type
StoreSample(ALfloat
);
68 template<> inline ALfloat StoreSample
<DevFmtFloat
>(ALfloat val
)
70 template<> inline ALint StoreSample
<DevFmtInt
>(ALfloat val
)
71 { return fastf2i(clampf(val
*16777216.0f
, -16777216.0f
, 16777215.0f
))<<7; }
72 template<> inline ALshort StoreSample
<DevFmtShort
>(ALfloat val
)
73 { return fastf2i(clampf(val
*32768.0f
, -32768.0f
, 32767.0f
)); }
74 template<> inline ALbyte StoreSample
<DevFmtByte
>(ALfloat val
)
75 { return fastf2i(clampf(val
*128.0f
, -128.0f
, 127.0f
)); }
77 /* Define unsigned output variations. */
78 template<> inline ALuint StoreSample
<DevFmtUInt
>(ALfloat val
)
79 { return StoreSample
<DevFmtInt
>(val
) + 2147483648u; }
80 template<> inline ALushort StoreSample
<DevFmtUShort
>(ALfloat val
)
81 { return StoreSample
<DevFmtShort
>(val
) + 32768; }
82 template<> inline ALubyte StoreSample
<DevFmtUByte
>(ALfloat val
)
83 { return StoreSample
<DevFmtByte
>(val
) + 128; }
85 template<DevFmtType T
>
86 inline void StoreSampleArray(void *dst
, const ALfloat
*RESTRICT src
, size_t dststep
,
89 using SampleType
= typename DevFmtTypeTraits
<T
>::Type
;
91 SampleType
*sdst
= static_cast<SampleType
*>(dst
);
92 for(ALsizei i
{0};i
< samples
;i
++)
93 sdst
[i
*dststep
] = StoreSample
<T
>(src
[i
]);
97 void StoreSamples(ALvoid
*dst
, const ALfloat
*src
, size_t dststep
, DevFmtType dsttype
, ALsizei samples
)
99 #define HANDLE_FMT(T) \
100 case T: StoreSampleArray<T>(dst, src, dststep, samples); break
103 HANDLE_FMT(DevFmtByte
);
104 HANDLE_FMT(DevFmtUByte
);
105 HANDLE_FMT(DevFmtShort
);
106 HANDLE_FMT(DevFmtUShort
);
107 HANDLE_FMT(DevFmtInt
);
108 HANDLE_FMT(DevFmtUInt
);
109 HANDLE_FMT(DevFmtFloat
);
115 template<DevFmtType T
>
116 void Mono2Stereo(ALfloat
*RESTRICT dst
, const void *src
, ALsizei frames
)
118 using SampleType
= typename DevFmtTypeTraits
<T
>::Type
;
120 const SampleType
*ssrc
= static_cast<const SampleType
*>(src
);
121 for(ALsizei i
{0};i
< frames
;i
++)
122 dst
[i
*2 + 1] = dst
[i
*2 + 0] = LoadSample
<T
>(ssrc
[i
]) * 0.707106781187f
;
125 template<DevFmtType T
>
126 void Stereo2Mono(ALfloat
*RESTRICT dst
, const void *src
, ALsizei frames
)
128 using SampleType
= typename DevFmtTypeTraits
<T
>::Type
;
130 const SampleType
*ssrc
= static_cast<const SampleType
*>(src
);
131 for(ALsizei i
{0};i
< frames
;i
++)
132 dst
[i
] = (LoadSample
<T
>(ssrc
[i
*2 + 0])+LoadSample
<T
>(ssrc
[i
*2 + 1])) *
138 SampleConverterPtr
CreateSampleConverter(DevFmtType srcType
, DevFmtType dstType
, ALsizei numchans
,
139 ALsizei srcRate
, ALsizei dstRate
, Resampler resampler
)
141 if(numchans
<= 0 || srcRate
<= 0 || dstRate
<= 0)
144 void *ptr
{al_calloc(16, SampleConverter::Sizeof(numchans
))};
145 SampleConverterPtr converter
{new (ptr
) SampleConverter
{static_cast<size_t>(numchans
)}};
146 converter
->mSrcType
= srcType
;
147 converter
->mDstType
= dstType
;
148 converter
->mSrcTypeSize
= BytesFromDevFmt(srcType
);
149 converter
->mDstTypeSize
= BytesFromDevFmt(dstType
);
151 converter
->mSrcPrepCount
= 0;
152 converter
->mFracOffset
= 0;
154 /* Have to set the mixer FPU mode since that's what the resampler code expects. */
156 auto step
= static_cast<ALsizei
>(
157 mind(static_cast<ALdouble
>(srcRate
)/dstRate
*FRACTIONONE
+ 0.5, MAX_PITCH
*FRACTIONONE
));
158 converter
->mIncrement
= maxi(step
, 1);
159 if(converter
->mIncrement
== FRACTIONONE
)
160 converter
->mResample
= Resample_copy_C
;
163 if(resampler
== BSinc24Resampler
)
164 BsincPrepare(converter
->mIncrement
, &converter
->mState
.bsinc
, &bsinc24
);
165 else if(resampler
== BSinc12Resampler
)
166 BsincPrepare(converter
->mIncrement
, &converter
->mState
.bsinc
, &bsinc12
);
167 converter
->mResample
= SelectResampler(resampler
);
173 ALsizei
SampleConverter::availableOut(ALsizei srcframes
) const
175 ALint prepcount
{mSrcPrepCount
};
178 /* Negative prepcount means we need to skip that many input samples. */
179 if(-prepcount
>= srcframes
)
181 srcframes
+= prepcount
;
187 /* No output samples if there's no input samples. */
191 if(prepcount
< MAX_RESAMPLE_PADDING
*2 &&
192 MAX_RESAMPLE_PADDING
*2 - prepcount
>= srcframes
)
194 /* Not enough input samples to generate an output sample. */
198 auto DataSize64
= static_cast<ALuint64
>(prepcount
);
199 DataSize64
+= srcframes
;
200 DataSize64
-= MAX_RESAMPLE_PADDING
*2;
201 DataSize64
<<= FRACTIONBITS
;
202 DataSize64
-= mFracOffset
;
204 /* If we have a full prep, we can generate at least one sample. */
205 return static_cast<ALsizei
>(clampu64((DataSize64
+ mIncrement
-1)/mIncrement
, 1, BUFFERSIZE
));
208 ALsizei
SampleConverter::convert(const ALvoid
**src
, ALsizei
*srcframes
, ALvoid
*dst
, ALsizei dstframes
)
210 const ALsizei SrcFrameSize
{static_cast<ALsizei
>(mChan
.size()) * mSrcTypeSize
};
211 const ALsizei DstFrameSize
{static_cast<ALsizei
>(mChan
.size()) * mDstTypeSize
};
212 const ALsizei increment
{mIncrement
};
213 auto SamplesIn
= static_cast<const ALbyte
*>(*src
);
214 ALsizei NumSrcSamples
{*srcframes
};
218 while(pos
< dstframes
&& NumSrcSamples
> 0)
220 ALint prepcount
{mSrcPrepCount
};
223 /* Negative prepcount means we need to skip that many input samples. */
224 if(-prepcount
>= NumSrcSamples
)
226 mSrcPrepCount
= prepcount
+ NumSrcSamples
;
230 SamplesIn
+= SrcFrameSize
*-prepcount
;
231 NumSrcSamples
+= prepcount
;
235 ALint toread
{mini(NumSrcSamples
, BUFFERSIZE
- MAX_RESAMPLE_PADDING
*2)};
237 if(prepcount
< MAX_RESAMPLE_PADDING
*2 &&
238 MAX_RESAMPLE_PADDING
*2 - prepcount
>= toread
)
240 /* Not enough input samples to generate an output sample. Store
241 * what we're given for later.
243 for(size_t chan
{0u};chan
< mChan
.size();chan
++)
244 LoadSamples(&mChan
[chan
].PrevSamples
[prepcount
], SamplesIn
+ mSrcTypeSize
*chan
,
245 mChan
.size(), mSrcType
, toread
);
247 mSrcPrepCount
= prepcount
+ toread
;
252 ALfloat
*RESTRICT SrcData
{mSrcSamples
};
253 ALfloat
*RESTRICT DstData
{mDstSamples
};
254 ALsizei DataPosFrac
{mFracOffset
};
255 auto DataSize64
= static_cast<ALuint64
>(prepcount
);
256 DataSize64
+= toread
;
257 DataSize64
-= MAX_RESAMPLE_PADDING
*2;
258 DataSize64
<<= FRACTIONBITS
;
259 DataSize64
-= DataPosFrac
;
261 /* If we have a full prep, we can generate at least one sample. */
262 auto DstSize
= static_cast<ALsizei
>(
263 clampu64((DataSize64
+ increment
-1)/increment
, 1, BUFFERSIZE
));
264 DstSize
= mini(DstSize
, dstframes
-pos
);
266 for(size_t chan
{0u};chan
< mChan
.size();chan
++)
268 const ALbyte
*SrcSamples
= SamplesIn
+ mSrcTypeSize
*chan
;
269 ALbyte
*DstSamples
= static_cast<ALbyte
*>(dst
) + mDstTypeSize
*chan
;
271 /* Load the previous samples into the source data first, then the
272 * new samples from the input buffer.
274 std::copy_n(mChan
[chan
].PrevSamples
, prepcount
, SrcData
);
275 LoadSamples(SrcData
+ prepcount
, SrcSamples
, mChan
.size(), mSrcType
, toread
);
277 /* Store as many prep samples for next time as possible, given the
278 * number of output samples being generated.
280 ALsizei SrcDataEnd
{(DstSize
*increment
+ DataPosFrac
)>>FRACTIONBITS
};
281 if(SrcDataEnd
>= prepcount
+toread
)
282 std::fill(std::begin(mChan
[chan
].PrevSamples
),
283 std::end(mChan
[chan
].PrevSamples
), 0.0f
);
286 size_t len
= mini(MAX_RESAMPLE_PADDING
*2, prepcount
+toread
-SrcDataEnd
);
287 std::copy_n(SrcData
+SrcDataEnd
, len
, mChan
[chan
].PrevSamples
);
288 std::fill(std::begin(mChan
[chan
].PrevSamples
)+len
,
289 std::end(mChan
[chan
].PrevSamples
), 0.0f
);
292 /* Now resample, and store the result in the output buffer. */
293 const ALfloat
*ResampledData
{mResample(&mState
, SrcData
+MAX_RESAMPLE_PADDING
,
294 DataPosFrac
, increment
, DstData
, DstSize
)};
296 StoreSamples(DstSamples
, ResampledData
, mChan
.size(), mDstType
, DstSize
);
299 /* Update the number of prep samples still available, as well as the
302 DataPosFrac
+= increment
*DstSize
;
303 mSrcPrepCount
= mini(prepcount
+ toread
- (DataPosFrac
>>FRACTIONBITS
),
304 MAX_RESAMPLE_PADDING
*2);
305 mFracOffset
= DataPosFrac
& FRACTIONMASK
;
307 /* Update the src and dst pointers in case there's still more to do. */
308 SamplesIn
+= SrcFrameSize
*(DataPosFrac
>>FRACTIONBITS
);
309 NumSrcSamples
-= mini(NumSrcSamples
, (DataPosFrac
>>FRACTIONBITS
));
311 dst
= static_cast<ALbyte
*>(dst
) + DstFrameSize
*DstSize
;
316 *srcframes
= NumSrcSamples
;
322 ChannelConverterPtr
CreateChannelConverter(DevFmtType srcType
, DevFmtChannels srcChans
, DevFmtChannels dstChans
)
324 if(srcChans
!= dstChans
&& !((srcChans
== DevFmtMono
&& dstChans
== DevFmtStereo
) ||
325 (srcChans
== DevFmtStereo
&& dstChans
== DevFmtMono
)))
328 return ChannelConverterPtr
{new ChannelConverter
{srcType
, srcChans
, dstChans
}};
331 void ChannelConverter::convert(const ALvoid
*src
, ALfloat
*dst
, ALsizei frames
) const
333 if(mSrcChans
== mDstChans
)
335 LoadSamples(dst
, src
, 1u, mSrcType
, frames
*ChannelsFromDevFmt(mSrcChans
, 0));
339 if(mSrcChans
== DevFmtStereo
&& mDstChans
== DevFmtMono
)
343 #define HANDLE_FMT(T) case T: Stereo2Mono<T>(dst, src, frames); break
344 HANDLE_FMT(DevFmtByte
);
345 HANDLE_FMT(DevFmtUByte
);
346 HANDLE_FMT(DevFmtShort
);
347 HANDLE_FMT(DevFmtUShort
);
348 HANDLE_FMT(DevFmtInt
);
349 HANDLE_FMT(DevFmtUInt
);
350 HANDLE_FMT(DevFmtFloat
);
354 else /*if(mSrcChans == DevFmtMono && mDstChans == DevFmtStereo)*/
358 #define HANDLE_FMT(T) case T: Mono2Stereo<T>(dst, src, frames); break
359 HANDLE_FMT(DevFmtByte
);
360 HANDLE_FMT(DevFmtUByte
);
361 HANDLE_FMT(DevFmtShort
);
362 HANDLE_FMT(DevFmtUShort
);
363 HANDLE_FMT(DevFmtInt
);
364 HANDLE_FMT(DevFmtUInt
);
365 HANDLE_FMT(DevFmtFloat
);