comparison audio/AudioCallbackPlaySource.cpp @ 739:ddfac001b543 audio-source-refactor

Introduce EffectWrapper for the auditioning effect
author Chris Cannam
date Thu, 19 Mar 2020 16:14:02 +0000
parents 48001ed9143b
children 846970dbef17
comparison
equal deleted inserted replaced
738:48001ed9143b 739:ddfac001b543
15 15
16 #include "AudioCallbackPlaySource.h" 16 #include "AudioCallbackPlaySource.h"
17 17
18 #include "AudioGenerator.h" 18 #include "AudioGenerator.h"
19 #include "TimeStretchWrapper.h" 19 #include "TimeStretchWrapper.h"
20 #include "EffectWrapper.h"
20 21
21 #include "data/model/Model.h" 22 #include "data/model/Model.h"
22 #include "base/ViewManagerBase.h" 23 #include "base/ViewManagerBase.h"
23 #include "base/PlayParameterRepository.h" 24 #include "base/PlayParameterRepository.h"
24 #include "base/Preferences.h" 25 #include "base/Preferences.h"
69 m_lastModelEndFrame(0), 70 m_lastModelEndFrame(0),
70 m_ringBufferSize(DEFAULT_RING_BUFFER_SIZE), 71 m_ringBufferSize(DEFAULT_RING_BUFFER_SIZE),
71 m_outputLeft(0.0), 72 m_outputLeft(0.0),
72 m_outputRight(0.0), 73 m_outputRight(0.0),
73 m_levelsSet(false), 74 m_levelsSet(false),
74 m_auditioningPlugin(nullptr),
75 m_auditioningPluginBypassed(false),
76 m_auditioningPluginFailed(false),
77 m_playStartFrame(0), 75 m_playStartFrame(0),
78 m_playStartFramePassed(false), 76 m_playStartFramePassed(false),
79 m_fillThread(nullptr), 77 m_fillThread(nullptr),
80 m_resamplerWrapper(nullptr), 78 m_resamplerWrapper(nullptr),
81 m_timeStretchWrapper(nullptr) 79 m_timeStretchWrapper(nullptr),
80 m_auditioningEffectWrapper(nullptr)
82 { 81 {
83 m_viewManager->setAudioPlaySource(this); 82 m_viewManager->setAudioPlaySource(this);
84 83
85 connect(m_viewManager, SIGNAL(selectionChanged()), 84 connect(m_viewManager, SIGNAL(selectionChanged()),
86 this, SLOT(selectionChanged())); 85 this, SLOT(selectionChanged()));
125 124
126 delete m_writeBuffers; 125 delete m_writeBuffers;
127 126
128 delete m_audioGenerator; 127 delete m_audioGenerator;
129 128
129 delete m_timeStretchWrapper;
130 delete m_auditioningEffectWrapper;
131 delete m_resamplerWrapper;
132
130 m_bufferScavenger.scavenge(true); 133 m_bufferScavenger.scavenge(true);
131 m_pluginScavenger.scavenge(true); 134 m_pluginScavenger.scavenge(true);
132 #ifdef DEBUG_AUDIO_PLAY_SOURCE 135 #ifdef DEBUG_AUDIO_PLAY_SOURCE
133 SVDEBUG << "AudioCallbackPlaySource::~AudioCallbackPlaySource finishing" << endl; 136 SVDEBUG << "AudioCallbackPlaySource::~AudioCallbackPlaySource finishing" << endl;
134 #endif 137 #endif
153 // to be called only with m_mutex held 156 // to be called only with m_mutex held
154 157
155 if (!m_resamplerWrapper) { 158 if (!m_resamplerWrapper) {
156 m_resamplerWrapper = new breakfastquay::ResamplerWrapper(this); 159 m_resamplerWrapper = new breakfastquay::ResamplerWrapper(this);
157 } 160 }
161 if (!m_auditioningEffectWrapper) {
162 m_auditioningEffectWrapper = new EffectWrapper(m_resamplerWrapper);
163 }
158 if (!m_timeStretchWrapper) { 164 if (!m_timeStretchWrapper) {
159 m_timeStretchWrapper = new TimeStretchWrapper(m_resamplerWrapper); 165 m_timeStretchWrapper = new TimeStretchWrapper(m_auditioningEffectWrapper);
160 } 166 }
161 } 167 }
162 168
163 void 169 void
164 AudioCallbackPlaySource::addModel(ModelId modelId) 170 AudioCallbackPlaySource::addModel(ModelId modelId)
593 { 599 {
594 SVCERR << "Audio processing overload!" << endl; 600 SVCERR << "Audio processing overload!" << endl;
595 601
596 if (!m_playing) return; 602 if (!m_playing) return;
597 603
598 RealTimePluginInstance *ap = m_auditioningPlugin; 604 if (m_auditioningEffectWrapper &&
599 if (ap && !m_auditioningPluginBypassed) { 605 !m_auditioningEffectWrapper->isBypassed()) {
600 m_auditioningPluginBypassed = true; 606 m_auditioningEffectWrapper->setBypassed(true);
601 emit audioOverloadPluginDisabled(); 607 emit audioOverloadPluginDisabled();
602 return; 608 return;
603 } 609 }
604 } 610 }
605 611
978 { 984 {
979 m_deviceChannelCount = count; 985 m_deviceChannelCount = count;
980 } 986 }
981 987
982 void 988 void
983 AudioCallbackPlaySource::setAuditioningEffect(Auditionable *a) 989 AudioCallbackPlaySource::setAuditioningEffect(std::shared_ptr<Auditionable> a)
984 { 990 {
985 RealTimePluginInstance *plugin = dynamic_cast<RealTimePluginInstance *>(a); 991 auto plugin = std::dynamic_pointer_cast<RealTimePluginInstance>(a);
986 if (a && !plugin) { 992 if (a && !plugin) {
987 SVCERR << "WARNING: AudioCallbackPlaySource::setAuditioningEffect: auditionable object " << a << " is not a real-time plugin instance" << endl; 993 SVCERR << "WARNING: AudioCallbackPlaySource::setAuditioningEffect: auditionable object " << a << " is not a real-time plugin instance" << endl;
988 } 994 }
989 995
990 m_mutex.lock(); 996 m_mutex.lock();
991 m_auditioningPlugin = plugin; 997 m_auditioningEffectWrapper->setEffect(plugin);
992 m_auditioningPluginBypassed = false; 998 m_auditioningEffectWrapper->setBypassed(false);
993 m_auditioningPluginFailed = false;
994 m_mutex.unlock(); 999 m_mutex.unlock();
995 1000
996 SVDEBUG << "AudioCallbackPlaySource::setAuditioningEffect: set plugin to " 1001 SVDEBUG << "AudioCallbackPlaySource::setAuditioningEffect: set plugin to "
997 << plugin << " and bypassed to " << m_auditioningPluginBypassed 1002 << plugin << endl;
998 << endl;
999 } 1003 }
1000 1004
1001 void 1005 void
1002 AudioCallbackPlaySource::setSoloModelSet(std::set<ModelId> s) 1006 AudioCallbackPlaySource::setSoloModelSet(std::set<ModelId> s)
1003 { 1007 {
1188 buffer[ch][i] = 0.0; 1192 buffer[ch][i] = 0.0;
1189 } 1193 }
1190 } 1194 }
1191 } 1195 }
1192 1196
1193 applyAuditioningEffect(count, buffer);
1194
1195 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1197 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1196 cout << "AudioCallbackPlaySource::getSamples: awakening thread" << endl; 1198 cout << "AudioCallbackPlaySource::getSamples: awakening thread" << endl;
1197 #endif 1199 #endif
1198 1200
1199 m_condition.wakeAll(); 1201 m_condition.wakeAll();
1200 1202
1201 return got; 1203 return got;
1202 } 1204 }
1203
1204 void
1205 AudioCallbackPlaySource::applyAuditioningEffect(sv_frame_t count, float *const *buffers)
1206 {
1207 if (m_auditioningPluginBypassed) return;
1208 RealTimePluginInstance *plugin = m_auditioningPlugin;
1209 if (!plugin) return;
1210
1211 if ((int)plugin->getAudioInputCount() != getTargetChannelCount()) {
1212 if (!m_auditioningPluginFailed) {
1213 SVCERR << "AudioCallbackPlaySource::applyAuditioningEffect: "
1214 << "Can't run plugin: plugin input count "
1215 << plugin->getAudioInputCount()
1216 << " != our channel count " << getTargetChannelCount()
1217 << " (future errors for this plugin will be suppressed)"
1218 << endl;
1219 m_auditioningPluginFailed = true;
1220 }
1221 return;
1222 }
1223 if ((int)plugin->getAudioOutputCount() != getTargetChannelCount()) {
1224 if (!m_auditioningPluginFailed) {
1225 SVCERR << "AudioCallbackPlaySource::applyAuditioningEffect: "
1226 << "Can't run plugin: plugin output count "
1227 << plugin->getAudioOutputCount()
1228 << " != our channel count " << getTargetChannelCount()
1229 << " (future errors for this plugin will be suppressed)"
1230 << endl;
1231 m_auditioningPluginFailed = true;
1232 }
1233 return;
1234 }
1235 if ((int)plugin->getBufferSize() < count) {
1236 if (!m_auditioningPluginFailed) {
1237 SVCERR << "AudioCallbackPlaySource::applyAuditioningEffect: "
1238 << "Can't run plugin: plugin buffer size "
1239 << plugin->getBufferSize()
1240 << " < our block size " << count
1241 << " (future errors for this plugin will be suppressed)"
1242 << endl;
1243 m_auditioningPluginFailed = true;
1244 }
1245 return;
1246 }
1247
1248 float **ib = plugin->getAudioInputBuffers();
1249 float **ob = plugin->getAudioOutputBuffers();
1250
1251 for (int c = 0; c < getTargetChannelCount(); ++c) {
1252 for (int i = 0; i < count; ++i) {
1253 ib[c][i] = buffers[c][i];
1254 }
1255 }
1256
1257 plugin->run(Vamp::RealTime::zeroTime, int(count));
1258
1259 for (int c = 0; c < getTargetChannelCount(); ++c) {
1260 for (int i = 0; i < count; ++i) {
1261 buffers[c][i] = ob[c][i];
1262 }
1263 }
1264 }
1265 1205
1266 // Called from fill thread, m_playing true, mutex held 1206 // Called from fill thread, m_playing true, mutex held
1267 bool 1207 bool
1268 AudioCallbackPlaySource::fillBuffers() 1208 AudioCallbackPlaySource::fillBuffers()
1269 { 1209 {