Skip to content

Commit

Permalink
Fixed sss noise in audio source
Browse files Browse the repository at this point in the history
  • Loading branch information
FangCunWuChang committed Jan 10, 2024
1 parent a02d694 commit e212fc0
Show file tree
Hide file tree
Showing 13 changed files with 91 additions and 53 deletions.
9 changes: 8 additions & 1 deletion src/audioCore/graph/MainGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,13 @@ void MainGraph::processBlock(juce::AudioBuffer<float>& audio, juce::MidiBuffer&

/** Add Position */
if (auto position = dynamic_cast<PlayPosition*>(this->getPlayHead())) {
position->next(audio.getNumSamples());
int currentPos = position->getPosition()->getTimeInSamples().orFallback(0);
if (INT_MAX - audio.getNumSamples() > currentPos) {
position->next(audio.getNumSamples());
}
else {
/** Time Overflow */
position->setOverflow();
}
}
}
50 changes: 28 additions & 22 deletions src/audioCore/graph/SeqSourceProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ void SeqSourceProcessor::processBlock(
double duration = buffer.getNumSamples() / sampleRate;
double endTime = startTime + duration;

int startTimeInSample = position->getTimeInSamples().orFallback(-1);
int durationInSample = buffer.getNumSamples();
int endTimeInSample = startTimeInSample + durationInSample;

/** Copy Source Data */
{
juce::ScopedTryReadLock managerLocker(CloneableSourceManager::getInstance()->getLock());
Expand All @@ -107,40 +111,42 @@ void SeqSourceProcessor::processBlock(
for (int i = std::get<0>(index);
i <= std::get<1>(index) && i < this->srcs.size() && i >= 0; i++) {
/** Get Block */
auto block = this->srcs.getUnchecked(i);
auto [blockStartTime, blockEndTime, blockOffset, blockPointer, blockIndex] = this->srcs.getUnchecked(i);
int blockStartTimeInSample = blockStartTime * sampleRate;
int blockEndTimeInSample = blockEndTime * sampleRate;
int blockOffsetInSample = blockOffset * sampleRate;

if (CloneableSource::SafePointer<> ptr = std::get<3>(block)) {
if (CloneableSource::SafePointer<> ptr = blockPointer) {
/** Caculate Time */
double dataStartTime = std::get<0>(block) + std::max(std::get<2>(block), 0.);
double dataEndTime =
std::min(std::get<1>(block), std::get<0>(block) + std::get<2>(block) + ptr->getSourceLength());
int blockLengthInSample = ptr->getSourceLength() * sampleRate;
int dataStartTimeInSample = blockStartTimeInSample + std::max(blockOffsetInSample, 0);
int dataEndTimeInSample =
std::min(blockEndTimeInSample, blockStartTimeInSample + blockOffsetInSample + blockLengthInSample);

if (dataEndTimeInSample > dataStartTimeInSample) {
int hotStartTimeInSample = std::max(startTimeInSample, dataStartTimeInSample);
int hotEndTimeInSample = std::min(endTimeInSample, dataEndTimeInSample);

if (dataEndTime > dataStartTime) {
double hotStartTime = std::max(startTime, dataStartTime);
double hotEndTime = std::min(endTime, dataEndTime);
if (hotEndTimeInSample > hotStartTimeInSample) {
int dataTimeInSample = blockStartTimeInSample + blockOffsetInSample;
int bufferOffsetInSample = hotStartTimeInSample - startTimeInSample;
int hotOffsetInSample = hotStartTimeInSample - dataTimeInSample;
int hotLengthInSample = hotEndTimeInSample - hotStartTimeInSample;

if (hotEndTime > hotStartTime) {
if (auto p = dynamic_cast<CloneableAudioSource*>(ptr.getSource())) {
/** Copy Audio Data */
p->readData(buffer,
hotStartTime - startTime,
hotStartTime - (std::get<0>(block) + std::get<2>(block)),
hotEndTime - hotStartTime);
p->readData(buffer, bufferOffsetInSample, hotOffsetInSample, hotLengthInSample);
}
else if (auto p = dynamic_cast<CloneableSynthSource*>(ptr.getSource())) {
/** Copy Audio Data */
p->readData(buffer,
hotStartTime - startTime,
hotStartTime - (std::get<0>(block) + std::get<2>(block)),
hotEndTime - hotStartTime);
p->readData(buffer, bufferOffsetInSample, hotOffsetInSample, hotLengthInSample);
}
else if (auto p = dynamic_cast<CloneableMIDISource*>(ptr.getSource())) {
/** Copy MIDI Message */
double dataTime = std::get<0>(block) + std::get<2>(block);
p->readData(midiMessages,
dataTime - startTime,
hotStartTime - dataTime,
hotEndTime - dataTime);
p->readData(midiMessages,
dataTimeInSample - startTimeInSample,
hotOffsetInSample,
hotEndTimeInSample - dataTimeInSample);
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/audioCore/graph/SourceList.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ class SourceList final : public Serializable {
public:
SourceList() = default;

/**
* StartTime, EndTime, Offset, Pointer, Index.
*/
using SeqBlock = std::tuple<
double, double, double,
CloneableSource::SafePointer<>, int>;
Expand Down
15 changes: 15 additions & 0 deletions src/audioCore/misc/PlayPosition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ void MovablePlayHead::transportPlay(bool shouldStartPlaying) {
this->position.setIsPlaying(shouldStartPlaying);
if (!shouldStartPlaying) {
this->position.setIsRecording(false);
this->overflowFlag = false;
}

UICallbackAPI<bool>::invoke(
Expand All @@ -54,6 +55,7 @@ void MovablePlayHead::transportRewind() {
this->position.setBarCount(0);
this->position.setPpqPositionOfLastBarStart(0);
this->position.setPpqPosition(0);
this->overflowFlag = false;
}

void MovablePlayHead::setTimeFormat(short ticksPerQuarter) {
Expand Down Expand Up @@ -149,6 +151,19 @@ juce::MidiMessageSequence& MovablePlayHead::getTempoSequence() {
return this->tempos;
}

double MovablePlayHead::getSampleRate() const {
juce::ScopedReadLock locker(this->lock);
return this->sampleRate;
}

void MovablePlayHead::setOverflow() {
this->overflowFlag = true;
}

bool MovablePlayHead::checkOverflow() const {
return this->overflowFlag;
}

void MovablePlayHead::updatePositionByTimeInSecond() {
double time = this->position.getTimeInSeconds().orFallback(0);
this->position.setTimeInSamples((int64_t)std::floor(time * this->sampleRate));
Expand Down
7 changes: 6 additions & 1 deletion src/audioCore/misc/PlayPosition.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#pragma once
#pragma once

#include <JuceHeader.h>

Expand Down Expand Up @@ -33,12 +33,17 @@ class MovablePlayHead : public juce::AudioPlayHead {
std::tuple<int, double> toBar(double timeSecond, short timeFormat) const;

juce::MidiMessageSequence& getTempoSequence();
double getSampleRate() const;

void setOverflow();
bool checkOverflow() const;

protected:
mutable juce::AudioPlayHead::PositionInfo position;
juce::MidiMessageSequence tempos;
std::atomic_short timeFormat = 480;
std::atomic<double> sampleRate = 48000;
std::atomic_bool overflowFlag = false;
juce::ReadWriteLock lock;

void updatePositionByTimeInSecond();
Expand Down
5 changes: 3 additions & 2 deletions src/audioCore/misc/PlayWatcher.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "PlayWatcher.h"
#include "PlayWatcher.h"

#include "PlayPosition.h"
#include "../AudioCore.h"
Expand All @@ -12,7 +12,8 @@ void PlayWatcher::timerCallback() {
auto playPosition = PlayPosition::getInstance()->getPosition();
if (playPosition->getIsPlaying() && !playPosition->getIsRecording()) {
if (auto mainGraph = AudioCore::getInstance()->getGraph()) {
if (playPosition->getTimeInSeconds() > mainGraph->getTailLengthSeconds()) {
if ((playPosition->getTimeInSeconds() > mainGraph->getTailLengthSeconds())
|| PlayPosition::getInstance()->checkOverflow()) {
AudioCore::getInstance()->pause();
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/audioCore/misc/Renderer.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "Renderer.h"
#include "Renderer.h"

#include "../AudioCore.h"
#include "../Utils.h"
Expand Down Expand Up @@ -76,6 +76,7 @@ void RenderThread::run() {

/** Get Total Time */
double totalLength = mainGraph->getTailLengthSeconds();
totalLength = std::min(totalLength, INT_MAX / PlayPosition::getInstance()->getSampleRate());

/** Reset Play Position */
PlayPosition::getInstance()->setPositionInSamples(0);
Expand Down
12 changes: 6 additions & 6 deletions src/audioCore/source/CloneableAudioSource.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "CloneableAudioSource.h"
#include "CloneableAudioSource.h"

#include "../Utils.h"
#include <VSP4.h>
Expand All @@ -8,19 +8,19 @@ double CloneableAudioSource::getSourceSampleRate() const {
return this->sourceSampleRate;
}

void CloneableAudioSource::readData(juce::AudioBuffer<float>& buffer, double bufferOffset,
double dataOffset, double length) const {
void CloneableAudioSource::readData(juce::AudioBuffer<float>& buffer, int bufferOffset,
int dataOffset, int length) const {
if (this->checkRecording()) { return; }
if (buffer.getNumSamples() <= 0 || length <= 0) { return; }

juce::ScopedTryReadLock locker(this->lock);
if (locker.isLocked()) {
if (this->source && this->memorySource) {
this->memorySource->setNextReadPosition(std::floor(dataOffset * this->sourceSampleRate));
int startSample = (int)std::floor(bufferOffset * this->getSampleRate());
this->memorySource->setNextReadPosition((int64_t)(dataOffset * this->source->getResamplingRatio()));
int startSample = bufferOffset;
this->source->getNextAudioBlock(juce::AudioSourceChannelInfo{
&buffer, startSample,
std::min(buffer.getNumSamples() - startSample, (int)std::ceil(length * this->getSampleRate()))});/**< Ceil then min with buffer size to ensure audio data fill the last point in buffer */
std::min(buffer.getNumSamples() - startSample, length)});
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/audioCore/source/CloneableAudioSource.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#pragma once
#pragma once

#include <JuceHeader.h>
#include "CloneableSource.h"
Expand All @@ -10,8 +10,8 @@ class CloneableAudioSource final : public CloneableSource {

double getSourceSampleRate() const;

void readData(juce::AudioBuffer<float>& buffer, double bufferOffset,
double dataOffset, double length) const;
void readData(juce::AudioBuffer<float>& buffer, int bufferOffset,
int dataOffset, int length) const;
int getChannelNum() const;

public:
Expand Down
10 changes: 5 additions & 5 deletions src/audioCore/source/CloneableMIDISource.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#include "CloneableMIDISource.h"
#include "CloneableMIDISource.h"

#include "../Utils.h"
#include <VSP4.h>
using namespace org::vocalsharp::vocalshaper;

void CloneableMIDISource::readData(
juce::MidiBuffer& buffer, double baseTime,
double startTime, double endTime) const {
juce::MidiBuffer& buffer, int baseTime,
int startTime, int endTime) const {
if (this->checkRecording()) { return; }

juce::ScopedTryReadLock locker(this->lock);
Expand All @@ -17,15 +17,15 @@ void CloneableMIDISource::readData(
for (int i = 0; i < this->buffer.getNumTracks(); i++) {
auto track = this->buffer.getTrack(i);
if (track) {
total.addSequence(*track, 0, startTime, endTime);
total.addSequence(*track, 0, startTime / this->getSampleRate(), endTime / this->getSampleRate());
}
}

/** Copy Data */
for (auto i : total) {
auto& message = i->message;
double time = message.getTimeStamp();
buffer.addEvent(message, std::floor((time + baseTime) * this->getSampleRate()));
buffer.addEvent(message, std::floor((time + baseTime / this->getSampleRate()) * this->getSampleRate()));
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/audioCore/source/CloneableMIDISource.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#pragma once
#pragma once

#include <JuceHeader.h>
#include "CloneableSource.h"
Expand All @@ -9,8 +9,8 @@ class CloneableMIDISource final : public CloneableSource {
~CloneableMIDISource() override = default;

void readData(
juce::MidiBuffer& buffer, double baseTime,
double startTime, double endTime) const;
juce::MidiBuffer& buffer, int baseTime,
int startTime, int endTime) const;
int getTrackNum() const;

public:
Expand Down
12 changes: 6 additions & 6 deletions src/audioCore/source/CloneableSynthSource.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "CloneableSynthSource.h"
#include "CloneableSynthSource.h"

#include <DMDA.h>
#include "../Utils.h"
Expand All @@ -18,19 +18,19 @@ double CloneableSynthSource::getSourceSampleRate() const {
return this->sourceSampleRate;
}

void CloneableSynthSource::readData(juce::AudioBuffer<float>& buffer, double bufferOffset,
double dataOffset, double length) const {
void CloneableSynthSource::readData(juce::AudioBuffer<float>& buffer, int bufferOffset,
int dataOffset, int length) const {
if (this->checkRecording()) { return; }
if (buffer.getNumSamples() <= 0 || length <= 0) { return; }

juce::ScopedTryReadLock locker(this->audioLock);
if (locker.isLocked()) {
if (this->source && this->memorySource) {
this->memorySource->setNextReadPosition(std::floor(dataOffset * this->sourceSampleRate));
int startSample = (int)std::floor(bufferOffset * this->getSampleRate());
this->memorySource->setNextReadPosition((int64_t)(dataOffset * this->source->getResamplingRatio()));
int startSample = bufferOffset;
this->source->getNextAudioBlock(juce::AudioSourceChannelInfo{
&buffer, startSample,
std::min(buffer.getNumSamples() - startSample, (int)std::ceil(length * this->getSampleRate()))});/**< Ceil then min with buffer size to ensure audio data fill the last point in buffer */
std::min(buffer.getNumSamples() - startSample, length)});
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/audioCore/source/CloneableSynthSource.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#pragma once
#pragma once

#include <JuceHeader.h>
#include "CloneableSource.h"
Expand All @@ -12,8 +12,8 @@ class CloneableSynthSource final : public CloneableSource {
int getTrackNum() const;

double getSourceSampleRate() const;
void readData(juce::AudioBuffer<float>& buffer, double bufferOffset,
double dataOffset, double length) const;
void readData(juce::AudioBuffer<float>& buffer, int bufferOffset,
int dataOffset, int length) const;
int getChannelNum() const;

void setSynthesizer(
Expand Down

0 comments on commit e212fc0

Please sign in to comment.