Deluge Firmware 1.3.0
Build date: 2025.04.16
Loading...
Searching...
No Matches
audio_file_manager.h
1/*
2 * Copyright © 2017-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#include "audio_file.h"
20#include "definitions_cxx.hpp"
21#include "storage/cluster/cluster.h"
22#include "storage/cluster/cluster_priority_queue.h"
23#include <array>
24#include <cstdint>
25#include <expected>
26#include <strings.h>
27
28extern "C" {
29#include "fatfs/ff.h"
30}
31
32class Sample;
33class SampleCache;
34class String;
35class SampleRecorder;
36class Output;
37class WaveTable;
38
39enum class AlternateLoadDirStatus {
40 NONE_SET,
41 NOT_FOUND,
42 MIGHT_EXIST,
43 DOES_EXIST,
44};
45
46char const* const audioRecordingFolderNames[] = {
47 "SAMPLES/CLIPS",
48 "SAMPLES/RECORD",
49 "SAMPLES/RESAMPLE",
50 "SAMPLES/EXPORTS",
51};
52
53/*
54 * ===================== SD card audio streaming ==================
55 *
56 * Audio streaming (for Samples and AudioClips) from the SD card functions by loading
57 * and caching Clusters of audio data from the SD card. A formatted card will have a
58 * cluster size for the filesystem - often 32kB, but it could be as small as 4kB, or even smaller maybe?
59 * The Deluge deals in these Clusters, whatever size they may be for the card, which makes
60 * sense because one Cluster always exists in one physical place on the SD card (or any disk),
61 * so may be easily loaded in one operation by DMA. Whereas consecutive clusters making up an
62 * (audio) file are often placed in completely different physical locations.
63 *
64 * For a Sample associated with a Sound or AudioClip, the Deluge keeps the first two Clusters of that file
65 * (from its set start-point and subject to reversing) permanently loaded in RAM, so playback of the
66 * Sample may begin instantly when the Sound or AudioClip is played. And if the Sample has a loop-start point,
67 * it keeps the first two Clusters from that point permanently loaded too.
68 *
69 * Then as the Sample plays, the currently-playing Cluster and the next one are kept loaded in RAM.
70 * Or rather, as soon as the “play-head” enters a new Cluster, the Deluge immediately enqueues
71 * the following Cluster to be loaded from the card ASAP.
72 *
73 * And then also, loaded Clusters remain loaded/cached in RAM for as long as possible while that RAM
74 * isn’t needed for something more important, so they may be played again without having to reload
75 * them from the card. Details on that process below.
76 *
77 * Quick note - Cluster objects are also used (in RAM) to store SampleCache data (which caches
78 * Sample data post-repitching or post-pitch-shifting), and “percussive” audio data (“perc” for short)
79 * which is condensed data for use by the time-stretching algorithm. The reason for these types
80 * of data being housed in Cluster objects is largely legacy, but it also is handy because all
81 * Cluster objects are made to be the same size in RAM, so “stealing” one will always make the
82 * right amount of space for another (see below to see what “stealing” means).
83 */
84
85class AudioFileManager {
87 bool operator()(String* const& lhs, String* const& rhs) const { return strcasecmp(lhs->get(), rhs->get()) < 0; }
88 };
89
90public:
91 AudioFileManager();
92
93 deluge::fast_map<String*, Sample*, StringLessThan> sampleFiles;
94 deluge::fast_map<String*, WaveTable*, StringLessThan> wavetableFiles;
95
96 void init();
97 std::expected<AudioFile*, Error> getAudioFileFromFilename(String& fileName, bool mayReadCard,
98 FilePointer* filePointer, AudioFileType type,
99 bool makeWaveTableWorkAtAllCosts = false);
100 bool loadCluster(Cluster& cluster, int32_t minNumReasonsAfter = 0);
101 void loadAnyEnqueuedClusters(int32_t maxNum = 128, bool mayProcessUserActionsBetween = false);
102 void removeReasonFromCluster(Cluster& cluster, char const* errorCode, bool deletingSong = false);
103
104 void slowRoutine();
105
106 std::expected<void, Error> setupAlternateAudioFilePath(String& newPath, int32_t dirPathLength, String& oldPath);
107 std::expected<void, Error> setupAlternateAudioFileDir(String& newPath, char const* rootDir,
108 String& songFilenameWithoutExtension);
109 bool loadingQueueHasAnyLowestPriorityElements();
112 Error getUnusedAudioRecordingFilePath(String& filePath, String* tempFilePathForRecording,
113 AudioRecordingFolder folder, uint32_t* getNumber, const char* channelName,
114 String* songName);
115 void deleteAnyTempRecordedSamplesFromMemory();
116
117 void releaseFile(Sample& sample);
118 void releaseFile(WaveTable& wavetable);
119 bool releaseSampleAtFilePath(String& filePath);
120 void releaseAllUnused();
121
122 void thingBeginningLoading(ThingType newThingType);
123 void thingFinishedLoading();
124
125 void setCardRead() { cardReadOnce = true; }
126 void setCardEjected() { cardEjected = true; }
127
128 ClusterPriorityQueue loadingQueue;
129
130 Cluster* clusterBeingLoaded;
131 int32_t minNumReasonsForClusterBeingLoaded; // Only valid when clusterBeingLoaded is set. And this exists for bug
132 // hunting only.
133
134 String alternateAudioFileLoadPath;
135 AlternateLoadDirStatus alternateLoadDirStatus = AlternateLoadDirStatus::NONE_SET;
136 ThingType thingTypeBeingLoaded = ThingType::NONE;
137 DIR alternateLoadDir;
138
139 std::array<int32_t, kNumAudioRecordingFolders> highestUsedAudioRecordingNumber;
140 std::bitset<kNumAudioRecordingFolders> highestUsedAudioRecordingNumberNeedsReChecking;
141 void firstCardRead();
142
143private:
144 bool cardReadOnce{false};
145 bool cardEjected;
146 bool cardDisabled = false;
147
148 uint32_t clusterSizeAtBoot{0};
149
150 void cardReinserted();
151 int32_t readBytes(char* buffer, int32_t num, int32_t* byteIndexWithinCluster, Cluster** currentCluster,
152 uint32_t* currentClusterIndex, uint32_t fileSize, Sample* sample);
153 int32_t loadAiff(Sample* newSample, uint32_t fileSize, Cluster** currentCluster, uint32_t* currentClusterIndex);
154 int32_t loadWav(Sample* newSample, uint32_t fileSize, Cluster** currentCluster, uint32_t* currentClusterIndex);
155};
156
157extern AudioFileManager audioFileManager;
Definition audio_file_manager.h:85
void releaseAllUnused()
release unused sapmles and wavetables
Definition audio_file_manager.cpp:378
Error getUnusedAudioRecordingFilePath(String &filePath, String *tempFilePathForRecording, AudioRecordingFolder folder, uint32_t *getNumber, const char *channelName, String *songName)
Definition audio_file_manager.cpp:224
Definition cluster.h:34
Definition output.h:81
Definition sample_cache.h:25
Definition sample_recorder.h:49
Definition sample.h:50
Definition d_string.h:46
Definition wave_table.h:42
Definition audio_file_manager.h:86