c_crossfader.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #include "c_crossfader.h"
  2. C_CROSSFADER::C_CROSSFADER(int length, int nCh, int sRate) : C_DATAPUMP<short>(length * 1 * 1) { // in milliseconds
  3. BufferLength = 0;
  4. srate = sRate;
  5. nch = nCh;
  6. crossfade = 0;
  7. mode = 0;
  8. SetBufferLength(length);
  9. }
  10. C_CROSSFADER::~C_CROSSFADER() {
  11. C_DATAPUMP<short>::~C_DATAPUMP();
  12. }
  13. // protected interfaces
  14. void C_CROSSFADER::SampleRateConvert(int newsrate) { // in samples per second // this needs work
  15. srate = newsrate;
  16. SetBufferLength(BufferLength);
  17. /*
  18. if (BufferBottom && BufferTop) {
  19. int newsratestep = srate != 0 ? newsrate / srate : 0;
  20. int oldsratestep = newsrate != 0 ? srate / newsrate : 0;
  21. if (newsratestep && oldsratestep) {
  22. int newbuflength = (BufferLength * newsrate) / srate;
  23. int newbufsize = (newbuflength * nch * srate * sizeof(short)) / 1000;
  24. short *newbuf = (short *)malloc(newbufsize);
  25. short *newbufptr = newbuf;
  26. short *endbufptr = newbufptr+(newbufsize/sizeof(short));
  27. short *oldbufptr = BufferBottom;
  28. do {
  29. for(int i = 0; i < newsratestep; i++, newbufptr+=nch) {
  30. if (newbufptr >= endbufptr) break;
  31. *newbufptr = *oldbufptr;
  32. if (nch == 2) *(newbufptr+1) = *(oldbufptr+1);
  33. }
  34. oldbufptr += oldsratestep * nch;
  35. } while(newbufptr < endbufptr);
  36. free(BufferBottom);
  37. BufferLength = newbuflength;
  38. BufferBottom = newbuf;
  39. BufferTop = endbufptr;
  40. BufferStart = BufferEnd = BufferBottom;
  41. }
  42. }
  43. */
  44. }
  45. void C_CROSSFADER::ChannelConvert(int newnch) { // this needs work
  46. nch = newnch;
  47. SetBufferLength(BufferLength);
  48. /*
  49. if (BufferBottom && BufferTop) {
  50. int newbuflength = (BufferLength * newnch) / nch;
  51. int newbufsize = (newbuflength * nch * srate * sizeof(short)) / 1000;
  52. short *newbuf = (short *)malloc(newbufsize);
  53. short *newbufptr = newbuf;
  54. short *endbufptr = newbufptr+(newbufsize/sizeof(short));
  55. short *oldbufptr = BufferBottom;
  56. for(; newbufptr < endbufptr; newbufptr+=newnch, oldbufptr+=nch) {
  57. if (newnch == 1) *newbufptr = (*oldbufptr + *(oldbufptr+1)) >> 1;
  58. else *(newbufptr+1) = *newbufptr = *oldbufptr;
  59. }
  60. free(BufferBottom);
  61. BufferLength = newbuflength;
  62. BufferBottom = newbuf;
  63. BufferTop = endbufptr;
  64. BufferStart = BufferEnd = BufferBottom;
  65. }
  66. */
  67. }
  68. // human interfaces
  69. void C_CROSSFADER::SetSampleRate(int sRate) { // in samples per second
  70. if (sRate != srate) {
  71. if (srate && sRate) SampleRateConvert(sRate);
  72. }
  73. if (sRate) srate = sRate;
  74. }
  75. void C_CROSSFADER::SetChannels(int nCh) {
  76. if (nCh != nch) {
  77. if (nch && nCh) ChannelConvert(nCh);
  78. }
  79. if (nCh) nch = nCh;
  80. }
  81. void C_CROSSFADER::SetBufferLength(int bufferLength) { // in milliseconds
  82. BufferLength = bufferLength;
  83. resizeBuffer((BufferLength * srate * nch) / 1000);
  84. }
  85. void C_CROSSFADER::SetCrossfading(int onoff) {
  86. if (crossfade == 0) {
  87. crossfade = onoff ? 1 : 0;
  88. if (onoff) BufferEnd = BufferStart;
  89. }
  90. }
  91. void C_CROSSFADER::SetCrossfadeMode(int Mode) {
  92. mode = Mode;
  93. }
  94. void C_CROSSFADER::addItems(short *inputBuffer, size_t inputSize) {
  95. if (inputBuffer && inputSize) {
  96. size_t numsamps = inputSize*nch;
  97. if (crossfade==0) {
  98. memcpy(BufferEnd,inputBuffer,numsamps*sizeof(short)); // copy our records in
  99. BufferEnd += numsamps;
  100. } else { // do our crappy crossfade
  101. short *smpptr = inputBuffer;
  102. size_t bufsamps = (BufferTop-BufferBottom)/nch;
  103. size_t bufpos = (BufferEnd >= BufferStart ? BufferEnd-BufferStart : (BufferEnd-BufferBottom)+(BufferTop-BufferStart)) / nch;
  104. size_t dist = ((BufferTop - BufferBottom) / nch) - bufpos;
  105. for(size_t i = 0; i != numsamps; i++) {
  106. if (BufferEnd >= BufferTop) BufferEnd = BufferBottom + (BufferEnd-BufferTop);
  107. if (mode == 0) { // X-style (techno mix-style)
  108. *BufferEnd = (short)(((((double)*BufferEnd++)*dist) + (((double)*smpptr++)*bufpos)) / bufsamps);
  109. if (nch==1 || i&1) { // every-other I or always when mono.
  110. bufpos++;
  111. dist--;
  112. }
  113. } else if (mode == 1) { // h-style (rock radio station-style)
  114. *BufferEnd = (short)(((((double)*BufferEnd++)*dist) + ((double)*smpptr++)) / bufsamps);
  115. if (nch==1 || i&1) dist--; // every-other I or always when mono.
  116. }
  117. }
  118. if (dist < inputSize) crossfade = 0;
  119. }
  120. if (BufferEnd >= BufferTop) BufferEnd = BufferBottom + (BufferEnd-BufferTop);
  121. }
  122. }
  123. size_t C_CROSSFADER::put(short *inputBuffer, size_t inputSize) { // in channel-less shorts
  124. // returns number of <T> records added to logical buffer
  125. size_t retval = 0;
  126. if (inputBuffer && inputSize) {
  127. size_t fitting = (((BufferTop-BufferBottom)-1) - size()) / nch; // can't go over our logical boundary.... blah
  128. if (fitting > inputSize) fitting = inputSize; // the entire thing can fit. yeay!
  129. retval = fitting;
  130. if (fitting > 0) {
  131. short *bufptr = inputBuffer;
  132. size_t top = (BufferEnd >= BufferStart ? BufferTop-BufferEnd : 0) / nch; // number of <T> records free at top of physical buffer
  133. size_t bottom = (BufferEnd >= BufferStart ? BufferStart-BufferBottom : (BufferStart-BufferEnd)) / nch; // number of <T> records free at bottom of physical buffer
  134. if (top > 0) {
  135. if (top > fitting) top = fitting;
  136. addItems(bufptr,top);
  137. fitting -= top;
  138. bufptr += top*nch;
  139. }
  140. if (bottom > 0 && fitting > 0) {
  141. if (bottom > fitting) bottom = fitting;
  142. addItems(bufptr,bottom);
  143. }
  144. }
  145. }
  146. return retval;
  147. }
  148. size_t C_CROSSFADER::get(short *outputBuffer, size_t outputSize, int nCh) { // in channel-less shorts
  149. // returns number of <T> records pulled from the logical buffer
  150. size_t retval = 0;
  151. nch = nCh;
  152. if (outputBuffer && outputSize) {
  153. size_t fitting = size() / nch;
  154. if (fitting > outputSize) fitting = outputSize;
  155. retval = fitting;
  156. if (fitting > 0) {
  157. short *bufptr = outputBuffer;
  158. size_t top = (BufferEnd >= BufferStart ? BufferEnd-BufferStart : BufferTop-BufferStart) / nch; // number of <T> records at top of physical buffer
  159. size_t bottom = (BufferEnd >= BufferStart ? 0 : BufferEnd-BufferBottom) / nch; // number of <T> records at bottom of physical buffer
  160. if (top > 0) {
  161. if (top > fitting) top = fitting;
  162. getItems(bufptr,top*nch);
  163. delItems(0,top*nch);
  164. fitting -= top;
  165. bufptr += top*nch;
  166. }
  167. if (bottom > 0 && fitting > 0) {
  168. if (bottom > fitting) bottom = fitting;
  169. getItems(bufptr,bottom*nch);
  170. delItems(0,bottom*nch);
  171. }
  172. }
  173. }
  174. return retval;
  175. }