BandLimitedWave.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * BandLimitedWave.h - helper functions for band-limited
  3. * waveform generation
  4. *
  5. * Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
  6. *
  7. * This file is part of LMMS - https://lmms.io
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2 of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public
  20. * License along with this program (see COPYING); if not, write to the
  21. * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  22. * Boston, MA 02110-1301 USA.
  23. *
  24. */
  25. #ifndef BANDLIMITEDWAVE_H
  26. #define BANDLIMITEDWAVE_H
  27. class QDataStream;
  28. class QString;
  29. #include "lmms_export.h"
  30. #include "interpolation.h"
  31. #include "lmms_basics.h"
  32. #include "lmms_math.h"
  33. #include "Engine.h"
  34. #include "AudioEngine.h"
  35. constexpr int MAXLEN = 11;
  36. constexpr int MIPMAPSIZE = 2 << ( MAXLEN + 1 );
  37. constexpr int MIPMAPSIZE3 = 3 << ( MAXLEN + 1 );
  38. constexpr int MAXTBL = 23;
  39. constexpr int MINTLEN = 2 << 0;
  40. constexpr int MAXTLEN = 3 << MAXLEN;
  41. // table for table sizes
  42. const int TLENS[MAXTBL+1] = { 2 << 0, 3 << 0, 2 << 1, 3 << 1,
  43. 2 << 2, 3 << 2, 2 << 3, 3 << 3,
  44. 2 << 4, 3 << 4, 2 << 5, 3 << 5,
  45. 2 << 6, 3 << 6, 2 << 7, 3 << 7,
  46. 2 << 8, 3 << 8, 2 << 9, 3 << 9,
  47. 2 << 10, 3 << 10, 2 << 11, 3 << 11 };
  48. typedef struct
  49. {
  50. public:
  51. inline sample_t sampleAt( int table, int ph )
  52. {
  53. if( table % 2 == 0 )
  54. { return m_data[ TLENS[ table ] + ph ]; }
  55. else
  56. { return m_data3[ TLENS[ table ] + ph ]; }
  57. }
  58. inline void setSampleAt( int table, int ph, sample_t sample )
  59. {
  60. if( table % 2 == 0 )
  61. { m_data[ TLENS[ table ] + ph ] = sample; }
  62. else
  63. { m_data3[ TLENS[ table ] + ph ] = sample; }
  64. }
  65. private:
  66. sample_t m_data [ MIPMAPSIZE ];
  67. sample_t m_data3 [ MIPMAPSIZE3 ];
  68. } WaveMipMap;
  69. QDataStream& operator<< ( QDataStream &out, WaveMipMap &waveMipMap );
  70. QDataStream& operator>> ( QDataStream &in, WaveMipMap &waveMipMap );
  71. class LMMS_EXPORT BandLimitedWave
  72. {
  73. public:
  74. enum Waveforms
  75. {
  76. BLSaw,
  77. BLSquare,
  78. BLTriangle,
  79. BLMoog,
  80. NumBLWaveforms
  81. };
  82. BandLimitedWave() {};
  83. virtual ~BandLimitedWave() {};
  84. /*! \brief This method converts frequency to wavelength. The oscillate function takes wavelength as argument so
  85. * use this to convert your note frequency to wavelength before using it.
  86. */
  87. static inline float freqToLen( float f )
  88. {
  89. return freqToLen( f, Engine::audioEngine()->processingSampleRate() );
  90. }
  91. /*! \brief This method converts frequency to wavelength, but you can use any custom sample rate with it.
  92. */
  93. static inline float freqToLen( float f, sample_rate_t sr )
  94. {
  95. return static_cast<float>( sr ) / f;
  96. }
  97. /*! \brief This method converts phase delta to wavelength. It assumes a phase scale of 0 to 1. */
  98. static inline float pdToLen( float pd )
  99. {
  100. return 1.0f / pd;
  101. }
  102. /*! \brief This method provides interpolated samples of bandlimited waveforms.
  103. * \param _ph The phase of the sample.
  104. * \param _wavelen The wavelength (length of one cycle, ie. the inverse of frequency) of the wanted oscillation, measured in sample frames
  105. * \param _wave The wanted waveform. Options currently are saw, triangle, square and moog saw.
  106. */
  107. static inline sample_t oscillate( float _ph, float _wavelen, Waveforms _wave )
  108. {
  109. // get the next higher tlen
  110. int t = 0;
  111. while( t < MAXTBL && _wavelen >= TLENS[t+1] ) { t++; }
  112. int tlen = TLENS[t];
  113. const float ph = fraction( _ph );
  114. const float lookupf = ph * static_cast<float>( tlen );
  115. int lookup = static_cast<int>( lookupf );
  116. const float ip = fraction( lookupf );
  117. const sample_t s1 = s_waveforms[ _wave ].sampleAt( t, lookup );
  118. const sample_t s2 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 1 ) % tlen );
  119. const int lm = lookup == 0 ? tlen - 1 : lookup - 1;
  120. const sample_t s0 = s_waveforms[ _wave ].sampleAt( t, lm );
  121. const sample_t s3 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 2 ) % tlen );
  122. const sample_t sr = optimal4pInterpolate( s0, s1, s2, s3, ip );
  123. return sr;
  124. /* lookup = lookup << 1;
  125. tlen = tlen << 1;
  126. t += 1;
  127. const sample_t s3 = s_waveforms[ _wave ].sampleAt( t, lookup );
  128. const sample_t s4 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 1 ) % tlen );
  129. const sample_t s34 = linearInterpolate( s3, s4, ip );
  130. const float ip2 = ( ( tlen - _wavelen ) / tlen - 0.5 ) * 2.0;
  131. return linearInterpolate( s12, s34, ip2 );
  132. */
  133. };
  134. static void generateWaves();
  135. static bool s_wavesGenerated;
  136. static WaveMipMap s_waveforms [NumBLWaveforms];
  137. static QString s_wavetableDir;
  138. };
  139. #endif