zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

Reverter.h (6738B)


      1 /*
      2   ZynAddSubFX - a software synthesizer
      3 
      4   Reverter.h - Reverse Delay
      5   Copyright (C) 2023-2024 Michael Kirchner
      6   Author: Michael Kirchner
      7 
      8   This program is free software; you can redistribute it and/or
      9   modify it under the terms of the GNU General Public License
     10   as published by the Free Software Foundation; either version 2
     11   of the License, or (at your option) any later version.
     12 */
     13 
     14 #pragma once
     15 #include "../globals.h"
     16 
     17 namespace zyn {
     18 
     19 #define SYNCMODES   NOTEON,\
     20                     NOTEONOFF,\
     21                     AUTO,\
     22                     HOST
     23 
     24 // State Machine for the modes NOTEON and NOTEONOFF
     25 // Sync-Event leads to a cycle of RECORDING->PLAYING->IDLE
     26 //
     27 // RECORDING - not playing but counting the recording duration
     28 // PLAYING - playing for delay duration (NOTEON) or for the recorded duration (NOTEONOFF)
     29 // IDLE - not playing
     30 
     31 #define STATES  RECORDING,\
     32                 PLAYING,\
     33                 IDLE
     34 
     35 /**
     36  * @brief Reverse Delay effect class
     37  *
     38  * Implements a reverse delay effect using a ring buffer. Supports synchronization
     39  * with host, MIDI, or note-on/off events.
     40  */
     41 class Reverter
     42 {
     43 public:
     44     enum SyncMode
     45     {
     46         SYNCMODES
     47     };
     48 
     49     enum State
     50     {
     51         STATES
     52     };
     53 
     54     /**
     55      * @brief Constructor for the Reverter class.
     56      *
     57      * @param alloc Allocator for memory management.
     58      * @param delay Initial delay time in seconds.
     59      * @param srate Sample rate in Hz.
     60      * @param bufsize Size of the audio buffer.
     61      * @param tRef Optional time reference (default is 0.0f).
     62      * @param time_ Optional pointer to an AbsTime object for timing.
     63      */
     64     Reverter(Allocator *alloc, float delay, unsigned int srate, int bufsize, float tRef = 0.0f, const AbsTime *time_ = nullptr);
     65 
     66     /// Destructor
     67     ~Reverter();
     68 
     69     /**
     70      * @brief Process and filter the input audio samples.
     71      *
     72      * @param smp Pointer to the buffer of input samples.
     73      */
     74     void filterout(float *smp);
     75 
     76     /**
     77      * @brief Set the delay time in seconds.
     78      *
     79      * @param value Delay time.
     80      */
     81     void setdelay(float value);
     82 
     83     /**
     84      * @brief Set the phase of the delay.
     85      *
     86      * @param value Phase value.
     87      */
     88     void setphase(float value);
     89 
     90     /**
     91      * @brief Set the crossfade time for the transition between buffers.
     92      *
     93      * @param value Crossfade time.
     94      */
     95     void setcrossfade(float value);
     96 
     97     /**
     98      * @brief Set the output gain.
     99      *
    100      * @param value Gain value in dB.
    101      */
    102     void setgain(float value);
    103 
    104     /**
    105      * @brief Set the synchronization mode for the reverter.
    106      *
    107      * @param value Synchronization mode (e.g., AUTO, MIDI, HOST).
    108      */
    109     void setsyncMode(SyncMode value);
    110 
    111     /// Reset the internal state and buffer.
    112     void reset();
    113 
    114     /**
    115      * @brief Synchronize the delay based on an external position.
    116      *
    117      * @param pos External position for syncing.
    118      */
    119     void sync(float pos);
    120 
    121 private:
    122     /**
    123      * @brief Switch between buffers when reverse playback is triggered.
    124      *
    125      * @param offset Offset for buffer switching.
    126      */
    127     void switchBuffers();
    128 
    129     /**
    130      * @brief Perform linear interpolation between two samples.
    131      *
    132      * @param smp Pointer to the sample buffer.
    133      * @param pos Position to interpolate.
    134      * @return Interpolated sample value.
    135      */
    136     float sampleLerp(const float *smp, const float pos);
    137 
    138     /**
    139      * @brief Write new input samples to the ring buffer.
    140      *
    141      * @param smp Pointer to the buffer of input samples.
    142      */
    143     void writeToRingBuffer(const float *smp);
    144 
    145     /**
    146      * @brief Process the samples and apply the reverse delay effect.
    147      *
    148      * @param smp Pointer to the buffer of input samples.
    149      */
    150     void processBuffer(float *smp);
    151 
    152     /**
    153      * @brief Handle synchronization modes and state transitions.
    154      *
    155      */
    156     void checkSync();
    157 
    158     /**
    159      * @brief Handles state transitions in NOTEON and NOTEONOFF modes.
    160      */
    161     void handleStateChange();
    162 
    163     /**
    164      * @brief Update the read position in the ring buffer.
    165      */
    166     void updateReaderPosition();
    167 
    168     /**
    169      * @brief Apply crossfading between two buffer segments.
    170      *
    171      * @param smp Pointer to the buffer of input samples.
    172      * @param i Index of the current sample in the buffer.
    173      */
    174     void crossfadeSamples(float *smp, int i);
    175 
    176     /**
    177      * @brief Apply fading for transitions between buffer segments.
    178      *
    179      * @param fadein Fade-in factor.
    180      * @param fadeout Fade-out factor.
    181      * @return Crossfaded sample value.
    182      */
    183     float applyFade(float fadein, float fadeout);
    184 
    185     /**
    186      * @brief Apply the output gain to a sample.
    187      *
    188      * @param sample Reference to the sample to modify.
    189      */
    190     void applyGain(float &sample);
    191 
    192     void update_memsize();
    193 
    194     /// Current synchronization mode
    195     SyncMode syncMode;
    196 
    197     /// Current state of the reverter (RECORDING, PLAYING, IDLE)
    198     State state;
    199 
    200     /// Ring buffer for input samples
    201     float* input;
    202 
    203     /// Output gain value
    204     float gain;
    205 
    206     /// Delay time in samples
    207     float delay;
    208 
    209     /// Phase value
    210     float phase;
    211 
    212     /// Crossfade duration in samples
    213     float crossfade;
    214 
    215     /// Time reference for syncing
    216     float tRef;
    217 
    218     /// Offset for global time synchronization
    219     float global_offset;
    220 
    221     /// Index for reverse playback
    222     int reverse_index;
    223 
    224     /// Phase offset for delay transitions
    225     float phase_offset_old;
    226     float phase_offset_fade;
    227 
    228     /// Number of samples for crossfading
    229     int fading_samples;
    230 
    231     /// Counter for crossfade processing
    232     int fade_counter;
    233 
    234     /// Root mean square (RMS) history for input volume analysis
    235     float mean_abs_value;
    236 
    237     /// Pointer to timing object for synchronization
    238     const AbsTime *time;
    239 
    240     /// Memory allocator
    241     Allocator &memory;
    242 
    243     /// Total size of the memory buffer in samples
    244     unsigned int mem_size;
    245 
    246     /// Sample rate of the audio engine
    247     const int samplerate;
    248 
    249     /// Size of the audio buffer in samples
    250     const int buffersize;
    251 
    252     /// Maximum allowable delay in samples
    253     const float max_delay_samples;
    254 
    255     /// Start position for the read head in the ring buffer
    256     unsigned int pos_start;
    257 
    258     /// Offset for phase correction
    259     float phase_offset;
    260 
    261     /// Number of samples recorded for playback
    262     int recorded_samples;
    263 
    264     /// Position to synchronize playback
    265     float syncPos;
    266 
    267     /// Current position of the read head in the ring buffer
    268     float pos_reader;
    269 
    270     /// Delta between crossfaded buffer positions
    271     float delta_crossfade;
    272 
    273     /// Flag indicating whether synchronization is active
    274     bool doSync;
    275 
    276     /// Write head position in the ring buffer
    277     unsigned int pos_writer;
    278 };
    279 
    280 }