Deluge Firmware 1.3.0
Build date: 2025.04.16
Loading...
Searching...
No Matches
voice_sample.h
1/*
2 * Copyright © 2015-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
23enum class LateStartAttemptStatus {
24 SUCCESS = 0,
25 FAILURE = 1,
26 WAIT = 2,
27};
28class TimeStretcher;
29class SampleCache;
30class Sample;
31class Voice;
33class Source;
34class SampleControls;
35
36class VoiceSample final : public SampleLowLevelReader {
37public:
38 VoiceSample() = default;
39 explicit VoiceSample(VoiceSample& other) = default;
40 VoiceSample(SampleLowLevelReader&& other) : SampleLowLevelReader{std::move(other)} {}
41 ~VoiceSample() override { endTimeStretching(); }
42 VoiceSample& operator=(const VoiceSample& other) = delete;
43 VoiceSample& operator=(VoiceSample&& other) = default;
44
45 void noteOn(SamplePlaybackGuide* guide, uint32_t samplesLate, int32_t priorityRating);
46 bool noteOffWhenLoopEndPointExists(Voice* voice, VoiceSamplePlaybackGuide* voiceSource);
47
48 void setupCacheLoopPoints(SamplePlaybackGuide* voiceSource, Sample* sample, LoopType loopingType);
49 LateStartAttemptStatus attemptLateSampleStart(SamplePlaybackGuide* voiceSource, Sample* sample,
50 int64_t rawSamplesLate, int32_t numSamples = 0);
51 void endTimeStretching();
52 bool render(SamplePlaybackGuide* guide, int32_t* oscBuffer, int32_t numSamples, Sample* sample, int32_t numChannels,
53 LoopType loopingType, int32_t phaseIncrement, int32_t timeStretchRatio, int32_t amplitude,
54 int32_t amplitudeIncrement, int32_t bufferSize, InterpolationMode desiredInterpolationMode,
55 int32_t priorityRating);
56 void beenUnassigned(bool wontBeUsedAgain);
57
58 // AudioClips don't obey markers because they "fudge" instead.
59 // Or if fudging can't happen cos no pre-margin, then
60 // AudioClip::doTickForward() manually forces restart.
61 [[nodiscard]] bool shouldObeyMarkers() const override {
62 return (cache == nullptr && timeStretcher == nullptr && !forAudioClip);
63 }
64
65 void readSamplesResampledPossiblyCaching(int32_t** oscBufferPos, int32_t** oscBufferRPos, int32_t numSamples,
66 Sample* sample, int32_t jumpAmount, int32_t numChannels,
67 int32_t numChannelsAfterCondensing, int32_t phaseIncrement,
68 int32_t* sourceAmplitudeNow, int32_t amplitudeIncrement,
69 int32_t bufferSize, int32_t reduceMagnitudeBy = 1);
70
71 bool sampleZoneChanged(SamplePlaybackGuide* voiceSource, Sample* sample, bool reversed, MarkerType markerType,
72 LoopType loopingType, int32_t priorityRating, bool forAudioClip = false);
73 int32_t getPlaySample(Sample* sample, SamplePlaybackGuide* guide);
74 bool stopUsingCache(SamplePlaybackGuide* guide, Sample* sample, int32_t priorityRating, bool loopingAtLowLevel);
75 bool possiblySetUpCache(SampleControls* sampleControls, SamplePlaybackGuide* guide, int32_t phaseIncrement,
76 int32_t timeStretchRatio, int32_t priorityRating, LoopType loopingType);
77 bool fudgeTimeStretchingToAvoidClick(Sample* sample, SamplePlaybackGuide* guide, int32_t phaseIncrement,
78 int32_t numSamplesTilLoop, int32_t playDirection, int32_t priorityRating);
79
80 uint32_t pendingSamplesLate = 0; // This isn't used for AudioClips. And for samples in STRETCH mode, the exact
81 // number isn't relevant - it gets recalculated
82 TimeStretcher* timeStretcher = nullptr;
83
84 SampleCache* cache = nullptr;
85 bool doneFirstRenderYet = false;
86 bool fudging = false;
87 bool forAudioClip = false; // This is a wee bit of a hack - but we need to be able to know this
88 bool writingToCache = false; // Value is only valid if cache assigned
89
90private:
91 bool weShouldBeTimeStretchingNow(Sample* sample, SamplePlaybackGuide* guide, int32_t numSamples,
92 int32_t phaseIncrement, int32_t timeStretchRatio, int32_t playDirection,
93 int32_t priorityRating, LoopType loopingType);
94 void switchToReadingCacheFromWriting();
95 bool stopReadingFromCache();
96
97 int32_t cacheBytePos = 0;
98 uint32_t cacheLoopLengthBytes = 0;
99 int32_t cacheLoopEndPointBytes = 0; // 2147483647 means no looping. Will be set to sample end-point if looping
100 // there. Gets re-set to 2147483647 when note "released"
101 int32_t cacheEndPointBytes = 0; // Will sometimes be the whole length of the sample. Wherever the red marker is. Or
102 // a little further if it's the full length of the sample, to allow for timestretch
103 // / interpolation ring-out
104};
Definition sample_cache.h:25
Definition sample_controls.h:22
Definition sample_playback_guide.h:28
Definition sample.h:50
Definition source.h:31
Definition time_stretcher.h:37
Definition voice_sample_playback_guide.h:28
Definition voice.h:35