Move some ambisonic-related macros to a separate header
[openal-soft.git] / Alc / converter.cpp
blob3effddd8d98c39b96d2d0f59f3b8c4e2cb4afb03
2 #include "config.h"
4 #include "converter.h"
6 #include <algorithm>
8 #include "fpu_modes.h"
9 #include "mixer/defs.h"
12 namespace {
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)
27 { return 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, ALint 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, ALint srcstep, enum DevFmtType srctype,
48 ALsizei samples)
50 #define HANDLE_FMT(T) \
51 case T: LoadSampleArray<T>(dst, src, srcstep, samples); break
52 switch(srctype)
54 HANDLE_FMT(DevFmtByte);
55 HANDLE_FMT(DevFmtUByte);
56 HANDLE_FMT(DevFmtShort);
57 HANDLE_FMT(DevFmtUShort);
58 HANDLE_FMT(DevFmtInt);
59 HANDLE_FMT(DevFmtUInt);
60 HANDLE_FMT(DevFmtFloat);
62 #undef HANDLE_FMT
66 template<DevFmtType T>
67 inline typename DevFmtTypeTraits<T>::Type StoreSample(ALfloat);
69 template<> inline ALfloat StoreSample<DevFmtFloat>(ALfloat val)
70 { return val; }
71 template<> inline ALint StoreSample<DevFmtInt>(ALfloat val)
72 { return fastf2i(clampf(val*16777216.0f, -16777216.0f, 16777215.0f))<<7; }
73 template<> inline ALshort StoreSample<DevFmtShort>(ALfloat val)
74 { return fastf2i(clampf(val*32768.0f, -32768.0f, 32767.0f)); }
75 template<> inline ALbyte StoreSample<DevFmtByte>(ALfloat val)
76 { return fastf2i(clampf(val*128.0f, -128.0f, 127.0f)); }
78 /* Define unsigned output variations. */
79 template<> inline ALuint StoreSample<DevFmtUInt>(ALfloat val)
80 { return StoreSample<DevFmtInt>(val) + 2147483648u; }
81 template<> inline ALushort StoreSample<DevFmtUShort>(ALfloat val)
82 { return StoreSample<DevFmtShort>(val) + 32768; }
83 template<> inline ALubyte StoreSample<DevFmtUByte>(ALfloat val)
84 { return StoreSample<DevFmtByte>(val) + 128; }
86 template<DevFmtType T>
87 inline void StoreSampleArray(void *dst, const ALfloat *RESTRICT src, ALint dststep,
88 ALsizei samples)
90 using SampleType = typename DevFmtTypeTraits<T>::Type;
92 SampleType *sdst = static_cast<SampleType*>(dst);
93 for(ALsizei i{0};i < samples;i++)
94 sdst[i*dststep] = StoreSample<T>(src[i]);
98 void StoreSamples(ALvoid *dst, const ALfloat *src, ALint dststep, enum DevFmtType dsttype, ALsizei samples)
100 #define HANDLE_FMT(T) \
101 case T: StoreSampleArray<T>(dst, src, dststep, samples); break
102 switch(dsttype)
104 HANDLE_FMT(DevFmtByte);
105 HANDLE_FMT(DevFmtUByte);
106 HANDLE_FMT(DevFmtShort);
107 HANDLE_FMT(DevFmtUShort);
108 HANDLE_FMT(DevFmtInt);
109 HANDLE_FMT(DevFmtUInt);
110 HANDLE_FMT(DevFmtFloat);
112 #undef HANDLE_FMT
116 template<DevFmtType T>
117 void Mono2Stereo(ALfloat *RESTRICT dst, const void *src, ALsizei frames)
119 using SampleType = typename DevFmtTypeTraits<T>::Type;
121 const SampleType *ssrc = static_cast<const SampleType*>(src);
122 for(ALsizei i{0};i < frames;i++)
123 dst[i*2 + 1] = dst[i*2 + 0] = LoadSample<T>(ssrc[i]) * 0.707106781187f;
126 template<DevFmtType T>
127 void Stereo2Mono(ALfloat *RESTRICT dst, const void *src, ALsizei frames)
129 using SampleType = typename DevFmtTypeTraits<T>::Type;
131 const SampleType *ssrc = static_cast<const SampleType*>(src);
132 for(ALsizei i{0};i < frames;i++)
133 dst[i] = (LoadSample<T>(ssrc[i*2 + 0])+LoadSample<T>(ssrc[i*2 + 1])) *
134 0.707106781187f;
137 } // namespace
139 SampleConverter *CreateSampleConverter(enum DevFmtType srcType, enum DevFmtType dstType,
140 ALsizei numchans, ALsizei srcRate, ALsizei dstRate,
141 Resampler resampler)
143 if(numchans <= 0 || srcRate <= 0 || dstRate <= 0)
144 return nullptr;
146 size_t alloc_size{FAM_SIZE(SampleConverter, Chan, numchans)};
147 auto converter = new (al_calloc(16, alloc_size)) SampleConverter{};
148 converter->mSrcType = srcType;
149 converter->mDstType = dstType;
150 converter->mNumChannels = numchans;
151 converter->mSrcTypeSize = BytesFromDevFmt(srcType);
152 converter->mDstTypeSize = BytesFromDevFmt(dstType);
154 converter->mSrcPrepCount = 0;
155 converter->mFracOffset = 0;
157 /* Have to set the mixer FPU mode since that's what the resampler code expects. */
158 FPUCtl mixer_mode{};
159 auto step = static_cast<ALsizei>(
160 mind((ALdouble)srcRate/dstRate*FRACTIONONE + 0.5, MAX_PITCH*FRACTIONONE));
161 converter->mIncrement = maxi(step, 1);
162 if(converter->mIncrement == FRACTIONONE)
163 converter->mResample = Resample_copy_C;
164 else
166 if(resampler == BSinc24Resampler)
167 BsincPrepare(converter->mIncrement, &converter->mState.bsinc, &bsinc24);
168 else if(resampler == BSinc12Resampler)
169 BsincPrepare(converter->mIncrement, &converter->mState.bsinc, &bsinc12);
170 converter->mResample = SelectResampler(resampler);
173 return converter;
176 void DestroySampleConverter(SampleConverter **converter)
178 if(converter)
180 delete *converter;
181 *converter = nullptr;
186 ALsizei SampleConverterAvailableOut(SampleConverter *converter, ALsizei srcframes)
188 ALint prepcount{converter->mSrcPrepCount};
189 if(prepcount < 0)
191 /* Negative prepcount means we need to skip that many input samples. */
192 if(-prepcount >= srcframes)
193 return 0;
194 srcframes += prepcount;
195 prepcount = 0;
198 if(srcframes < 1)
200 /* No output samples if there's no input samples. */
201 return 0;
204 if(prepcount < MAX_RESAMPLE_PADDING*2 &&
205 MAX_RESAMPLE_PADDING*2 - prepcount >= srcframes)
207 /* Not enough input samples to generate an output sample. */
208 return 0;
211 ALsizei increment{converter->mIncrement};
212 ALsizei DataPosFrac{converter->mFracOffset};
213 auto DataSize64 = static_cast<ALuint64>(prepcount);
214 DataSize64 += srcframes;
215 DataSize64 -= MAX_RESAMPLE_PADDING*2;
216 DataSize64 <<= FRACTIONBITS;
217 DataSize64 -= DataPosFrac;
219 /* If we have a full prep, we can generate at least one sample. */
220 return (ALsizei)clampu64((DataSize64 + increment-1)/increment, 1, BUFFERSIZE);
223 ALsizei SampleConverterInput(SampleConverter *converter, const ALvoid **src, ALsizei *srcframes, ALvoid *dst, ALsizei dstframes)
225 const ALsizei SrcFrameSize{converter->mNumChannels * converter->mSrcTypeSize};
226 const ALsizei DstFrameSize{converter->mNumChannels * converter->mDstTypeSize};
227 const ALsizei increment{converter->mIncrement};
228 auto SamplesIn = static_cast<const ALbyte*>(*src);
229 ALsizei NumSrcSamples{*srcframes};
231 FPUCtl mixer_mode{};
232 ALsizei pos{0};
233 while(pos < dstframes && NumSrcSamples > 0)
235 ALint prepcount{converter->mSrcPrepCount};
236 if(prepcount < 0)
238 /* Negative prepcount means we need to skip that many input samples. */
239 if(-prepcount >= NumSrcSamples)
241 converter->mSrcPrepCount = prepcount + NumSrcSamples;
242 NumSrcSamples = 0;
243 break;
245 SamplesIn += SrcFrameSize*-prepcount;
246 NumSrcSamples += prepcount;
247 converter->mSrcPrepCount = 0;
248 continue;
250 ALint toread{mini(NumSrcSamples, BUFFERSIZE - MAX_RESAMPLE_PADDING*2)};
252 if(prepcount < MAX_RESAMPLE_PADDING*2 &&
253 MAX_RESAMPLE_PADDING*2 - prepcount >= toread)
255 /* Not enough input samples to generate an output sample. Store
256 * what we're given for later.
258 for(ALsizei chan{0};chan < converter->mNumChannels;chan++)
259 LoadSamples(&converter->Chan[chan].mPrevSamples[prepcount],
260 SamplesIn + converter->mSrcTypeSize*chan,
261 converter->mNumChannels, converter->mSrcType, toread
264 converter->mSrcPrepCount = prepcount + toread;
265 NumSrcSamples = 0;
266 break;
269 ALfloat *RESTRICT SrcData{converter->mSrcSamples};
270 ALfloat *RESTRICT DstData{converter->mDstSamples};
271 ALsizei DataPosFrac{converter->mFracOffset};
272 auto DataSize64 = static_cast<ALuint64>(prepcount);
273 DataSize64 += toread;
274 DataSize64 -= MAX_RESAMPLE_PADDING*2;
275 DataSize64 <<= FRACTIONBITS;
276 DataSize64 -= DataPosFrac;
278 /* If we have a full prep, we can generate at least one sample. */
279 auto DstSize = static_cast<ALsizei>(
280 clampu64((DataSize64 + increment-1)/increment, 1, BUFFERSIZE));
281 DstSize = mini(DstSize, dstframes-pos);
283 for(ALsizei chan{0};chan < converter->mNumChannels;chan++)
285 const ALbyte *SrcSamples = SamplesIn + converter->mSrcTypeSize*chan;
286 ALbyte *DstSamples = (ALbyte*)dst + converter->mDstTypeSize*chan;
288 /* Load the previous samples into the source data first, then the
289 * new samples from the input buffer.
291 std::copy_n(converter->Chan[chan].mPrevSamples, prepcount, SrcData);
292 LoadSamples(SrcData + prepcount, SrcSamples,
293 converter->mNumChannels, converter->mSrcType, toread
296 /* Store as many prep samples for next time as possible, given the
297 * number of output samples being generated.
299 ALsizei SrcDataEnd{(DstSize*increment + DataPosFrac)>>FRACTIONBITS};
300 if(SrcDataEnd >= prepcount+toread)
301 std::fill(std::begin(converter->Chan[chan].mPrevSamples),
302 std::end(converter->Chan[chan].mPrevSamples), 0.0f);
303 else
305 size_t len = mini(MAX_RESAMPLE_PADDING*2, prepcount+toread-SrcDataEnd);
306 std::copy_n(SrcData+SrcDataEnd, len, converter->Chan[chan].mPrevSamples);
307 std::fill(std::begin(converter->Chan[chan].mPrevSamples)+len,
308 std::end(converter->Chan[chan].mPrevSamples), 0.0f);
311 /* Now resample, and store the result in the output buffer. */
312 const ALfloat *ResampledData{converter->mResample(&converter->mState,
313 SrcData+MAX_RESAMPLE_PADDING, DataPosFrac, increment,
314 DstData, DstSize
317 StoreSamples(DstSamples, ResampledData, converter->mNumChannels,
318 converter->mDstType, DstSize);
321 /* Update the number of prep samples still available, as well as the
322 * fractional offset.
324 DataPosFrac += increment*DstSize;
325 converter->mSrcPrepCount = mini(prepcount + toread - (DataPosFrac>>FRACTIONBITS),
326 MAX_RESAMPLE_PADDING*2);
327 converter->mFracOffset = DataPosFrac & FRACTIONMASK;
329 /* Update the src and dst pointers in case there's still more to do. */
330 SamplesIn += SrcFrameSize*(DataPosFrac>>FRACTIONBITS);
331 NumSrcSamples -= mini(NumSrcSamples, (DataPosFrac>>FRACTIONBITS));
333 dst = (ALbyte*)dst + DstFrameSize*DstSize;
334 pos += DstSize;
337 *src = SamplesIn;
338 *srcframes = NumSrcSamples;
340 return pos;
344 ChannelConverter *CreateChannelConverter(DevFmtType srcType, DevFmtChannels srcChans, DevFmtChannels dstChans)
346 if(srcChans != dstChans && !((srcChans == DevFmtMono && dstChans == DevFmtStereo) ||
347 (srcChans == DevFmtStereo && dstChans == DevFmtMono)))
348 return nullptr;
350 return new ChannelConverter{srcType, srcChans, dstChans};
353 void DestroyChannelConverter(ChannelConverter **converter)
355 if(converter)
357 delete *converter;
358 *converter = nullptr;
362 void ChannelConverterInput(ChannelConverter *converter, const ALvoid *src, ALfloat *dst, ALsizei frames)
364 if(converter->mSrcChans == converter->mDstChans)
366 LoadSamples(dst, src, 1, converter->mSrcType,
367 frames*ChannelsFromDevFmt(converter->mSrcChans, 0));
368 return;
371 if(converter->mSrcChans == DevFmtStereo && converter->mDstChans == DevFmtMono)
373 switch(converter->mSrcType)
375 #define HANDLE_FMT(T) case T: Stereo2Mono<T>(dst, src, frames); break
376 HANDLE_FMT(DevFmtByte);
377 HANDLE_FMT(DevFmtUByte);
378 HANDLE_FMT(DevFmtShort);
379 HANDLE_FMT(DevFmtUShort);
380 HANDLE_FMT(DevFmtInt);
381 HANDLE_FMT(DevFmtUInt);
382 HANDLE_FMT(DevFmtFloat);
383 #undef HANDLE_FMT
386 else /*if(converter->mSrcChans == DevFmtMono && converter->mDstChans == DevFmtStereo)*/
388 switch(converter->mSrcType)
390 #define HANDLE_FMT(T) case T: Mono2Stereo<T>(dst, src, frames); break
391 HANDLE_FMT(DevFmtByte);
392 HANDLE_FMT(DevFmtUByte);
393 HANDLE_FMT(DevFmtShort);
394 HANDLE_FMT(DevFmtUShort);
395 HANDLE_FMT(DevFmtInt);
396 HANDLE_FMT(DevFmtUInt);
397 HANDLE_FMT(DevFmtFloat);
398 #undef HANDLE_FMT