![]() |
Mixxx
|
00001 #include <gmock/gmock.h> 00002 #include <gtest/gtest.h> 00003 00004 #include <QtDebug> 00005 #include <QVector> 00006 00007 #include "defs.h" 00008 #include "configobject.h" 00009 #include "engine/readaheadmanager.h" 00010 #include "engine/enginebufferscalelinear.h" 00011 00012 using ::testing::StrictMock; 00013 using ::testing::Return; 00014 using ::testing::Invoke; 00015 using ::testing::_; 00016 00017 namespace { 00018 00019 class ReadAheadManagerMock : public ReadAheadManager { 00020 public: 00021 ReadAheadManagerMock() 00022 : ReadAheadManager(NULL), 00023 m_pBuffer(NULL), 00024 m_iBufferSize(0), 00025 m_iReadPosition(0), 00026 m_iSamplesRead(0) { 00027 } 00028 00029 int getNextSamplesFake(double dRate, CSAMPLE* buffer, int requested_samples) { 00030 bool hasBuffer = m_pBuffer != NULL; 00031 // You forgot to set the mock read buffer. 00032 EXPECT_TRUE(hasBuffer); 00033 00034 for (int i = 0; i < requested_samples; ++i) { 00035 buffer[i] = hasBuffer ? m_pBuffer[m_iReadPosition++ % m_iBufferSize] : 0; 00036 } 00037 m_iSamplesRead += requested_samples; 00038 return requested_samples; 00039 } 00040 00041 void setReadBuffer(CSAMPLE* pBuffer, int iBufferSize) { 00042 m_pBuffer = pBuffer; 00043 m_iBufferSize = iBufferSize; 00044 m_iReadPosition = 0; 00045 } 00046 00047 int getSamplesRead() { 00048 return m_iSamplesRead; 00049 } 00050 00051 MOCK_METHOD3(getNextSamples, int(double dRate, CSAMPLE* buffer, int requested_samples)); 00052 00053 CSAMPLE* m_pBuffer; 00054 int m_iBufferSize; 00055 int m_iReadPosition; 00056 int m_iSamplesRead; 00057 }; 00058 00059 class EngineBufferScaleLinearTest : public testing::Test { 00060 protected: 00061 virtual void SetUp() { 00062 m_pConfig = new ConfigObject<ConfigValue>(""); 00063 m_pReadAheadMock = new StrictMock<ReadAheadManagerMock>(); 00064 m_pScaler = new EngineBufferScaleLinear(m_pReadAheadMock); 00065 } 00066 00067 virtual void TearDown() { 00068 delete m_pConfig; 00069 delete m_pScaler; 00070 delete m_pReadAheadMock; 00071 } 00072 00073 void SetRate(double rate) { 00074 m_pScaler->setTempo(1.0); 00075 m_pScaler->setBaseRate(rate); 00076 } 00077 00078 void SetRateNoLerp(double rate) { 00079 // Set it twice to prevent rate LERP'ing 00080 SetRate(rate); 00081 SetRate(rate); 00082 } 00083 00084 void ClearBuffer(CSAMPLE* pBuffer, int length) { 00085 memset(pBuffer, 0, sizeof(pBuffer[0])*length); 00086 } 00087 00088 void FillBuffer(CSAMPLE* pBuffer, CSAMPLE value, int length) { 00089 for (int i = 0; i < length; ++i) { 00090 pBuffer[i] = value; 00091 } 00092 } 00093 00094 void AssertWholeBufferEquals(const CSAMPLE* pBuffer, CSAMPLE value, int iBufferLen) { 00095 for (int i = 0; i < iBufferLen; ++i) { 00096 EXPECT_FLOAT_EQ(value, pBuffer[i]); 00097 } 00098 } 00099 00100 void AssertBufferCycles(const CSAMPLE* pBuffer, int iBufferLen, 00101 CSAMPLE* pCycleBuffer, int iCycleLength) { 00102 int cycleRead = 0; 00103 for (int i = 0; i < iBufferLen; ++i) { 00104 qDebug() << "i" << i << pBuffer[i] << pCycleBuffer[cycleRead % iCycleLength]; 00105 EXPECT_FLOAT_EQ(pCycleBuffer[cycleRead++ % iCycleLength], pBuffer[i]); 00106 } 00107 } 00108 00109 void AssertBufferMonotonicallyProgresses(const CSAMPLE* pBuffer, 00110 CSAMPLE start, CSAMPLE finish, 00111 int iBufferLen) { 00112 CSAMPLE currentLimit = start; 00113 bool increasing = (finish - start) > 0; 00114 00115 for (int i = 0; i < iBufferLen; ++i) { 00116 if (increasing) { 00117 //qDebug() << "i" << i << pBuffer[i] << currentLimit; 00118 EXPECT_GE(pBuffer[i], currentLimit); 00119 currentLimit = pBuffer[i]; 00120 } else { 00121 EXPECT_LE(pBuffer[i], currentLimit); 00122 currentLimit = pBuffer[i]; 00123 } 00124 } 00125 } 00126 00127 ConfigObject<ConfigValue>* m_pConfig; 00128 StrictMock<ReadAheadManagerMock>* m_pReadAheadMock; 00129 EngineBufferScaleLinear* m_pScaler; 00130 }; 00131 00132 TEST_F(EngineBufferScaleLinearTest, ScaleConstant) { 00133 SetRateNoLerp(1.0); 00134 00135 CSAMPLE readBuffer[1] = { 1.0f }; 00136 m_pReadAheadMock->setReadBuffer(readBuffer, 1); 00137 00138 // Tell the RAMAN mock to invoke getNextSamplesFake 00139 EXPECT_CALL(*m_pReadAheadMock, getNextSamples(_, _, _)) 00140 .WillRepeatedly(Invoke(m_pReadAheadMock, &ReadAheadManagerMock::getNextSamplesFake)); 00141 00142 CSAMPLE* pOutput = m_pScaler->scale(0, kiLinearScaleReadAheadLength, 0, 0); 00143 // TODO(rryan) the LERP w/ the previous buffer causes samples 0 and 1 to be 00144 // 0, for now skip the first two. 00145 AssertWholeBufferEquals(pOutput+2, 1.0f, kiLinearScaleReadAheadLength-2); 00146 00147 // Check that the total samples read from the RAMAN is equal to the samples 00148 // we requested. 00149 ASSERT_EQ(kiLinearScaleReadAheadLength, m_pReadAheadMock->getSamplesRead()); 00150 } 00151 00152 TEST_F(EngineBufferScaleLinearTest, UnityRateIsSamplePerfect) { 00153 SetRateNoLerp(1.0); 00154 00155 // Tell the RAMAN mock to invoke getNextSamplesFake 00156 EXPECT_CALL(*m_pReadAheadMock, getNextSamples(_, _, _)) 00157 .WillRepeatedly(Invoke(m_pReadAheadMock, &ReadAheadManagerMock::getNextSamplesFake)); 00158 00159 QVector<CSAMPLE> readBuffer; 00160 for (int i = 0; i < 1000; ++i) { 00161 readBuffer.push_back(i); 00162 } 00163 m_pReadAheadMock->setReadBuffer(readBuffer.data(), readBuffer.size()); 00164 00165 const int totalSamples = kiLinearScaleReadAheadLength; 00166 CSAMPLE* pOutput = m_pScaler->scale(0, totalSamples, 0, 0); 00167 00168 // TODO(rryan) the LERP w/ the previous buffer causes samples 0 and 1 to be 00169 // 0, for now skip the first two. 00170 const int skip = 2; 00171 AssertBufferCycles(pOutput+skip, totalSamples-skip, readBuffer.data(), readBuffer.size()); 00172 00173 // Check that the total samples read from the RAMAN is equal to the samples 00174 // we requested. 00175 ASSERT_EQ(totalSamples, m_pReadAheadMock->getSamplesRead()); 00176 } 00177 00178 TEST_F(EngineBufferScaleLinearTest, TestRateLERPMonotonicallyProgresses) { 00179 // Starting from a rate of 0.0, we'll go to a rate of 1.0 00180 SetRate(0.0f); 00181 SetRate(1.0f); 00182 00183 const int bufferSize = 1000; // kiLinearScaleReadAheadLength; 00184 00185 // Read all 1's 00186 CSAMPLE readBuffer[] = { 1.0f }; 00187 m_pReadAheadMock->setReadBuffer(readBuffer, 1); 00188 00189 // Tell the RAMAN mock to invoke getNextSamplesFake 00190 EXPECT_CALL(*m_pReadAheadMock, getNextSamples(_, _, _)) 00191 .WillRepeatedly(Invoke(m_pReadAheadMock, &ReadAheadManagerMock::getNextSamplesFake)); 00192 00193 CSAMPLE* pOutput = m_pScaler->scale(0, bufferSize, 0, 0); 00194 00195 AssertBufferMonotonicallyProgresses(pOutput, 0.0f, 1.0f, bufferSize); 00196 } 00197 00198 TEST_F(EngineBufferScaleLinearTest, TestDoubleSpeedSmoothlyHalvesSamples) { 00199 SetRateNoLerp(2.0f); 00200 const int bufferSize = 1000; // kiLinearScaleReadAheadLength; 00201 00202 // To prove that the channels don't touch each other, we're using negative 00203 // values on the first channel and positive values on the second channel. If 00204 // a fraction of either channel were mixed into either, then we would see a 00205 // big shift in our desired values. 00206 CSAMPLE readBuffer[] = { 1.0, 1.0, 00207 0.0, 0.0, 00208 -1.0, -1.0, 00209 0.0, 0.0 }; 00210 m_pReadAheadMock->setReadBuffer(readBuffer, 8); 00211 00212 // Tell the RAMAN mock to invoke getNextSamplesFake 00213 EXPECT_CALL(*m_pReadAheadMock, getNextSamples(_, _, _)) 00214 .WillRepeatedly(Invoke(m_pReadAheadMock, &ReadAheadManagerMock::getNextSamplesFake)); 00215 00216 CSAMPLE* pOutput = m_pScaler->scale(0, bufferSize, 0, 0); 00217 00218 CSAMPLE expectedResult[] = { 1.0, 1.0, 00219 -1.0, -1.0 }; 00220 00221 // TODO(rryan) the LERP w/ the previous buffer causes samples 0 and 1 to be 00222 // 0, for now skip the first two. 00223 const int skip = 2; 00224 AssertBufferCycles(pOutput+skip, bufferSize-skip, expectedResult, 4); 00225 00226 // Check that the total samples read from the RAMAN is double the samples 00227 // we requested. 00228 ASSERT_EQ(bufferSize*2, m_pReadAheadMock->getSamplesRead()); 00229 } 00230 00231 TEST_F(EngineBufferScaleLinearTest, TestHalfSpeedSmoothlyDoublesSamples) { 00232 SetRateNoLerp(0.5f); 00233 const int bufferSize = 1000; // kiLinearScaleReadAheadLength; 00234 00235 // To prove that the channels don't touch each other, we're using negative 00236 // values on the first channel and positive values on the second channel. If 00237 // a fraction of either channel were mixed into either, then we would see a 00238 // big shift in our desired values. 00239 CSAMPLE readBuffer[] = { -101.0, 101.0, 00240 -99.0, 99.0 }; 00241 m_pReadAheadMock->setReadBuffer(readBuffer, 4); 00242 00243 // Tell the RAMAN mock to invoke getNextSamplesFake 00244 EXPECT_CALL(*m_pReadAheadMock, getNextSamples(_, _, _)) 00245 .WillRepeatedly(Invoke(m_pReadAheadMock, &ReadAheadManagerMock::getNextSamplesFake)); 00246 00247 CSAMPLE* pOutput = m_pScaler->scale(0, bufferSize, 0, 0); 00248 00249 CSAMPLE expectedResult[] = { -101.0, 101.0, 00250 -100.0, 100.0, 00251 -99.0, 99.0, 00252 -100.0, 100.0 }; 00253 00254 // TODO(rryan) strange hysteresis happens and it takes 12 samples to produce 00255 // the desired cycle. Need to investigate this. 00256 const int skip = 12; 00257 AssertBufferCycles(pOutput+skip, bufferSize-skip, expectedResult, 8); 00258 00259 // Check that the total samples read from the RAMAN is half the samples 00260 // we requested. 00261 ASSERT_EQ(bufferSize/2, m_pReadAheadMock->getSamplesRead()); 00262 } 00263 00264 TEST_F(EngineBufferScaleLinearTest, TestRepeatedScaleCalls) { 00265 SetRateNoLerp(0.5f); 00266 const int bufferSize = 1000; // kiLinearScaleReadAheadLength; 00267 00268 // To prove that the channels don't touch each other, we're using negative 00269 // values on the first channel and positive values on the second channel. If 00270 // a fraction of either channel were mixed into either, then we would see a 00271 // big shift in our desired values. 00272 CSAMPLE readBuffer[] = { -101.0, 101.0, 00273 -99.0, 99.0 }; 00274 m_pReadAheadMock->setReadBuffer(readBuffer, 4); 00275 00276 // Tell the RAMAN mock to invoke getNextSamplesFake 00277 EXPECT_CALL(*m_pReadAheadMock, getNextSamples(_, _, _)) 00278 .WillRepeatedly(Invoke(m_pReadAheadMock, &ReadAheadManagerMock::getNextSamplesFake)); 00279 00280 CSAMPLE expectedResult[] = { -101.0, 101.0, 00281 -100.0, 100.0, 00282 -99.0, 99.0, 00283 -100.0, 100.0 }; 00284 00285 // Process 12 off the bat, strange hysteresis happens so get that over with here. 00286 const int skip = 12; 00287 CSAMPLE* pOutput = m_pScaler->scale(0, skip, 0, 0); 00288 00289 int samplesRemaining = bufferSize - skip; 00290 while (samplesRemaining > 0) { 00291 int toRead = math_min(8, samplesRemaining); 00292 pOutput = m_pScaler->scale(0, 8, 0, 0); 00293 samplesRemaining -= toRead; 00294 AssertBufferCycles(pOutput, toRead, expectedResult, toRead); 00295 } 00296 } 00297 00298 } // namespace