15 #include "mixer/defs.h"
23 /* Base template left undefined. Should be marked =delete, but Clang 3.8.1
24 * chokes on that given the inline specializations.
26 template<DevFmtType T
>
27 inline float LoadSample(typename DevFmtTypeTraits
<T
>::Type val
) noexcept
;
29 template<> inline float LoadSample
<DevFmtByte
>(DevFmtTypeTraits
<DevFmtByte
>::Type val
) noexcept
30 { return val
* (1.0f
/128.0f
); }
31 template<> inline float LoadSample
<DevFmtShort
>(DevFmtTypeTraits
<DevFmtShort
>::Type val
) noexcept
32 { return val
* (1.0f
/32768.0f
); }
33 template<> inline float LoadSample
<DevFmtInt
>(DevFmtTypeTraits
<DevFmtInt
>::Type val
) noexcept
34 { return static_cast<float>(val
) * (1.0f
/2147483648.0f
); }
35 template<> inline float LoadSample
<DevFmtFloat
>(DevFmtTypeTraits
<DevFmtFloat
>::Type val
) noexcept
38 template<> inline float LoadSample
<DevFmtUByte
>(DevFmtTypeTraits
<DevFmtUByte
>::Type val
) noexcept
39 { return LoadSample
<DevFmtByte
>(static_cast<ALbyte
>(val
- 128)); }
40 template<> inline float LoadSample
<DevFmtUShort
>(DevFmtTypeTraits
<DevFmtUShort
>::Type val
) noexcept
41 { return LoadSample
<DevFmtShort
>(static_cast<ALshort
>(val
- 32768)); }
42 template<> inline float LoadSample
<DevFmtUInt
>(DevFmtTypeTraits
<DevFmtUInt
>::Type val
) noexcept
43 { return LoadSample
<DevFmtInt
>(static_cast<ALint
>(val
- 2147483648u)); }
46 template<DevFmtType T
>
47 inline void LoadSampleArray(float *RESTRICT dst
, const void *src
, const size_t srcstep
,
48 const size_t samples
) noexcept
50 using SampleType
= typename DevFmtTypeTraits
<T
>::Type
;
52 const SampleType
*ssrc
= static_cast<const SampleType
*>(src
);
53 for(size_t i
{0u};i
< samples
;i
++)
54 dst
[i
] = LoadSample
<T
>(ssrc
[i
*srcstep
]);
57 void LoadSamples(float *dst
, const void *src
, const size_t srcstep
, const DevFmtType srctype
,
58 const size_t samples
) noexcept
60 #define HANDLE_FMT(T) \
61 case T: LoadSampleArray<T>(dst, src, srcstep, samples); break
64 HANDLE_FMT(DevFmtByte
);
65 HANDLE_FMT(DevFmtUByte
);
66 HANDLE_FMT(DevFmtShort
);
67 HANDLE_FMT(DevFmtUShort
);
68 HANDLE_FMT(DevFmtInt
);
69 HANDLE_FMT(DevFmtUInt
);
70 HANDLE_FMT(DevFmtFloat
);
76 template<DevFmtType T
>
77 inline typename DevFmtTypeTraits
<T
>::Type
StoreSample(float) noexcept
;
79 template<> inline ALfloat StoreSample
<DevFmtFloat
>(float val
) noexcept
81 template<> inline ALint StoreSample
<DevFmtInt
>(float val
) noexcept
82 { return fastf2i(clampf(val
*2147483648.0f
, -2147483648.0f
, 2147483520.0f
)); }
83 template<> inline ALshort StoreSample
<DevFmtShort
>(float val
) noexcept
84 { return static_cast<ALshort
>(fastf2i(clampf(val
*32768.0f
, -32768.0f
, 32767.0f
))); }
85 template<> inline ALbyte StoreSample
<DevFmtByte
>(float val
) noexcept
86 { return static_cast<ALbyte
>(fastf2i(clampf(val
*128.0f
, -128.0f
, 127.0f
))); }
88 /* Define unsigned output variations. */
89 template<> inline ALuint StoreSample
<DevFmtUInt
>(float val
) noexcept
90 { return static_cast<ALuint
>(StoreSample
<DevFmtInt
>(val
)) + 2147483648u; }
91 template<> inline ALushort StoreSample
<DevFmtUShort
>(float val
) noexcept
92 { return static_cast<ALushort
>(StoreSample
<DevFmtShort
>(val
) + 32768); }
93 template<> inline ALubyte StoreSample
<DevFmtUByte
>(float val
) noexcept
94 { return static_cast<ALubyte
>(StoreSample
<DevFmtByte
>(val
) + 128); }
96 template<DevFmtType T
>
97 inline void StoreSampleArray(void *dst
, const float *RESTRICT src
, const size_t dststep
,
98 const size_t samples
) noexcept
100 using SampleType
= typename DevFmtTypeTraits
<T
>::Type
;
102 SampleType
*sdst
= static_cast<SampleType
*>(dst
);
103 for(size_t i
{0u};i
< samples
;i
++)
104 sdst
[i
*dststep
] = StoreSample
<T
>(src
[i
]);
108 void StoreSamples(void *dst
, const float *src
, const size_t dststep
, const DevFmtType dsttype
,
109 const size_t samples
) noexcept
111 #define HANDLE_FMT(T) \
112 case T: StoreSampleArray<T>(dst, src, dststep, samples); break
115 HANDLE_FMT(DevFmtByte
);
116 HANDLE_FMT(DevFmtUByte
);
117 HANDLE_FMT(DevFmtShort
);
118 HANDLE_FMT(DevFmtUShort
);
119 HANDLE_FMT(DevFmtInt
);
120 HANDLE_FMT(DevFmtUInt
);
121 HANDLE_FMT(DevFmtFloat
);
127 template<DevFmtType T
>
128 void Mono2Stereo(float *RESTRICT dst
, const void *src
, const size_t frames
) noexcept
130 using SampleType
= typename DevFmtTypeTraits
<T
>::Type
;
132 const SampleType
*ssrc
= static_cast<const SampleType
*>(src
);
133 for(size_t i
{0u};i
< frames
;i
++)
134 dst
[i
*2 + 1] = dst
[i
*2 + 0] = LoadSample
<T
>(ssrc
[i
]) * 0.707106781187f
;
137 template<DevFmtType T
>
138 void Stereo2Mono(float *RESTRICT dst
, const void *src
, const size_t frames
) noexcept
140 using SampleType
= typename DevFmtTypeTraits
<T
>::Type
;
142 const SampleType
*ssrc
= static_cast<const SampleType
*>(src
);
143 for(size_t i
{0u};i
< frames
;i
++)
144 dst
[i
] = (LoadSample
<T
>(ssrc
[i
*2 + 0])+LoadSample
<T
>(ssrc
[i
*2 + 1])) *
150 SampleConverterPtr
CreateSampleConverter(DevFmtType srcType
, DevFmtType dstType
, size_t numchans
,
151 ALuint srcRate
, ALuint dstRate
, Resampler resampler
)
153 if(numchans
< 1 || srcRate
< 1 || dstRate
< 1)
156 SampleConverterPtr converter
{new(FamCount(numchans
)) SampleConverter
{numchans
}};
157 converter
->mSrcType
= srcType
;
158 converter
->mDstType
= dstType
;
159 converter
->mSrcTypeSize
= BytesFromDevFmt(srcType
);
160 converter
->mDstTypeSize
= BytesFromDevFmt(dstType
);
162 converter
->mSrcPrepCount
= 0;
163 converter
->mFracOffset
= 0;
165 /* Have to set the mixer FPU mode since that's what the resampler code expects. */
167 auto step
= static_cast<ALuint
>(
168 mind(srcRate
*double{FRACTIONONE
}/dstRate
+ 0.5, MAX_PITCH
*FRACTIONONE
));
169 converter
->mIncrement
= maxu(step
, 1);
170 if(converter
->mIncrement
== FRACTIONONE
)
171 converter
->mResample
= Resample_
<CopyTag
,CTag
>;
173 converter
->mResample
= PrepareResampler(resampler
, converter
->mIncrement
,
179 ALuint
SampleConverter::availableOut(ALuint srcframes
) const
181 int prepcount
{mSrcPrepCount
};
184 /* Negative prepcount means we need to skip that many input samples. */
185 if(static_cast<ALuint
>(-prepcount
) >= srcframes
)
187 srcframes
-= static_cast<ALuint
>(-prepcount
);
193 /* No output samples if there's no input samples. */
197 if(prepcount
< MAX_RESAMPLER_PADDING
198 && static_cast<ALuint
>(MAX_RESAMPLER_PADDING
- prepcount
) >= srcframes
)
200 /* Not enough input samples to generate an output sample. */
204 auto DataSize64
= static_cast<uint64_t>(prepcount
);
205 DataSize64
+= srcframes
;
206 DataSize64
-= MAX_RESAMPLER_PADDING
;
207 DataSize64
<<= FRACTIONBITS
;
208 DataSize64
-= mFracOffset
;
210 /* If we have a full prep, we can generate at least one sample. */
211 return static_cast<ALuint
>(clampu64((DataSize64
+ mIncrement
-1)/mIncrement
, 1, BUFFERSIZE
));
214 ALuint
SampleConverter::convert(const void **src
, ALuint
*srcframes
, void *dst
, ALuint dstframes
)
216 const ALuint SrcFrameSize
{static_cast<ALuint
>(mChan
.size()) * mSrcTypeSize
};
217 const ALuint DstFrameSize
{static_cast<ALuint
>(mChan
.size()) * mDstTypeSize
};
218 const ALuint increment
{mIncrement
};
219 auto SamplesIn
= static_cast<const al::byte
*>(*src
);
220 ALuint NumSrcSamples
{*srcframes
};
224 while(pos
< dstframes
&& NumSrcSamples
> 0)
226 int prepcount
{mSrcPrepCount
};
229 /* Negative prepcount means we need to skip that many input samples. */
230 if(static_cast<ALuint
>(-prepcount
) >= NumSrcSamples
)
232 mSrcPrepCount
= static_cast<int>(NumSrcSamples
) + prepcount
;
236 SamplesIn
+= SrcFrameSize
*static_cast<ALuint
>(-prepcount
);
237 NumSrcSamples
-= static_cast<ALuint
>(-prepcount
);
241 ALuint toread
{minu(NumSrcSamples
, BUFFERSIZE
- MAX_RESAMPLER_PADDING
)};
243 if(prepcount
< MAX_RESAMPLER_PADDING
244 && static_cast<ALuint
>(MAX_RESAMPLER_PADDING
- prepcount
) >= toread
)
246 /* Not enough input samples to generate an output sample. Store
247 * what we're given for later.
249 for(size_t chan
{0u};chan
< mChan
.size();chan
++)
250 LoadSamples(&mChan
[chan
].PrevSamples
[prepcount
], SamplesIn
+ mSrcTypeSize
*chan
,
251 mChan
.size(), mSrcType
, toread
);
253 mSrcPrepCount
= prepcount
+ static_cast<int>(toread
);
258 float *RESTRICT SrcData
{mSrcSamples
};
259 float *RESTRICT DstData
{mDstSamples
};
260 ALuint DataPosFrac
{mFracOffset
};
261 auto DataSize64
= static_cast<uint64_t>(prepcount
);
262 DataSize64
+= toread
;
263 DataSize64
-= MAX_RESAMPLER_PADDING
;
264 DataSize64
<<= FRACTIONBITS
;
265 DataSize64
-= DataPosFrac
;
267 /* If we have a full prep, we can generate at least one sample. */
268 auto DstSize
= static_cast<ALuint
>(
269 clampu64((DataSize64
+ increment
-1)/increment
, 1, BUFFERSIZE
));
270 DstSize
= minu(DstSize
, dstframes
-pos
);
272 for(size_t chan
{0u};chan
< mChan
.size();chan
++)
274 const al::byte
*SrcSamples
{SamplesIn
+ mSrcTypeSize
*chan
};
275 al::byte
*DstSamples
= static_cast<al::byte
*>(dst
) + mDstTypeSize
*chan
;
277 /* Load the previous samples into the source data first, then the
278 * new samples from the input buffer.
280 std::copy_n(mChan
[chan
].PrevSamples
, prepcount
, SrcData
);
281 LoadSamples(SrcData
+ prepcount
, SrcSamples
, mChan
.size(), mSrcType
, toread
);
283 /* Store as many prep samples for next time as possible, given the
284 * number of output samples being generated.
286 ALuint SrcDataEnd
{(DstSize
*increment
+ DataPosFrac
)>>FRACTIONBITS
};
287 if(SrcDataEnd
>= static_cast<ALuint
>(prepcount
)+toread
)
288 std::fill(std::begin(mChan
[chan
].PrevSamples
),
289 std::end(mChan
[chan
].PrevSamples
), 0.0f
);
292 const size_t len
{minz(al::size(mChan
[chan
].PrevSamples
),
293 static_cast<ALuint
>(prepcount
)+toread
-SrcDataEnd
)};
294 std::copy_n(SrcData
+SrcDataEnd
, len
, mChan
[chan
].PrevSamples
);
295 std::fill(std::begin(mChan
[chan
].PrevSamples
)+len
,
296 std::end(mChan
[chan
].PrevSamples
), 0.0f
);
299 /* Now resample, and store the result in the output buffer. */
300 const float *ResampledData
{mResample(&mState
, SrcData
+(MAX_RESAMPLER_PADDING
>>1),
301 DataPosFrac
, increment
, {DstData
, DstSize
})};
303 StoreSamples(DstSamples
, ResampledData
, mChan
.size(), mDstType
, DstSize
);
306 /* Update the number of prep samples still available, as well as the
309 DataPosFrac
+= increment
*DstSize
;
310 mSrcPrepCount
= mini(prepcount
+ static_cast<int>(toread
- (DataPosFrac
>>FRACTIONBITS
)),
311 MAX_RESAMPLER_PADDING
);
312 mFracOffset
= DataPosFrac
& FRACTIONMASK
;
314 /* Update the src and dst pointers in case there's still more to do. */
315 SamplesIn
+= SrcFrameSize
*(DataPosFrac
>>FRACTIONBITS
);
316 NumSrcSamples
-= minu(NumSrcSamples
, (DataPosFrac
>>FRACTIONBITS
));
318 dst
= static_cast<al::byte
*>(dst
) + DstFrameSize
*DstSize
;
323 *srcframes
= NumSrcSamples
;
329 void ChannelConverter::convert(const void *src
, float *dst
, ALuint frames
) const
331 if(mSrcChans
== DevFmtStereo
&& mDstChans
== DevFmtMono
)
335 #define HANDLE_FMT(T) case T: Stereo2Mono<T>(dst, src, frames); break
336 HANDLE_FMT(DevFmtByte
);
337 HANDLE_FMT(DevFmtUByte
);
338 HANDLE_FMT(DevFmtShort
);
339 HANDLE_FMT(DevFmtUShort
);
340 HANDLE_FMT(DevFmtInt
);
341 HANDLE_FMT(DevFmtUInt
);
342 HANDLE_FMT(DevFmtFloat
);
346 else if(mSrcChans
== DevFmtMono
&& mDstChans
== DevFmtStereo
)
350 #define HANDLE_FMT(T) case T: Mono2Stereo<T>(dst, src, frames); break
351 HANDLE_FMT(DevFmtByte
);
352 HANDLE_FMT(DevFmtUByte
);
353 HANDLE_FMT(DevFmtShort
);
354 HANDLE_FMT(DevFmtUShort
);
355 HANDLE_FMT(DevFmtInt
);
356 HANDLE_FMT(DevFmtUInt
);
357 HANDLE_FMT(DevFmtFloat
);
362 LoadSamples(dst
, src
, 1u, mSrcType
, frames
* ChannelsFromDevFmt(mSrcChans
, 0));