From 443303bac580d36bcf26bc21adb893dde82a8fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=84=A1=E5=B8=B8?= <3142324836@qq.com> Date: Mon, 25 Nov 2024 23:50:50 +0800 Subject: [PATCH] Update RecordTemp data buffers --- src/audioCore/graph/SourceRecordProcessor.cpp | 5 ++ src/audioCore/graph/SourceRecordProcessor.h | 2 + src/audioCore/misc/RecordTemp.cpp | 88 ++++++++++++++++++- src/audioCore/misc/RecordTemp.h | 20 ++++- 4 files changed, 113 insertions(+), 2 deletions(-) diff --git a/src/audioCore/graph/SourceRecordProcessor.cpp b/src/audioCore/graph/SourceRecordProcessor.cpp index 4fd45188..c76596cc 100644 --- a/src/audioCore/graph/SourceRecordProcessor.cpp +++ b/src/audioCore/graph/SourceRecordProcessor.cpp @@ -13,6 +13,7 @@ SourceRecordProcessor::~SourceRecordProcessor() {} void SourceRecordProcessor::prepareToPlay( double sampleRate, int maximumExpectedSamplesPerBlock) { this->setRateAndBufferSizeDetails(sampleRate, maximumExpectedSamplesPerBlock); + RecordTemp::getInstance()->setInputSampleRate(sampleRate); } void SourceRecordProcessor::processBlock( @@ -43,3 +44,7 @@ double SourceRecordProcessor::getTailLengthSeconds() const { } return 0; } + +void SourceRecordProcessor::numChannelsChanged() { + RecordTemp::getInstance()->setInputChannelNum(this->getTotalNumInputChannels()); +} diff --git a/src/audioCore/graph/SourceRecordProcessor.h b/src/audioCore/graph/SourceRecordProcessor.h index 34b01fc2..c6c716de 100644 --- a/src/audioCore/graph/SourceRecordProcessor.h +++ b/src/audioCore/graph/SourceRecordProcessor.h @@ -61,6 +61,8 @@ class SourceRecordProcessor final : public juce::AudioProcessor { MainGraph* const parent; LimitedCall limitedCall; + void numChannelsChanged() override; + JUCE_DECLARE_WEAK_REFERENCEABLE(SourceRecordProcessor) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SourceRecordProcessor) }; diff --git a/src/audioCore/misc/RecordTemp.cpp b/src/audioCore/misc/RecordTemp.cpp index 58c5ca1a..143d34fd 100644 --- a/src/audioCore/misc/RecordTemp.cpp +++ b/src/audioCore/misc/RecordTemp.cpp @@ -1,8 +1,94 @@ #include "RecordTemp.h" +#include "VMath.h" + +#define AUDIO_BUFFER_MIN 48000 * 30 + +RecordTemp::RecordTemp() { + /** Init Audio Buffer */ + this->clearAudio(); +} + +void RecordTemp::setInputSampleRate(double sampleRate) { + juce::GenericScopedLock locker(this->lock); + this->sampleRate = sampleRate; + this->clearAll(); +} + +void RecordTemp::setInputChannelNum(int channels) { + juce::GenericScopedLock locker(this->lock); + this->audioBuffer.setSize(channels, + this->audioBuffer.getNumSamples(), true, true, true); +} void RecordTemp::recordData(double timeSec, const juce::AudioBuffer& buffer, const juce::MidiBuffer& midiMessages) { - /** TODO */ + /** Lock */ + juce::GenericScopedLock locker(this->lock); + + /** Set Start Time */ + if (timeSec < this->startTime) { + this->clearAll(); + } + if (this->startTime < 0) { + this->startTime = timeSec; + } + + /** Collect MIDI Message */ + if (this->recordMIDI) { + for (auto i : midiMessages) { + auto message = i.getMessage(); + message.setTimeStamp((timeSec - this->startTime) + message.getTimeStamp() / this->sampleRate); + this->midiCollector.addMessageToQueue(message); + } + } + + /** Write Audio Buffer */ + if (this->recordAudio) { + uint64_t startSample = (timeSec - this->startTime) * this->sampleRate; + uint64_t endSample = startSample + buffer.getNumSamples(); + if (this->tryToEnsureAudioBufferSamplesAllocated(endSample)) { + int channelNum = std::min(buffer.getNumChannels(), this->audioBuffer.getNumChannels()); + for (int i = 0; i < channelNum; i++) { + vMath::copyAudioData(this->audioBuffer, buffer, + (int)startSample, 0, i, i, buffer.getNumSamples()); + } + } + } +} + +void RecordTemp::clearAll() { + juce::GenericScopedLock locker(this->lock); + this->clearAudio(); + this->clearMIDI(); + this->startTime = -1; +} + +void RecordTemp::clearMIDI() { + juce::GenericScopedLock locker(this->lock); + this->midiCollector.reset(sampleRate); +} + +void RecordTemp::clearAudio() { + juce::GenericScopedLock locker(this->lock); + this->audioBuffer.setSize( + this->audioBuffer.getNumChannels(), + AUDIO_BUFFER_MIN, false, true, true); +} + +bool RecordTemp::tryToEnsureAudioBufferSamplesAllocated(uint64_t sampleNum) { + while (this->audioBuffer.getNumSamples() < sampleNum) { + uint16_t num = (uint64_t)(this->audioBuffer.getNumSamples()) * 2; + if (num > INT_MAX) { + this->audioBuffer.setSize(this->audioBuffer.getNumChannels(), + INT_MAX, false, true, true); + break; + } + + this->audioBuffer.setSize(this->audioBuffer.getNumChannels(), + (int)num, false, true, true); + } + + return this->audioBuffer.getNumSamples() >= sampleNum; } RecordTemp* RecordTemp::getInstance() { diff --git a/src/audioCore/misc/RecordTemp.h b/src/audioCore/misc/RecordTemp.h index c9243e51..dc9c2ec0 100644 --- a/src/audioCore/misc/RecordTemp.h +++ b/src/audioCore/misc/RecordTemp.h @@ -4,11 +4,29 @@ class RecordTemp final : private juce::DeletedAtShutdown { public: - RecordTemp() = default; + RecordTemp(); + void setInputSampleRate(double sampleRate); + void setInputChannelNum(int channels); void recordData(double timeSec, const juce::AudioBuffer& buffer, const juce::MidiBuffer& midiMessages); + void clearAll(); + void clearMIDI(); + void clearAudio(); + +private: + juce::CriticalSection lock; + double sampleRate = 0; + + juce::MidiMessageCollector midiCollector; + juce::AudioSampleBuffer audioBuffer; + double startTime = -1; + + bool recordMIDI = true, recordAudio = true; + + bool tryToEnsureAudioBufferSamplesAllocated(uint64_t sampleNum); + public: static RecordTemp* getInstance(); static void releaseInstance();