Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
* SymMODEcho.cpp
|
||||
* --------------
|
||||
* Purpose: Implementation of the SymMOD Echo DSP
|
||||
* Notes : (currently none)
|
||||
* Authors: OpenMPT Devs
|
||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifndef NO_PLUGINS
|
||||
#include "../Sndfile.h"
|
||||
#include "SymMODEcho.h"
|
||||
|
||||
OPENMPT_NAMESPACE_BEGIN
|
||||
|
||||
IMixPlugin *SymMODEcho::Create(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct)
|
||||
{
|
||||
return new (std::nothrow) SymMODEcho(factory, sndFile, mixStruct);
|
||||
}
|
||||
|
||||
|
||||
SymMODEcho::SymMODEcho(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct)
|
||||
: IMixPlugin(factory, sndFile, mixStruct)
|
||||
, m_chunk(PluginChunk::Default())
|
||||
{
|
||||
m_mixBuffer.Initialize(2, 2);
|
||||
InsertIntoFactoryList();
|
||||
RecalculateEchoParams();
|
||||
}
|
||||
|
||||
|
||||
void SymMODEcho::Process(float* pOutL, float* pOutR, uint32 numFrames)
|
||||
{
|
||||
const float *srcL = m_mixBuffer.GetInputBuffer(0), *srcR = m_mixBuffer.GetInputBuffer(1);
|
||||
float *outL = m_mixBuffer.GetOutputBuffer(0), *outR = m_mixBuffer.GetOutputBuffer(1);
|
||||
|
||||
const uint32 delayTime = m_SndFile.m_PlayState.m_nSamplesPerTick * m_chunk.param[kEchoDelay];
|
||||
// SymMODs don't have a variable tempo so the tick duration should never change... but if someone loads a module into an MPTM file we have to account for this.
|
||||
if(m_delayLine.size() < delayTime * 2)
|
||||
m_delayLine.resize(delayTime * 2);
|
||||
|
||||
const auto dspType = GetDSPType();
|
||||
if(dspType == DSPType::Off)
|
||||
{
|
||||
// Toggling the echo while it's running keeps its delay line untouched
|
||||
std::copy(srcL, srcL + numFrames, outL);
|
||||
std::copy(srcR, srcR + numFrames, outR);
|
||||
} else
|
||||
{
|
||||
for(uint32 i = 0; i < numFrames; i++)
|
||||
{
|
||||
if(m_writePos >= delayTime)
|
||||
m_writePos = 0;
|
||||
int readPos = m_writePos - delayTime;
|
||||
if(readPos < 0)
|
||||
readPos += delayTime;
|
||||
|
||||
const float lDry = *srcL++, rDry = *srcR++;
|
||||
const float lDelay = m_delayLine[readPos * 2], rDelay = m_delayLine[readPos * 2 + 1];
|
||||
|
||||
// Output samples
|
||||
*outL++ = (lDry + lDelay);
|
||||
*outR++ = (rDry + rDelay);
|
||||
|
||||
// Compute new delay line values
|
||||
float lOut = 0.0f, rOut = 0.0f;
|
||||
switch(dspType)
|
||||
{
|
||||
case DSPType::Off:
|
||||
break;
|
||||
case DSPType::Normal: // Normal
|
||||
lOut = (lDelay + lDry) * m_feedback;
|
||||
rOut = (rDelay + rDry) * m_feedback;
|
||||
break;
|
||||
case DSPType::Cross:
|
||||
case DSPType::Cross2:
|
||||
lOut = (rDelay + rDry) * m_feedback;
|
||||
rOut = (lDelay + lDry) * m_feedback;
|
||||
break;
|
||||
case DSPType::Center:
|
||||
lOut = (lDelay + (lDry + rDry) * 0.5f) * m_feedback;
|
||||
rOut = lOut;
|
||||
break;
|
||||
case DSPType::NumTypes:
|
||||
break;
|
||||
}
|
||||
|
||||
// Prevent denormals
|
||||
if(std::abs(lOut) < 1e-24f)
|
||||
lOut = 0.0f;
|
||||
if(std::abs(rOut) < 1e-24f)
|
||||
rOut = 0.0f;
|
||||
|
||||
m_delayLine[m_writePos * 2 + 0] = lOut;
|
||||
m_delayLine[m_writePos * 2 + 1] = rOut;
|
||||
m_writePos++;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessMixOps(pOutL, pOutR, m_mixBuffer.GetOutputBuffer(0), m_mixBuffer.GetOutputBuffer(1), numFrames);
|
||||
}
|
||||
|
||||
|
||||
void SymMODEcho::SaveAllParameters()
|
||||
{
|
||||
m_pMixStruct->defaultProgram = -1;
|
||||
try
|
||||
{
|
||||
const auto pluginData = mpt::as_raw_memory(m_chunk);
|
||||
m_pMixStruct->pluginData.assign(pluginData.begin(), pluginData.end());
|
||||
} catch(mpt::out_of_memory e)
|
||||
{
|
||||
mpt::delete_out_of_memory(e);
|
||||
m_pMixStruct->pluginData.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SymMODEcho::RestoreAllParameters(int32 program)
|
||||
{
|
||||
if(m_pMixStruct->pluginData.size() == sizeof(m_chunk) && !memcmp(m_pMixStruct->pluginData.data(), "Echo", 4))
|
||||
{
|
||||
std::copy(m_pMixStruct->pluginData.begin(), m_pMixStruct->pluginData.end(), mpt::as_raw_memory(m_chunk).begin());
|
||||
} else
|
||||
{
|
||||
IMixPlugin::RestoreAllParameters(program);
|
||||
}
|
||||
RecalculateEchoParams();
|
||||
}
|
||||
|
||||
|
||||
PlugParamValue SymMODEcho::GetParameter(PlugParamIndex index)
|
||||
{
|
||||
if(index < kEchoNumParameters)
|
||||
{
|
||||
return m_chunk.param[index] / 127.0f;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void SymMODEcho::SetParameter(PlugParamIndex index, PlugParamValue value)
|
||||
{
|
||||
if(index < kEchoNumParameters)
|
||||
{
|
||||
m_chunk.param[index] = mpt::saturate_round<uint8>(mpt::safe_clamp(value, 0.0f, 1.0f) * 127.0f);
|
||||
RecalculateEchoParams();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SymMODEcho::Resume()
|
||||
{
|
||||
m_isResumed = true;
|
||||
PositionChanged();
|
||||
}
|
||||
|
||||
|
||||
void SymMODEcho::PositionChanged()
|
||||
{
|
||||
try
|
||||
{
|
||||
m_delayLine.assign(127 * 2 * m_SndFile.m_PlayState.m_nSamplesPerTick, 0.0f);
|
||||
} catch(mpt::out_of_memory e)
|
||||
{
|
||||
mpt::delete_out_of_memory(e);
|
||||
}
|
||||
m_writePos = 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef MODPLUG_TRACKER
|
||||
|
||||
std::pair<PlugParamValue, PlugParamValue> SymMODEcho::GetParamUIRange(PlugParamIndex param)
|
||||
{
|
||||
if(param == kEchoType)
|
||||
return {0.0f, (static_cast<uint8>(DSPType::NumTypes) - 1) / 127.0f};
|
||||
else
|
||||
return {0.0f, 1.0f};
|
||||
}
|
||||
|
||||
CString SymMODEcho::GetParamName(PlugParamIndex param)
|
||||
{
|
||||
switch (param)
|
||||
{
|
||||
case kEchoType: return _T("Type");
|
||||
case kEchoDelay: return _T("Delay");
|
||||
case kEchoFeedback: return _T("Feedback");
|
||||
case kEchoNumParameters: break;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
CString SymMODEcho::GetParamLabel(PlugParamIndex param)
|
||||
{
|
||||
if(param == kEchoDelay)
|
||||
return _T("Ticks");
|
||||
if(param == kEchoFeedback)
|
||||
return _T("%");
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
CString SymMODEcho::GetParamDisplay(PlugParamIndex param)
|
||||
{
|
||||
switch(static_cast<Parameters>(param))
|
||||
{
|
||||
case kEchoType:
|
||||
switch(GetDSPType())
|
||||
{
|
||||
case DSPType::Off: return _T("Off");
|
||||
case DSPType::Normal: return _T("Normal");
|
||||
case DSPType::Cross: return _T("Cross");
|
||||
case DSPType::Cross2: return _T("Cross 2");
|
||||
case DSPType::Center: return _T("Center");
|
||||
case DSPType::NumTypes: break;
|
||||
}
|
||||
break;
|
||||
case kEchoDelay:
|
||||
return mpt::cfmt::val(m_chunk.param[kEchoDelay]);
|
||||
case kEchoFeedback:
|
||||
return mpt::cfmt::flt(m_feedback * 100.0f, 4);
|
||||
case kEchoNumParameters:
|
||||
break;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
#endif // MODPLUG_TRACKER
|
||||
|
||||
|
||||
IMixPlugin::ChunkData SymMODEcho::GetChunk(bool)
|
||||
{
|
||||
auto data = reinterpret_cast<const std::byte *>(&m_chunk);
|
||||
return ChunkData(data, sizeof(m_chunk));
|
||||
}
|
||||
|
||||
|
||||
void SymMODEcho::SetChunk(const ChunkData& chunk, bool)
|
||||
{
|
||||
auto data = chunk.data();
|
||||
if(chunk.size() == sizeof(chunk) && !memcmp(data, "Echo", 4))
|
||||
{
|
||||
memcpy(&m_chunk, data, chunk.size());
|
||||
RecalculateEchoParams();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SymMODEcho::RecalculateEchoParams()
|
||||
{
|
||||
if(m_chunk.param[kEchoType] >= static_cast<uint8>(DSPType::NumTypes))
|
||||
m_chunk.param[kEchoType] = 0;
|
||||
if(m_chunk.param[kEchoDelay] > 127)
|
||||
m_chunk.param[kEchoDelay] = 127;
|
||||
if(m_chunk.param[kEchoFeedback] > 127)
|
||||
m_chunk.param[kEchoFeedback] = 127;
|
||||
|
||||
if(GetDSPType() == DSPType::Cross2)
|
||||
m_feedback = 1.0f - std::pow(2.0f, -static_cast<float>(m_chunk.param[kEchoFeedback] + 1));
|
||||
else
|
||||
m_feedback = std::pow(2.0f, -static_cast<float>(m_chunk.param[kEchoFeedback]));
|
||||
}
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
||||
|
||||
#endif // NO_PLUGINS
|
Loading…
Add table
Add a link
Reference in a new issue