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.

r8bbase.h 33KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123
  1. //$ nobt
  2. /**
  3. * @file r8bbase.h
  4. *
  5. * @brief The "base" inclusion file with basic classes and functions.
  6. *
  7. * This is the "base" inclusion file for the "r8brain-free-src" sample rate
  8. * converter. This inclusion file contains implementations of several small
  9. * utility classes and functions used by the library.
  10. *
  11. * r8brain-free-src Copyright (c) 2013-2014 Aleksey Vaneev
  12. * See the "License.txt" file for license.
  13. *
  14. * @mainpage
  15. *
  16. * @section intro_sec Introduction
  17. *
  18. * Open source (under the MIT license) high-quality professional audio sample
  19. * rate converter (SRC) (resampling) library. Features routines for SRC, both
  20. * up- and downsampling, to/from any sample rate, including non-integer sample
  21. * rates: it can be also used for conversion to/from SACD sample rate and even
  22. * go beyond that. SRC routines were implemented in multi-platform C++ code,
  23. * and have a high level of optimality.
  24. *
  25. * The structure of this library's objects is such that they can be frequently
  26. * created and destroyed in large applications with a minimal performance
  27. * impact due to a high level of reusability of its most
  28. * "initialization-expensive" objects: the fast Fourier transform and FIR
  29. * filter objects.
  30. *
  31. * The SRC algorithm at first produces 2X oversampled (relative to the source
  32. * sample rate, or the destination sample rate if the downsampling is
  33. * performed) signal and then performs interpolation using a bank of short
  34. * (14 to 28 taps, depending on the required precision)
  35. * polynomial-interpolated sinc function-based fractional delay filters. This puts the
  36. * algorithm into the league of the fastest among the most precise SRC
  37. * algorithms. The more precise alternative being only the whole
  38. * number-factored SRC, which can be slower.
  39. *
  40. * @section requirements Requirements
  41. *
  42. * C++ compiler and system with the "double" floating point type (53-bit
  43. * mantissa) support. No explicit code for the "float" type is present in this
  44. * library, because as practice has shown the "float"-based code performs
  45. * considerably slower on a modern processor, at least in this library.
  46. * However, if the "double" type really represents the "float" type (24-bit
  47. * mantissa) in a given compiler, on a given system, the library won't become
  48. * broken, only the conversion quality may become degraded. This library
  49. * always uses the "sizeof( double )" operator to obtain "double" floating
  50. * point type's size in bytes. This library does not have dependencies beside
  51. * the standard C library, the "windows.h" on Windows and the "pthread.h" on
  52. * Mac OS X and Linux.
  53. *
  54. * @section usage Usage Information
  55. *
  56. * The sample rate converter (resampler) is represented by the
  57. * r8b::CDSPResampler class, which is a single front-end class for the whole
  58. * library. You do not basically need to use nor understand any other classes
  59. * beside this class. Several derived classes that have varying levels of
  60. * precision are also available.
  61. *
  62. * The code of the library resides in the "r8b" C++ namespace, effectively
  63. * isolating it from all other code. The code is thread-safe. A separate
  64. * resampler object should be created for each audio channel or stream being
  65. * processed.
  66. *
  67. * Note that you will need to compile the "r8bbase.cpp" source file and
  68. * include the resulting object file into your application build. This source
  69. * file includes definitions of several global static objects used by the
  70. * library. You may also need to include to your project: the "Kernel32"
  71. * library (on Windows) and the "pthread" library on Mac OS X and Linux.
  72. *
  73. * The library is able to process signal of any scale and loudness: it is not
  74. * limited to just a "usual" -1.0 to 1.0 range.
  75. *
  76. * The code of this library was commented in the Doxygen style. To generate
  77. * the documentation locally you may run the "doxygen ./other/r8bdoxy.txt"
  78. * command from the library's directory.
  79. *
  80. * Preliminary tests show that the r8b::CDSPResampler24 resampler class
  81. * achieves 15.6*n_cores Mflops when converting 1 channel of audio from 44100
  82. * to 96000 sample rate, on a typical Intel Core i7-4770K processor-based
  83. * system without overclocking. This approximately translates to a real-time
  84. * resampling of 160*n_cores audio streams, at 100% CPU load.
  85. *
  86. * @section dll Dynamic Link Library
  87. *
  88. * The functions of this SRC library are also accessible in simplified form
  89. * via the DLL file on Windows, requiring a processor with SSE2 support.
  90. * Delphi Pascal interface unit file for the DLL file is available. DLL and
  91. * C LIB files are distributed in a separate ZIP file on the project's home
  92. * page. On non-Windows systems it is preferrable to use the C++ library
  93. * directly.
  94. *
  95. * @section realtime Real-time Applications
  96. *
  97. * The resampler class of this library was designed as asynchronous processor:
  98. * it may produce any number of output samples, depending on the input sample
  99. * data length and the resampling parameters. The resampler must be fed with
  100. * the input sample data until enough output sample data was produced, with
  101. * any excess output samples used before feeding the resampler with more input
  102. * data. A "relief" factor here is that the resampler removes the initial
  103. * processing latency automatically, and that after initial moments of
  104. * processing the output becomes steady, with only minor output sample data
  105. * length fluctuations.
  106. *
  107. * Note that the r8b::CDSPResampler::getInLenBeforeOutStart() function can be
  108. * used to estimate the number of input samples that should be provided to the
  109. * resampler before the actual output starts.
  110. *
  111. * @section notes Notes
  112. *
  113. * When using the r8b::CDSPResampler<> class directly, you may select the
  114. * transition band/steepness of the low-pass (reconstruction) filter,
  115. * expressed as a percentage of the full spectral bandwidth of the input
  116. * signal (or the output signal if the downsampling is performed), and the
  117. * desired stop-band attenuation in decibel.
  118. *
  119. * The transition band is specified as the normalized spectral space of the
  120. * input signal (or the output signal if the downsampling is performed)
  121. * between the low-pass filter's -3 dB point and the Nyquist frequency, and
  122. * ranges from 0.5% to 45%. Stop-band attenuation can be specified in the
  123. * range 49 to 218 decibel.
  124. *
  125. * This SRC library also implements a faster "power of 2" resampling (e.g. 2X,
  126. * 4X, 8X, 16X, etc. upsampling and downsampling).
  127. *
  128. * This library was tested for compatibility with GNU C++, Microsoft Visual
  129. * C++ and Intel C++ compilers, on 32- and 64-bit Windows, Mac OS X and CentOS
  130. * Linux.
  131. *
  132. * All code is fully "inline", without the need to compile many source files.
  133. * The memory footprint is quite modest.
  134. *
  135. * @section users Users
  136. *
  137. * This library is used by:
  138. *
  139. * * http://www.martinic.com/combov/ Combo Model V VSTi instrument
  140. * * http://midithru.net/Home/AsioLink WDM Asio Link Driver
  141. *
  142. * @section license License
  143. *
  144. * The MIT License (MIT)
  145. *
  146. * r8brain-free-src Copyright (c) 2013-2014 Aleksey Vaneev
  147. *
  148. * Permission is hereby granted, free of charge, to any person obtaining a
  149. * copy of this software and associated documentation files (the "Software"),
  150. * to deal in the Software without restriction, including without limitation
  151. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  152. * and/or sell copies of the Software, and to permit persons to whom the
  153. * Software is furnished to do so, subject to the following conditions:
  154. *
  155. * The above copyright notice and this permission notice shall be included in
  156. * all copies or substantial portions of the Software.
  157. *
  158. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  159. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  160. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  161. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  162. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  163. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  164. * DEALINGS IN THE SOFTWARE.
  165. *
  166. * Please credit the creator of this library in your documentation in the
  167. * following way: "Sample rate converter designed by Aleksey Vaneev of
  168. * Voxengo"
  169. *
  170. * @version 1.6
  171. */
  172. #pragma once
  173. #include <stdlib.h>
  174. #include <string.h>
  175. #include <math.h>
  176. #include "r8bconf.h"
  177. #if defined( R8B_WIN )
  178. #include <windows.h>
  179. #else // R8B_WIN
  180. #include <pthread.h>
  181. #endif // R8B_WIN
  182. /**
  183. * @brief The "r8brain-free-src" library namespace.
  184. *
  185. * The "r8brain-free-src" sample rate converter library namespace.
  186. */
  187. namespace r8b
  188. {
  189. #if !defined( M_PI )
  190. /**
  191. * The macro equals to "pi" constant, fits 53-bit floating point mantissa.
  192. */
  193. #define M_PI 3.14159265358979324
  194. #endif // M_PI
  195. #if !defined( M_2PI )
  196. /**
  197. * The M_2PI macro equals to "2 * pi" constant, fits 53-bit floating point
  198. * mantissa.
  199. */
  200. #define M_2PI 6.28318530717958648
  201. #endif // M_2PI
  202. #if !defined( M_3PI )
  203. /**
  204. * The M_3PI macro equals to "3 * pi" constant, fits 53-bit floating point
  205. * mantissa.
  206. */
  207. #define M_3PI 9.42477796076937972
  208. #endif // M_3PI
  209. #if !defined( M_4PI )
  210. /**
  211. * The M_4PI macro equals to "4 * pi" constant, fits 53-bit floating point
  212. * mantissa.
  213. */
  214. #define M_4PI 12.56637061435917295
  215. #endif // M_4PI
  216. #if !defined( M_PId2 )
  217. /**
  218. * The macro equals to "pi divided by 2" constant, fits 53-bit floating
  219. * point mantissa.
  220. */
  221. #define M_PId2 1.57079632679489662
  222. #endif // M_PId2
  223. /**
  224. * A special macro that defines empty copy-constructor and copy operator with
  225. * the "private:" prefix. This macro should be used in classes that cannot be
  226. * copied in a standard C++ way.
  227. *
  228. * This macro does not need to be defined in classes derived from a class
  229. * where such macro was already used.
  230. *
  231. * @param ClassName The name of the class which uses this macro.
  232. */
  233. #define R8BNOCTOR( ClassName ) \
  234. private: \
  235. ClassName( const ClassName& ) { } \
  236. ClassName& operator = ( const ClassName& ) { return( *this ); }
  237. /**
  238. * @brief The default base class for objects created on heap.
  239. *
  240. * Class that implements "new" and "delete" operators that use standard
  241. * malloc() and free() functions.
  242. */
  243. class CStdClassAllocator
  244. {
  245. public:
  246. /**
  247. * @param n The size of the object, in bytes.
  248. * @param p Pointer to object's pre-allocated memory block.
  249. * @return Pointer to object.
  250. */
  251. void* operator new(size_t, void* p) { return (p); }
  252. /**
  253. * @param n The size of the object, in bytes.
  254. * @return Pointer to the allocated memory block for the object.
  255. */
  256. void* operator new(size_t n) { return (malloc(n)); }
  257. /**
  258. * @param n The size of the object, in bytes.
  259. * @return Pointer to the allocated memory block for the object.
  260. */
  261. void* operator new[](size_t n) { return (malloc(n)); }
  262. /**
  263. * Operator frees a previously allocated memory block for the object.
  264. *
  265. * @param p Pointer to the allocated memory block for the object.
  266. */
  267. void operator delete(void* p) { free(p); }
  268. /**
  269. * Operator frees a previously allocated memory block for the object.
  270. *
  271. * @param p Pointer to the allocated memory block for the object.
  272. */
  273. void operator delete[](void* p) { free(p); }
  274. };
  275. /**
  276. * @brief The default base class for objects that allocate blocks of memory.
  277. *
  278. * Memory buffer allocator that uses "stdlib" standard memory functions.
  279. */
  280. class CStdMemAllocator : public CStdClassAllocator
  281. {
  282. public:
  283. /**
  284. * Function allocates memory block.
  285. *
  286. * @param Size The size of the block, in bytes.
  287. * @result The pointer to the allocated block.
  288. */
  289. static void* allocmem(const size_t Size) { return (malloc(Size)); }
  290. /**
  291. * Function reallocates a previously allocated memory block.
  292. *
  293. * @param p Pointer to the allocated block, can be NULL.
  294. * @param Size The new size of the block, in bytes.
  295. * @result The pointer to the (re)allocated block.
  296. */
  297. static void* reallocmem(void* p, const size_t Size) { return (realloc(p, Size)); }
  298. /**
  299. * Function frees a previously allocated memory block.
  300. *
  301. * @param p Pointer to the allocated block, can be NULL.
  302. */
  303. static void freemem(void* p) { free(p); }
  304. };
  305. /**
  306. * @brief Templated memory buffer class for element buffers of fixed capacity.
  307. *
  308. * Fixed memory buffer object. Supports allocation of a fixed amount of
  309. * memory. Does not store buffer's capacity - the user should know the actual
  310. * capacity of the buffer. Does not feature "internal" storage, memory is
  311. * always allocated via the R8B_MEMALLOCCLASS class's functions. Thus the
  312. * object of this class can be moved in memory.
  313. *
  314. * This class manages memory space only - it does not perform element class
  315. * construction nor destruction operations.
  316. *
  317. * @param T The class of the stored elements (e.g. "double").
  318. */
  319. template <class T>
  320. class CFixedBuffer : public R8B_MEMALLOCCLASS
  321. {
  322. R8BNOCTOR(CFixedBuffer)
  323. public:
  324. CFixedBuffer() : Data(nullptr) { }
  325. /**
  326. * Constructor allocates memory so that the specified number of elements
  327. * of type T can be stored in *this buffer object.
  328. *
  329. * @param Capacity Storage for this number of elements to allocate.
  330. */
  331. CFixedBuffer(const int Capacity)
  332. {
  333. R8BASSERT(Capacity > 0 || Capacity == 0);
  334. Data = (T*)allocmem(Capacity * sizeof(T));
  335. R8BASSERT(Data != nullptr || Capacity == 0);
  336. }
  337. ~CFixedBuffer() { freemem(Data); }
  338. /**
  339. * Function allocates memory so that the specified number of elements of
  340. * type T can be stored in *this buffer object.
  341. *
  342. * @param Capacity Storage for this number of elements to allocate.
  343. */
  344. void alloc(const int Capacity)
  345. {
  346. R8BASSERT(Capacity > 0 || Capacity == 0);
  347. freemem(Data);
  348. Data = (T*)allocmem(Capacity * sizeof(T));
  349. R8BASSERT(Data != nullptr || Capacity == 0);
  350. }
  351. /**
  352. * Function deallocates a previously allocated buffer.
  353. */
  354. void free()
  355. {
  356. freemem(Data);
  357. Data = NULL;
  358. }
  359. /**
  360. * @return Pointer to the first element of the allocated buffer, nullptr if
  361. * not allocated.
  362. */
  363. T* getPtr() const { return (Data); }
  364. /**
  365. * @return Pointer to the first element of the allocated buffer, nullptr if
  366. * not allocated.
  367. */
  368. operator T*() const { return (Data); }
  369. private:
  370. T* Data = nullptr; ///< Element buffer pointer.
  371. ///<
  372. };
  373. /**
  374. * @brief Pointer-to-object "keeper" class with automatic deletion.
  375. *
  376. * An auxiliary class that can be used for keeping a pointer to object that
  377. * should be deleted together with the "keeper" by calling object's "delete"
  378. * operator.
  379. *
  380. * @param T Pointer type to operate with, must include the asterisk (e.g.
  381. * "CDSPFIRFilter*").
  382. */
  383. template <class T>
  384. class CPtrKeeper
  385. {
  386. R8BNOCTOR(CPtrKeeper)
  387. public:
  388. CPtrKeeper() : Object(NULL) { }
  389. /**
  390. * Constructor assigns a pointer to object to *this keeper.
  391. *
  392. * @param aObject Pointer to object to keep, can be NULL.
  393. */
  394. template <class T2>
  395. CPtrKeeper(T2 const aObject) : Object(aObject) { }
  396. ~CPtrKeeper() { delete Object; }
  397. /**
  398. * Function assigns a pointer to object to *this keeper. A previously
  399. * keeped pointer will be reset and object deleted.
  400. *
  401. * @param aObject Pointer to object to keep, can be NULL.
  402. */
  403. template <class T2>
  404. void operator =(T2 const aObject)
  405. {
  406. reset();
  407. Object = aObject;
  408. }
  409. /**
  410. * @return Pointer to keeped object, nullptr if no object is being kept.
  411. */
  412. T operator ->() const { return (Object); }
  413. /**
  414. * @return Pointer to keeped object, nullptr if no object is being kept.
  415. */
  416. operator T() const { return (Object); }
  417. /**
  418. * Function resets the keeped pointer and deletes the keeped object.
  419. */
  420. void reset()
  421. {
  422. T DelObj = Object;
  423. Object = NULL;
  424. delete DelObj;
  425. }
  426. /**
  427. * @return Function returns the keeped pointer and resets it in *this
  428. * keeper without object deletion.
  429. */
  430. T unkeep()
  431. {
  432. T ResObject = Object;
  433. Object = NULL;
  434. return (ResObject);
  435. }
  436. private:
  437. T Object; ///< Pointer to keeped object.
  438. ///<
  439. };
  440. /**
  441. * @brief Multi-threaded synchronization object class.
  442. *
  443. * This class uses standard OS thread-locking (mutex) mechanism which is
  444. * fairly efficient in most cases.
  445. *
  446. * The acquire() function can be called recursively, in the same thread, for
  447. * this kind of thread-locking mechanism. This will not produce a dead-lock.
  448. */
  449. class CSyncObject
  450. {
  451. R8BNOCTOR(CSyncObject)
  452. public:
  453. CSyncObject()
  454. {
  455. #if defined( R8B_WIN )
  456. InitializeCriticalSectionAndSpinCount(&CritSec, 4000);
  457. #else // R8B_WIN
  458. pthread_mutexattr_t MutexAttrs;
  459. pthread_mutexattr_init( &MutexAttrs );
  460. pthread_mutexattr_settype( &MutexAttrs, PTHREAD_MUTEX_RECURSIVE );
  461. pthread_mutex_init( &Mutex, &MutexAttrs );
  462. pthread_mutexattr_destroy( &MutexAttrs );
  463. #endif // R8B_WIN
  464. }
  465. ~CSyncObject()
  466. {
  467. #if defined( R8B_WIN )
  468. DeleteCriticalSection(&CritSec);
  469. #else // R8B_WIN
  470. pthread_mutex_destroy( &Mutex );
  471. #endif // R8B_WIN
  472. }
  473. /**
  474. * Function "acquires" *this thread synchronizer object immediately or
  475. * waits until another thread releases it.
  476. */
  477. void acquire()
  478. {
  479. #if defined( R8B_WIN )
  480. EnterCriticalSection(&CritSec);
  481. #else // R8B_WIN
  482. pthread_mutex_lock( &Mutex );
  483. #endif // R8B_WIN
  484. }
  485. /**
  486. * Function "releases" *this previously acquired thread synchronizer
  487. * object.
  488. */
  489. void release()
  490. {
  491. #if defined( R8B_WIN )
  492. LeaveCriticalSection(&CritSec);
  493. #else // R8B_WIN
  494. pthread_mutex_unlock( &Mutex );
  495. #endif // R8B_WIN
  496. }
  497. private:
  498. #if defined( R8B_WIN )
  499. CRITICAL_SECTION CritSec; ///< Standard Windows critical section
  500. ///< structure.
  501. ///<
  502. #else // R8B_WIN
  503. pthread_mutex_t Mutex; ///< pthread.h mutex object.
  504. ///<
  505. #endif // R8B_WIN
  506. };
  507. /**
  508. * @brief A "keeper" class for CSyncObject-based synchronization.
  509. *
  510. * Sync keeper class. The object of this class can be used as auto-init and
  511. * auto-deinit object for calling the acquire() and release() functions of an
  512. * object of the CSyncObject class. This "keeper" object is best used in
  513. * functions as an "automatic" object allocated on the stack, possibly via the
  514. * R8BSYNC() macro.
  515. */
  516. class CSyncKeeper
  517. {
  518. R8BNOCTOR(CSyncKeeper)
  519. public:
  520. CSyncKeeper() { }
  521. /**
  522. * @param aSyncObj Pointer to the sync object which should be used for
  523. * sync'ing, can be NULL.
  524. */
  525. CSyncKeeper(CSyncObject* const aSyncObj) : SyncObj(aSyncObj) { if (SyncObj != nullptr) { SyncObj->acquire(); } }
  526. /**
  527. * @param aSyncObj Reference to the sync object which should be used for
  528. * sync'ing.
  529. */
  530. CSyncKeeper(CSyncObject& aSyncObj) : SyncObj(&aSyncObj) { SyncObj->acquire(); }
  531. ~CSyncKeeper() { if (SyncObj != nullptr) { SyncObj->release(); } }
  532. protected:
  533. CSyncObject* SyncObj = nullptr; ///< Sync object in use (can be NULL).
  534. ///<
  535. };
  536. /**
  537. * The synchronization macro. The R8BSYNC( obj ) macro, which creates and
  538. * object of the r8b::CSyncKeeper class on stack, should be put before
  539. * sections of the code that may potentially change data asynchronously with
  540. * other threads at the same time. The R8BSYNC( obj ) macro "acquires" the
  541. * synchronization object thus blocking execution of other threads that also
  542. * use the same R8BSYNC( obj ) macro. The blocked section begins with the
  543. * R8BSYNC( obj ) macro and finishes at the end of the current C++ code block.
  544. * Multiple R8BSYNC() macros may be defined from within the same code block.
  545. *
  546. * @param SyncObject An object of the CSyncObject type that is used for
  547. * synchronization.
  548. */
  549. #define R8BSYNC( SyncObject ) R8BSYNC_( SyncObject, __LINE__ )
  550. #define R8BSYNC_( SyncObject, id ) R8BSYNC__( SyncObject, id )
  551. #define R8BSYNC__( SyncObject, id ) CSyncKeeper SyncKeeper##id( SyncObject )
  552. /**
  553. * @brief Sine signal generator class.
  554. *
  555. * Class implements sine signal generator without biasing.
  556. */
  557. class CSineGen
  558. {
  559. public:
  560. CSineGen() { }
  561. /**
  562. * Constructor initializes *this sine signal generator.
  563. *
  564. * @param si Sine function increment, in radians.
  565. * @param ph Starting phase, in radians. Add 0.5 * M_PI for cosine
  566. * function.
  567. */
  568. CSineGen(const double si, const double ph) : svalue1(sin(ph)), svalue2(sin(ph - si)), sincr(2.0 * cos(si)) { }
  569. /**
  570. * Constructor initializes *this sine signal generator.
  571. *
  572. * @param si Sine function increment, in radians.
  573. * @param ph Starting phase, in radians. Add 0.5 * M_PI for cosine
  574. * function.
  575. * @param g The overall gain factor, 1.0 for unity gain (-1.0 to 1.0
  576. * amplitude).
  577. */
  578. CSineGen(const double si, const double ph, const double g) : svalue1(sin(ph) * g), svalue2(sin(ph - si) * g), sincr(2.0 * cos(si)) { }
  579. /**
  580. * Function initializes *this sine signal generator.
  581. *
  582. * @param si Sine function increment, in radians.
  583. * @param ph Starting phase, in radians. Add 0.5 * M_PI for cosine
  584. * function.
  585. */
  586. void init(const double si, const double ph)
  587. {
  588. svalue1 = sin(ph);
  589. svalue2 = sin(ph - si);
  590. sincr = 2.0 * cos(si);
  591. }
  592. /**
  593. * Function initializes *this sine signal generator.
  594. *
  595. * @param si Sine function increment, in radians.
  596. * @param ph Starting phase, in radians. Add 0.5 * M_PI for cosine
  597. * function.
  598. * @param g The overall gain factor, 1.0 for unity gain (-1.0 to 1.0
  599. * amplitude).
  600. */
  601. void init(const double si, const double ph, const double g)
  602. {
  603. svalue1 = sin(ph) * g;
  604. svalue2 = sin(ph - si) * g;
  605. sincr = 2.0 * cos(si);
  606. }
  607. /**
  608. * @return Next value of the sine function, without biasing.
  609. */
  610. double generate()
  611. {
  612. const double res = svalue1;
  613. svalue1 = sincr * res - svalue2;
  614. svalue2 = res;
  615. return (res);
  616. }
  617. private:
  618. double svalue1 = 0; ///< Current sine value.
  619. ///<
  620. double svalue2 = 0; ///< Previous sine value.
  621. ///<
  622. double sincr = 0; ///< Sine value increment.
  623. ///<
  624. };
  625. /**
  626. * @param v Input value.
  627. * @return Calculated bit occupancy of the specified input value. Bit
  628. * occupancy means how many significant lower bits are necessary to store a
  629. * specified value. Function treats the input value as unsigned.
  630. */
  631. inline int getBitOccupancy(const int v)
  632. {
  633. static const char OccupancyTable[] =
  634. {
  635. 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
  636. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  637. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  638. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  639. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  640. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  641. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  642. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  643. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  644. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  645. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  646. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  647. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  648. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  649. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  650. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
  651. };
  652. const int tt = v >> 16;
  653. if (tt != 0)
  654. {
  655. const int t = v >> 24;
  656. return (t != 0 ? 24 + OccupancyTable[t & 0xFF] : 16 + OccupancyTable[tt]);
  657. }
  658. const int t = v >> 8;
  659. return (t != 0 ? 8 + OccupancyTable[t] : OccupancyTable[v]);
  660. }
  661. /**
  662. * Function calculates frequency response of the specified FIR filter at the
  663. * specified circular frequency. Phase can be calculated as atan2( im, re ).
  664. *
  665. * @param flt FIR filter's coefficients.
  666. * @param fltlen Number of coefficients (taps) in the filter.
  667. * @param th Circular frequency [0; pi].
  668. * @param[out] re0 Resulting real part of the complex frequency response.
  669. * @param[out] im0 Resulting imaginary part of the complex frequency response.
  670. * @param fltlat Filter's latency in samples.
  671. */
  672. inline void calcFIRFilterResponse(const double* flt, int fltlen, const double th, double& re0, double& im0, const int fltlat = 0)
  673. {
  674. const double sincr = 2.0 * cos(th);
  675. double cvalue1;
  676. double svalue1;
  677. if (fltlat == 0)
  678. {
  679. cvalue1 = 1.0;
  680. svalue1 = 0.0;
  681. }
  682. else
  683. {
  684. cvalue1 = cos(-fltlat * th);
  685. svalue1 = sin(-fltlat * th);
  686. }
  687. double cvalue2 = cos(-(fltlat + 1) * th);
  688. double svalue2 = sin(-(fltlat + 1) * th);
  689. double re = 0.0;
  690. double im = 0.0;
  691. while (fltlen > 0)
  692. {
  693. re += cvalue1 * flt[0];
  694. im += svalue1 * flt[0];
  695. flt++;
  696. fltlen--;
  697. double tmp = cvalue1;
  698. cvalue1 = sincr * cvalue1 - cvalue2;
  699. cvalue2 = tmp;
  700. tmp = svalue1;
  701. svalue1 = sincr * svalue1 - svalue2;
  702. svalue2 = tmp;
  703. }
  704. re0 = re;
  705. im0 = im;
  706. }
  707. /**
  708. * Function calculates frequency response and group delay of the specified FIR
  709. * filter at the specified circular frequency. The group delay is calculated
  710. * by evaluating the filter's response at close side-band frequencies of "th".
  711. *
  712. * @param flt FIR filter's coefficients.
  713. * @param fltlen Number of coefficients (taps) in the filter.
  714. * @param th Circular frequency [0; pi].
  715. * @param[out] re Resulting real part of the complex frequency response.
  716. * @param[out] im Resulting imaginary part of the complex frequency response.
  717. * @param[out] gd Resulting group delay at the specified frequency, in
  718. * samples.
  719. */
  720. inline void calcFIRFilterResponseAndGroupDelay(const double* const flt, const int fltlen, const double th, double& re, double& im, double& gd)
  721. {
  722. // Calculate response at "th".
  723. calcFIRFilterResponse(flt, fltlen, th, re, im);
  724. // Calculate response at close sideband frequencies.
  725. const int Count = 2;
  726. const double thd2 = 1e-9;
  727. double ths[ Count ] = { th - thd2, th + thd2 };
  728. if (ths[0] < 0.0) { ths[0] = 0.0; }
  729. if (ths[1] > M_PI) { ths[1] = M_PI; }
  730. double ph1[ Count ];
  731. for (int i = 0; i < Count; ++i)
  732. {
  733. double re1;
  734. double im1;
  735. calcFIRFilterResponse(flt, fltlen, ths[i], re1, im1);
  736. ph1[i] = atan2(im1, re1);
  737. }
  738. if (fabs(ph1[1] - ph1[0]) > M_PI)
  739. {
  740. if (ph1[1] > ph1[0]) { ph1[1] -= M_2PI; }
  741. else { ph1[1] += M_2PI; }
  742. }
  743. const double thd = ths[1] - ths[0];
  744. gd = (ph1[1] - ph1[0]) / -thd;
  745. }
  746. /**
  747. * Function normalizes FIR filter so that its frequency response at DC is
  748. * equal to DCGain.
  749. *
  750. * @param[in,out] p Filter coefficients.
  751. * @param l Filter length.
  752. * @param DCGain Filter's gain at DC (linear, non-decibel value).
  753. * @param pstep "p" array step.
  754. */
  755. inline void normalizeFIRFilter(double* const p, const int l, const double DCGain, const int pstep = 1)
  756. {
  757. R8BASSERT(l > 0);
  758. R8BASSERT(pstep != 0);
  759. double s = 0.0;
  760. double* pp = p;
  761. int i = l;
  762. while (i > 0)
  763. {
  764. s += *pp;
  765. pp += pstep;
  766. i--;
  767. }
  768. s = DCGain / s;
  769. pp = p;
  770. i = l;
  771. while (i > 0)
  772. {
  773. *pp *= s;
  774. pp += pstep;
  775. i--;
  776. }
  777. }
  778. /**
  779. * Function calculates coefficients used to calculate 3rd order spline
  780. * (polynomial) on the equidistant lattice, using 8 points.
  781. *
  782. * @param[out] c Output coefficients buffer, length = 4.
  783. * @param xm3 Point at x-3 position.
  784. * @param xm2 Point at x-2 position.
  785. * @param xm1 Point at x-1 position.
  786. * @param x0 Point at x position.
  787. * @param x1 Point at x+1 position.
  788. * @param x2 Point at x+2 position.
  789. * @param x3 Point at x+3 position.
  790. * @param x4 Point at x+4 position.
  791. */
  792. inline void calcSpline3p8Coeffs(double* c, const double xm3, const double xm2, const double xm1, const double x0, const double x1, const double x2,
  793. const double x3, const double x4)
  794. {
  795. c[0] = x0;
  796. c[1] = (61.0 * (x1 - xm1) + 16.0 * (xm2 - x2) + 3.0 * (x3 - xm3)) / 76.0;
  797. c[2] = (106.0 * (xm1 + x1) + 10.0 * x3 + 6.0 * xm3 - 3.0 * x4 - 29.0 * (xm2 + x2) - 167.0 * x0) / 76.0;
  798. c[3] = (91.0 * (x0 - x1) + 45.0 * (x2 - xm1) + 13.0 * (xm2 - x3) + 3.0 * (x4 - xm3)) / 76.0;
  799. }
  800. /**
  801. * Function calculates coefficients used to calculate 2rd order spline
  802. * (polynomial) on the equidistant lattice, using 8 points. This function is
  803. * based on the calcSpline3Coeffs8() function, but without the 3rd order
  804. * coefficient.
  805. *
  806. * @param[out] c Output coefficients buffer, length = 3.
  807. * @param xm3 Point at x-3 position.
  808. * @param xm2 Point at x-2 position.
  809. * @param xm1 Point at x-1 position.
  810. * @param x0 Point at x position.
  811. * @param x1 Point at x+1 position.
  812. * @param x2 Point at x+2 position.
  813. * @param x3 Point at x+3 position.
  814. * @param x4 Point at x+4 position.
  815. */
  816. inline void calcSpline2p8Coeffs(double* c, const double xm3, const double xm2, const double xm1, const double x0, const double x1, const double x2,
  817. const double x3, const double x4)
  818. {
  819. c[0] = x0;
  820. c[1] = (61.0 * (x1 - xm1) + 16.0 * (xm2 - x2) + 3.0 * (x3 - xm3)) / 76.0;
  821. c[2] = (106.0 * (xm1 + x1) + 10.0 * x3 + 6.0 * xm3 - 3.0 * x4 - 29.0 * (xm2 + x2) - 167.0 * x0) / 76.0;
  822. }
  823. /**
  824. * Function calculates coefficients used to calculate 3rd order segment
  825. * interpolation polynomial on the equidistant lattice, using 4 points.
  826. *
  827. * @param[out] c Output coefficients buffer, length = 4.
  828. * @param[in] y Equidistant point values. Value at offset 1 corresponds to
  829. * x=0 point.
  830. */
  831. inline void calcInterpCoeffs3p4(double* const c, const double* const y)
  832. {
  833. c[0] = y[1];
  834. c[1] = 0.5 * (y[2] - y[0]);
  835. c[2] = y[0] - 2.5 * y[1] + y[2] + y[2] - 0.5 * y[3];
  836. c[3] = 0.5 * (y[3] - y[0]) + 1.5 * (y[1] - y[2]);
  837. }
  838. /**
  839. * Function calculates coefficients used to calculate 3rd order segment
  840. * interpolation polynomial on the equidistant lattice, using 6 points.
  841. *
  842. * @param[out] c Output coefficients buffer, length = 4.
  843. * @param[in] y Equidistant point values. Value at offset 2 corresponds to
  844. * x=0 point.
  845. */
  846. inline void calcInterpCoeffs3p6(double* const c, const double* const y)
  847. {
  848. c[0] = y[2];
  849. c[1] = (11.0 * (y[3] - y[1]) + 2.0 * (y[0] - y[4])) / 14.0;
  850. c[2] = (20.0 * (y[1] + y[3]) + 2.0 * y[5] - 4.0 * y[0] - 7.0 * y[4] - 31.0 * y[2]) / 14.0;
  851. c[3] = (17.0 * (y[2] - y[3]) + 9.0 * (y[4] - y[1]) + 2.0 * (y[0] - y[5])) / 14.0;
  852. }
  853. /**
  854. * Function calculates coefficients used to calculate 3rd order segment
  855. * interpolation polynomial on the equidistant lattice, using 8 points.
  856. *
  857. * @param[out] c Output coefficients buffer, length = 4.
  858. * @param[in] y Equidistant point values. Value at offset 3 corresponds to
  859. * x=0 point.
  860. */
  861. inline void calcInterpCoeffs3p8(double* const c, const double* const y)
  862. {
  863. c[0] = y[3];
  864. c[1] = (61.0 * (y[4] - y[2]) + 16.0 * (y[1] - y[5]) + 3.0 * (y[6] - y[0])) / 76.0;
  865. c[2] = (106.0 * (y[2] + y[4]) + 10.0 * y[6] + 6.0 * y[0] - 3.0 * y[7] - 29.0 * (y[1] + y[5]) - 167.0 * y[3]) / 76.0;
  866. c[3] = (91.0 * (y[3] - y[4]) + 45.0 * (y[5] - y[2]) + 13.0 * (y[1] - y[6]) + 3.0 * (y[7] - y[0])) / 76.0;
  867. }
  868. /**
  869. * Function calculates coefficients used to calculate 3rd order segment
  870. * interpolation polynomial on the equidistant lattice, using 8 points.
  871. *
  872. * @param[out] c Output coefficients buffer, length = 3.
  873. * @param[in] y Equidistant point values. Value at offset 3 corresponds to
  874. * x=0 point.
  875. */
  876. inline void calcInterpCoeffs2p8(double* const c, const double* const y)
  877. {
  878. c[0] = y[3];
  879. c[1] = (61.0 * (y[4] - y[2]) + 16.0 * (y[1] - y[5]) + 3.0 * (y[6] - y[0])) / 76.0;
  880. c[2] = (106.0 * (y[2] + y[4]) + 10.0 * y[6] + 6.0 * y[0] - 3.0 * y[7] - 29.0 * (y[1] + y[5]) - 167.0 * y[3]) / 76.0;
  881. }
  882. #if !defined( min )
  883. /**
  884. * @param v1 Value 1.
  885. * @param v2 Value 2.
  886. * @return The minimum of 2 values.
  887. */
  888. template <class T>
  889. T min(const T& v1, const T& v2) { return (v1 < v2 ? v1 : v2); }
  890. #endif // min
  891. #if !defined( max )
  892. /**
  893. * @param v1 Value 1.
  894. * @param v2 Value 2.
  895. * @return The maximum of 2 values.
  896. */
  897. template <class T>
  898. T max(const T& v1, const T& v2) { return (v1 > v2 ? v1 : v2); }
  899. #endif // max
  900. /**
  901. * Function "clamps" (clips) the specified value so that it is not lesser than
  902. * "minv", and not greater than "maxv".
  903. *
  904. * @param Value Value to clamp.
  905. * @param minv Minimal allowed value.
  906. * @param maxv Maximal allowed value.
  907. * @return "Clamped" value.
  908. */
  909. inline double clampr(const double Value, const double minv, const double maxv)
  910. {
  911. if (Value < minv) { return (minv); }
  912. if (Value > maxv) { return (maxv); }
  913. return (Value);
  914. }
  915. /**
  916. * @param x Value to square.
  917. * @return Squared value of the argument.
  918. */
  919. inline double sqr(const double x) { return (x * x); }
  920. /**
  921. * @param v Input value.
  922. * @param p Power factor.
  923. * @return Returns pow() function's value with input value's sign check.
  924. */
  925. inline double pows(const double v, const double p) { return (v < 0.0 ? -pow(-v, p) : pow(v, p)); }
  926. /**
  927. * @param v Input value.
  928. * @return Calculated single-argument Gaussian function of the input value.
  929. */
  930. inline double gauss(const double v) { return (exp(-(v * v))); }
  931. /**
  932. * @param v Input value.
  933. * @return Calculated inverse hyperbolic sine of the input value.
  934. */
  935. inline double asinh(const double v) { return (log(v + sqrt(v * v + 1.0))); }
  936. /**
  937. * @param x Input value.
  938. * @return Calculated zero-th order modified Bessel function of the first kind
  939. * of the input value. Approximate value.
  940. */
  941. inline double besselI0(const double x)
  942. {
  943. const double ax = fabs(x);
  944. double y;
  945. if (ax < 3.75)
  946. {
  947. y = x / 3.75;
  948. y *= y;
  949. return (1.0 + y * (3.5156229 + y * (3.0899424 + y * (1.2067492 + y * (0.2659732 + y * (0.360768e-1 + y * 0.45813e-2))))));
  950. }
  951. y = 3.75 / ax;
  952. return (exp(ax) / sqrt(ax) * (0.39894228 + y * (0.1328592e-1 + y * (
  953. 0.225319e-2 + y * (
  954. -0.157565e-2 + y * (
  955. 0.916281e-2 + y * (
  956. -0.2057706e-1 + y * (0.2635537e-1 + y * (-0.1647633e-1 + y * 0.392377e-2)))))))));
  957. }
  958. } // namespace r8b