Skip to content

Commit b0b7888

Browse files
VST: optimize audio client init
1 parent 4d159fc commit b0b7888

File tree

6 files changed

+95
-135
lines changed

6 files changed

+95
-135
lines changed

src/framework/vst/internal/fx/vstfxprocessor.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* MuseScore
66
* Music Composition & Notation
77
*
8-
* Copyright (C) 2021 MuseScore Limited and others
8+
* Copyright (C) 2025 MuseScore Limited and others
99
*
1010
* This program is free software: you can redistribute it and/or modify
1111
* it under the terms of the GNU General Public License version 3 as
@@ -46,8 +46,7 @@ void VstFxProcessor::init(const audio::OutputSpec& spec)
4646

4747
auto onPluginLoaded = [this]() {
4848
m_pluginPtr->updatePluginConfig(m_params.configuration);
49-
m_vstAudioClient->setSampleRate(m_outputSpec.sampleRate);
50-
m_vstAudioClient->setMaxSamplesPerBlock(m_outputSpec.samplesPerChannel);
49+
m_vstAudioClient->setOutputSpec(m_outputSpec);
5150
m_inited = true;
5251
};
5352

@@ -85,7 +84,7 @@ async::Channel<AudioFxParams> VstFxProcessor::paramsChanged() const
8584
void VstFxProcessor::setOutputSpec(const audio::OutputSpec& spec)
8685
{
8786
m_outputSpec = spec;
88-
m_vstAudioClient->setSampleRate(spec.sampleRate);
87+
m_vstAudioClient->setOutputSpec(spec);
8988
}
9089

9190
bool VstFxProcessor::active() const

src/framework/vst/internal/fx/vstfxprocessor.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* MuseScore
66
* Music Composition & Notation
77
*
8-
* Copyright (C) 2021 MuseScore Limited and others
8+
* Copyright (C) 2025 MuseScore Limited and others
99
*
1010
* This program is free software: you can redistribute it and/or modify
1111
* it under the terms of the GNU General Public License version 3 as
@@ -19,8 +19,8 @@
1919
* You should have received a copy of the GNU General Public License
2020
* along with this program. If not, see <https://www.gnu.org/licenses/>.
2121
*/
22-
#ifndef MUSE_VST_VSTFXPROCESSOR_H
23-
#define MUSE_VST_VSTFXPROCESSOR_H
22+
23+
#pragma once
2424

2525
#include <memory>
2626

@@ -61,5 +61,3 @@ class VstFxProcessor : public muse::audio::IFxProcessor, public async::Asyncable
6161

6262
using VstFxPtr = std::shared_ptr<VstFxProcessor>;
6363
}
64-
65-
#endif // MUSE_VST_VSTFXPROCESSOR_H

src/framework/vst/internal/synth/vstsynthesiser.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* MuseScore
66
* Music Composition & Notation
77
*
8-
* Copyright (C) 2021 MuseScore Limited and others
8+
* Copyright (C) 2025 MuseScore Limited and others
99
*
1010
* This program is free software: you can redistribute it and/or modify
1111
* it under the terms of the GNU General Public License version 3 as
@@ -60,12 +60,11 @@ void VstSynthesiser::init(const OutputSpec& spec)
6060

6161
m_pluginPtr = instancesRegister()->makeAndRegisterInstrPlugin(m_params.resourceMeta.id, m_trackId);
6262

63-
m_vstAudioClient->init(AudioPluginType::Instrument, m_pluginPtr, m_outputSpec.audioChannelCount);
63+
m_vstAudioClient->init(AudioPluginType::Instrument, m_pluginPtr);
6464

6565
auto onPluginLoaded = [this]() {
6666
m_pluginPtr->updatePluginConfig(m_params.configuration);
67-
m_vstAudioClient->setSampleRate(m_outputSpec.sampleRate);
68-
m_vstAudioClient->setMaxSamplesPerBlock(m_outputSpec.samplesPerChannel);
67+
m_vstAudioClient->setOutputSpec(m_outputSpec);
6968
m_vstAudioClient->loadSupportedParams();
7069
m_sequencer.init(m_vstAudioClient->paramsMapping(SUPPORTED_CONTROLLERS), m_useDynamicEvents);
7170
};
@@ -183,7 +182,7 @@ void VstSynthesiser::setPlaybackPosition(const muse::audio::msecs_t newPosition)
183182
void VstSynthesiser::setOutputSpec(const audio::OutputSpec& spec)
184183
{
185184
m_outputSpec = spec;
186-
m_vstAudioClient->setSampleRate(spec.sampleRate);
185+
m_vstAudioClient->setOutputSpec(spec);
187186
}
188187

189188
unsigned int VstSynthesiser::audioChannelsCount() const
@@ -202,10 +201,6 @@ samples_t VstSynthesiser::process(float* buffer, samples_t samplesPerChannel)
202201
return 0;
203202
}
204203

205-
if (samplesPerChannel > m_vstAudioClient->maxSamplesPerBlock()) {
206-
m_vstAudioClient->setMaxSamplesPerBlock(samplesPerChannel);
207-
}
208-
209204
const msecs_t nextMsecs = samplesToMsecs(samplesPerChannel, m_outputSpec.sampleRate);
210205
const VstSequencer::EventSequenceMap sequences = m_sequencer.movePlaybackForward(nextMsecs);
211206

src/framework/vst/internal/synth/vstsynthesiser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* MuseScore
66
* Music Composition & Notation
77
*
8-
* Copyright (C) 2021 MuseScore Limited and others
8+
* Copyright (C) 2025 MuseScore Limited and others
99
*
1010
* This program is free software: you can redistribute it and/or modify
1111
* it under the terms of the GNU General Public License version 3 as

src/framework/vst/internal/vstaudioclient.cpp

Lines changed: 76 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* MuseScore
66
* Music Composition & Notation
77
*
8-
* Copyright (C) 2021 MuseScore Limited and others
8+
* Copyright (C) 2025 MuseScore Limited and others
99
*
1010
* This program is free software: you can redistribute it and/or modify
1111
* it under the terms of the GNU General Public License version 3 as
@@ -46,15 +46,14 @@ VstAudioClient::~VstAudioClient()
4646
m_pluginComponent->terminate();
4747
}
4848

49-
void VstAudioClient::init(AudioPluginType type, IVstPluginInstancePtr instance, audioch_t audioChannelsCount)
49+
void VstAudioClient::init(AudioPluginType type, IVstPluginInstancePtr instance)
5050
{
5151
IF_ASSERT_FAILED(instance && type != AudioPluginType::Undefined) {
5252
return;
5353
}
5454

5555
m_type = type;
5656
m_pluginPtr = std::move(instance);
57-
m_audioChannelsCount = audioChannelsCount;
5857
}
5958

6059
void VstAudioClient::loadSupportedParams()
@@ -90,6 +89,36 @@ void VstAudioClient::setIsActive(const bool isActive)
9089
}
9190
}
9291

92+
void VstAudioClient::setOutputSpec(const audio::OutputSpec& spec)
93+
{
94+
if (m_outputSpec == spec) {
95+
return;
96+
}
97+
98+
m_processData.numSamples = static_cast<Steinberg::int32>(spec.samplesPerChannel);
99+
m_outputSpec = spec;
100+
m_needUnprepareProcessData = true;
101+
102+
updateProcessSetup();
103+
}
104+
105+
void VstAudioClient::setProcessMode(VstProcessMode mode)
106+
{
107+
if (m_processMode == mode) {
108+
return;
109+
}
110+
111+
m_processMode = mode;
112+
m_needUnprepareProcessData = true;
113+
114+
updateProcessSetup();
115+
}
116+
117+
void VstAudioClient::setVolumeGain(const muse::audio::gain_t newVolumeGain)
118+
{
119+
m_volumeGain = newVolumeGain;
120+
}
121+
93122
bool VstAudioClient::handleEvent(const VstEvent& event)
94123
{
95124
ensureActivity();
@@ -119,58 +148,6 @@ bool VstAudioClient::handleParamChange(const ParamChangeEvent& param)
119148
return true;
120149
}
121150

122-
void VstAudioClient::setVolumeGain(const muse::audio::gain_t newVolumeGain)
123-
{
124-
m_volumeGain = newVolumeGain;
125-
}
126-
127-
muse::audio::samples_t VstAudioClient::process(float* output, muse::audio::samples_t samplesPerChannel,
128-
muse::audio::msecs_t playbackPosition)
129-
{
130-
IAudioProcessorPtr processor = pluginProcessor();
131-
if (!processor || !output) {
132-
return 0;
133-
}
134-
135-
if (!m_isActive) {
136-
return 0;
137-
}
138-
139-
//! NOTE: From the VST3 documentation:
140-
//!
141-
//! Note that the ProcessData->numSamples
142-
//! which indicates how many samples are used in a process call can change from call to call,
143-
//! but never bigger than the maxSamplesPerBlock
144-
m_processData.numSamples = samplesPerChannel;
145-
146-
m_processContext.projectTimeSamples = (playbackPosition / 1000000.f) * m_samplesInfo.sampleRate;
147-
148-
if (samplesPerChannel > m_samplesInfo.maxSamplesPerBlock) {
149-
setMaxSamplesPerBlock(samplesPerChannel);
150-
}
151-
152-
if (m_type == AudioPluginType::Fx) {
153-
extractInputSamples(samplesPerChannel, output);
154-
}
155-
156-
if (processor->process(m_processData) != Steinberg::kResultOk) {
157-
return 0;
158-
}
159-
160-
if (m_type == AudioPluginType::Instrument) {
161-
m_eventList.clear();
162-
m_paramChanges.clearQueue();
163-
164-
if (!fillOutputBufferInstrument(samplesPerChannel, output)) {
165-
return 0;
166-
}
167-
} else if (!fillOutputBufferFx(samplesPerChannel, output)) {
168-
return 0;
169-
}
170-
171-
return samplesPerChannel;
172-
}
173-
174151
void VstAudioClient::flushSound()
175152
{
176153
if (m_playingNotes.empty() && m_playingParams.empty()) {
@@ -217,42 +194,53 @@ void VstAudioClient::flushSound()
217194
m_playingParams.clear();
218195
}
219196

220-
samples_t VstAudioClient::maxSamplesPerBlock() const
197+
muse::audio::samples_t VstAudioClient::process(float* output, muse::audio::samples_t samplesPerChannel,
198+
muse::audio::msecs_t playbackPosition)
221199
{
222-
return m_samplesInfo.maxSamplesPerBlock;
223-
}
200+
IAudioProcessorPtr processor = pluginProcessor();
201+
if (!processor || !output) {
202+
return 0;
203+
}
224204

225-
void VstAudioClient::setMaxSamplesPerBlock(samples_t samples)
226-
{
227-
if (m_samplesInfo.maxSamplesPerBlock == samples) {
228-
return;
205+
if (!m_isActive) {
206+
return 0;
229207
}
230208

231-
m_processData.numSamples = static_cast<Steinberg::int32>(samples);
232-
m_samplesInfo.maxSamplesPerBlock = samples;
233-
m_needUnprepareProcessData = true;
209+
//! NOTE: From the VST3 documentation:
210+
//!
211+
//! Note that the ProcessData->numSamples
212+
//! which indicates how many samples are used in a process call can change from call to call,
213+
//! but never bigger than the maxSamplesPerBlock
214+
m_processData.numSamples = samplesPerChannel;
234215

235-
updateProcessSetup();
236-
}
216+
m_processContext.projectTimeSamples = (playbackPosition / 1000000.f) * m_outputSpec.sampleRate;
237217

238-
void VstAudioClient::setSampleRate(unsigned int sampleRate)
239-
{
240-
if (m_samplesInfo.sampleRate == sampleRate) {
241-
return;
218+
if (samplesPerChannel > m_outputSpec.samplesPerChannel) {
219+
OutputSpec newSpec = m_outputSpec;
220+
newSpec.samplesPerChannel = samplesPerChannel;
221+
setOutputSpec(newSpec);
242222
}
243223

244-
m_samplesInfo.sampleRate = sampleRate;
245-
updateProcessSetup();
246-
}
224+
if (m_type == AudioPluginType::Fx) {
225+
extractInputSamples(samplesPerChannel, output);
226+
}
247227

248-
void VstAudioClient::setProcessMode(VstProcessMode mode)
249-
{
250-
if (m_processMode == mode) {
251-
return;
228+
if (processor->process(m_processData) != Steinberg::kResultOk) {
229+
return 0;
252230
}
253231

254-
m_processMode = mode;
255-
updateProcessSetup();
232+
if (m_type == AudioPluginType::Instrument) {
233+
m_eventList.clear();
234+
m_paramChanges.clearQueue();
235+
236+
if (!fillOutputBufferInstrument(samplesPerChannel, output)) {
237+
return 0;
238+
}
239+
} else if (!fillOutputBufferFx(samplesPerChannel, output)) {
240+
return 0;
241+
}
242+
243+
return samplesPerChannel;
256244
}
257245

258246
ParamsMapping VstAudioClient::paramsMapping(const std::set<Steinberg::Vst::CtrlNumber>& controllers) const
@@ -308,8 +296,7 @@ void VstAudioClient::setUpProcessData()
308296
return;
309297
}
310298

311-
m_processContext.sampleRate = m_samplesInfo.sampleRate;
312-
299+
m_processContext.sampleRate = m_outputSpec.sampleRate;
313300
m_processData.inputEvents = &m_eventList;
314301
m_processData.inputParameterChanges = &m_paramChanges;
315302
m_processData.processContext = &m_processContext;
@@ -320,7 +307,7 @@ void VstAudioClient::setUpProcessData()
320307
}
321308

322309
if (!m_processData.outputs || !m_processData.inputs) {
323-
m_processData.prepare(*component, m_samplesInfo.maxSamplesPerBlock, Steinberg::Vst::kSample32);
310+
m_processData.prepare(*component, m_outputSpec.samplesPerChannel, Steinberg::Vst::kSample32);
324311
}
325312

326313
if (!m_activeOutputBusses.empty() && !m_activeInputBusses.empty()) {
@@ -376,7 +363,7 @@ void VstAudioClient::setUpProcessData()
376363

377364
void VstAudioClient::updateProcessSetup()
378365
{
379-
if (!m_samplesInfo.isValid()) {
366+
if (!m_outputSpec.isValid()) {
380367
return;
381368
}
382369

@@ -390,8 +377,8 @@ void VstAudioClient::updateProcessSetup()
390377
VstProcessSetup setup;
391378
setup.processMode = m_processMode;
392379
setup.symbolicSampleSize = Steinberg::Vst::kSample32;
393-
setup.maxSamplesPerBlock = m_samplesInfo.maxSamplesPerBlock;
394-
setup.sampleRate = m_samplesInfo.sampleRate;
380+
setup.maxSamplesPerBlock = m_outputSpec.samplesPerChannel;
381+
setup.sampleRate = m_outputSpec.sampleRate;
395382

396383
if (processor->setupProcessing(setup) != Steinberg::kResultOk) {
397384
return;
@@ -412,7 +399,7 @@ void VstAudioClient::extractInputSamples(samples_t sampleCount, const float* sou
412399
Steinberg::Vst::AudioBusBuffers& bus = m_processData.inputs[0];
413400

414401
for (samples_t sampleIndex = 0; sampleIndex < sampleCount; ++sampleIndex) {
415-
size_t offset = sampleIndex * m_audioChannelsCount;
402+
size_t offset = sampleIndex * m_outputSpec.audioChannelCount;
416403

417404
for (audioch_t audioChannelIndex = 0; audioChannelIndex < bus.numChannels; ++audioChannelIndex) {
418405
bus.channelBuffers32[audioChannelIndex][sampleIndex] = sourceBuffer[offset + audioChannelIndex];
@@ -432,7 +419,7 @@ bool VstAudioClient::fillOutputBufferInstrument(samples_t sampleCount, float* ou
432419
Steinberg::Vst::AudioBusBuffers bus = m_processData.outputs[busIndex];
433420

434421
for (samples_t sampleIndex = 0; sampleIndex < sampleCount; ++sampleIndex) {
435-
size_t offset = sampleIndex * m_audioChannelsCount;
422+
size_t offset = sampleIndex * m_outputSpec.audioChannelCount;
436423

437424
for (audioch_t audioChannelIndex = 0; audioChannelIndex < bus.numChannels; ++audioChannelIndex) {
438425
float sample = bus.channelBuffers32[audioChannelIndex][sampleIndex];
@@ -460,7 +447,7 @@ bool VstAudioClient::fillOutputBufferFx(samples_t sampleCount, float* output)
460447
Steinberg::Vst::AudioBusBuffers bus = m_processData.outputs[busIndex];
461448

462449
for (samples_t sampleIndex = 0; sampleIndex < sampleCount; ++sampleIndex) {
463-
size_t offset = sampleIndex * m_audioChannelsCount;
450+
size_t offset = sampleIndex * m_outputSpec.audioChannelCount;
464451

465452
for (audioch_t audioChannelIndex = 0; audioChannelIndex < bus.numChannels; ++audioChannelIndex) {
466453
float sample = bus.channelBuffers32[audioChannelIndex][sampleIndex];

0 commit comments

Comments
 (0)