Mercurial > hg > svapp
comparison audioio/AudioCallbackPlaySource.cpp @ 239:4d1501b27075 integration_library
Merge from branch "sonification"
| author | mathieub <mathieu.barthet@eecs.qmul.ac.uk> | 
|---|---|
| date | Mon, 25 Jul 2011 17:57:59 +0100 | 
| parents | 1fcee2a1c03e | 
| children | a99de38af73f | 
   comparison
  equal
  deleted
  inserted
  replaced
| 237:1ebd8e13262d | 239:4d1501b27075 | 
|---|---|
| 22 #include "base/PlayParameterRepository.h" | 22 #include "base/PlayParameterRepository.h" | 
| 23 #include "base/Preferences.h" | 23 #include "base/Preferences.h" | 
| 24 #include "data/model/DenseTimeValueModel.h" | 24 #include "data/model/DenseTimeValueModel.h" | 
| 25 #include "data/model/WaveFileModel.h" | 25 #include "data/model/WaveFileModel.h" | 
| 26 #include "data/model/SparseOneDimensionalModel.h" | 26 #include "data/model/SparseOneDimensionalModel.h" | 
| 27 #include "data/model/NoteModel.h" | |
| 27 #include "plugin/RealTimePluginInstance.h" | 28 #include "plugin/RealTimePluginInstance.h" | 
| 29 #include "base/Debug.h" | |
| 28 | 30 | 
| 29 #include "AudioCallbackPlayTarget.h" | 31 #include "AudioCallbackPlayTarget.h" | 
| 30 | 32 | 
| 31 #include <rubberband/RubberBandStretcher.h> | 33 #include <rubberband/RubberBandStretcher.h> | 
| 32 using namespace RubberBand; | 34 using namespace RubberBand; | 
| 67 m_outputRight(0.0), | 69 m_outputRight(0.0), | 
| 68 m_auditioningPlugin(0), | 70 m_auditioningPlugin(0), | 
| 69 m_auditioningPluginBypassed(false), | 71 m_auditioningPluginBypassed(false), | 
| 70 m_playStartFrame(0), | 72 m_playStartFrame(0), | 
| 71 m_playStartFramePassed(false), | 73 m_playStartFramePassed(false), | 
| 74 m_exampleNotes(0), | |
| 75 m_examplePlaybackFrame(0), | |
| 72 m_timeStretcher(0), | 76 m_timeStretcher(0), | 
| 73 m_monoStretcher(0), | 77 m_monoStretcher(0), | 
| 74 m_stretchRatio(1.0), | 78 m_stretchRatio(1.0), | 
| 75 m_stretcherInputCount(0), | 79 m_stretcherInputCount(0), | 
| 76 m_stretcherInputs(0), | 80 m_stretcherInputs(0), | 
| 113 m_fillThread->wait(); | 117 m_fillThread->wait(); | 
| 114 delete m_fillThread; | 118 delete m_fillThread; | 
| 115 } | 119 } | 
| 116 | 120 | 
| 117 clearModels(); | 121 clearModels(); | 
| 122 | |
| 123 delete m_exampleNotes; | |
| 118 | 124 | 
| 119 if (m_readBuffers != m_writeBuffers) { | 125 if (m_readBuffers != m_writeBuffers) { | 
| 120 delete m_readBuffers; | 126 delete m_readBuffers; | 
| 121 } | 127 } | 
| 122 | 128 | 
| 985 | 991 | 
| 986 m_mutex.lock(); | 992 m_mutex.lock(); | 
| 987 m_auditioningPlugin = plugin; | 993 m_auditioningPlugin = plugin; | 
| 988 m_auditioningPluginBypassed = false; | 994 m_auditioningPluginBypassed = false; | 
| 989 m_mutex.unlock(); | 995 m_mutex.unlock(); | 
| 996 } | |
| 997 | |
| 998 void | |
| 999 AudioCallbackPlaySource::queueExampleNote(int midiPitch) | |
| 1000 { | |
| 1001 SVDEBUG << "AudioCallbackPlaySource::queueExampleNote " << midiPitch << endl; | |
| 1002 | |
| 1003 size_t rate = getTargetSampleRate(); | |
| 1004 if (!rate) return; | |
| 1005 | |
| 1006 Note n(m_examplePlaybackFrame, | |
| 1007 midiPitch, | |
| 1008 rate / 2, // half a second | |
| 1009 0, | |
| 1010 ""); | |
| 1011 | |
| 1012 NoteModel *newNoteModel = 0; | |
| 1013 | |
| 1014 if (!m_exampleNotes) { | |
| 1015 // do this outside mutex -- adding the playable and the model | |
| 1016 // both call back on us into functions that need to lock | |
| 1017 newNoteModel = new NoteModel(rate, 1, false); | |
| 1018 PlayParameterRepository::getInstance()->addPlayable(newNoteModel); | |
| 1019 m_audioGenerator->addModel(newNoteModel); | |
| 1020 m_exampleNotes = newNoteModel; | |
| 1021 } | |
| 1022 | |
| 1023 m_mutex.lock(); | |
| 1024 m_exampleNotes->addPoint(n); | |
| 1025 m_mutex.unlock(); | |
| 1026 | |
| 1027 SVDEBUG << "AudioCallbackPlaySource::queueExampleNote: Added note at frame " | |
| 1028 << n.frame << endl; | |
| 990 } | 1029 } | 
| 991 | 1030 | 
| 992 void | 1031 void | 
| 993 AudioCallbackPlaySource::setSoloModelSet(std::set<Model *> s) | 1032 AudioCallbackPlaySource::setSoloModelSet(std::set<Model *> s) | 
| 994 { | 1033 { | 
| 1060 | 1099 | 
| 1061 emit activity(tr("Change time-stretch factor to %1").arg(factor)); | 1100 emit activity(tr("Change time-stretch factor to %1").arg(factor)); | 
| 1062 } | 1101 } | 
| 1063 | 1102 | 
| 1064 size_t | 1103 size_t | 
| 1104 AudioCallbackPlaySource::mixExampleModel(size_t count, float **buffer) | |
| 1105 { | |
| 1106 SVDEBUG << "AudioCallbackPlaySource::mixExampleModel" << endl; | |
| 1107 | |
| 1108 if (!m_exampleNotes || m_exampleNotes->isEmpty()) { | |
| 1109 return 0; | |
| 1110 } | |
| 1111 | |
| 1112 SVDEBUG << "AudioCallbackPlaySource::mixExampleModel: Model non-empty; m_examplePlaybackFrame is " << m_examplePlaybackFrame << " and count " << count << endl; | |
| 1113 | |
| 1114 QMutexLocker locker(&m_mutex); | |
| 1115 | |
| 1116 size_t n = 0; | |
| 1117 | |
| 1118 n = m_audioGenerator->mixModel(m_exampleNotes, | |
| 1119 m_examplePlaybackFrame, | |
| 1120 count, | |
| 1121 buffer, | |
| 1122 0, | |
| 1123 0); | |
| 1124 | |
| 1125 m_examplePlaybackFrame += n; | |
| 1126 | |
| 1127 // prune notes that have finished | |
| 1128 while (1) { | |
| 1129 const NoteModel::PointList &points = m_exampleNotes->getPoints(); | |
| 1130 if (!points.empty()) { | |
| 1131 NoteModel::Point p(*points.begin()); | |
| 1132 if (p.frame + p.duration < m_examplePlaybackFrame) { | |
| 1133 m_exampleNotes->deletePoint(p); | |
| 1134 continue; | |
| 1135 } | |
| 1136 } | |
| 1137 break; | |
| 1138 } | |
| 1139 | |
| 1140 SVDEBUG << "AudioCallbackPlaySource::mixExampleModel: done, got " | |
| 1141 << n << " frames for new m_examplePlaybackFrame of " | |
| 1142 << m_examplePlaybackFrame << ", " | |
| 1143 << m_exampleNotes->getPoints().size() << " queued notes remain" | |
| 1144 << endl; | |
| 1145 | |
| 1146 return n; | |
| 1147 } | |
| 1148 | |
| 1149 size_t | |
| 1065 AudioCallbackPlaySource::getSourceSamples(size_t ucount, float **buffer) | 1150 AudioCallbackPlaySource::getSourceSamples(size_t ucount, float **buffer) | 
| 1066 { | 1151 { | 
| 1067 int count = ucount; | 1152 int count = ucount; | 
| 1068 | 1153 | 
| 1069 if (!m_playing) { | 1154 if (!m_playing) { | 
| 1073 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) { | 1158 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) { | 
| 1074 for (int i = 0; i < count; ++i) { | 1159 for (int i = 0; i < count; ++i) { | 
| 1075 buffer[ch][i] = 0.0; | 1160 buffer[ch][i] = 0.0; | 
| 1076 } | 1161 } | 
| 1077 } | 1162 } | 
| 1078 return 0; | 1163 return mixExampleModel(ucount, buffer); | 
| 1079 } | 1164 } | 
| 1080 | 1165 | 
| 1081 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING | 1166 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING | 
| 1082 SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Playing" << endl; | 1167 SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Playing" << endl; | 
| 1083 #endif | 1168 #endif | 
| 1178 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 1263 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 
| 1179 std::cout << "AudioCallbackPlaySource::getSamples: awakening thread" << std::endl; | 1264 std::cout << "AudioCallbackPlaySource::getSamples: awakening thread" << std::endl; | 
| 1180 #endif | 1265 #endif | 
| 1181 | 1266 | 
| 1182 m_condition.wakeAll(); | 1267 m_condition.wakeAll(); | 
| 1268 | |
| 1269 (void)mixExampleModel(got, buffer); | |
| 1183 | 1270 | 
| 1184 return got; | 1271 return got; | 
| 1185 } | 1272 } | 
| 1186 | 1273 | 
| 1187 size_t channels = getTargetChannelCount(); | 1274 size_t channels = getTargetChannelCount(); | 
| 1271 std::cout << "AudioCallbackPlaySource::getSamples [stretched]: awakening thread" << std::endl; | 1358 std::cout << "AudioCallbackPlaySource::getSamples [stretched]: awakening thread" << std::endl; | 
| 1272 #endif | 1359 #endif | 
| 1273 | 1360 | 
| 1274 m_condition.wakeAll(); | 1361 m_condition.wakeAll(); | 
| 1275 | 1362 | 
| 1363 (void)mixExampleModel(count, buffer); | |
| 1364 | |
| 1276 return count; | 1365 return count; | 
| 1277 } | 1366 } | 
| 1278 | 1367 | 
| 1279 void | 1368 void | 
| 1280 AudioCallbackPlaySource::applyAuditioningEffect(size_t count, float **buffers) | 1369 AudioCallbackPlaySource::applyAuditioningEffect(size_t count, float **buffers) | 
