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.

CDSPResampler.h 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. //$ nocpp
  2. /**
  3. * @file CDSPResampler.h
  4. *
  5. * @brief The master sample rate converter (resampler) class.
  6. *
  7. * This file includes the master sample rate converter (resampler) class that
  8. * combines all elements of this library into a single front-end class.
  9. *
  10. * r8brain-free-src Copyright (c) 2013-2014 Aleksey Vaneev
  11. * See the "License.txt" file for license.
  12. */
  13. #ifndef R8B_CDSPRESAMPLER_INCLUDED
  14. #define R8B_CDSPRESAMPLER_INCLUDED
  15. #include "CDSPBlockConvolver.h"
  16. #include "CDSPFracInterpolator.h"
  17. namespace r8b
  18. {
  19. /**
  20. * @brief The master sample rate converter (resampler) class.
  21. *
  22. * This class can be considered the "master" sample rate converter (resampler)
  23. * class since it combines all functionality of this library into a single
  24. * front-end class to perform sample rate conversion to/from any sample rate,
  25. * including non-integer sample rates.
  26. *
  27. * Note that objects of this class can be constructed on the stack as it has a
  28. * small member data size. The default template parameters of this class are
  29. * suited for 27-bit fixed point resampling.
  30. *
  31. * Use the CDSPResampler16 class for 16-bit resampling.
  32. *
  33. * Use the CDSPResampler16IR class for 16-bit impulse response resampling.
  34. *
  35. * Use the CDSPResampler24 class for 24-bit resampling (including 32-bit
  36. * floating point resampling).
  37. *
  38. * @param CInterpClass Interpolator class that should be used by the
  39. * resampler. The desired interpolation quality can be defined via the
  40. * template parameters of the interpolator class. See
  41. * r8b::CDSPFracInterpolator and r8b::CDSPFracDelayFilterBank for description
  42. * of the template parameters.
  43. */
  44. template <class CInterpClass =
  45. CDSPFracInterpolator<R8B_FLTLEN, R8B_FLTFRACS>>
  46. class CDSPResampler : public CDSPProcessor
  47. {
  48. public:
  49. /**
  50. * Constructor initalizes the resampler object.
  51. *
  52. * Note that increasing the transition band and decreasing attenuation
  53. * reduces the filter length, this in turn reduces the "input before
  54. * output" delay. However, the filter length has only a minor influence on
  55. * the overall resampling speed.
  56. *
  57. * It should be noted that the ReqAtten specifies the minimal difference
  58. * between the loudest input signal component and the produced aliasing
  59. * artifacts during resampling. For example, if ReqAtten=100 was specified
  60. * when performing 2x upsampling, the analysis of the resulting signal may
  61. * display high-frequency components which are quieter than the loudest
  62. * part of the input signal by only 100 decibel meaning the high-frequency
  63. * part did not become "magically" completely silent after resampling. You
  64. * have to specify a higher ReqAtten value if you need a totally clean
  65. * high-frequency content. On the other hand, it may not be reasonable to
  66. * have a high-frequency content cleaner than the input signal itself: if
  67. * the input signal is 16-bit, setting ReqAtten to 150 will make its
  68. * high-frequency content 24-bit, but the original part of the signal will
  69. * remain 16-bit.
  70. *
  71. * @param SrcSampleRate Source signal sample rate. Both sample rates can
  72. * be specified as a ratio, e.g. SrcSampleRate = 1.0, DstSampleRate = 2.0.
  73. * @param DstSampleRate Destination signal sample rate. The "power of 2"
  74. * ratios between the source and destination sample rates force resampler
  75. * to use several fast "power of 2" resampling steps, without using
  76. * fractional interpolation at all. Note that the "power of 2" upsampling
  77. * (but not downsampling) requires a lot of buffer memory: e.g. upsampling
  78. * by a factor of 16 requires an intermediate buffer MaxInLen*(16+8)
  79. * samples long. So, when doing the "power of 2" upsampling it is highly
  80. * recommended to do it in small steps, e.g. no more than 256 samples at
  81. * once (also set the MaxInLen to 256).
  82. * @param MaxInLen The maximal planned length of the input buffer (in
  83. * samples) that will be passed to the resampler. The resampler relies on
  84. * this value as it allocates intermediate buffers. Input buffers longer
  85. * than this value should never be supplied to the resampler. Note that
  86. * the resampler may use the input buffer itself for intermediate sample
  87. * data storage.
  88. * @param ReqTransBand Required transition band, in percent of the
  89. * spectral space of the input signal (or the output signal if
  90. * downsampling is performed) between filter's -3 dB point and the Nyquist
  91. * frequency. The range is from CDSPFIRFilter::getLPMinTransBand() to
  92. * CDSPFIRFilter::getLPMaxTransBand(), inclusive. When upsampling 88200 or
  93. * 96000 audio to a higher sample rates the ReqTransBand can be
  94. * considerably increased, up to 30. The selection of ReqTransBand depends
  95. * on the level of desire to preserve the high-frequency content. While
  96. * values 0.5 to 2 are extremely "greedy" settings, not necessary in most
  97. * cases, values 2 to 3 can be used in most cases. Values 3 to 4 are
  98. * relaxed settings, but they still offer a flat frequency response up to
  99. * 21kHz with 44.1k source or destination sample rate.
  100. * @param ReqAtten Required stop-band attenuation in decibel, in the range
  101. * CDSPFIRFilter::getLPMinAtten() to CDSPFIRFilter::getLPMaxAtten(),
  102. * inclusive. The actual attenuation may be 0.40-4.46 dB higher. The
  103. * general formula for selecting the ReqAtten is 6.02 * Bits + 40, where
  104. * "Bits" is the bit resolution (e.g. 16, 24), "40" is an added resolution
  105. * for stationary signals, this value can be decreased to 20 to 10 if the
  106. * signal being resampled is mostly non-stationary (e.g. impulse
  107. * response).
  108. * @param ReqPhase Required filter's phase response. Note that this
  109. * setting does not affect interpolator's phase response which is always
  110. * linear-phase. Also note that if the "power of 2" resampling was engaged
  111. * by the resampler together with the minimum-phase response, the audio
  112. * stream may become fractionally delayed by up to 1 sample, depending on
  113. * the minimum-phase filter's actual fractional delay. If the output
  114. * stream should always start at "time zero" offset with minimum-phase
  115. * filters the UsePower2 should be set to "false". Linear-phase filters
  116. * do not have fractional delay.
  117. * @param UsePower2 "True" if the "power of 2" resampling optimization
  118. * should be used when possible. This value should be set to "false" if
  119. * the access to interpolator is needed in any case (also the source and
  120. * destination sample rates should not be equal).
  121. * @see CDSPFIRFilterCache::getLPFilter()
  122. */
  123. CDSPResampler(const double SrcSampleRate, const double DstSampleRate,
  124. const int MaxInLen, const double ReqTransBand = 2.0,
  125. const double ReqAtten = 206.91,
  126. const EDSPFilterPhaseResponse ReqPhase = fprLinearPhase,
  127. const bool UsePower2 = true)
  128. {
  129. R8BASSERT(SrcSampleRate > 0.0);
  130. R8BASSERT(DstSampleRate > 0.0);
  131. R8BASSERT(MaxInLen > 0);
  132. if (SrcSampleRate == DstSampleRate)
  133. {
  134. ConvCount = 0;
  135. return;
  136. }
  137. int SrcSRMult;
  138. int SrcSRDiv = 1;
  139. int MaxOutLen = MaxInLen;
  140. int ConvBufCapacities[ 2 ];
  141. double PrevLatencyFrac = 0.0;
  142. if (DstSampleRate * 2 > SrcSampleRate)
  143. {
  144. // Only a single convolver with 2X upsampling is required.
  145. SrcSRMult = 2;
  146. const double NormFreq = (DstSampleRate > SrcSampleRate ? 0.5 : 0.5 * DstSampleRate / SrcSampleRate);
  147. Convs[0] = new CDSPBlockConvolver(CDSPFIRFilterCache::getLPFilter(NormFreq, ReqTransBand, ReqAtten, ReqPhase, 2.0), 2, 1, 0.0);
  148. ConvCount = 1;
  149. MaxOutLen = Convs[0]->getMaxOutLen(MaxOutLen);
  150. ConvBufCapacities[0] = MaxOutLen;
  151. PrevLatencyFrac = Convs[0]->getLatencyFrac();
  152. // Find if the destination to source sample rate ratio is
  153. // a "power of 2" value.
  154. int UseConvCount = 1;
  155. while (true)
  156. {
  157. const double TestSR = SrcSampleRate * (1 << UseConvCount);
  158. if (TestSR > DstSampleRate)
  159. {
  160. UseConvCount = 0; // Power of 2 not found.
  161. break;
  162. }
  163. if (TestSR == DstSampleRate)
  164. {
  165. break; // Power of 2 found.
  166. }
  167. UseConvCount++;
  168. }
  169. if (UsePower2 && UseConvCount > 0)
  170. {
  171. R8BASSERT(UseConvCount <= ConvCountMax);
  172. ConvBufCapacities[1] = 0;
  173. ConvCount = UseConvCount;
  174. for (int i = 1; i < UseConvCount; ++i)
  175. {
  176. const double tb = (i >= 2 ? 45.0 : 34.0);
  177. Convs[i] = new CDSPBlockConvolver(CDSPFIRFilterCache::getLPFilter(0.5, tb, ReqAtten, ReqPhase, 2.0), 2, 1, PrevLatencyFrac);
  178. MaxOutLen = Convs[i]->getMaxOutLen(MaxOutLen);
  179. ConvBufCapacities[i & 1] = MaxOutLen;
  180. PrevLatencyFrac = Convs[i]->getLatencyFrac();
  181. }
  182. ConvBufs[0].alloc(ConvBufCapacities[0]);
  183. if (ConvBufCapacities[1] > 0) { ConvBufs[1].alloc(ConvBufCapacities[1]); }
  184. return; // No interpolator is needed.
  185. }
  186. ConvBufs[0].alloc(ConvBufCapacities[0]);
  187. }
  188. else
  189. {
  190. SrcSRMult = 1;
  191. ConvBufCapacities[0] = 0;
  192. ConvCount = 0;
  193. const double CheckSR = DstSampleRate * 4;
  194. while (CheckSR * SrcSRDiv <= SrcSampleRate)
  195. {
  196. SrcSRDiv *= 2;
  197. // If downsampling is even deeper, use a less steep filter at
  198. // this step.
  199. const double tb =
  200. (CheckSR * SrcSRDiv <= SrcSampleRate ? 45.0 : 34.0);
  201. Convs[ConvCount] = new CDSPBlockConvolver(CDSPFIRFilterCache::getLPFilter(0.5, tb, ReqAtten, ReqPhase, 1.0), 1, 2, PrevLatencyFrac);
  202. MaxOutLen = Convs[ConvCount]->getMaxOutLen(MaxOutLen);
  203. PrevLatencyFrac = Convs[ConvCount]->getLatencyFrac();
  204. ConvCount++;
  205. R8BASSERT(ConvCount < ConvCountMax);
  206. }
  207. const double NormFreq = DstSampleRate * SrcSRDiv / SrcSampleRate;
  208. const int downf = (UsePower2 && NormFreq == 0.5 ? 2 : 1);
  209. Convs[ConvCount] = new CDSPBlockConvolver(CDSPFIRFilterCache::getLPFilter(NormFreq, ReqTransBand, ReqAtten, ReqPhase, 1.0), 1, downf,
  210. PrevLatencyFrac);
  211. MaxOutLen = Convs[ConvCount]->getMaxOutLen(MaxOutLen);
  212. PrevLatencyFrac = Convs[ConvCount]->getLatencyFrac();
  213. ConvCount++;
  214. if (downf > 1)
  215. {
  216. return; // No interpolator is needed.
  217. }
  218. }
  219. Interp = new CInterpClass(SrcSampleRate * SrcSRMult / SrcSRDiv, DstSampleRate, PrevLatencyFrac);
  220. MaxOutLen = Interp->getMaxOutLen(MaxOutLen);
  221. if (MaxOutLen <= ConvBufCapacities[0]) { InterpBuf = ConvBufs[0]; }
  222. else if (MaxOutLen <= MaxInLen) { InterpBuf = nullptr; }
  223. else
  224. {
  225. TmpBuf.alloc(MaxOutLen);
  226. InterpBuf = TmpBuf;
  227. }
  228. }
  229. int getLatency() const override { return (0); }
  230. double getLatencyFrac() const override { return (0.0); }
  231. int getInLenBeforeOutStart(const int NextInLen) const override
  232. {
  233. int l = (Interp == nullptr ? 0 : Interp->getInLenBeforeOutStart(NextInLen));
  234. for (int i = ConvCount - 1; i >= 0; i--) { l = Convs[i]->getInLenBeforeOutStart(l); }
  235. return (l);
  236. }
  237. int getMaxOutLen(const int/* MaxInLen */) const override { return (0); }
  238. /**
  239. * Function clears (resets) the state of *this object and returns it to
  240. * the state after construction. All input data accumulated in the
  241. * internal buffer so far will be discarded.
  242. *
  243. * This function makes it possible to use *this object for converting
  244. * separate streams from the same source sample rate to the same
  245. * destination sample rate without reconstructing the object. It is more
  246. * efficient to clear the state of the resampler object than to destroy it
  247. * and create a new object.
  248. */
  249. void clear() override
  250. {
  251. for (int i = 0; i < ConvCount; ++i) { Convs[i]->clear(); }
  252. if (Interp != nullptr) { Interp->clear(); }
  253. }
  254. /**
  255. * Function performs sample rate conversion.
  256. *
  257. * If the source and destination sample rates are equal, the resampler
  258. * will do nothing and will simply return the input buffer unchanged.
  259. *
  260. * You do not need to allocate an intermediate output buffer for use with
  261. * this function. If required, the resampler will allocate a suitable
  262. * intermediate output buffer itself.
  263. *
  264. * @param ip0 Input buffer. This buffer may be used as output buffer by
  265. * this function.
  266. * @param l The number of samples available in the input buffer. Should
  267. * not exceed the MaxInLen supplied to the constructor.
  268. * @param[out] op0 This variable receives the pointer to the resampled
  269. * data. On function's return, this pointer may point to the address
  270. * within the "ip0" input buffer, or to *this object's internal buffer. In
  271. * real-time applications it is suggested to pass this pointer to the next
  272. * output audio block and consume any data left from the previous output
  273. * audio block first before calling the process() function again. The
  274. * buffer pointed to by the "op0" on return may be owned by the resampler,
  275. * so it should not be freed by the caller.
  276. * @return The number of samples available in the "op0" output buffer. If
  277. * the data from the output buffer "op0" is going to be written to a
  278. * bigger output buffer, it is suggested to check the returned number of
  279. * samples so that no overflow of the bigger output buffer happens.
  280. */
  281. int process(double* ip0, int l, double*& op0) override
  282. {
  283. R8BASSERT(l >= 0);
  284. if (ConvCount == 0)
  285. {
  286. op0 = ip0;
  287. return (l);
  288. }
  289. double* ip = ip0;
  290. double* op = nullptr;
  291. for (int i = 0; i < ConvCount; ++i)
  292. {
  293. op = (ConvBufs[i & 1] == nullptr ? ip0 : ConvBufs[i & 1]);
  294. l = Convs[i]->process(ip, l, op);
  295. ip = op;
  296. }
  297. if (Interp == nullptr)
  298. {
  299. op0 = op;
  300. return (l);
  301. }
  302. op = (InterpBuf == nullptr ? ip0 : InterpBuf);
  303. op0 = op;
  304. return (Interp->process(ip, l, op));
  305. }
  306. /**
  307. * Function performs resampling of an input sample buffer of the specified
  308. * length in the "one-shot" mode. This function can be useful when impulse
  309. * response resampling is required.
  310. *
  311. * @param MaxInLen The max input length value which was previously passed
  312. * to the constructor.
  313. * @param ip Input buffer pointer.
  314. * @param iplen Length of the input buffer in samples.
  315. * @param op Output buffer pointer.
  316. * @param oplen Length of the output buffer in samples.
  317. */
  318. void oneshot(const int MaxInLen, const double* ip, int iplen,
  319. double* op, int oplen)
  320. {
  321. const CFixedBuffer<double> ZeroBuf(MaxInLen);
  322. memset(&ZeroBuf[0], 0, MaxInLen * sizeof(double));
  323. while (oplen > 0)
  324. {
  325. int rc;
  326. double* p;
  327. if (iplen == 0)
  328. {
  329. rc = MaxInLen;
  330. p = static_cast<double*>(&ZeroBuf[0]);
  331. }
  332. else
  333. {
  334. rc = min(iplen, MaxInLen);
  335. p = const_cast<double*>(ip);
  336. ip += rc;
  337. iplen -= rc;
  338. }
  339. double* op0;
  340. int wc = process(p, rc, op0);
  341. wc = min(oplen, wc);
  342. memcpy(op, op0, wc * sizeof(double));
  343. op += wc;
  344. oplen -= wc;
  345. }
  346. clear();
  347. }
  348. private:
  349. static const int ConvCountMax = 8; ///< 8 convolvers with the
  350. ///< built-in 2x up- or downsampling is enough for 256x up- or
  351. ///< downsampling.
  352. ///<
  353. CPtrKeeper<CDSPBlockConvolver*> Convs[ ConvCountMax ]; ///< Convolvers.
  354. ///<
  355. int ConvCount = 0; ///< The number of objects defined in the Convs[] array.
  356. ///< Equals to 0 if sample rate conversion is not needed.
  357. ///<
  358. CPtrKeeper<CInterpClass*> Interp; ///< Fractional interpolator object.
  359. ///< Equals NULL if no fractional interpolation is required meaning
  360. ///< the "power of 2" resampling is performed or no resampling is
  361. ///< performed at all.
  362. ///<
  363. CFixedBuffer<double> ConvBufs[ 2 ]; ///< Intermediate convolution
  364. ///< buffers to use, used only when at least 2x upsampling is
  365. ///< performed. These buffers are used in flip-flop manner. If NULL
  366. ///< then the input buffer will be used instead.
  367. ///<
  368. CFixedBuffer<double> TmpBuf; ///< Additional output buffer, can be
  369. ///< addressed by the InterpBuf pointer.
  370. ///<
  371. double* InterpBuf = nullptr; ///< Final output interpolation buffer to use. If NULL
  372. ///< then the input buffer will be used instead. Otherwise this
  373. ///< pointer points to either ConvBufs or TmpBuf.
  374. ///<
  375. };
  376. /**
  377. * @brief The resampler class for 16-bit resampling.
  378. *
  379. * This class defines resampling parameters suitable for 16-bit resampling,
  380. * using linear-phase low-pass filter. See the r8b::CDSPResampler class for
  381. * details.
  382. */
  383. class CDSPResampler16 final : public CDSPResampler<CDSPFracInterpolator<18, 137>>
  384. {
  385. public:
  386. /**
  387. * Constructor initializes the 16-bit resampler. See the
  388. * r8b::CDSPResampler class for details.
  389. *
  390. * @param SrcSampleRate Source signal sample rate.
  391. * @param DstSampleRate Destination signal sample rate.
  392. * @param MaxInLen The maximal planned length of the input buffer (in
  393. * samples) that will be passed to the resampler.
  394. * @param ReqTransBand Required transition band, in percent.
  395. */
  396. CDSPResampler16(const double SrcSampleRate, const double DstSampleRate, const int MaxInLen, const double ReqTransBand = 2.0)
  397. : CDSPResampler<CDSPFracInterpolator<18, 137>>(SrcSampleRate, DstSampleRate, MaxInLen, ReqTransBand, 136.45, fprLinearPhase, true) { }
  398. };
  399. /**
  400. * @brief The resampler class for 16-bit impulse response resampling.
  401. *
  402. * This class defines resampling parameters suitable for 16-bit impulse
  403. * response resampling, using linear-phase low-pass filter. Impulse responses
  404. * usually do not feature stationary signal components and thus need resampler
  405. * with a less SNR. See the r8b::CDSPResampler class for details.
  406. */
  407. class CDSPResampler16IR final : public CDSPResampler<CDSPFracInterpolator<14, 67>>
  408. {
  409. public:
  410. /**
  411. * Constructor initializes the 16-bit impulse response resampler. See the
  412. * r8b::CDSPResampler class for details.
  413. *
  414. * @param SrcSampleRate Source signal sample rate.
  415. * @param DstSampleRate Destination signal sample rate.
  416. * @param MaxInLen The maximal planned length of the input buffer (in
  417. * samples) that will be passed to the resampler.
  418. * @param ReqTransBand Required transition band, in percent.
  419. */
  420. CDSPResampler16IR(const double SrcSampleRate, const double DstSampleRate, const int MaxInLen, const double ReqTransBand = 2.0)
  421. : CDSPResampler<CDSPFracInterpolator<14, 67>>(SrcSampleRate, DstSampleRate, MaxInLen, ReqTransBand, 109.56, fprLinearPhase, true) { }
  422. };
  423. /**
  424. * @brief The resampler class for 24-bit resampling.
  425. *
  426. * This class defines resampling parameters suitable for 24-bit resampling
  427. * (including 32-bit floating point resampling), using linear-phase low-pass
  428. * filter. See the r8b::CDSPResampler class for details.
  429. */
  430. class CDSPResampler24 final : public CDSPResampler<CDSPFracInterpolator<24, 673>>
  431. {
  432. public:
  433. /**
  434. * Constructor initializes the 24-bit resampler (including 32-bit floating
  435. * point). See the r8b::CDSPResampler class for details.
  436. *
  437. * @param SrcSampleRate Source signal sample rate.
  438. * @param DstSampleRate Destination signal sample rate.
  439. * @param MaxInLen The maximal planned length of the input buffer (in
  440. * samples) that will be passed to the resampler.
  441. * @param ReqTransBand Required transition band, in percent.
  442. */
  443. CDSPResampler24(const double SrcSampleRate, const double DstSampleRate, const int MaxInLen, const double ReqTransBand = 2.0)
  444. : CDSPResampler<CDSPFracInterpolator<24, 673>>(SrcSampleRate, DstSampleRate, MaxInLen, ReqTransBand, 180.15, fprLinearPhase, true) { }
  445. };
  446. } // namespace r8b
  447. #endif // R8B_CDSPRESAMPLER_INCLUDED