Deluge Firmware 1.3.0
Build date: 2026.07.30
Loading...
Searching...
No Matches
sample_recorder.h
1/*
2 * Copyright © 2016-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 "definitions_cxx.hpp"
21#include "dsp/envelope_follower/absolute_value.h"
22#include "dsp/stereo_sample.h"
23#include "fatfs/fatfs.hpp"
24#include <cstddef>
25#include <gsl/gsl>
26#include <optional>
27
28enum class MonitoringAction {
29 NONE = 0,
30 REMOVE_RIGHT_CHANNEL = 1,
31 SUBTRACT_RIGHT_CHANNEL = 2,
32};
33
34enum class RecorderStatus {
35 CAPTURING_DATA = 0,
36 CAPTURING_DATA_WAITING_TO_STOP = 1,
37 FINISHED_CAPTURING_BUT_STILL_WRITING = 2,
38 COMPLETE = 3,
39
40 // Means RAM error only. SD errors are noted separately and won't affect operation, as long as RAM lasts
41 ABORTED = 4,
42 AWAITING_DELETION = 5,
43};
44
45class Sample;
46class Cluster;
47class AudioClip;
48class Output;
50 bool neverUseThreshold = false;
51};
52
53class SampleRecorder {
54public:
55 SampleRecorder() = default;
56 ~SampleRecorder();
57 Error setup(int32_t newNumChannels, AudioInputChannel newMode, bool newKeepingReasons,
58 bool shouldRecordExtraMargins, AudioRecordingFolder newFolderID, int32_t buttonPressLatency,
59 Output* outputRecordingFrom, RecorderConfig config = {});
60 void setRecordingThreshold(RecorderConfig config);
61 void feedAudio(std::span<StereoSample> input, bool applyGain = false, uint8_t gainToApply = 5);
62 Error cardRoutine();
63 void endSyncedRecording(int32_t buttonLatencyForTempolessRecording);
64 bool inputLooksDifferential();
65 bool inputHasNoRightChannel();
66 void removeFromOutput() {
67 if (status < RecorderStatus::FINISHED_CAPTURING_BUT_STILL_WRITING) {
68 abort();
69 }
70 outputRecordingFrom = nullptr;
71 };
72 void abort();
73
74 SampleRecorder* next;
75
76 gsl::owner<Sample*> sample;
77
78 int32_t numSamplesToRunBeforeBeginningCapturing;
79 uint32_t numSamplesBeenRunning;
80 uint32_t numSamplesCaptured;
81
82 uint32_t numSamplesExtraToCaptureAtEndSyncingWise;
83
84 int32_t firstUnwrittenClusterIndex = 0;
85
86 // Put things in valid state so if we get destructed before any recording, it's all ok
87 int32_t currentRecordClusterIndex = -1;
88
89 // Note! If this is NULL, that means that currentRecordClusterIndex refers to a cluster that never got created (cos
90 // some error or max file size reached)
91 Cluster* currentRecordCluster = nullptr;
92
93 uint32_t audioFileNumber;
94 AudioRecordingFolder folderID;
95
96 char* writePos;
97 char* clusterEndPos;
98
99 // When this gets set, we add the Sample to the master list. This is stored here in addition to in the Sample,
100 // so we can delete an aborted file even after the Sample has been detached / destructed.
101 // This will be the temp file path if there is one.
102 String filePathCreated;
103
104 RecorderStatus status = RecorderStatus::CAPTURING_DATA;
105 AudioInputChannel mode;
106 Output* outputRecordingFrom; // for when recording from a specific output
107
108 // Need to keep track of this, so we know whether to remove it. Well I guess we could just look and see if it's
109 // there... but this is nice.
110 bool haveAddedSampleToArray = false;
111
112 bool allowFileAlterationAfter = false;
113 bool allowNormalization = true;
114 bool autoDeleteWhenDone = false;
115 bool keepingReasonsForFirstClusters;
116 uint8_t recordingNumChannels;
117 bool hadCardError = false;
118 bool reachedMaxFileSize = false;
119 bool recordingExtraMargins = false;
120 bool pointerHeldElsewhere = false;
121 bool capturedTooMuch = false;
122 bool thresholdRecording = false;
123 uint32_t minThresholdMargin = 0;
124
125 // Most of these are not captured in the case of BALANCED input for AudioClips
126 bool recordingClippedRecently;
127 int32_t recordPeakL;
128 int32_t recordPeakR;
129 int32_t recordPeakLMinusR;
130 uint64_t recordSumL;
131 uint64_t recordSumR;
132 uint64_t recordSumLPlusR; // L and R are halved before these two are calculated
133 uint64_t recordSumLMinusR; // --------
134
135 int32_t recordMax;
136 int32_t recordMin;
137
138 uint32_t audioDataLengthBytesAsWrittenToFile;
139 uint32_t loopEndSampleAsWrittenToFile;
140
141 float startValueThreshold;
142
143 int32_t* sourcePos;
144
145 std::optional<FatFS::File> file;
146
147private:
148 void setExtraBytesOnPreviousCluster(Cluster* currentCluster, int32_t currentClusterIndex);
149 Error writeCluster(int32_t clusterIndex, size_t numBytes);
150 Error alterFile(MonitoringAction action, int32_t lshiftAmount, uint32_t idealFileSizeBeforeAction,
151
152 uint64_t dataLengthAfterAction);
153 Error finalizeRecordedFile();
154 Error createNextCluster();
155 Error writeAnyCompletedClusters();
156 void finishCapturing();
157 void updateDataLengthInFirstCluster(Cluster* cluster);
158 void totalSampleLengthNowKnown(uint32_t totalLength, uint32_t loopEndPointSamples = 0);
159 void detachSample();
160 Error truncateFileDownToSize(uint32_t newFileSize);
161 Error writeOneCompletedCluster();
162 AbsValueFollower envelopeFollower{};
163};
Definition absolute_value.h:24
Definition audio_clip.h:35
Definition cluster.h:34
Definition output.h:81
Definition sample.h:50
Definition d_string.h:41
Definition sample_recorder.h:49