Deluge Firmware 1.3.0
Build date: 2025.09.14
Loading...
Searching...
No Matches
GranularProcessor.h
1/*
2 * Copyright © 2024 Mark Adams and Alter-Alter
3 *
4 * This file is part of The Synthstrom Audible Deluge Firmware.
5 *
6 * The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software Foundation,
8 * either version 3 of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with this program.
15 * If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19
20#include "GranularProcessor.h"
21#include "OSLikeStuff/scheduler_api.h"
22#include "definitions_cxx.hpp"
23#include "dsp/filter/ladder_components.h"
24#include "dsp_ng/core/types.hpp"
25#include "memory/stealable.h"
26#include "modulation/lfo.h"
27#include <span>
28
30
31namespace deluge::dsp {
32
33struct Grain {
34 int32_t length = 0; // in samples 0=OFF
35 int32_t startPoint; // starttimepos in samples
36 int32_t counter; // relative pos in samples
37 uint16_t pitch; // 1024=1.0
38 int32_t volScale;
39 int32_t volScaleMax;
40 bool rev; // 0=normal, 1 =reverse
41 int32_t panVolL; // 0 - 1073741823
42 int32_t panVolR; // 0 - 1073741823
43};
44class GrainBuffer;
45
48class GranularProcessor {
49public:
50 GranularProcessor() { getBuffer(); }
51 GranularProcessor(const GranularProcessor& other); // copy constructor
52 ~GranularProcessor();
53 [[nodiscard]] int32_t getSamplesToShutdown() const { return wrapsToShutdown * kModFXGrainBufferSize; }
54
57
59 void processGrainFX(StereoBuffer<q31_t> buffer, int32_t grainRate, int32_t grainMix, int32_t grainDensity,
60 int32_t pitchRandomness, int32_t* postFXVolume, bool anySoundComingIn, float tempoBPM,
61 q31_t reverbAmount);
62
63 void clearGrainFXBuffer();
64 void grainBufferStolen() { grainBuffer = nullptr; }
65
66private:
67 void setupGrainFX(int32_t grainRate, int32_t grainMix, int32_t grainDensity, int32_t pitchRandomness,
68 int32_t* postFXVolume, float timePerInternalTick);
69 StereoSample<q31_t> processOneGrainSample(StereoSample<q31_t> currentSample);
70 void getBuffer();
71 void setWrapsToShutdown();
72 void setupGrainsIfNeeded(int32_t writeIndex);
73 // parameters
74 uint32_t bufferWriteIndex = 0;
75 int32_t _grainSize = 13230; // 300ms
76 int32_t _grainRate = 1260; // 35hz
77 int32_t _grainShift = 13230; // 300ms
78 int32_t _grainFeedbackVol = 161061273; // Q30: 0.15
79 int32_t _grainVol = 0; // Q31: 0
80 int32_t _grainDryVol = std::numeric_limits<int32_t>::max(); // Q31: 1
81 int32_t _pitchRandomness = 0;
82
83 bool grainLastTickCountIsZero = true;
84 bool grainInitialized = false;
85
86 std::array<Grain, 8> grains = {0};
87
88 int32_t wrapsToShutdown = 0;
89 GrainBuffer* grainBuffer = nullptr;
90 int32_t _densityKnobPos = 0;
91 int32_t _rateKnobPos = 0;
92 int32_t _mixKnobPos = 0; // Q31
95 bool tempoSync = true;
96 bool bufferFull = false;
97};
98
99class GrainBuffer : public Stealable {
100public:
101 GrainBuffer() = delete;
102 GrainBuffer(GrainBuffer& other) = delete;
103 GrainBuffer(const GrainBuffer& other) = delete;
104 explicit GrainBuffer(GranularProcessor* grainFX) : owner(grainFX) {}
105 bool mayBeStolen(void* thingNotToStealFrom) override {
106 if (thingNotToStealFrom != this) {
107 return !inUse;
108 }
109 return false;
110 };
111 void steal(char const* errorCode) override { owner->grainBufferStolen(); };
112
113 // gives it a high priority - these are huge so reallocating them can be slow
114 [[nodiscard]] StealableQueue getAppropriateQueue() const override {
115 return StealableQueue::CURRENT_SONG_SAMPLE_DATA_REPITCHED_CACHE;
116 };
117 StereoSample<q31_t>& operator[](int32_t i) { return sampleBuffer[i]; }
118 StereoSample<q31_t> operator[](int32_t i) const { return sampleBuffer[i]; }
119 bool inUse = true;
120
121private:
122 GranularProcessor* owner;
123 std::array<StereoSample<q31_t>, kModFXGrainBufferSize * sizeof(StereoSample<q31_t>)> sampleBuffer;
124};
125} // namespace deluge::dsp
Definition param_set.h:98
Definition GranularProcessor.h:99
Definition GranularProcessor.h:48
void startSkippingRendering()
allows the buffer to be stolen
Definition GranularProcessor.cpp:319
void processGrainFX(StereoBuffer< q31_t > buffer, int32_t grainRate, int32_t grainMix, int32_t grainDensity, int32_t pitchRandomness, int32_t *postFXVolume, bool anySoundComingIn, float tempoBPM, q31_t reverbAmount)
preset is currently converted from a param to a 0-4 preset inside the grain, which is probably not gr...
Definition GranularProcessor.cpp:50
Definition ladder_components.h:23
Definition GranularProcessor.h:33