Mercurial > hg > svapp
diff audioio/AudioCallbackPlaySource.cpp @ 235:1fcee2a1c03e sonification
Add queueExampleNote method to AudioCallbackPlaySource, providing a way to add a note to a special model which is mixed in outside of the normal playback flow. Currently mixing & generation happen in the play thread, which doesn't work very well -- buffer pending.
author | Chris Cannam |
---|---|
date | Fri, 24 Jun 2011 16:44:02 +0100 |
parents | 8aace2d9f1c2 |
children | a99de38af73f |
line wrap: on
line diff
--- a/audioio/AudioCallbackPlaySource.cpp Fri Jun 24 15:39:00 2011 +0100 +++ b/audioio/AudioCallbackPlaySource.cpp Fri Jun 24 16:44:02 2011 +0100 @@ -24,7 +24,9 @@ #include "data/model/DenseTimeValueModel.h" #include "data/model/WaveFileModel.h" #include "data/model/SparseOneDimensionalModel.h" +#include "data/model/NoteModel.h" #include "plugin/RealTimePluginInstance.h" +#include "base/Debug.h" #include "AudioCallbackPlayTarget.h" @@ -69,6 +71,8 @@ m_auditioningPluginBypassed(false), m_playStartFrame(0), m_playStartFramePassed(false), + m_exampleNotes(0), + m_examplePlaybackFrame(0), m_timeStretcher(0), m_monoStretcher(0), m_stretchRatio(1.0), @@ -115,6 +119,8 @@ } clearModels(); + + delete m_exampleNotes; if (m_readBuffers != m_writeBuffers) { delete m_readBuffers; @@ -990,6 +996,39 @@ } void +AudioCallbackPlaySource::queueExampleNote(int midiPitch) +{ + SVDEBUG << "AudioCallbackPlaySource::queueExampleNote " << midiPitch << endl; + + size_t rate = getTargetSampleRate(); + if (!rate) return; + + Note n(m_examplePlaybackFrame, + midiPitch, + rate / 2, // half a second + 0, + ""); + + NoteModel *newNoteModel = 0; + + if (!m_exampleNotes) { + // do this outside mutex -- adding the playable and the model + // both call back on us into functions that need to lock + newNoteModel = new NoteModel(rate, 1, false); + PlayParameterRepository::getInstance()->addPlayable(newNoteModel); + m_audioGenerator->addModel(newNoteModel); + m_exampleNotes = newNoteModel; + } + + m_mutex.lock(); + m_exampleNotes->addPoint(n); + m_mutex.unlock(); + + SVDEBUG << "AudioCallbackPlaySource::queueExampleNote: Added note at frame " + << n.frame << endl; +} + +void AudioCallbackPlaySource::setSoloModelSet(std::set<Model *> s) { m_audioGenerator->setSoloModelSet(s); @@ -1062,6 +1101,52 @@ } size_t +AudioCallbackPlaySource::mixExampleModel(size_t count, float **buffer) +{ + SVDEBUG << "AudioCallbackPlaySource::mixExampleModel" << endl; + + if (!m_exampleNotes || m_exampleNotes->isEmpty()) { + return 0; + } + + SVDEBUG << "AudioCallbackPlaySource::mixExampleModel: Model non-empty; m_examplePlaybackFrame is " << m_examplePlaybackFrame << " and count " << count << endl; + + QMutexLocker locker(&m_mutex); + + size_t n = 0; + + n = m_audioGenerator->mixModel(m_exampleNotes, + m_examplePlaybackFrame, + count, + buffer, + 0, + 0); + + m_examplePlaybackFrame += n; + + // prune notes that have finished + while (1) { + const NoteModel::PointList &points = m_exampleNotes->getPoints(); + if (!points.empty()) { + NoteModel::Point p(*points.begin()); + if (p.frame + p.duration < m_examplePlaybackFrame) { + m_exampleNotes->deletePoint(p); + continue; + } + } + break; + } + + SVDEBUG << "AudioCallbackPlaySource::mixExampleModel: done, got " + << n << " frames for new m_examplePlaybackFrame of " + << m_examplePlaybackFrame << ", " + << m_exampleNotes->getPoints().size() << " queued notes remain" + << endl; + + return n; +} + +size_t AudioCallbackPlaySource::getSourceSamples(size_t ucount, float **buffer) { int count = ucount; @@ -1075,7 +1160,7 @@ buffer[ch][i] = 0.0; } } - return 0; + return mixExampleModel(ucount, buffer); } #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING @@ -1180,6 +1265,8 @@ #endif m_condition.wakeAll(); + + (void)mixExampleModel(got, buffer); return got; } @@ -1273,6 +1360,8 @@ m_condition.wakeAll(); + (void)mixExampleModel(count, buffer); + return count; }