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 }