Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #23446: Playback artifact when solo-ing instruments (MuseSounds) #26585

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/framework/audio/internal/worker/eventaudiosource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ void EventAudioSource::setIsActive(const bool active)
return;
}

if (m_synth->isActive() == active) {
return;
}

m_synth->setIsActive(active);
m_synth->flushSound();
}
Expand Down
67 changes: 34 additions & 33 deletions src/framework/audio/internal/worker/mixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,12 @@ RetVal<MixerChannelPtr> Mixer::addChannel(const TrackId trackId, ITrackAudioInpu
return;
}

ITrackAudioInputPtr source = std::static_pointer_cast<ITrackAudioInput>(channel->source());

if (channel->muted()) {
if (source) {
source->setIsActive(false);
}
if (m_nonMutedTrackCount != 0) {
m_nonMutedTrackCount--;
}
Expand All @@ -92,8 +97,8 @@ RetVal<MixerChannelPtr> Mixer::addChannel(const TrackId trackId, ITrackAudioInpu

m_nonMutedTrackCount++;

ITrackAudioInputPtr source = std::static_pointer_cast<ITrackAudioInput>(channel->source());
if (source) {
source->setIsActive(isActive());
source->seek(currentTime());
}
});
Expand Down Expand Up @@ -206,26 +211,25 @@ samples_t Mixer::process(float* outBuffer, samples_t samplesPerChannel)

prepareAuxBuffers(outBufferSize);

samples_t masterChannelSampleCount = 0;

for (auto& pair : tracksData) {
const std::vector<float>& trackBuffer = pair.second;

bool outBufferIsSilent = false;
mixOutputFromChannel(outBuffer, trackBuffer.data(), samplesPerChannel, outBufferIsSilent);
masterChannelSampleCount = std::max(samplesPerChannel, masterChannelSampleCount);
auto channelIt = m_trackChannels.find(pair.first);
if (channelIt == m_trackChannels.cend()) {
continue;
}

if (!outBufferIsSilent) {
const MixerChannelPtr channel = channelIt->second;
if (!channel->isSilent()) {
m_isSilence = false;
} else if (m_isSilence) {
continue;
}

const AuxSendsParams& auxSends = m_trackChannels.at(pair.first)->outputParams().auxSends;
writeTrackToAuxBuffers(trackBuffer.data(), auxSends, samplesPerChannel);
const std::vector<float>& trackBuffer = pair.second;
mixOutputFromChannel(outBuffer, trackBuffer.data(), samplesPerChannel);
writeTrackToAuxBuffers(trackBuffer.data(), channel->outputParams().auxSends, samplesPerChannel);
}

if (m_masterParams.muted || masterChannelSampleCount == 0 || m_isSilence) {
if (m_masterParams.muted || samplesPerChannel == 0 || m_isSilence) {
notifyNoAudioSignal();
return 0;
}
Expand All @@ -239,7 +243,7 @@ samples_t Mixer::process(float* outBuffer, samples_t samplesPerChannel)
}
}

return masterChannelSampleCount;
return samplesPerChannel;
}

void Mixer::processTrackChannels(size_t outBufferSize, size_t samplesPerChannel, TracksData& outTracksData)
Expand Down Expand Up @@ -272,7 +276,7 @@ void Mixer::processTrackChannels(size_t outBufferSize, size_t samplesPerChannel,
continue;
}

if (pair.second->muted()) {
if (pair.second->muted() && pair.second->isSilent()) {
pair.second->notifyNoAudioSignal();
continue;
}
Expand All @@ -290,7 +294,7 @@ void Mixer::processTrackChannels(size_t outBufferSize, size_t samplesPerChannel,
continue;
}

if (pair.second->muted()) {
if (pair.second->muted() && pair.second->isSilent()) {
pair.second->notifyNoAudioSignal();
continue;
}
Expand Down Expand Up @@ -321,8 +325,16 @@ void Mixer::setIsActive(bool arg)

AbstractAudioSource::setIsActive(arg);

for (const auto& channel : m_trackChannels) {
channel.second->setIsActive(arg);
for (auto& channel : m_trackChannels) {
if (!channel.second->muted()) {
channel.second->setIsActive(arg);
}
}

for (auto& aux : m_auxChannelInfoList) {
if (!aux.channel->muted()) {
aux.channel->setIsActive(arg);
}
}
}

Expand Down Expand Up @@ -429,14 +441,12 @@ void Mixer::setTracksToProcessWhenIdle(std::unordered_set<TrackId>&& trackIds)
m_tracksToProcessWhenIdle = std::move(trackIds);
}

void Mixer::mixOutputFromChannel(float* outBuffer, const float* inBuffer, unsigned int samplesCount, bool& outBufferIsSilent)
void Mixer::mixOutputFromChannel(float* outBuffer, const float* inBuffer, unsigned int samplesCount) const
{
IF_ASSERT_FAILED(outBuffer && inBuffer) {
return;
}

outBufferIsSilent = true;

if (m_masterParams.muted) {
return;
}
Expand All @@ -448,10 +458,6 @@ void Mixer::mixOutputFromChannel(float* outBuffer, const float* inBuffer, unsign
size_t idx = samplePos + audioChNum;
float sample = inBuffer[idx];
outBuffer[idx] += sample;

if (outBufferIsSilent && !RealIsNull(sample)) {
outBufferIsSilent = false;
}
}
}
}
Expand Down Expand Up @@ -516,8 +522,9 @@ void Mixer::processAuxChannels(float* buffer, samples_t samplesPerChannel)
float* auxBuffer = aux.buffer.data();
aux.channel->process(auxBuffer, samplesPerChannel);

static bool isSilent = false;
mixOutputFromChannel(buffer, auxBuffer, samplesPerChannel, isSilent);
if (!aux.channel->isSilent()) {
mixOutputFromChannel(buffer, auxBuffer, samplesPerChannel);
}
}
}

Expand All @@ -527,14 +534,11 @@ void Mixer::completeOutput(float* buffer, samples_t samplesPerChannel)
return;
}

m_isSilence = true;

float totalSquaredSum = 0.f;
float volume = muse::db_to_linear(m_masterParams.volume);

for (audioch_t audioChNum = 0; audioChNum < m_audioChannelsCount; ++audioChNum) {
float singleChannelSquaredSum = 0.f;

gain_t totalGain = dsp::balanceGain(m_masterParams.balance, audioChNum) * volume;

for (samples_t s = 0; s < samplesPerChannel; ++s) {
Expand All @@ -543,10 +547,6 @@ void Mixer::completeOutput(float* buffer, samples_t samplesPerChannel)
float resultSample = buffer[idx] * totalGain;
buffer[idx] = resultSample;

if (m_isSilence && !RealIsNull(resultSample)) {
m_isSilence = false;
}

float squaredSample = resultSample * resultSample;
totalSquaredSum += squaredSample;
singleChannelSquaredSum += squaredSample;
Expand All @@ -556,6 +556,7 @@ void Mixer::completeOutput(float* buffer, samples_t samplesPerChannel)
m_audioSignalNotifier.updateSignalValues(audioChNum, rms);
}

m_isSilence = RealIsNull(totalSquaredSum);
m_audioSignalNotifier.notifyAboutChanges();

if (!m_limiter->isActive()) {
Expand Down
2 changes: 1 addition & 1 deletion src/framework/audio/internal/worker/mixer.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class Mixer : public AbstractAudioSource, public Injectable, public async::Async
using TracksData = std::map<TrackId, std::vector<float> >;

void processTrackChannels(size_t outBufferSize, size_t samplesPerChannel, TracksData& outTracksData);
void mixOutputFromChannel(float* outBuffer, const float* inBuffer, unsigned int samplesCount, bool& outBufferIsSilent);
void mixOutputFromChannel(float* outBuffer, const float* inBuffer, unsigned int samplesCount) const;
void prepareAuxBuffers(size_t outBufferSize);
void writeTrackToAuxBuffers(const float* trackBuffer, const AuxSendsParams& auxSends, samples_t samplesPerChannel);
void processAuxChannels(float* buffer, samples_t samplesPerChannel);
Expand Down
16 changes: 12 additions & 4 deletions src/framework/audio/internal/worker/mixerchannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,13 @@ samples_t MixerChannel::process(float* buffer, samples_t samplesPerChannel)

samples_t processedSamplesCount = samplesPerChannel;

if (m_audioSource && !m_params.muted) {
processedSamplesCount = m_audioSource->process(buffer, samplesPerChannel);
if (m_audioSource) {
if (!m_params.muted || !m_isSilent) {
processedSamplesCount = m_audioSource->process(buffer, samplesPerChannel);
}
}

if (processedSamplesCount == 0 || m_params.muted) {
if (processedSamplesCount == 0 || (m_params.muted && m_isSilent)) {
std::fill(buffer, buffer + samplesPerChannel * audioChannelsCount(), 0.f);
notifyNoAudioSignal();

Expand All @@ -215,7 +217,7 @@ samples_t MixerChannel::process(float* buffer, samples_t samplesPerChannel)
return processedSamplesCount;
}

void MixerChannel::completeOutput(float* buffer, unsigned int samplesCount) const
void MixerChannel::completeOutput(float* buffer, unsigned int samplesCount)
{
unsigned int channelsCount = audioChannelsCount();
float volume = muse::db_to_linear(m_params.volume);
Expand All @@ -241,6 +243,7 @@ void MixerChannel::completeOutput(float* buffer, unsigned int samplesCount) cons
m_audioSignalNotifier.updateSignalValues(audioChNum, rms);
}

m_isSilent = RealIsNull(totalSquaredSum);
m_audioSignalNotifier.notifyAboutChanges();

if (!m_compressor->isActive()) {
Expand All @@ -251,6 +254,11 @@ void MixerChannel::completeOutput(float* buffer, unsigned int samplesCount) cons
m_compressor->process(totalRms, buffer, channelsCount, samplesCount);
}

bool MixerChannel::isSilent() const
{
return m_isSilent;
}

void MixerChannel::notifyNoAudioSignal()
{
unsigned int channelsCount = audioChannelsCount();
Expand Down
6 changes: 5 additions & 1 deletion src/framework/audio/internal/worker/mixerchannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class MixerChannel : public ITrackAudioOutput, public Injectable, public async::
bool muted() const;
async::Notification mutedChanged() const;

bool isSilent() const;

void notifyNoAudioSignal();

const AudioOutputParams& outputParams() const override;
Expand All @@ -65,7 +67,7 @@ class MixerChannel : public ITrackAudioOutput, public Injectable, public async::
samples_t process(float* buffer, samples_t samplesPerChannel) override;

private:
void completeOutput(float* buffer, unsigned int samplesCount) const;
void completeOutput(float* buffer, unsigned int samplesCount);

TrackId m_trackId = -1;

Expand All @@ -78,6 +80,8 @@ class MixerChannel : public ITrackAudioOutput, public Injectable, public async::

dsp::CompressorPtr m_compressor = nullptr;

bool m_isSilent = true;

async::Notification m_mutedChanged;
mutable async::Channel<AudioOutputParams> m_paramsChanges;
mutable AudioSignalsNotifier m_audioSignalNotifier;
Expand Down
23 changes: 5 additions & 18 deletions src/framework/audio/internal/worker/sequenceplayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ SequencePlayer::SequencePlayer(IGetTracks* getTracks, IClockPtr clock, const mod
});

m_clock->statusChanged().onReceive(this, [this](const PlaybackStatus status) {
setAllTracksActive(status == PlaybackStatus::Running);
audioEngine()->mixer()->setIsActive(status == PlaybackStatus::Running);
});
}

Expand All @@ -48,7 +48,7 @@ void SequencePlayer::play()

audioEngine()->setMode(RenderMode::RealTimeMode);
m_clock->start();
setAllTracksActive(true);
audioEngine()->mixer()->setIsActive(true);
}

void SequencePlayer::seek(const secs_t newPosition)
Expand All @@ -66,7 +66,7 @@ void SequencePlayer::stop()

audioEngine()->setMode(RenderMode::IdleMode);
m_clock->stop();
setAllTracksActive(false);
audioEngine()->mixer()->setIsActive(false);
}

void SequencePlayer::pause()
Expand All @@ -75,7 +75,7 @@ void SequencePlayer::pause()

audioEngine()->setMode(RenderMode::IdleMode);
m_clock->pause();
setAllTracksActive(false);
audioEngine()->mixer()->setIsActive(false);
}

void SequencePlayer::resume()
Expand All @@ -84,7 +84,7 @@ void SequencePlayer::resume()

audioEngine()->setMode(RenderMode::RealTimeMode);
m_clock->resume();
setAllTracksActive(true);
audioEngine()->mixer()->setIsActive(true);
}

msecs_t SequencePlayer::duration() const
Expand Down Expand Up @@ -147,19 +147,6 @@ Channel<PlaybackStatus> SequencePlayer::playbackStatusChanged() const
return m_clock->statusChanged();
}

void SequencePlayer::setAllTracksActive(bool active)
{
IF_ASSERT_FAILED(m_getTracks) {
return;
}

for (const auto& pair : m_getTracks->allTracks()) {
if (pair.second->inputHandler) {
pair.second->inputHandler->setIsActive(active);
}
}
}

void SequencePlayer::seekAllTracks(const msecs_t newPositionMsecs)
{
IF_ASSERT_FAILED(m_getTracks) {
Expand Down
1 change: 0 additions & 1 deletion src/framework/audio/internal/worker/sequenceplayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ class SequencePlayer : public ISequencePlayer, public Injectable, public async::
async::Channel<secs_t> playbackPositionChanged() const override;

private:
void setAllTracksActive(bool active);
void seekAllTracks(const msecs_t newPositionMsecs);

IGetTracks* m_getTracks = nullptr;
Expand Down
4 changes: 2 additions & 2 deletions src/framework/vst/internal/vstaudioclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ bool VstAudioClient::fillOutputBufferInstrument(samples_t sampleCount, float* ou
float sample = bus.channelBuffers32[audioChannelIndex][sampleIndex];
output[offset + audioChannelIndex] += sample * m_volumeGain;

if (isSilence && !RealIsNull(sample)) {
if (isSilence && sample != 0.f) {
isSilence = false;
}
}
Expand Down Expand Up @@ -450,7 +450,7 @@ bool VstAudioClient::fillOutputBufferFx(samples_t sampleCount, float* output)
float sample = bus.channelBuffers32[audioChannelIndex][sampleIndex];
output[offset + audioChannelIndex] = sample * m_volumeGain;

if (isSilence && !RealIsNull(sample)) {
if (isSilence && sample != 0.f) {
isSilence = false;
}
}
Expand Down
Loading