diff options
author | Robert Jonsson <spamatica@gmail.com> | 2010-10-13 19:34:22 +0000 |
---|---|---|
committer | Robert Jonsson <spamatica@gmail.com> | 2010-10-13 19:34:22 +0000 |
commit | 8a2c2824a59d7644e13bc52c9a0ecbd641f21f95 (patch) | |
tree | 064ad3f2bf8daab0ad27b128abd86a9bbdb1e496 /muse2/muse/audioprefetch.cpp | |
parent | a27706d9629e8b592cca4659f865b70adef24e6d (diff) |
new branch muse2, first checkin
Diffstat (limited to 'muse2/muse/audioprefetch.cpp')
-rw-r--r-- | muse2/muse/audioprefetch.cpp | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/muse2/muse/audioprefetch.cpp b/muse2/muse/audioprefetch.cpp new file mode 100644 index 00000000..b2ddab8c --- /dev/null +++ b/muse2/muse/audioprefetch.cpp @@ -0,0 +1,262 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: audioprefetch.cpp,v 1.14.2.7 2009/12/20 05:00:35 terminator356 Exp $ +// +// (C) Copyright 2001 Werner Schweer (ws@seh.de) +//========================================================= + +#include <poll.h> +#include <stdio.h> +#include <unistd.h> +#include <values.h> + +#include "audioprefetch.h" +#include "globals.h" +#include "track.h" +#include "song.h" +#include "audio.h" +#include "sync.h" + +// Added by Tim. p3.3.20 +//#define AUDIOPREFETCH_DEBUG + +enum { PREFETCH_TICK, PREFETCH_SEEK + }; + +//--------------------------------------------------------- +// PrefetchMsg +//--------------------------------------------------------- + +struct PrefetchMsg : public ThreadMsg { + int pos; + }; + +AudioPrefetch* audioPrefetch; + +//--------------------------------------------------------- +// AudioPrefetch +//--------------------------------------------------------- + +//AudioPrefetch::AudioPrefetch(int prio, const char* name) +// : Thread(prio,name) +AudioPrefetch::AudioPrefetch(const char* name) + : Thread(name) + { + seekPos = ~0; + writePos = ~0; + //seekDone = true; + seekCount = 0; + } + +//--------------------------------------------------------- +// readMsg +//--------------------------------------------------------- + +static void readMsgP(void* p, void*) + { + AudioPrefetch* at = (AudioPrefetch*)p; + at->readMsg1(sizeof(PrefetchMsg)); + } + +//--------------------------------------------------------- +// start +//--------------------------------------------------------- + +//void AudioPrefetch::start() +void AudioPrefetch::start(int priority) + { + clearPollFd(); + addPollFd(toThreadFdr, POLLIN, ::readMsgP, this, 0); + //Thread::start(); + Thread::start(priority); + } + +//--------------------------------------------------------- +// ~AudioPrefetch +//--------------------------------------------------------- + +AudioPrefetch::~AudioPrefetch() + { + } + +//--------------------------------------------------------- +// processMsg +//--------------------------------------------------------- + +void AudioPrefetch::processMsg1(const void* m) + { + const PrefetchMsg* msg = (PrefetchMsg*)m; + switch(msg->id) { + case PREFETCH_TICK: + if (audio->isRecording()) { + //puts("writeTick"); + audio->writeTick(); + } + // Indicate do not seek file before each read. + // Changed by Tim. p3.3.17 + //prefetch(); + prefetch(false); + + seekPos = ~0; // invalidate cached last seek position + break; + case PREFETCH_SEEK: + #ifdef AUDIOPREFETCH_DEBUG + printf("AudioPrefetch::processMsg1 PREFETCH_SEEK msg->pos:%d\n", msg->pos); + #endif + + // process seek in background + seek(msg->pos); + break; + default: + printf("AudioPrefetch::processMsg1: unknown message\n"); + } + } + +//--------------------------------------------------------- +// msgTick +//--------------------------------------------------------- + +void AudioPrefetch::msgTick() + { + PrefetchMsg msg; + msg.id = PREFETCH_TICK; + while (sendMsg1(&msg, sizeof(msg))) { + printf("AudioPrefetch::msgTick(): send failed!\n"); + } + } + +//--------------------------------------------------------- +// msgSeek +// called from audio RT context +//--------------------------------------------------------- + +void AudioPrefetch::msgSeek(unsigned samplePos, bool force) + { + if (samplePos == seekPos && !force) { + //seekDone = true; + return; + } + + ++seekCount; + //seekDone = false; + + #ifdef AUDIOPREFETCH_DEBUG + printf("AudioPrefetch::msgSeek samplePos:%u force:%d seekCount:%d\n", samplePos, force, seekCount); + #endif + + PrefetchMsg msg; + msg.id = PREFETCH_SEEK; + msg.pos = samplePos; + while (sendMsg1(&msg, sizeof(msg))) { + printf("AudioPrefetch::msgSeek::sleep(1)\n"); + sleep(1); + } + } + +//--------------------------------------------------------- +// prefetch +//--------------------------------------------------------- + +//void AudioPrefetch::prefetch() +void AudioPrefetch::prefetch(bool doSeek) + { + if (writePos == ~0U) { + printf("AudioPrefetch::prefetch: invalid write position\n"); + return; + } + if (song->loop() && !audio->bounce() && !extSyncFlag.value()) { + const Pos& loop = song->rPos(); + unsigned n = loop.frame() - writePos; + if (n < segmentSize) { + unsigned lpos = song->lPos().frame(); + // adjust loop start so we get exact loop len + if (n > lpos) + n = 0; +// printf("prefetch seek %d\n", writePos); + writePos = lpos - n; + } + } + WaveTrackList* tl = song->waves(); + for (iWaveTrack it = tl->begin(); it != tl->end(); ++it) { + WaveTrack* track = *it; + // p3.3.29 + // Save time. Don't bother if track is off. Track On/Off not designed for rapid repeated response (but mute is). + if(track->off()) + continue; + + int ch = track->channels(); + float* bp[ch]; +// printf("prefetch %d\n", writePos); + if (track->prefetchFifo()->getWriteBuffer(ch, segmentSize, bp, writePos)) { + // printf("AudioPrefetch::prefetch No write buffer!\n"); // p3.3.46 Was getting this... + continue; + } + //track->fetchData(writePos, segmentSize, bp); + track->fetchData(writePos, segmentSize, bp, doSeek); + + // p3.3.41 + //fprintf(stderr, "AudioPrefetch::prefetch data: segmentSize:%ld %e %e %e %e\n", segmentSize, bp[0][0], bp[0][1], bp[0][2], bp[0][3]); + + } + writePos += segmentSize; + } + +//--------------------------------------------------------- +// seek +//--------------------------------------------------------- + +void AudioPrefetch::seek(unsigned seekTo) + { +// printf("seek %d\n", seekTo); + #ifdef AUDIOPREFETCH_DEBUG + printf("AudioPrefetch::seek to:%u seekCount:%d\n", seekTo, seekCount); + #endif + + // Speedup: More than one seek message pending? + // Eat up seek messages until we get to the very LATEST one, + // because all the rest which came before it are irrelevant now, + // and processing them all was taking extreme time, especially with + // resampling enabled. + // In particular, when the user 'slides' the play cursor back and forth + // there are MANY seek messages in the pipe, and with resampling enabled + // it was taking minutes to finish seeking. If the user hit play during that time, + // things were messed up (FIFO underruns, choppy intermittent sound etc). + // Added by Tim. p3.3.20 + if(seekCount > 1) + { + --seekCount; + return; + } + + writePos = seekTo; + WaveTrackList* tl = song->waves(); + for (iWaveTrack it = tl->begin(); it != tl->end(); ++it) { + WaveTrack* track = *it; + track->clearPrefetchFifo(); + } + + bool isFirstPrefetch = true; + for (unsigned int i = 0; i < (fifoLength)-1; ++i)//prevent compiler warning: comparison of signed/unsigned + { + // Indicate do a seek command before read, but only on the first pass. + // Changed by Tim. p3.3.17 + //prefetch(); + prefetch(isFirstPrefetch); + + isFirstPrefetch = false; + + // To help speed things up even more, check the count again. Return if more seek messages are pending. + // Added by Tim. p3.3.20 + if(seekCount > 1) + { + --seekCount; + return; + } + } + + seekPos = seekTo; + //seekDone = true; + --seekCount; + } + |