pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plonk_AudioFileReader.h
00001 /*
00002  -------------------------------------------------------------------------------
00003  This file is part of the Plink, Plonk, Plank libraries
00004   by Martin Robinson
00005  
00006  http://code.google.com/p/pl-nk/
00007  
00008  Copyright University of the West of England, Bristol 2011-14
00009  All rights reserved.
00010  
00011  Redistribution and use in source and binary forms, with or without
00012  modification, are permitted provided that the following conditions are met:
00013  
00014  * Redistributions of source code must retain the above copyright
00015    notice, this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright
00017    notice, this list of conditions and the following disclaimer in the
00018    documentation and/or other materials provided with the distribution.
00019  * Neither the name of University of the West of England, Bristol nor 
00020    the names of its contributors may be used to endorse or promote products
00021    derived from this software without specific prior written permission.
00022  
00023  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00024  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00025  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00026  DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF THE WEST OF ENGLAND, BRISTOL BE 
00027  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00028  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
00029  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
00030  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00031  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
00032  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00033  
00034  This software makes use of third party libraries. For more information see:
00035  doc/license.txt included in the distribution.
00036  -------------------------------------------------------------------------------
00037  */
00038 
00039 #ifndef PLONK_AUDIOFILEREADER_H
00040 #define PLONK_AUDIOFILEREADER_H
00041 
00042 #include "../../core/plonk_CoreForwardDeclarations.h"
00043 #include "../../core/plonk_SmartPointer.h"
00044 #include "../../core/plonk_WeakPointer.h"
00045 #include "../../core/plonk_SenderContainer.h"
00046 #include "../../core/plonk_SmartPointerContainer.h"
00047 #include "../../containers/plonk_Text.h"
00048 #include "../../core/plonk_Sender.h"
00049 #include "plonk_AudioFile.h"
00050 #include "plonk_AudioFileMetaData.h"
00051 
00052 
00053 class AudioFileReaderInternal : public SmartPointer
00054 {
00055 public:
00056     typedef AudioFileReader Container;
00057 
00058     AudioFileReaderInternal() throw();
00059     AudioFileReaderInternal (const char* path, const int bufferSize, AudioFileMetaDataIOFlags const& metaDataIOFlags) throw();
00060     AudioFileReaderInternal (ByteArray const& bytes, const int bufferSize, AudioFileMetaDataIOFlags const& metaDataIOFlags) throw();
00061     AudioFileReaderInternal (FilePathArray const& paths, const AudioFile::MultiFileTypes multiMode, const int bufferSize) throw();
00062     AudioFileReaderInternal (FilePathArray const& paths, IntVariable const& indexRef, const int bufferSize) throw();
00063     AudioFileReaderInternal (AudioFileReaderArray const& audioFiles, const AudioFile::MultiFileTypes multiMode, const int bufferSize, IntVariable* indexRef = 0) throw();
00064     AudioFileReaderInternal (FilePathQueue const& paths, const int bufferSize) throw();
00065     AudioFileReaderInternal (AudioFileReaderQueue const& audioFiles, const int bufferSize) throw();
00066 //    AudioFileReaderInternal (AudioFileReader const& original, const LongLong start, const LongLong end, const int bufferSize) throw();
00067     AudioFileReaderInternal (AudioFileReader const& original, AudioFileRegion const& region, const int bufferSize) throw();
00068 
00069     ~AudioFileReaderInternal();
00070     
00071     ResultCode open (const char* path, const int bufferSize, AudioFileMetaDataIOFlags const& metaDataIOFlags) throw();
00072     
00073     AudioFile::Format getFormat() const throw();
00074     AudioFile::Encoding getEncoding() const throw();
00075     AudioFile::SampleType getSampleType() const throw();
00076     
00077     int getBitsPerSample() const throw();
00078     int getBytesPerFrame() const throw();
00079     int getBytesPerSample() const throw();
00080     int getNumChannels() const throw();
00081     int getDefaultNumChannels() throw();
00082     void setDefaultNumChannels (const int numChannels) throw();
00083     void setDefaultSampleRate (const double sampleRate) throw();
00084     double getDefaultSampleRate() const throw();
00085     double getSampleRate() const throw();
00086     
00087     ChannelLayout getChannelLayout() const throw();
00088     ChannelIdentifier getChannelIdentifier (const int channel) const throw();
00089     
00090     LongLong getNumFrames() const throw();
00091     LongLong getFramePosition() const throw();
00092     
00093     bool isPositionable() const throw();
00094     void setFramePosition (const LongLong position) throw();
00095     void resetFramePosition() throw();
00096     void setFramePositionOnNextRead (const LongLong position) throw();
00097     
00098     template<class SampleType>
00099     void readFrames (NumericalArray<SampleType>& data, const bool applyScaling, const bool deinterleave, IntVariable& numLoops) throw();
00100     
00101     template<class SampleType>
00102     inline void initSignal (SignalBase<SampleType>& signal, const int numFrames) const throw()
00103     {
00104         const int numChannels = getNumChannels();
00105         const int length = (numFrames > 0) ? numFrames * numChannels : (int)getNumFrames() * numChannels;
00106         NumericalArray<SampleType> buffer = NumericalArray<SampleType>::withSize (length);
00107         signal = SignalBase<SampleType> (buffer, getSampleRate(), numChannels);
00108     }
00109     
00110     template<class SampleType>
00111     inline void readSignal (SignalBase<SampleType>& signal, const bool applyScaling) throw()
00112     {
00113         // would need to decide in here to deinterleave..
00114         
00115         signal.getSampleRate().setValue (getSampleRate());
00116         IntVariable oneLoop (1);
00117         readFrames (signal.getBuffers().first(), applyScaling, false, oneLoop);
00118     }
00119     
00120     void setOwner (void* owner) throw();
00121     void* getOwner() const throw();
00122     bool isOwned() const throw();
00123     bool isReady() const throw();
00124     
00125     void disownPeer (PlankAudioFileReaderRef otherReader) throw();
00126     
00127     bool didHitEOF() const throw() { return hitEndOfFile; }
00128     bool didNumChannelsChange() const throw() { return numChannelsChanged; }
00129     bool didAudioFileChange() const throw() { return audioFileChanged; }
00130     
00131     void setName (Text const& name) throw();
00132     Text getName() const throw();
00133     
00134     bool hasMetaData() const throw();
00135     AudioFileMetaData getMetaData() const throw();
00136 //    int getNumCuePoints() const throw();
00137 //    bool getCuePointAtIndex (const int index, UnsignedInt& cueID, Text& label, LongLong& position) const throw();
00138     
00139     inline PlankAudioFileReaderRef getPeerRef() { return static_cast<PlankAudioFileReaderRef> (&peer); }
00140     inline const PlankAudioFileReaderRef getPeerRef() const { return const_cast<const PlankAudioFileReaderRef> (&peer); }
00141 
00142 private:
00143     ResultCode init (const char* path, AudioFileMetaDataIOFlags const& metaDataIOFlags) throw();
00144     ResultCode init (ByteArray const& bytes, AudioFileMetaDataIOFlags const& metaDataIOFlags) throw();
00145 
00146     template<class Type>
00147     static inline void swapEndianIfNotNative (Type* data, const int numItems, const bool dataIsBigEndian) throw()
00148     {
00149 #if PLONK_BIGENDIAN
00150         if (! dataIsBigEndian) Endian::swap (data, numItems);
00151 #endif
00152 #if PLONK_LITTLEENDIAN
00153         if (dataIsBigEndian) Endian::swap (data, numItems);
00154 #endif
00155     }
00156 
00157     PlankAudioFileReader peer;
00158     Chars readBuffer;
00159     int numFramesPerBuffer;
00160     AtomicLongLong newPositionOnNextRead;
00161     AtomicValue<void*> owner;
00162     bool hitEndOfFile;
00163     bool numChannelsChanged;
00164     bool audioFileChanged;
00165     IntVariable nextMultiIndexRef;
00166     int defaultNumChannels;
00167     double defaultSampleRate;
00168 };
00169 
00170 //------------------------------------------------------------------------------
00171 
00172 template<class SampleType>
00173 void AudioFileReaderInternal::readFrames (NumericalArray<SampleType>& data,
00174                                           const bool applyScaling, 
00175                                           const bool deinterleave,
00176                                           IntVariable& numLoops) throw()
00177 {        
00178     typedef NumericalArray<SampleType> Buffer;
00179     
00180     this->hitEndOfFile = false;
00181     this->numChannelsChanged = false;
00182     this->audioFileChanged = false;
00183     
00184     ResultCode result = PlankResult_OK;
00185     
00186     const int dataLength = data.length();
00187     int dataRemaining = dataLength;
00188     
00189     SampleType* dataArray = data.getArray();
00190     void* const readBufferArray = readBuffer.getArray();
00191     
00192     int encoding = getEncoding();
00193     int channels = getNumChannels();
00194     int bytesPerSample = getBytesPerSample();
00195     
00196     plonk_assert ((encoding >= AudioFile::EncodingMin) && (encoding <= AudioFile::EncodingMax));
00197     plonk_assert (getBitsPerSample() > 0);
00198     plonk_assert (channels > 0);
00199     plonk_assert (getBytesPerFrame() > 0);
00200     
00201     bool isPCM = encoding & AudioFile::EncodingFlagPCM;
00202     bool isFloat = encoding & AudioFile::EncodingFlagFloat;
00203     bool isBigEndian = encoding & AudioFile::EncodingFlagBigEndian;
00204     bool isInterleaved = !(encoding & AudioFile::EncodingFlagNonIntervleaved);
00205         
00206     int dataIndex = 0;
00207     const int numFailsAllowed = 3;
00208     int numFails = 0;
00209     
00210     if (!numFramesPerBuffer)
00211     {
00212         if (!getBytesPerFrame())
00213             goto exit;
00214         
00215         numFramesPerBuffer = readBuffer.length() / getBytesPerFrame();
00216     }
00217         
00218     while ((dataRemaining > 0) && 
00219            (result != PlankResult_FileEOF) &&
00220            (result != PlankResult_AudioFileFrameFormatChanged) &&
00221            (result != PlankResult_AudioFileChanged) &&
00222            (numFails < numFailsAllowed))
00223     {
00224         AtomicLongLong newPosition (-1);
00225         newPositionOnNextRead.swapWith (newPosition);
00226         
00227         if (newPosition.getValueUnchecked() >= 0)
00228         {
00229             result = pl_AudioFileReader_SetFramePosition (getPeerRef(), newPosition.getValueUnchecked());
00230             plonk_assert (result == PlankResult_OK); // just continue though in release
00231         }
00232         
00233         const int framesToRead = plonk::min (dataRemaining / channels, numFramesPerBuffer);
00234         
00235         if (framesToRead == 0)
00236             break; // not enough data left for one frame
00237 
00238         int framesRead;
00239         result = pl_AudioFileReader_ReadFrames (getPeerRef(), PLANK_FALSE, framesToRead, readBufferArray, &framesRead);
00240         plonk_assert ((result == PlankResult_OK) ||
00241                       (result == PlankResult_FileEOF) ||
00242                       (result == PlankResult_AudioFileFrameFormatChanged) ||
00243                       (result == PlankResult_AudioFileChanged));
00244         
00245         if (framesRead > 0)
00246         {
00247             const int samplesRead = framesRead * channels;
00248             plonk_assert (samplesRead <= dataRemaining);
00249             
00250             if (isPCM)
00251             {            
00252                 if (bytesPerSample == 2)
00253                 {
00254                     Short* const convertBuffer = static_cast<Short*> (readBufferArray); 
00255                     swapEndianIfNotNative (convertBuffer, samplesRead, isBigEndian);
00256                     Buffer::convert (dataArray, convertBuffer, samplesRead, applyScaling);
00257                 }
00258                 else if (bytesPerSample == 3)
00259                 {
00260                     Int24* const convertBuffer = static_cast<Int24*> (readBufferArray); 
00261                     swapEndianIfNotNative (convertBuffer, samplesRead, isBigEndian);
00262                     Buffer::convert (dataArray, convertBuffer, samplesRead, applyScaling);
00263                 }
00264                 else if (bytesPerSample == 4)
00265                 {
00266                     Int* const convertBuffer = static_cast<Int*> (readBufferArray); 
00267                     swapEndianIfNotNative (convertBuffer, samplesRead, isBigEndian);
00268                     Buffer::convert (dataArray, convertBuffer, samplesRead, applyScaling);
00269                 }
00270                 else if (bytesPerSample == 1)
00271                 {
00272                     Char* const convertBuffer = static_cast<Char*> (readBufferArray); 
00273                     Buffer::convert (dataArray, convertBuffer, samplesRead, applyScaling);
00274                 }
00275                 else
00276                 {
00277                     plonk_assertfalse;
00278                     return;
00279                 }
00280             }
00281             else if (isFloat)
00282             {
00283                 if (bytesPerSample == 4)
00284                 {
00285                     Float* const convertBuffer = static_cast<Float*> (readBufferArray); 
00286                     swapEndianIfNotNative (convertBuffer, samplesRead, isBigEndian);
00287                     Buffer::convert (dataArray, convertBuffer, samplesRead, applyScaling);
00288                 }
00289                 else if (bytesPerSample == 8)
00290                 {
00291                     Double* const convertBuffer = static_cast<Double*> (readBufferArray); 
00292                     swapEndianIfNotNative (convertBuffer, samplesRead, isBigEndian);
00293                     Buffer::convert (dataArray, convertBuffer, samplesRead, applyScaling);
00294                 }
00295                 else
00296                 {
00297                     plonk_assertfalse;
00298                     return;
00299                 }
00300             }
00301             
00302             if (deinterleave && isInterleaved)
00303             {
00304                 plonk_assertfalse; // haven't tested this yet...
00305                 SampleType* const deinterleaveBuffer = static_cast<SampleType*> (readBufferArray); 
00306                 Buffer::deinterleave (deinterleaveBuffer, dataArray, samplesRead, channels);
00307                 Buffer::copyData (dataArray, deinterleaveBuffer, samplesRead);
00308             }
00309             else if (!deinterleave && !isInterleaved)
00310             {
00311                 plonk_assertfalse; // haven't tested this yet...
00312                 SampleType* const interleaveBuffer = static_cast<SampleType*> (readBufferArray); 
00313                 Buffer::interleave (interleaveBuffer, dataArray, samplesRead / channels, channels);
00314                 Buffer::copyData (dataArray, interleaveBuffer, samplesRead);
00315             }
00316             
00317             dataArray += samplesRead;
00318             dataIndex += samplesRead;
00319             dataRemaining -= samplesRead;
00320         }
00321         else
00322         {
00323             numFails++;
00324         }
00325             
00326         if ((result == PlankResult_FileEOF) && ((numLoops.getValue() == 0) || (numLoops.getValue() > 1)))
00327         {
00328             result = pl_AudioFileReader_ResetFramePosition (getPeerRef());              
00329             plonk_assert (result == PlankResult_OK);
00330             
00331             if (numLoops.getValue() > 1)
00332                 numLoops.setValue (numLoops.getValue() - 1);
00333         }
00334         else if (result == PlankResult_AudioFileFrameFormatChanged)
00335         {
00336             encoding = getEncoding();
00337             
00338             const int newNumChannels = getNumChannels();
00339             
00340             if (newNumChannels == channels)
00341             {
00342                 result = PlankResult_AudioFileChanged;
00343             }
00344             else
00345             {
00346                 channels = getNumChannels();
00347             }
00348             
00349             bytesPerSample = getBytesPerSample();
00350             
00351             plonk_assert ((encoding >= AudioFile::EncodingMin) && (encoding <= AudioFile::EncodingMax));
00352             plonk_assert (getBitsPerSample() > 0);
00353             plonk_assert (channels > 0);
00354             plonk_assert (getBytesPerFrame() > 0);
00355             
00356             isPCM = encoding & AudioFile::EncodingFlagPCM;
00357             isFloat = encoding & AudioFile::EncodingFlagFloat;
00358             isBigEndian = encoding & AudioFile::EncodingFlagBigEndian;
00359             isInterleaved = !(encoding & AudioFile::EncodingFlagNonIntervleaved);
00360             
00361             if (!getBytesPerFrame())
00362                 goto exit;
00363             
00364             numFramesPerBuffer = readBuffer.length() / getBytesPerFrame();
00365         }
00366     }
00367     
00368 exit:
00369     if (dataIndex < dataLength)
00370         data.setSize (dataIndex, true);
00371     
00372     this->hitEndOfFile       = (result == PlankResult_FileEOF);
00373     this->numChannelsChanged = (result == PlankResult_AudioFileFrameFormatChanged);
00374     this->audioFileChanged   = (result == PlankResult_AudioFileChanged);
00375 }
00376 
00377 
00378 //------------------------------------------------------------------------------
00379 
00386 class AudioFileReader : public SmartPointerContainer<AudioFileReaderInternal>
00387 {
00388 public:
00389     typedef AudioFileReaderInternal                 Internal;
00390     typedef SmartPointerContainer<Internal>         Base;
00391     typedef WeakPointerContainer<AudioFileReader>   Weak;
00392 
00393     
00394     static const AudioFileReader& getNull() throw()
00395     {
00396         static AudioFileReader null;        
00397         return null;
00398     }
00399     
00402     AudioFileReader() throw()
00403     :   Base (new Internal())
00404     {
00405     }
00406     
00410         AudioFileReader (Text const& path) throw()
00411         :       Base (new Internal (path.getArray(), 0, AudioFileMetaDataIOFlags((UnsignedInt)AudioFile::MetaDataIOFlagsNone)))
00412         {
00413         }
00414         
00418         AudioFileReader (const char* path) throw()
00419         :       Base (new Internal (path, 0, AudioFileMetaDataIOFlags((UnsignedInt)AudioFile::MetaDataIOFlagsNone)))
00420         {
00421         }
00422     
00426         AudioFileReader (FilePath const& path) throw()
00427         :       Base (new Internal (path.fullpath().getArray(), 0, AudioFileMetaDataIOFlags((UnsignedInt)AudioFile::MetaDataIOFlagsNone)))
00428         {
00429         }
00430     
00431     AudioFileReader (FilePath const& path, const int bufferSize, AudioFileMetaDataIOFlags const& metaDataIOFlags) throw()
00432         :       Base (new Internal (path.fullpath().getArray(), bufferSize, metaDataIOFlags))
00433         {
00434         }
00435     
00439         AudioFileReader (const char* path, const int bufferSize, AudioFileMetaDataIOFlags const& metaDataIOFlags) throw()
00440         :       Base (new Internal (path, bufferSize, metaDataIOFlags))
00441         {
00442         }
00443 
00444     AudioFileReader (FilePath const& path, const int bufferSize, UnsignedInt const& metaDataIOFlags) throw()
00445         :       Base (new Internal (path.fullpath().getArray(), bufferSize, AudioFileMetaDataIOFlags (metaDataIOFlags)))
00446         {
00447         }
00448     
00452         AudioFileReader (const char* path, const int bufferSize, UnsignedInt const& metaDataIOFlags) throw()
00453         :       Base (new Internal (path, bufferSize, AudioFileMetaDataIOFlags (metaDataIOFlags)))
00454         {
00455         }
00456 
00460         AudioFileReader (FilePathArray const& paths, const AudioFile::MultiFileTypes multiMode = AudioFile::MultiFileArraySequenceLoop, const int bufferSize = 0) throw()
00461         :       Base (new Internal (paths, multiMode, bufferSize))
00462         {
00463         }
00464     
00468         AudioFileReader (FilePathArray const& paths, IntVariable const& nextIndex, const int bufferSize = 0) throw()
00469         :       Base (new Internal (paths, nextIndex, bufferSize))
00470         {
00471         }
00472     
00473     AudioFileReader (AudioFileReaderArray const& audioFiles, const AudioFile::MultiFileTypes multiMode, const int bufferSize = 0, IntVariable* indexRef = 0) throw()
00474         :       Base (new Internal (audioFiles, multiMode, bufferSize, indexRef))
00475     {
00476     }
00477 
00478     AudioFileReader (FilePathQueue const& paths, const int bufferSize = 0) throw()
00479     :   Base (new Internal (paths, bufferSize))
00480     {
00481     }
00482     
00483     AudioFileReader (AudioFileReaderQueue const& audioFiles, const int bufferSize = 0) throw()
00484     :   Base (new Internal (audioFiles, bufferSize))
00485     {
00486     }
00487     
00488     AudioFileReader (AudioFileReader const& original, AudioFileRegion const region, const int bufferSize = 0) throw()
00489     :   Base (new Internal (original, region, bufferSize))
00490     {
00491     }
00492     
00493 //    AudioFileReader (AudioFileReader const& original, const LongLong start, const LongLong end, const int bufferSize = 0) throw()
00494 //    : Base (new Internal (original, start, end, bufferSize))
00495 //    {
00496 //    }
00497 //    
00498 //    AudioFileReader (AudioFileReader const& original, const int start, const int end, const int bufferSize = 0) throw()
00499 //    : Base (new Internal (original, start, end, bufferSize))
00500 //    {
00501 //    }
00502 //    
00503 //    AudioFileReader (AudioFileReader const& original, const long start, const long end, const int bufferSize = 0) throw()
00504 //    : Base (new Internal (original, start, end, bufferSize))
00505 //    {
00506 //    }
00507 //
00508     AudioFileReader (AudioFileReader const& original, const double start, const double end, const int bufferSize = 0) throw()
00509     :   Base (new Internal (original,
00510                             AudioFileRegion (0, start, end, -1.0),
00511                             bufferSize))
00512     {
00513     }
00514 //
00515 //    AudioFileReader (AudioFileReader const& original, const float start, const float end, const int bufferSize = 0) throw()
00516 //    : Base (new Internal (original,
00517 //                            LongLong (start * original.getSampleRate()),
00518 //                            LongLong (end * original.getSampleRate()),
00519 //                            bufferSize))
00520 //    {
00521 //    }
00522 
00524     explicit AudioFileReader (Internal* internalToUse) throw() 
00525         :       Base (internalToUse)
00526         {
00527         }    
00528     
00531     AudioFileReader (AudioFileReader const& copy) throw()
00532     :   Base (static_cast<Base const&> (copy))
00533     {
00534     }
00535     
00536     AudioFileReader (ByteArray const& bytes, const int bufferSize = 0, AudioFileMetaDataIOFlags const& metaDataIOFlags = AudioFileMetaDataIOFlags ((UnsignedInt)AudioFile::MetaDataIOFlagsNone)) throw()
00537         :       Base (new Internal (bytes, bufferSize, metaDataIOFlags))
00538         {
00539         }
00540     
00541     AudioFileReader (ByteArray const& bytes, const int bufferSize = 0, UnsignedInt const& metaDataIOFlags = AudioFile::MetaDataIOFlagsNone) throw()
00542         :       Base (new Internal (bytes, bufferSize, AudioFileMetaDataIOFlags (metaDataIOFlags)))
00543         {
00544         }
00545     
00547     AudioFileReader& operator= (AudioFileReader const& other) throw()
00548         {
00549                 if (this != &other)
00550             this->setInternal (other.getInternal());
00551         
00552         return *this;
00553         }
00554     
00558     static AudioFileReader fromWeak (Weak const& weak) throw()
00559     {
00560         return weak.fromWeak();
00561     }    
00562     
00566     inline AudioFile::Format getFormat() const throw()
00567     {
00568         return getInternal()->getFormat();
00569     }
00570     
00574     inline AudioFile::Encoding getEncoding() const throw()
00575     {
00576         return getInternal()->getEncoding();
00577     }
00578     
00582     inline AudioFile::SampleType getSampleType() const throw()
00583     {
00584         return getInternal()->getSampleType();   
00585     }
00586     
00588     inline int getBitsPerSample() const throw()
00589     {
00590         return getInternal()->getBitsPerSample();
00591     }
00592     
00594     inline int getBytesPerFrame() const throw()
00595     {
00596         return getInternal()->getBytesPerFrame();
00597     }
00598     
00600     inline int getBytesPerSample() const throw()
00601     {
00602         return getInternal()->getBytesPerSample();
00603     }
00604     
00606     inline int getNumChannels() const throw()
00607     {
00608         return getInternal()->getNumChannels();
00609     }
00610     
00614     inline void setDefaultNumChannels (const int numChannels) throw()
00615     {
00616         getInternal()->setDefaultNumChannels (numChannels);
00617     }
00618 
00620     inline int getDefaultNumChannels() const throw()
00621     {
00622         return getInternal()->getDefaultNumChannels();
00623     }
00624     
00625     inline void setDefaultSampleRate (const double sampleRate) throw()
00626     {
00627         getInternal()->setDefaultSampleRate (sampleRate);
00628     }
00629 
00630     inline double getDefaultSampleRate() const throw()
00631     {
00632         return getInternal()->getDefaultSampleRate();
00633     }
00634 
00636     inline double getSampleRate() const throw()
00637     {
00638         return getInternal()->getSampleRate();
00639     }
00640     
00642     inline LongLong getNumFrames() const throw()
00643     {
00644         return getInternal()->getNumFrames();
00645     }
00646     
00647     inline bool isPositionable() const throw()
00648     {
00649         return getInternal()->isPositionable();
00650     }
00651     
00653     inline LongLong getFramePosition() const throw()
00654     {
00655         return getInternal()->getFramePosition();
00656     }
00657     
00661     inline void setFramePosition (const LongLong position) throw()
00662     {
00663         getInternal()->setFramePosition (position);
00664     }
00665     
00668     inline void setFramePositionOnNextRead (const LongLong position) throw()
00669     {
00670         getInternal()->setFramePositionOnNextRead (position);
00671     }
00672     
00674     inline void resetFramePosition() throw()
00675     {
00676         getInternal()->resetFramePosition();
00677     }
00678     
00679     inline double getDuration() const throw()
00680     {
00681         return getInternal()->getNumFrames() / getInternal()->getSampleRate();
00682     }
00683         
00684     inline double getTime() const throw()
00685     {
00686         return getInternal()->getFramePosition() / getInternal()->getSampleRate();
00687     }
00688     
00689     inline void setTime (const double time) throw()
00690     {
00691         getInternal()->setFramePosition (LongLong (time * getInternal()->getSampleRate()));
00692     }
00693     
00694     inline void setTimeOnNextRead (const double time) throw()
00695     {
00696         getInternal()->setFramePositionOnNextRead (LongLong (time * getInternal()->getSampleRate()));
00697     }
00698     
00704     template<class SampleType>
00705     inline void readFrames (NumericalArray<SampleType>& data, IntVariable& numLoops) throw()
00706     {
00707         getInternal()->readFrames (data, true, false, numLoops);
00708     }
00709     
00710     template<class SampleType>
00711     inline void readFrames (NumericalArray<SampleType>& data) throw()
00712     {
00713         IntVariable numLoops (1);
00714         getInternal()->readFrames (data, true, false, numLoops);
00715     }
00716     
00721     template<class SampleType>
00722     inline void readFramesDirect (NumericalArray<SampleType>& data, IntVariable& numLoops) throw()
00723     {
00724         getInternal()->readFrames (data, false, false, numLoops);
00725     }
00726     
00727     template<class SampleType>
00728     inline void readFramesDirect (NumericalArray<SampleType>& data) throw()
00729     {
00730         IntVariable numLoops (1);
00731         getInternal()->readFrames (data, false, false, numLoops);
00732     }
00733     
00737     template<class SampleType>
00738     void initSignal (SignalBase<SampleType>& signal, const int numFrames = 0) const throw()
00739     {
00740         getInternal()->initSignal (signal, numFrames);
00741     }
00742     
00748     template<class SampleType>
00749     inline void readSignal (SignalBase<SampleType>& signal) throw()
00750     {
00751         plonk_assert (signal.isInterleaved());
00752         getInternal()->readSignal (signal, true);
00753     }
00754     
00758     template<class SampleType>
00759     inline void readSignalDirect (SignalBase<SampleType>& signal) throw()
00760     {
00761         plonk_assert (signal.isInterleaved());
00762         getInternal()->readSignal (signal, false);
00763     }
00764     
00770     template<class SampleType>
00771     inline NumericalArray<SampleType> readAllFrames (const bool applyScaling) throw()
00772     {
00773         typedef NumericalArray<SampleType> SampleArray;
00774         SampleArray data = SampleArray::withSize ((int)getNumFrames() * getNumChannels());
00775         resetFramePosition();
00776         IntVariable oneLoop (1);
00777         getInternal()->readFrames (data, applyScaling, false, oneLoop);
00778         return data;
00779     }
00780 
00783     template<class SampleType>
00784     inline operator NumericalArray<SampleType> () throw()
00785     {
00786         return readAllFrames<SampleType> (true);
00787     }
00788     
00791     template<class SampleType>
00792     inline operator SignalBase<SampleType> () throw()
00793     {
00794         NumericalArray<SampleType> data = readAllFrames<SampleType> (true);
00795         return SignalBase<SampleType> (data, getSampleRate(), getNumChannels());
00796     }
00797     
00800     template<class SampleType>
00801     inline SignalBase<SampleType> getOtherSignal() throw()
00802     {
00803         NumericalArray<SampleType> data = readAllFrames<SampleType> (true);
00804         return SignalBase<SampleType> (data, getSampleRate(), getNumChannels());
00805     }
00806     
00809     inline SignalBase<PLONK_TYPE_DEFAULT> getSignal() throw()
00810     {
00811         return getOtherSignal<PLONK_TYPE_DEFAULT>();
00812     }    
00813     
00814     void setOwner (void* owner) throw()
00815     {
00816         getInternal()->setOwner (owner);
00817     }
00818     
00819     void* getOwner() const throw()
00820     {
00821         return getInternal()->getOwner();
00822     }
00823     
00824     bool isOwned() const throw()
00825     {
00826         return getInternal()->isOwned();
00827     }
00828     
00831     bool isReady() const throw()
00832     {
00833         return getInternal()->isReady();
00834     }
00835     
00836     void disownPeer (PlankAudioFileReaderRef otherReader) throw()
00837     {
00838         getInternal()->disownPeer (otherReader);
00839     }
00840     
00841     bool didHitEOF() const throw()
00842     {
00843         return getInternal()->didHitEOF();
00844     }
00845     
00846     bool didNumChannelsChange() const throw()
00847     {
00848         return getInternal()->didNumChannelsChange();
00849     }
00850     
00851     bool didAudioFileChange() const throw()
00852     {
00853         return getInternal()->didAudioFileChange();
00854     }
00855     
00856     AudioFileReaderArray regionsFromMetaData (const int metaDataOption, const int bufferSize = 0) throw();
00857     
00858     void setName (Text const& name) throw()
00859     {
00860         getInternal()->setName (name);
00861     }
00862     
00863     Text getName() const throw()
00864     {
00865         return getInternal()->getName();
00866     }
00867 
00868     bool hasMetaData() const throw()
00869     {
00870         return this->getInternal()->hasMetaData();
00871     }
00872     
00873     AudioFileMetaData getMetaData() const throw()
00874     {
00875         return this->getInternal()->getMetaData();
00876     }
00877     
00878     inline ChannelLayout getChannelLayout() const throw()
00879     {
00880         return this->getInternal()->getChannelLayout();
00881     }
00882     
00883     inline ChannelIdentifier getChannelIdentifier (const int channel) const throw()
00884     {
00885         return this->getInternal()->getChannelIdentifier (channel);
00886     }
00887 
00888 
00889 private:
00890     // these could be currently dangerous across threads, need to look at a safer way to open
00891     // a new file once one is already running...
00892     
00893     ResultCode open (const char* path, const int bufferSize, AudioFileMetaDataIOFlags const& metaDataIOFlags) throw()
00894     {
00895         return getInternal()->open (path, bufferSize, metaDataIOFlags);
00896     }
00897     
00898     ResultCode open (Text const& path) throw()
00899     {
00900         return getInternal()->open (path.getArray(), 0, AudioFileMetaDataIOFlags((UnsignedInt)AudioFile::MetaDataIOFlagsNone));
00901     }    
00902 };
00903 
00904 
00905 
00906 #endif // PLONK_AUDIOFILEREADER_H
 All Classes Functions Typedefs Enumerations Enumerator Properties