r8bbase.h 28 KB

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