Mixxx

/home/maxime/Projets/Mixxx/1.10/mixxx/src/engine/readaheadmanager.h

Go to the documentation of this file.
00001 // readaheadmanager.h
00002 // Created 8/2/2009 by RJ Ryan (rryan@mit.edu)
00003 
00004 #ifndef READAHEADMANGER_H
00005 #define READAHEADMANGER_H
00006 
00007 #include <QLinkedList>
00008 #include <QList>
00009 #include <QMutex>
00010 #include <QPair>
00011 
00012 #include "defs.h"
00013 
00014 struct Hint;
00015 class EngineControl;
00016 class CachingReader;
00017 
00018 // ReadAheadManager is a tool for keeping track of the engine's current position
00019 // in a file. In the case that the engine needs to read ahead of the current
00020 // play position (for example, to feed more samples into a library like
00021 // SoundTouch) then this will keep track of how many samples the engine has
00022 // consumed. The getNextSamples() method encapsulates the logic of determining
00023 // whether to take a loop or jump into a single method. Whenever the Engine
00024 // seeks or the current play position is invalidated somehow, the Engine must
00025 // call notifySeek to inform the ReadAheadManager to reset itself to the seek
00026 // point.
00027 class ReadAheadManager {
00028   public:
00029     explicit ReadAheadManager(CachingReader* reader);
00030     virtual ~ReadAheadManager();
00031     
00032     // Call this method to fill buffer with requested_samples out of the
00033     // lookahead buffer. Provide rate as dRate so that the manager knows the
00034     // direction the audio is progressing in. Returns the total number of
00035     // samples read into buffer. Note that it is very common that the total
00036     // samples read is less than the requested number of samples.
00037     virtual int getNextSamples(double dRate, CSAMPLE* buffer, int requested_samples);
00038 
00039     // Used to add a new EngineControl that ReadAheadManager will use to decide
00040     // which samples to return.
00041     virtual void addEngineControl(EngineControl* control);
00042 
00043     // Notify the ReadAheadManager that the current playposition has
00044     // changed. Units are stereo samples.
00045     virtual void setNewPlaypos(int iNewPlaypos);
00046 
00047     // Get the current read-ahead position in stereo samples.
00048     virtual inline int getPlaypos() const {
00049         return m_iCurrentPosition;
00050     }
00051 
00052     virtual void notifySeek(int iSeekPosition);
00053 
00054     // hintReader allows the ReadAheadManager to provide hints to the reader to
00055     // indicate that the given portion of a song is about to be read.
00056     virtual void hintReader(double dRate, QList<Hint>& hintList,
00057                             int iSamplesPerBuffer);
00058 
00059 
00060     virtual int getEffectiveVirtualPlaypositionFromLog(double currentVirtualPlayposition,
00061                                                        double numConsumedSamples);
00062 
00063   private:
00064     // An entry in the read log indicates the virtual playposition the read
00065     // began at and the virtual playposition it ended at.
00066     struct ReadLogEntry {
00067         double virtualPlaypositionStart;
00068         double virtualPlaypositionEndNonInclusive;
00069 
00070         ReadLogEntry(double virtualPlaypositionStart,
00071                      double virtualPlaypositionEndNonInclusive) {
00072             this->virtualPlaypositionStart = virtualPlaypositionStart;
00073             this->virtualPlaypositionEndNonInclusive =
00074                     virtualPlaypositionEndNonInclusive;
00075         }
00076 
00077         bool direction() const {
00078             return virtualPlaypositionStart < virtualPlaypositionEndNonInclusive;
00079         }
00080 
00081         double length() const {
00082             return abs(virtualPlaypositionEndNonInclusive -
00083                        virtualPlaypositionStart);
00084         }
00085 
00086         // Moves the start position forward or backward (depending on
00087         // direction()) by numSamples. Returns the total number of samples
00088         // consumed. Caller should check if length() is 0 after consumption in
00089         // order to expire the ReadLogEntry.
00090         double consume(double numSamples) {
00091             double available = math_min(numSamples, length());
00092             virtualPlaypositionStart += (direction() ? 1 : -1) * available;
00093             return available;
00094         }
00095 
00096         bool merge(const ReadLogEntry& other) {
00097             if (direction() == other.direction() &&
00098                 virtualPlaypositionEndNonInclusive == other.virtualPlaypositionStart) {
00099                 virtualPlaypositionEndNonInclusive =
00100                         other.virtualPlaypositionEndNonInclusive;
00101                 return true;
00102             }
00103             return false;
00104         }
00105     };
00106 
00107     // virtualPlaypositionEnd is the first sample in the direction that was read
00108     // that was NOT read as part of this log entry. This is to simplify the
00109     void addReadLogEntry(double virtualPlaypositionStart,
00110                          double virtualPlaypositionEndNonInclusive);
00111 
00112     QMutex m_mutex;
00113     QList<EngineControl*> m_sEngineControls;
00114     QLinkedList<ReadLogEntry> m_readAheadLog;
00115     int m_iCurrentPosition;
00116     CachingReader* m_pReader;
00117 };
00118 
00119 #endif // READAHEADMANGER_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines