# HG changeset patch # User lbajardsilogic # Date 1189586856 0 # Node ID d94ee3e8dfe1a21fc60f734f5ca4f52d63843908 # Parent 490e955a21f832bdefdbaaad9883662ab3b92109 modify the way the RingBuffer is read to let the TimeStretchFilter be the master diff -r 490e955a21f8 -r d94ee3e8dfe1 sv/audioio/AudioCallbackPlaySource.cpp --- a/sv/audioio/AudioCallbackPlaySource.cpp Tue Sep 04 07:54:09 2007 +0000 +++ b/sv/audioio/AudioCallbackPlaySource.cpp Wed Sep 12 08:47:36 2007 +0000 @@ -726,7 +726,7 @@ existingStretcher->getRatio() == factor && existingStretcher->getSharpening() == sharpen && existingStretcher->getChannelCount() == channels) { - return; + return; } if (factor != 1) { @@ -734,25 +734,25 @@ if (existingStretcher && existingStretcher->getSharpening() == sharpen && existingStretcher->getChannelCount() == channels) { - existingStretcher->setRatio(factor); - return; + existingStretcher->setRatio(factor); + return; } - PhaseVocoderTimeStretcher *newStretcher = new PhaseVocoderTimeStretcher + PhaseVocoderTimeStretcher *newStretcher = new PhaseVocoderTimeStretcher (getTargetSampleRate(), channels, factor, sharpen, getTargetBlockSize()); - m_timeStretcher = newStretcher; + m_timeStretcher = newStretcher; } else { - m_timeStretcher = 0; + m_timeStretcher = 0; } if (existingStretcher) { - m_timeStretcherScavenger.claim(existingStretcher); + m_timeStretcherScavenger.claim(existingStretcher); } } @@ -797,7 +797,7 @@ if (count == 0) return 0; - PhaseVocoderTimeStretcher *ts = m_timeStretcher; +/* PhaseVocoderTimeStretcher *ts = m_timeStretcher; if (!ts || ts->getRatio() == 1) { @@ -923,8 +923,12 @@ applyAuditioningEffect(count, buffer); + */ + applyRealTimeFilters(count, buffer); + applyAuditioningEffect(count, buffer); + m_condition.wakeAll(); return count; @@ -983,11 +987,11 @@ size_t space = 0; for (size_t c = 0; c < getTargetChannelCount(); ++c) { - RingBuffer *wb = getWriteRingBuffer(c); - if (wb) { - size_t spaceHere = wb->getWriteSpace(); - if (c == 0 || spaceHere < space) space = spaceHere; - } + RingBuffer *wb = getWriteRingBuffer(c); + if (wb) { + size_t spaceHere = wb->getWriteSpace(); + if (c == 0 || spaceHere < space) space = spaceHere; + } } if (space == 0) return false; @@ -1019,164 +1023,164 @@ static size_t bufferPtrCount = 0; if (bufferPtrCount < channels) { - if (bufferPtrs) delete[] bufferPtrs; - bufferPtrs = new float *[channels]; - 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; - } + 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); + 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; + // orig must be a multiple of generatorBlockSize + orig = (orig / generatorBlockSize) * generatorBlockSize; + if (orig == 0) return false; - size_t work = max(orig, space); + size_t work = 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; - } + // 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; - } - } + 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; - } + for (size_t c = 0; c < channels; ++c) { + bufferPtrs[c] = nonintlv + c * orig; + } - got = mixModels(f, orig, bufferPtrs); + 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; - } - } + // 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; - 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 = 0; + int err = 0; - if (m_timeStretcher && m_timeStretcher->getRatio() < 0.4) { + if (m_timeStretcher && m_timeStretcher->getRatio() < 0.4) { #ifdef DEBUG_AUDIO_PLAY_SOURCE - std::cout << "Using crappy converter" << std::endl; + std::cout << "Using crappy converter" << std::endl; #endif - src_process(m_crapConverter, &data); - } else { - src_process(m_converter, &data); - } + src_process(m_crapConverter, &data); + } else { + src_process(m_converter, &data); + } - size_t toCopy = size_t(got * 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? + 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::cout << "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 *wb = getWriteRingBuffer(c); + if (wb) wb->write(tmp, toCopy); + } + + m_writeBufferFill = f; + if (readWriteEqual) m_readBufferFill = f; + } else { - got = data.input_frames_used; - toCopy = data.output_frames_gen; + + // 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 *wb = getWriteRingBuffer(c); + if (wb) { + size_t actual = wb->write(bufferPtrs[c], got); #ifdef DEBUG_AUDIO_PLAY_SOURCE - std::cout << "Resampled " << got << " frames to " << toCopy << " frames" << std::endl; + std::cout << "Wrote " << actual << " samples for ch " << c << ", now " + << wb->getReadSpace() << " to read" + << 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 *wb = getWriteRingBuffer(c); - if (wb) wb->write(tmp, toCopy); - } + if (actual < got) { + std::cerr << "WARNING: Buffer overrun in channel " << c + << ": wrote " << actual << " of " << got + << " samples" << std::endl; + } + } + } - m_writeBufferFill = f; - if (readWriteEqual) m_readBufferFill = f; + 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 *wb = getWriteRingBuffer(c); - if (wb) { - size_t actual = wb->write(bufferPtrs[c], got); -#ifdef DEBUG_AUDIO_PLAY_SOURCE - std::cout << "Wrote " << actual << " samples for ch " << c << ", now " - << wb->getReadSpace() << " to read" - << std::endl; -#endif - if (actual < got) { - std::cerr << "WARNING: Buffer overrun in channel " << c - << ": wrote " << actual << " of " << got - << " samples" << std::endl; - } - } - } - - 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 + //!!! 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; @@ -1204,126 +1208,126 @@ #endif if (chunkBufferPtrCount < channels) { - if (chunkBufferPtrs) delete[] chunkBufferPtrs; - chunkBufferPtrs = new float *[channels]; - chunkBufferPtrCount = channels; + if (chunkBufferPtrs) delete[] chunkBufferPtrs; + chunkBufferPtrs = new float *[channels]; + chunkBufferPtrCount = channels; } for (size_t c = 0; c < channels; ++c) { - chunkBufferPtrs[c] = buffers[c]; + chunkBufferPtrs[c] = buffers[c]; } while (processed < count) { - chunkSize = count - processed; - nextChunkStart = chunkStart + chunkSize; - selectionSize = 0; + chunkSize = count - processed; + nextChunkStart = chunkStart + chunkSize; + selectionSize = 0; - size_t fadeIn = 0, fadeOut = 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 (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::cout << "chunkStart " << chunkStart << ", chunkSize " << chunkSize << ", nextChunkStart " << nextChunkStart << ", frame " << frame << ", count " << count << ", processed " << processed << std::endl; - if (selection.isEmpty()) { - - chunkSize = 0; - nextChunkStart = chunkStart; - - } else { - - selectionSize = - selection.getEndFrame() - - selection.getStartFrame(); - - if (chunkStart < selection.getStartFrame()) { - chunkStart = selection.getStartFrame(); - fadeIn = 50; + if (!chunkSize) { +#ifdef DEBUG_AUDIO_PLAY_SOURCE + std::cout << "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; } - nextChunkStart = chunkStart + chunkSize; +#ifdef DEBUG_AUDIO_PLAY_SOURCE + std::cout << "Selection playback: chunk at " << chunkStart << " -> " << nextChunkStart << " (size " << chunkSize << ")" << std::endl; +#endif - if (nextChunkStart >= selection.getEndFrame()) { - nextChunkStart = selection.getEndFrame(); - fadeOut = 50; + 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; } - chunkSize = nextChunkStart - chunkStart; - } - - } else if (looping && m_lastModelEndFrame > 0) { + if (fadeIn > 0) { + if (processed * 2 < fadeIn) { + fadeIn = processed * 2; + } + } - if (chunkStart >= m_lastModelEndFrame) { - chunkStart = 0; - } - if (chunkSize > m_lastModelEndFrame - chunkStart) { - chunkSize = m_lastModelEndFrame - chunkStart; - } - nextChunkStart = chunkStart + chunkSize; - } - -// std::cout << "chunkStart " << chunkStart << ", chunkSize " << chunkSize << ", nextChunkStart " << nextChunkStart << ", frame " << frame << ", count " << count << ", processed " << processed << std::endl; + if (fadeOut > 0) { + if ((count - processed - chunkSize) * 2 < fadeOut) { + fadeOut = (count - processed - chunkSize) * 2; + } + } - if (!chunkSize) { -#ifdef DEBUG_AUDIO_PLAY_SOURCE - std::cout << "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; - } + for (std::set::iterator mi = m_models.begin(); + mi != m_models.end(); ++mi) { + + got = m_audioGenerator->mixModel(*mi, chunkStart, + chunkSize, chunkBufferPtrs, + fadeIn, fadeOut); + } -#ifdef DEBUG_AUDIO_PLAY_SOURCE - std::cout << "Selection playback: chunk at " << chunkStart << " -> " << nextChunkStart << " (size " << chunkSize << ")" << std::endl; -#endif + for (size_t c = 0; c < channels; ++c) { + chunkBufferPtrs[c] += chunkSize; + } - 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::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; + processed += chunkSize; + chunkStart = nextChunkStart; } #ifdef DEBUG_AUDIO_PLAY_SOURCE @@ -1412,59 +1416,59 @@ while (!s.m_exiting) { - s.unifyRingBuffers(); - s.m_bufferScavenger.scavenge(); - s.m_pluginScavenger.scavenge(); - s.m_timeStretcherScavenger.scavenge(); + s.unifyRingBuffers(); + s.m_bufferScavenger.scavenge(); + s.m_pluginScavenger.scavenge(); + s.m_timeStretcherScavenger.scavenge(); - if (work && s.m_playing && s.getSourceSampleRate()) { - + if (work && s.m_playing && s.getSourceSampleRate()) { + #ifdef DEBUG_AUDIO_PLAY_SOURCE - std::cout << "AudioCallbackPlaySourceFillThread: not waiting" << std::endl; + std::cout << "AudioCallbackPlaySourceFillThread: not waiting" << std::endl; #endif - s.m_mutex.unlock(); - s.m_mutex.lock(); + 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; + } 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 - if (!s.m_playing) std::cout << std::endl; - std::cout << "AudioCallbackPlaySourceFillThread: waiting for " << ms << "ms..." << std::endl; + if (!s.m_playing) std::cout << std::endl; + std::cout << "AudioCallbackPlaySourceFillThread: waiting for " << ms << "ms..." << std::endl; #endif - - s.m_condition.wait(&s.m_mutex, size_t(ms)); - } + + s.m_condition.wait(&s.m_mutex, size_t(ms)); + } #ifdef DEBUG_AUDIO_PLAY_SOURCE - std::cout << "AudioCallbackPlaySourceFillThread: awoken" << std::endl; + std::cout << "AudioCallbackPlaySourceFillThread: awoken" << std::endl; #endif - work = false; + work = false; - if (!s.getSourceSampleRate()) continue; + if (!s.getSourceSampleRate()) continue; - bool playing = s.m_playing; + bool playing = s.m_playing; - if (playing && !previouslyPlaying) { + if (playing && !previouslyPlaying) { #ifdef DEBUG_AUDIO_PLAY_SOURCE - std::cout << "AudioCallbackPlaySourceFillThread: playback state changed, resetting" << std::endl; + std::cout << "AudioCallbackPlaySourceFillThread: playback state changed, resetting" << std::endl; #endif - for (size_t c = 0; c < s.getTargetChannelCount(); ++c) { - RingBuffer *rb = s.getReadRingBuffer(c); - if (rb) rb->reset(); - } - } - previouslyPlaying = playing; + for (size_t c = 0; c < s.getTargetChannelCount(); ++c) { + RingBuffer *rb = s.getReadRingBuffer(c); + if (rb) rb->reset(); + } + } + previouslyPlaying = playing; - work = s.fillBuffers(); + work = s.fillBuffers(); } s.m_mutex.unlock(); @@ -1474,7 +1478,7 @@ { if (!m_filterStack) return; - size_t required = m_filterStack->getRequiredInputSamples(count); +/* size_t required = m_filterStack->getRequiredInputSamples(count); if (required <= count) { @@ -1485,7 +1489,7 @@ size_t missing = required - count; size_t channels = getTargetChannelCount(); - + size_t got = required; float **ib = (float**) malloc(channels*sizeof(float*)); @@ -1498,7 +1502,7 @@ } RingBuffer *rb = getReadRingBuffer(c); if (rb) { - size_t gotHere = rb->peek(ib[c]+count, missing); + size_t gotHere = rb->peek(ib[c]+count, missing); //should be got not missing parameter !!!! if (gotHere < got) got = gotHere; } @@ -1518,5 +1522,74 @@ delete ib; } m_filterStack->getOutput(buffers, count); +*/ + size_t required = m_filterStack->getRequiredInputSamples(count); + + size_t channels = getTargetChannelCount(); + + size_t got = required; + + //if no filters are available + if (required == 0) + { + got = count; + for (size_t ch = 0; ch < channels; ++ch) + { + RingBuffer *rb = getReadRingBuffer(ch); + if (rb) { + size_t gotHere = rb->read(buffers[ch], got); + if (gotHere < got) + got = gotHere; + } + + for (size_t ch = 0; ch < channels; ++ch) { + for (size_t i = got; i < count; ++i) { + buffers[ch][i] = 0.0; + } + } + } + return; + } + + float **ib = (float**) malloc(channels*sizeof(float*)); + + for (size_t c = 0; c < channels; ++c) + { + ib[c] = (float*) malloc(required*sizeof(float)); + RingBuffer *rb = getReadRingBuffer(c); + if (rb) { + size_t gotHere = rb->peek(ib[c], got); + if (gotHere < got) + got = gotHere; + } + } + if (got < required) + { + std::cerr << "ERROR applyRealTimeFilters(): Read underrun in playback (" + << got << " < " << required << ")" << std::endl; + return; + } + + m_filterStack->putInput(ib, required); + + m_filterStack->getOutput(buffers, count); + + //move the read pointer + got = m_filterStack->getRequiredSkipSamples(); + for (size_t c = 0; c < channels; ++c) + { + RingBuffer *rb = getReadRingBuffer(c); + if (rb) { + size_t gotHere = rb->skip(got); + if (gotHere < got) + got = gotHere; + } + } + + //delete + for (size_t c = 0; c < channels; ++c) { + delete ib[c]; + } + delete ib; } \ No newline at end of file diff -r 490e955a21f8 -r d94ee3e8dfe1 sv/filter/FilterStack.cpp --- a/sv/filter/FilterStack.cpp Tue Sep 04 07:54:09 2007 +0000 +++ b/sv/filter/FilterStack.cpp Wed Sep 12 08:47:36 2007 +0000 @@ -13,6 +13,8 @@ #include "FilterStack.h" +#include "TimeStretchFilter.h" + FilterStack::FilterStack() : QObject() {} @@ -130,6 +132,25 @@ return max; } +size_t FilterStack::getRequiredSkipSamples() +{ + size_t skip = 1024; + + std::map::iterator iter; + + for (iter = m_filters.begin(); iter != m_filters.end(); iter++) + { + // find the time filter + Filter * filter = iter->second; + if (filter->objectName() == "Pitch-Time Stretching") + { + TimeStretchFilter * timefilter = (TimeStretchFilter *) filter; + skip = timefilter->getRequiredSkipSamples(); + } + } + return skip; +} + void FilterStack::setSourceChannelCount(size_t channel) { m_sourceChannelCount = channel; diff -r 490e955a21f8 -r d94ee3e8dfe1 sv/filter/FilterStack.h --- a/sv/filter/FilterStack.h Tue Sep 04 07:54:09 2007 +0000 +++ b/sv/filter/FilterStack.h Wed Sep 12 08:47:36 2007 +0000 @@ -38,6 +38,7 @@ QString getUniqueFilterName(QString candidate); size_t getRequiredInputSamples(size_t outputSamplesNeeded); + size_t getRequiredSkipSamples(); void setSourceChannelCount(size_t channel); diff -r 490e955a21f8 -r d94ee3e8dfe1 sv/filter/TimeStretchFilter.cpp --- a/sv/filter/TimeStretchFilter.cpp Tue Sep 04 07:54:09 2007 +0000 +++ b/sv/filter/TimeStretchFilter.cpp Wed Sep 12 08:47:36 2007 +0000 @@ -56,7 +56,8 @@ m_transcheck(false), m_peakcheck(false), m_framesize(4096), - m_interpfactor(1) + m_interpfactor(1), + m_transhold(0) { m_hop = m_framesize/4; @@ -124,7 +125,7 @@ TimeStretchFilter::PropertyList TimeStretchFilter::getProperties() const { PropertyList list; - //list.push_back("Time"); + list.push_back("Time"); list.push_back("Pitch"); list.push_back("Bypass"); list.push_back("Transdetect"); @@ -242,22 +243,23 @@ float interpsample; bool drum = 0; - float drumthresh = 65; - int transhold = 0; + float drumthresh = 65; - if (samples < floor(m_framesize*m_interpfactor + 1)) + int currentposition = m_hop+1; + + if (samples < floor((m_framesize-1)*m_interpfactor + 1 + 1025)) return; int channel = getSourceChannelCount(); for (int i=0; i 1) - m_inputBuffer[i] = (input[0][i] + input[1][i]) /2; + m_inputBuffer[i] = input[0][i];// + input[1][i]) /2; else m_inputBuffer[i] = input[0][i]; } - for (int i = 0; i<(m_framesize); i++) + for (int i = 0; i