WaveTable.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*
  2. * Copyright (C) 2012 Google Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  14. * its contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  18. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include "config.h"
  29. #if ENABLE(WEB_AUDIO)
  30. #include "WaveTable.h"
  31. #include "FFTFrame.h"
  32. #include "OscillatorNode.h"
  33. #include "VectorMath.h"
  34. #include <algorithm>
  35. #include <wtf/OwnPtr.h>
  36. const unsigned WaveTableSize = 4096; // This must be a power of two.
  37. const unsigned NumberOfRanges = 36; // There should be 3 * log2(WaveTableSize) 1/3 octave ranges.
  38. const float CentsPerRange = 1200 / 3; // 1/3 Octave.
  39. namespace WebCore {
  40. using namespace VectorMath;
  41. PassRefPtr<WaveTable> WaveTable::create(float sampleRate, Float32Array* real, Float32Array* imag)
  42. {
  43. bool isGood = real && imag && real->length() == imag->length();
  44. ASSERT(isGood);
  45. if (isGood) {
  46. RefPtr<WaveTable> waveTable = adoptRef(new WaveTable(sampleRate));
  47. size_t numberOfComponents = real->length();
  48. waveTable->createBandLimitedTables(real->data(), imag->data(), numberOfComponents);
  49. return waveTable;
  50. }
  51. return 0;
  52. }
  53. PassRefPtr<WaveTable> WaveTable::createSine(float sampleRate)
  54. {
  55. RefPtr<WaveTable> waveTable = adoptRef(new WaveTable(sampleRate));
  56. waveTable->generateBasicWaveform(OscillatorNode::SINE);
  57. return waveTable;
  58. }
  59. PassRefPtr<WaveTable> WaveTable::createSquare(float sampleRate)
  60. {
  61. RefPtr<WaveTable> waveTable = adoptRef(new WaveTable(sampleRate));
  62. waveTable->generateBasicWaveform(OscillatorNode::SQUARE);
  63. return waveTable;
  64. }
  65. PassRefPtr<WaveTable> WaveTable::createSawtooth(float sampleRate)
  66. {
  67. RefPtr<WaveTable> waveTable = adoptRef(new WaveTable(sampleRate));
  68. waveTable->generateBasicWaveform(OscillatorNode::SAWTOOTH);
  69. return waveTable;
  70. }
  71. PassRefPtr<WaveTable> WaveTable::createTriangle(float sampleRate)
  72. {
  73. RefPtr<WaveTable> waveTable = adoptRef(new WaveTable(sampleRate));
  74. waveTable->generateBasicWaveform(OscillatorNode::TRIANGLE);
  75. return waveTable;
  76. }
  77. WaveTable::WaveTable(float sampleRate)
  78. : m_sampleRate(sampleRate)
  79. , m_waveTableSize(WaveTableSize)
  80. , m_numberOfRanges(NumberOfRanges)
  81. , m_centsPerRange(CentsPerRange)
  82. {
  83. float nyquist = 0.5 * m_sampleRate;
  84. m_lowestFundamentalFrequency = nyquist / maxNumberOfPartials();
  85. m_rateScale = m_waveTableSize / m_sampleRate;
  86. }
  87. void WaveTable::waveDataForFundamentalFrequency(float fundamentalFrequency, float* &lowerWaveData, float* &higherWaveData, float& tableInterpolationFactor)
  88. {
  89. // Negative frequencies are allowed, in which case we alias to the positive frequency.
  90. fundamentalFrequency = fabsf(fundamentalFrequency);
  91. // Calculate the pitch range.
  92. float ratio = fundamentalFrequency > 0 ? fundamentalFrequency / m_lowestFundamentalFrequency : 0.5;
  93. float centsAboveLowestFrequency = log2f(ratio) * 1200;
  94. // Add one to round-up to the next range just in time to truncate partials before aliasing occurs.
  95. float pitchRange = 1 + centsAboveLowestFrequency / m_centsPerRange;
  96. pitchRange = std::max(pitchRange, 0.0f);
  97. pitchRange = std::min(pitchRange, static_cast<float>(m_numberOfRanges - 1));
  98. // The words "lower" and "higher" refer to the table data having the lower and higher numbers of partials.
  99. // It's a little confusing since the range index gets larger the more partials we cull out.
  100. // So the lower table data will have a larger range index.
  101. unsigned rangeIndex1 = static_cast<unsigned>(pitchRange);
  102. unsigned rangeIndex2 = rangeIndex1 < m_numberOfRanges - 1 ? rangeIndex1 + 1 : rangeIndex1;
  103. lowerWaveData = m_bandLimitedTables[rangeIndex2]->data();
  104. higherWaveData = m_bandLimitedTables[rangeIndex1]->data();
  105. // Ranges from 0 -> 1 to interpolate between lower -> higher.
  106. tableInterpolationFactor = pitchRange - rangeIndex1;
  107. }
  108. unsigned WaveTable::maxNumberOfPartials() const
  109. {
  110. return m_waveTableSize / 2;
  111. }
  112. unsigned WaveTable::numberOfPartialsForRange(unsigned rangeIndex) const
  113. {
  114. // Number of cents below nyquist where we cull partials.
  115. float centsToCull = rangeIndex * m_centsPerRange;
  116. // A value from 0 -> 1 representing what fraction of the partials to keep.
  117. float cullingScale = pow(2, -centsToCull / 1200);
  118. // The very top range will have all the partials culled.
  119. unsigned numberOfPartials = cullingScale * maxNumberOfPartials();
  120. return numberOfPartials;
  121. }
  122. // Convert into time-domain wave tables.
  123. // One table is created for each range for non-aliasing playback at different playback rates.
  124. // Thus, higher ranges have more high-frequency partials culled out.
  125. void WaveTable::createBandLimitedTables(const float* realData, const float* imagData, unsigned numberOfComponents)
  126. {
  127. float normalizationScale = 1;
  128. unsigned fftSize = m_waveTableSize;
  129. unsigned halfSize = fftSize / 2;
  130. unsigned i;
  131. numberOfComponents = std::min(numberOfComponents, halfSize);
  132. m_bandLimitedTables.reserveCapacity(m_numberOfRanges);
  133. for (unsigned rangeIndex = 0; rangeIndex < m_numberOfRanges; ++rangeIndex) {
  134. // This FFTFrame is used to cull partials (represented by frequency bins).
  135. FFTFrame frame(fftSize);
  136. float* realP = frame.realData();
  137. float* imagP = frame.imagData();
  138. // Copy from loaded frequency data and scale.
  139. float scale = fftSize;
  140. vsmul(realData, 1, &scale, realP, 1, numberOfComponents);
  141. vsmul(imagData, 1, &scale, imagP, 1, numberOfComponents);
  142. // If fewer components were provided than 1/2 FFT size, then clear the remaining bins.
  143. for (i = numberOfComponents; i < halfSize; ++i) {
  144. realP[i] = 0;
  145. imagP[i] = 0;
  146. }
  147. // Generate complex conjugate because of the way the inverse FFT is defined.
  148. float minusOne = -1;
  149. vsmul(imagP, 1, &minusOne, imagP, 1, halfSize);
  150. // Find the starting bin where we should start culling.
  151. // We need to clear out the highest frequencies to band-limit the waveform.
  152. unsigned numberOfPartials = numberOfPartialsForRange(rangeIndex);
  153. // Cull the aliasing partials for this pitch range.
  154. for (i = numberOfPartials + 1; i < halfSize; ++i) {
  155. realP[i] = 0;
  156. imagP[i] = 0;
  157. }
  158. // Clear packed-nyquist if necessary.
  159. if (numberOfPartials < halfSize)
  160. imagP[0] = 0;
  161. // Clear any DC-offset.
  162. realP[0] = 0;
  163. // Create the band-limited table.
  164. OwnPtr<AudioFloatArray> table = adoptPtr(new AudioFloatArray(m_waveTableSize));
  165. m_bandLimitedTables.append(table.release());
  166. // Apply an inverse FFT to generate the time-domain table data.
  167. float* data = m_bandLimitedTables[rangeIndex]->data();
  168. frame.doInverseFFT(data);
  169. // For the first range (which has the highest power), calculate its peak value then compute normalization scale.
  170. if (!rangeIndex) {
  171. float maxValue;
  172. vmaxmgv(data, 1, &maxValue, m_waveTableSize);
  173. if (maxValue)
  174. normalizationScale = 1.0f / maxValue;
  175. }
  176. // Apply normalization scale.
  177. vsmul(data, 1, &normalizationScale, data, 1, m_waveTableSize);
  178. }
  179. }
  180. void WaveTable::generateBasicWaveform(int shape)
  181. {
  182. unsigned fftSize = waveTableSize();
  183. unsigned halfSize = fftSize / 2;
  184. AudioFloatArray real(halfSize);
  185. AudioFloatArray imag(halfSize);
  186. float* realP = real.data();
  187. float* imagP = imag.data();
  188. // Clear DC and Nyquist.
  189. realP[0] = 0;
  190. imagP[0] = 0;
  191. for (unsigned n = 1; n < halfSize; ++n) {
  192. float omega = 2 * piFloat * n;
  193. float invOmega = 1 / omega;
  194. // Fourier coefficients according to standard definition.
  195. float a; // Coefficient for cos().
  196. float b; // Coefficient for sin().
  197. // Calculate Fourier coefficients depending on the shape.
  198. // Note that the overall scaling (magnitude) of the waveforms is normalized in createBandLimitedTables().
  199. switch (shape) {
  200. case OscillatorNode::SINE:
  201. // Standard sine wave function.
  202. a = 0;
  203. b = (n == 1) ? 1 : 0;
  204. break;
  205. case OscillatorNode::SQUARE:
  206. // Square-shaped waveform with the first half its maximum value and the second half its minimum value.
  207. a = 0;
  208. b = invOmega * ((n & 1) ? 2 : 0);
  209. break;
  210. case OscillatorNode::SAWTOOTH:
  211. // Sawtooth-shaped waveform with the first half ramping from zero to maximum and the second half from minimum to zero.
  212. a = 0;
  213. b = -invOmega * cos(0.5 * omega);
  214. break;
  215. case OscillatorNode::TRIANGLE:
  216. // Triangle-shaped waveform going from its maximum value to its minimum value then back to the maximum value.
  217. a = (4 - 4 * cos(0.5 * omega)) / (n * n * piFloat * piFloat);
  218. b = 0;
  219. break;
  220. default:
  221. ASSERT_NOT_REACHED();
  222. a = 0;
  223. b = 0;
  224. break;
  225. }
  226. realP[n] = a;
  227. imagP[n] = b;
  228. }
  229. createBandLimitedTables(realP, imagP, halfSize);
  230. }
  231. } // namespace WebCore
  232. #endif // ENABLE(WEB_AUDIO)