Deluge Firmware 1.3.0
Build date: 2025.04.16
Loading...
Searching...
No Matches
time_stretcher.h
1/*
2 * Copyright © 2016-2023 Synthstrom Audible Limited
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 "definitions_cxx.hpp"
21#include "model/sample/sample_low_level_reader.h"
22#include <cstdint>
23
24#define BUFFER_FILLING_OFF 0
25#define BUFFER_FILLING_NEWER 1
26#define BUFFER_FILLING_OLDER 2
27#define BUFFER_FILLING_NEITHER 3
28
29class VoiceSample;
30class Voice;
33class Cluster;
34class Sample;
35class SampleCache;
36
37class [[gnu::hot]] TimeStretcher {
38public:
39 TimeStretcher() = default;
40 bool init(Sample* sample, VoiceSample* voiceSample, SamplePlaybackGuide* guide, int64_t newSamplePosBig,
41 int32_t numChannels, int32_t phaseIncrement, int32_t timeStretchRatio, int32_t playDirection,
42 int32_t priorityRating, int32_t fudgingNumSamplesTilLoop, LoopType loopingType);
43 void reInit(int64_t newSamplePosBig, SamplePlaybackGuide* guide, VoiceSample* voiceSample, Sample* sample,
44 int32_t numChannels, int32_t timeStretchRatio, int32_t phaseIncrement, uint64_t combinedIncrement,
45 int32_t playDirection, LoopType loopingType, int32_t priorityRating);
46 void beenUnassigned();
47 void unassignAllReasonsForPercLookahead();
48 void unassignAllReasonsForPercCacheClusters();
49 bool hopEnd(SamplePlaybackGuide* guide, VoiceSample* voiceSample, Sample* sample, int32_t numChannels,
50 int32_t timeStretchRatio, int32_t phaseIncrement, uint64_t combinedIncrement, int32_t playDirection,
51 LoopType loopingType, int32_t priorityRating);
52
53 void rememberPercCacheCluster(Cluster* cluster);
54 void updateClustersForPercLookahead(Sample* sample, uint32_t sourceBytePos, int32_t playDirection);
55
56 int32_t getSamplePos(int32_t playDirection);
57 bool allocateBuffer(int32_t numChannels);
58
59 void readFromBuffer(int32_t* oscBufferPos, int32_t numSamples, int32_t numChannels,
60 int32_t numChannelsAfterCondensing, int32_t sourceAmplitudeNow, int32_t amplitudeIncrementNow,
61 int32_t* bufferReadPos);
62
63 void setupCrossfadeFromCache(SampleCache* cache, int32_t cacheBytePos, int32_t numChannels);
64
65#if TIME_STRETCH_ENABLE_BUFFER
66 void reassessWhetherToBeFillingBuffer(int32_t phaseIncrement, int32_t timeStretchRatio,
67 int32_t newBufferFillingMode, int32_t numChannels);
68#endif
69
70 int64_t samplePosBig; // In whole samples including both channels. From audioDataStart. <<'d by 24
71
72 uint32_t crossfadeProgress; // Out of kMaxSampleValue
73 uint32_t crossfadeIncrement;
74
75 int32_t samplesTilHopEnd;
76
77 SampleLowLevelReader olderPartReader;
78
79 int32_t* buffer;
80 bool olderHeadReadingFromBuffer;
81 bool hasLoopedBackIntoPreMargin;
82 bool playHeadStillActive[2];
83 uint8_t numTimesMissedHop;
84
85 int32_t olderBufferReadPos; // In whole samples including both channels
86
87#if TIME_STRETCH_ENABLE_BUFFER
88 bool newerHeadReadingFromBuffer;
89 int32_t newerBufferReadPos; // In whole samples including both channels
90
91 uint8_t bufferFillingMode;
92 int32_t bufferWritePos; // In whole samples including both channels
93 uint64_t bufferSamplesWritten; // Hopefully we can do away with the need for this
94#endif
95
96 Cluster* clustersForPercLookahead[kNumClustersLoadedAhead];
97
98 Cluster* percCacheClustersNearby[2]; // Remembers and acts as a "reason" for the two most recently needed / accessed
99 // Clusters, basically
100
101private:
102 bool setupNewPlayHead(Sample* sample, VoiceSample* voiceSample, SamplePlaybackGuide* guide, int32_t newHeadBytePos,
103 int32_t additionalOscPos, int32_t priorityRating, LoopType loopingType);
104};
105
106inline int32_t getTotalDifferenceAbs(int32_t* totals1, int32_t* totals2) {
107 int32_t totalDifferenceAbs = 0;
108 for (int32_t i = 0; i < TimeStretch::Crossfade::kNumMovingAverages; i++) {
109 int32_t differenceAbsHere = totals2[i] - totals1[i];
110 if (differenceAbsHere < 0)
111 differenceAbsHere = -differenceAbsHere;
112 totalDifferenceAbs += differenceAbsHere;
113 }
114 return totalDifferenceAbs;
115}
116
117inline int32_t getTotalChange(int32_t* totals1, int32_t* totals2) {
118 int32_t totalChange = 0;
119 for (int32_t i = 0; i < TimeStretch::Crossfade::kNumMovingAverages; i++) {
120 totalChange += totals2[i];
121 }
122
123 for (int32_t i = 0; i < TimeStretch::Crossfade::kNumMovingAverages; i++) {
124 totalChange -= totals1[i];
125 }
126 return totalChange;
127}
Definition cluster.h:34
Definition sample_cache.h:25
Definition sample_low_level_reader.h:36
Definition sample_playback_guide.h:28
Definition sample.h:50
bool setupNewPlayHead(Sample *sample, VoiceSample *voiceSample, SamplePlaybackGuide *guide, int32_t newHeadBytePos, int32_t additionalOscPos, int32_t priorityRating, LoopType loopingType)
Definition time_stretcher.cpp:980
Definition voice_sample_playback_guide.h:28
Definition voice_sample.h:36
Definition voice_unison_part_source.h:31
Definition voice.h:35