CDSPHBUpsampler.h 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. //$ nobt
  2. //$ nocpp
  3. /**
  4. * @file CDSPHBUpsampler.h
  5. *
  6. * @brief Half-band upsampling class.
  7. *
  8. * This file includes half-band upsampling class.
  9. *
  10. * r8brain-free-src Copyright (c) 2013-2022 Aleksey Vaneev
  11. * See the "LICENSE" file for license.
  12. */
  13. #ifndef R8B_CDSPHBUPSAMPLER_INCLUDED
  14. #define R8B_CDSPHBUPSAMPLER_INCLUDED
  15. #include "CDSPProcessor.h"
  16. namespace r8b {
  17. /**
  18. * @brief Half-band upsampling class.
  19. *
  20. * Class implements brute-force half-band 2X upsampling that uses small
  21. * sparse symmetric FIR filters. It is very efficient and should be used at
  22. * latter upsampling steps after initial steep 2X upsampling.
  23. */
  24. class CDSPHBUpsampler : public CDSPProcessor
  25. {
  26. public:
  27. /**
  28. * Function that provides filter data for various steepness indices and
  29. * attenuations.
  30. *
  31. * @param ReqAtten Required half-band filter attentuation.
  32. * @param SteepIndex Steepness index - 0=steepest. Corresponds to general
  33. * upsampling/downsampling ratio, e.g. at 4x 0 is used, at 8x 1 is used,
  34. * etc.
  35. */
  36. static void getHBFilter( const double ReqAtten, const int SteepIndex,
  37. const double*& flt, int& fltt, double& att )
  38. {
  39. static const double HBKernel_4A[ 4 ] = { // -54.5176 dB, 4
  40. 6.1729335650971517e-001, -1.5963945620743250e-001,
  41. 5.5073370934086312e-002, -1.4603578989932850e-002,};
  42. static const double HBKernel_5A[ 5 ] = { // -66.3075 dB, 4
  43. 6.2068807424902472e-001, -1.6827573634467302e-001,
  44. 6.5263016720721170e-002, -2.2483331611592005e-002,
  45. 5.2917326684281110e-003,};
  46. static const double HBKernel_6A[ 6 ] = { // -89.5271 dB, 4
  47. 6.2187202340480707e-001, -1.7132842113816371e-001,
  48. 6.9019169178765674e-002, -2.5799728312695277e-002,
  49. 7.4880112525741666e-003, -1.2844465869952567e-003,};
  50. static const double HBKernel_7A[ 7 ] = { // -105.2842 dB, 4
  51. 6.2354494135775851e-001, -1.7571220703702045e-001,
  52. 7.4529843603968457e-002, -3.0701736822442153e-002,
  53. 1.0716755639039573e-002, -2.7833422930759735e-003,
  54. 4.1118797093875510e-004,};
  55. static const double HBKernel_8A[ 8 ] = { // -121.0063 dB, 4
  56. 6.2488363107953926e-001, -1.7924942606514119e-001,
  57. 7.9068155655640557e-002, -3.4907523415495731e-002,
  58. 1.3710256799907897e-002, -4.3991142586987933e-003,
  59. 1.0259190163889602e-003, -1.3278941979339359e-004,};
  60. static const double HBKernel_9A[ 9 ] = { // -136.6982 dB, 4
  61. 6.2597763804021977e-001, -1.8216414325139055e-001,
  62. 8.2879104876726728e-002, -3.8563442248249404e-002,
  63. 1.6471530499739394e-002, -6.0489108881335227e-003,
  64. 1.7805283804140392e-003, -3.7533200112729561e-004,
  65. 4.3172840558735476e-005,};
  66. static const double HBKernel_10A[ 10 ] = { // -152.3572 dB, 4
  67. 6.2688767582974092e-001, -1.8460766807559420e-001,
  68. 8.6128943000481864e-002, -4.1774474147006607e-002,
  69. 1.9014801985747346e-002, -7.6870397465866507e-003,
  70. 2.6264590175341853e-003, -7.1106660285478562e-004,
  71. 1.3645852036179345e-004, -1.4113888783332969e-005,};
  72. static const double HBKernel_11A[ 11 ] = { // -183.7962 dB, 4
  73. 6.2667167706948146e-001, -1.8407153342635879e-001,
  74. 8.5529995610836046e-002, -4.1346831462361310e-002,
  75. 1.8844831691322637e-002, -7.7125170365394992e-003,
  76. 2.7268674860562087e-003, -7.9745028501057233e-004,
  77. 1.8116344606360795e-004, -2.8569149754241848e-005,
  78. 2.3667022010173616e-006,};
  79. static const double HBKernel_12A[ 12 ] = { // -199.4768 dB, 4
  80. 6.2747849730367999e-001, -1.8623616784506747e-001,
  81. 8.8409755898467945e-002, -4.4207468821462342e-002,
  82. 2.1149175945115381e-002, -9.2551508371115209e-003,
  83. 3.5871562170822330e-003, -1.1923167653750219e-003,
  84. 3.2627812189920129e-004, -6.9106902511490413e-005,
  85. 1.0122897863125124e-005, -7.7531878906846174e-007,};
  86. static const double HBKernel_13A[ 13 ] = { // -215.1364 dB, 4
  87. 6.2816416252367324e-001, -1.8809076955230414e-001,
  88. 9.0918539867353029e-002, -4.6765502683599310e-002,
  89. 2.3287520498995663e-002, -1.0760627245014184e-002,
  90. 4.4853922948425683e-003, -1.6438775426910800e-003,
  91. 5.1441312354764978e-004, -1.3211725685765050e-004,
  92. 2.6191319837779187e-005, -3.5802430606313093e-006,
  93. 2.5491278270628601e-007,};
  94. static const double HBKernel_14A[ 14 ] = { // -230.7526 dB, 4
  95. 6.2875473120929948e-001, -1.8969941936903847e-001,
  96. 9.3126094480960403e-002, -4.9067251179869126e-002,
  97. 2.5273008851199916e-002, -1.2218646153393291e-002,
  98. 5.4048942085580280e-003, -2.1409919546078581e-003,
  99. 7.4250292812927973e-004, -2.1924542206832172e-004,
  100. 5.3015808983125091e-005, -9.8743034923598196e-006,
  101. 1.2650391141650221e-006, -8.4146674637474946e-008,};
  102. static const int FltCountA = 11;
  103. static const int FlttBaseA = 4;
  104. static const double FltAttensA[ FltCountA ] = {
  105. 54.5176, 66.3075, 89.5271, 105.2842, 121.0063, 136.6982, 152.3572, 183.7962, 199.4768, 215.1364, 230.7526, };
  106. static const double* const FltPtrsA[ FltCountA ] = {
  107. HBKernel_4A, HBKernel_5A, HBKernel_6A, HBKernel_7A, HBKernel_8A, HBKernel_9A, HBKernel_10A, HBKernel_11A, HBKernel_12A, HBKernel_13A, HBKernel_14A, };
  108. static const double HBKernel_2B[ 2 ] = { // -56.6007 dB, 8
  109. 5.7361525854329076e-001, -7.5092074924827903e-002,};
  110. static const double HBKernel_3B[ 3 ] = { // -83.0295 dB, 8
  111. 5.9277038608066912e-001, -1.0851340190268854e-001,
  112. 1.5813570475513079e-002,};
  113. static const double HBKernel_4B[ 4 ] = { // -123.4724 dB, 8
  114. 6.0140277542879617e-001, -1.2564483854574138e-001,
  115. 2.7446500598038322e-002, -3.2051079559057435e-003,};
  116. static const double HBKernel_5B[ 5 ] = { // -152.4411 dB, 8
  117. 6.0818642429088932e-001, -1.3981140187175697e-001,
  118. 3.8489164054503623e-002, -7.6218861797853104e-003,
  119. 7.5772358130952392e-004,};
  120. static const double HBKernel_6B[ 6 ] = { // -181.2501 dB, 8
  121. 6.1278392271464355e-001, -1.5000053762513338e-001,
  122. 4.7575323511364960e-002, -1.2320702802243476e-002,
  123. 2.1462442592348487e-003, -1.8425092381892940e-004,};
  124. static const double HBKernel_7B[ 7 ] = { // -209.9472 dB, 8
  125. 6.1610372263478952e-001, -1.5767891882524138e-001,
  126. 5.5089691170294691e-002, -1.6895755656366061e-002,
  127. 3.9416643438213977e-003, -6.0603623791604668e-004,
  128. 4.5632602433393365e-005,};
  129. static const double HBKernel_8B[ 8 ] = { // -238.5616 dB, 8
  130. 6.1861282914465976e-001, -1.6367179451225150e-001,
  131. 6.1369861342939716e-002, -2.1184466539006987e-002,
  132. 5.9623357510842061e-003, -1.2483098507454090e-003,
  133. 1.7099297537964702e-004, -1.1448313239478885e-005,};
  134. static const int FltCountB = 7;
  135. static const int FlttBaseB = 2;
  136. static const double FltAttensB[ FltCountB ] = {
  137. 56.6007, 83.0295, 123.4724, 152.4411, 181.2501, 209.9472, 238.5616, };
  138. static const double* const FltPtrsB[ FltCountB ] = {
  139. HBKernel_2B, HBKernel_3B, HBKernel_4B, HBKernel_5B, HBKernel_6B, HBKernel_7B, HBKernel_8B, };
  140. static const double HBKernel_2C[ 2 ] = { // -89.0473 dB, 16
  141. 5.6430278013478008e-001, -6.4338068855763375e-002,};
  142. static const double HBKernel_3C[ 3 ] = { // -130.8951 dB, 16
  143. 5.8706402915551448e-001, -9.9362380958670449e-002,
  144. 1.2298637065869358e-002,};
  145. static const double HBKernel_4C[ 4 ] = { // -172.3192 dB, 16
  146. 5.9896586134984675e-001, -1.2111680603434927e-001,
  147. 2.4763118076458895e-002, -2.6121758132212989e-003,};
  148. static const double HBKernel_5C[ 5 ] = { // -213.4984 dB, 16
  149. 6.0626808285230716e-001, -1.3588224032740795e-001,
  150. 3.5544305238309003e-002, -6.5127022377289654e-003,
  151. 5.8255449565950768e-004,};
  152. static const double HBKernel_6C[ 6 ] = { // -254.5186 dB, 16
  153. 6.1120171263351242e-001, -1.4654486853757870e-001,
  154. 4.4582959299131253e-002, -1.0840543858123995e-002,
  155. 1.7343706485509962e-003, -1.3363018567985596e-004,};
  156. static const int FltCountC = 5;
  157. static const int FlttBaseC = 2;
  158. static const double FltAttensC[ FltCountC ] = {
  159. 89.0473, 130.8951, 172.3192, 213.4984, 254.5186, };
  160. static const double* const FltPtrsC[ FltCountC ] = {
  161. HBKernel_2C, HBKernel_3C, HBKernel_4C, HBKernel_5C, HBKernel_6C, };
  162. static const double HBKernel_1D[ 1 ] = { // -54.4754 dB, 32
  163. 5.0188900022775451e-001,};
  164. static const double HBKernel_2D[ 2 ] = { // -113.2139 dB, 32
  165. 5.6295152180538044e-001, -6.2953706070191726e-002,};
  166. static const double HBKernel_3D[ 3 ] = { // -167.1447 dB, 32
  167. 5.8621968728755036e-001, -9.8080551656524531e-002,
  168. 1.1860868761997080e-002,};
  169. static const double HBKernel_4D[ 4 ] = { // -220.6519 dB, 32
  170. 5.9835028657163591e-001, -1.1999986086623511e-001,
  171. 2.4132530854004228e-002, -2.4829565686819706e-003,};
  172. static const int FltCountD = 4;
  173. static const int FlttBaseD = 1;
  174. static const double FltAttensD[ FltCountD ] = {
  175. 54.4754, 113.2139, 167.1447, 220.6519, };
  176. static const double* const FltPtrsD[ FltCountD ] = {
  177. HBKernel_1D, HBKernel_2D, HBKernel_3D, HBKernel_4D, };
  178. static const double HBKernel_1E[ 1 ] = { // -66.5391 dB, 64
  179. 5.0047102586416625e-001,};
  180. static const double HBKernel_2E[ 2 ] = { // -137.3173 dB, 64
  181. 5.6261293163933568e-001, -6.2613067826620017e-002,};
  182. static const double HBKernel_3E[ 3 ] = { // -203.2997 dB, 64
  183. 5.8600808139396787e-001, -9.7762185880067784e-002,
  184. 1.1754104554493029e-002,};
  185. static const double HBKernel_4E[ 4 ] = { // -268.8550 dB, 64
  186. 5.9819599352772002e-001, -1.1972157555011861e-001,
  187. 2.3977305567947922e-002, -2.4517235455853992e-003,};
  188. static const int FltCountE = 4;
  189. static const int FlttBaseE = 1;
  190. static const double FltAttensE[ FltCountE ] = {
  191. 66.5391, 137.3173, 203.2997, 268.8550, };
  192. static const double* const FltPtrsE[ FltCountE ] = {
  193. HBKernel_1E, HBKernel_2E, HBKernel_3E, HBKernel_4E, };
  194. static const double HBKernel_1F[ 1 ] = { // -82.4633 dB, 128
  195. 5.0007530666642896e-001,};
  196. static const double HBKernel_2F[ 2 ] = { // -161.4049 dB, 128
  197. 5.6252823610146030e-001, -6.2528244608044792e-002,};
  198. static const double HBKernel_3F[ 3 ] = { // -239.4313 dB, 128
  199. 5.8595514744674237e-001, -9.7682725156791952e-002,
  200. 1.1727577711117231e-002,};
  201. static const int FltCountF = 3;
  202. static const int FlttBaseF = 1;
  203. static const double FltAttensF[ FltCountF ] = {
  204. 82.4633, 161.4049, 239.4313, };
  205. static const double* const FltPtrsF[ FltCountF ] = {
  206. HBKernel_1F, HBKernel_2F, HBKernel_3F, };
  207. static const double HBKernel_1G[ 1 ] = { // -94.5052 dB, 256
  208. 5.0001882524896712e-001,};
  209. static const double HBKernel_2G[ 2 ] = { // -185.4886 dB, 256
  210. 5.6250705922479682e-001, -6.2507059756378394e-002,};
  211. static const double HBKernel_3G[ 3 ] = { // -275.5501 dB, 256
  212. 5.8594191201187384e-001, -9.7662868266991207e-002,
  213. 1.1720956255134043e-002,};
  214. static const int FltCountG = 3;
  215. static const int FlttBaseG = 1;
  216. static const double FltAttensG[ FltCountG ] = {
  217. 94.5052, 185.4886, 275.5501, };
  218. static const double* const FltPtrsG[ FltCountG ] = {
  219. HBKernel_1G, HBKernel_2G, HBKernel_3G, };
  220. int k = 0;
  221. if( SteepIndex <= 0 )
  222. {
  223. while( k != FltCountA - 1 && FltAttensA[ k ] < ReqAtten )
  224. {
  225. k++;
  226. }
  227. flt = FltPtrsA[ k ];
  228. fltt = FlttBaseA + k;
  229. att = FltAttensA[ k ];
  230. }
  231. else
  232. if( SteepIndex == 1 )
  233. {
  234. while( k != FltCountB - 1 && FltAttensB[ k ] < ReqAtten )
  235. {
  236. k++;
  237. }
  238. flt = FltPtrsB[ k ];
  239. fltt = FlttBaseB + k;
  240. att = FltAttensB[ k ];
  241. }
  242. else
  243. if( SteepIndex == 2 )
  244. {
  245. while( k != FltCountC - 1 && FltAttensC[ k ] < ReqAtten )
  246. {
  247. k++;
  248. }
  249. flt = FltPtrsC[ k ];
  250. fltt = FlttBaseC + k;
  251. att = FltAttensC[ k ];
  252. }
  253. else
  254. if( SteepIndex == 3 )
  255. {
  256. while( k != FltCountD - 1 && FltAttensD[ k ] < ReqAtten )
  257. {
  258. k++;
  259. }
  260. flt = FltPtrsD[ k ];
  261. fltt = FlttBaseD + k;
  262. att = FltAttensD[ k ];
  263. }
  264. else
  265. if( SteepIndex == 4 )
  266. {
  267. while( k != FltCountE - 1 && FltAttensE[ k ] < ReqAtten )
  268. {
  269. k++;
  270. }
  271. flt = FltPtrsE[ k ];
  272. fltt = FlttBaseE + k;
  273. att = FltAttensE[ k ];
  274. }
  275. else
  276. if( SteepIndex == 5 )
  277. {
  278. while( k != FltCountF - 1 && FltAttensF[ k ] < ReqAtten )
  279. {
  280. k++;
  281. }
  282. flt = FltPtrsF[ k ];
  283. fltt = FlttBaseF + k;
  284. att = FltAttensF[ k ];
  285. }
  286. else
  287. {
  288. while( k != FltCountG - 1 && FltAttensG[ k ] < ReqAtten )
  289. {
  290. k++;
  291. }
  292. flt = FltPtrsG[ k ];
  293. fltt = FlttBaseG + k;
  294. att = FltAttensG[ k ];
  295. }
  296. }
  297. /**
  298. * Function that provides filter data for various steepness indices and
  299. * attenuations. For 1/3 resamplings.
  300. *
  301. * @param ReqAtten Required half-band filter attentuation.
  302. * @param SteepIndex Steepness index - 0=steepest. Corresponds to general
  303. * upsampling/downsampling ratio, e.g. at 4x 0 is used, at 8x 1 is used,
  304. * etc.
  305. */
  306. static void getHBFilterThird( const double ReqAtten, const int SteepIndex,
  307. const double*& flt, int& fltt, double& att )
  308. {
  309. static const double HBKernel_3A[ 3 ] = { // -66.3726 dB, 6
  310. 5.9811355069551475e-001, -1.1793396656733847e-001,
  311. 2.0300557211946322e-002,};
  312. static const double HBKernel_4A[ 4 ] = { // -90.2546 dB, 6
  313. 6.0645499250612578e-001, -1.3555496505481171e-001,
  314. 3.4022804962365975e-002, -4.9535418595798757e-003,};
  315. static const double HBKernel_5A[ 5 ] = { // -126.5507 dB, 6
  316. 6.1014115058940210e-001, -1.4393081816629907e-001,
  317. 4.1760642892852244e-002, -8.9692183234056175e-003,
  318. 9.9871340618342070e-004,};
  319. static const double HBKernel_6A[ 6 ] = { // -150.1839 dB, 6
  320. 6.1439563420546972e-001, -1.5360187826905250e-001,
  321. 5.0840891345687034e-002, -1.4053648740561121e-002,
  322. 2.6771286587305727e-003, -2.5815816044823123e-004,};
  323. static const double HBKernel_7A[ 7 ] = { // -173.7068 dB, 6
  324. 6.1747493476329918e-001, -1.6087373733313212e-001,
  325. 5.8263075641409430e-002, -1.8872408173431318e-002,
  326. 4.7421376543513687e-003, -8.0196529612267474e-004,
  327. 6.7964807393798996e-005,};
  328. static const double HBKernel_8A[ 8 ] = { // -197.1454 dB, 6
  329. 6.1980610947775050e-001, -1.6654070578314714e-001,
  330. 6.4416567441730327e-002, -2.3307744348719822e-002,
  331. 6.9909157372312443e-003, -1.5871946293364403e-003,
  332. 2.4017727382382763e-004, -1.8125308241541697e-005,};
  333. static const double HBKernel_9A[ 9 ] = { // -220.5199 dB, 6
  334. 6.2163188951899306e-001, -1.7108115323810941e-001,
  335. 6.9588370095600260e-002, -2.7339625080613838e-002,
  336. 9.2954469183791771e-003, -2.5537179959555429e-003,
  337. 5.2572290897951021e-004, -7.1813356135154921e-005,
  338. 4.8802382808892154e-006,};
  339. static const int FltCountA = 7;
  340. static const int FlttBaseA = 3;
  341. static const double FltAttensA[ FltCountA ] = {
  342. 66.3726, 90.2546, 126.5507, 150.1839, 173.7068, 197.1454, 220.5199, };
  343. static const double* const FltPtrsA[ FltCountA ] = {
  344. HBKernel_3A, HBKernel_4A, HBKernel_5A, HBKernel_6A, HBKernel_7A, HBKernel_8A, HBKernel_9A, };
  345. static const double HBKernel_2B[ 2 ] = { // -71.0965 dB, 12
  346. 5.6748544264806311e-001, -6.7764090509431732e-002,};
  347. static const double HBKernel_3B[ 3 ] = { // -115.7707 dB, 12
  348. 5.8793612182667199e-001, -1.0070583248877293e-001,
  349. 1.2771337947163834e-002,};
  350. static const double HBKernel_4B[ 4 ] = { // -152.1535 dB, 12
  351. 5.9960155600862808e-001, -1.2228154335199336e-001,
  352. 2.5433718917694709e-002, -2.7537562530837154e-003,};
  353. static const double HBKernel_5B[ 5 ] = { // -188.2914 dB, 12
  354. 6.0676859170554343e-001, -1.3689667009876413e-001,
  355. 3.6288512631926818e-002, -6.7838855305035351e-003,
  356. 6.2345167677087547e-004,};
  357. static const double HBKernel_6B[ 6 ] = { // -224.2705 dB, 12
  358. 6.1161456341904397e-001, -1.4743901958274458e-001,
  359. 4.5344160157313275e-002, -1.1207371780924531e-002,
  360. 1.8328497112594935e-003, -1.4518193006359589e-004,};
  361. static const int FltCountB = 5;
  362. static const int FlttBaseB = 2;
  363. static const double FltAttensB[ FltCountB ] = {
  364. 71.0965, 115.7707, 152.1535, 188.2914, 224.2705, };
  365. static const double* const FltPtrsB[ FltCountB ] = {
  366. HBKernel_2B, HBKernel_3B, HBKernel_4B, HBKernel_5B, HBKernel_6B, };
  367. static const double HBKernel_1C[ 1 ] = { // -49.4544 dB, 24
  368. 5.0336730531430562e-001,};
  369. static const double HBKernel_2C[ 2 ] = { // -103.1970 dB, 24
  370. 5.6330232648142819e-001, -6.3309247177420452e-002,};
  371. static const double HBKernel_3C[ 3 ] = { // -152.1195 dB, 24
  372. 5.8643891113580415e-001, -9.8411593011583087e-002,
  373. 1.1972706651483846e-002,};
  374. static const double HBKernel_4C[ 4 ] = { // -200.6182 dB, 24
  375. 5.9851012363917222e-001, -1.2028885239978220e-001,
  376. 2.4294521083140615e-002, -2.5157924156609776e-003,};
  377. static const double HBKernel_5C[ 5 ] = { // -248.8730 dB, 24
  378. 6.0590922882030196e-001, -1.3515953438018685e-001,
  379. 3.5020857107815606e-002, -6.3256196990467053e-003,
  380. 5.5506815147598793e-004,};
  381. static const int FltCountC = 5;
  382. static const int FlttBaseC = 1;
  383. static const double FltAttensC[ FltCountC ] = {
  384. 49.4544, 103.1970, 152.1195, 200.6182, 248.8730, };
  385. static const double* const FltPtrsC[ FltCountC ] = {
  386. HBKernel_1C, HBKernel_2C, HBKernel_3C, HBKernel_4C, HBKernel_5C, };
  387. static const double HBKernel_1D[ 1 ] = { // -61.5357 dB, 48
  388. 5.0083794231068057e-001,};
  389. static const double HBKernel_2D[ 2 ] = { // -127.3167 dB, 48
  390. 5.6270074379958690e-001, -6.2701174487726344e-002,};
  391. static const double HBKernel_3D[ 3 ] = { // -188.2990 dB, 48
  392. 5.8606296210323228e-001, -9.7844644765123029e-002,
  393. 1.1781683046528768e-002,};
  394. static const double HBKernel_4D[ 4 ] = { // -248.8580 dB, 48
  395. 5.9823601243162516e-001, -1.1979368994739022e-001,
  396. 2.4017458606412575e-002, -2.4597810910081913e-003,};
  397. static const int FltCountD = 4;
  398. static const int FlttBaseD = 1;
  399. static const double FltAttensD[ FltCountD ] = {
  400. 61.5357, 127.3167, 188.2990, 248.8580, };
  401. static const double* const FltPtrsD[ FltCountD ] = {
  402. HBKernel_1D, HBKernel_2D, HBKernel_3D, HBKernel_4D, };
  403. static const double HBKernel_1E[ 1 ] = { // -77.4651 dB, 96
  404. 5.0013388897382527e-001,};
  405. static const double HBKernel_2E[ 2 ] = { // -151.4084 dB, 96
  406. 5.6255019604317880e-001, -6.2550222932381064e-002,};
  407. static const double HBKernel_3E[ 3 ] = { // -224.4365 dB, 96
  408. 5.8596887234201078e-001, -9.7703321113080305e-002,
  409. 1.1734448777069783e-002,};
  410. static const int FltCountE = 3;
  411. static const int FlttBaseE = 1;
  412. static const double FltAttensE[ FltCountE ] = {
  413. 77.4651, 151.4084, 224.4365, };
  414. static const double* const FltPtrsE[ FltCountE ] = {
  415. HBKernel_1E, HBKernel_2E, HBKernel_3E, };
  416. static const double HBKernel_1F[ 1 ] = { // -89.5075 dB, 192
  417. 5.0003346776264190e-001,};
  418. static const double HBKernel_2F[ 2 ] = { // -175.4932 dB, 192
  419. 5.6251254964097952e-001, -6.2512551321105267e-002,};
  420. static const double HBKernel_3F[ 3 ] = { // -260.5645 dB, 192
  421. 5.8594534336747051e-001, -9.7668015838639821e-002,
  422. 1.1722672471262996e-002,};
  423. static const int FltCountF = 3;
  424. static const int FlttBaseF = 1;
  425. static const double FltAttensF[ FltCountF ] = {
  426. 89.5075, 175.4932, 260.5645, };
  427. static const double* const FltPtrsF[ FltCountF ] = {
  428. HBKernel_1F, HBKernel_2F, HBKernel_3F, };
  429. static const double HBKernel_1G[ 1 ] = { // -101.5490 dB, 384
  430. 5.0000836666064941e-001,};
  431. static const double HBKernel_2G[ 2 ] = { // -199.5761 dB, 384
  432. 5.6250313744943459e-001, -6.2503137554435345e-002,};
  433. static const double HBKernel_3G[ 3 ] = { // -296.5185 dB, 384
  434. 5.8593945786963764e-001, -9.7659186853499613e-002,
  435. 1.1719728983863425e-002,};
  436. static const int FltCountG = 3;
  437. static const int FlttBaseG = 1;
  438. static const double FltAttensG[ FltCountG ] = {
  439. 101.5490, 199.5761, 296.5185, };
  440. static const double* const FltPtrsG[ FltCountG ] = {
  441. HBKernel_1G, HBKernel_2G, HBKernel_3G, };
  442. int k = 0;
  443. if( SteepIndex <= 0 )
  444. {
  445. while( k != FltCountA - 1 && FltAttensA[ k ] < ReqAtten )
  446. {
  447. k++;
  448. }
  449. flt = FltPtrsA[ k ];
  450. fltt = FlttBaseA + k;
  451. att = FltAttensA[ k ];
  452. }
  453. else
  454. if( SteepIndex == 1 )
  455. {
  456. while( k != FltCountB - 1 && FltAttensB[ k ] < ReqAtten )
  457. {
  458. k++;
  459. }
  460. flt = FltPtrsB[ k ];
  461. fltt = FlttBaseB + k;
  462. att = FltAttensB[ k ];
  463. }
  464. else
  465. if( SteepIndex == 2 )
  466. {
  467. while( k != FltCountC - 1 && FltAttensC[ k ] < ReqAtten )
  468. {
  469. k++;
  470. }
  471. flt = FltPtrsC[ k ];
  472. fltt = FlttBaseC + k;
  473. att = FltAttensC[ k ];
  474. }
  475. else
  476. if( SteepIndex == 3 )
  477. {
  478. while( k != FltCountD - 1 && FltAttensD[ k ] < ReqAtten )
  479. {
  480. k++;
  481. }
  482. flt = FltPtrsD[ k ];
  483. fltt = FlttBaseD + k;
  484. att = FltAttensD[ k ];
  485. }
  486. else
  487. if( SteepIndex == 4 )
  488. {
  489. while( k != FltCountE - 1 && FltAttensE[ k ] < ReqAtten )
  490. {
  491. k++;
  492. }
  493. flt = FltPtrsE[ k ];
  494. fltt = FlttBaseE + k;
  495. att = FltAttensE[ k ];
  496. }
  497. else
  498. if( SteepIndex == 5 )
  499. {
  500. while( k != FltCountF - 1 && FltAttensF[ k ] < ReqAtten )
  501. {
  502. k++;
  503. }
  504. flt = FltPtrsF[ k ];
  505. fltt = FlttBaseF + k;
  506. att = FltAttensF[ k ];
  507. }
  508. else
  509. {
  510. while( k != FltCountG - 1 && FltAttensG[ k ] < ReqAtten )
  511. {
  512. k++;
  513. }
  514. flt = FltPtrsG[ k ];
  515. fltt = FlttBaseG + k;
  516. att = FltAttensG[ k ];
  517. }
  518. }
  519. /**
  520. * Constructor initalizes the half-band upsampler.
  521. *
  522. * @param ReqAtten Required half-band filter attentuation.
  523. * @param SteepIndex Steepness index - 0=steepest. Corresponds to general
  524. * upsampling ratio, e.g. at 4x upsampling 0 is used, at 8x upsampling 1
  525. * is used, etc.
  526. * @param IsThird "True" if 1/3 of frequency response resampling is
  527. * performed.
  528. * @param PrevLatency Latency, in samples (any value >=0), which was left
  529. * in the output signal by a previous process. Whole-number latency will
  530. * be consumed by *this object while remaining fractional latency can be
  531. * obtained via the getLatencyFrac() function.
  532. * @param aDoConsumeLatency "True" if the output latency should be
  533. * consumed. Does not apply to the fractional part of the latency (if such
  534. * part is available).
  535. */
  536. CDSPHBUpsampler( const double ReqAtten, const int SteepIndex,
  537. const bool IsThird, const double PrevLatency,
  538. const bool aDoConsumeLatency = true )
  539. : DoConsumeLatency( aDoConsumeLatency )
  540. {
  541. static const CConvolveFn FltConvFn[ 14 ] = {
  542. &CDSPHBUpsampler :: convolve1, &CDSPHBUpsampler :: convolve2,
  543. &CDSPHBUpsampler :: convolve3, &CDSPHBUpsampler :: convolve4,
  544. &CDSPHBUpsampler :: convolve5, &CDSPHBUpsampler :: convolve6,
  545. &CDSPHBUpsampler :: convolve7, &CDSPHBUpsampler :: convolve8,
  546. &CDSPHBUpsampler :: convolve9, &CDSPHBUpsampler :: convolve10,
  547. &CDSPHBUpsampler :: convolve11, &CDSPHBUpsampler :: convolve12,
  548. &CDSPHBUpsampler :: convolve13, &CDSPHBUpsampler :: convolve14 };
  549. const double* fltp0;
  550. int fltt;
  551. double att;
  552. if( IsThird )
  553. {
  554. getHBFilterThird( ReqAtten, SteepIndex, fltp0, fltt, att );
  555. }
  556. else
  557. {
  558. getHBFilter( ReqAtten, SteepIndex, fltp0, fltt, att );
  559. }
  560. // Copy obtained filter to address-aligned buffer.
  561. fltp = alignptr( FltBuf, 16 );
  562. memcpy( fltp, fltp0, fltt * sizeof( fltp[ 0 ]));
  563. convfn = FltConvFn[ fltt - 1 ];
  564. fll = fltt - 1;
  565. fl2 = fltt;
  566. flo = fll + fl2;
  567. BufRP = Buf + fll;
  568. LatencyFrac = PrevLatency * 2.0;
  569. Latency = (int) LatencyFrac;
  570. LatencyFrac -= Latency;
  571. R8BASSERT( Latency >= 0 );
  572. if( DoConsumeLatency )
  573. {
  574. flb = BufLen - fll;
  575. }
  576. else
  577. {
  578. Latency += fl2 + fl2;
  579. flb = BufLen - flo;
  580. }
  581. R8BCONSOLE( "CDSPHBUpsampler: sti=%i third=%i taps=%i att=%.1f "
  582. "io=2/1\n", SteepIndex, (int) IsThird, fltt, att );
  583. clear();
  584. }
  585. virtual int getLatency() const
  586. {
  587. return( DoConsumeLatency ? 0 : Latency );
  588. }
  589. virtual double getLatencyFrac() const
  590. {
  591. return( LatencyFrac );
  592. }
  593. virtual int getMaxOutLen( const int MaxInLen ) const
  594. {
  595. R8BASSERT( MaxInLen >= 0 );
  596. return( MaxInLen << 1 );
  597. }
  598. virtual void clear()
  599. {
  600. if( DoConsumeLatency )
  601. {
  602. LatencyLeft = Latency;
  603. BufLeft = 0;
  604. }
  605. else
  606. {
  607. LatencyLeft = 0;
  608. BufLeft = fl2;
  609. }
  610. WritePos = 0;
  611. ReadPos = flb; // Set "read" position to account for filter's latency.
  612. memset( &Buf[ ReadPos ], 0, ( BufLen - flb ) * sizeof( Buf[ 0 ]));
  613. }
  614. virtual int process( double* ip, int l, double*& op0 )
  615. {
  616. R8BASSERT( l >= 0 );
  617. double* op = op0;
  618. while( l > 0 )
  619. {
  620. // Add new input samples to both halves of the ring buffer.
  621. const int b = min( min( l, BufLen - WritePos ), flb - BufLeft );
  622. double* const wp1 = Buf + WritePos;
  623. memcpy( wp1, ip, b * sizeof( wp1[ 0 ]));
  624. if( WritePos < flo )
  625. {
  626. const int c = min( b, flo - WritePos );
  627. memcpy( wp1 + BufLen, wp1, c * sizeof( wp1[ 0 ]));
  628. }
  629. ip += b;
  630. WritePos = ( WritePos + b ) & BufLenMask;
  631. l -= b;
  632. BufLeft += b;
  633. // Produce output.
  634. if( BufLeft > fl2 )
  635. {
  636. const int c = BufLeft - fl2;
  637. double* const opend = op + ( c + c );
  638. ( *convfn )( op, opend, fltp, BufRP, ReadPos );
  639. op = opend;
  640. ReadPos = ( ReadPos + c ) & BufLenMask;
  641. BufLeft -= c;
  642. }
  643. }
  644. int ol = (int) ( op - op0 );
  645. if( LatencyLeft != 0 )
  646. {
  647. if( LatencyLeft >= ol )
  648. {
  649. LatencyLeft -= ol;
  650. return( 0 );
  651. }
  652. ol -= LatencyLeft;
  653. op0 += LatencyLeft;
  654. LatencyLeft = 0;
  655. }
  656. return( ol );
  657. }
  658. private:
  659. static const int BufLenBits = 9; ///< The length of the ring buffer,
  660. ///< expressed as Nth power of 2. This value can be reduced if it is
  661. ///< known that only short input buffers will be passed to the
  662. ///< interpolator. The minimum value of this parameter is 5, and
  663. ///< 1 << BufLenBits should be at least 3 times larger than the
  664. ///< FilterLen.
  665. ///<
  666. static const int BufLen = 1 << BufLenBits; ///< The length of the ring
  667. ///< buffer. The actual length is twice as long to allow "beyond max
  668. ///< position" positioning.
  669. ///<
  670. static const int BufLenMask = BufLen - 1; ///< Mask used for quick buffer
  671. ///< position wrapping.
  672. ///<
  673. double Buf[ BufLen + 27 ]; ///< The ring buffer, including overrun
  674. ///< protection for the largest filter.
  675. ///<
  676. double FltBuf[ 14 + 2 ]; ///< Holder for half-band filter taps, used with
  677. ///< 16-byte address-aligning, for SIMD use.
  678. ///<
  679. double* fltp; ///< Half-band filter taps, points to FltBuf.
  680. ///<
  681. int fll; ///< Input latency.
  682. ///<
  683. int fl2; ///< Right-side filter length.
  684. ///<
  685. int flo; ///< Overrrun length.
  686. ///<
  687. int flb; ///< Initial read position and maximal buffer write length.
  688. ///<
  689. const double* BufRP; ///< Offseted Buf pointer at ReadPos=0.
  690. ///<
  691. bool DoConsumeLatency; ///< "True" if the output latency should be
  692. ///< consumed. Does not apply to the fractional part of the latency
  693. ///< (if such part is available).
  694. ///<
  695. int Latency; ///< Initial latency that should be removed from the output.
  696. ///<
  697. double LatencyFrac; ///< Fractional latency left on the output.
  698. ///<
  699. int BufLeft; ///< The number of samples left in the buffer to process.
  700. ///< When this value is below FilterLenD2Plus1, the interpolation
  701. ///< cycle ends.
  702. ///<
  703. int WritePos; ///< The current buffer write position. Incremented together
  704. ///< with the BufLeft variable.
  705. ///<
  706. int ReadPos; ///< The current buffer read position.
  707. ///<
  708. int LatencyLeft; ///< Latency left to remove.
  709. ///<
  710. typedef void( *CConvolveFn )( double* op, double* const opend,
  711. const double* const flt, const double* const rp0, int rpos ); ///<
  712. ///< Convolution function type.
  713. ///<
  714. CConvolveFn convfn; ///< Convolution function in use.
  715. ///<
  716. #define R8BHBC1( fn ) \
  717. static void fn( double* op, double* const opend, const double* const flt, \
  718. const double* const rp0, int rpos ) \
  719. { \
  720. while( op != opend ) \
  721. { \
  722. const double* const rp = rp0 + rpos; \
  723. op[ 0 ] = rp[ 0 ];
  724. #define R8BHBC2 \
  725. rpos = ( rpos + 1 ) & BufLenMask; \
  726. op += 2; \
  727. } \
  728. }
  729. #include "CDSPHBUpsampler.inc"
  730. #undef R8BHBC1
  731. #undef R8BHBC2
  732. };
  733. // ---------------------------------------------------------------------------
  734. } // namespace r8b
  735. #endif // R8B_CDSPHBUPSAMPLER_INCLUDED