![]() |
pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
|
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