tracktion-engine 3.0-10-g034fdde4aa5
Tracktion Engine — High level data model for audio applications

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_AudioFileUtils.h
Go to the documentation of this file.
1 /*
2 ,--. ,--. ,--. ,--.
3 ,-' '-.,--.--.,--,--.,---.| |,-.,-' '-.`--' ,---. ,--,--, Copyright 2024
4 '-. .-'| .--' ,-. | .--'| /'-. .-',--.| .-. || \ Tracktion Software
5 | | | | \ '-' \ `--.| \ \ | | | |' '-' '| || | Corporation
6 `---' `--' `--`--'`---'`--'`--' `---' `--' `---' `--''--' www.tracktion.com
7
8 Tracktion Engine uses a GPL/commercial licence - see LICENCE.md for details.
9*/
10
11namespace tracktion { inline namespace engine
12{
13
14//==============================================================================
18{
19 static juce::AudioFormatReader* createReaderFor (Engine&, const juce::File&);
20 static juce::AudioFormatReader* createReaderFindingFormat (Engine&, const juce::File&, juce::AudioFormat*&);
21 static juce::MemoryMappedAudioFormatReader* createMemoryMappedReader (Engine&, const juce::File&, juce::AudioFormat*&);
22
28
29 static std::unique_ptr<MappedFileAndReader> createMappedFileAndReaderFor (Engine&, const juce::File&);
30
31 static juce::AudioFormatWriter* createWriterFor (Engine&, const juce::File&,
32 double sampleRate, unsigned int numChannels, int bitsPerSample,
33 const juce::StringPairArray& metadata, int quality);
34
35 static juce::AudioFormatWriter* createWriterFor (juce::AudioFormat*, const juce::File&,
36 double sampleRate, unsigned int numChannels, int bitsPerSample,
37 const juce::StringPairArray& metadata, int quality);
38
39 static SampleRange scanForNonZeroSamples (Engine&, const juce::File&, float maxZeroLevelDb);
40
41 static SampleRange copyNonSilentSectionToNewFile (Engine&,
42 const juce::File& sourceFile,
43 const juce::File& destFile,
44 float maxZeroLevelDb);
45
46 static SampleRange trimSilence (Engine&, const juce::File&, float maxZeroLevelDb);
47
49 static bool reverse (Engine&, const juce::File& source, const juce::File& destination,
50 std::atomic<float>& progress, juce::ThreadPoolJob* job = nullptr,
51 bool canCreateWavIntermediate = true);
52
53 // returns length of file created, or -1
54 static SampleCount copySectionToNewFile (Engine& e,
55 const juce::File& sourceFile,
56 const juce::File& destFile,
57 SampleRange range);
58
59 static SampleCount copySectionToNewFile (Engine& e,
60 const juce::File& sourceFile,
61 const juce::File& destFile,
62 TimeRange range);
63
64 static void addBWAVStartToMetadata (juce::StringPairArray& metadata, SampleCount start);
65
66 static void applyBWAVStartTime (const juce::File&, SampleCount start);
67
68 static SampleCount getFileLengthSamples (Engine& e, const juce::File&);
69
70 //==============================================================================
71 template<class TargetFormat>
72 static bool convertToFormat (Engine& e, const juce::File& sourceFile, juce::OutputStream& destStream,
73 int quality, const juce::StringPairArray& metadata,
74 juce::int64 blockSize = -1,
75 std::function<bool()> continuePredicate = {},
76 std::function<void (float)> updateProgress = {})
77 {
78 std::unique_ptr<juce::AudioFormatReader> reader (createReaderFor (e, sourceFile));
79 return convertToFormat<TargetFormat> (reader.get(), destStream, quality, metadata, blockSize,
80 continuePredicate, updateProgress);
81 }
82
83 template<class TargetFormat>
84 static bool convertToFormat (juce::AudioFormatReader* reader,
85 juce::OutputStream& destStream,
86 int quality, const juce::StringPairArray& metadata,
87 juce::int64 blockSize = -1,
88 std::function<bool()> continuePredicate = {},
89 std::function<void (float)> updateProgress = {})
90 {
91 if (reader != nullptr)
92 {
93 // NB: must write to a temp file because the archiver relies on the destStream's position
94 // being left pointing to the end of the data that was written, whereas some formats
95 // may leave the position set elsewhere.
96 juce::TemporaryFile tempFile;
97
98 if (auto out = tempFile.getFile().createOutputStream())
99 {
100 TargetFormat format;
101
102 if (auto writer = std::unique_ptr<juce::AudioFormatWriter> (format.createWriterFor (out.get(), reader->sampleRate,
103 reader->numChannels,
104 (int) reader->bitsPerSample,
105 metadata, quality)))
106 {
107 out.release();
108
109 if (blockSize < 0)
110 {
111 if (writer->writeFromAudioReader (*reader, 0, -1))
112 {
113 writer = nullptr;
114 destStream << tempFile.getFile();
115 return true;
116 }
117 }
118 else
119 {
120 juce::int64 numLeft = reader->lengthInSamples;
121
122 if (numLeft <= 0)
123 return false;
124
125 for (juce::int64 startSample = 0;;)
126 {
127 if (continuePredicate && ! continuePredicate())
128 return false;
129
130 const juce::int64 numThisTime = std::min (blockSize, numLeft);
131
132 if (! writer->writeFromAudioReader (*reader, startSample, numThisTime))
133 return false;
134
135 startSample += numThisTime;
136 numLeft -= numThisTime;
137
138 if (updateProgress)
139 updateProgress (static_cast<float> (startSample) / reader->lengthInSamples);
140
141 if (numLeft <= 0)
142 {
143 writer = nullptr;
144 destStream << tempFile.getFile();
145 return true;
146 }
147 }
148 }
149 }
150 }
151 else
152 {
154 }
155 }
156
157 return false;
158 }
159
160 //==============================================================================
161 template <typename SourceFormat>
162 inline static bool readFromFormat (Engine& engine, juce::InputStream& source, const juce::File& dest)
163 {
164 struct ForwardingInputStream : public juce::InputStream
165 {
166 ForwardingInputStream (juce::InputStream& s) : stream (s) {}
167
168 juce::int64 getTotalLength() override { return stream.getTotalLength(); }
169 bool isExhausted() override { return stream.isExhausted(); }
170 int read (void* d, int sz) override { return stream.read (d, sz); }
171 juce::int64 getPosition() override { return stream.getPosition(); }
172 bool setPosition (juce::int64 pos) override { return stream.setPosition (pos); }
173
174 InputStream& stream;
175 };
176
177 SourceFormat sourceFormat;
178
179 if (auto reader = std::unique_ptr<juce::AudioFormatReader> (sourceFormat.createReaderFor (new ForwardingInputStream (source), true)))
180 {
181 auto& manager = engine.getAudioFileFormatManager().writeFormatManager;
182
183 auto* destFormat = manager.findFormatForFileExtension (dest.getFileExtension());
184
185 if (destFormat == nullptr)
186 destFormat = manager.findFormatForFileExtension ("wav");
187
188 AudioFileWriter writer (AudioFile (engine, dest), destFormat,
189 (int) reader->numChannels,
190 reader->sampleRate,
191 (int) reader->bitsPerSample,
192 reader->metadataValues, 0);
193
194 if (writer.isOpen() && writer.writeFromAudioReader (*reader, 0, -1))
195 return true;
196 }
197
199 return false;
200 }
201
202 //==============================================================================
204 {
205 public:
207
208 void processEnvelope (const float* inputBuffer, float* outputBuffer, int numSamples) noexcept
209 {
210 for (int i = 0; i < numSamples; ++i)
211 {
212 float envIn = std::abs (inputBuffer[i]);
213
214 if (envelope < envIn)
215 envelope += envAttack * (envIn - envelope);
216 else if (envelope > envIn)
217 envelope -= envRelease * (envelope - envIn);
218
219 outputBuffer[i] = envelope;
220 }
221 }
222
226 void setCoefficients (float attack, float release) noexcept
227 {
228 envAttack = attack;
229 envRelease = release;
230 }
231
232 private:
233 float envelope = 0.0f;
234 float envAttack = 1.0f, envRelease = 1.0f;
235
237 };
238};
239
240}} // namespace tracktion { inline namespace engine
StringPairArray metadataValues
unsigned int bitsPerSample
unsigned int numChannels
std::unique_ptr< FileOutputStream > createOutputStream(size_t bufferSize=0x8000) const
String getFileExtension() const
const File & getFile() const noexcept
void setCoefficients(float attack, float release) noexcept
Sets the times for the vaious stages of the envelope.
The Engine is the central class for all tracktion sessions.
T format(T... args)
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
#define jassertfalse
T min(T... args)
long long int64
read
static bool reverse(Engine &, const juce::File &source, const juce::File &destination, std::atomic< float > &progress, juce::ThreadPoolJob *job=nullptr, bool canCreateWavIntermediate=true)
Reverses a file updating a progress value and checking the exit status of a given job.