14 #include "fpu_modes.h"
15 #include "mixer/defs.h"
20 /* Base template left undefined. Should be marked =delete, but Clang 3.8.1
21 * chokes on that given the inline specializations.
23 template<DevFmtType T
>
24 inline ALfloat
LoadSample(typename DevFmtTypeTraits
<T
>::Type val
) noexcept
;
26 template<> inline ALfloat LoadSample
<DevFmtByte
>(DevFmtTypeTraits
<DevFmtByte
>::Type val
) noexcept
27 { return val
* (1.0f
/128.0f
); }
28 template<> inline ALfloat LoadSample
<DevFmtShort
>(DevFmtTypeTraits
<DevFmtShort
>::Type val
) noexcept
29 { return val
* (1.0f
/32768.0f
); }
30 template<> inline ALfloat LoadSample
<DevFmtInt
>(DevFmtTypeTraits
<DevFmtInt
>::Type val
) noexcept
31 { return static_cast<float>(val
) * (1.0f
/2147483648.0f
); }
32 template<> inline ALfloat LoadSample
<DevFmtFloat
>(DevFmtTypeTraits
<DevFmtFloat
>::Type val
) noexcept
35 template<> inline ALfloat LoadSample
<DevFmtUByte
>(DevFmtTypeTraits
<DevFmtUByte
>::Type val
) noexcept
36 { return LoadSample
<DevFmtByte
>(static_cast<ALbyte
>(val
- 128)); }
37 template<> inline ALfloat LoadSample
<DevFmtUShort
>(DevFmtTypeTraits
<DevFmtUShort
>::Type val
) noexcept
38 { return LoadSample
<DevFmtShort
>(static_cast<ALshort
>(val
- 32768)); }
39 template<> inline ALfloat LoadSample
<DevFmtUInt
>(DevFmtTypeTraits
<DevFmtUInt
>::Type val
) noexcept
40 { return LoadSample
<DevFmtInt
>(static_cast<ALint
>(val
- 2147483648u)); }
43 template<DevFmtType T
>
44 inline void LoadSampleArray(ALfloat
*RESTRICT dst
, const void *src
, const size_t srcstep
,
45 const size_t samples
) noexcept
47 using SampleType
= typename DevFmtTypeTraits
<T
>::Type
;
49 const SampleType
*ssrc
= static_cast<const SampleType
*>(src
);
50 for(size_t i
{0u};i
< samples
;i
++)
51 dst
[i
] = LoadSample
<T
>(ssrc
[i
*srcstep
]);
54 void LoadSamples(ALfloat
*dst
, const ALvoid
*src
, const size_t srcstep
, const DevFmtType srctype
,
55 const size_t samples
) noexcept
57 #define HANDLE_FMT(T) \
58 case T: LoadSampleArray<T>(dst, src, srcstep, samples); break
61 HANDLE_FMT(DevFmtByte
);
62 HANDLE_FMT(DevFmtUByte
);
63 HANDLE_FMT(DevFmtShort
);
64 HANDLE_FMT(DevFmtUShort
);
65 HANDLE_FMT(DevFmtInt
);
66 HANDLE_FMT(DevFmtUInt
);
67 HANDLE_FMT(DevFmtFloat
);
73 template<DevFmtType T
>
74 inline typename DevFmtTypeTraits
<T
>::Type
StoreSample(ALfloat
) noexcept
;
76 template<> inline ALfloat StoreSample
<DevFmtFloat
>(ALfloat val
) noexcept
78 template<> inline ALint StoreSample
<DevFmtInt
>(ALfloat val
) noexcept
79 { return fastf2i(clampf(val
*2147483648.0f
, -2147483648.0f
, 2147483520.0f
)); }
80 template<> inline ALshort StoreSample
<DevFmtShort
>(ALfloat val
) noexcept
81 { return static_cast<ALshort
>(fastf2i(clampf(val
*32768.0f
, -32768.0f
, 32767.0f
))); }
82 template<> inline ALbyte StoreSample
<DevFmtByte
>(ALfloat val
) noexcept
83 { return static_cast<ALbyte
>(fastf2i(clampf(val
*128.0f
, -128.0f
, 127.0f
))); }
85 /* Define unsigned output variations. */
86 template<> inline ALuint StoreSample
<DevFmtUInt
>(ALfloat val
) noexcept
87 { return static_cast<ALuint
>(StoreSample
<DevFmtInt
>(val
)) + 2147483648u; }
88 template<> inline ALushort StoreSample
<DevFmtUShort
>(ALfloat val
) noexcept
89 { return static_cast<ALushort
>(StoreSample
<DevFmtShort
>(val
) + 32768); }
90 template<> inline ALubyte StoreSample
<DevFmtUByte
>(ALfloat val
) noexcept
91 { return static_cast<ALubyte
>(StoreSample
<DevFmtByte
>(val
) + 128); }
93 template<DevFmtType T
>
94 inline void StoreSampleArray(void *dst
, const ALfloat
*RESTRICT src
, const size_t dststep
,
95 const size_t samples
) noexcept
97 using SampleType
= typename DevFmtTypeTraits
<T
>::Type
;
99 SampleType
*sdst
= static_cast<SampleType
*>(dst
);
100 for(size_t i
{0u};i
< samples
;i
++)
101 sdst
[i
*dststep
] = StoreSample
<T
>(src
[i
]);
105 void StoreSamples(ALvoid
*dst
, const ALfloat
*src
, const size_t dststep
, const DevFmtType dsttype
,
106 const size_t samples
) noexcept
108 #define HANDLE_FMT(T) \
109 case T: StoreSampleArray<T>(dst, src, dststep, samples); break
112 HANDLE_FMT(DevFmtByte
);
113 HANDLE_FMT(DevFmtUByte
);
114 HANDLE_FMT(DevFmtShort
);
115 HANDLE_FMT(DevFmtUShort
);
116 HANDLE_FMT(DevFmtInt
);
117 HANDLE_FMT(DevFmtUInt
);
118 HANDLE_FMT(DevFmtFloat
);
124 template<DevFmtType T
>
125 void Mono2Stereo(ALfloat
*RESTRICT dst
, const void *src
, const size_t frames
) noexcept
127 using SampleType
= typename DevFmtTypeTraits
<T
>::Type
;
129 const SampleType
*ssrc
= static_cast<const SampleType
*>(src
);
130 for(size_t i
{0u};i
< frames
;i
++)
131 dst
[i
*2 + 1] = dst
[i
*2 + 0] = LoadSample
<T
>(ssrc
[i
]) * 0.707106781187f
;
134 template<DevFmtType T
>
135 void Stereo2Mono(ALfloat
*RESTRICT dst
, const void *src
, const size_t frames
) noexcept
137 using SampleType
= typename DevFmtTypeTraits
<T
>::Type
;
139 const SampleType
*ssrc
= static_cast<const SampleType
*>(src
);
140 for(size_t i
{0u};i
< frames
;i
++)
141 dst
[i
] = (LoadSample
<T
>(ssrc
[i
*2 + 0])+LoadSample
<T
>(ssrc
[i
*2 + 1])) *
147 SampleConverterPtr
CreateSampleConverter(DevFmtType srcType
, DevFmtType dstType
, size_t numchans
,
148 ALuint srcRate
, ALuint dstRate
, Resampler resampler
)
150 if(numchans
< 1 || srcRate
< 1 || dstRate
< 1)
153 SampleConverterPtr converter
{new (FamCount
{numchans
}) SampleConverter
{numchans
}};
154 converter
->mSrcType
= srcType
;
155 converter
->mDstType
= dstType
;
156 converter
->mSrcTypeSize
= BytesFromDevFmt(srcType
);
157 converter
->mDstTypeSize
= BytesFromDevFmt(dstType
);
159 converter
->mSrcPrepCount
= 0;
160 converter
->mFracOffset
= 0;
162 /* Have to set the mixer FPU mode since that's what the resampler code expects. */
164 auto step
= static_cast<ALuint
>(
165 mind(srcRate
*double{FRACTIONONE
}/dstRate
+ 0.5, MAX_PITCH
*FRACTIONONE
));
166 converter
->mIncrement
= maxu(step
, 1);
167 if(converter
->mIncrement
== FRACTIONONE
)
168 converter
->mResample
= Resample_
<CopyTag
,CTag
>;
170 converter
->mResample
= PrepareResampler(resampler
, converter
->mIncrement
,
176 ALuint
SampleConverter::availableOut(ALuint srcframes
) const
178 ALint prepcount
{mSrcPrepCount
};
181 /* Negative prepcount means we need to skip that many input samples. */
182 if(static_cast<ALuint
>(-prepcount
) >= srcframes
)
184 srcframes
-= static_cast<ALuint
>(-prepcount
);
190 /* No output samples if there's no input samples. */
194 if(prepcount
< MAX_RESAMPLER_PADDING
195 && static_cast<ALuint
>(MAX_RESAMPLER_PADDING
- prepcount
) >= srcframes
)
197 /* Not enough input samples to generate an output sample. */
201 auto DataSize64
= static_cast<uint64_t>(prepcount
);
202 DataSize64
+= srcframes
;
203 DataSize64
-= MAX_RESAMPLER_PADDING
;
204 DataSize64
<<= FRACTIONBITS
;
205 DataSize64
-= mFracOffset
;
207 /* If we have a full prep, we can generate at least one sample. */
208 return static_cast<ALuint
>(clampu64((DataSize64
+ mIncrement
-1)/mIncrement
, 1, BUFFERSIZE
));
211 ALuint
SampleConverter::convert(const ALvoid
**src
, ALuint
*srcframes
, ALvoid
*dst
, ALuint dstframes
)
213 const ALuint SrcFrameSize
{static_cast<ALuint
>(mChan
.size()) * mSrcTypeSize
};
214 const ALuint DstFrameSize
{static_cast<ALuint
>(mChan
.size()) * mDstTypeSize
};
215 const ALuint increment
{mIncrement
};
216 auto SamplesIn
= static_cast<const al::byte
*>(*src
);
217 ALuint NumSrcSamples
{*srcframes
};
221 while(pos
< dstframes
&& NumSrcSamples
> 0)
223 ALint prepcount
{mSrcPrepCount
};
226 /* Negative prepcount means we need to skip that many input samples. */
227 if(static_cast<ALuint
>(-prepcount
) >= NumSrcSamples
)
229 mSrcPrepCount
= static_cast<ALint
>(NumSrcSamples
) + prepcount
;
233 SamplesIn
+= SrcFrameSize
*static_cast<ALuint
>(-prepcount
);
234 NumSrcSamples
-= static_cast<ALuint
>(-prepcount
);
238 ALuint toread
{minu(NumSrcSamples
, BUFFERSIZE
- MAX_RESAMPLER_PADDING
)};
240 if(prepcount
< MAX_RESAMPLER_PADDING
241 && static_cast<ALuint
>(MAX_RESAMPLER_PADDING
- prepcount
) >= toread
)
243 /* Not enough input samples to generate an output sample. Store
244 * what we're given for later.
246 for(size_t chan
{0u};chan
< mChan
.size();chan
++)
247 LoadSamples(&mChan
[chan
].PrevSamples
[prepcount
], SamplesIn
+ mSrcTypeSize
*chan
,
248 mChan
.size(), mSrcType
, toread
);
250 mSrcPrepCount
= prepcount
+ static_cast<ALint
>(toread
);
255 ALfloat
*RESTRICT SrcData
{mSrcSamples
};
256 ALfloat
*RESTRICT DstData
{mDstSamples
};
257 ALuint DataPosFrac
{mFracOffset
};
258 auto DataSize64
= static_cast<uint64_t>(prepcount
);
259 DataSize64
+= toread
;
260 DataSize64
-= MAX_RESAMPLER_PADDING
;
261 DataSize64
<<= FRACTIONBITS
;
262 DataSize64
-= DataPosFrac
;
264 /* If we have a full prep, we can generate at least one sample. */
265 auto DstSize
= static_cast<ALuint
>(
266 clampu64((DataSize64
+ increment
-1)/increment
, 1, BUFFERSIZE
));
267 DstSize
= minu(DstSize
, dstframes
-pos
);
269 for(size_t chan
{0u};chan
< mChan
.size();chan
++)
271 const al::byte
*SrcSamples
{SamplesIn
+ mSrcTypeSize
*chan
};
272 al::byte
*DstSamples
= static_cast<al::byte
*>(dst
) + mDstTypeSize
*chan
;
274 /* Load the previous samples into the source data first, then the
275 * new samples from the input buffer.
277 std::copy_n(mChan
[chan
].PrevSamples
, prepcount
, SrcData
);
278 LoadSamples(SrcData
+ prepcount
, SrcSamples
, mChan
.size(), mSrcType
, toread
);
280 /* Store as many prep samples for next time as possible, given the
281 * number of output samples being generated.
283 ALuint SrcDataEnd
{(DstSize
*increment
+ DataPosFrac
)>>FRACTIONBITS
};
284 if(SrcDataEnd
>= static_cast<ALuint
>(prepcount
)+toread
)
285 std::fill(std::begin(mChan
[chan
].PrevSamples
),
286 std::end(mChan
[chan
].PrevSamples
), 0.0f
);
289 const size_t len
{minz(al::size(mChan
[chan
].PrevSamples
),
290 static_cast<ALuint
>(prepcount
)+toread
-SrcDataEnd
)};
291 std::copy_n(SrcData
+SrcDataEnd
, len
, mChan
[chan
].PrevSamples
);
292 std::fill(std::begin(mChan
[chan
].PrevSamples
)+len
,
293 std::end(mChan
[chan
].PrevSamples
), 0.0f
);
296 /* Now resample, and store the result in the output buffer. */
297 const ALfloat
*ResampledData
{mResample(&mState
, SrcData
+(MAX_RESAMPLER_PADDING
>>1),
298 DataPosFrac
, increment
, {DstData
, DstSize
})};
300 StoreSamples(DstSamples
, ResampledData
, mChan
.size(), mDstType
, DstSize
);
303 /* Update the number of prep samples still available, as well as the
306 DataPosFrac
+= increment
*DstSize
;
307 mSrcPrepCount
= mini(prepcount
+ static_cast<ALint
>(toread
- (DataPosFrac
>>FRACTIONBITS
)),
308 MAX_RESAMPLER_PADDING
);
309 mFracOffset
= DataPosFrac
& FRACTIONMASK
;
311 /* Update the src and dst pointers in case there's still more to do. */
312 SamplesIn
+= SrcFrameSize
*(DataPosFrac
>>FRACTIONBITS
);
313 NumSrcSamples
-= minu(NumSrcSamples
, (DataPosFrac
>>FRACTIONBITS
));
315 dst
= static_cast<al::byte
*>(dst
) + DstFrameSize
*DstSize
;
320 *srcframes
= NumSrcSamples
;
326 void ChannelConverter::convert(const ALvoid
*src
, ALfloat
*dst
, ALuint frames
) const
328 if(mSrcChans
== DevFmtStereo
&& mDstChans
== DevFmtMono
)
332 #define HANDLE_FMT(T) case T: Stereo2Mono<T>(dst, src, frames); break
333 HANDLE_FMT(DevFmtByte
);
334 HANDLE_FMT(DevFmtUByte
);
335 HANDLE_FMT(DevFmtShort
);
336 HANDLE_FMT(DevFmtUShort
);
337 HANDLE_FMT(DevFmtInt
);
338 HANDLE_FMT(DevFmtUInt
);
339 HANDLE_FMT(DevFmtFloat
);
343 else if(mSrcChans
== DevFmtMono
&& mDstChans
== DevFmtStereo
)
347 #define HANDLE_FMT(T) case T: Mono2Stereo<T>(dst, src, frames); break
348 HANDLE_FMT(DevFmtByte
);
349 HANDLE_FMT(DevFmtUByte
);
350 HANDLE_FMT(DevFmtShort
);
351 HANDLE_FMT(DevFmtUShort
);
352 HANDLE_FMT(DevFmtInt
);
353 HANDLE_FMT(DevFmtUInt
);
354 HANDLE_FMT(DevFmtFloat
);
359 LoadSamples(dst
, src
, 1u, mSrcType
, frames
* ChannelsFromDevFmt(mSrcChans
, 0));