Skip to content

Commit

Permalink
Fix fm synthesis.
Browse files Browse the repository at this point in the history
  • Loading branch information
linuscu committed Sep 11, 2024
1 parent 4305a25 commit 37df159
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 38 deletions.
13 changes: 13 additions & 0 deletions packages/math/include/math/MathFunc.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,19 @@ namespace l::math::functions {
}
}


template<class T>
T cos(T val) {
if constexpr (std::is_floating_point_v<T>) {
if constexpr (sizeof(T) == 4) {
return cosf(val);
}
else if constexpr (sizeof(T) == 8) {
return ::cos(val);
}
}
}

template<class T>
T mod(T val, T mod) {
if constexpr (std::is_floating_point_v<T>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,11 +331,11 @@ namespace l::nodegraph {
/*********************************************************************/
class GraphEffectArpeggio: public NodeGraphOp {
public:
std::string defaultInStrings[7] = { "Note On Id", "Note Off Id", "Velocity", "Bpm", "Fmod", "Attack", "Drift Sync"};
std::string defaultInStrings[8] = { "Note On Id", "Note Off Id", "Velocity", "Bpm", "Fmod", "Attack", "Smooth", "Drift Sync"};
std::string defaultOutStrings[3] = { "Freq", "Volume" };

GraphEffectArpeggio(NodeGraphBase* node) :
NodeGraphOp(node, 7, 2, 0)
NodeGraphOp(node, 8, 2, 0)
{}

virtual ~GraphEffectArpeggio() = default;
Expand Down Expand Up @@ -364,7 +364,9 @@ namespace l::nodegraph {
float mGainSmoothing = 0.01f;
float mGainSmoothingNeg = 0.01f;

float mCurrentNoteFreq = 0.0f;
float mFreqSmoothing = 0.1f;
float mFreqTarget = 0.0f;
float mFreq = 0.0f;
std::vector<int32_t> mNotes;
int32_t mNoteIndex = 0;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ namespace l::nodegraph {
class GraphSignalBase : public NodeGraphOp {
public:

static const int8_t mNumDefaultInputs = 6;
static const int8_t mNumDefaultInputs = 7;
static const int8_t mNumDefaultOutputs = 1;

GraphSignalBase(NodeGraphBase* node, std::string_view name, int32_t numInputs = 0, int32_t numOutputs = 0, int32_t numConstants = 0) :
NodeGraphOp(node, mNumDefaultInputs + numInputs, mNumDefaultOutputs + numOutputs, numConstants),
mName(name)
{}

std::string defaultInStrings[mNumDefaultInputs] = { "Reset", "Freq", "Volume", "Smooth", "Cutoff", "Resonance"};
std::string defaultInStrings[mNumDefaultInputs] = { "Reset", "Freq", "Volume", "Smooth", "Cutoff", "Resonance", "Phase expansion"};
std::string defaultOutStrings[mNumDefaultOutputs] = { "Out" };

virtual ~GraphSignalBase() = default;
Expand All @@ -58,7 +58,7 @@ namespace l::nodegraph {
virtual std::string_view GetOutputNameExtra(int8_t) { return ""; };
virtual void ResetSignal() {};
virtual void UpdateSignal(std::vector<NodeGraphInput>&, std::vector<NodeGraphOutput>&) {};
virtual float GenerateSignal(float deltaPhase) = 0;
virtual float GenerateSignal(float deltaTime, float freq, float deltaPhase) = 0;
protected:
std::string mName;

Expand Down Expand Up @@ -96,7 +96,7 @@ namespace l::nodegraph {
}
void ResetSignal() override;
void UpdateSignal(std::vector<NodeGraphInput>& inputs, std::vector<NodeGraphOutput>& outputs) override;
float GenerateSignal(float deltaPhase) override;
float GenerateSignal(float deltaTime, float freq, float deltaPhase) override;
protected:
float mFmod = 0.0f;
float mPmod = 0.0f;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ namespace l::nodegraph {
float fmod = inputs.at(4).Get();
float attack = inputs.at(5).Get();

if (inputs.at(6).Get() > 0.5f) {
if (inputs.at(7).Get() > 0.5f) {
mSamplesUntilUpdate = 0.0f;
}

Expand Down Expand Up @@ -565,9 +565,11 @@ namespace l::nodegraph {
}
else {
mNoteIndex = mNoteIndex % mNotes.size();
mCurrentNoteFreq = l::audio::GetFrequencyFromNote(static_cast<float>(mNotes.at(mNoteIndex)));
mFreqTarget = l::audio::GetFrequencyFromNote(static_cast<float>(mNotes.at(mNoteIndex)));
mNoteIndex++;
mGainTarget = velocity;
mFreqSmoothing = inputs.at(6).Get();
mFreqSmoothing *= mFreqSmoothing * 0.5f;
}
},
[&](int32_t start, int32_t end, bool) {
Expand All @@ -580,7 +582,8 @@ namespace l::nodegraph {
mGain += mGainSmoothingNeg * (-l::math::smooth::smootPolyh3(-delta));
}

outputs.at(0).mOutput = mCurrentNoteFreq;
mFreq += mFreqSmoothing * (mFreqTarget - mFreq);
outputs.at(0).mOutput = mFreq;
outputs.at(1).mOutput = mGain;
}
});
Expand Down
56 changes: 28 additions & 28 deletions packages/nodegraph/source/common/operations/NodeGraphOpSignal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace l::nodegraph {
mDeltaTime = 0.0f;
mVolume = 0.0f;
mSamplesUntilUpdate = 0.0f;
mUpdateSamples = 256.0f;
mUpdateSamples = 16.0f;
mHPCutoff = 0.5f;
mHPResonance = 0.0001f;
mHPState0 = 0.0f;
Expand All @@ -30,15 +30,17 @@ namespace l::nodegraph {
mNode->SetInput(0, 0.0f);
mNode->SetInput(1, 0.0f);
mNode->SetInput(2, 0.5f);
mNode->SetInput(3, 0.5f);
mNode->SetInput(4, 0.5f);
mNode->SetInput(5, 0.0001f);
mNode->SetInput(3, 1.0f);
mNode->SetInput(4, 0.0f);
mNode->SetInput(5, 0.0f);
mNode->SetInput(6, 0.5f);
mNode->SetInputBound(0, InputBound::INPUT_0_TO_1);
mNode->SetInputBound(1, InputBound::INPUT_CUSTOM, 0.0f, l::math::constants::FLTMAX);
mNode->SetInputBound(2, InputBound::INPUT_0_100);
mNode->SetInputBound(3, InputBound::INPUT_0_TO_1);
mNode->SetInputBound(4, InputBound::INPUT_0_TO_1);
mNode->SetInputBound(5, InputBound::INPUT_0_TO_1);
mNode->SetInputBound(6, InputBound::INPUT_0_TO_1);

ResetSignal();
}
Expand All @@ -53,18 +55,15 @@ namespace l::nodegraph {
mFreq = inputs.at(1).Get();
mVolumeTarget = inputs.at(2).Get();
mSmooth = 0.5f * inputs.at(3).Get();
float phaseExpansion = inputs.at(6).Get();

mDeltaPhase = mDeltaTime * mFreq;
float deltaPhaseExpanded = l::math::functions::pow(mDeltaPhase, 0.125f);
//float deltaPhaseExpanded = l::math::functions::pow(mDeltaPhase, phaseExpansion);
float deltaPhaseExpanded = l::math::functions::pow(mDeltaPhase, 0.4f - phaseExpansion * mDeltaPhase * 6.0f);
mHPCutoff = deltaPhaseExpanded + (1.0f - deltaPhaseExpanded) * inputs.at(4).Get();
mHPResonance = 1.0f - inputs.at(5).Get();

if (mFreq == 0.0f) {
mVolumeTarget = 0.0f;
outputs.at(0).mOutput = 0.0f;
return;
}
if (mReset > 0.5f) {
if (mFreq == 0.0f || mReset > 0.5f) {
mVolumeTarget = 0.0f;
}

Expand All @@ -73,7 +72,7 @@ namespace l::nodegraph {
},
[&](int32_t start, int32_t end, bool) {
for (int32_t i = start; i < end; i++) {
float signalTarget = GenerateSignal(mDeltaPhase);
float signalTarget = GenerateSignal(mDeltaTime, mFreq, mDeltaPhase);

// highpass filter
{
Expand All @@ -99,32 +98,33 @@ namespace l::nodegraph {
/*********************************************************************/

void GraphSignalSine2::ResetSignal() {
mNode->SetInput(mNumDefaultInputs + 0, 0.5f);
mNode->SetInput(mNumDefaultInputs + 0, 0.0f);
mNode->SetInput(mNumDefaultInputs + 1, 0.0f);
mNode->SetInputBound(mNumDefaultInputs + 0, InputBound::INPUT_0_TO_1);
mNode->SetInputBound(mNumDefaultInputs + 1, InputBound::INPUT_0_TO_1);
mUpdateSamples = 16.0f;
}

void GraphSignalSine2::UpdateSignal(std::vector<NodeGraphInput>& inputs, std::vector<NodeGraphOutput>&) {
mFmod = inputs.at(mNumDefaultInputs + 0).Get();
mPmod = inputs.at(mNumDefaultInputs + 1).Get();
float fmodRange = 16.0f;
mFmod = mFmod > 0.5f ? 1.0f + fmodRange * (mFmod - 0.5f) : 1.0f / (1.0f + fmodRange * (0.5f - mFmod));
mFmod *= 0.25f * 0.25f * 0.5f * 44100.0f / l::math::functions::max(mFreq, 1.0f);
}

float GraphSignalSine2::GenerateSignal(float deltaPhase) {
float GraphSignalSine2::GenerateSignal(float, float, float deltaPhase) {
mPhaseFmod += deltaPhase;
mPhaseFmod = l::math::functions::mod(mPhaseFmod, 1.0f);
float modulation = mFmod * (1.0f + 0.5f * l::math::functions::sin(l::math::constants::PI_f * mPhaseFmod * 2.0f));
float modulation = l::math::functions::cos(l::math::constants::PI_f * mPhaseFmod * 2.0f);

mPhase += deltaPhase * modulation;
mPhase = l::math::functions::mod(mPhase, 1.0f);
mPhase = mPhaseFmod;
mPhase += mFmod * modulation;
mPhase -= l::math::functions::floor(mPhase);

float phaseMod = mPhase + mPmod;
phaseMod = l::math::functions::mod(phaseMod, 1.0f);
float phaseMod = mPhaseFmod + mPmod;
phaseMod -= l::math::functions::floor(phaseMod);

mWave = mSmooth * (mPhase + phaseMod - mWave);
return l::math::functions::sin(l::math::constants::PI_f * mWave);
//mWave = mSmooth * (mPhase + phaseMod - mWave);
return 0.5f * (l::math::functions::sin(l::math::constants::PI_f * mPhase * 2.0f) + l::math::functions::sin(l::math::constants::PI_f * phaseMod * 2.0f));
}

/*********************************************************************/
Expand All @@ -137,7 +137,7 @@ namespace l::nodegraph {
mNode->SetInput(3, 0.0f);
mNode->SetInput(4, 0.5f);
mNode->SetInput(5, 0.0f);
mNode->SetInputBound(0, InputBound::INPUT_UNBOUNDED);
mNode->SetInputBound(0, InputBound::INPUT_CUSTOM, 0.0f, l::math::constants::FLTMAX);
mNode->SetInputBound(1, InputBound::INPUT_0_100);
mNode->SetInputBound(2, InputBound::INPUT_0_TO_2);
mNode->SetInputBound(3, InputBound::INPUT_0_TO_1);
Expand Down Expand Up @@ -228,7 +228,7 @@ namespace l::nodegraph {
mNode->SetInput(6, 0.0f);
mNode->SetInput(7, 0.5f);
mNode->SetInput(8, 0.0f);
mNode->SetInputBound(0, InputBound::INPUT_UNBOUNDED);
mNode->SetInputBound(0, InputBound::INPUT_CUSTOM, 0.0f, l::math::constants::FLTMAX);
mNode->SetInputBound(1, InputBound::INPUT_0_100);
mNode->SetInputBound(2, InputBound::INPUT_UNBOUNDED);
mNode->SetInputBound(3, InputBound::INPUT_UNBOUNDED);
Expand Down Expand Up @@ -301,7 +301,7 @@ namespace l::nodegraph {
mNode->SetInput(3, 0.0f);
mNode->SetInput(4, 0.5f);
mNode->SetInput(5, 0.0f);
mNode->SetInputBound(0, InputBound::INPUT_UNBOUNDED);
mNode->SetInputBound(0, InputBound::INPUT_CUSTOM, 0.0f, l::math::constants::FLTMAX);
mNode->SetInputBound(1, InputBound::INPUT_0_100);
mNode->SetInputBound(2, InputBound::INPUT_0_TO_1);
mNode->SetInputBound(3, InputBound::INPUT_0_100);
Expand Down Expand Up @@ -374,7 +374,7 @@ namespace l::nodegraph {
mNode->SetInput(1, 0.5f);
mNode->SetInput(2, 0.5f);
mNode->SetInput(3, 0.0f);
mNode->SetInputBound(0, InputBound::INPUT_UNBOUNDED);
mNode->SetInputBound(0, InputBound::INPUT_CUSTOM, 0.0f, l::math::constants::FLTMAX);
mNode->SetInputBound(1, InputBound::INPUT_0_100);
mNode->SetInputBound(2, InputBound::INPUT_0_TO_1);
mNode->SetInputBound(3, InputBound::INPUT_0_TO_1);
Expand Down Expand Up @@ -437,7 +437,7 @@ namespace l::nodegraph {
mNode->SetInput(3, 0.0f);
mNode->SetInput(4, 0.5f);
mNode->SetInput(5, 0.0f);
mNode->SetInputBound(0, InputBound::INPUT_UNBOUNDED);
mNode->SetInputBound(0, InputBound::INPUT_CUSTOM, 0.0f, l::math::constants::FLTMAX);
mNode->SetInputBound(1, InputBound::INPUT_0_100);
mNode->SetInputBound(2, InputBound::INPUT_0_TO_2);
mNode->SetInputBound(3, InputBound::INPUT_0_TO_1);
Expand Down

0 comments on commit 37df159

Please sign in to comment.