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