🛠️🐜 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.

371 lines
13 KiB

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