| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 m_lastPreDelayFrames = preDelayFrames; | 87 m_lastPreDelayFrames = preDelayFrames; |
| 88 for (unsigned i = 0; i < m_preDelayBuffers.size(); ++i) | 88 for (unsigned i = 0; i < m_preDelayBuffers.size(); ++i) |
| 89 m_preDelayBuffers[i]->zero(); | 89 m_preDelayBuffers[i]->zero(); |
| 90 | 90 |
| 91 m_preDelayReadIndex = 0; | 91 m_preDelayReadIndex = 0; |
| 92 m_preDelayWriteIndex = preDelayFrames; | 92 m_preDelayWriteIndex = preDelayFrames; |
| 93 } | 93 } |
| 94 } | 94 } |
| 95 | 95 |
| 96 // Exponential curve for the knee. | 96 // Exponential curve for the knee. |
| 97 // It is 1st derivative matched at m_linearThreshold and asymptotically approach
es the value m_linearThreshold + 1 / k. | 97 // It is 1st derivative matched at m_linearThreshold and asymptotically |
| 98 // approaches the value m_linearThreshold + 1 / k. |
| 98 float DynamicsCompressorKernel::kneeCurve(float x, float k) { | 99 float DynamicsCompressorKernel::kneeCurve(float x, float k) { |
| 99 // Linear up to threshold. | 100 // Linear up to threshold. |
| 100 if (x < m_linearThreshold) | 101 if (x < m_linearThreshold) |
| 101 return x; | 102 return x; |
| 102 | 103 |
| 103 return m_linearThreshold + (1 - expf(-k * (x - m_linearThreshold))) / k; | 104 return m_linearThreshold + (1 - expf(-k * (x - m_linearThreshold))) / k; |
| 104 } | 105 } |
| 105 | 106 |
| 106 // Full compression curve with constant ratio after knee. | 107 // Full compression curve with constant ratio after knee. |
| 107 float DynamicsCompressorKernel::saturate(float x, float k) { | 108 float DynamicsCompressorKernel::saturate(float x, float k) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 float DynamicsCompressorKernel::kAtSlope(float desiredSlope) { | 144 float DynamicsCompressorKernel::kAtSlope(float desiredSlope) { |
| 144 float xDb = m_dbThreshold + m_dbKnee; | 145 float xDb = m_dbThreshold + m_dbKnee; |
| 145 float x = decibelsToLinear(xDb); | 146 float x = decibelsToLinear(xDb); |
| 146 | 147 |
| 147 // Approximate k given initial values. | 148 // Approximate k given initial values. |
| 148 float minK = 0.1; | 149 float minK = 0.1; |
| 149 float maxK = 10000; | 150 float maxK = 10000; |
| 150 float k = 5; | 151 float k = 5; |
| 151 | 152 |
| 152 for (int i = 0; i < 15; ++i) { | 153 for (int i = 0; i < 15; ++i) { |
| 153 // A high value for k will more quickly asymptotically approach a slope of 0
. | 154 // A high value for k will more quickly asymptotically approach a slope of |
| 155 // 0. |
| 154 float slope = slopeAt(x, k); | 156 float slope = slopeAt(x, k); |
| 155 | 157 |
| 156 if (slope < desiredSlope) { | 158 if (slope < desiredSlope) { |
| 157 // k is too high. | 159 // k is too high. |
| 158 maxK = k; | 160 maxK = k; |
| 159 } else { | 161 } else { |
| 160 // k is too low. | 162 // k is too low. |
| 161 minK = k; | 163 minK = k; |
| 162 } | 164 } |
| 163 | 165 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 // Create a smooth function which passes through four points. | 246 // Create a smooth function which passes through four points. |
| 245 | 247 |
| 246 // Polynomial of the form | 248 // Polynomial of the form |
| 247 // y = a + b*x + c*x^2 + d*x^3 + e*x^4; | 249 // y = a + b*x + c*x^2 + d*x^3 + e*x^4; |
| 248 | 250 |
| 249 float y1 = releaseFrames * releaseZone1; | 251 float y1 = releaseFrames * releaseZone1; |
| 250 float y2 = releaseFrames * releaseZone2; | 252 float y2 = releaseFrames * releaseZone2; |
| 251 float y3 = releaseFrames * releaseZone3; | 253 float y3 = releaseFrames * releaseZone3; |
| 252 float y4 = releaseFrames * releaseZone4; | 254 float y4 = releaseFrames * releaseZone4; |
| 253 | 255 |
| 254 // All of these coefficients were derived for 4th order polynomial curve fitti
ng where the y values | 256 // All of these coefficients were derived for 4th order polynomial curve |
| 255 // match the evenly spaced x values as follows: (y1 : x == 0, y2 : x == 1, y3
: x == 2, y4 : x == 3) | 257 // fitting where the y values match the evenly spaced x values as follows: |
| 258 // (y1 : x == 0, y2 : x == 1, y3 : x == 2, y4 : x == 3) |
| 256 float a = 0.9999999999999998f * y1 + 1.8432219684323923e-16f * y2 - | 259 float a = 0.9999999999999998f * y1 + 1.8432219684323923e-16f * y2 - |
| 257 1.9373394351676423e-16f * y3 + 8.824516011816245e-18f * y4; | 260 1.9373394351676423e-16f * y3 + 8.824516011816245e-18f * y4; |
| 258 float b = -1.5788320352845888f * y1 + 2.3305837032074286f * y2 - | 261 float b = -1.5788320352845888f * y1 + 2.3305837032074286f * y2 - |
| 259 0.9141194204840429f * y3 + 0.1623677525612032f * y4; | 262 0.9141194204840429f * y3 + 0.1623677525612032f * y4; |
| 260 float c = 0.5334142869106424f * y1 - 1.272736789213631f * y2 + | 263 float c = 0.5334142869106424f * y1 - 1.272736789213631f * y2 + |
| 261 0.9258856042207512f * y3 - 0.18656310191776226f * y4; | 264 0.9258856042207512f * y3 - 0.18656310191776226f * y4; |
| 262 float d = 0.08783463138207234f * y1 - 0.1694162967925622f * y2 + | 265 float d = 0.08783463138207234f * y1 - 0.1694162967925622f * y2 + |
| 263 0.08588057951595272f * y3 - 0.00429891410546283f * y4; | 266 0.08588057951595272f * y3 - 0.00429891410546283f * y4; |
| 264 float e = -0.042416883008123074f * y1 + 0.1115693827987602f * y2 - | 267 float e = -0.042416883008123074f * y1 + 0.1115693827987602f * y2 - |
| 265 0.09764676325265872f * y3 + 0.028494263462021576f * y4; | 268 0.09764676325265872f * y3 + 0.028494263462021576f * y4; |
| 266 | 269 |
| 267 // x ranges from 0 -> 3 0 1 2 3 | 270 // x ranges from 0 -> 3 0 1 2 3 |
| 268 // -15 -10 -5 0db | 271 // -15 -10 -5 0db |
| 269 | 272 |
| 270 // y calculates adaptive release frames depending on the amount of compression
. | 273 // y calculates adaptive release frames depending on the amount of |
| 274 // compression. |
| 271 | 275 |
| 272 setPreDelayTime(preDelayTime); | 276 setPreDelayTime(preDelayTime); |
| 273 | 277 |
| 274 const int nDivisionFrames = 32; | 278 const int nDivisionFrames = 32; |
| 275 | 279 |
| 276 const int nDivisions = framesToProcess / nDivisionFrames; | 280 const int nDivisions = framesToProcess / nDivisionFrames; |
| 277 | 281 |
| 278 unsigned frameIndex = 0; | 282 unsigned frameIndex = 0; |
| 279 for (int i = 0; i < nDivisions; ++i) { | 283 for (int i = 0; i < nDivisions; ++i) { |
| 280 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~ | 284 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~ |
| 281 // Calculate desired gain | 285 // Calculate desired gain |
| 282 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~ | 286 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~ |
| 283 | 287 |
| 284 // Fix gremlins. | 288 // Fix gremlins. |
| 285 if (std::isnan(m_detectorAverage)) | 289 if (std::isnan(m_detectorAverage)) |
| 286 m_detectorAverage = 1; | 290 m_detectorAverage = 1; |
| 287 if (std::isinf(m_detectorAverage)) | 291 if (std::isinf(m_detectorAverage)) |
| 288 m_detectorAverage = 1; | 292 m_detectorAverage = 1; |
| 289 | 293 |
| 290 float desiredGain = m_detectorAverage; | 294 float desiredGain = m_detectorAverage; |
| 291 | 295 |
| 292 // Pre-warp so we get desiredGain after sin() warp below. | 296 // Pre-warp so we get desiredGain after sin() warp below. |
| 293 float scaledDesiredGain = asinf(desiredGain) / (piOverTwoFloat); | 297 float scaledDesiredGain = asinf(desiredGain) / (piOverTwoFloat); |
| 294 | 298 |
| 295 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~ | 299 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~ |
| 296 // Deal with envelopes | 300 // Deal with envelopes |
| 297 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~ | 301 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~ |
| 298 | 302 |
| 299 // envelopeRate is the rate we slew from current compressor level to the des
ired level. | 303 // envelopeRate is the rate we slew from current compressor level to the |
| 300 // The exact rate depends on if we're attacking or releasing and by how much
. | 304 // desired level. The exact rate depends on if we're attacking or |
| 305 // releasing and by how much. |
| 301 float envelopeRate; | 306 float envelopeRate; |
| 302 | 307 |
| 303 bool isReleasing = scaledDesiredGain > m_compressorGain; | 308 bool isReleasing = scaledDesiredGain > m_compressorGain; |
| 304 | 309 |
| 305 // compressionDiffDb is the difference between current compression level and
the desired level. | 310 // compressionDiffDb is the difference between current compression level and |
| 311 // the desired level. |
| 306 float compressionDiffDb = | 312 float compressionDiffDb = |
| 307 linearToDecibels(m_compressorGain / scaledDesiredGain); | 313 linearToDecibels(m_compressorGain / scaledDesiredGain); |
| 308 | 314 |
| 309 if (isReleasing) { | 315 if (isReleasing) { |
| 310 // Release mode - compressionDiffDb should be negative dB | 316 // Release mode - compressionDiffDb should be negative dB |
| 311 m_maxAttackCompressionDiffDb = -1; | 317 m_maxAttackCompressionDiffDb = -1; |
| 312 | 318 |
| 313 // Fix gremlins. | 319 // Fix gremlins. |
| 314 if (std::isnan(compressionDiffDb)) | 320 if (std::isnan(compressionDiffDb)) |
| 315 compressionDiffDb = -1; | 321 compressionDiffDb = -1; |
| 316 if (std::isinf(compressionDiffDb)) | 322 if (std::isinf(compressionDiffDb)) |
| 317 compressionDiffDb = -1; | 323 compressionDiffDb = -1; |
| 318 | 324 |
| 319 // Adaptive release - higher compression (lower compressionDiffDb) releas
es faster. | 325 // Adaptive release - higher compression (lower compressionDiffDb) |
| 326 // releases faster. |
| 320 | 327 |
| 321 // Contain within range: -12 -> 0 then scale to go from 0 -> 3 | 328 // Contain within range: -12 -> 0 then scale to go from 0 -> 3 |
| 322 float x = compressionDiffDb; | 329 float x = compressionDiffDb; |
| 323 x = clampTo(x, -12.0f, 0.0f); | 330 x = clampTo(x, -12.0f, 0.0f); |
| 324 x = 0.25f * (x + 12); | 331 x = 0.25f * (x + 12); |
| 325 | 332 |
| 326 // Compute adaptive release curve using 4th order polynomial. | 333 // Compute adaptive release curve using 4th order polynomial. |
| 327 // Normal values for the polynomial coefficients would create a monotonica
lly increasing function. | 334 // Normal values for the polynomial coefficients would create a |
| 335 // monotonically increasing function. |
| 328 float x2 = x * x; | 336 float x2 = x * x; |
| 329 float x3 = x2 * x; | 337 float x3 = x2 * x; |
| 330 float x4 = x2 * x2; | 338 float x4 = x2 * x2; |
| 331 float releaseFrames = a + b * x + c * x2 + d * x3 + e * x4; | 339 float releaseFrames = a + b * x + c * x2 + d * x3 + e * x4; |
| 332 | 340 |
| 333 #define kSpacingDb 5 | 341 #define kSpacingDb 5 |
| 334 float dbPerFrame = kSpacingDb / releaseFrames; | 342 float dbPerFrame = kSpacingDb / releaseFrames; |
| 335 | 343 |
| 336 envelopeRate = decibelsToLinear(dbPerFrame); | 344 envelopeRate = decibelsToLinear(dbPerFrame); |
| 337 } else { | 345 } else { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 362 { | 370 { |
| 363 int preDelayReadIndex = m_preDelayReadIndex; | 371 int preDelayReadIndex = m_preDelayReadIndex; |
| 364 int preDelayWriteIndex = m_preDelayWriteIndex; | 372 int preDelayWriteIndex = m_preDelayWriteIndex; |
| 365 float detectorAverage = m_detectorAverage; | 373 float detectorAverage = m_detectorAverage; |
| 366 float compressorGain = m_compressorGain; | 374 float compressorGain = m_compressorGain; |
| 367 | 375 |
| 368 int loopFrames = nDivisionFrames; | 376 int loopFrames = nDivisionFrames; |
| 369 while (loopFrames--) { | 377 while (loopFrames--) { |
| 370 float compressorInput = 0; | 378 float compressorInput = 0; |
| 371 | 379 |
| 372 // Predelay signal, computing compression amount from un-delayed version
. | 380 // Predelay signal, computing compression amount from un-delayed |
| 381 // version. |
| 373 for (unsigned i = 0; i < numberOfChannels; ++i) { | 382 for (unsigned i = 0; i < numberOfChannels; ++i) { |
| 374 float* delayBuffer = m_preDelayBuffers[i]->data(); | 383 float* delayBuffer = m_preDelayBuffers[i]->data(); |
| 375 float undelayedSource = sourceChannels[i][frameIndex]; | 384 float undelayedSource = sourceChannels[i][frameIndex]; |
| 376 delayBuffer[preDelayWriteIndex] = undelayedSource; | 385 delayBuffer[preDelayWriteIndex] = undelayedSource; |
| 377 | 386 |
| 378 float absUndelayedSource = | 387 float absUndelayedSource = |
| 379 undelayedSource > 0 ? undelayedSource : -undelayedSource; | 388 undelayedSource > 0 ? undelayedSource : -undelayedSource; |
| 380 if (compressorInput < absUndelayedSource) | 389 if (compressorInput < absUndelayedSource) |
| 381 compressorInput = absUndelayedSource; | 390 compressorInput = absUndelayedSource; |
| 382 } | 391 } |
| 383 | 392 |
| 384 // Calculate shaped power on undelayed input. | 393 // Calculate shaped power on undelayed input. |
| 385 | 394 |
| 386 float scaledInput = compressorInput; | 395 float scaledInput = compressorInput; |
| 387 float absInput = scaledInput > 0 ? scaledInput : -scaledInput; | 396 float absInput = scaledInput > 0 ? scaledInput : -scaledInput; |
| 388 | 397 |
| 389 // Put through shaping curve. | 398 // Put through shaping curve. |
| 390 // This is linear up to the threshold, then enters a "knee" portion foll
owed by the "ratio" portion. | 399 // This is linear up to the threshold, then enters a "knee" portion |
| 391 // The transition from the threshold to the knee is smooth (1st derivati
ve matched). | 400 // followed by the "ratio" portion. The transition from the threshold |
| 392 // The transition from the knee to the ratio portion is smooth (1st deri
vative matched). | 401 // to the knee is smooth (1st derivative matched). The transition from |
| 402 // the knee to the ratio portion is smooth (1st derivative matched). |
| 393 float shapedInput = saturate(absInput, k); | 403 float shapedInput = saturate(absInput, k); |
| 394 | 404 |
| 395 float attenuation = absInput <= 0.0001f ? 1 : shapedInput / absInput; | 405 float attenuation = absInput <= 0.0001f ? 1 : shapedInput / absInput; |
| 396 | 406 |
| 397 float attenuationDb = -linearToDecibels(attenuation); | 407 float attenuationDb = -linearToDecibels(attenuation); |
| 398 attenuationDb = std::max(2.0f, attenuationDb); | 408 attenuationDb = std::max(2.0f, attenuationDb); |
| 399 | 409 |
| 400 float dbPerFrame = attenuationDb / satReleaseFrames; | 410 float dbPerFrame = attenuationDb / satReleaseFrames; |
| 401 | 411 |
| 402 float satReleaseRate = decibelsToLinear(dbPerFrame) - 1; | 412 float satReleaseRate = decibelsToLinear(dbPerFrame) - 1; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 416 // Exponential approach to desired gain. | 426 // Exponential approach to desired gain. |
| 417 if (envelopeRate < 1) { | 427 if (envelopeRate < 1) { |
| 418 // Attack - reduce gain to desired. | 428 // Attack - reduce gain to desired. |
| 419 compressorGain += (scaledDesiredGain - compressorGain) * envelopeRate; | 429 compressorGain += (scaledDesiredGain - compressorGain) * envelopeRate; |
| 420 } else { | 430 } else { |
| 421 // Release - exponentially increase gain to 1.0 | 431 // Release - exponentially increase gain to 1.0 |
| 422 compressorGain *= envelopeRate; | 432 compressorGain *= envelopeRate; |
| 423 compressorGain = std::min(1.0f, compressorGain); | 433 compressorGain = std::min(1.0f, compressorGain); |
| 424 } | 434 } |
| 425 | 435 |
| 426 // Warp pre-compression gain to smooth out sharp exponential transition
points. | 436 // Warp pre-compression gain to smooth out sharp exponential transition |
| 437 // points. |
| 427 float postWarpCompressorGain = sinf(piOverTwoFloat * compressorGain); | 438 float postWarpCompressorGain = sinf(piOverTwoFloat * compressorGain); |
| 428 | 439 |
| 429 // Calculate total gain using master gain and effect blend. | 440 // Calculate total gain using master gain and effect blend. |
| 430 float totalGain = | 441 float totalGain = |
| 431 dryMix + wetMix * masterLinearGain * postWarpCompressorGain; | 442 dryMix + wetMix * masterLinearGain * postWarpCompressorGain; |
| 432 | 443 |
| 433 // Calculate metering. | 444 // Calculate metering. |
| 434 float dbRealGain = 20 * std::log10(postWarpCompressorGain); | 445 float dbRealGain = 20 * std::log10(postWarpCompressorGain); |
| 435 if (dbRealGain < m_meteringGain) | 446 if (dbRealGain < m_meteringGain) |
| 436 m_meteringGain = dbRealGain; | 447 m_meteringGain = dbRealGain; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 for (unsigned i = 0; i < m_preDelayBuffers.size(); ++i) | 480 for (unsigned i = 0; i < m_preDelayBuffers.size(); ++i) |
| 470 m_preDelayBuffers[i]->zero(); | 481 m_preDelayBuffers[i]->zero(); |
| 471 | 482 |
| 472 m_preDelayReadIndex = 0; | 483 m_preDelayReadIndex = 0; |
| 473 m_preDelayWriteIndex = DefaultPreDelayFrames; | 484 m_preDelayWriteIndex = DefaultPreDelayFrames; |
| 474 | 485 |
| 475 m_maxAttackCompressionDiffDb = -1; // uninitialized state | 486 m_maxAttackCompressionDiffDb = -1; // uninitialized state |
| 476 } | 487 } |
| 477 | 488 |
| 478 } // namespace blink | 489 } // namespace blink |
| OLD | NEW |