🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

369 lines
13 KiB

  1. #include "config.h"
  2. #include "converter.h"
  3. #include <algorithm>
  4. #include "fpu_modes.h"
  5. #include "mixer/defs.h"
  6. namespace {
  7. /* Base template left undefined. Should be marked =delete, but Clang 3.8.1
  8. * chokes on that given the inline specializations.
  9. */
  10. template<DevFmtType T>
  11. inline ALfloat LoadSample(typename DevFmtTypeTraits<T>::Type val);
  12. template<> inline ALfloat LoadSample<DevFmtByte>(DevFmtTypeTraits<DevFmtByte>::Type val)
  13. { return val * (1.0f/128.0f); }
  14. template<> inline ALfloat LoadSample<DevFmtShort>(DevFmtTypeTraits<DevFmtShort>::Type val)
  15. { return val * (1.0f/32768.0f); }
  16. template<> inline ALfloat LoadSample<DevFmtInt>(DevFmtTypeTraits<DevFmtInt>::Type val)
  17. { return val * (1.0f/2147483648.0f); }
  18. template<> inline ALfloat LoadSample<DevFmtFloat>(DevFmtTypeTraits<DevFmtFloat>::Type val)
  19. { return val; }
  20. template<> inline ALfloat LoadSample<DevFmtUByte>(DevFmtTypeTraits<DevFmtUByte>::Type val)
  21. { return LoadSample<DevFmtByte>(val - 128); }
  22. template<> inline ALfloat LoadSample<DevFmtUShort>(DevFmtTypeTraits<DevFmtUShort>::Type val)
  23. { return LoadSample<DevFmtByte>(val - 32768); }
  24. template<> inline ALfloat LoadSample<DevFmtUInt>(DevFmtTypeTraits<DevFmtUInt>::Type val)
  25. { return LoadSample<DevFmtByte>(val - 2147483648u); }
  26. template<DevFmtType T>
  27. inline void LoadSampleArray(ALfloat *RESTRICT dst, const void *src, size_t srcstep, ALsizei samples)
  28. {
  29. using SampleType = typename DevFmtTypeTraits<T>::Type;
  30. const SampleType *ssrc = static_cast<const SampleType*>(src);
  31. for(ALsizei i{0};i < samples;i++)
  32. dst[i] = LoadSample<T>(ssrc[i*srcstep]);
  33. }
  34. void LoadSamples(ALfloat *dst, const ALvoid *src, size_t srcstep, DevFmtType srctype, ALsizei samples)
  35. {
  36. #define HANDLE_FMT(T) \
  37. case T: LoadSampleArray<T>(dst, src, srcstep, samples); break
  38. switch(srctype)
  39. {
  40. HANDLE_FMT(DevFmtByte);
  41. HANDLE_FMT(DevFmtUByte);
  42. HANDLE_FMT(DevFmtShort);
  43. HANDLE_FMT(DevFmtUShort);
  44. HANDLE_FMT(DevFmtInt);
  45. HANDLE_FMT(DevFmtUInt);
  46. HANDLE_FMT(DevFmtFloat);
  47. }
  48. #undef HANDLE_FMT
  49. }
  50. template<DevFmtType T>
  51. inline typename DevFmtTypeTraits<T>::Type StoreSample(ALfloat);
  52. template<> inline ALfloat StoreSample<DevFmtFloat>(ALfloat val)
  53. { return val; }
  54. template<> inline ALint StoreSample<DevFmtInt>(ALfloat val)
  55. { return fastf2i(clampf(val*2147483648.0f, -2147483648.0f, 2147483520.0f)); }
  56. template<> inline ALshort StoreSample<DevFmtShort>(ALfloat val)
  57. { return fastf2i(clampf(val*32768.0f, -32768.0f, 32767.0f)); }
  58. template<> inline ALbyte StoreSample<DevFmtByte>(ALfloat val)
  59. { return fastf2i(clampf(val*128.0f, -128.0f, 127.0f)); }
  60. /* Define unsigned output variations. */
  61. template<> inline ALuint StoreSample<DevFmtUInt>(ALfloat val)
  62. { return StoreSample<DevFmtInt>(val) + 2147483648u; }
  63. template<> inline ALushort StoreSample<DevFmtUShort>(ALfloat val)
  64. { return StoreSample<DevFmtShort>(val) + 32768; }
  65. template<> inline ALubyte StoreSample<DevFmtUByte>(ALfloat val)
  66. { return StoreSample<DevFmtByte>(val) + 128; }
  67. template<DevFmtType T>
  68. inline void StoreSampleArray(void *dst, const ALfloat *RESTRICT src, size_t dststep,
  69. ALsizei samples)
  70. {
  71. using SampleType = typename DevFmtTypeTraits<T>::Type;
  72. SampleType *sdst = static_cast<SampleType*>(dst);
  73. for(ALsizei i{0};i < samples;i++)
  74. sdst[i*dststep] = StoreSample<T>(src[i]);
  75. }
  76. void StoreSamples(ALvoid *dst, const ALfloat *src, size_t dststep, DevFmtType dsttype, ALsizei samples)
  77. {
  78. #define HANDLE_FMT(T) \
  79. case T: StoreSampleArray<T>(dst, src, dststep, samples); break
  80. switch(dsttype)
  81. {
  82. HANDLE_FMT(DevFmtByte);
  83. HANDLE_FMT(DevFmtUByte);
  84. HANDLE_FMT(DevFmtShort);
  85. HANDLE_FMT(DevFmtUShort);
  86. HANDLE_FMT(DevFmtInt);
  87. HANDLE_FMT(DevFmtUInt);
  88. HANDLE_FMT(DevFmtFloat);
  89. }
  90. #undef HANDLE_FMT
  91. }
  92. template<DevFmtType T>
  93. void Mono2Stereo(ALfloat *RESTRICT dst, const void *src, ALsizei frames)
  94. {
  95. using SampleType = typename DevFmtTypeTraits<T>::Type;
  96. const SampleType *ssrc = static_cast<const SampleType*>(src);
  97. for(ALsizei i{0};i < frames;i++)
  98. dst[i*2 + 1] = dst[i*2 + 0] = LoadSample<T>(ssrc[i]) * 0.707106781187f;
  99. }
  100. template<DevFmtType T>
  101. void Stereo2Mono(ALfloat *RESTRICT dst, const void *src, ALsizei frames)
  102. {
  103. using SampleType = typename DevFmtTypeTraits<T>::Type;
  104. const SampleType *ssrc = static_cast<const SampleType*>(src);
  105. for(ALsizei i{0};i < frames;i++)
  106. dst[i] = (LoadSample<T>(ssrc[i*2 + 0])+LoadSample<T>(ssrc[i*2 + 1])) *
  107. 0.707106781187f;
  108. }
  109. } // namespace
  110. SampleConverterPtr CreateSampleConverter(DevFmtType srcType, DevFmtType dstType, ALsizei numchans,
  111. ALsizei srcRate, ALsizei dstRate, Resampler resampler)
  112. {
  113. if(numchans <= 0 || srcRate <= 0 || dstRate <= 0)
  114. return nullptr;
  115. void *ptr{al_calloc(16, SampleConverter::Sizeof(numchans))};
  116. SampleConverterPtr converter{new (ptr) SampleConverter{static_cast<size_t>(numchans)}};
  117. converter->mSrcType = srcType;
  118. converter->mDstType = dstType;
  119. converter->mSrcTypeSize = BytesFromDevFmt(srcType);
  120. converter->mDstTypeSize = BytesFromDevFmt(dstType);
  121. converter->mSrcPrepCount = 0;
  122. converter->mFracOffset = 0;
  123. /* Have to set the mixer FPU mode since that's what the resampler code expects. */
  124. FPUCtl mixer_mode{};
  125. auto step = static_cast<ALsizei>(
  126. mind(static_cast<ALdouble>(srcRate)/dstRate*FRACTIONONE + 0.5, MAX_PITCH*FRACTIONONE));
  127. converter->mIncrement = maxi(step, 1);
  128. if(converter->mIncrement == FRACTIONONE)
  129. converter->mResample = Resample_<CopyTag,CTag>;
  130. else
  131. {
  132. if(resampler == BSinc24Resampler)
  133. BsincPrepare(converter->mIncrement, &converter->mState.bsinc, &bsinc24);
  134. else if(resampler == BSinc12Resampler)
  135. BsincPrepare(converter->mIncrement, &converter->mState.bsinc, &bsinc12);
  136. converter->mResample = SelectResampler(resampler);
  137. }
  138. return converter;
  139. }
  140. ALsizei SampleConverter::availableOut(ALsizei srcframes) const
  141. {
  142. ALint prepcount{mSrcPrepCount};
  143. if(prepcount < 0)
  144. {
  145. /* Negative prepcount means we need to skip that many input samples. */
  146. if(-prepcount >= srcframes)
  147. return 0;
  148. srcframes += prepcount;
  149. prepcount = 0;
  150. }
  151. if(srcframes < 1)
  152. {
  153. /* No output samples if there's no input samples. */
  154. return 0;
  155. }
  156. if(prepcount < MAX_RESAMPLE_PADDING*2 &&
  157. MAX_RESAMPLE_PADDING*2 - prepcount >= srcframes)
  158. {
  159. /* Not enough input samples to generate an output sample. */
  160. return 0;
  161. }
  162. auto DataSize64 = static_cast<uint64_t>(prepcount);
  163. DataSize64 += srcframes;
  164. DataSize64 -= MAX_RESAMPLE_PADDING*2;
  165. DataSize64 <<= FRACTIONBITS;
  166. DataSize64 -= mFracOffset;
  167. /* If we have a full prep, we can generate at least one sample. */
  168. return static_cast<ALsizei>(clampu64((DataSize64 + mIncrement-1)/mIncrement, 1, BUFFERSIZE));
  169. }
  170. ALsizei SampleConverter::convert(const ALvoid **src, ALsizei *srcframes, ALvoid *dst, ALsizei dstframes)
  171. {
  172. const ALsizei SrcFrameSize{static_cast<ALsizei>(mChan.size()) * mSrcTypeSize};
  173. const ALsizei DstFrameSize{static_cast<ALsizei>(mChan.size()) * mDstTypeSize};
  174. const ALsizei increment{mIncrement};
  175. auto SamplesIn = static_cast<const ALbyte*>(*src);
  176. ALsizei NumSrcSamples{*srcframes};
  177. FPUCtl mixer_mode{};
  178. ALsizei pos{0};
  179. while(pos < dstframes && NumSrcSamples > 0)
  180. {
  181. ALint prepcount{mSrcPrepCount};
  182. if(prepcount < 0)
  183. {
  184. /* Negative prepcount means we need to skip that many input samples. */
  185. if(-prepcount >= NumSrcSamples)
  186. {
  187. mSrcPrepCount = prepcount + NumSrcSamples;
  188. NumSrcSamples = 0;
  189. break;
  190. }
  191. SamplesIn += SrcFrameSize*-prepcount;
  192. NumSrcSamples += prepcount;
  193. mSrcPrepCount = 0;
  194. continue;
  195. }
  196. ALint toread{mini(NumSrcSamples, BUFFERSIZE - MAX_RESAMPLE_PADDING*2)};
  197. if(prepcount < MAX_RESAMPLE_PADDING*2 &&
  198. MAX_RESAMPLE_PADDING*2 - prepcount >= toread)
  199. {
  200. /* Not enough input samples to generate an output sample. Store
  201. * what we're given for later.
  202. */
  203. for(size_t chan{0u};chan < mChan.size();chan++)
  204. LoadSamples(&mChan[chan].PrevSamples[prepcount], SamplesIn + mSrcTypeSize*chan,
  205. mChan.size(), mSrcType, toread);
  206. mSrcPrepCount = prepcount + toread;
  207. NumSrcSamples = 0;
  208. break;
  209. }
  210. ALfloat *RESTRICT SrcData{mSrcSamples};
  211. ALfloat *RESTRICT DstData{mDstSamples};
  212. ALsizei DataPosFrac{mFracOffset};
  213. auto DataSize64 = static_cast<uint64_t>(prepcount);
  214. DataSize64 += toread;
  215. DataSize64 -= MAX_RESAMPLE_PADDING*2;
  216. DataSize64 <<= FRACTIONBITS;
  217. DataSize64 -= DataPosFrac;
  218. /* If we have a full prep, we can generate at least one sample. */
  219. auto DstSize = static_cast<ALsizei>(
  220. clampu64((DataSize64 + increment-1)/increment, 1, BUFFERSIZE));
  221. DstSize = mini(DstSize, dstframes-pos);
  222. for(size_t chan{0u};chan < mChan.size();chan++)
  223. {
  224. const ALbyte *SrcSamples = SamplesIn + mSrcTypeSize*chan;
  225. ALbyte *DstSamples = static_cast<ALbyte*>(dst) + mDstTypeSize*chan;
  226. /* Load the previous samples into the source data first, then the
  227. * new samples from the input buffer.
  228. */
  229. std::copy_n(mChan[chan].PrevSamples, prepcount, SrcData);
  230. LoadSamples(SrcData + prepcount, SrcSamples, mChan.size(), mSrcType, toread);
  231. /* Store as many prep samples for next time as possible, given the
  232. * number of output samples being generated.
  233. */
  234. ALsizei SrcDataEnd{(DstSize*increment + DataPosFrac)>>FRACTIONBITS};
  235. if(SrcDataEnd >= prepcount+toread)
  236. std::fill(std::begin(mChan[chan].PrevSamples),
  237. std::end(mChan[chan].PrevSamples), 0.0f);
  238. else
  239. {
  240. size_t len = mini(MAX_RESAMPLE_PADDING*2, prepcount+toread-SrcDataEnd);
  241. std::copy_n(SrcData+SrcDataEnd, len, mChan[chan].PrevSamples);
  242. std::fill(std::begin(mChan[chan].PrevSamples)+len,
  243. std::end(mChan[chan].PrevSamples), 0.0f);
  244. }
  245. /* Now resample, and store the result in the output buffer. */
  246. const ALfloat *ResampledData{mResample(&mState, SrcData+MAX_RESAMPLE_PADDING,
  247. DataPosFrac, increment, DstData, DstSize)};
  248. StoreSamples(DstSamples, ResampledData, mChan.size(), mDstType, DstSize);
  249. }
  250. /* Update the number of prep samples still available, as well as the
  251. * fractional offset.
  252. */
  253. DataPosFrac += increment*DstSize;
  254. mSrcPrepCount = mini(prepcount + toread - (DataPosFrac>>FRACTIONBITS),
  255. MAX_RESAMPLE_PADDING*2);
  256. mFracOffset = DataPosFrac & FRACTIONMASK;
  257. /* Update the src and dst pointers in case there's still more to do. */
  258. SamplesIn += SrcFrameSize*(DataPosFrac>>FRACTIONBITS);
  259. NumSrcSamples -= mini(NumSrcSamples, (DataPosFrac>>FRACTIONBITS));
  260. dst = static_cast<ALbyte*>(dst) + DstFrameSize*DstSize;
  261. pos += DstSize;
  262. }
  263. *src = SamplesIn;
  264. *srcframes = NumSrcSamples;
  265. return pos;
  266. }
  267. ChannelConverterPtr CreateChannelConverter(DevFmtType srcType, DevFmtChannels srcChans, DevFmtChannels dstChans)
  268. {
  269. if(srcChans != dstChans && !((srcChans == DevFmtMono && dstChans == DevFmtStereo) ||
  270. (srcChans == DevFmtStereo && dstChans == DevFmtMono)))
  271. return nullptr;
  272. return ChannelConverterPtr{new ChannelConverter{srcType, srcChans, dstChans}};
  273. }
  274. void ChannelConverter::convert(const ALvoid *src, ALfloat *dst, ALsizei frames) const
  275. {
  276. if(mSrcChans == mDstChans)
  277. {
  278. LoadSamples(dst, src, 1u, mSrcType, frames*ChannelsFromDevFmt(mSrcChans, 0));
  279. return;
  280. }
  281. if(mSrcChans == DevFmtStereo && mDstChans == DevFmtMono)
  282. {
  283. switch(mSrcType)
  284. {
  285. #define HANDLE_FMT(T) case T: Stereo2Mono<T>(dst, src, frames); break
  286. HANDLE_FMT(DevFmtByte);
  287. HANDLE_FMT(DevFmtUByte);
  288. HANDLE_FMT(DevFmtShort);
  289. HANDLE_FMT(DevFmtUShort);
  290. HANDLE_FMT(DevFmtInt);
  291. HANDLE_FMT(DevFmtUInt);
  292. HANDLE_FMT(DevFmtFloat);
  293. #undef HANDLE_FMT
  294. }
  295. }
  296. else /*if(mSrcChans == DevFmtMono && mDstChans == DevFmtStereo)*/
  297. {
  298. switch(mSrcType)
  299. {
  300. #define HANDLE_FMT(T) case T: Mono2Stereo<T>(dst, src, frames); break
  301. HANDLE_FMT(DevFmtByte);
  302. HANDLE_FMT(DevFmtUByte);
  303. HANDLE_FMT(DevFmtShort);
  304. HANDLE_FMT(DevFmtUShort);
  305. HANDLE_FMT(DevFmtInt);
  306. HANDLE_FMT(DevFmtUInt);
  307. HANDLE_FMT(DevFmtFloat);
  308. #undef HANDLE_FMT
  309. }
  310. }
  311. }