RateTransposer.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. ////////////////////////////////////////////////////////////////////////////////
  2. ///
  3. /// Sample rate transposer. Changes sample rate by using linear interpolation
  4. /// together with anti-alias filtering (first order interpolation with anti-
  5. /// alias filtering should be quite adequate for this application)
  6. ///
  7. /// Author : Copyright (c) Olli Parviainen
  8. /// Author e-mail : oparviai 'at' iki.fi
  9. /// SoundTouch WWW: http://www.surina.net/soundtouch
  10. ///
  11. ////////////////////////////////////////////////////////////////////////////////
  12. //
  13. // Last changed : $Date: 2013-06-14 17:34:33 +0000 (Fri, 14 Jun 2013) $
  14. // File revision : $Revision: 4 $
  15. //
  16. // $Id: RateTransposer.cpp 172 2013-06-14 17:34:33Z oparviai $
  17. //
  18. ////////////////////////////////////////////////////////////////////////////////
  19. //
  20. // License :
  21. //
  22. // SoundTouch audio processing library
  23. // Copyright (c) Olli Parviainen
  24. //
  25. // This library is free software; you can redistribute it and/or
  26. // modify it under the terms of the GNU Lesser General Public
  27. // License as published by the Free Software Foundation; either
  28. // version 2.1 of the License, or (at your option) any later version.
  29. //
  30. // This library is distributed in the hope that it will be useful,
  31. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  32. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  33. // Lesser General Public License for more details.
  34. //
  35. // You should have received a copy of the GNU Lesser General Public
  36. // License along with this library; if not, write to the Free Software
  37. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  38. //
  39. ////////////////////////////////////////////////////////////////////////////////
  40. #include <memory.h>
  41. #include <assert.h>
  42. #include <stdlib.h>
  43. #include <stdio.h>
  44. #include "RateTransposer.h"
  45. #include "AAFilter.h"
  46. using namespace soundtouch;
  47. /// A linear samplerate transposer class that uses integer arithmetics.
  48. /// for the transposing.
  49. class RateTransposerInteger : public RateTransposer
  50. {
  51. protected:
  52. int iSlopeCount;
  53. int iRate;
  54. SAMPLETYPE *sPrevSample;
  55. virtual void resetRegisters();
  56. virtual int transposeStereo(SAMPLETYPE *dest,
  57. const SAMPLETYPE *src,
  58. uint numSamples);
  59. virtual int transposeMono(SAMPLETYPE *dest,
  60. const SAMPLETYPE *src,
  61. uint numSamples);
  62. virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples);
  63. public:
  64. RateTransposerInteger();
  65. virtual ~RateTransposerInteger();
  66. /// Sets new target rate. Normal rate = 1.0, smaller values represent slower
  67. /// rate, larger faster rates.
  68. virtual void setRate(float newRate);
  69. };
  70. /// A linear samplerate transposer class that uses floating point arithmetics
  71. /// for the transposing.
  72. class RateTransposerFloat : public RateTransposer
  73. {
  74. protected:
  75. float fSlopeCount;
  76. SAMPLETYPE *sPrevSample;
  77. virtual void resetRegisters();
  78. virtual int transposeStereo(SAMPLETYPE *dest,
  79. const SAMPLETYPE *src,
  80. uint numSamples);
  81. virtual int transposeMono(SAMPLETYPE *dest,
  82. const SAMPLETYPE *src,
  83. uint numSamples);
  84. virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples);
  85. public:
  86. RateTransposerFloat();
  87. virtual ~RateTransposerFloat();
  88. };
  89. // Operator 'new' is overloaded so that it automatically creates a suitable instance
  90. // depending on if we've a MMX/SSE/etc-capable CPU available or not.
  91. void * RateTransposer::operator new(size_t s)
  92. {
  93. ST_THROW_RT_ERROR("Error in RateTransoser::new: don't use \"new TDStretch\" directly, use \"newInstance\" to create a new instance instead!");
  94. return newInstance();
  95. }
  96. RateTransposer *RateTransposer::newInstance()
  97. {
  98. #ifdef SOUNDTOUCH_INTEGER_SAMPLES
  99. return ::new RateTransposerInteger;
  100. #else
  101. return ::new RateTransposerFloat;
  102. #endif
  103. }
  104. // Constructor
  105. RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
  106. {
  107. numChannels = 2;
  108. bUseAAFilter = TRUE;
  109. fRate = 0;
  110. // Instantiates the anti-alias filter with default tap length
  111. // of 32
  112. pAAFilter = new AAFilter(32);
  113. }
  114. RateTransposer::~RateTransposer()
  115. {
  116. delete pAAFilter;
  117. }
  118. /// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable
  119. void RateTransposer::enableAAFilter(BOOL newMode)
  120. {
  121. bUseAAFilter = newMode;
  122. }
  123. /// Returns nonzero if anti-alias filter is enabled.
  124. BOOL RateTransposer::isAAFilterEnabled() const
  125. {
  126. return bUseAAFilter;
  127. }
  128. AAFilter *RateTransposer::getAAFilter()
  129. {
  130. return pAAFilter;
  131. }
  132. // Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
  133. // iRate, larger faster iRates.
  134. void RateTransposer::setRate(float newRate)
  135. {
  136. double fCutoff;
  137. fRate = newRate;
  138. // design a new anti-alias filter
  139. if (newRate > 1.0f)
  140. {
  141. fCutoff = 0.5f / newRate;
  142. }
  143. else
  144. {
  145. fCutoff = 0.5f * newRate;
  146. }
  147. pAAFilter->setCutoffFreq(fCutoff);
  148. }
  149. // Outputs as many samples of the 'outputBuffer' as possible, and if there's
  150. // any room left, outputs also as many of the incoming samples as possible.
  151. // The goal is to drive the outputBuffer empty.
  152. //
  153. // It's allowed for 'output' and 'input' parameters to point to the same
  154. // memory position.
  155. /*
  156. void RateTransposer::flushStoreBuffer()
  157. {
  158. if (storeBuffer.isEmpty()) return;
  159. outputBuffer.moveSamples(storeBuffer);
  160. }
  161. */
  162. // Adds 'nSamples' pcs of samples from the 'samples' memory position into
  163. // the input of the object.
  164. void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples)
  165. {
  166. processSamples(samples, nSamples);
  167. }
  168. // Transposes up the sample rate, causing the observed playback 'rate' of the
  169. // sound to decrease
  170. void RateTransposer::upsample(const SAMPLETYPE *src, uint nSamples)
  171. {
  172. uint count, sizeTemp, num;
  173. // If the parameter 'uRate' value is smaller than 'SCALE', first transpose
  174. // the samples and then apply the anti-alias filter to remove aliasing.
  175. // First check that there's enough room in 'storeBuffer'
  176. // (+16 is to reserve some slack in the destination buffer)
  177. sizeTemp = (uint)((float)nSamples / fRate + 16.0f);
  178. // Transpose the samples, store the result into the end of "storeBuffer"
  179. count = transpose(storeBuffer.ptrEnd(sizeTemp), src, nSamples);
  180. storeBuffer.putSamples(count);
  181. // Apply the anti-alias filter to samples in "store output", output the
  182. // result to "dest"
  183. num = storeBuffer.numSamples();
  184. count = pAAFilter->evaluate(outputBuffer.ptrEnd(num),
  185. storeBuffer.ptrBegin(), num, (uint)numChannels);
  186. outputBuffer.putSamples(count);
  187. // Remove the processed samples from "storeBuffer"
  188. storeBuffer.receiveSamples(count);
  189. }
  190. // Transposes down the sample rate, causing the observed playback 'rate' of the
  191. // sound to increase
  192. void RateTransposer::downsample(const SAMPLETYPE *src, uint nSamples)
  193. {
  194. uint count, sizeTemp;
  195. // If the parameter 'uRate' value is larger than 'SCALE', first apply the
  196. // anti-alias filter to remove high frequencies (prevent them from folding
  197. // over the lover frequencies), then transpose.
  198. // Add the new samples to the end of the storeBuffer
  199. storeBuffer.putSamples(src, nSamples);
  200. // Anti-alias filter the samples to prevent folding and output the filtered
  201. // data to tempBuffer. Note : because of the FIR filter length, the
  202. // filtering routine takes in 'filter_length' more samples than it outputs.
  203. assert(tempBuffer.isEmpty());
  204. sizeTemp = storeBuffer.numSamples();
  205. count = pAAFilter->evaluate(tempBuffer.ptrEnd(sizeTemp),
  206. storeBuffer.ptrBegin(), sizeTemp, (uint)numChannels);
  207. if (count == 0) return;
  208. // Remove the filtered samples from 'storeBuffer'
  209. storeBuffer.receiveSamples(count);
  210. // Transpose the samples (+16 is to reserve some slack in the destination buffer)
  211. sizeTemp = (uint)((float)nSamples / fRate + 16.0f);
  212. count = transpose(outputBuffer.ptrEnd(sizeTemp), tempBuffer.ptrBegin(), count);
  213. outputBuffer.putSamples(count);
  214. }
  215. // Transposes sample rate by applying anti-alias filter to prevent folding.
  216. // Returns amount of samples returned in the "dest" buffer.
  217. // The maximum amount of samples that can be returned at a time is set by
  218. // the 'set_returnBuffer_size' function.
  219. void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
  220. {
  221. uint count;
  222. uint sizeReq;
  223. if (nSamples == 0) return;
  224. assert(pAAFilter);
  225. // If anti-alias filter is turned off, simply transpose without applying
  226. // the filter
  227. if (bUseAAFilter == FALSE)
  228. {
  229. sizeReq = (uint)((float)nSamples / fRate + 1.0f);
  230. count = transpose(outputBuffer.ptrEnd(sizeReq), src, nSamples);
  231. outputBuffer.putSamples(count);
  232. return;
  233. }
  234. // Transpose with anti-alias filter
  235. if (fRate < 1.0f)
  236. {
  237. upsample(src, nSamples);
  238. }
  239. else
  240. {
  241. downsample(src, nSamples);
  242. }
  243. }
  244. // Transposes the sample rate of the given samples using linear interpolation.
  245. // Returns the number of samples returned in the "dest" buffer
  246. inline int RateTransposer::transpose(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
  247. {
  248. #ifndef USE_MULTICH_ALWAYS
  249. if (numChannels == 1)
  250. {
  251. return transposeMono(dest, src, nSamples);
  252. }
  253. else if (numChannels == 2)
  254. {
  255. return transposeStereo(dest, src, nSamples);
  256. }
  257. else
  258. #endif // USE_MULTICH_ALWAYS
  259. {
  260. assert(numChannels > 0);
  261. return transposeMulti(dest, src, nSamples);
  262. }
  263. }
  264. // Sets the number of channels, 1 = mono, 2 = stereo
  265. void RateTransposer::setChannels(int nChannels)
  266. {
  267. assert(nChannels > 0);
  268. if (numChannels == nChannels) return;
  269. // assert(nChannels == 1 || nChannels == 2);
  270. numChannels = nChannels;
  271. storeBuffer.setChannels(numChannels);
  272. tempBuffer.setChannels(numChannels);
  273. outputBuffer.setChannels(numChannels);
  274. // Inits the linear interpolation registers
  275. resetRegisters();
  276. }
  277. // Clears all the samples in the object
  278. void RateTransposer::clear()
  279. {
  280. outputBuffer.clear();
  281. storeBuffer.clear();
  282. }
  283. // Returns nonzero if there aren't any samples available for outputting.
  284. int RateTransposer::isEmpty() const
  285. {
  286. int res;
  287. res = FIFOProcessor::isEmpty();
  288. if (res == 0) return 0;
  289. return storeBuffer.isEmpty();
  290. }
  291. //////////////////////////////////////////////////////////////////////////////
  292. //
  293. // RateTransposerInteger - integer arithmetic implementation
  294. //
  295. /// fixed-point interpolation routine precision
  296. #define SCALE 65536
  297. // Constructor
  298. RateTransposerInteger::RateTransposerInteger() : RateTransposer()
  299. {
  300. // Notice: use local function calling syntax for sake of clarity,
  301. // to indicate the fact that C++ constructor can't call virtual functions.
  302. sPrevSample=0;
  303. RateTransposerInteger::resetRegisters();
  304. RateTransposerInteger::setRate(1.0f);
  305. }
  306. RateTransposerInteger::~RateTransposerInteger()
  307. {
  308. if (sPrevSample) delete[] sPrevSample;
  309. }
  310. void RateTransposerInteger::resetRegisters()
  311. {
  312. iSlopeCount = 0;
  313. delete[] sPrevSample;
  314. sPrevSample = new SAMPLETYPE[numChannels];
  315. memset(sPrevSample, 0, numChannels * sizeof(SAMPLETYPE));
  316. }
  317. // Transposes the sample rate of the given samples using linear interpolation.
  318. // 'Mono' version of the routine. Returns the number of samples returned in
  319. // the "dest" buffer
  320. int RateTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
  321. {
  322. int i, remain;
  323. LONG_SAMPLETYPE temp, vol1;
  324. if (nSamples == 0) return 0; // no samples, no work
  325. remain = nSamples - 1;
  326. i = 0;
  327. // Process the last sample saved from the previous call first...
  328. while (iSlopeCount <= SCALE)
  329. {
  330. vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
  331. temp = vol1 * sPrevSample[0] + iSlopeCount * src[0];
  332. dest[i] = (SAMPLETYPE)(temp / SCALE);
  333. i++;
  334. iSlopeCount += iRate;
  335. }
  336. // now always (iSlopeCount > SCALE)
  337. iSlopeCount -= SCALE;
  338. while (1)
  339. {
  340. while (iSlopeCount > SCALE)
  341. {
  342. iSlopeCount -= SCALE;
  343. src ++;
  344. remain --;
  345. if (remain == 0) goto end;
  346. }
  347. vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
  348. temp = src[0] * vol1 + iSlopeCount * src[1];
  349. dest[i] = (SAMPLETYPE)(temp / SCALE);
  350. i++;
  351. iSlopeCount += iRate;
  352. }
  353. end:
  354. // Store the last sample for the next round
  355. sPrevSample[0] = src[0];
  356. return i;
  357. }
  358. // Transposes the sample rate of the given samples using linear interpolation.
  359. // 'Stereo' version of the routine. Returns the number of samples returned in
  360. // the "dest" buffer
  361. int RateTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
  362. {
  363. int i, remain;
  364. LONG_SAMPLETYPE temp, vol1;
  365. if (nSamples == 0) return 0; // no samples, no work
  366. remain = nSamples - 1;
  367. i = 0;
  368. // Process the last sample saved from the sPrevSampleLious call first...
  369. while (iSlopeCount <= SCALE)
  370. {
  371. vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
  372. temp = vol1 * sPrevSample[0] + iSlopeCount * src[0];
  373. dest[2 * i] = (SAMPLETYPE)(temp / SCALE);
  374. temp = vol1 * sPrevSample[1] + iSlopeCount * src[1];
  375. dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE);
  376. i++;
  377. iSlopeCount += iRate;
  378. }
  379. // now always (iSlopeCount > SCALE)
  380. iSlopeCount -= SCALE;
  381. while (1)
  382. {
  383. while (iSlopeCount > SCALE)
  384. {
  385. iSlopeCount -= SCALE;
  386. remain --;
  387. src += 2;
  388. if (remain == 0) goto end;
  389. }
  390. vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
  391. temp = src[0] * vol1 + iSlopeCount * src[2];
  392. dest[2 * i] = (SAMPLETYPE)(temp / SCALE);
  393. temp = src[1] * vol1 + iSlopeCount * src[3];
  394. dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE);
  395. i++;
  396. iSlopeCount += iRate;
  397. }
  398. end:
  399. // Store the last sample for the next round
  400. sPrevSample[0] = src[0];
  401. sPrevSample[1] = src[1];
  402. return i;
  403. }
  404. int RateTransposerInteger::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
  405. {
  406. int i, remaining;
  407. LONG_SAMPLETYPE temp, vol1;
  408. if (nSamples == 0) return 0; // no samples, no work
  409. remaining = nSamples - 1;
  410. i = 0;
  411. // Process the last sample saved from the sPrevSampleLious call first...
  412. while (iSlopeCount <= SCALE)
  413. {
  414. for (int c = 0; c < numChannels; c ++)
  415. {
  416. vol1 = (SCALE - iSlopeCount);
  417. temp = vol1 * sPrevSample[c] + iSlopeCount * src[c];
  418. *dest = (SAMPLETYPE)(temp / SCALE);
  419. dest ++;
  420. }
  421. i++;
  422. iSlopeCount += iRate;
  423. }
  424. // now always (iSlopeCount > SCALE)
  425. iSlopeCount -= SCALE;
  426. while (1)
  427. {
  428. while (iSlopeCount > SCALE)
  429. {
  430. iSlopeCount -= SCALE;
  431. src += numChannels;
  432. remaining --;
  433. if (remaining == 0) goto end;
  434. }
  435. for (int c = 0; c < numChannels; c ++)
  436. {
  437. vol1 = (SCALE - iSlopeCount);
  438. temp = src[c] * vol1 + iSlopeCount * src[c + numChannels];
  439. *dest = (SAMPLETYPE)(temp / SCALE);
  440. dest++;
  441. }
  442. i++;
  443. iSlopeCount += iRate;
  444. }
  445. end:
  446. // Store the last sample for the next round
  447. memcpy(sPrevSample, src, numChannels * sizeof(SAMPLETYPE));
  448. return i;
  449. }
  450. // Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
  451. // iRate, larger faster iRates.
  452. void RateTransposerInteger::setRate(float newRate)
  453. {
  454. iRate = (int)(newRate * SCALE + 0.5f);
  455. RateTransposer::setRate(newRate);
  456. }
  457. //////////////////////////////////////////////////////////////////////////////
  458. //
  459. // RateTransposerFloat - floating point arithmetic implementation
  460. //
  461. //////////////////////////////////////////////////////////////////////////////
  462. // Constructor
  463. RateTransposerFloat::RateTransposerFloat() : RateTransposer()
  464. {
  465. // Notice: use local function calling syntax for sake of clarity,
  466. // to indicate the fact that C++ constructor can't call virtual functions.
  467. sPrevSample = NULL;
  468. RateTransposerFloat::resetRegisters();
  469. RateTransposerFloat::setRate(1.0f);
  470. }
  471. RateTransposerFloat::~RateTransposerFloat()
  472. {
  473. delete[] sPrevSample;
  474. }
  475. void RateTransposerFloat::resetRegisters()
  476. {
  477. fSlopeCount = 0;
  478. delete[] sPrevSample;
  479. sPrevSample = new SAMPLETYPE[numChannels];
  480. memset(sPrevSample, 0, numChannels * sizeof(SAMPLETYPE));
  481. }
  482. // Transposes the sample rate of the given samples using linear interpolation.
  483. // 'Mono' version of the routine. Returns the number of samples returned in
  484. // the "dest" buffer
  485. int RateTransposerFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
  486. {
  487. int i, remain;
  488. remain = 0;
  489. i = 0;
  490. // Process the last sample saved from the previous call first...
  491. while (fSlopeCount <= 1.0f)
  492. {
  493. dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSample[0] + fSlopeCount * src[0]);
  494. i++;
  495. fSlopeCount += fRate;
  496. }
  497. fSlopeCount -= 1.0f;
  498. if (nSamples > 1)
  499. {
  500. while (1)
  501. {
  502. while (fSlopeCount > 1.0f)
  503. {
  504. fSlopeCount -= 1.0f;
  505. src ++;
  506. remain --;
  507. if (remain == 0) goto end;
  508. }
  509. dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[0] + fSlopeCount * src[1]);
  510. i++;
  511. fSlopeCount += fRate;
  512. }
  513. }
  514. end:
  515. // Store the last sample for the next round
  516. sPrevSample[0] = src[0];
  517. return i;
  518. }
  519. // Transposes the sample rate of the given samples using linear interpolation.
  520. // 'Mono' version of the routine. Returns the number of samples returned in
  521. // the "dest" buffer
  522. int RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
  523. {
  524. int i, remain;
  525. if (nSamples == 0) return 0; // no samples, no work
  526. remain = nSamples - 1;
  527. i = 0;
  528. // Process the last sample saved from the sPrevSampleLious call first...
  529. while (fSlopeCount <= 1.0f)
  530. {
  531. dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSample[0] + fSlopeCount * src[0]);
  532. dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSample[1] + fSlopeCount * src[1]);
  533. i++;
  534. fSlopeCount += fRate;
  535. }
  536. // now always (iSlopeCount > 1.0f)
  537. fSlopeCount -= 1.0f;
  538. if (nSamples > 1)
  539. {
  540. while (1)
  541. {
  542. while (fSlopeCount > 1.0f)
  543. {
  544. fSlopeCount -= 1.0f;
  545. remain --;
  546. src += 2;
  547. if (remain == 0) goto end;
  548. }
  549. dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[0]
  550. + fSlopeCount * src[2]);
  551. dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[1]
  552. + fSlopeCount * src[3]);
  553. i++;
  554. fSlopeCount += fRate;
  555. }
  556. }
  557. end:
  558. // Store the last sample for the next round
  559. sPrevSample[0] = src[0];
  560. sPrevSample[1] = src[1];
  561. return i;
  562. }
  563. int RateTransposerFloat::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
  564. {
  565. int i, remaining;
  566. if (nSamples == 0) return 0; // no samples, no work
  567. remaining = nSamples - 1;
  568. i = 0;
  569. // Process the last sample saved from the sPrevSampleLious call first...
  570. while (fSlopeCount <= 1.0f)
  571. {
  572. for (int c = 0; c < numChannels; c ++)
  573. {
  574. *dest = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSample[c] + fSlopeCount * src[c]);
  575. dest ++;
  576. }
  577. i++;
  578. fSlopeCount += fRate;
  579. }
  580. // now always (iSlopeCount > 1.0f)
  581. fSlopeCount -= 1.0f;
  582. while (remaining > 0)
  583. {
  584. while (fSlopeCount > 1.0f)
  585. {
  586. fSlopeCount -= 1.0f;
  587. src += numChannels;
  588. remaining --;
  589. if (remaining == 0) goto end;
  590. }
  591. for (int c = 0; c < numChannels; c ++)
  592. {
  593. *dest = (SAMPLETYPE)((1.0f - fSlopeCount) * src[c]
  594. + fSlopeCount * src[c + numChannels]);
  595. dest++;
  596. }
  597. i++;
  598. fSlopeCount += fRate;
  599. }
  600. end:
  601. // Store the last sample for the next round
  602. memcpy(sPrevSample, src, numChannels * sizeof(SAMPLETYPE));
  603. return i;
  604. }