Deluge Firmware 1.3.0
Build date: 2025.08.14
Loading...
Searching...
No Matches
functions.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 "const_functions.h"
21#include "definitions_cxx.hpp"
22#include "fatfs/ff.h"
23#include "gui/colour/colour.h" // IWYU pragma: export todo: this probably shouldn't be exported from here
24#include "util/cfunctions.h" // IWYU pragma: export - minimal set of functions which need c linkage
25#include "util/d_string.h"
26#include "util/fixedpoint.h"
27#include "util/lookuptables/lookuptables.h"
28#include "util/waves.h"
29#include <bit>
30#include <cstdint>
31#include <cstring>
32#include <string>
33
34class UI;
35
36extern UI* getCurrentUI();
37
38extern const uint8_t modButtonX[];
39extern const uint8_t modButtonY[];
40
41extern uint8_t subModeToReturnTo;
42
43extern int32_t paramRanges[];
44extern int32_t paramNeutralValues[];
45
46void functionsInit();
47
48char const* getThingName(OutputType outputType);
49char const* getOutputTypeName(OutputType outputType, int32_t channel);
50
51// bits must be *less* than 32! I.e. 31 or less
52[[gnu::always_inline]] inline int32_t signed_saturate_operand_unknown(int32_t val, int32_t bits) {
53
54 // Despite having this switch at the per-audio-sample level, it doesn't introduce any slowdown compared to just
55 // always saturating by the same amount!
56 switch (bits) {
57 case 31:
58 return signed_saturate<31>(val);
59 case 30:
60 return signed_saturate<30>(val);
61 case 29:
62 return signed_saturate<29>(val);
63 case 28:
64 return signed_saturate<28>(val);
65 case 27:
66 return signed_saturate<27>(val);
67 case 26:
68 return signed_saturate<26>(val);
69 case 25:
70 return signed_saturate<25>(val);
71 case 24:
72 return signed_saturate<24>(val);
73 case 23:
74 return signed_saturate<23>(val);
75 case 22:
76 return signed_saturate<22>(val);
77 case 21:
78 return signed_saturate<21>(val);
79 case 20:
80 return signed_saturate<20>(val);
81 case 19:
82 return signed_saturate<19>(val);
83 case 18:
84 return signed_saturate<18>(val);
85 case 17:
86 return signed_saturate<17>(val);
87 case 16:
88 return signed_saturate<16>(val);
89 case 15:
90 return signed_saturate<15>(val);
91 case 14:
92 return signed_saturate<14>(val);
93 case 13:
94 return signed_saturate<13>(val);
95 default:
96 return signed_saturate<12>(val);
97 }
98}
99
100template <uint8_t lshift>
101[[gnu::always_inline]] inline int32_t lshiftAndSaturate(int32_t val) {
102 return signed_saturate<32 - lshift>(val) << lshift;
103}
104
105// lshift must be greater than 0! Not 0
106[[gnu::always_inline]] inline int32_t lshiftAndSaturateUnknown(int32_t val, uint8_t lshift) {
107 return signed_saturate_operand_unknown(val, 32 - lshift) << lshift;
108}
109
110[[gnu::always_inline]] constexpr uint32_t charsToIntegerConstant(char a, char b, char c, char d) {
111 return (static_cast<uint32_t>(a)) | (static_cast<uint32_t>(b) << 8) | (static_cast<uint32_t>(c) << 16)
112 | (static_cast<uint32_t>(d) << 24);
113}
114
115[[gnu::always_inline]] constexpr uint16_t charsToIntegerConstant(char a, char b) {
116 return (static_cast<uint16_t>(a)) | (static_cast<uint16_t>(b) << 8);
117}
122[[gnu::always_inline]] constexpr void asterixToInt(char* str, int32_t i) {
123 while (*str != 0) {
124 if (*str == '*') {
125 *str = (char)('0' + i);
126 }
127 str++;
128 }
129}
130
131void replace_char(char* str, const char* in_str, char find, char replace);
132
134[[gnu::always_inline]] constexpr void padStringTo(std::string& str, const size_t num) {
135 if (num > str.size()) {
136 str.insert(0, num - str.size(), ' ');
137 }
138}
139
140int32_t stringToInt(char const* string);
141int32_t stringToUIntOrError(char const* mem);
142int32_t memToUIntOrError(char const* mem, char const* const memEnd);
143void getInstrumentPresetFilename(char const* filePrefix, int16_t presetNumber, int8_t presetSubslotNumber,
144 char* fileName);
145char const* oscTypeToString(OscType osctype);
146OscType stringToOscType(char const* string);
147
148char const* lfoTypeToString(LFOType oscType);
149LFOType stringToLFOType(char const* string);
150
151char const* synthModeToString(SynthMode synthMode);
152SynthMode stringToSynthMode(char const* string);
153
154char const* polyphonyModeToString(PolyphonyMode synthMode);
155PolyphonyMode stringToPolyphonyMode(char const* string);
156
157char const* fxTypeToString(ModFXType fxType);
158ModFXType stringToFXType(char const* string);
159
160char const* modFXParamToString(ModFXParam fxType);
161ModFXParam stringToModFXParam(char const* string);
162
163char const* filterTypeToString(FilterType fxType);
164FilterType stringToFilterType(char const* string);
165
166ArpMode oldModeToArpMode(OldArpMode oldMode);
167ArpNoteMode oldModeToArpNoteMode(OldArpMode oldMode);
168ArpOctaveMode oldModeToArpOctaveMode(OldArpMode oldMode);
169
170char const* oldArpModeToString(OldArpMode mode);
171OldArpMode stringToOldArpMode(char const* string);
172
173char const* arpModeToString(ArpMode mode);
174ArpMode stringToArpMode(char const* string);
175
176char const* arpNoteModeToString(ArpNoteMode mode);
177ArpNoteMode stringToArpNoteMode(char const* string);
178
179char const* arpOctaveModeToString(ArpOctaveMode mode);
180ArpOctaveMode stringToArpOctaveMode(char const* string);
181
182char const* arpMpeModSourceToString(ArpMpeModSource modSource);
183ArpMpeModSource stringToArpMpeModSource(char const* string);
184
185char const* inputChannelToString(AudioInputChannel inputChannel);
186AudioInputChannel stringToInputChannel(char const* string);
187
188char const* sequenceDirectionModeToString(SequenceDirection sequenceDirectionMode);
189SequenceDirection stringToSequenceDirectionMode(char const* string);
190char const* launchStyleToString(LaunchStyle launchStyle);
191LaunchStyle stringToLaunchStyle(char const* string);
192
193char const* getInstrumentFolder(OutputType outputType);
194
195int32_t getExp(int32_t presetValue, int32_t adjustment);
196
197bool isAudioFilename(char const* filename);
198bool isAiffFilename(char const* filename);
199
200char const* getFileNameFromEndOfPath(char const* filePathChars);
201char const* getPathFromFullPath(char const* filePathChars);
202
203int32_t lookupReleaseRate(int32_t input);
204int32_t getParamFromUserValue(uint8_t p, int8_t userValue);
205int32_t getLookupIndexFromValue(int32_t value, const int32_t* table, int32_t maxIndex);
206int32_t instantTan(int32_t input);
207
208int32_t combineHitStrengths(int32_t strength1, int32_t strength2);
209
210int32_t cableToLinearParamShortcut(int32_t sourceValue);
211int32_t cableToExpParamShortcut(int32_t sourceValue);
212
213class Sound;
214int32_t getFinalParameterValueVolume(int32_t paramNeutralValue, int32_t patchedValue);
215int32_t getFinalParameterValueLinear(int32_t paramNeutralValue, int32_t patchedValue);
216int32_t getFinalParameterValueHybrid(int32_t paramNeutralValue, int32_t patchedValue);
217int32_t getFinalParameterValueExp(int32_t paramNeutralValue, int32_t patchedValue);
218int32_t getFinalParameterValueExpWithDumbEnvelopeHack(int32_t paramNeutralValue, int32_t patchedValue, int32_t p);
219
220char const* getSourceDisplayNameForOLED(PatchSource s);
221
222char const* sourceToString(PatchSource source);
223PatchSource stringToSource(char const* string);
224char const* sourceToStringShort(PatchSource source);
225
226int32_t shiftVolumeByDB(int32_t oldValue, float offset);
227int32_t quickLog(uint32_t input);
228
229int32_t interpolateTable(uint32_t input, int32_t numBitsInInput, const uint16_t* table, int32_t numBitsInTableSize = 8);
230uint32_t interpolateTableInverse(int32_t tableValueBig, int32_t numBitsInLookupOutput, const uint16_t* table,
231 int32_t numBitsInTableSize = 8);
232
233// input must not have any extra bits set than numBitsInInput specifies
234// Output of this function (unlike the regular 1d one) is only +- 1073741824
235[[gnu::always_inline]] inline int32_t interpolateTableSigned2d(uint32_t inputX, uint32_t inputY,
236 int32_t numBitsInInputX, int32_t numBitsInInputY,
237 const int16_t* table, int32_t numBitsInTableSizeX,
238 int32_t numBitsInTableSizeY) {
239
240 int32_t whichValue = inputY >> (numBitsInInputY - numBitsInTableSizeY);
241
242 int32_t tableSizeOneRow = (1 << numBitsInTableSizeX) + 1;
243
244 int32_t value1 =
245 interpolateTableSigned(inputX, numBitsInInputX, &table[whichValue * tableSizeOneRow], numBitsInTableSizeX);
246 int32_t value2 = interpolateTableSigned(inputX, numBitsInInputX, &table[(whichValue + 1) * tableSizeOneRow],
247 numBitsInTableSizeX);
248
249 int32_t lshiftAmount = 31 + numBitsInTableSizeY - numBitsInInputY;
250
251 uint32_t strength2;
252
253 if (lshiftAmount >= 0)
254 strength2 = (inputY << lshiftAmount) & 2147483647;
255 else
256 strength2 = (inputY >> (0 - lshiftAmount)) & 2147483647;
257
258 uint32_t strength1 = 2147483647 - strength2;
259 return multiply_32x32_rshift32(value1, strength1) + multiply_32x32_rshift32(value2, strength2);
260}
261
262template <unsigned saturationAmount>
263[[gnu::always_inline]] inline int32_t getTanH(int32_t input) {
264 uint32_t workingValue;
265
266 if (saturationAmount)
267 workingValue = (uint32_t)lshiftAndSaturate<saturationAmount>(input) + 2147483648u;
268 else
269 workingValue = (uint32_t)input + 2147483648u;
270
271 return interpolateTableSigned(workingValue, 32, tanHSmall, 8) >> (saturationAmount + 2);
272}
273
274[[gnu::always_inline]] inline int32_t getTanHUnknown(int32_t input, uint32_t saturationAmount) {
275 uint32_t workingValue;
276
277 if (saturationAmount)
278 workingValue = (uint32_t)lshiftAndSaturateUnknown(input, saturationAmount) + 2147483648u;
279 else
280 workingValue = (uint32_t)input + 2147483648u;
281
282 return interpolateTableSigned(workingValue, 32, tanHSmall, 8) >> (saturationAmount + 2);
283}
284
285[[gnu::always_inline]] inline int32_t getTanHAntialiased(int32_t input, uint32_t* lastWorkingValue,
286 uint32_t saturationAmount) {
287
288 uint32_t workingValue = (uint32_t)lshiftAndSaturateUnknown(input, saturationAmount) + 2147483648u;
289
290 int32_t toReturn = interpolateTableSigned2d(workingValue, *lastWorkingValue, 32, 32, &tanH2d[0][0], 7, 6)
291 >> (saturationAmount + 1);
292 *lastWorkingValue = workingValue;
293 return toReturn;
294}
295
296int32_t getDecay8(uint32_t input, uint8_t numBitsInInput);
297int32_t getDecay4(uint32_t input, uint8_t numBitsInInput);
298
299#define znew (z = 36969 * (z & 65535) + (z >> 16))
300#define wnew (w = 18000 * (w & 65535) + (w >> 16))
301#define MWC (int32_t)((znew << 16) + wnew)
302
303[[gnu::always_inline]] inline uint8_t getRandom255() {
304 return CONG >> 24;
305}
306
307[[gnu::always_inline]] inline int32_t getNoise() {
308 return CONG;
309}
310
312inline q31_t sampleTriangleDistribution() {
313 auto u1 = getNoise();
314 auto u2 = getNoise();
315 auto s = add_saturate(u1, u2);
316 return s;
317}
318
319void seedRandom();
320
321extern bool shouldInterpretNoteNames;
322extern bool octaveStartsFromA;
323
324int32_t random(int32_t upperLimit);
325bool shouldDoPanning(int32_t panAmount, int32_t* amplitudeL, int32_t* amplitudeR);
326
327uint32_t getOscInitialPhaseForZero(OscType waveType);
328int32_t fastPythag(int32_t x, int32_t y);
329int32_t strcmpspecial(char const* first, char const* second);
330int32_t doLanczos(int32_t* data, int32_t pos, uint32_t posWithinPos, int32_t memoryNumElements);
331int32_t doLanczosCircular(int32_t* data, int32_t pos, uint32_t posWithinPos, int32_t memoryNumElements);
332
333// intensity is out of 65536 now
334// occupancyMask is out of 64 now
335inline RGB drawSquare(const RGB& squareColour, int32_t intensity, const RGB& square, uint8_t* occupancyMask,
336 int32_t occupancyFromWhichColourCame) {
337
338 int32_t modifiedIntensity = intensity; //(intensity * occupancyFromWhichColourCame) >> 6; // Out of 65536
339
340 // Make new colour being drawn into this square marginalise the colour already in the square
341 int32_t colourRemainingAmount = 65536;
342
343 // We know how much colour we want to add to this square, so constrain any existing colour to the remaining "space"
344 // that it may still occupy
345 int32_t maxOldOccupancy = (65536 - modifiedIntensity) >> 10;
346
347 // If the square has more colour in it than it's allowed to retain, then plan to reduce it
348 if (*occupancyMask > maxOldOccupancy) {
349 colourRemainingAmount = (maxOldOccupancy << 16) / *occupancyMask; // out of 65536
350 }
351
352 // Add the new colour, reducing the old if that's what we're doing
353 int32_t newOccupancyMaskValue =
354 rshift_round(*occupancyMask * colourRemainingAmount, 16) + rshift_round(modifiedIntensity, 10);
355 *occupancyMask = std::min<int32_t>(64, newOccupancyMaskValue);
356
357 return RGB::blend2(square, squareColour, colourRemainingAmount, modifiedIntensity);
358}
359
360[[gnu::always_inline]] inline int32_t increaseMagnitude(int32_t number, int32_t magnitude) {
361 if (magnitude >= 0) {
362 return number << magnitude;
363 }
364 return number >> (-magnitude);
365}
366
367[[gnu::always_inline]] inline int32_t increaseMagnitudeAndSaturate(int32_t number, int32_t magnitude) {
368 if (magnitude > 0) {
369 return lshiftAndSaturateUnknown(number, magnitude);
370 }
371 return number >> (-magnitude);
372}
373
374int32_t howMuchMoreMagnitude(uint32_t to, uint32_t from);
375void noteCodeToString(int32_t noteCode, char* buffer, int32_t* getLengthWithoutDot = nullptr,
376 bool appendOctaveNo = true);
377void concatenateLines(const char* lines[], size_t numLines, char* resultString);
378double ConvertFromIeeeExtended(unsigned char* bytes /* LCN */);
379int32_t divide_round_negative(int32_t dividend, int32_t divisor);
380
381[[gnu::always_inline]] inline uint32_t swapEndianness32(uint32_t input) {
382 int32_t out;
383 asm("rev %0, %1" : "=r"(out) : "r"(input));
384 return out;
385}
386
387[[gnu::always_inline]] inline uint32_t swapEndianness2x16(uint32_t input) {
388 int32_t out;
389 asm("rev16 %0, %1" : "=r"(out) : "r"(input));
390 return out;
391}
392
393[[gnu::always_inline]] inline int32_t getMagnitudeOld(uint32_t input) {
394 return 32 - std::countl_zero(input);
395}
396
397[[gnu::always_inline]] inline int32_t getMagnitude(uint32_t input) {
398 return 31 - std::countl_zero(input);
399}
400
401[[gnu::always_inline]] inline bool isPowerOfTwo(uint32_t input) {
402 return (input == 1 << getMagnitude(input));
403}
404
405int32_t getWhichKernel(int32_t phaseIncrement);
406
407int32_t memcasecmp(char const* first, char const* second, int32_t size);
408int32_t getHowManyCharsAreTheSame(char const* a, char const* b);
409void dimColour(uint8_t colour[3]);
410bool charCaseEqual(char firstChar, char secondChar);
411bool shouldAbortLoading();
412int32_t getNoteMagnitudeFfromNoteLength(uint32_t noteLength, int32_t tickMagnitude);
414void getNoteLengthNameFromMagnitude(StringBuf& buf, int32_t magnitude, char const* durrationSuffix = "-notes",
415 bool clarifyPerColumn = false);
416bool doesFilenameFitPrefixFormat(char const* fileName, char const* filePrefix, int32_t prefixLength);
417Error fresultToDelugeErrorCode(FRESULT result);
418namespace FatFS {
419enum class Error;
420}
421Error fatfsErrorToDelugeError(FatFS::Error result);
422
423[[gnu::always_inline]] inline void writeInt16(char** address, uint16_t number) {
424 *(uint16_t*)*address = number;
425 *address += 2;
426}
427
428[[gnu::always_inline]] inline void writeInt32(char** address, uint32_t number) {
429 *(uint32_t*)*address = number;
430 *address += 4;
431}
432
433extern char miscStringBuffer[];
434
435constexpr size_t kShortStringBufferSize = 64;
436extern char shortStringBuffer[];
437
438float sigmoidLikeCurve(const float x, const float xMax, const float softening);
This class represents the colour format most used by the Deluge globally.
Definition rgb.h:14
static constexpr RGB blend2(RGB sourceA, RGB sourceB, uint16_t indexA, uint16_t indexB)
Generate a new colour made from blending two source colours with individual proportions.
Definition rgb.h:181
Definition sound.h:71
Definition d_stringbuf.h:16
Definition ui.h:92