Skip to content

Commit

Permalink
Add FFTCrossFade node
Browse files Browse the repository at this point in the history
  • Loading branch information
ideoforms committed Jul 4, 2024
1 parent dbc2c00 commit 7e757f2
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 1 deletion.
13 changes: 13 additions & 0 deletions docs/library/fft/fftcrossfade/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
title: FFTCrossFade node documentation
description: FFTCrossFade: FFT FFTCrossFade. Requires two FFT* inputs.

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

# FFTCrossFade

```python
FFTCrossFade(inputA=0, inputB=0, crossfade=0.0)
```

FFT FFTCrossFade. Requires two FFT* inputs.

1 change: 1 addition & 0 deletions docs/library/fft/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- **[FFTContinuousPhaseVocoder](fftcontinuousphasevocoder/index.md)**: Continuous phase vocoder. Requires an FFT* input.
- **[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.
- **[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 @@ -55,6 +55,7 @@
- **[FFTContinuousPhaseVocoder](fft/fftcontinuousphasevocoder/index.md)**: Continuous phase vocoder. Requires an FFT* input.
- **[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.
- **[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
25 changes: 25 additions & 0 deletions source/include/signalflow/node/fft/fft-cross-fade.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

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

namespace signalflow
{

/**--------------------------------------------------------------------------------*
* FFT FFTCrossFade.
* Requires two FFT* inputs.
*---------------------------------------------------------------------------------*/
class FFTCrossFade : public FFTOpNode
{
public:
FFTCrossFade(NodeRef inputA = 0, NodeRef inputB = 0, NodeRef crossfade = 0.0);
virtual void process(Buffer &out, int num_frames);

private:
NodeRef inputB;
NodeRef crossfade;
};

REGISTER(FFTCrossFade, "fft-cross-fade")

}
1 change: 1 addition & 0 deletions source/include/signalflow/signalflow.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,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-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 @@ -46,6 +46,7 @@ set(SRC ${SRC}
${CMAKE_CURRENT_SOURCE_DIR}/node/fft/fft-magnitude-phase-array.cpp
${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/processors/delays/comb.cpp
${CMAKE_CURRENT_SOURCE_DIR}/node/processors/delays/allpass.cpp
${CMAKE_CURRENT_SOURCE_DIR}/node/processors/delays/onetap.cpp
Expand Down
39 changes: 39 additions & 0 deletions source/src/node/fft/fft-cross-fade.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "signalflow/node/fft/fft-cross-fade.h"
#include <algorithm>

namespace signalflow
{

FFTCrossFade::FFTCrossFade(NodeRef inputA, NodeRef inputB, NodeRef crossfade)
: FFTOpNode(inputA), inputB(inputB), crossfade(crossfade)
{
this->name = "fft-contrast";

this->create_input("inputB", this->inputB);
this->create_input("crossfade", this->crossfade);
}

void FFTCrossFade::process(Buffer &out, int num_frames)
{
FFTNode *fftnode = (FFTNode *) this->input.get();
this->num_hops = fftnode->num_hops;

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

for (int frame = 0; frame < this->fft_size; frame++)
{
if (frame < this->num_bins)
{
out[hop][frame] = (input->out[hop][frame] * (1 - crossfade)) + (inputB->out[hop][frame] * (crossfade));
}
else
{
out[hop][frame] = (input->out[hop][frame] * (1 - crossfade)) + (inputB->out[hop][frame] * (crossfade));
}
}
}
}

}
5 changes: 4 additions & 1 deletion source/src/python/nodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void init_python_nodes(py::module &m)
py::class_<BufferLooper, Node, NodeRefTemplate<BufferLooper>>(m, "BufferLooper", "Read and write from a buffer concurrently, with controllable overdub.")
.def(py::init<BufferRef, NodeRef, NodeRef, bool, bool>(), "buffer"_a = nullptr, "input"_a = 0.0, "feedback"_a = 0.0, "loop_playback"_a = false, "loop_record"_a = false);

py::class_<BufferPlayer, Node, NodeRefTemplate<BufferPlayer>>(m, "BufferPlayer", "Plays the contents of the given buffer. start_time/end_time are in seconds. When a clock signal is received, rewinds to the start_time.")
py::class_<BufferPlayer, Node, NodeRefTemplate<BufferPlayer>>(m, "BufferPlayer", "Plays the contents of the given buffer. `start_time`/`end_time` are in seconds. When a `clock` signal is received, rewinds to the `start_time`. Set `clock` to `0` to prevent the buffer from being triggered immediately.")
.def(py::init<BufferRef, NodeRef, NodeRef, NodeRef, NodeRef, NodeRef>(), "buffer"_a = nullptr, "rate"_a = 1.0, "loop"_a = 0, "start_time"_a = nullptr, "end_time"_a = nullptr, "clock"_a = nullptr);

py::class_<BufferRecorder, Node, NodeRefTemplate<BufferRecorder>>(m, "BufferRecorder", "Records the input to a buffer. feedback controls overdub.")
Expand Down Expand Up @@ -112,6 +112,9 @@ void init_python_nodes(py::module &m)
py::class_<FFTContrast, FFTOpNode, NodeRefTemplate<FFTContrast>>(m, "FFTContrast", "FFT Contrast. Requires an FFT* input.")
.def(py::init<NodeRef, NodeRef>(), "input"_a = 0, "contrast"_a = 1);

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_<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 7e757f2

Please sign in to comment.