Mercurial > hg > svapp
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 { |