changeset 42:0619006a1ee3 last-cc-copyright sv1-1.0pre1 sv1-1.0pre2 sv1-1.0pre3 sv1-1.0pre4 sv1-1.0rc1 sv1-v1.0

* Reorganising code base. This revision will not compile.
author Chris Cannam
date Mon, 31 Jul 2006 12:03:45 +0000
parents a4a05344c7d6
children 3c5756fb6a68
files audioio/AudioCallbackPlaySource.cpp audioio/AudioCallbackPlaySource.h audioio/AudioCallbackPlayTarget.cpp audioio/AudioCallbackPlayTarget.h audioio/AudioCoreAudioTarget.cpp audioio/AudioCoreAudioTarget.h audioio/AudioGenerator.cpp audioio/AudioGenerator.h audioio/AudioJACKTarget.cpp audioio/AudioJACKTarget.h audioio/AudioPortAudioTarget.cpp audioio/AudioPortAudioTarget.h audioio/AudioTargetFactory.cpp audioio/AudioTargetFactory.h audioio/IntegerTimeStretcher.cpp audioio/IntegerTimeStretcher.h
diffstat 16 files changed, 0 insertions(+), 3612 deletions(-) [+]
line wrap: on
line diff
--- a/audioio/AudioCallbackPlaySource.cpp	Thu Jul 27 16:06:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1257 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#include "AudioCallbackPlaySource.h"
-
-#include "AudioGenerator.h"
-
-#include "base/Model.h"
-#include "base/ViewManager.h"
-#include "base/PlayParameterRepository.h"
-#include "model/DenseTimeValueModel.h"
-#include "model/SparseOneDimensionalModel.h"
-#include "IntegerTimeStretcher.h"
-
-#include <iostream>
-#include <cassert>
-
-//#define DEBUG_AUDIO_PLAY_SOURCE 1
-//#define DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1
-
-//const size_t AudioCallbackPlaySource::m_ringBufferSize = 102400;
-const size_t AudioCallbackPlaySource::m_ringBufferSize = 131071;
-
-AudioCallbackPlaySource::AudioCallbackPlaySource(ViewManager *manager) :
-    m_viewManager(manager),
-    m_audioGenerator(new AudioGenerator()),
-    m_readBuffers(0),
-    m_writeBuffers(0),
-    m_readBufferFill(0),
-    m_writeBufferFill(0),
-    m_bufferScavenger(1),
-    m_sourceChannelCount(0),
-    m_blockSize(1024),
-    m_sourceSampleRate(0),
-    m_targetSampleRate(0),
-    m_playLatency(0),
-    m_playing(false),
-    m_exiting(false),
-    m_lastModelEndFrame(0),
-    m_outputLeft(0.0),
-    m_outputRight(0.0),
-    m_slowdownCounter(0),
-    m_timeStretcher(0),
-    m_fillThread(0),
-    m_converter(0)
-{
-    m_viewManager->setAudioPlaySource(this);
-
-    connect(m_viewManager, SIGNAL(selectionChanged()),
-	    this, SLOT(selectionChanged()));
-    connect(m_viewManager, SIGNAL(playLoopModeChanged()),
-	    this, SLOT(playLoopModeChanged()));
-    connect(m_viewManager, SIGNAL(playSelectionModeChanged()),
-	    this, SLOT(playSelectionModeChanged()));
-
-    connect(PlayParameterRepository::getInstance(),
-	    SIGNAL(playParametersChanged(PlayParameters *)),
-	    this, SLOT(playParametersChanged(PlayParameters *)));
-}
-
-AudioCallbackPlaySource::~AudioCallbackPlaySource()
-{
-    m_exiting = true;
-
-    if (m_fillThread) {
-	m_condition.wakeAll();
-	m_fillThread->wait();
-	delete m_fillThread;
-    }
-
-    clearModels();
-    
-    if (m_readBuffers != m_writeBuffers) {
-	delete m_readBuffers;
-    }
-
-    delete m_writeBuffers;
-
-    delete m_audioGenerator;
-
-    m_bufferScavenger.scavenge(true);
-}
-
-void
-AudioCallbackPlaySource::addModel(Model *model)
-{
-    if (m_models.find(model) != m_models.end()) return;
-
-    bool canPlay = m_audioGenerator->addModel(model);
-
-    m_mutex.lock();
-
-    m_models.insert(model);
-    if (model->getEndFrame() > m_lastModelEndFrame) {
-	m_lastModelEndFrame = model->getEndFrame();
-    }
-
-    bool buffersChanged = false, srChanged = false;
-
-    size_t modelChannels = 1;
-    DenseTimeValueModel *dtvm = dynamic_cast<DenseTimeValueModel *>(model);
-    if (dtvm) modelChannels = dtvm->getChannelCount();
-    if (modelChannels > m_sourceChannelCount) {
-	m_sourceChannelCount = modelChannels;
-    }
-
-//    std::cerr << "Adding model with " << modelChannels << " channels " << std::endl;
-
-    if (m_sourceSampleRate == 0) {
-
-	m_sourceSampleRate = model->getSampleRate();
-	srChanged = true;
-
-    } else if (model->getSampleRate() != m_sourceSampleRate) {
-
-        // If this is a dense time-value model and we have no other, we
-        // can just switch to this model's sample rate
-
-        if (dtvm) {
-
-            bool conflicting = false;
-
-            for (std::set<Model *>::const_iterator i = m_models.begin();
-                 i != m_models.end(); ++i) {
-                if (*i != dtvm && dynamic_cast<DenseTimeValueModel *>(*i)) {
-                    std::cerr << "AudioCallbackPlaySource::addModel: Conflicting dense time-value model " << *i << " found" << std::endl;
-                    conflicting = true;
-                    break;
-                }
-            }
-
-            if (conflicting) {
-
-                std::cerr << "AudioCallbackPlaySource::addModel: ERROR: "
-                          << "New model sample rate does not match" << std::endl
-                          << "existing model(s) (new " << model->getSampleRate()
-                          << " vs " << m_sourceSampleRate
-                          << "), playback will be wrong"
-                          << std::endl;
-                
-                emit sampleRateMismatch(model->getSampleRate(), m_sourceSampleRate,
-                                        false);
-            } else {
-                m_sourceSampleRate = model->getSampleRate();
-                srChanged = true;
-            }
-        }
-    }
-
-    if (!m_writeBuffers || (m_writeBuffers->size() < getTargetChannelCount())) {
-	clearRingBuffers(true, getTargetChannelCount());
-	buffersChanged = true;
-    } else {
-	if (canPlay) clearRingBuffers(true);
-    }
-
-    if (buffersChanged || srChanged) {
-	if (m_converter) {
-	    src_delete(m_converter);
-	    m_converter = 0;
-	}
-    }
-
-    m_mutex.unlock();
-
-    m_audioGenerator->setTargetChannelCount(getTargetChannelCount());
-
-    if (!m_fillThread) {
-	m_fillThread = new AudioCallbackPlaySourceFillThread(*this);
-	m_fillThread->start();
-    }
-
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-    std::cerr << "AudioCallbackPlaySource::addModel: emitting modelReplaced" << std::endl;
-#endif
-
-    if (buffersChanged || srChanged) {
-	emit modelReplaced();
-    }
-
-    m_condition.wakeAll();
-}
-
-void
-AudioCallbackPlaySource::removeModel(Model *model)
-{
-    m_mutex.lock();
-
-    m_models.erase(model);
-
-    if (m_models.empty()) {
-	if (m_converter) {
-	    src_delete(m_converter);
-	    m_converter = 0;
-	}
-	m_sourceSampleRate = 0;
-    }
-
-    size_t lastEnd = 0;
-    for (std::set<Model *>::const_iterator i = m_models.begin();
-	 i != m_models.end(); ++i) {
-//	std::cerr << "AudioCallbackPlaySource::removeModel(" << model << "): checking end frame on model " << *i << std::endl;
-	if ((*i)->getEndFrame() > lastEnd) lastEnd = (*i)->getEndFrame();
-//	std::cerr << "(done, lastEnd now " << lastEnd << ")" << std::endl;
-    }
-    m_lastModelEndFrame = lastEnd;
-
-    m_mutex.unlock();
-
-    m_audioGenerator->removeModel(model);
-
-    clearRingBuffers();
-}
-
-void
-AudioCallbackPlaySource::clearModels()
-{
-    m_mutex.lock();
-
-    m_models.clear();
-
-    if (m_converter) {
-	src_delete(m_converter);
-	m_converter = 0;
-    }
-
-    m_lastModelEndFrame = 0;
-
-    m_sourceSampleRate = 0;
-
-    m_mutex.unlock();
-
-    m_audioGenerator->clearModels();
-}    
-
-void
-AudioCallbackPlaySource::clearRingBuffers(bool haveLock, size_t count)
-{
-    if (!haveLock) m_mutex.lock();
-
-    if (count == 0) {
-	if (m_writeBuffers) count = m_writeBuffers->size();
-    }
-
-    size_t sf = m_readBufferFill;
-    RingBuffer<float> *rb = getReadRingBuffer(0);
-    if (rb) {
-	//!!! This is incorrect if we're in a non-contiguous selection
-	//Same goes for all related code (subtracting the read space
-	//from the fill frame to try to establish where the effective
-	//pre-resample/timestretch read pointer is)
-	size_t rs = rb->getReadSpace();
-	if (rs < sf) sf -= rs;
-	else sf = 0;
-    }
-    m_writeBufferFill = sf;
-
-    if (m_readBuffers != m_writeBuffers) {
-	delete m_writeBuffers;
-    }
-
-    m_writeBuffers = new RingBufferVector;
-
-    for (size_t i = 0; i < count; ++i) {
-	m_writeBuffers->push_back(new RingBuffer<float>(m_ringBufferSize));
-    }
-
-//    std::cerr << "AudioCallbackPlaySource::clearRingBuffers: Created "
-//	      << count << " write buffers" << std::endl;
-
-    if (!haveLock) {
-	m_mutex.unlock();
-    }
-}
-
-void
-AudioCallbackPlaySource::play(size_t startFrame)
-{
-    if (m_viewManager->getPlaySelectionMode() &&
-	!m_viewManager->getSelections().empty()) {
-	MultiSelection::SelectionList selections = m_viewManager->getSelections();
-	MultiSelection::SelectionList::iterator i = selections.begin();
-	if (i != selections.end()) {
-	    if (startFrame < i->getStartFrame()) {
-		startFrame = i->getStartFrame();
-	    } else {
-		MultiSelection::SelectionList::iterator j = selections.end();
-		--j;
-		if (startFrame >= j->getEndFrame()) {
-		    startFrame = i->getStartFrame();
-		}
-	    }
-	}
-    } else {
-	if (startFrame >= m_lastModelEndFrame) {
-	    startFrame = 0;
-	}
-    }
-
-    // The fill thread will automatically empty its buffers before
-    // starting again if we have not so far been playing, but not if
-    // we're just re-seeking.
-
-    m_mutex.lock();
-    if (m_playing) {
-	m_readBufferFill = m_writeBufferFill = startFrame;
-	if (m_readBuffers) {
-	    for (size_t c = 0; c < getTargetChannelCount(); ++c) {
-		RingBuffer<float> *rb = getReadRingBuffer(c);
-		if (rb) rb->reset();
-	    }
-	}
-	if (m_converter) src_reset(m_converter);
-    } else {
-	if (m_converter) src_reset(m_converter);
-	m_readBufferFill = m_writeBufferFill = startFrame;
-    }
-    m_mutex.unlock();
-
-    m_audioGenerator->reset();
-
-    bool changed = !m_playing;
-    m_playing = true;
-    m_condition.wakeAll();
-    if (changed) emit playStatusChanged(m_playing);
-}
-
-void
-AudioCallbackPlaySource::stop()
-{
-    bool changed = m_playing;
-    m_playing = false;
-    m_condition.wakeAll();
-    if (changed) emit playStatusChanged(m_playing);
-}
-
-void
-AudioCallbackPlaySource::selectionChanged()
-{
-    if (m_viewManager->getPlaySelectionMode()) {
-	clearRingBuffers();
-    }
-}
-
-void
-AudioCallbackPlaySource::playLoopModeChanged()
-{
-    clearRingBuffers();
-}
-
-void
-AudioCallbackPlaySource::playSelectionModeChanged()
-{
-    if (!m_viewManager->getSelections().empty()) {
-	clearRingBuffers();
-    }
-}
-
-void
-AudioCallbackPlaySource::playParametersChanged(PlayParameters *params)
-{
-    clearRingBuffers();
-}
-
-void
-AudioCallbackPlaySource::setTargetBlockSize(size_t size)
-{
-//    std::cerr << "AudioCallbackPlaySource::setTargetBlockSize() -> " << size << std::endl;
-    assert(size < m_ringBufferSize);
-    m_blockSize = size;
-}
-
-size_t
-AudioCallbackPlaySource::getTargetBlockSize() const
-{
-//    std::cerr << "AudioCallbackPlaySource::getTargetBlockSize() -> " << m_blockSize << std::endl;
-    return m_blockSize;
-}
-
-void
-AudioCallbackPlaySource::setTargetPlayLatency(size_t latency)
-{
-    m_playLatency = latency;
-}
-
-size_t
-AudioCallbackPlaySource::getTargetPlayLatency() const
-{
-    return m_playLatency;
-}
-
-size_t
-AudioCallbackPlaySource::getCurrentPlayingFrame()
-{
-    bool resample = false;
-    double ratio = 1.0;
-
-    if (getSourceSampleRate() != getTargetSampleRate()) {
-	resample = true;
-	ratio = double(getSourceSampleRate()) / double(getTargetSampleRate());
-    }
-
-    size_t readSpace = 0;
-    for (size_t c = 0; c < getTargetChannelCount(); ++c) {
-	RingBuffer<float> *rb = getReadRingBuffer(c);
-	if (rb) {
-	    size_t spaceHere = rb->getReadSpace();
-	    if (c == 0 || spaceHere < readSpace) readSpace = spaceHere;
-	}
-    }
-
-    if (resample) {
-	readSpace = size_t(readSpace * ratio + 0.1);
-    }
-
-    size_t latency = m_playLatency;
-    if (resample) latency = size_t(m_playLatency * ratio + 0.1);
-    
-    TimeStretcherData *timeStretcher = m_timeStretcher;
-    if (timeStretcher) {
-	latency += timeStretcher->getStretcher(0)->getProcessingLatency();
-    }
-
-    latency += readSpace;
-    size_t bufferedFrame = m_readBufferFill;
-
-    bool looping = m_viewManager->getPlayLoopMode();
-    bool constrained = (m_viewManager->getPlaySelectionMode() &&
-			!m_viewManager->getSelections().empty());
-
-    size_t framePlaying = bufferedFrame;
-
-    if (looping && !constrained) {
-	while (framePlaying < latency) framePlaying += m_lastModelEndFrame;
-    }
-
-    if (framePlaying > latency) framePlaying -= latency;
-    else framePlaying = 0;
-
-    if (!constrained) {
-	if (!looping && framePlaying > m_lastModelEndFrame) {
-	    framePlaying = m_lastModelEndFrame;
-	    stop();
-	}
-	return framePlaying;
-    }
-
-    MultiSelection::SelectionList selections = m_viewManager->getSelections();
-    MultiSelection::SelectionList::const_iterator i;
-
-    i = selections.begin();
-    size_t rangeStart = i->getStartFrame();
-
-    i = selections.end();
-    --i;
-    size_t rangeEnd = i->getEndFrame();
-
-    for (i = selections.begin(); i != selections.end(); ++i) {
-	if (i->contains(bufferedFrame)) break;
-    }
-
-    size_t f = bufferedFrame;
-
-//    std::cerr << "getCurrentPlayingFrame: f=" << f << ", latency=" << latency << ", rangeEnd=" << rangeEnd << std::endl;
-
-    if (i == selections.end()) {
-	--i;
-	if (i->getEndFrame() + latency < f) {
-//    std::cerr << "framePlaying = " << framePlaying << ", rangeEnd = " << rangeEnd << std::endl;
-
-	    if (!looping && (framePlaying > rangeEnd)) {
-//		std::cerr << "STOPPING" << std::endl;
-		stop();
-		return rangeEnd;
-	    } else {
-		return framePlaying;
-	    }
-	} else {
-//	    std::cerr << "latency <- " << latency << "-(" << f << "-" << i->getEndFrame() << ")" << std::endl;
-	    latency -= (f - i->getEndFrame());
-	    f = i->getEndFrame();
-	}
-    }
-
-//    std::cerr << "i=(" << i->getStartFrame() << "," << i->getEndFrame() << ") f=" << f << ", latency=" << latency << std::endl;
-
-    while (latency > 0) {
-	size_t offset = f - i->getStartFrame();
-	if (offset >= latency) {
-	    if (f > latency) {
-		framePlaying = f - latency;
-	    } else {
-		framePlaying = 0;
-	    }
-	    break;
-	} else {
-	    if (i == selections.begin()) {
-		if (looping) {
-		    i = selections.end();
-		}
-	    }
-	    latency -= offset;
-	    --i;
-	    f = i->getEndFrame();
-	}
-    }
-
-    return framePlaying;
-}
-
-void
-AudioCallbackPlaySource::setOutputLevels(float left, float right)
-{
-    m_outputLeft = left;
-    m_outputRight = right;
-}
-
-bool
-AudioCallbackPlaySource::getOutputLevels(float &left, float &right)
-{
-    left = m_outputLeft;
-    right = m_outputRight;
-    return true;
-}
-
-void
-AudioCallbackPlaySource::setTargetSampleRate(size_t sr)
-{
-    m_targetSampleRate = sr;
-
-    if (getSourceSampleRate() != getTargetSampleRate()) {
-
-	int err = 0;
-	m_converter = src_new(SRC_SINC_BEST_QUALITY,
-			      getTargetChannelCount(), &err);
-	if (!m_converter) {
-	    std::cerr
-		<< "AudioCallbackPlaySource::setModel: ERROR in creating samplerate converter: "
-		<< src_strerror(err) << std::endl;
-
-            emit sampleRateMismatch(getSourceSampleRate(),
-                                    getTargetSampleRate(),
-                                    false);
-	} else {
-
-            emit sampleRateMismatch(getSourceSampleRate(),
-                                    getTargetSampleRate(),
-                                    true);
-        }
-    }
-}
-
-size_t
-AudioCallbackPlaySource::getTargetSampleRate() const
-{
-    if (m_targetSampleRate) return m_targetSampleRate;
-    else return getSourceSampleRate();
-}
-
-size_t
-AudioCallbackPlaySource::getSourceChannelCount() const
-{
-    return m_sourceChannelCount;
-}
-
-size_t
-AudioCallbackPlaySource::getTargetChannelCount() const
-{
-    if (m_sourceChannelCount < 2) return 2;
-    return m_sourceChannelCount;
-}
-
-size_t
-AudioCallbackPlaySource::getSourceSampleRate() const
-{
-    return m_sourceSampleRate;
-}
-
-AudioCallbackPlaySource::TimeStretcherData::TimeStretcherData(size_t channels,
-							      size_t factor,
-							      size_t blockSize) :
-    m_factor(factor),
-    m_blockSize(blockSize)
-{
-//    std::cerr << "TimeStretcherData::TimeStretcherData(" << channels << ", " << factor << ", " << blockSize << ")" << std::endl;
-
-    for (size_t ch = 0; ch < channels; ++ch) {
-	m_stretcher[ch] = StretcherBuffer
-	    //!!! We really need to measure performance and work out
-	    //what sort of quality level to use -- or at least to
-	    //allow the user to configure it
-	    (new IntegerTimeStretcher(factor, blockSize, 128),
-	     new float[blockSize * factor]);
-    }
-    m_stretchInputBuffer = new float[blockSize];
-}
-
-AudioCallbackPlaySource::TimeStretcherData::~TimeStretcherData()
-{
-//    std::cerr << "TimeStretcherData::~TimeStretcherData" << std::endl;
-
-    while (!m_stretcher.empty()) {
-	delete m_stretcher.begin()->second.first;
-	delete[] m_stretcher.begin()->second.second;
-	m_stretcher.erase(m_stretcher.begin());
-    }
-    delete m_stretchInputBuffer;
-}
-
-IntegerTimeStretcher *
-AudioCallbackPlaySource::TimeStretcherData::getStretcher(size_t channel)
-{
-    return m_stretcher[channel].first;
-}
-
-float *
-AudioCallbackPlaySource::TimeStretcherData::getOutputBuffer(size_t channel)
-{
-    return m_stretcher[channel].second;
-}
-
-float *
-AudioCallbackPlaySource::TimeStretcherData::getInputBuffer()
-{
-    return m_stretchInputBuffer;
-}
-
-void
-AudioCallbackPlaySource::TimeStretcherData::run(size_t channel)
-{
-    getStretcher(channel)->process(getInputBuffer(),
-				   getOutputBuffer(channel),
-				   m_blockSize);
-}
-
-void
-AudioCallbackPlaySource::setSlowdownFactor(size_t factor)
-{
-    // Avoid locks -- create, assign, mark old one for scavenging
-    // later (as a call to getSourceSamples may still be using it)
-
-    TimeStretcherData *existingStretcher = m_timeStretcher;
-
-    if (existingStretcher && existingStretcher->getFactor() == factor) {
-	return;
-    }
-
-    if (factor > 1) {
-	TimeStretcherData *newStretcher = new TimeStretcherData
-	    (getTargetChannelCount(), factor, getTargetBlockSize());
-	m_slowdownCounter = 0;
-	m_timeStretcher = newStretcher;
-    } else {
-	m_timeStretcher = 0;
-    }
-
-    if (existingStretcher) {
-	m_timeStretcherScavenger.claim(existingStretcher);
-    }
-}
-	    
-size_t
-AudioCallbackPlaySource::getSourceSamples(size_t count, float **buffer)
-{
-    if (!m_playing) {
-	for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
-	    for (size_t i = 0; i < count; ++i) {
-		buffer[ch][i] = 0.0;
-	    }
-	}
-	return 0;
-    }
-
-    TimeStretcherData *timeStretcher = m_timeStretcher;
-
-    if (!timeStretcher || timeStretcher->getFactor() == 1) {
-
-	size_t got = 0;
-
-	for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
-
-	    RingBuffer<float> *rb = getReadRingBuffer(ch);
-
-	    if (rb) {
-
-		// this is marginally more likely to leave our channels in
-		// sync after a processing failure than just passing "count":
-		size_t request = count;
-		if (ch > 0) request = got;
-
-		got = rb->read(buffer[ch], request);
-	    
-#ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
-		std::cout << "AudioCallbackPlaySource::getSamples: got " << got << " samples on channel " << ch << ", signalling for more (possibly)" << std::endl;
-#endif
-	    }
-
-	    for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
-		for (size_t i = got; i < count; ++i) {
-		    buffer[ch][i] = 0.0;
-		}
-	    }
-	}
-
-        m_condition.wakeAll();
-	return got;
-    }
-
-    if (m_slowdownCounter == 0) {
-
-	size_t got = 0;
-	float *ib = timeStretcher->getInputBuffer();
-
-	for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
-
-	    RingBuffer<float> *rb = getReadRingBuffer(ch);
-
-	    if (rb) {
-
-		size_t request = count;
-		if (ch > 0) request = got; // see above
-		got = rb->read(buffer[ch], request);
-
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-		std::cout << "AudioCallbackPlaySource::getSamples: got " << got << " samples on channel " << ch << ", running time stretcher" << std::endl;
-#endif
-
-		for (size_t i = 0; i < count; ++i) {
-		    ib[i] = buffer[ch][i];
-		}
-	    
-		timeStretcher->run(ch);
-	    }
-	}
-
-    } else if (m_slowdownCounter >= timeStretcher->getFactor()) {
-	// reset this in case the factor has changed leaving the
-	// counter out of range
-	m_slowdownCounter = 0;
-    }
-
-    for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
-
-	float *ob = timeStretcher->getOutputBuffer(ch);
-
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-	std::cerr << "AudioCallbackPlaySource::getSamples: Copying from (" << (m_slowdownCounter * count) << "," << count << ") to buffer" << std::endl;
-#endif
-
-	for (size_t i = 0; i < count; ++i) {
-	    buffer[ch][i] = ob[m_slowdownCounter * count + i];
-	}
-    }
-
-//!!!    if (m_slowdownCounter == 0) m_condition.wakeAll();
-    m_slowdownCounter = (m_slowdownCounter + 1) % timeStretcher->getFactor();
-    return count;
-}
-
-// Called from fill thread, m_playing true, mutex held
-bool
-AudioCallbackPlaySource::fillBuffers()
-{
-    static float *tmp = 0;
-    static size_t tmpSize = 0;
-
-    size_t space = 0;
-    for (size_t c = 0; c < getTargetChannelCount(); ++c) {
-	RingBuffer<float> *wb = getWriteRingBuffer(c);
-	if (wb) {
-	    size_t spaceHere = wb->getWriteSpace();
-	    if (c == 0 || spaceHere < space) space = spaceHere;
-	}
-    }
-    
-    if (space == 0) return false;
-
-    size_t f = m_writeBufferFill;
-	
-    bool readWriteEqual = (m_readBuffers == m_writeBuffers);
-
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-    std::cout << "AudioCallbackPlaySourceFillThread: filling " << space << " frames" << std::endl;
-#endif
-
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-    std::cout << "buffered to " << f << " already" << std::endl;
-#endif
-
-    bool resample = (getSourceSampleRate() != getTargetSampleRate());
-
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-    std::cout << (resample ? "" : "not ") << "resampling (source " << getSourceSampleRate() << ", target " << getTargetSampleRate() << ")" << std::endl;
-#endif
-
-    size_t channels = getTargetChannelCount();
-
-    size_t orig = space;
-    size_t got = 0;
-
-    static float **bufferPtrs = 0;
-    static size_t bufferPtrCount = 0;
-
-    if (bufferPtrCount < channels) {
-	if (bufferPtrs) delete[] bufferPtrs;
-	bufferPtrs = new float *[channels];
-	bufferPtrCount = channels;
-    }
-
-    size_t generatorBlockSize = m_audioGenerator->getBlockSize();
-
-    if (resample && !m_converter) {
-	static bool warned = false;
-	if (!warned) {
-	    std::cerr << "WARNING: sample rates differ, but no converter available!" << std::endl;
-	    warned = true;
-	}
-    }
-
-    if (resample && m_converter) {
-
-	double ratio =
-	    double(getTargetSampleRate()) / double(getSourceSampleRate());
-	orig = size_t(orig / ratio + 0.1);
-
-	// orig must be a multiple of generatorBlockSize
-	orig = (orig / generatorBlockSize) * generatorBlockSize;
-	if (orig == 0) return false;
-
-	size_t work = std::max(orig, space);
-
-	// We only allocate one buffer, but we use it in two halves.
-	// We place the non-interleaved values in the second half of
-	// the buffer (orig samples for channel 0, orig samples for
-	// channel 1 etc), and then interleave them into the first
-	// half of the buffer.  Then we resample back into the second
-	// half (interleaved) and de-interleave the results back to
-	// the start of the buffer for insertion into the ringbuffers.
-	// What a faff -- especially as we've already de-interleaved
-	// the audio data from the source file elsewhere before we
-	// even reach this point.
-	
-	if (tmpSize < channels * work * 2) {
-	    delete[] tmp;
-	    tmp = new float[channels * work * 2];
-	    tmpSize = channels * work * 2;
-	}
-
-	float *nonintlv = tmp + channels * work;
-	float *intlv = tmp;
-	float *srcout = tmp + channels * work;
-	
-	for (size_t c = 0; c < channels; ++c) {
-	    for (size_t i = 0; i < orig; ++i) {
-		nonintlv[channels * i + c] = 0.0f;
-	    }
-	}
-
-	for (size_t c = 0; c < channels; ++c) {
-	    bufferPtrs[c] = nonintlv + c * orig;
-	}
-
-	got = mixModels(f, orig, bufferPtrs);
-
-	// and interleave into first half
-	for (size_t c = 0; c < channels; ++c) {
-	    for (size_t i = 0; i < got; ++i) {
-		float sample = nonintlv[c * got + i];
-		intlv[channels * i + c] = sample;
-	    }
-	}
-		
-	SRC_DATA data;
-	data.data_in = intlv;
-	data.data_out = srcout;
-	data.input_frames = got;
-	data.output_frames = work;
-	data.src_ratio = ratio;
-	data.end_of_input = 0;
-	
-	int err = src_process(m_converter, &data);
-//	size_t toCopy = size_t(work * ratio + 0.1);
-	size_t toCopy = size_t(got * ratio + 0.1);
-
-	if (err) {
-	    std::cerr
-		<< "AudioCallbackPlaySourceFillThread: ERROR in samplerate conversion: "
-		<< src_strerror(err) << std::endl;
-	    //!!! Then what?
-	} else {
-	    got = data.input_frames_used;
-	    toCopy = data.output_frames_gen;
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-	    std::cerr << "Resampled " << got << " frames to " << toCopy << " frames" << std::endl;
-#endif
-	}
-	
-	for (size_t c = 0; c < channels; ++c) {
-	    for (size_t i = 0; i < toCopy; ++i) {
-		tmp[i] = srcout[channels * i + c];
-	    }
-	    RingBuffer<float> *wb = getWriteRingBuffer(c);
-	    if (wb) wb->write(tmp, toCopy);
-	}
-
-	m_writeBufferFill = f;
-	if (readWriteEqual) m_readBufferFill = f;
-
-    } else {
-
-	// space must be a multiple of generatorBlockSize
-	space = (space / generatorBlockSize) * generatorBlockSize;
-	if (space == 0) return false;
-
-	if (tmpSize < channels * space) {
-	    delete[] tmp;
-	    tmp = new float[channels * space];
-	    tmpSize = channels * space;
-	}
-
-	for (size_t c = 0; c < channels; ++c) {
-
-	    bufferPtrs[c] = tmp + c * space;
-	    
-	    for (size_t i = 0; i < space; ++i) {
-		tmp[c * space + i] = 0.0f;
-	    }
-	}
-
-	size_t got = mixModels(f, space, bufferPtrs);
-
-	for (size_t c = 0; c < channels; ++c) {
-
-	    RingBuffer<float> *wb = getWriteRingBuffer(c);
-	    if (wb) wb->write(bufferPtrs[c], got);
-
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-	    if (wb)
-		std::cerr << "Wrote " << got << " frames for ch " << c << ", now "
-			  << wb->getReadSpace() << " to read" 
-			  << std::endl;
-#endif
-	}
-
-	m_writeBufferFill = f;
-	if (readWriteEqual) m_readBufferFill = f;
-
-	//!!! how do we know when ended? need to mark up a fully-buffered flag and check this if we find the buffers empty in getSourceSamples
-    }
-
-    return true;
-}    
-
-size_t
-AudioCallbackPlaySource::mixModels(size_t &frame, size_t count, float **buffers)
-{
-    size_t processed = 0;
-    size_t chunkStart = frame;
-    size_t chunkSize = count;
-    size_t selectionSize = 0;
-    size_t nextChunkStart = chunkStart + chunkSize;
-    
-    bool looping = m_viewManager->getPlayLoopMode();
-    bool constrained = (m_viewManager->getPlaySelectionMode() &&
-			!m_viewManager->getSelections().empty());
-
-    static float **chunkBufferPtrs = 0;
-    static size_t chunkBufferPtrCount = 0;
-    size_t channels = getTargetChannelCount();
-
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-    std::cerr << "Selection playback: start " << frame << ", size " << count <<", channels " << channels << std::endl;
-#endif
-
-    if (chunkBufferPtrCount < channels) {
-	if (chunkBufferPtrs) delete[] chunkBufferPtrs;
-	chunkBufferPtrs = new float *[channels];
-	chunkBufferPtrCount = channels;
-    }
-
-    for (size_t c = 0; c < channels; ++c) {
-	chunkBufferPtrs[c] = buffers[c];
-    }
-
-    while (processed < count) {
-	
-	chunkSize = count - processed;
-	nextChunkStart = chunkStart + chunkSize;
-	selectionSize = 0;
-
-	size_t fadeIn = 0, fadeOut = 0;
-
-	if (constrained) {
-	    
-	    Selection selection =
-		m_viewManager->getContainingSelection(chunkStart, true);
-	    
-	    if (selection.isEmpty()) {
-		if (looping) {
-		    selection = *m_viewManager->getSelections().begin();
-		    chunkStart = selection.getStartFrame();
-		    fadeIn = 50;
-		}
-	    }
-
-	    if (selection.isEmpty()) {
-
-		chunkSize = 0;
-		nextChunkStart = chunkStart;
-
-	    } else {
-
-		selectionSize =
-		    selection.getEndFrame() -
-		    selection.getStartFrame();
-
-		if (chunkStart < selection.getStartFrame()) {
-		    chunkStart = selection.getStartFrame();
-		    fadeIn = 50;
-		}
-
-		nextChunkStart = chunkStart + chunkSize;
-
-		if (nextChunkStart >= selection.getEndFrame()) {
-		    nextChunkStart = selection.getEndFrame();
-		    fadeOut = 50;
-		}
-
-		chunkSize = nextChunkStart - chunkStart;
-	    }
-	
-	} else if (looping && m_lastModelEndFrame > 0) {
-
-	    if (chunkStart >= m_lastModelEndFrame) {
-		chunkStart = 0;
-	    }
-	    if (chunkSize > m_lastModelEndFrame - chunkStart) {
-		chunkSize = m_lastModelEndFrame - chunkStart;
-	    }
-	    nextChunkStart = chunkStart + chunkSize;
-	}
-	
-//	std::cerr << "chunkStart " << chunkStart << ", chunkSize " << chunkSize << ", nextChunkStart " << nextChunkStart << ", frame " << frame << ", count " << count << ", processed " << processed << std::endl;
-
-	if (!chunkSize) {
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-	    std::cerr << "Ending selection playback at " << nextChunkStart << std::endl;
-#endif
-	    // We need to maintain full buffers so that the other
-	    // thread can tell where it's got to in the playback -- so
-	    // return the full amount here
-	    frame = frame + count;
-	    return count;
-	}
-
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-	std::cerr << "Selection playback: chunk at " << chunkStart << " -> " << nextChunkStart << " (size " << chunkSize << ")" << std::endl;
-#endif
-
-	size_t got = 0;
-
-	if (selectionSize < 100) {
-	    fadeIn = 0;
-	    fadeOut = 0;
-	} else if (selectionSize < 300) {
-	    if (fadeIn > 0) fadeIn = 10;
-	    if (fadeOut > 0) fadeOut = 10;
-	}
-
-	if (fadeIn > 0) {
-	    if (processed * 2 < fadeIn) {
-		fadeIn = processed * 2;
-	    }
-	}
-
-	if (fadeOut > 0) {
-	    if ((count - processed - chunkSize) * 2 < fadeOut) {
-		fadeOut = (count - processed - chunkSize) * 2;
-	    }
-	}
-
-	for (std::set<Model *>::iterator mi = m_models.begin();
-	     mi != m_models.end(); ++mi) {
-	    
-	    got = m_audioGenerator->mixModel(*mi, chunkStart, 
-					     chunkSize, chunkBufferPtrs,
-					     fadeIn, fadeOut);
-	}
-
-	for (size_t c = 0; c < channels; ++c) {
-	    chunkBufferPtrs[c] += chunkSize;
-	}
-
-	processed += chunkSize;
-	chunkStart = nextChunkStart;
-    }
-
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-    std::cerr << "Returning selection playback " << processed << " frames to " << nextChunkStart << std::endl;
-#endif
-
-    frame = nextChunkStart;
-    return processed;
-}
-
-void
-AudioCallbackPlaySource::unifyRingBuffers()
-{
-    if (m_readBuffers == m_writeBuffers) return;
-
-    // only unify if there will be something to read
-    for (size_t c = 0; c < getTargetChannelCount(); ++c) {
-	RingBuffer<float> *wb = getWriteRingBuffer(c);
-	if (wb) {
-	    if (wb->getReadSpace() < m_blockSize * 2) {
-		if ((m_writeBufferFill + m_blockSize * 2) < 
-		    m_lastModelEndFrame) {
-		    // OK, we don't have enough and there's more to
-		    // read -- don't unify until we can do better
-		    return;
-		}
-	    }
-	    break;
-	}
-    }
-
-    size_t rf = m_readBufferFill;
-    RingBuffer<float> *rb = getReadRingBuffer(0);
-    if (rb) {
-	size_t rs = rb->getReadSpace();
-	//!!! incorrect when in non-contiguous selection, see comments elsewhere
-//	std::cerr << "rs = " << rs << std::endl;
-	if (rs < rf) rf -= rs;
-	else rf = 0;
-    }
-    
-    //std::cerr << "m_readBufferFill = " << m_readBufferFill << ", rf = " << rf << ", m_writeBufferFill = " << m_writeBufferFill << std::endl;
-
-    size_t wf = m_writeBufferFill;
-    size_t skip = 0;
-    for (size_t c = 0; c < getTargetChannelCount(); ++c) {
-	RingBuffer<float> *wb = getWriteRingBuffer(c);
-	if (wb) {
-	    if (c == 0) {
-		
-		size_t wrs = wb->getReadSpace();
-//		std::cerr << "wrs = " << wrs << std::endl;
-
-		if (wrs < wf) wf -= wrs;
-		else wf = 0;
-//		std::cerr << "wf = " << wf << std::endl;
-		
-		if (wf < rf) skip = rf - wf;
-		if (skip == 0) break;
-	    }
-
-//	    std::cerr << "skipping " << skip << std::endl;
-	    wb->skip(skip);
-	}
-    }
-		    
-    m_bufferScavenger.claim(m_readBuffers);
-    m_readBuffers = m_writeBuffers;
-    m_readBufferFill = m_writeBufferFill;
-//    std::cerr << "unified" << std::endl;
-}
-
-void
-AudioCallbackPlaySource::AudioCallbackPlaySourceFillThread::run()
-{
-    AudioCallbackPlaySource &s(m_source);
-    
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-    std::cerr << "AudioCallbackPlaySourceFillThread starting" << std::endl;
-#endif
-
-    s.m_mutex.lock();
-
-    bool previouslyPlaying = s.m_playing;
-    bool work = false;
-
-    while (!s.m_exiting) {
-
-	s.unifyRingBuffers();
-	s.m_bufferScavenger.scavenge();
-	s.m_timeStretcherScavenger.scavenge();
-
-	if (work && s.m_playing && s.getSourceSampleRate()) {
-	    
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-	    std::cout << "AudioCallbackPlaySourceFillThread: not waiting" << std::endl;
-#endif
-
-	    s.m_mutex.unlock();
-	    s.m_mutex.lock();
-
-	} else {
-	    
-	    float ms = 100;
-	    if (s.getSourceSampleRate() > 0) {
-		ms = float(m_ringBufferSize) / float(s.getSourceSampleRate()) * 1000.0;
-	    }
-	    
-	    if (s.m_playing) ms /= 10;
-	    
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-	    std::cout << "AudioCallbackPlaySourceFillThread: waiting for " << ms << "ms..." << std::endl;
-#endif
-	    
-	    s.m_condition.wait(&s.m_mutex, size_t(ms));
-	}
-
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-	std::cout << "AudioCallbackPlaySourceFillThread: awoken" << std::endl;
-#endif
-
-	work = false;
-
-	if (!s.getSourceSampleRate()) continue;
-
-	bool playing = s.m_playing;
-
-	if (playing && !previouslyPlaying) {
-#ifdef DEBUG_AUDIO_PLAY_SOURCE
-	    std::cout << "AudioCallbackPlaySourceFillThread: playback state changed, resetting" << std::endl;
-#endif
-	    for (size_t c = 0; c < s.getTargetChannelCount(); ++c) {
-		RingBuffer<float> *rb = s.getReadRingBuffer(c);
-		if (rb) rb->reset();
-	    }
-	}
-	previouslyPlaying = playing;
-
-	work = s.fillBuffers();
-    }
-
-    s.m_mutex.unlock();
-}
-
-
-
-#ifdef INCLUDE_MOCFILES
-#include "AudioCallbackPlaySource.moc.cpp"
-#endif
-
--- a/audioio/AudioCallbackPlaySource.h	Thu Jul 27 16:06:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,306 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifndef _AUDIO_CALLBACK_PLAY_SOURCE_H_
-#define _AUDIO_CALLBACK_PLAY_SOURCE_H_
-
-#include "base/RingBuffer.h"
-#include "base/AudioPlaySource.h"
-#include "base/Scavenger.h"
-
-#include <QObject>
-#include <QMutex>
-#include <QWaitCondition>
-
-#include "base/Thread.h"
-
-#include <samplerate.h>
-
-#include <set>
-#include <map>
-
-class Model;
-class ViewManager;
-class AudioGenerator;
-class PlayParameters;
-class IntegerTimeStretcher;
-
-/**
- * AudioCallbackPlaySource manages audio data supply to callback-based
- * audio APIs such as JACK or CoreAudio.  It maintains one ring buffer
- * per channel, filled during playback by a non-realtime thread, and
- * provides a method for a realtime thread to pick up the latest
- * available sample data from these buffers.
- */
-class AudioCallbackPlaySource : public virtual QObject,
-				public AudioPlaySource
-{
-    Q_OBJECT
-
-public:
-    AudioCallbackPlaySource(ViewManager *);
-    virtual ~AudioCallbackPlaySource();
-    
-    /**
-     * Add a data model to be played from.  The source can mix
-     * playback from a number of sources including dense and sparse
-     * models.  The models must match in sample rate, but they don't
-     * have to have identical numbers of channels.
-     */
-    virtual void addModel(Model *model);
-
-    /**
-     * Remove a model.
-     */
-    virtual void removeModel(Model *model);
-
-    /**
-     * Remove all models.  (Silence will ensue.)
-     */
-    virtual void clearModels();
-
-    /**
-     * Start making data available in the ring buffers for playback,
-     * from the given frame.  If playback is already under way, reseek
-     * to the given frame and continue.
-     */
-    virtual void play(size_t startFrame);
-
-    /**
-     * Stop playback and ensure that no more data is returned.
-     */
-    virtual void stop();
-
-    /**
-     * Return whether playback is currently supposed to be happening.
-     */
-    virtual bool isPlaying() const { return m_playing; }
-
-    /**
-     * Return the frame number that is currently expected to be coming
-     * out of the speakers.  (i.e. compensating for playback latency.)
-     */
-    virtual size_t getCurrentPlayingFrame();
-
-    /**
-     * Set the block size of the target audio device.  This should
-     * be called by the target class.
-     */
-    void setTargetBlockSize(size_t);
-
-    /**
-     * Get the block size of the target audio device.
-     */
-    size_t getTargetBlockSize() const;
-
-    /**
-     * Set the playback latency of the target audio device, in frames
-     * at the target sample rate.  This is the difference between the
-     * frame currently "leaving the speakers" and the last frame (or
-     * highest last frame across all channels) requested via
-     * getSamples().  The default is zero.
-     */
-    void setTargetPlayLatency(size_t);
-
-    /**
-     * Get the playback latency of the target audio device.
-     */
-    size_t getTargetPlayLatency() const;
-
-    /**
-     * Specify that the target audio device has a fixed sample rate
-     * (i.e. cannot accommodate arbitrary sample rates based on the
-     * source).  If the target sets this to something other than the
-     * source sample rate, this class will resample automatically to
-     * fit.
-     */
-    void setTargetSampleRate(size_t);
-
-    /**
-     * Return the sample rate set by the target audio device (or the
-     * source sample rate if the target hasn't set one).
-     */
-    virtual size_t getTargetSampleRate() const;
-
-    /**
-     * Set the current output levels for metering (for call from the
-     * target)
-     */
-    void setOutputLevels(float left, float right);
-
-    /**
-     * Return the current (or thereabouts) output levels in the range
-     * 0.0 -> 1.0, for metering purposes.
-     */
-    virtual bool getOutputLevels(float &left, float &right);
-
-    /**
-     * Get the number of channels of audio that in the source models.
-     * This may safely be called from a realtime thread.  Returns 0 if
-     * there is no source yet available.
-     */
-    size_t getSourceChannelCount() const;
-
-    /**
-     * Get the number of channels of audio that will be provided
-     * to the play target.  This may be more than the source channel
-     * count: for example, a mono source will provide 2 channels
-     * after pan.
-     * This may safely be called from a realtime thread.  Returns 0 if
-     * there is no source yet available.
-     */
-    size_t getTargetChannelCount() const;
-
-    /**
-     * Get the actual sample rate of the source material.  This may
-     * safely be called from a realtime thread.  Returns 0 if there is
-     * no source yet available.
-     */
-    size_t getSourceSampleRate() const;
-
-    /**
-     * Get "count" samples (at the target sample rate) of the mixed
-     * audio data, in all channels.  This may safely be called from a
-     * realtime thread.
-     */
-    size_t getSourceSamples(size_t count, float **buffer);
-
-    void setSlowdownFactor(size_t factor);
-
-signals:
-    void modelReplaced();
-
-    void playStatusChanged(bool isPlaying);
-
-    void sampleRateMismatch(size_t requested, size_t available, bool willResample);
-
-protected slots:
-    void selectionChanged();
-    void playLoopModeChanged();
-    void playSelectionModeChanged();
-    void playParametersChanged(PlayParameters *);
-
-protected:
-    ViewManager                     *m_viewManager;
-    AudioGenerator                  *m_audioGenerator;
-
-    class RingBufferVector : public std::vector<RingBuffer<float> *> {
-    public:
-	virtual ~RingBufferVector() {
-	    while (!empty()) {
-		delete *begin();
-		erase(begin());
-	    }
-	}
-    };
-
-    std::set<Model *>                m_models;
-    RingBufferVector                *m_readBuffers;
-    RingBufferVector                *m_writeBuffers;
-    size_t                           m_readBufferFill;
-    size_t                           m_writeBufferFill;
-    Scavenger<RingBufferVector>      m_bufferScavenger;
-    size_t                           m_sourceChannelCount;
-    size_t                           m_blockSize;
-    size_t                           m_sourceSampleRate;
-    size_t                           m_targetSampleRate;
-    size_t                           m_playLatency;
-    bool                             m_playing;
-    bool                             m_exiting;
-    size_t                           m_lastModelEndFrame;
-    static const size_t              m_ringBufferSize;
-    float                            m_outputLeft;
-    float                            m_outputRight;
-
-    RingBuffer<float> *getWriteRingBuffer(size_t c) {
-	if (m_writeBuffers && c < m_writeBuffers->size()) {
-	    return (*m_writeBuffers)[c];
-	} else {
-	    return 0;
-	}
-    }
-
-    RingBuffer<float> *getReadRingBuffer(size_t c) {
-	RingBufferVector *rb = m_readBuffers;
-	if (rb && c < rb->size()) {
-	    return (*rb)[c];
-	} else {
-	    return 0;
-	}
-    }
-
-    void clearRingBuffers(bool haveLock = false, size_t count = 0);
-    void unifyRingBuffers();
-
-    class TimeStretcherData
-    {
-    public:
-	TimeStretcherData(size_t channels, size_t factor, size_t blockSize);
-	~TimeStretcherData();
-
-	size_t getFactor() const { return m_factor; }
-	IntegerTimeStretcher *getStretcher(size_t channel);
-	float *getOutputBuffer(size_t channel);
-	float *getInputBuffer();
-	
-	void run(size_t channel);
-
-    protected:
-	TimeStretcherData(const TimeStretcherData &); // not provided
-	TimeStretcherData &operator=(const TimeStretcherData &); // not provided
-
-	typedef std::pair<IntegerTimeStretcher *, float *> StretcherBuffer;
-	std::map<size_t, StretcherBuffer> m_stretcher;
-	float *m_stretchInputBuffer;
-	size_t m_factor;
-	size_t m_blockSize;
-    };
-
-    size_t m_slowdownCounter;
-    TimeStretcherData *m_timeStretcher;
-    Scavenger<TimeStretcherData> m_timeStretcherScavenger;
-
-    // Called from fill thread, m_playing true, mutex held
-    // Return true if work done
-    bool fillBuffers();
-    
-    // Called from fillBuffers.  Return the number of frames written,
-    // which will be count or fewer.  Return in the frame argument the
-    // new buffered frame position (which may be earlier than the
-    // frame argument passed in, in the case of looping).
-    size_t mixModels(size_t &frame, size_t count, float **buffers);
-
-    class AudioCallbackPlaySourceFillThread : public Thread
-    {
-    public:
-	AudioCallbackPlaySourceFillThread(AudioCallbackPlaySource &source) :
-            Thread(Thread::NonRTThread),
-	    m_source(source) { }
-
-	virtual void run();
-
-    protected:
-	AudioCallbackPlaySource &m_source;
-    };
-
-    QMutex m_mutex;
-    QWaitCondition m_condition;
-    AudioCallbackPlaySourceFillThread *m_fillThread;
-    SRC_STATE *m_converter;
-};
-
-#endif
-
-
--- a/audioio/AudioCallbackPlayTarget.cpp	Thu Jul 27 16:06:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#include "AudioCallbackPlayTarget.h"
-#include "AudioCallbackPlaySource.h"
-
-#include <iostream>
-
-AudioCallbackPlayTarget::AudioCallbackPlayTarget(AudioCallbackPlaySource *source) :
-    m_source(source),
-    m_outputGain(1.0)
-{
-    if (m_source) {
-	connect(m_source, SIGNAL(modelReplaced()),
-		this, SLOT(sourceModelReplaced()));
-    }
-}
-
-AudioCallbackPlayTarget::~AudioCallbackPlayTarget()
-{
-}
-
-void
-AudioCallbackPlayTarget::setOutputGain(float gain)
-{
-    m_outputGain = gain;
-}
-
-#ifdef INCLUDE_MOCFILES
-#ifdef INCLUDE_MOCFILES
-#include "AudioCallbackPlayTarget.moc.cpp"
-#endif
-#endif
-
--- a/audioio/AudioCallbackPlayTarget.h	Thu Jul 27 16:06:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifndef _AUDIO_CALLBACK_PLAY_TARGET_H_
-#define _AUDIO_CALLBACK_PLAY_TARGET_H_
-
-#include <QObject>
-
-class AudioCallbackPlaySource;
-
-class AudioCallbackPlayTarget : public QObject
-{
-    Q_OBJECT
-
-public:
-    AudioCallbackPlayTarget(AudioCallbackPlaySource *source);
-    virtual ~AudioCallbackPlayTarget();
-
-    virtual bool isOK() const = 0;
-
-    float getOutputGain() const {
-	return m_outputGain;
-    }
-
-public slots:
-    /**
-     * Set the playback gain (0.0 = silence, 1.0 = levels unmodified)
-     */
-    virtual void setOutputGain(float gain);
-
-    /**
-     * The main source model (providing the playback sample rate) has
-     * been changed.  The target should query the source's sample
-     * rate, set its output sample rate accordingly, and call back on
-     * the source's setTargetSampleRate to indicate what sample rate
-     * it succeeded in setting at the output.  If this differs from
-     * the model rate, the source will resample.
-     */
-    virtual void sourceModelReplaced() = 0;
-
-protected:
-    AudioCallbackPlaySource *m_source;
-    float m_outputGain;
-};
-
-#endif
-
--- a/audioio/AudioCoreAudioTarget.cpp	Thu Jul 27 16:06:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifdef HAVE_COREAUDIO
-
-#include "AudioCoreAudioTarget.h"
-
-
-
-#endif
--- a/audioio/AudioCoreAudioTarget.h	Thu Jul 27 16:06:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifndef _AUDIO_CORE_AUDIO_TARGET_H_
-#define _AUDIO_CORE_AUDIO_TARGET_H_
-
-#ifdef HAVE_COREAUDIO
-
-#include <jack/jack.h>
-#include <vector>
-
-#include <CoreAudio/CoreAudio.h>
-#include <CoreAudio/CoreAudioTypes.h>
-#include <AudioUnit/AUComponent.h>
-#include <AudioUnit/AudioUnitProperties.h>
-#include <AudioUnit/AudioUnitParameters.h>
-#include <AudioUnit/AudioOutputUnit.h>
-
-#include "AudioCallbackPlayTarget.h"
-
-class AudioCallbackPlaySource;
-
-class AudioCoreAudioTarget : public AudioCallbackPlayTarget
-{
-    Q_OBJECT
-
-public:
-    AudioCoreAudioTarget(AudioCallbackPlaySource *source);
-    ~AudioCoreAudioTarget();
-
-    virtual bool isOK() const;
-
-public slots:
-    virtual void sourceModelReplaced();
-
-protected:
-    OSStatus process(void *data,
-		     AudioUnitRenderActionFlags *flags,
-		     const AudioTimeStamp *timestamp,
-		     unsigned int inbus,
-		     unsigned int inframes,
-		     AudioBufferList *ioData);
-
-    int m_bufferSize;
-    int m_sampleRate;
-    int m_latency;
-};
-
-#endif /* HAVE_COREAUDIO */
-
-#endif
-
--- a/audioio/AudioGenerator.cpp	Thu Jul 27 16:06:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,764 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#include "AudioGenerator.h"
-
-#include "base/TempDirectory.h"
-#include "base/PlayParameters.h"
-#include "base/PlayParameterRepository.h"
-#include "base/Pitch.h"
-#include "base/Exceptions.h"
-
-#include "model/NoteModel.h"
-#include "model/DenseTimeValueModel.h"
-#include "model/SparseOneDimensionalModel.h"
-
-#include "plugin/RealTimePluginFactory.h"
-#include "plugin/RealTimePluginInstance.h"
-#include "plugin/PluginIdentifier.h"
-#include "plugin/PluginXml.h"
-#include "plugin/api/alsa/seq_event.h"
-
-#include <iostream>
-#include <math.h>
-
-#include <QDir>
-#include <QFile>
-
-const size_t
-AudioGenerator::m_pluginBlockSize = 2048;
-
-QString
-AudioGenerator::m_sampleDir = "";
-
-//#define DEBUG_AUDIO_GENERATOR 1
-
-AudioGenerator::AudioGenerator() :
-    m_sourceSampleRate(0),
-    m_targetChannelCount(1)
-{
-    connect(PlayParameterRepository::getInstance(),
-            SIGNAL(playPluginIdChanged(const Model *, QString)),
-            this,
-            SLOT(playPluginIdChanged(const Model *, QString)));
-
-    connect(PlayParameterRepository::getInstance(),
-            SIGNAL(playPluginConfigurationChanged(const Model *, QString)),
-            this,
-            SLOT(playPluginConfigurationChanged(const Model *, QString)));
-}
-
-AudioGenerator::~AudioGenerator()
-{
-}
-
-bool
-AudioGenerator::canPlay(const Model *model)
-{
-    if (dynamic_cast<const DenseTimeValueModel *>(model) ||
-	dynamic_cast<const SparseOneDimensionalModel *>(model) ||
-	dynamic_cast<const NoteModel *>(model)) {
-	return true;
-    } else {
-	return false;
-    }
-}
-
-bool
-AudioGenerator::addModel(Model *model)
-{
-    if (m_sourceSampleRate == 0) {
-
-	m_sourceSampleRate = model->getSampleRate();
-
-    } else {
-
-	DenseTimeValueModel *dtvm =
-	    dynamic_cast<DenseTimeValueModel *>(model);
-
-	if (dtvm) {
-	    m_sourceSampleRate = model->getSampleRate();
-	    return true;
-	}
-    }
-
-    RealTimePluginInstance *plugin = loadPluginFor(model);
-    if (plugin) {
-        QMutexLocker locker(&m_mutex);
-        m_synthMap[model] = plugin;
-        return true;
-    }
-
-    return false;
-}
-
-void
-AudioGenerator::playPluginIdChanged(const Model *model, QString)
-{
-    if (m_synthMap.find(model) == m_synthMap.end()) return;
-    
-    RealTimePluginInstance *plugin = loadPluginFor(model);
-    if (plugin) {
-        QMutexLocker locker(&m_mutex);
-        delete m_synthMap[model];
-        m_synthMap[model] = plugin;
-    }
-}
-
-void
-AudioGenerator::playPluginConfigurationChanged(const Model *model,
-                                               QString configurationXml)
-{
-//    std::cerr << "AudioGenerator::playPluginConfigurationChanged" << std::endl;
-
-    if (m_synthMap.find(model) == m_synthMap.end()) {
-        std::cerr << "AudioGenerator::playPluginConfigurationChanged: We don't know about this plugin" << std::endl;
-        return;
-    }
-
-    RealTimePluginInstance *plugin = m_synthMap[model];
-    if (plugin) {
-        PluginXml(plugin).setParametersFromXml(configurationXml);
-    }
-}
-
-QString
-AudioGenerator::getDefaultPlayPluginId(const Model *model)
-{
-    const SparseOneDimensionalModel *sodm =
-        dynamic_cast<const SparseOneDimensionalModel *>(model);
-    if (sodm) {
-        return QString("dssi:%1:sample_player").
-            arg(PluginIdentifier::BUILTIN_PLUGIN_SONAME);
-    }
-
-    const NoteModel *nm = dynamic_cast<const NoteModel *>(model);
-    if (nm) {
-        return QString("dssi:%1:sample_player").
-            arg(PluginIdentifier::BUILTIN_PLUGIN_SONAME);
-    }  
-    
-    return "";
-}
-
-QString
-AudioGenerator::getDefaultPlayPluginConfiguration(const Model *model)
-{
-    QString program = "";
-
-    const SparseOneDimensionalModel *sodm =
-        dynamic_cast<const SparseOneDimensionalModel *>(model);
-    if (sodm) {
-        program = "tap";
-    }
-
-    const NoteModel *nm = dynamic_cast<const NoteModel *>(model);
-    if (nm) {
-        program = "piano";
-    }
-
-    if (program == "") return "";
-
-    return
-        QString("<plugin configuration=\"%1\" program=\"%2\"/>")
-        .arg(XmlExportable::encodeEntities
-             (QString("sampledir=%1")
-              .arg(PluginXml::encodeConfigurationChars(getSampleDir()))))
-        .arg(XmlExportable::encodeEntities(program));
-}    
-
-QString
-AudioGenerator::getSampleDir()
-{
-    if (m_sampleDir != "") return m_sampleDir;
-
-    try {
-        m_sampleDir = TempDirectory::getInstance()->getSubDirectoryPath("samples");
-    } catch (DirectoryCreationFailed f) {
-        std::cerr << "WARNING: AudioGenerator::getSampleDir: Failed to create "
-                  << "temporary sample directory" << std::endl;
-        m_sampleDir = "";
-        return "";
-    }
-
-    QDir sampleResourceDir(":/samples", "*.wav");
-
-    for (unsigned int i = 0; i < sampleResourceDir.count(); ++i) {
-
-        QString fileName(sampleResourceDir[i]);
-        QFile file(sampleResourceDir.filePath(fileName));
-
-        if (!file.copy(QDir(m_sampleDir).filePath(fileName))) {
-            std::cerr << "WARNING: AudioGenerator::getSampleDir: "
-                      << "Unable to copy " << fileName.toStdString()
-                      << " into temporary directory \""
-                      << m_sampleDir.toStdString() << "\"" << std::endl;
-        }
-    }
-
-    return m_sampleDir;
-}
-
-void
-AudioGenerator::setSampleDir(RealTimePluginInstance *plugin)
-{
-    plugin->configure("sampledir", getSampleDir().toStdString());
-} 
-
-RealTimePluginInstance *
-AudioGenerator::loadPluginFor(const Model *model)
-{
-    QString pluginId, configurationXml;
-
-    PlayParameters *parameters =
-	PlayParameterRepository::getInstance()->getPlayParameters(model);
-    if (parameters) {
-        pluginId = parameters->getPlayPluginId();
-        configurationXml = parameters->getPlayPluginConfiguration();
-    }
-
-    if (pluginId == "") {
-        pluginId = getDefaultPlayPluginId(model);
-        configurationXml = getDefaultPlayPluginConfiguration(model);
-    }
-
-    if (pluginId == "") return 0;
-
-    RealTimePluginInstance *plugin = loadPlugin(pluginId, "");
-    if (!plugin) return 0;
-
-    if (configurationXml != "") {
-        PluginXml(plugin).setParametersFromXml(configurationXml);
-    }
-
-    if (parameters) {
-        parameters->setPlayPluginId(pluginId);
-        parameters->setPlayPluginConfiguration(configurationXml);
-    }
-
-    return plugin;
-}
-
-RealTimePluginInstance *
-AudioGenerator::loadPlugin(QString pluginId, QString program)
-{
-    RealTimePluginFactory *factory =
-	RealTimePluginFactory::instanceFor(pluginId);
-    
-    if (!factory) {
-	std::cerr << "Failed to get plugin factory" << std::endl;
-	return false;
-    }
-	
-    RealTimePluginInstance *instance =
-	factory->instantiatePlugin
-	(pluginId, 0, 0, m_sourceSampleRate, m_pluginBlockSize, m_targetChannelCount);
-
-    if (!instance) {
-	std::cerr << "Failed to instantiate plugin " << pluginId.toStdString() << std::endl;
-        return 0;
-    }
-
-    setSampleDir(instance);
-
-    for (unsigned int i = 0; i < instance->getParameterCount(); ++i) {
-        instance->setParameterValue(i, instance->getParameterDefault(i));
-    }
-    std::string defaultProgram = instance->getProgram(0, 0);
-    if (defaultProgram != "") {
-//        std::cerr << "first selecting default program " << defaultProgram << std::endl;
-        instance->selectProgram(defaultProgram);
-    }
-    if (program != "") {
-//        std::cerr << "now selecting desired program " << program.toStdString() << std::endl;
-        instance->selectProgram(program.toStdString());
-    }
-    instance->setIdealChannelCount(m_targetChannelCount); // reset!
-
-    return instance;
-}
-
-void
-AudioGenerator::removeModel(Model *model)
-{
-    SparseOneDimensionalModel *sodm =
-	dynamic_cast<SparseOneDimensionalModel *>(model);
-    if (!sodm) return; // nothing to do
-
-    QMutexLocker locker(&m_mutex);
-
-    if (m_synthMap.find(sodm) == m_synthMap.end()) return;
-
-    RealTimePluginInstance *instance = m_synthMap[sodm];
-    m_synthMap.erase(sodm);
-    delete instance;
-}
-
-void
-AudioGenerator::clearModels()
-{
-    QMutexLocker locker(&m_mutex);
-    while (!m_synthMap.empty()) {
-	RealTimePluginInstance *instance = m_synthMap.begin()->second;
-	m_synthMap.erase(m_synthMap.begin());
-	delete instance;
-    }
-}    
-
-void
-AudioGenerator::reset()
-{
-    QMutexLocker locker(&m_mutex);
-    for (PluginMap::iterator i = m_synthMap.begin(); i != m_synthMap.end(); ++i) {
-	if (i->second) {
-	    i->second->silence();
-	    i->second->discardEvents();
-	}
-    }
-
-    m_noteOffs.clear();
-}
-
-void
-AudioGenerator::setTargetChannelCount(size_t targetChannelCount)
-{
-    if (m_targetChannelCount == targetChannelCount) return;
-
-//    std::cerr << "AudioGenerator::setTargetChannelCount(" << targetChannelCount << ")" << std::endl;
-
-    QMutexLocker locker(&m_mutex);
-    m_targetChannelCount = targetChannelCount;
-
-    for (PluginMap::iterator i = m_synthMap.begin(); i != m_synthMap.end(); ++i) {
-	if (i->second) i->second->setIdealChannelCount(targetChannelCount);
-    }
-}
-
-size_t
-AudioGenerator::getBlockSize() const
-{
-    return m_pluginBlockSize;
-}
-
-size_t
-AudioGenerator::mixModel(Model *model, size_t startFrame, size_t frameCount,
-			 float **buffer, size_t fadeIn, size_t fadeOut)
-{
-    if (m_sourceSampleRate == 0) {
-	std::cerr << "WARNING: AudioGenerator::mixModel: No base source sample rate available" << std::endl;
-	return frameCount;
-    }
-
-    QMutexLocker locker(&m_mutex);
-
-    PlayParameters *parameters =
-	PlayParameterRepository::getInstance()->getPlayParameters(model);
-    if (!parameters) return frameCount;
-
-    bool playing = !parameters->isPlayMuted();
-    if (!playing) return frameCount;
-
-    float gain = parameters->getPlayGain();
-    float pan = parameters->getPlayPan();
-
-    DenseTimeValueModel *dtvm = dynamic_cast<DenseTimeValueModel *>(model);
-    if (dtvm) {
-	return mixDenseTimeValueModel(dtvm, startFrame, frameCount,
-				      buffer, gain, pan, fadeIn, fadeOut);
-    }
-
-    SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *>
-	(model);
-    if (sodm) {
-	return mixSparseOneDimensionalModel(sodm, startFrame, frameCount,
-					    buffer, gain, pan, fadeIn, fadeOut);
-    }
-
-    NoteModel *nm = dynamic_cast<NoteModel *>(model);
-    if (nm) {
-	return mixNoteModel(nm, startFrame, frameCount,
-			    buffer, gain, pan, fadeIn, fadeOut);
-    }
-
-    return frameCount;
-}
-
-size_t
-AudioGenerator::mixDenseTimeValueModel(DenseTimeValueModel *dtvm,
-				       size_t startFrame, size_t frames,
-				       float **buffer, float gain, float pan,
-				       size_t fadeIn, size_t fadeOut)
-{
-    static float *channelBuffer = 0;
-    static size_t channelBufSiz = 0;
-
-    size_t totalFrames = frames + fadeIn/2 + fadeOut/2;
-
-    if (channelBufSiz < totalFrames) {
-	delete[] channelBuffer;
-	channelBuffer = new float[totalFrames];
-	channelBufSiz = totalFrames;
-    }
-    
-    size_t got = 0;
-    size_t prevChannel = 999;
-
-    for (size_t c = 0; c < m_targetChannelCount; ++c) {
-
-	size_t sourceChannel = (c % dtvm->getChannelCount());
-
-//	std::cerr << "mixing channel " << c << " from source channel " << sourceChannel << std::endl;
-
-	float channelGain = gain;
-	if (pan != 0.0) {
-	    if (c == 0) {
-		if (pan > 0.0) channelGain *= 1.0 - pan;
-	    } else {
-		if (pan < 0.0) channelGain *= pan + 1.0;
-	    }
-	}
-
-	if (prevChannel != sourceChannel) {
-	    if (startFrame >= fadeIn/2) {
-		got = dtvm->getValues
-		    (sourceChannel,
-		     startFrame - fadeIn/2, startFrame + frames + fadeOut/2,
-		     channelBuffer);
-	    } else {
-		size_t missing = fadeIn/2 - startFrame;
-		got = dtvm->getValues
-		    (sourceChannel,
-		     0, startFrame + frames + fadeOut/2,
-		     channelBuffer + missing);
-	    }	    
-	}
-	prevChannel = sourceChannel;
-
-	for (size_t i = 0; i < fadeIn/2; ++i) {
-	    float *back = buffer[c];
-	    back -= fadeIn/2;
-	    back[i] += (channelGain * channelBuffer[i] * i) / fadeIn;
-	}
-
-	for (size_t i = 0; i < frames + fadeOut/2; ++i) {
-	    float mult = channelGain;
-	    if (i < fadeIn/2) {
-		mult = (mult * i) / fadeIn;
-	    }
-	    if (i > frames - fadeOut/2) {
-		mult = (mult * ((frames + fadeOut/2) - i)) / fadeOut;
-	    }
-	    buffer[c][i] += mult * channelBuffer[i];
-	}
-    }
-
-    return got;
-}
-  
-size_t
-AudioGenerator::mixSparseOneDimensionalModel(SparseOneDimensionalModel *sodm,
-					     size_t startFrame, size_t frames,
-					     float **buffer, float gain, float pan,
-					     size_t /* fadeIn */,
-					     size_t /* fadeOut */)
-{
-    RealTimePluginInstance *plugin = m_synthMap[sodm];
-    if (!plugin) return 0;
-
-    size_t latency = plugin->getLatency();
-    size_t blocks = frames / m_pluginBlockSize;
-    
-    //!!! hang on -- the fact that the audio callback play source's
-    //buffer is a multiple of the plugin's buffer size doesn't mean
-    //that we always get called for a multiple of it here (because it
-    //also depends on the JACK block size).  how should we ensure that
-    //all models write the same amount in to the mix, and that we
-    //always have a multiple of the plugin buffer size?  I guess this
-    //class has to be queryable for the plugin buffer size & the
-    //callback play source has to use that as a multiple for all the
-    //calls to mixModel
-
-    size_t got = blocks * m_pluginBlockSize;
-
-#ifdef DEBUG_AUDIO_GENERATOR
-    std::cout << "mixModel [sparse]: frames " << frames
-	      << ", blocks " << blocks << std::endl;
-#endif
-
-    snd_seq_event_t onEv;
-    onEv.type = SND_SEQ_EVENT_NOTEON;
-    onEv.data.note.channel = 0;
-    onEv.data.note.note = 64;
-    onEv.data.note.velocity = 127;
-
-    snd_seq_event_t offEv;
-    offEv.type = SND_SEQ_EVENT_NOTEOFF;
-    offEv.data.note.channel = 0;
-    offEv.data.note.velocity = 0;
-    
-    NoteOffSet &noteOffs = m_noteOffs[sodm];
-
-    for (size_t i = 0; i < blocks; ++i) {
-
-	size_t reqStart = startFrame + i * m_pluginBlockSize;
-
-	SparseOneDimensionalModel::PointList points =
-	    sodm->getPoints(reqStart + latency,
-			    reqStart + latency + m_pluginBlockSize);
-
-        Vamp::RealTime blockTime = Vamp::RealTime::frame2RealTime
-	    (startFrame + i * m_pluginBlockSize, m_sourceSampleRate);
-
-	for (SparseOneDimensionalModel::PointList::iterator pli =
-		 points.begin(); pli != points.end(); ++pli) {
-
-	    size_t pliFrame = pli->frame;
-
-	    if (pliFrame >= latency) pliFrame -= latency;
-
-	    if (pliFrame < reqStart ||
-		pliFrame >= reqStart + m_pluginBlockSize) continue;
-
-	    while (noteOffs.begin() != noteOffs.end() &&
-		   noteOffs.begin()->frame <= pliFrame) {
-
-                Vamp::RealTime eventTime = Vamp::RealTime::frame2RealTime
-		    (noteOffs.begin()->frame, m_sourceSampleRate);
-
-		offEv.data.note.note = noteOffs.begin()->pitch;
-
-#ifdef DEBUG_AUDIO_GENERATOR
-		std::cerr << "mixModel [sparse]: sending note-off event at time " << eventTime << " frame " << noteOffs.begin()->frame << std::endl;
-#endif
-
-		plugin->sendEvent(eventTime, &offEv);
-		noteOffs.erase(noteOffs.begin());
-	    }
-
-            Vamp::RealTime eventTime = Vamp::RealTime::frame2RealTime
-		(pliFrame, m_sourceSampleRate);
-	    
-	    plugin->sendEvent(eventTime, &onEv);
-
-#ifdef DEBUG_AUDIO_GENERATOR
-	    std::cout << "mixModel [sparse]: point at frame " << pliFrame << ", block start " << (startFrame + i * m_pluginBlockSize) << ", resulting time " << eventTime << std::endl;
-#endif
-	    
-	    size_t duration = 7000; // frames [for now]
-	    NoteOff noff;
-	    noff.pitch = onEv.data.note.note;
-	    noff.frame = pliFrame + duration;
-	    noteOffs.insert(noff);
-	}
-
-	while (noteOffs.begin() != noteOffs.end() &&
-	       noteOffs.begin()->frame <=
-	       startFrame + i * m_pluginBlockSize + m_pluginBlockSize) {
-
-            Vamp::RealTime eventTime = Vamp::RealTime::frame2RealTime
-		(noteOffs.begin()->frame, m_sourceSampleRate);
-
-	    offEv.data.note.note = noteOffs.begin()->pitch;
-
-#ifdef DEBUG_AUDIO_GENERATOR
-		std::cerr << "mixModel [sparse]: sending leftover note-off event at time " << eventTime << " frame " << noteOffs.begin()->frame << std::endl;
-#endif
-
-	    plugin->sendEvent(eventTime, &offEv);
-	    noteOffs.erase(noteOffs.begin());
-	}
-	
-	plugin->run(blockTime);
-	float **outs = plugin->getAudioOutputBuffers();
-
-	for (size_t c = 0; c < m_targetChannelCount; ++c) {
-#ifdef DEBUG_AUDIO_GENERATOR
-	    std::cout << "mixModel [sparse]: adding " << m_pluginBlockSize << " samples from plugin output " << c << std::endl;
-#endif
-
-	    size_t sourceChannel = (c % plugin->getAudioOutputCount());
-
-	    float channelGain = gain;
-	    if (pan != 0.0) {
-		if (c == 0) {
-		    if (pan > 0.0) channelGain *= 1.0 - pan;
-		} else {
-		    if (pan < 0.0) channelGain *= pan + 1.0;
-		}
-	    }
-
-	    for (size_t j = 0; j < m_pluginBlockSize; ++j) {
-		buffer[c][i * m_pluginBlockSize + j] +=
-		    channelGain * outs[sourceChannel][j];
-	    }
-	}
-    }
-
-    return got;
-}
-
-    
-//!!! mucho duplication with above -- refactor
-size_t
-AudioGenerator::mixNoteModel(NoteModel *nm,
-			     size_t startFrame, size_t frames,
-			     float **buffer, float gain, float pan,
-			     size_t /* fadeIn */,
-			     size_t /* fadeOut */)
-{
-    RealTimePluginInstance *plugin = m_synthMap[nm];
-    if (!plugin) return 0;
-
-    size_t latency = plugin->getLatency();
-    size_t blocks = frames / m_pluginBlockSize;
-    
-    //!!! hang on -- the fact that the audio callback play source's
-    //buffer is a multiple of the plugin's buffer size doesn't mean
-    //that we always get called for a multiple of it here (because it
-    //also depends on the JACK block size).  how should we ensure that
-    //all models write the same amount in to the mix, and that we
-    //always have a multiple of the plugin buffer size?  I guess this
-    //class has to be queryable for the plugin buffer size & the
-    //callback play source has to use that as a multiple for all the
-    //calls to mixModel
-
-    size_t got = blocks * m_pluginBlockSize;
-
-#ifdef DEBUG_AUDIO_GENERATOR
-    std::cout << "mixModel [note]: frames " << frames
-	      << ", blocks " << blocks << std::endl;
-#endif
-
-    snd_seq_event_t onEv;
-    onEv.type = SND_SEQ_EVENT_NOTEON;
-    onEv.data.note.channel = 0;
-    onEv.data.note.note = 64;
-    onEv.data.note.velocity = 127;
-
-    snd_seq_event_t offEv;
-    offEv.type = SND_SEQ_EVENT_NOTEOFF;
-    offEv.data.note.channel = 0;
-    offEv.data.note.velocity = 0;
-    
-    NoteOffSet &noteOffs = m_noteOffs[nm];
-
-    for (size_t i = 0; i < blocks; ++i) {
-
-	size_t reqStart = startFrame + i * m_pluginBlockSize;
-
-	NoteModel::PointList points =
-	    nm->getPoints(reqStart + latency,
-			    reqStart + latency + m_pluginBlockSize);
-
-        Vamp::RealTime blockTime = Vamp::RealTime::frame2RealTime
-	    (startFrame + i * m_pluginBlockSize, m_sourceSampleRate);
-
-	for (NoteModel::PointList::iterator pli =
-		 points.begin(); pli != points.end(); ++pli) {
-
-	    size_t pliFrame = pli->frame;
-
-	    if (pliFrame >= latency) pliFrame -= latency;
-
-	    if (pliFrame < reqStart ||
-		pliFrame >= reqStart + m_pluginBlockSize) continue;
-
-	    while (noteOffs.begin() != noteOffs.end() &&
-		   noteOffs.begin()->frame <= pliFrame) {
-
-                Vamp::RealTime eventTime = Vamp::RealTime::frame2RealTime
-		    (noteOffs.begin()->frame, m_sourceSampleRate);
-
-		offEv.data.note.note = noteOffs.begin()->pitch;
-
-#ifdef DEBUG_AUDIO_GENERATOR
-		std::cerr << "mixModel [note]: sending note-off event at time " << eventTime << " frame " << noteOffs.begin()->frame << std::endl;
-#endif
-
-		plugin->sendEvent(eventTime, &offEv);
-		noteOffs.erase(noteOffs.begin());
-	    }
-
-            Vamp::RealTime eventTime = Vamp::RealTime::frame2RealTime
-		(pliFrame, m_sourceSampleRate);
-	    
-            if (nm->getScaleUnits() == "Hz") {
-                onEv.data.note.note = Pitch::getPitchForFrequency(pli->value);
-            } else {
-                onEv.data.note.note = lrintf(pli->value);
-            }
-
-	    plugin->sendEvent(eventTime, &onEv);
-
-#ifdef DEBUG_AUDIO_GENERATOR
-	    std::cout << "mixModel [note]: point at frame " << pliFrame << ", block start " << (startFrame + i * m_pluginBlockSize) << ", resulting time " << eventTime << std::endl;
-#endif
-	    
-	    size_t duration = pli->duration;
-            if (duration == 0 || duration == 1) {
-                duration = m_sourceSampleRate / 20;
-            }
-	    NoteOff noff;
-	    noff.pitch = onEv.data.note.note;
-	    noff.frame = pliFrame + duration;
-	    noteOffs.insert(noff);
-	}
-
-	while (noteOffs.begin() != noteOffs.end() &&
-	       noteOffs.begin()->frame <=
-	       startFrame + i * m_pluginBlockSize + m_pluginBlockSize) {
-
-            Vamp::RealTime eventTime = Vamp::RealTime::frame2RealTime
-		(noteOffs.begin()->frame, m_sourceSampleRate);
-
-	    offEv.data.note.note = noteOffs.begin()->pitch;
-
-#ifdef DEBUG_AUDIO_GENERATOR
-		std::cerr << "mixModel [note]: sending leftover note-off event at time " << eventTime << " frame " << noteOffs.begin()->frame << std::endl;
-#endif
-
-	    plugin->sendEvent(eventTime, &offEv);
-	    noteOffs.erase(noteOffs.begin());
-	}
-	
-	plugin->run(blockTime);
-	float **outs = plugin->getAudioOutputBuffers();
-
-	for (size_t c = 0; c < m_targetChannelCount; ++c) {
-#ifdef DEBUG_AUDIO_GENERATOR
-	    std::cout << "mixModel [note]: adding " << m_pluginBlockSize << " samples from plugin output " << c << std::endl;
-#endif
-
-	    size_t sourceChannel = (c % plugin->getAudioOutputCount());
-
-	    float channelGain = gain;
-	    if (pan != 0.0) {
-		if (c == 0) {
-		    if (pan > 0.0) channelGain *= 1.0 - pan;
-		} else {
-		    if (pan < 0.0) channelGain *= pan + 1.0;
-		}
-	    }
-
-	    for (size_t j = 0; j < m_pluginBlockSize; ++j) {
-		buffer[c][i * m_pluginBlockSize + j] += 
-		    channelGain * outs[sourceChannel][j];
-	    }
-	}
-    }
-
-    return got;
-}
-
--- a/audioio/AudioGenerator.h	Thu Jul 27 16:06:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifndef _AUDIO_GENERATOR_H_
-#define _AUDIO_GENERATOR_H_
-
-class Model;
-class NoteModel;
-class DenseTimeValueModel;
-class SparseOneDimensionalModel;
-class RealTimePluginInstance;
-
-#include <QObject>
-#include <QMutex>
-
-#include <set>
-#include <map>
-
-class AudioGenerator : public QObject
-{
-    Q_OBJECT
-
-public:
-    AudioGenerator();
-    virtual ~AudioGenerator();
-
-    /**
-     * Return true if the given model is of a type that we generally
-     * know how to play.  This doesn't guarantee that a specific
-     * AudioGenerator will actually produce sounds for it (for
-     * example, it may turn out that a vital plugin is missing).
-     */
-    static bool canPlay(const Model *model);
-
-    static QString getDefaultPlayPluginId(const Model *model);
-    static QString getDefaultPlayPluginConfiguration(const Model *model);
-
-    /**
-     * Add a data model to be played from and initialise any necessary
-     * audio generation code.  Returns true if the model will be
-     * played.  (The return value test here is stricter than that for
-     * canPlay, above.)  The model will be added regardless of the
-     * return value.
-     */
-    virtual bool addModel(Model *model);
-
-    /**
-     * Remove a model.
-     */
-    virtual void removeModel(Model *model);
-
-    /**
-     * Remove all models.
-     */
-    virtual void clearModels();
-
-    /**
-     * Reset playback, clearing plugins and the like.
-     */
-    virtual void reset();
-
-    /**
-     * Set the target channel count.  The buffer parameter to mixModel
-     * must always point to at least this number of arrays.
-     */
-    virtual void setTargetChannelCount(size_t channelCount);
-
-    /**
-     * Return the internal processing block size.  The frameCount
-     * argument to all mixModel calls must be a multiple of this
-     * value.
-     */
-    virtual size_t getBlockSize() const;
-
-    /**
-     * Mix a single model into an output buffer.
-     */
-    virtual size_t mixModel(Model *model, size_t startFrame, size_t frameCount,
-			    float **buffer, size_t fadeIn = 0, size_t fadeOut = 0);
-
-protected slots:
-    void playPluginIdChanged(const Model *, QString);
-    void playPluginConfigurationChanged(const Model *, QString);
-
-protected:
-    size_t       m_sourceSampleRate;
-    size_t       m_targetChannelCount;
-
-    struct NoteOff {
-
-	int pitch;
-	size_t frame;
-
-	struct Comparator {
-	    bool operator()(const NoteOff &n1, const NoteOff &n2) const {
-		return n1.frame < n2.frame;
-	    }
-	};
-    };
-
-    typedef std::map<const Model *, RealTimePluginInstance *> PluginMap;
-
-    typedef std::set<NoteOff, NoteOff::Comparator> NoteOffSet;
-    typedef std::map<const Model *, NoteOffSet> NoteOffMap;
-
-    QMutex m_mutex;
-    PluginMap m_synthMap;
-    NoteOffMap m_noteOffs;
-    static QString m_sampleDir;
-
-    virtual RealTimePluginInstance *loadPluginFor(const Model *model);
-    virtual RealTimePluginInstance *loadPlugin(QString id, QString program);
-    static QString getSampleDir();
-    static void setSampleDir(RealTimePluginInstance *plugin);
-
-    virtual size_t mixDenseTimeValueModel
-    (DenseTimeValueModel *model, size_t startFrame, size_t frameCount,
-     float **buffer, float gain, float pan, size_t fadeIn, size_t fadeOut);
-
-    virtual size_t mixSparseOneDimensionalModel
-    (SparseOneDimensionalModel *model, size_t startFrame, size_t frameCount,
-     float **buffer, float gain, float pan, size_t fadeIn, size_t fadeOut);
-
-    virtual size_t mixNoteModel
-    (NoteModel *model, size_t startFrame, size_t frameCount,
-     float **buffer, float gain, float pan, size_t fadeIn, size_t fadeOut);
-
-    static const size_t m_pluginBlockSize;
-};
-
-#endif
-
--- a/audioio/AudioJACKTarget.cpp	Thu Jul 27 16:06:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifdef HAVE_JACK
-
-#include "AudioJACKTarget.h"
-#include "AudioCallbackPlaySource.h"
-
-#include <iostream>
-#include <cmath>
-
-//#define DEBUG_AUDIO_JACK_TARGET 1
-
-AudioJACKTarget::AudioJACKTarget(AudioCallbackPlaySource *source) :
-    AudioCallbackPlayTarget(source),
-    m_client(0),
-    m_bufferSize(0),
-    m_sampleRate(0)
-{
-    char name[20];
-    strcpy(name, "Sonic Visualiser");
-    m_client = jack_client_new(name);
-
-    if (!m_client) {
-	sprintf(name, "Sonic Visualiser (%d)", (int)getpid());
-	m_client = jack_client_new(name);
-	if (!m_client) {
-	    std::cerr
-		<< "ERROR: AudioJACKTarget: Failed to connect to JACK server"
-		<< std::endl;
-	}
-    }
-
-    if (!m_client) return;
-
-    m_bufferSize = jack_get_buffer_size(m_client);
-    m_sampleRate = jack_get_sample_rate(m_client);
-
-    jack_set_process_callback(m_client, processStatic, this);
-
-    if (jack_activate(m_client)) {
-	std::cerr << "ERROR: AudioJACKTarget: Failed to activate JACK client"
-		  << std::endl;
-    }
-
-    if (m_source) {
-	sourceModelReplaced();
-    }
-}
-
-AudioJACKTarget::~AudioJACKTarget()
-{
-    if (m_client) {
-	jack_deactivate(m_client);
-	jack_client_close(m_client);
-    }
-}
-
-bool
-AudioJACKTarget::isOK() const
-{
-    return (m_client != 0);
-}
-
-int
-AudioJACKTarget::processStatic(jack_nframes_t nframes, void *arg)
-{
-    return ((AudioJACKTarget *)arg)->process(nframes);
-}
-
-void
-AudioJACKTarget::sourceModelReplaced()
-{
-    m_mutex.lock();
-
-    m_source->setTargetBlockSize(m_bufferSize);
-    m_source->setTargetSampleRate(m_sampleRate);
-
-    size_t channels = m_source->getSourceChannelCount();
-
-    // Because we offer pan, we always want at least 2 channels
-    if (channels < 2) channels = 2;
-
-    if (channels == m_outputs.size() || !m_client) {
-	m_mutex.unlock();
-	return;
-    }
-
-    const char **ports =
-	jack_get_ports(m_client, NULL, NULL,
-		       JackPortIsPhysical | JackPortIsInput);
-    size_t physicalPortCount = 0;
-    while (ports[physicalPortCount]) ++physicalPortCount;
-
-#ifdef DEBUG_AUDIO_JACK_TARGET    
-    std::cerr << "AudioJACKTarget::sourceModelReplaced: have " << channels << " channels and " << physicalPortCount << " physical ports" << std::endl;
-#endif
-
-    while (m_outputs.size() < channels) {
-	
-	char name[20];
-	jack_port_t *port;
-
-	sprintf(name, "out %d", m_outputs.size() + 1);
-
-	port = jack_port_register(m_client,
-				  name,
-				  JACK_DEFAULT_AUDIO_TYPE,
-				  JackPortIsOutput,
-				  0);
-
-	if (!port) {
-	    std::cerr
-		<< "ERROR: AudioJACKTarget: Failed to create JACK output port "
-		<< m_outputs.size() << std::endl;
-	} else {
-	    m_source->setTargetPlayLatency(jack_port_get_latency(port));
-	}
-
-	if (m_outputs.size() < physicalPortCount) {
-	    jack_connect(m_client, jack_port_name(port), ports[m_outputs.size()]);
-	}
-
-	m_outputs.push_back(port);
-    }
-
-    while (m_outputs.size() > channels) {
-	std::vector<jack_port_t *>::iterator itr = m_outputs.end();
-	--itr;
-	jack_port_t *port = *itr;
-	if (port) jack_port_unregister(m_client, port);
-	m_outputs.erase(itr);
-    }
-
-    m_mutex.unlock();
-}
-
-int
-AudioJACKTarget::process(jack_nframes_t nframes)
-{
-    if (!m_mutex.tryLock()) {
-	return 0;
-    }
-
-    if (m_outputs.empty()) {
-	m_mutex.unlock();
-	return 0;
-    }
-
-#ifdef DEBUG_AUDIO_JACK_TARGET    
-    std::cout << "AudioJACKTarget::process(" << nframes << "): have a source" << std::endl;
-#endif
-
-#ifdef DEBUG_AUDIO_JACK_TARGET    
-    if (m_bufferSize != nframes) {
-	std::cerr << "WARNING: m_bufferSize != nframes (" << m_bufferSize << " != " << nframes << ")" << std::endl;
-    }
-#endif
-
-    float **buffers = (float **)alloca(m_outputs.size() * sizeof(float *));
-
-    for (size_t ch = 0; ch < m_outputs.size(); ++ch) {
-	buffers[ch] = (float *)jack_port_get_buffer(m_outputs[ch], nframes);
-    }
-
-    if (m_source) {
-	m_source->getSourceSamples(nframes, buffers);
-    } else {
-	for (size_t ch = 0; ch < m_outputs.size(); ++ch) {
-	    for (size_t i = 0; i < nframes; ++i) {
-		buffers[ch][i] = 0.0;
-	    }
-	}
-    }
-
-    float peakLeft = 0.0, peakRight = 0.0;
-
-    for (size_t ch = 0; ch < m_outputs.size(); ++ch) {
-
-	float peak = 0.0;
-
-	for (size_t i = 0; i < nframes; ++i) {
-	    buffers[ch][i] *= m_outputGain;
-	    float sample = fabsf(buffers[ch][i]);
-	    if (sample > peak) peak = sample;
-	}
-
-	if (ch == 0) peakLeft = peak;
-	if (ch > 0 || m_outputs.size() == 1) peakRight = peak;
-    }
-	    
-    if (m_source) {
-	m_source->setOutputLevels(peakLeft, peakRight);
-    }
-
-    m_mutex.unlock();
-    return 0;
-}
-
-
-#ifdef INCLUDE_MOCFILES
-#include "AudioJACKTarget.moc.cpp"
-#endif
-
-#endif /* HAVE_JACK */
-
--- a/audioio/AudioJACKTarget.h	Thu Jul 27 16:06:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifndef _AUDIO_JACK_TARGET_H_
-#define _AUDIO_JACK_TARGET_H_
-
-#ifdef HAVE_JACK
-
-#include <jack/jack.h>
-#include <vector>
-
-#include "AudioCallbackPlayTarget.h"
-
-#include <QMutex>
-
-class AudioCallbackPlaySource;
-
-class AudioJACKTarget : public AudioCallbackPlayTarget
-{
-    Q_OBJECT
-
-public:
-    AudioJACKTarget(AudioCallbackPlaySource *source);
-    virtual ~AudioJACKTarget();
-
-    virtual bool isOK() const;
-
-public slots:
-    virtual void sourceModelReplaced();
-
-protected:
-    int process(jack_nframes_t nframes);
-
-    static int processStatic(jack_nframes_t, void *);
-
-    jack_client_t              *m_client;
-    std::vector<jack_port_t *>  m_outputs;
-    jack_nframes_t              m_bufferSize;
-    jack_nframes_t              m_sampleRate;
-    QMutex                      m_mutex;
-};
-
-#endif /* HAVE_JACK */
-
-#endif
-
--- a/audioio/AudioPortAudioTarget.cpp	Thu Jul 27 16:06:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,201 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifdef HAVE_PORTAUDIO
-
-#include "AudioPortAudioTarget.h"
-#include "AudioCallbackPlaySource.h"
-
-#include <iostream>
-#include <cassert>
-#include <cmath>
-
-//#define DEBUG_AUDIO_PORT_AUDIO_TARGET 1
-
-AudioPortAudioTarget::AudioPortAudioTarget(AudioCallbackPlaySource *source) :
-    AudioCallbackPlayTarget(source),
-    m_stream(0),
-    m_bufferSize(0),
-    m_sampleRate(0),
-    m_latency(0)
-{
-    PaError err;
-
-    err = Pa_Initialize();
-    if (err != paNoError) {
-	std::cerr << "ERROR: AudioPortAudioTarget: Failed to initialize PortAudio" << std::endl;
-	return;
-    }
-
-    m_bufferSize = 1024;
-    m_sampleRate = 44100;
-    if (m_source && (m_source->getSourceSampleRate() != 0)) {
-	m_sampleRate = m_source->getSourceSampleRate();
-    }
-
-    m_latency = Pa_GetMinNumBuffers(m_bufferSize, m_sampleRate) * m_bufferSize;
-
-    std::cerr << "\n\n\nLATENCY= " << m_latency << std::endl;
-
-    err = Pa_OpenDefaultStream(&m_stream, 0, 2, paFloat32,
-			       m_sampleRate, m_bufferSize, 0,
-			       processStatic, this);
-
-    if (err != paNoError) {
-	std::cerr << "ERROR: AudioPortAudioTarget: Failed to open PortAudio stream" << std::endl;
-	m_stream = 0;
-	Pa_Terminate();
-	return;
-    }
-
-    err = Pa_StartStream(m_stream);
-
-    if (err != paNoError) {
-	std::cerr << "ERROR: AudioPortAudioTarget: Failed to start PortAudio stream" << std::endl;
-	Pa_CloseStream(m_stream);
-	m_stream = 0;
-	Pa_Terminate();
-	return;
-    }
-
-    if (m_source) {
-	std::cerr << "AudioPortAudioTarget: block size " << m_bufferSize << std::endl;
-	m_source->setTargetBlockSize(m_bufferSize);
-	m_source->setTargetSampleRate(m_sampleRate);
-	m_source->setTargetPlayLatency(m_latency);
-    }
-}
-
-AudioPortAudioTarget::~AudioPortAudioTarget()
-{
-    if (m_stream) {
-	PaError err;
-	err = Pa_CloseStream(m_stream);
-	if (err != paNoError) {
-	    std::cerr << "ERROR: AudioPortAudioTarget: Failed to close PortAudio stream" << std::endl;
-	}
-	Pa_Terminate();
-    }
-}
-
-bool
-AudioPortAudioTarget::isOK() const
-{
-    return (m_stream != 0);
-}
-
-int
-AudioPortAudioTarget::processStatic(void *input, void *output,
-				    unsigned long nframes,
-				    PaTimestamp outTime, void *data)
-{
-    return ((AudioPortAudioTarget *)data)->process(input, output,
-						   nframes, outTime);
-}
-
-void
-AudioPortAudioTarget::sourceModelReplaced()
-{
-    m_source->setTargetSampleRate(m_sampleRate);
-}
-
-int
-AudioPortAudioTarget::process(void *inputBuffer, void *outputBuffer,
-			      unsigned long nframes,
-			      PaTimestamp)
-{
-#ifdef DEBUG_AUDIO_PORT_AUDIO_TARGET    
-    std::cout << "AudioPortAudioTarget::process(" << nframes << ")" << std::endl;
-#endif
-
-    if (!m_source) return 0;
-
-    float *output = (float *)outputBuffer;
-
-    assert(nframes <= m_bufferSize);
-
-    static float **tmpbuf = 0;
-    static size_t tmpbufch = 0;
-    static size_t tmpbufsz = 0;
-
-    size_t sourceChannels = m_source->getSourceChannelCount();
-
-    // Because we offer pan, we always want at least 2 channels
-    if (sourceChannels < 2) sourceChannels = 2;
-
-    if (!tmpbuf || tmpbufch != sourceChannels || tmpbufsz < m_bufferSize) {
-
-	if (tmpbuf) {
-	    for (size_t i = 0; i < tmpbufch; ++i) {
-		delete[] tmpbuf[i];
-	    }
-	    delete[] tmpbuf;
-	}
-
-	tmpbufch = sourceChannels;
-	tmpbufsz = m_bufferSize;
-	tmpbuf = new float *[tmpbufch];
-
-	for (size_t i = 0; i < tmpbufch; ++i) {
-	    tmpbuf[i] = new float[tmpbufsz];
-	}
-    }
-	
-    m_source->getSourceSamples(nframes, tmpbuf);
-
-    float peakLeft = 0.0, peakRight = 0.0;
-
-    for (size_t ch = 0; ch < 2; ++ch) {
-	
-	float peak = 0.0;
-
-	if (ch < sourceChannels) {
-
-	    // PortAudio samples are interleaved
-	    for (size_t i = 0; i < nframes; ++i) {
-		output[i * 2 + ch] = tmpbuf[ch][i] * m_outputGain;
-		float sample = fabsf(output[i * 2 + ch]);
-		if (sample > peak) peak = sample;
-	    }
-
-	} else if (ch == 1 && sourceChannels == 1) {
-
-	    for (size_t i = 0; i < nframes; ++i) {
-		output[i * 2 + ch] = tmpbuf[0][i] * m_outputGain;
-		float sample = fabsf(output[i * 2 + ch]);
-		if (sample > peak) peak = sample;
-	    }
-
-	} else {
-	    for (size_t i = 0; i < nframes; ++i) {
-		output[i * 2 + ch] = 0;
-	    }
-	}
-
-	if (ch == 0) peakLeft = peak;
-	if (ch > 0 || sourceChannels == 1) peakRight = peak;
-    }
-
-    m_source->setOutputLevels(peakLeft, peakRight);
-
-    return 0;
-}
-
-#ifdef INCLUDE_MOCFILES
-#include "AudioPortAudioTarget.moc.cpp"
-#endif
-
-#endif /* HAVE_PORTAUDIO */
-
--- a/audioio/AudioPortAudioTarget.h	Thu Jul 27 16:06:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifndef _AUDIO_PORT_AUDIO_TARGET_H_
-#define _AUDIO_PORT_AUDIO_TARGET_H_
-
-#ifdef HAVE_PORTAUDIO
-
-#include <portaudio.h>
-#include <vector>
-
-#include "AudioCallbackPlayTarget.h"
-
-class AudioCallbackPlaySource;
-
-class AudioPortAudioTarget : public AudioCallbackPlayTarget
-{
-    Q_OBJECT
-
-public:
-    AudioPortAudioTarget(AudioCallbackPlaySource *source);
-    virtual ~AudioPortAudioTarget();
-
-    virtual bool isOK() const;
-
-public slots:
-    virtual void sourceModelReplaced();
-
-protected:
-    int process(void *input, void *output, unsigned long frames,
-		PaTimestamp outTime);
-
-    static int processStatic(void *, void *, unsigned long,
-			     PaTimestamp, void *);
-
-    PortAudioStream *m_stream;
-
-    int m_bufferSize;
-    int m_sampleRate;
-    int m_latency;
-};
-
-#endif /* HAVE_PORTAUDIO */
-
-#endif
-
--- a/audioio/AudioTargetFactory.cpp	Thu Jul 27 16:06:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#include "AudioTargetFactory.h"
-
-#include "AudioJACKTarget.h"
-#include "AudioCoreAudioTarget.h"
-#include "AudioPortAudioTarget.h"
-
-#include <iostream>
-
-AudioCallbackPlayTarget *
-AudioTargetFactory::createCallbackTarget(AudioCallbackPlaySource *source)
-{
-    AudioCallbackPlayTarget *target = 0;
-
-#ifdef HAVE_JACK
-    target = new AudioJACKTarget(source);
-    if (target->isOK()) return target;
-    else {
-	std::cerr << "WARNING: AudioTargetFactory::createCallbackTarget: Failed to open JACK target" << std::endl;
-	delete target;
-    }
-#endif
-
-#ifdef HAVE_COREAUDIO
-    target = new AudioCoreAudioTarget(source);
-    if (target->isOK()) return target;
-    else {
-	std::cerr << "WARNING: AudioTargetFactory::createCallbackTarget: Failed to open CoreAudio target" << std::endl;
-	delete target;
-    }
-#endif
-
-#ifdef HAVE_DIRECTSOUND
-    target = new AudioDirectSoundTarget(source);
-    if (target->isOK()) return target;
-    else {
-	std::cerr << "WARNING: AudioTargetFactory::createCallbackTarget: Failed to open DirectSound target" << std::endl;
-	delete target;
-    }
-#endif
-
-#ifdef HAVE_PORTAUDIO
-    target = new AudioPortAudioTarget(source);
-    if (target->isOK()) return target;
-    else {
-	std::cerr << "WARNING: AudioTargetFactory::createCallbackTarget: Failed to open PortAudio target" << std::endl;
-	delete target;
-    }
-#endif
-
-    std::cerr << "WARNING: AudioTargetFactory::createCallbackTarget: No suitable targets available" << std::endl;
-    return 0;
-}
-
-
--- a/audioio/AudioTargetFactory.h	Thu Jul 27 16:06:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifndef _AUDIO_TARGET_FACTORY_H_
-#define _AUDIO_TARGET_FACTORY_H_
-
-class AudioCallbackPlaySource;
-class AudioCallbackPlayTarget;
-
-class AudioTargetFactory 
-{
-public:
-    static AudioCallbackPlayTarget *createCallbackTarget(AudioCallbackPlaySource *);
-};
-
-#endif
-
--- a/audioio/IntegerTimeStretcher.cpp	Thu Jul 27 16:06:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#include "IntegerTimeStretcher.h"
-
-#include <iostream>
-#include <cassert>
-
-//#define DEBUG_INTEGER_TIME_STRETCHER 1
-
-IntegerTimeStretcher::IntegerTimeStretcher(size_t ratio,
-					   size_t maxProcessInputBlockSize,
-					   size_t inputIncrement,
-					   size_t windowSize,
-					   WindowType windowType) :
-    m_ratio(ratio),
-    m_n1(inputIncrement),
-    m_n2(m_n1 * ratio),
-    m_wlen(std::max(windowSize, m_n2 * 2)),
-    m_inbuf(m_wlen),
-    m_outbuf(maxProcessInputBlockSize * ratio)
-{
-    m_window = new Window<float>(windowType, m_wlen),
-
-    m_time = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * m_wlen);
-    m_freq = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * m_wlen);
-    m_dbuf = (float *)fftwf_malloc(sizeof(float) * m_wlen);
-
-    m_plan = fftwf_plan_dft_1d(m_wlen, m_time, m_freq, FFTW_FORWARD, FFTW_ESTIMATE);
-    m_iplan = fftwf_plan_dft_c2r_1d(m_wlen, m_freq, m_dbuf, FFTW_ESTIMATE);
-
-    m_mashbuf = new float[m_wlen];
-    for (int i = 0; i < m_wlen; ++i) {
-	m_mashbuf[i] = 0.0;
-    }
-}
-
-IntegerTimeStretcher::~IntegerTimeStretcher()
-{
-    std::cerr << "IntegerTimeStretcher::~IntegerTimeStretcher" << std::endl;
-
-    fftwf_destroy_plan(m_plan);
-    fftwf_destroy_plan(m_iplan);
-
-    fftwf_free(m_time);
-    fftwf_free(m_freq);
-    fftwf_free(m_dbuf);
-
-    delete m_window;
-    delete m_mashbuf;
-}	
-
-size_t
-IntegerTimeStretcher::getProcessingLatency() const
-{
-    return getWindowSize() - getInputIncrement();
-}
-
-void
-IntegerTimeStretcher::process(float *input, float *output, size_t samples)
-{
-    // We need to add samples from input to our internal buffer.  When
-    // we have m_windowSize samples in the buffer, we can process it,
-    // move the samples back by m_n1 and write the output onto our
-    // internal output buffer.  If we have (samples * ratio) samples
-    // in that, we can write m_n2 of them back to output and return
-    // (otherwise we have to write zeroes).
-
-    // When we process, we write m_wlen to our fixed output buffer
-    // (m_mashbuf).  We then pull out the first m_n2 samples from that
-    // buffer, push them into the output ring buffer, and shift
-    // m_mashbuf left by that amount.
-
-    // The processing latency is then m_wlen - m_n2.
-
-    size_t consumed = 0;
-
-#ifdef DEBUG_INTEGER_TIME_STRETCHER
-    std::cerr << "IntegerTimeStretcher::process(" << samples << ", consumed = " << consumed << "), writable " << m_inbuf.getWriteSpace() <<", readable "<< m_outbuf.getReadSpace() << std::endl;
-#endif
-
-    while (consumed < samples) {
-
-	size_t writable = m_inbuf.getWriteSpace();
-	writable = std::min(writable, samples - consumed);
-
-	if (writable == 0) {
-	    //!!! then what? I don't think this should happen, but
-	    std::cerr << "WARNING: IntegerTimeStretcher::process: writable == 0" << std::endl;
-	    break;
-	}
-
-#ifdef DEBUG_INTEGER_TIME_STRETCHER
-	std::cerr << "writing " << writable << " from index " << consumed << " to inbuf, consumed will be " << consumed + writable << std::endl;
-#endif
-	m_inbuf.write(input + consumed, writable);
-	consumed += writable;
-
-	while (m_inbuf.getReadSpace() >= m_wlen &&
-	       m_outbuf.getWriteSpace() >= m_n2) {
-
-	    // We know we have at least m_wlen samples available
-	    // in m_inbuf.  We need to peek m_wlen of them for
-	    // processing, and then read m_n1 to advance the read
-	    // pointer.
-
-	    size_t got = m_inbuf.peek(m_dbuf, m_wlen);
-	    assert(got == m_wlen);
-		
-	    processBlock(m_dbuf, m_mashbuf);
-
-#ifdef DEBUG_INTEGER_TIME_STRETCHER
-	    std::cerr << "writing first " << m_n2 << " from mashbuf, skipping " << m_n1 << " on inbuf " << std::endl;
-#endif
-	    m_inbuf.skip(m_n1);
-	    m_outbuf.write(m_mashbuf, m_n2);
-
-	    for (size_t i = 0; i < m_wlen - m_n2; ++i) {
-		m_mashbuf[i] = m_mashbuf[i + m_n2];
-	    }
-	    for (size_t i = m_wlen - m_n2; i < m_wlen; ++i) {
-		m_mashbuf[i] = 0.0f;
-	    }
-	}
-
-//	std::cerr << "WARNING: IntegerTimeStretcher::process: writespace not enough for output increment (" << m_outbuf.getWriteSpace() << " < " << m_n2 << ")" << std::endl;
-//	}
-
-#ifdef DEBUG_INTEGER_TIME_STRETCHER
-	std::cerr << "loop ended: inbuf read space " << m_inbuf.getReadSpace() << ", outbuf write space " << m_outbuf.getWriteSpace() << std::endl;
-#endif
-    }
-
-    if (m_outbuf.getReadSpace() < samples * m_ratio) {
-	std::cerr << "WARNING: IntegerTimeStretcher::process: not enough data (yet?) (" << m_outbuf.getReadSpace() << " < " << (samples * m_ratio) << ")" << std::endl;
-	size_t fill = samples * m_ratio - m_outbuf.getReadSpace();
-	for (size_t i = 0; i < fill; ++i) {
-	    output[i] = 0.0;
-	}
-	m_outbuf.read(output + fill, m_outbuf.getReadSpace());
-    } else {
-#ifdef DEBUG_INTEGER_TIME_STRETCHER
-	std::cerr << "enough data - writing " << samples * m_ratio << " from outbuf" << std::endl;
-#endif
-	m_outbuf.read(output, samples * m_ratio);
-    }
-
-#ifdef DEBUG_INTEGER_TIME_STRETCHER
-    std::cerr << "IntegerTimeStretcher::process returning" << std::endl;
-#endif
-}
-
-void
-IntegerTimeStretcher::processBlock(float *buf, float *out)
-{
-    size_t i;
-
-    // buf contains m_wlen samples; out contains enough space for
-    // m_wlen * ratio samples (we mix into out, rather than replacing)
-
-#ifdef DEBUG_INTEGER_TIME_STRETCHER
-    std::cerr << "IntegerTimeStretcher::processBlock" << std::endl;
-#endif
-
-    m_window->cut(buf);
-
-    for (i = 0; i < m_wlen/2; ++i) {
-	float temp = buf[i];
-	buf[i] = buf[i + m_wlen/2];
-	buf[i + m_wlen/2] = temp;
-    }
-    
-    for (i = 0; i < m_wlen; ++i) {
-	m_time[i][0] = buf[i];
-	m_time[i][1] = 0.0;
-    }
-
-    fftwf_execute(m_plan); // m_time -> m_freq
-
-    for (i = 0; i < m_wlen; ++i) {
-	
-	float mag = sqrtf(m_freq[i][0] * m_freq[i][0] +
-			  m_freq[i][1] * m_freq[i][1]);
-		
-	float phase = atan2f(m_freq[i][1], m_freq[i][0]);
-	
-	phase = phase * m_ratio;
-	
-	float real = mag * cosf(phase);
-	float imag = mag * sinf(phase);
-	m_freq[i][0] = real;
-	m_freq[i][1] = imag;
-    }
-    
-    fftwf_execute(m_iplan); // m_freq -> in, inverse fft
-    
-    for (i = 0; i < m_wlen/2; ++i) {
-	float temp = buf[i] / m_wlen;
-	buf[i] = buf[i + m_wlen/2] / m_wlen;
-	buf[i + m_wlen/2] = temp;
-    }
-    
-    m_window->cut(buf);
-    
-    int div = m_wlen / m_n2;
-    if (div > 1) div /= 2;
-    for (i = 0; i < m_wlen; ++i) {
-	buf[i] /= div;
-    }
-
-    for (i = 0; i < m_wlen; ++i) {
-	out[i] += buf[i];
-    }
-}
--- a/audioio/IntegerTimeStretcher.h	Thu Jul 27 16:06:32 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#ifndef _INTEGER_TIME_STRETCHER_H_
-#define _INTEGER_TIME_STRETCHER_H_
-
-#include "base/Window.h"
-#include "base/RingBuffer.h"
-
-#include <fftw3.h>
-
-/**
- * A time stretcher that slows down audio by an integer multiple of
- * its original duration, preserving pitch.  This uses the simple
- * phase vocoder technique from DAFX pp275-276, adding a block-based
- * stream oriented API.
- *
- * Causes significant transient smearing, but sounds good for steady
- * notes and is generally predictable.
- */
-
-class IntegerTimeStretcher
-{
-public:
-    IntegerTimeStretcher(size_t ratio,
-			 size_t maxProcessInputBlockSize,
-			 size_t inputIncrement = 64,
-			 size_t windowSize = 2048,
-			 WindowType windowType = HanningWindow);
-    virtual ~IntegerTimeStretcher();
-
-    void process(float *input, float *output, size_t samples);
-
-    /**
-     * Get the hop size for input.  Smaller values may produce better
-     * results, at a cost in processing time.  Larger values are
-     * faster but increase the likelihood of echo-like effects.  The
-     * default is 64, which is usually pretty good, though heavy on
-     * processor power.
-     */
-    size_t getInputIncrement() const { return m_n1; }
-
-    /**
-     * Get the window size for FFT processing.  Must be larger than
-     * the input and output increments.  The default is 2048.
-     */
-    size_t getWindowSize() const { return m_wlen; }
-
-    /**
-     * Get the window type.  The default is a Hanning window.
-     */
-    WindowType getWindowType() const { return m_window->getType(); }
-
-    size_t getRatio() const { return m_ratio; }
-    size_t getOutputIncrement() const { return getInputIncrement() * getRatio(); }
-    size_t getProcessingLatency() const;
-
-protected:
-    void processBlock(float *in, float *out);
-
-    size_t m_ratio;
-    size_t m_n1;
-    size_t m_n2;
-    size_t m_wlen;
-    Window<float> *m_window;
-
-    fftwf_complex *m_time;
-    fftwf_complex *m_freq;
-    float *m_dbuf;
-
-    fftwf_plan m_plan;
-    fftwf_plan m_iplan;
-    
-    RingBuffer<float> m_inbuf;
-    RingBuffer<float> m_outbuf;
-    float *m_mashbuf;
-};
-
-#endif