Skip to content

Commit

Permalink
Add FFTLFO node
Browse files Browse the repository at this point in the history
  • Loading branch information
ideoforms committed Jul 4, 2024
1 parent 7e757f2 commit f4d410a
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ The following Node classes are currently included with the base distribution:
| **Buffer: Granulation** | [SegmentedGranulator](https://signalflow.dev/library/buffer/granulation/segmentedgranulator/), [Granulator](https://signalflow.dev/library/buffer/granulation/granulator/) |
| **Control** | [MouseX](https://signalflow.dev/library/control/mousex/), [MouseY](https://signalflow.dev/library/control/mousey/), [MouseDown](https://signalflow.dev/library/control/mousedown/) |
| **Envelope** | [ADSREnvelope](https://signalflow.dev/library/envelope/adsrenvelope/), [ASREnvelope](https://signalflow.dev/library/envelope/asrenvelope/), [DetectSilence](https://signalflow.dev/library/envelope/detectsilence/), [Envelope](https://signalflow.dev/library/envelope/envelope/), [Line](https://signalflow.dev/library/envelope/line/), [RectangularEnvelope](https://signalflow.dev/library/envelope/rectangularenvelope/) |
| **FFT** | [FFTContinuousPhaseVocoder](https://signalflow.dev/library/fft/fftcontinuousphasevocoder/), [FFTConvolve](https://signalflow.dev/library/fft/fftconvolve/), [FFTContrast](https://signalflow.dev/library/fft/fftcontrast/), [FFTMagnitudePhaseArray](https://signalflow.dev/library/fft/fftmagnitudephasearray/), [FFTRandomPhase](https://signalflow.dev/library/fft/fftrandomphase/), [FFTScaleMagnitudes](https://signalflow.dev/library/fft/fftscalemagnitudes/), [FFTTransform](https://signalflow.dev/library/fft/ffttransform/), [FFT](https://signalflow.dev/library/fft/fft/), [FFTNode](https://signalflow.dev/library/fft/fftnode/), [FFTOpNode](https://signalflow.dev/library/fft/fftopnode/), [FFTFindPeaks](https://signalflow.dev/library/fft/fftfindpeaks/), [IFFT](https://signalflow.dev/library/fft/ifft/), [FFTLPF](https://signalflow.dev/library/fft/fftlpf/), [FFTNoiseGate](https://signalflow.dev/library/fft/fftnoisegate/), [FFTPhaseVocoder](https://signalflow.dev/library/fft/fftphasevocoder/), [FFTTonality](https://signalflow.dev/library/fft/ffttonality/), [FFTZeroPhase](https://signalflow.dev/library/fft/fftzerophase/) |
| **FFT** | [FFTContinuousPhaseVocoder](https://signalflow.dev/library/fft/fftcontinuousphasevocoder/), [FFTConvolve](https://signalflow.dev/library/fft/fftconvolve/), [FFTContrast](https://signalflow.dev/library/fft/fftcontrast/), [FFTCrossFade](https://signalflow.dev/library/fft/fftcrossfade/), [FFTLFO](https://signalflow.dev/library/fft/fftlfo/), [FFTMagnitudePhaseArray](https://signalflow.dev/library/fft/fftmagnitudephasearray/), [FFTRandomPhase](https://signalflow.dev/library/fft/fftrandomphase/), [FFTScaleMagnitudes](https://signalflow.dev/library/fft/fftscalemagnitudes/), [FFTTransform](https://signalflow.dev/library/fft/ffttransform/), [FFT](https://signalflow.dev/library/fft/fft/), [FFTNode](https://signalflow.dev/library/fft/fftnode/), [FFTOpNode](https://signalflow.dev/library/fft/fftopnode/), [FFTFindPeaks](https://signalflow.dev/library/fft/fftfindpeaks/), [IFFT](https://signalflow.dev/library/fft/ifft/), [FFTLPF](https://signalflow.dev/library/fft/fftlpf/), [FFTNoiseGate](https://signalflow.dev/library/fft/fftnoisegate/), [FFTPhaseVocoder](https://signalflow.dev/library/fft/fftphasevocoder/), [FFTTonality](https://signalflow.dev/library/fft/ffttonality/), [FFTZeroPhase](https://signalflow.dev/library/fft/fftzerophase/) |
| **Operators** | [Add](https://signalflow.dev/library/operators/add/), [AmplitudeToDecibels](https://signalflow.dev/library/operators/amplitudetodecibels/), [DecibelsToAmplitude](https://signalflow.dev/library/operators/decibelstoamplitude/), [ChannelArray](https://signalflow.dev/library/operators/channelarray/), [ChannelCrossfade](https://signalflow.dev/library/operators/channelcrossfade/), [ChannelMixer](https://signalflow.dev/library/operators/channelmixer/), [ChannelSelect](https://signalflow.dev/library/operators/channelselect/), [Equal](https://signalflow.dev/library/operators/equal/), [NotEqual](https://signalflow.dev/library/operators/notequal/), [GreaterThan](https://signalflow.dev/library/operators/greaterthan/), [GreaterThanOrEqual](https://signalflow.dev/library/operators/greaterthanorequal/), [LessThan](https://signalflow.dev/library/operators/lessthan/), [LessThanOrEqual](https://signalflow.dev/library/operators/lessthanorequal/), [Modulo](https://signalflow.dev/library/operators/modulo/), [Abs](https://signalflow.dev/library/operators/abs/), [If](https://signalflow.dev/library/operators/if/), [Divide](https://signalflow.dev/library/operators/divide/), [FrequencyToMidiNote](https://signalflow.dev/library/operators/frequencytomidinote/), [MidiNoteToFrequency](https://signalflow.dev/library/operators/midinotetofrequency/), [Multiply](https://signalflow.dev/library/operators/multiply/), [Pow](https://signalflow.dev/library/operators/pow/), [RoundToScale](https://signalflow.dev/library/operators/roundtoscale/), [Round](https://signalflow.dev/library/operators/round/), [ScaleLinExp](https://signalflow.dev/library/operators/scalelinexp/), [ScaleLinLin](https://signalflow.dev/library/operators/scalelinlin/), [Subtract](https://signalflow.dev/library/operators/subtract/), [Sum](https://signalflow.dev/library/operators/sum/), [TimeShift](https://signalflow.dev/library/operators/timeshift/), [Sin](https://signalflow.dev/library/operators/sin/), [Cos](https://signalflow.dev/library/operators/cos/), [Tan](https://signalflow.dev/library/operators/tan/), [Tanh](https://signalflow.dev/library/operators/tanh/) |
| **Oscillators** | [Constant](https://signalflow.dev/library/oscillators/constant/), [Impulse](https://signalflow.dev/library/oscillators/impulse/), [LFO](https://signalflow.dev/library/oscillators/lfo/), [SawLFO](https://signalflow.dev/library/oscillators/sawlfo/), [SawOscillator](https://signalflow.dev/library/oscillators/sawoscillator/), [SineLFO](https://signalflow.dev/library/oscillators/sinelfo/), [SineOscillator](https://signalflow.dev/library/oscillators/sineoscillator/), [SquareLFO](https://signalflow.dev/library/oscillators/squarelfo/), [SquareOscillator](https://signalflow.dev/library/oscillators/squareoscillator/), [TriangleLFO](https://signalflow.dev/library/oscillators/trianglelfo/), [TriangleOscillator](https://signalflow.dev/library/oscillators/triangleoscillator/), [Wavetable](https://signalflow.dev/library/oscillators/wavetable/), [Wavetable2D](https://signalflow.dev/library/oscillators/wavetable2d/) |
| **Processors** | [Clip](https://signalflow.dev/library/processors/clip/), [Fold](https://signalflow.dev/library/processors/fold/), [Smooth](https://signalflow.dev/library/processors/smooth/), [WetDry](https://signalflow.dev/library/processors/wetdry/), [Wrap](https://signalflow.dev/library/processors/wrap/) |
Expand Down
13 changes: 13 additions & 0 deletions docs/library/fft/fftlfo/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
title: FFTLFO node documentation
description: FFTLFO: FFT LFO. Requires an FFT* input.

[Reference library](../../index.md) > [FFT](../index.md) > [FFTLFO](index.md)

# FFTLFO

```python
FFTLFO(input=0, frequency=1.0, spectral_cycles=1.0)
```

FFT LFO. Requires an FFT* input.

1 change: 1 addition & 0 deletions docs/library/fft/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- **[FFTConvolve](fftconvolve/index.md)**: Frequency-domain convolution, using overlap-add. Useful for convolution reverb, with the input buffer containing an impulse response. Requires an FFT* input.
- **[FFTContrast](fftcontrast/index.md)**: FFT Contrast. Requires an FFT* input.
- **[FFTCrossFade](fftcrossfade/index.md)**: FFT FFTCrossFade. Requires two FFT* inputs.
- **[FFTLFO](fftlfo/index.md)**: FFT LFO. Requires an FFT* input.
- **[FFTMagnitudePhaseArray](fftmagnitudephasearray/index.md)**: Fixed mag/phase array.
- **[FFTRandomPhase](fftrandomphase/index.md)**: Randomise phase values.
- **[FFTScaleMagnitudes](fftscalemagnitudes/index.md)**: Randomise phase values.
Expand Down
1 change: 1 addition & 0 deletions docs/library/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
- **[FFTConvolve](fft/fftconvolve/index.md)**: Frequency-domain convolution, using overlap-add. Useful for convolution reverb, with the input buffer containing an impulse response. Requires an FFT* input.
- **[FFTContrast](fft/fftcontrast/index.md)**: FFT Contrast. Requires an FFT* input.
- **[FFTCrossFade](fft/fftcrossfade/index.md)**: FFT FFTCrossFade. Requires two FFT* inputs.
- **[FFTLFO](fft/fftlfo/index.md)**: FFT LFO. Requires an FFT* input.
- **[FFTMagnitudePhaseArray](fft/fftmagnitudephasearray/index.md)**: Fixed mag/phase array.
- **[FFTRandomPhase](fft/fftrandomphase/index.md)**: Randomise phase values.
- **[FFTScaleMagnitudes](fft/fftscalemagnitudes/index.md)**: Randomise phase values.
Expand Down
26 changes: 26 additions & 0 deletions source/include/signalflow/node/fft/fft-lfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include "signalflow/node/fft/fftnode.h"

namespace signalflow
{

/**--------------------------------------------------------------------------------*
* FFT LFO.
* Requires an FFT* input.
*---------------------------------------------------------------------------------*/
class FFTLFO : public FFTOpNode
{
public:
FFTLFO(NodeRef input = 0, NodeRef frequency = 1.0, NodeRef spectral_cycles = 1.0);
virtual void process(Buffer &out, int num_frames);

private:
NodeRef frequency;
NodeRef spectral_cycles;
double phase;
};

REGISTER(FFTLFO, "fft-lfo")

}
1 change: 1 addition & 0 deletions source/include/signalflow/signalflow.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@
#include <signalflow/node/fft/continuous-pv.h>
#include <signalflow/node/fft/fft-contrast.h>
#include <signalflow/node/fft/fft-cross-fade.h>
#include <signalflow/node/fft/fft-lfo.h>
#include <signalflow/node/fft/fft-magnitude-phase-array.h>
#include <signalflow/node/fft/fft-random-phase.h>
#include <signalflow/node/fft/fft-scale-magnitudes.h>
Expand Down
1 change: 1 addition & 0 deletions source/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ set(SRC ${SRC}
${CMAKE_CURRENT_SOURCE_DIR}/node/fft/fft-random-phase.cpp
${CMAKE_CURRENT_SOURCE_DIR}/node/fft/fft-scale-magnitudes.cpp
${CMAKE_CURRENT_SOURCE_DIR}/node/fft/fft-cross-fade.cpp
${CMAKE_CURRENT_SOURCE_DIR}/node/fft/fft-lfo.cpp
${CMAKE_CURRENT_SOURCE_DIR}/node/processors/delays/comb.cpp
${CMAKE_CURRENT_SOURCE_DIR}/node/processors/delays/allpass.cpp
${CMAKE_CURRENT_SOURCE_DIR}/node/processors/delays/onetap.cpp
Expand Down
49 changes: 49 additions & 0 deletions source/src/node/fft/fft-lfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "signalflow/core/graph.h"
#include "signalflow/node/fft/fft-lfo.h"

namespace signalflow
{

FFTLFO::FFTLFO(NodeRef input, NodeRef frequency, NodeRef spectral_cycles)
: FFTOpNode(input), frequency(frequency), spectral_cycles(spectral_cycles)
{
this->name = "fft-contrast";

this->create_input("frequency", this->frequency);
this->create_input("spectral_cycles", this->spectral_cycles);
this->phase = 0.0;
}

void FFTLFO::process(Buffer &out, int num_frames)
{
FFTNode *fftnode = (FFTNode *) this->input.get();
this->num_hops = fftnode->num_hops;
// TODO: Could this update per hop if I index based on hop?
float increment_per_bin = this->spectral_cycles->out[0][0] / (M_PI * 2);

for (int hop = 0; hop < this->num_hops; hop++)
{
float frequency = this->frequency->out[0][0];

for (int frame = 0; frame < this->fft_size; frame++)
{
if (frame < this->num_bins)
{
float phase_accum = phase + (increment_per_bin * frame / num_frames);
out[hop][frame] = input->out[hop][frame] * (sinf(M_PI * 2 * phase_accum) * 2 + 1.0);
}
else
{
out[hop][frame] = input->out[hop][frame];
}

phase += frequency / this->graph->get_sample_rate();
while (phase > 1.0)
{
phase -= 1.0;
}
}
}
}

}
3 changes: 3 additions & 0 deletions source/src/python/nodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ void init_python_nodes(py::module &m)
py::class_<FFTCrossFade, FFTOpNode, NodeRefTemplate<FFTCrossFade>>(m, "FFTCrossFade", "FFT FFTCrossFade. Requires two FFT* inputs.")
.def(py::init<NodeRef, NodeRef, NodeRef>(), "inputA"_a = 0, "inputB"_a = 0, "crossfade"_a = 0.0);

py::class_<FFTLFO, FFTOpNode, NodeRefTemplate<FFTLFO>>(m, "FFTLFO", "FFT LFO. Requires an FFT* input.")
.def(py::init<NodeRef, NodeRef, NodeRef>(), "input"_a = 0, "frequency"_a = 1.0, "spectral_cycles"_a = 1.0);

py::class_<FFTMagnitudePhaseArray, FFTOpNode, NodeRefTemplate<FFTMagnitudePhaseArray>>(m, "FFTMagnitudePhaseArray", "Fixed mag/phase array.")
.def(py::init<NodeRef, std::vector<float>, std::vector<float>>(), "input"_a = 0, "magnitudes"_a = 0, "phases"_a = 0)
.def("set_magnitudes", &FFTMagnitudePhaseArray::set_magnitudes);
Expand Down

0 comments on commit f4d410a

Please sign in to comment.