1 #include "engine/enginexfader.h"
2
3 #include "util/math.h"
4
5 //static
6 const char* EngineXfader::kXfaderConfigKey = "[Mixer Profile]";
7 const double EngineXfader::kTransformDefault = 1.0;
8 const double EngineXfader::kTransformMax = 1000.0;
9 const double EngineXfader::kTransformMin = 0.6;
10
getPowerCalibration(double transform)11 double EngineXfader::getPowerCalibration(double transform) {
12 // get the transform_root of -3db (.5)
13 return pow(0.5, 1.0 / transform);
14 }
15
getXfadeGains(double xfadePosition,double transform,double powerCalibration,double curve,bool reverse,CSAMPLE_GAIN * gain1,CSAMPLE_GAIN * gain2)16 void EngineXfader::getXfadeGains(double xfadePosition,
17 double transform,
18 double powerCalibration,
19 double curve,
20 bool reverse,
21 CSAMPLE_GAIN* gain1,
22 CSAMPLE_GAIN* gain2) {
23 if (gain1 == nullptr || gain2 == nullptr) {
24 return;
25 }
26
27 // Slow-fade/fast-cut
28 double xfadePositionLeft = xfadePosition;
29 double xfadePositionRight = xfadePosition;
30
31 if (curve == MIXXX_XFADER_CONSTPWR) {
32 // Apply Calibration
33 xfadePosition *= powerCalibration;
34 xfadePositionLeft = xfadePosition - powerCalibration;
35 xfadePositionRight = xfadePosition + powerCalibration;
36 }
37
38 if (xfadePositionLeft < 0) { // on left side
39 xfadePositionLeft *= -1;
40 *gain2 = static_cast<CSAMPLE_GAIN>(1.0 - (1.0 * pow(xfadePositionLeft, transform)));
41 } else {
42 *gain2 = 1.0f;
43 }
44
45 if(xfadePositionRight > 0) { // right side
46 *gain1 = static_cast<CSAMPLE_GAIN>(1.0 - (1.0 * pow(xfadePositionRight, transform)));
47 } else {
48 *gain1 = 1.0f;
49 }
50
51 //prevent phase reversal
52 if (*gain1 < 0.0) {
53 *gain1 = 0.0f;
54 }
55 if (*gain2 < 0.0) {
56 *gain2 = 0.0f;
57 }
58
59 if (curve == MIXXX_XFADER_CONSTPWR) {
60 if (*gain1 > *gain2) {
61 *gain2 = 1 - *gain1;
62 } else {
63 *gain1 = 1 - *gain2;
64 }
65
66 // The resulting power at the crossover point depends on the correlation of the input signals
67 // In theory the gain ratio varies from 0.5 for two equal signals to sqrt(0.5) = 0.707 for totally
68 // uncorrelated signals.
69 // Since the underlying requirement for this curve is constant loudness, we did a test with 30 s
70 // snippets of various genres and ReplayGain 2.0 analysis. Almost all results where near 0.707
71 // with one exception of mixing two parts of the same track, which resulted in 0.66.
72 // Based on the testing, we normalize the gain as if the signals were uncorrelated. The
73 // correction on the following lines ensures that gain1^2 + gain2^2 == 1.
74 CSAMPLE_GAIN gain = static_cast<CSAMPLE_GAIN>(sqrt(*gain1 * *gain1 + *gain2 * *gain2));
75 *gain1 = *gain1 / gain;
76 *gain2 = *gain2 / gain;
77 }
78
79 if (reverse) {
80 CSAMPLE_GAIN gain_temp = *gain1;
81 *gain1 = *gain2;
82 *gain2 = gain_temp;
83 }
84 }
85