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