DelayDSPKernel.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * Copyright (C) 2010, 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. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  15. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  16. * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  17. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  18. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  19. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  20. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  22. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. #include "config.h"
  25. #if ENABLE(WEB_AUDIO)
  26. #include "DelayDSPKernel.h"
  27. #include "AudioUtilities.h"
  28. #include <algorithm>
  29. using namespace std;
  30. namespace WebCore {
  31. const float SmoothingTimeConstant = 0.020f; // 20ms
  32. DelayDSPKernel::DelayDSPKernel(DelayProcessor* processor)
  33. : AudioDSPKernel(processor)
  34. , m_writeIndex(0)
  35. , m_firstTime(true)
  36. , m_delayTimes(AudioNode::ProcessingSizeInFrames)
  37. {
  38. ASSERT(processor && processor->sampleRate() > 0);
  39. if (!(processor && processor->sampleRate() > 0))
  40. return;
  41. m_maxDelayTime = processor->maxDelayTime();
  42. ASSERT(m_maxDelayTime >= 0);
  43. if (m_maxDelayTime < 0)
  44. return;
  45. m_buffer.allocate(bufferLengthForDelay(m_maxDelayTime, processor->sampleRate()));
  46. m_buffer.zero();
  47. m_smoothingRate = AudioUtilities::discreteTimeConstantForSampleRate(SmoothingTimeConstant, processor->sampleRate());
  48. }
  49. DelayDSPKernel::DelayDSPKernel(double maxDelayTime, float sampleRate)
  50. : AudioDSPKernel(sampleRate)
  51. , m_maxDelayTime(maxDelayTime)
  52. , m_writeIndex(0)
  53. , m_firstTime(true)
  54. {
  55. ASSERT(maxDelayTime > 0.0);
  56. if (maxDelayTime <= 0.0)
  57. return;
  58. size_t bufferLength = bufferLengthForDelay(maxDelayTime, sampleRate);
  59. ASSERT(bufferLength);
  60. if (!bufferLength)
  61. return;
  62. m_buffer.allocate(bufferLength);
  63. m_buffer.zero();
  64. m_smoothingRate = AudioUtilities::discreteTimeConstantForSampleRate(SmoothingTimeConstant, sampleRate);
  65. }
  66. size_t DelayDSPKernel::bufferLengthForDelay(double maxDelayTime, double sampleRate) const
  67. {
  68. // Compute the length of the buffer needed to handle a max delay of |maxDelayTime|. One is
  69. // added to handle the case where the actual delay equals the maximum delay.
  70. return 1 + AudioUtilities::timeToSampleFrame(maxDelayTime, sampleRate);
  71. }
  72. void DelayDSPKernel::process(const float* source, float* destination, size_t framesToProcess)
  73. {
  74. size_t bufferLength = m_buffer.size();
  75. float* buffer = m_buffer.data();
  76. ASSERT(bufferLength);
  77. if (!bufferLength)
  78. return;
  79. ASSERT(source && destination);
  80. if (!source || !destination)
  81. return;
  82. float sampleRate = this->sampleRate();
  83. double delayTime = 0;
  84. float* delayTimes = m_delayTimes.data();
  85. double maxTime = maxDelayTime();
  86. bool sampleAccurate = delayProcessor() && delayProcessor()->delayTime()->hasSampleAccurateValues();
  87. if (sampleAccurate)
  88. delayProcessor()->delayTime()->calculateSampleAccurateValues(delayTimes, framesToProcess);
  89. else {
  90. delayTime = delayProcessor() ? delayProcessor()->delayTime()->finalValue() : m_desiredDelayFrames / sampleRate;
  91. // Make sure the delay time is in a valid range.
  92. delayTime = min(maxTime, delayTime);
  93. delayTime = max(0.0, delayTime);
  94. if (m_firstTime) {
  95. m_currentDelayTime = delayTime;
  96. m_firstTime = false;
  97. }
  98. }
  99. for (unsigned i = 0; i < framesToProcess; ++i) {
  100. if (sampleAccurate) {
  101. delayTime = delayTimes[i];
  102. delayTime = std::min(maxTime, delayTime);
  103. delayTime = std::max(0.0, delayTime);
  104. m_currentDelayTime = delayTime;
  105. } else {
  106. // Approach desired delay time.
  107. m_currentDelayTime += (delayTime - m_currentDelayTime) * m_smoothingRate;
  108. }
  109. double desiredDelayFrames = m_currentDelayTime * sampleRate;
  110. double readPosition = m_writeIndex + bufferLength - desiredDelayFrames;
  111. if (readPosition >= bufferLength)
  112. readPosition -= bufferLength;
  113. // Linearly interpolate in-between delay times.
  114. int readIndex1 = static_cast<int>(readPosition);
  115. int readIndex2 = (readIndex1 + 1) % bufferLength;
  116. double interpolationFactor = readPosition - readIndex1;
  117. double input = static_cast<float>(*source++);
  118. buffer[m_writeIndex] = static_cast<float>(input);
  119. m_writeIndex = (m_writeIndex + 1) % bufferLength;
  120. double sample1 = buffer[readIndex1];
  121. double sample2 = buffer[readIndex2];
  122. double output = (1.0 - interpolationFactor) * sample1 + interpolationFactor * sample2;
  123. *destination++ = static_cast<float>(output);
  124. }
  125. }
  126. void DelayDSPKernel::reset()
  127. {
  128. m_firstTime = true;
  129. m_buffer.zero();
  130. }
  131. double DelayDSPKernel::tailTime() const
  132. {
  133. return m_maxDelayTime;
  134. }
  135. double DelayDSPKernel::latencyTime() const
  136. {
  137. return 0;
  138. }
  139. } // namespace WebCore
  140. #endif // ENABLE(WEB_AUDIO)