Deluge Firmware 1.3.0
Build date: 2025.04.16
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;
214class StereoSample;
215int32_t getFinalParameterValueVolume(int32_t paramNeutralValue, int32_t patchedValue);
216int32_t getFinalParameterValueLinear(int32_t paramNeutralValue, int32_t patchedValue);
217int32_t getFinalParameterValueHybrid(int32_t paramNeutralValue, int32_t patchedValue);
218int32_t getFinalParameterValueExp(int32_t paramNeutralValue, int32_t patchedValue);
219int32_t getFinalParameterValueExpWithDumbEnvelopeHack(int32_t paramNeutralValue, int32_t patchedValue, int32_t p);
220
221char const* getSourceDisplayNameForOLED(PatchSource s);
222
223char const* sourceToString(PatchSource source);
224PatchSource stringToSource(char const* string);
225char const* sourceToStringShort(PatchSource source);
226
227int32_t shiftVolumeByDB(int32_t oldValue, float offset);
228int32_t quickLog(uint32_t input);
229
230int32_t interpolateTable(uint32_t input, int32_t numBitsInInput, const uint16_t* table, int32_t numBitsInTableSize = 8);
231uint32_t interpolateTableInverse(int32_t tableValueBig, int32_t numBitsInLookupOutput, const uint16_t* table,
232 int32_t numBitsInTableSize = 8);
233
234// input must not have any extra bits set than numBitsInInput specifies
235// Output of this function (unlike the regular 1d one) is only +- 1073741824
236[[gnu::always_inline]] inline int32_t interpolateTableSigned2d(uint32_t inputX, uint32_t inputY,
237 int32_t numBitsInInputX, int32_t numBitsInInputY,
238 const int16_t* table, int32_t numBitsInTableSizeX,
239 int32_t numBitsInTableSizeY) {
240
241 int32_t whichValue = inputY >> (numBitsInInputY - numBitsInTableSizeY);
242
243 int32_t tableSizeOneRow = (1 << numBitsInTableSizeX) + 1;
244
245 int32_t value1 =
246 interpolateTableSigned(inputX, numBitsInInputX, &table[whichValue * tableSizeOneRow], numBitsInTableSizeX);
247 int32_t value2 = interpolateTableSigned(inputX, numBitsInInputX, &table[(whichValue + 1) * tableSizeOneRow],
248 numBitsInTableSizeX);
249
250 int32_t lshiftAmount = 31 + numBitsInTableSizeY - numBitsInInputY;
251
252 uint32_t strength2;
253
254 if (lshiftAmount >= 0)
255 strength2 = (inputY << lshiftAmount) & 2147483647;
256 else
257 strength2 = (inputY >> (0 - lshiftAmount)) & 2147483647;
258
259 uint32_t strength1 = 2147483647 - strength2;
260 return multiply_32x32_rshift32(value1, strength1) + multiply_32x32_rshift32(value2, strength2);
261}
262
263template <unsigned saturationAmount>
264[[gnu::always_inline]] inline int32_t getTanH(int32_t input) {
265 uint32_t workingValue;
266
267 if (saturationAmount)
268 workingValue = (uint32_t)lshiftAndSaturate<saturationAmount>(input) + 2147483648u;
269 else
270 workingValue = (uint32_t)input + 2147483648u;
271
272 return interpolateTableSigned(workingValue, 32, tanHSmall, 8) >> (saturationAmount + 2);
273}
274
275[[gnu::always_inline]] inline int32_t getTanHUnknown(int32_t input, uint32_t saturationAmount) {
276 uint32_t workingValue;
277
278 if (saturationAmount)
279 workingValue = (uint32_t)lshiftAndSaturateUnknown(input, saturationAmount) + 2147483648u;
280 else
281 workingValue = (uint32_t)input + 2147483648u;
282
283 return interpolateTableSigned(workingValue, 32, tanHSmall, 8) >> (saturationAmount + 2);
284}
285
286[[gnu::always_inline]] inline int32_t getTanHAntialiased(int32_t input, uint32_t* lastWorkingValue,
287 uint32_t saturationAmount) {
288
289 uint32_t workingValue = (uint32_t)lshiftAndSaturateUnknown(input, saturationAmount) + 2147483648u;
290
291 int32_t toReturn = interpolateTableSigned2d(workingValue, *lastWorkingValue, 32, 32, &tanH2d[0][0], 7, 6)
292 >> (saturationAmount + 1);
293 *lastWorkingValue = workingValue;
294 return toReturn;
295}
296
297int32_t getDecay8(uint32_t input, uint8_t numBitsInInput);
298int32_t getDecay4(uint32_t input, uint8_t numBitsInInput);
299
300#define znew (z = 36969 * (z & 65535) + (z >> 16))
301#define wnew (w = 18000 * (w & 65535) + (w >> 16))
302#define MWC (int32_t)((znew << 16) + wnew)
303
304[[gnu::always_inline]] inline uint8_t getRandom255() {
305 return CONG >> 24;
306}
307
308[[gnu::always_inline]] inline int32_t getNoise() {
309 return CONG;
310}
311
313inline q31_t sampleTriangleDistribution() {
314 auto u1 = getNoise();
315 auto u2 = getNoise();
316 auto s = add_saturate(u1, u2);
317 return s;
318}
319
320void seedRandom();
321
322extern bool shouldInterpretNoteNames;
323extern bool octaveStartsFromA;
324
325int32_t random(int32_t upperLimit);
326bool shouldDoPanning(int32_t panAmount, int32_t* amplitudeL, int32_t* amplitudeR);
327
328uint32_t getOscInitialPhaseForZero(OscType waveType);
329int32_t fastPythag(int32_t x, int32_t y);
330int32_t strcmpspecial(char const* first, char const* second);
331int32_t doLanczos(int32_t* data, int32_t pos, uint32_t posWithinPos, int32_t memoryNumElements);
332int32_t doLanczosCircular(int32_t* data, int32_t pos, uint32_t posWithinPos, int32_t memoryNumElements);
333
334// intensity is out of 65536 now
335// occupancyMask is out of 64 now
336inline RGB drawSquare(const RGB& squareColour, int32_t intensity, const RGB& square, uint8_t* occupancyMask,
337 int32_t occupancyFromWhichColourCame) {
338
339 int32_t modifiedIntensity = intensity; //(intensity * occupancyFromWhichColourCame) >> 6; // Out of 65536
340
341 // Make new colour being drawn into this square marginalise the colour already in the square
342 int32_t colourRemainingAmount = 65536;
343
344 // We know how much colour we want to add to this square, so constrain any existing colour to the remaining "space"
345 // that it may still occupy
346 int32_t maxOldOccupancy = (65536 - modifiedIntensity) >> 10;
347
348 // If the square has more colour in it than it's allowed to retain, then plan to reduce it
349 if (*occupancyMask > maxOldOccupancy) {
350 colourRemainingAmount = (maxOldOccupancy << 16) / *occupancyMask; // out of 65536
351 }
352
353 // Add the new colour, reducing the old if that's what we're doing
354 int32_t newOccupancyMaskValue =
355 rshift_round(*occupancyMask * colourRemainingAmount, 16) + rshift_round(modifiedIntensity, 10);
356 *occupancyMask = std::min<int32_t>(64, newOccupancyMaskValue);
357
358 return RGB::blend2(square, squareColour, colourRemainingAmount, modifiedIntensity);
359}
360
361[[gnu::always_inline]] inline int32_t increaseMagnitude(int32_t number, int32_t magnitude) {
362 if (magnitude >= 0) {
363 return number << magnitude;
364 }
365 return number >> (-magnitude);
366}
367
368[[gnu::always_inline]] inline int32_t increaseMagnitudeAndSaturate(int32_t number, int32_t magnitude) {
369 if (magnitude > 0) {
370 return lshiftAndSaturateUnknown(number, magnitude);
371 }
372 return number >> (-magnitude);
373}
374
375int32_t howMuchMoreMagnitude(uint32_t to, uint32_t from);
376void noteCodeToString(int32_t noteCode, char* buffer, int32_t* getLengthWithoutDot = nullptr,
377 bool appendOctaveNo = true);
378void concatenateLines(const char* lines[], size_t numLines, char* resultString);
379double ConvertFromIeeeExtended(unsigned char* bytes /* LCN */);
380int32_t divide_round_negative(int32_t dividend, int32_t divisor);
381
382[[gnu::always_inline]] inline uint32_t swapEndianness32(uint32_t input) {
383 int32_t out;
384 asm("rev %0, %1" : "=r"(out) : "r"(input));
385 return out;
386}
387
388[[gnu::always_inline]] inline uint32_t swapEndianness2x16(uint32_t input) {
389 int32_t out;
390 asm("rev16 %0, %1" : "=r"(out) : "r"(input));
391 return out;
392}
393
394[[gnu::always_inline]] inline int32_t getMagnitudeOld(uint32_t input) {
395 return 32 - std::countl_zero(input);
396}
397
398[[gnu::always_inline]] inline int32_t getMagnitude(uint32_t input) {
399 return 31 - std::countl_zero(input);
400}
401
402[[gnu::always_inline]] inline bool isPowerOfTwo(uint32_t input) {
403 return (input == 1 << getMagnitude(input));
404}
405
406int32_t getWhichKernel(int32_t phaseIncrement);
407
408int32_t memcasecmp(char const* first, char const* second, int32_t size);
409int32_t getHowManyCharsAreTheSame(char const* a, char const* b);
410void dimColour(uint8_t colour[3]);
411bool charCaseEqual(char firstChar, char secondChar);
412bool shouldAbortLoading();
413int32_t getNoteMagnitudeFfromNoteLength(uint32_t noteLength, int32_t tickMagnitude);
415void getNoteLengthNameFromMagnitude(StringBuf& buf, int32_t magnitude, char const* durrationSuffix = "-notes",
416 bool clarifyPerColumn = false);
417bool doesFilenameFitPrefixFormat(char const* fileName, char const* filePrefix, int32_t prefixLength);
418Error fresultToDelugeErrorCode(FRESULT result);
419namespace FatFS {
420enum class Error;
421}
422Error fatfsErrorToDelugeError(FatFS::Error result);
423
424[[gnu::always_inline]] inline void writeInt16(char** address, uint16_t number) {
425 *(uint16_t*)*address = number;
426 *address += 2;
427}
428
429[[gnu::always_inline]] inline void writeInt32(char** address, uint32_t number) {
430 *(uint32_t*)*address = number;
431 *address += 4;
432}
433
434extern char miscStringBuffer[];
435
436constexpr size_t kShortStringBufferSize = 64;
437extern char shortStringBuffer[];
438
440 float l;
441 float r;
442};
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_string.h:106
Definition ui.h:92
Definition functions.h:439
Definition stereo_sample.h:25