Deluge Firmware 1.3.0
Build date: 2026.10.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/db_shift.h"
27#include "util/fixedpoint.h"
28#include "util/lookuptables/lookuptables.h"
29#include "util/name_compare.h" // IWYU pragma: export - strcmpspecial and friends used to live here
30#include "util/waves.h"
31#include <bit>
32#include <cstdint>
33#include <cstring>
34#include <string>
35
36class UI;
37
38extern UI* getCurrentUI();
39
40extern const uint8_t modButtonX[];
41extern const uint8_t modButtonY[];
42
43extern uint8_t subModeToReturnTo;
44
45extern int32_t paramRanges[];
46extern int32_t paramNeutralValues[];
47
48void functionsInit();
49
50char const* getThingName(OutputType outputType);
51char const* getOutputTypeName(OutputType outputType, int32_t channel);
52
53// bits must be *less* than 32! I.e. 31 or less
54[[gnu::always_inline]] inline int32_t signed_saturate_operand_unknown(int32_t val, int32_t bits) {
55
56 // Despite having this switch at the per-audio-sample level, it doesn't introduce any slowdown compared to just
57 // always saturating by the same amount!
58 switch (bits) {
59 case 31:
60 return signed_saturate<31>(val);
61 case 30:
62 return signed_saturate<30>(val);
63 case 29:
64 return signed_saturate<29>(val);
65 case 28:
66 return signed_saturate<28>(val);
67 case 27:
68 return signed_saturate<27>(val);
69 case 26:
70 return signed_saturate<26>(val);
71 case 25:
72 return signed_saturate<25>(val);
73 case 24:
74 return signed_saturate<24>(val);
75 case 23:
76 return signed_saturate<23>(val);
77 case 22:
78 return signed_saturate<22>(val);
79 case 21:
80 return signed_saturate<21>(val);
81 case 20:
82 return signed_saturate<20>(val);
83 case 19:
84 return signed_saturate<19>(val);
85 case 18:
86 return signed_saturate<18>(val);
87 case 17:
88 return signed_saturate<17>(val);
89 case 16:
90 return signed_saturate<16>(val);
91 case 15:
92 return signed_saturate<15>(val);
93 case 14:
94 return signed_saturate<14>(val);
95 case 13:
96 return signed_saturate<13>(val);
97 default:
98 return signed_saturate<12>(val);
99 }
100}
101
102template <uint8_t lshift>
103[[gnu::always_inline]] inline int32_t lshiftAndSaturate(int32_t val) {
104 return signed_saturate<32 - lshift>(val) << lshift;
105}
106
107// lshift must be greater than 0! Not 0
108[[gnu::always_inline]] inline int32_t lshiftAndSaturateUnknown(int32_t val, uint8_t lshift) {
109 return signed_saturate_operand_unknown(val, 32 - lshift) << lshift;
110}
111
112[[gnu::always_inline]] constexpr uint32_t charsToIntegerConstant(char a, char b, char c, char d) {
113 return (static_cast<uint32_t>(a)) | (static_cast<uint32_t>(b) << 8) | (static_cast<uint32_t>(c) << 16)
114 | (static_cast<uint32_t>(d) << 24);
115}
116
117[[gnu::always_inline]] constexpr uint16_t charsToIntegerConstant(char a, char b) {
118 return (static_cast<uint16_t>(a)) | (static_cast<uint16_t>(b) << 8);
119}
126[[gnu::always_inline]] constexpr void asterixToInt(char* str, int32_t i) {
127 while (*str != 0) {
128 // if double asterix (two digits)
129 if (*str == '*' && *(str + 1) == '*') {
130 intToString(i, str, 2);
131 break;
132 }
133 // if single asterix (single digit)
134 else if (*str == '*') {
135 *str = (char)('0' + i);
136 break;
137 }
138 str++;
139 }
140}
141
142void replace_char(char* str, const char* in_str, char find, char replace);
143
145[[gnu::always_inline]] constexpr void padStringTo(std::string& str, const size_t num) {
146 if (num > str.size()) {
147 str.insert(0, num - str.size(), ' ');
148 }
149}
150
151int32_t stringToInt(char const* string);
152int32_t stringToUIntOrError(char const* mem);
153int32_t memToUIntOrError(char const* mem, char const* const memEnd);
154void getInstrumentPresetFilename(char const* filePrefix, int16_t presetNumber, int8_t presetSubslotNumber,
155 char* fileName);
156char const* oscTypeToString(OscType osctype);
157OscType stringToOscType(char const* string);
158
159char const* lfoTypeToString(LFOType oscType);
160LFOType stringToLFOType(char const* string);
161
162char const* synthModeToString(SynthMode synthMode);
163SynthMode stringToSynthMode(char const* string);
164
165char const* polyphonyModeToString(PolyphonyMode synthMode);
166PolyphonyMode stringToPolyphonyMode(char const* string);
167
168char const* fxTypeToString(ModFXType fxType);
169ModFXType stringToFXType(char const* string);
170
171char const* modFXParamToString(ModFXParam fxType);
172ModFXParam stringToModFXParam(char const* string);
173
174char const* filterTypeToString(FilterType fxType);
175FilterType stringToFilterType(char const* string);
176
177ArpMode oldModeToArpMode(OldArpMode oldMode);
178ArpNoteMode oldModeToArpNoteMode(OldArpMode oldMode);
179ArpOctaveMode oldModeToArpOctaveMode(OldArpMode oldMode);
180
181char const* oldArpModeToString(OldArpMode mode);
182OldArpMode stringToOldArpMode(char const* string);
183
184char const* arpModeToString(ArpMode mode);
185ArpMode stringToArpMode(char const* string);
186
187char const* arpNoteModeToString(ArpNoteMode mode);
188ArpNoteMode stringToArpNoteMode(char const* string);
189
190char const* arpOctaveModeToString(ArpOctaveMode mode);
191ArpOctaveMode stringToArpOctaveMode(char const* string);
192
193char const* arpMpeModSourceToString(ArpMpeModSource modSource);
194ArpMpeModSource stringToArpMpeModSource(char const* string);
195
196char const* inputChannelToString(AudioInputChannel inputChannel);
197AudioInputChannel stringToInputChannel(char const* string);
198
199char const* sequenceDirectionModeToString(SequenceDirection sequenceDirectionMode);
200SequenceDirection stringToSequenceDirectionMode(char const* string);
201char const* launchStyleToString(LaunchStyle launchStyle);
202LaunchStyle stringToLaunchStyle(char const* string);
203
204char const* getInstrumentFolder(OutputType outputType);
205
206int32_t getExp(int32_t presetValue, int32_t adjustment);
207
208bool isAudioFilename(char const* filename);
209bool isAiffFilename(char const* filename);
210
211char const* getFileNameFromEndOfPath(char const* filePathChars);
212
213int32_t lookupReleaseRate(int32_t input);
214int32_t getParamFromUserValue(uint8_t p, int8_t userValue);
215int32_t getLookupIndexFromValue(int32_t value, const int32_t* table, int32_t maxIndex);
216int32_t instantTan(int32_t input);
217
218int32_t combineHitStrengths(int32_t strength1, int32_t strength2);
219
220int32_t cableToLinearParamShortcut(int32_t sourceValue);
221int32_t cableToExpParamShortcut(int32_t sourceValue);
222
223class Sound;
224struct StereoSample;
225int32_t getFinalParameterValueVolume(int32_t paramNeutralValue, int32_t patchedValue);
226int32_t getFinalParameterValueLinear(int32_t paramNeutralValue, int32_t patchedValue);
227int32_t getFinalParameterValueHybrid(int32_t paramNeutralValue, int32_t patchedValue);
228int32_t getFinalParameterValueExp(int32_t paramNeutralValue, int32_t patchedValue);
229int32_t getFinalParameterValueExpWithDumbEnvelopeHack(int32_t paramNeutralValue, int32_t patchedValue, int32_t p);
230
231char const* getSourceDisplayNameForOLED(PatchSource s);
232
233char const* sourceToString(PatchSource source);
234PatchSource stringToSource(char const* string);
235char const* sourceToStringShort(PatchSource source);
236
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:76
Definition d_stringbuf.h:16
Definition ui.h:92
Definition functions.h:444
Definition stereo_sample.h:25