diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/DSP/dsp_sc/crossfader | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Plugins/DSP/dsp_sc/crossfader')
-rw-r--r-- | Src/Plugins/DSP/dsp_sc/crossfader/c_crossfader.cpp | 189 | ||||
-rw-r--r-- | Src/Plugins/DSP/dsp_sc/crossfader/c_crossfader.h | 33 |
2 files changed, 222 insertions, 0 deletions
diff --git a/Src/Plugins/DSP/dsp_sc/crossfader/c_crossfader.cpp b/Src/Plugins/DSP/dsp_sc/crossfader/c_crossfader.cpp new file mode 100644 index 00000000..776f2c61 --- /dev/null +++ b/Src/Plugins/DSP/dsp_sc/crossfader/c_crossfader.cpp @@ -0,0 +1,189 @@ +#include "c_crossfader.h" + +C_CROSSFADER::C_CROSSFADER(int length, int nCh, int sRate) : C_DATAPUMP<short>(length * 1 * 1) { // in milliseconds + BufferLength = 0; + srate = sRate; + nch = nCh; + crossfade = 0; + mode = 0; + SetBufferLength(length); +} + +C_CROSSFADER::~C_CROSSFADER() { + C_DATAPUMP<short>::~C_DATAPUMP(); +} + +// protected interfaces + +void C_CROSSFADER::SampleRateConvert(int newsrate) { // in samples per second // this needs work + srate = newsrate; + SetBufferLength(BufferLength); +/* + if (BufferBottom && BufferTop) { + int newsratestep = srate != 0 ? newsrate / srate : 0; + int oldsratestep = newsrate != 0 ? srate / newsrate : 0; + if (newsratestep && oldsratestep) { + int newbuflength = (BufferLength * newsrate) / srate; + int newbufsize = (newbuflength * nch * srate * sizeof(short)) / 1000; + short *newbuf = (short *)malloc(newbufsize); + short *newbufptr = newbuf; + short *endbufptr = newbufptr+(newbufsize/sizeof(short)); + short *oldbufptr = BufferBottom; + do { + for(int i = 0; i < newsratestep; i++, newbufptr+=nch) { + if (newbufptr >= endbufptr) break; + *newbufptr = *oldbufptr; + if (nch == 2) *(newbufptr+1) = *(oldbufptr+1); + } + oldbufptr += oldsratestep * nch; + } while(newbufptr < endbufptr); + free(BufferBottom); + BufferLength = newbuflength; + BufferBottom = newbuf; + BufferTop = endbufptr; + BufferStart = BufferEnd = BufferBottom; + } + } +*/ +} + +void C_CROSSFADER::ChannelConvert(int newnch) { // this needs work + nch = newnch; + SetBufferLength(BufferLength); +/* + if (BufferBottom && BufferTop) { + int newbuflength = (BufferLength * newnch) / nch; + int newbufsize = (newbuflength * nch * srate * sizeof(short)) / 1000; + short *newbuf = (short *)malloc(newbufsize); + short *newbufptr = newbuf; + short *endbufptr = newbufptr+(newbufsize/sizeof(short)); + short *oldbufptr = BufferBottom; + for(; newbufptr < endbufptr; newbufptr+=newnch, oldbufptr+=nch) { + if (newnch == 1) *newbufptr = (*oldbufptr + *(oldbufptr+1)) >> 1; + else *(newbufptr+1) = *newbufptr = *oldbufptr; + } + free(BufferBottom); + BufferLength = newbuflength; + BufferBottom = newbuf; + BufferTop = endbufptr; + BufferStart = BufferEnd = BufferBottom; + } +*/ +} + +// human interfaces + +void C_CROSSFADER::SetSampleRate(int sRate) { // in samples per second + if (sRate != srate) { + if (srate && sRate) SampleRateConvert(sRate); + } + if (sRate) srate = sRate; +} + +void C_CROSSFADER::SetChannels(int nCh) { + if (nCh != nch) { + if (nch && nCh) ChannelConvert(nCh); + } + if (nCh) nch = nCh; +} + +void C_CROSSFADER::SetBufferLength(int bufferLength) { // in milliseconds + BufferLength = bufferLength; + resizeBuffer((BufferLength * srate * nch) / 1000); +} + +void C_CROSSFADER::SetCrossfading(int onoff) { + if (crossfade == 0) { + crossfade = onoff ? 1 : 0; + if (onoff) BufferEnd = BufferStart; + } +} + +void C_CROSSFADER::SetCrossfadeMode(int Mode) { + mode = Mode; +} + +void C_CROSSFADER::addItems(short *inputBuffer, size_t inputSize) { + if (inputBuffer && inputSize) { + size_t numsamps = inputSize*nch; + if (crossfade==0) { + memcpy(BufferEnd,inputBuffer,numsamps*sizeof(short)); // copy our records in + BufferEnd += numsamps; + } else { // do our crappy crossfade + short *smpptr = inputBuffer; + size_t bufsamps = (BufferTop-BufferBottom)/nch; + size_t bufpos = (BufferEnd >= BufferStart ? BufferEnd-BufferStart : (BufferEnd-BufferBottom)+(BufferTop-BufferStart)) / nch; + size_t dist = ((BufferTop - BufferBottom) / nch) - bufpos; + for(size_t i = 0; i != numsamps; i++) { + if (BufferEnd >= BufferTop) BufferEnd = BufferBottom + (BufferEnd-BufferTop); + if (mode == 0) { // X-style (techno mix-style) + *BufferEnd = (short)(((((double)*BufferEnd++)*dist) + (((double)*smpptr++)*bufpos)) / bufsamps); + if (nch==1 || i&1) { // every-other I or always when mono. + bufpos++; + dist--; + } + } else if (mode == 1) { // h-style (rock radio station-style) + *BufferEnd = (short)(((((double)*BufferEnd++)*dist) + ((double)*smpptr++)) / bufsamps); + if (nch==1 || i&1) dist--; // every-other I or always when mono. + } + } + if (dist < inputSize) crossfade = 0; + } + if (BufferEnd >= BufferTop) BufferEnd = BufferBottom + (BufferEnd-BufferTop); + } +} + +size_t C_CROSSFADER::put(short *inputBuffer, size_t inputSize) { // in channel-less shorts + // returns number of <T> records added to logical buffer + size_t retval = 0; + if (inputBuffer && inputSize) { + size_t fitting = (((BufferTop-BufferBottom)-1) - size()) / nch; // can't go over our logical boundary.... blah + if (fitting > inputSize) fitting = inputSize; // the entire thing can fit. yeay! + retval = fitting; + if (fitting > 0) { + short *bufptr = inputBuffer; + size_t top = (BufferEnd >= BufferStart ? BufferTop-BufferEnd : 0) / nch; // number of <T> records free at top of physical buffer + size_t bottom = (BufferEnd >= BufferStart ? BufferStart-BufferBottom : (BufferStart-BufferEnd)) / nch; // number of <T> records free at bottom of physical buffer + if (top > 0) { + if (top > fitting) top = fitting; + addItems(bufptr,top); + fitting -= top; + bufptr += top*nch; + } + if (bottom > 0 && fitting > 0) { + if (bottom > fitting) bottom = fitting; + addItems(bufptr,bottom); + } + } + } + return retval; +} + +size_t C_CROSSFADER::get(short *outputBuffer, size_t outputSize, int nCh) { // in channel-less shorts + // returns number of <T> records pulled from the logical buffer + size_t retval = 0; + nch = nCh; + if (outputBuffer && outputSize) { + size_t fitting = size() / nch; + if (fitting > outputSize) fitting = outputSize; + retval = fitting; + if (fitting > 0) { + short *bufptr = outputBuffer; + size_t top = (BufferEnd >= BufferStart ? BufferEnd-BufferStart : BufferTop-BufferStart) / nch; // number of <T> records at top of physical buffer + size_t bottom = (BufferEnd >= BufferStart ? 0 : BufferEnd-BufferBottom) / nch; // number of <T> records at bottom of physical buffer + if (top > 0) { + if (top > fitting) top = fitting; + getItems(bufptr,top*nch); + delItems(0,top*nch); + fitting -= top; + bufptr += top*nch; + } + if (bottom > 0 && fitting > 0) { + if (bottom > fitting) bottom = fitting; + getItems(bufptr,bottom*nch); + delItems(0,bottom*nch); + } + } + } + return retval; +}
\ No newline at end of file diff --git a/Src/Plugins/DSP/dsp_sc/crossfader/c_crossfader.h b/Src/Plugins/DSP/dsp_sc/crossfader/c_crossfader.h new file mode 100644 index 00000000..7c044a9a --- /dev/null +++ b/Src/Plugins/DSP/dsp_sc/crossfader/c_crossfader.h @@ -0,0 +1,33 @@ +#ifndef __C_CROSSFADER_H__ +#define __C_CROSSFADER_H__ + +#include "../Include/c_datapump.h" + +class C_CROSSFADER : public C_DATAPUMP<short> { +private: +protected: + int BufferLength; // in milliseconds + int srate; + int nch; + int crossfade; + int mode; + + void SampleRateConvert(int newsrate); + void ChannelConvert(int newnch); + + virtual void addItems(short *inputBuffer, size_t inputSize); // overriding the addItems() function to do crossfading and channels +public: + C_CROSSFADER(int length, int nCh, int sRate); // length is in milliseconds + virtual ~C_CROSSFADER(); + + void SetChannels(int nCh); + void SetSampleRate(int sRate); // in samples per second + void SetBufferLength(int bufferLength); // in milliseconds + void SetCrossfading(int onoff); + void SetCrossfadeMode(int Mode); // 0 = X-style, 1 = h-style + + virtual size_t put(short *inputBuffer, size_t inputSize); // in channel-less shorts + virtual size_t get(short *outputBuffer, size_t outputSize, int nCh); // in channel-less shorts +}; + +#endif // !__C_CROSSFADER_H__
\ No newline at end of file |