Deluge Firmware 1.3.0
Build date: 2025.06.05
Loading...
Searching...
No Matches
sample.h
1/*
2 * Copyright © 2014-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_cluster.h"
22#include "storage/audio/audio_file.h"
23#include "util/container/array/ordered_resizeable_array.h"
24#include "util/container/array/ordered_resizeable_array_with_multi_word_key.h"
25#include "util/fixedpoint.h"
26#include "util/functions.h"
27#include <bit>
28#include <cstdint>
29
30#define SAMPLE_DO_LOCKS (ALPHA_OR_BETA_VERSION)
31
32enum class RawDataFormat : uint8_t {
33 NATIVE = 0,
34 FLOAT = 1,
35 UNSIGNED_8 = 2,
36 ENDIANNESS_WRONG_16 = 3,
37 ENDIANNESS_WRONG_24 = 4,
38 ENDIANNESS_WRONG_32 = 5,
39};
40
41const float MIDI_NOTE_UNSET = (-999);
42const float MIDI_NOTE_ERROR = (-1000);
43class LoadedSamplePosReason;
44class SampleCache;
46class TimeStretcher;
47class SampleHolder;
48
49class Sample final : public AudioFile {
50public:
51 Sample();
52 ~Sample() override;
53
54 void workOutBitMask();
55 Error initialize(int32_t numClusters);
56 void markAsUnloadable();
57 float determinePitch(bool doingSingleCycle, float minFreqHz, float maxFreqHz, bool doPrimeTest);
58 void workOutMIDINote(bool doingSingleCycle, float minFreqHz = 20, float maxFreqHz = 10000, bool doPrimeTest = true);
59 uint32_t getLengthInMSec();
60 SampleCache* getOrCreateCache(SampleHolder* sampleHolder, int32_t phaseIncrement, int32_t timeStretchRatio,
61 bool reversed, bool mayCreate, bool* created);
62 void deleteCache(SampleCache* cache);
63 int32_t getFirstClusterIndexWithAudioData();
64 int32_t getFirstClusterIndexWithNoAudioData();
65 Error fillPercCache(TimeStretcher* timeStretcher, int32_t startPosSamples, int32_t endPosSamples,
66 int32_t playDirection, int32_t maxNumSamplesToProcess);
67 void percCacheClusterStolen(Cluster* cluster);
68 void deletePercCache(bool beingDestructed = false);
69 uint8_t* prepareToReadPercCache(int32_t pixellatedPos, int32_t playDirection, int32_t* earliestPixellatedPos,
70 int32_t* latestPixellatedPos);
71 bool getAveragesForCrossfade(int32_t* totals, int32_t startBytePos, int32_t crossfadeLengthSamples,
72 int32_t playDirection, int32_t lengthToAverageEach);
73 void convertDataOnAnyClustersIfNecessary();
74 int32_t getMaxPeakFromZero();
75 int32_t getFoundValueCentrePoint();
76 int32_t getValueSpan();
77 void finalizeAfterLoad(uint32_t fileSize) override;
78
79 // Floating point
80 [[nodiscard]] q31_t convertToNative(float value) const { return q31_from_float(value); }
81
82 [[nodiscard]] q31_t convertToNative(int32_t value) const {
83 switch (rawDataFormat) {
84 case RawDataFormat::FLOAT:
85 return q31_from_float(std::bit_cast<float>(value));
86
87 case RawDataFormat::ENDIANNESS_WRONG_32: // Or endianness swap
88 return swapEndianness32(value);
89
90 case RawDataFormat::ENDIANNESS_WRONG_16:
91 return swapEndianness2x16(value);
92
93 case RawDataFormat::UNSIGNED_8:
94 return value ^ 0x80808080;
95
96 case RawDataFormat::ENDIANNESS_WRONG_24:
97 // handled by caller
98 [[fallthrough]];
99
100 case RawDataFormat::NATIVE:
101 // nothing to be done
102 break;
103 }
104 return value;
105 }
106
107 String tempFilePathForRecording;
108 uint8_t byteDepth{0};
109 uint32_t sampleRate{44100};
110 uint32_t audioDataStartPosBytes; // That is, the offset from the start of the WAV file
111 uint64_t audioDataLengthBytes;
112 uint32_t bitMask{0};
113 bool audioStartDetected;
114
115 uint64_t lengthInSamples;
116
117 // These two are for holding a value loaded from file
118 uint32_t fileLoopStartSamples; // And during recording, this one also stores the final value once known
119 uint32_t fileLoopEndSamples;
120
121 float midiNoteFromFile; // -1 means none
122
123 RawDataFormat rawDataFormat;
124
125 bool unloadable{false}; // Only gets set to true if user has re-inserted the card and the sample appears to have
126 // been deleted / moved / modified
127 bool unplayable{false};
128 bool partOfFolderBeingLoaded;
129 bool fileExplicitlySpecifiesSelfAsWaveTable{false};
130
131#if SAMPLE_DO_LOCKS
132 bool lock;
133#endif
134
135 float midiNote; // -999 means not worked out yet. -1000 means error working out
136
137 // int32_t valueSpan; // -2147483648 means both these are uninitialized
138 int32_t minValueFound;
139 int32_t maxValueFound;
140
142
143 uint8_t* percCacheMemory[2]{nullptr, nullptr}; // One for each play-direction: 0=forwards; 1=reversed
144 OrderedResizeableArrayWith32bitKey percCacheZones[2]; // One for each play-direction: 0=forwards; 1=reversed
145
146 Cluster** percCacheClusters[2]{nullptr, nullptr}; // One for each play-direction: 0=forwards; 1=reversed
147 int32_t numPercCacheClusters{};
148
149 int32_t beginningOffsetForPitchDetection;
150 bool beginningOffsetForPitchDetectionFound;
151
152 uint32_t waveTableCycleSize{0}; // In case this later gets used for a WaveTable
153
154 std::vector<SampleCluster> clusters;
155
156 // Stealable Implementation
157 bool mayBeStolen(void* thingNotToStealFrom = nullptr) override;
158 void steal(char const* errorCode) override;
159
160protected:
161#if ALPHA_OR_BETA_VERSION
162 void numReasonsDecreasedToZero(char const* errorCode) override;
163#endif
164
165private:
166 int32_t investigateFundamentalPitch(int32_t fundamentalIndexProvided, int32_t tableSize, int32_t* heightTable,
167 uint64_t* sumTable, float* floatIndexTable, float* getFreq,
168 int32_t numDoublings, bool doPrimeTest);
169};
Definition cluster.h:34
Definition multisample_range.h:27
Definition ordered_resizeable_array.h:72
Definition ordered_resizeable_array_with_multi_word_key.h:25
Definition sample_cache.h:25
Definition sample_holder.h:32
Definition d_string.h:41
Definition time_stretcher.h:37