![]() |
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_AUDIOFILEWRITER_H 00040 #define PLONK_AUDIOFILEWRITER_H 00041 00042 #include "../../core/plonk_CoreForwardDeclarations.h" 00043 #include "../plonk_FilesForwardDeclarations.h" 00044 #include "../../core/plonk_SmartPointer.h" 00045 #include "../../core/plonk_WeakPointer.h" 00046 #include "../../core/plonk_SmartPointerContainer.h" 00047 #include "../../containers/plonk_Text.h" 00048 #include "plonk_AudioFile.h" 00049 #include "plonk_AudioFileMetaData.h" 00050 00051 00052 template<class SampleType> 00053 class AudioFileWriterInternalBase : public SmartPointer 00054 { 00055 private: 00056 AudioFileWriterInternalBase(); // incompatible SampleType 00057 }; 00058 00059 template<> class AudioFileWriterInternalBase<Char> : public SmartPointer { public: AudioFileWriterInternalBase<Char>() : isFloat (false) { } protected: const bool isFloat; }; 00060 template<> class AudioFileWriterInternalBase<Short> : public SmartPointer { public: AudioFileWriterInternalBase<Short>() : isFloat (false) { } protected: const bool isFloat; }; 00061 template<> class AudioFileWriterInternalBase<Int24> : public SmartPointer { public: AudioFileWriterInternalBase<Int24>() : isFloat (false) { } protected: const bool isFloat; }; 00062 template<> class AudioFileWriterInternalBase<Int> : public SmartPointer { public: AudioFileWriterInternalBase<Int>() : isFloat (false) { } protected: const bool isFloat; }; 00063 template<> class AudioFileWriterInternalBase<Float> : public SmartPointer { public: AudioFileWriterInternalBase<Float>() : isFloat (true) { } protected: const bool isFloat; }; 00064 template<> class AudioFileWriterInternalBase<Double> : public SmartPointer { public: AudioFileWriterInternalBase<Double>() : isFloat (true) { } protected: const bool isFloat; }; 00065 00066 template<class SampleType> 00067 class AudioFileWriterInternal : public AudioFileWriterInternalBase<SampleType> 00068 { 00069 public: 00070 typedef NumericalArray<SampleType> Buffer; 00071 00072 AudioFileWriterInternal (const int bufferSize) throw() 00073 : buffer (Buffer::withSize (bufferSize > 0 ? bufferSize : AudioFile::DefaultBufferSize, false)), 00074 ready (false) 00075 { 00076 pl_AudioFileWriter_Init (&peer); 00077 } 00078 00079 bool openPath (FilePath const& path) 00080 { 00081 return pl_AudioFileWriter_Open (&peer, path.fullpath().getArray()) == PlankResult_OK; 00082 } 00083 00084 bool openFile (PlankFileRef file) 00085 { 00086 return pl_AudioFileWriter_OpenWithFile (&peer, file) == PlankResult_OK; 00087 } 00088 00089 bool initBytes (PlankFileRef file, ByteArray const& bytes) throw() 00090 { 00091 return BinaryFileInternal::setupBytes (file, bytes, true); 00092 } 00093 00094 static AudioFileWriterInternal* createPCM (FilePath const& path, const ChannelLayout channelLayout, const double sampleRate, const int bufferSize) throw() 00095 { 00096 AudioFileWriterInternal* internal = new AudioFileWriterInternal ((channelLayout.getValue() & 0x0000FFFF) * bufferSize); 00097 const Text ext = path.extension(); 00098 00099 AudioFile::Format format = AudioFile::FormatInvalid; 00100 00101 if (ext.equalsIgnoreCase ("wav")) 00102 { 00103 format = AudioFile::FormatWAV; 00104 } 00105 else if (ext.equalsIgnoreCase ("aif")) 00106 { 00107 format = AudioFile::FormatAIFF; 00108 } 00109 else if (ext.equalsIgnoreCase ("aiff") || ext.equalsIgnoreCase ("aifc")) 00110 { 00111 format = AudioFile::FormatAIFC; 00112 } 00113 else if (ext.equalsIgnoreCase ("caf")) 00114 { 00115 format = AudioFile::FormatCAF; 00116 } 00117 else if (ext.equalsIgnoreCase ("w64")) 00118 { 00119 format = AudioFile::FormatW64; 00120 } 00121 00122 if (!internal->initPCM (format, channelLayout, sampleRate, bufferSize)) 00123 { 00124 pl_AudioFileWriter_Init (&internal->peer); 00125 goto exit; 00126 } 00127 00128 if (!internal->openPath (path)) 00129 { 00130 pl_AudioFileWriter_Close (&internal->peer); 00131 pl_AudioFileWriter_Init (&internal->peer); 00132 goto exit; 00133 } 00134 00135 internal->ready = true; 00136 00137 exit: 00138 return internal; 00139 } 00140 00141 static AudioFileWriterInternal* createPCM (ByteArray const& bytes, AudioFile::Format format, const ChannelLayout channelLayout, const double sampleRate, const int bufferSize) throw() 00142 { 00143 AudioFileWriterInternal* internal = new AudioFileWriterInternal ((channelLayout & 0x0000FFFF) * bufferSize); 00144 PlankFile file; 00145 00146 if (!internal->initBytes (&file, bytes)) 00147 { 00148 pl_AudioFileWriter_Init (&internal->peer); 00149 goto exit; 00150 } 00151 00152 if (!internal->initPCM (format, channelLayout, sampleRate, bufferSize)) 00153 { 00154 pl_AudioFileWriter_Init (&internal->peer); 00155 goto exit; 00156 } 00157 00158 if (!internal->openFile (&file)) 00159 { 00160 pl_AudioFileWriter_Close (&internal->peer); 00161 pl_AudioFileWriter_Init (&internal->peer); 00162 goto exit; 00163 } 00164 00165 internal->ready = true; 00166 00167 exit: 00168 return internal; 00169 } 00170 00171 static AudioFileWriterInternal* createCompressedVBR (FilePath const& path, const ChannelLayout channelLayout, const double sampleRate, 00172 const float quality, const double frameDuration, const int bufferSize) throw() 00173 { 00174 AudioFileWriterInternal* internal = new AudioFileWriterInternal ((channelLayout.getValue() & 0x0000FFFF) * bufferSize); 00175 const Text ext = path.extension(); 00176 00177 AudioFile::Format format = AudioFile::FormatInvalid; 00178 00179 if (false) 00180 { 00181 } 00182 #if PLANK_OGGVORBIS 00183 else if (ext.equalsIgnoreCase ("ogg") && 00184 (sizeof (SampleType) == 4) && 00185 internal->isFloat) 00186 { 00187 format = AudioFile::FormatOggVorbis; 00188 } 00189 #endif 00190 #if PLANK_OPUS 00191 else if (ext.equalsIgnoreCase ("opus") && 00192 (sizeof (SampleType) == 4) && 00193 internal->isFloat) 00194 { 00195 format = AudioFile::FormatOpus; 00196 } 00197 #endif 00198 00199 if (!internal->initCompressedVBR (format, channelLayout, sampleRate, quality, frameDuration, bufferSize)) 00200 { 00201 pl_AudioFileWriter_Init (&internal->peer); 00202 goto exit; 00203 } 00204 00205 if (!internal->openPath (path)) 00206 { 00207 pl_AudioFileWriter_Close (&internal->peer); 00208 pl_AudioFileWriter_Init (&internal->peer); 00209 goto exit; 00210 } 00211 00212 internal->ready = true; 00213 00214 exit: 00215 return internal; 00216 } 00217 00218 static AudioFileWriterInternal* createCompressedVBR (ByteArray const& bytes, AudioFile::Format format, const ChannelLayout channelLayout, const double sampleRate, 00219 const float quality, const double frameDuration, const int bufferSize) throw() 00220 { 00221 AudioFileWriterInternal* internal = new AudioFileWriterInternal ((channelLayout.getValue() & 0x0000FFFF) * bufferSize); 00222 PlankFile file; 00223 00224 if (!internal->initBytes (&file, bytes)) 00225 { 00226 pl_AudioFileWriter_Init (&internal->peer); 00227 goto exit; 00228 } 00229 00230 if (!internal->initCompressedVBR (format, channelLayout, sampleRate, quality, frameDuration, bufferSize)) 00231 { 00232 pl_AudioFileWriter_Init (&internal->peer); 00233 goto exit; 00234 } 00235 00236 if (!internal->openFile (&file)) 00237 { 00238 pl_AudioFileWriter_Close (&internal->peer); 00239 pl_AudioFileWriter_Init (&internal->peer); 00240 goto exit; 00241 } 00242 00243 internal->ready = true; 00244 00245 exit: 00246 return internal; 00247 } 00248 00249 static AudioFileWriterInternal* createCompressedManaged (FilePath const& path, const ChannelLayout channelLayout, const double sampleRate, 00250 const int minBitRate, const int nominalBitRate, const int maxBitRate, 00251 const double frameDuration, const int bufferSize) throw() 00252 { 00253 AudioFileWriterInternal* internal = new AudioFileWriterInternal ((channelLayout.getValue() & 0x0000FFFF) * bufferSize); 00254 const Text ext = path.extension(); 00255 00256 AudioFile::Format format = AudioFile::FormatInvalid; 00257 00258 if (false) 00259 { 00260 } 00261 #if PLANK_OGGVORBIS 00262 else if (ext.equalsIgnoreCase ("ogg") && 00263 (sizeof (SampleType) == 4) && 00264 internal->isFloat) 00265 { 00266 format = AudioFile::FormatOggVorbis; 00267 } 00268 #endif 00269 #if PLANK_OPUS 00270 else if (ext.equalsIgnoreCase ("opus") && 00271 (sizeof (SampleType) == 4) && 00272 internal->isFloat) 00273 { 00274 format = AudioFile::FormatOpus; 00275 } 00276 #endif 00277 00278 if (!internal->initCompressedManaged (format, channelLayout, sampleRate, minBitRate, nominalBitRate, maxBitRate, frameDuration, bufferSize)) 00279 { 00280 pl_AudioFileWriter_Init (&internal->peer); 00281 goto exit; 00282 } 00283 00284 if (!internal->openPath (path)) 00285 { 00286 pl_AudioFileWriter_Close (&internal->peer); 00287 pl_AudioFileWriter_Init (&internal->peer); 00288 goto exit; 00289 } 00290 00291 internal->ready = true; 00292 00293 exit: 00294 return internal; 00295 } 00296 00297 static AudioFileWriterInternal* createCompressedManaged (ByteArray const& bytes, AudioFile::Format format, const ChannelLayout channelLayout, const double sampleRate, 00298 const int minBitRate, const int nominalBitRate, const int maxBitRate, 00299 const double frameDuration, const int bufferSize) throw() 00300 { 00301 AudioFileWriterInternal* internal = new AudioFileWriterInternal ((channelLayout.getValue() & 0x0000FFFF) * bufferSize); 00302 PlankFile file; 00303 00304 if (!internal->initBytes (&file, bytes)) 00305 { 00306 pl_AudioFileWriter_Init (&internal->peer); 00307 goto exit; 00308 } 00309 00310 if (!internal->initCompressedManaged (format, channelLayout, sampleRate, minBitRate, nominalBitRate, maxBitRate, frameDuration, bufferSize)) 00311 { 00312 pl_AudioFileWriter_Init (&internal->peer); 00313 goto exit; 00314 } 00315 00316 if (!internal->openFile (&file)) 00317 { 00318 pl_AudioFileWriter_Close (&internal->peer); 00319 pl_AudioFileWriter_Init (&internal->peer); 00320 goto exit; 00321 } 00322 00323 internal->ready = true; 00324 00325 exit: 00326 return internal; 00327 } 00328 00329 00330 bool initPCM (const AudioFile::Format format, const ChannelLayout channelLayout, const double sampleRate, const int bufferSize) throw() 00331 { 00332 ResultCode result = PlankResult_UnknownError; 00333 00334 if (format == AudioFile::FormatWAV) 00335 { 00336 if ((result = pl_AudioFileWriter_SetFormatWAV (&peer, sizeof (SampleType) * 8, channelLayout, sampleRate, this->isFloat)) != PlankResult_OK) goto exit; 00337 } 00338 else if (format == AudioFile::FormatAIFF) 00339 { 00340 // ideally we'd allow aiff but this is used to identify aifc (below) 00341 00342 if (this->isFloat) 00343 { 00344 if ((result = pl_AudioFileWriter_SetFormatAIFC (&peer, sizeof (SampleType) * 8, channelLayout, sampleRate, true, false)) != PlankResult_OK) goto exit;; 00345 } 00346 else 00347 { 00348 if ((result = pl_AudioFileWriter_SetFormatAIFF (&peer, sizeof (SampleType) * 8, channelLayout, sampleRate)) != PlankResult_OK) goto exit;; 00349 } 00350 } 00351 else if (format == AudioFile::FormatAIFC) 00352 { 00353 // ideally we'd use aifc only but some audio apps don't recognise this 00354 #if PLANK_LITTLEENDIAN 00355 if ((result = pl_AudioFileWriter_SetFormatAIFC (&peer, sizeof (SampleType) * 8, channelLayout, sampleRate, this->isFloat, !this->isFloat && sizeof (SampleType) == 2)) != PlankResult_OK) goto exit;; 00356 #endif 00357 #if PLANK_BIGENDIAN 00358 if ((result = pl_AudioFileWriter_SetFormatAIFC (&peer, sizeof (SampleType) * 8, channelLayout, sampleRate, this->isFloat, false)) != PlankResult_OK) goto exit;; 00359 #endif 00360 } 00361 else if (format == AudioFile::FormatCAF) 00362 { 00363 if ((result = pl_AudioFileWriter_SetFormatCAF (&peer, sizeof (SampleType) * 8, channelLayout, sampleRate, this->isFloat, PLANK_LITTLEENDIAN)) != PlankResult_OK) goto exit; 00364 this->setHeaderPad (AudioFile::CAFDefaultHeaderPad); 00365 } 00366 else if (format == AudioFile::FormatW64) 00367 { 00368 if ((result = pl_AudioFileWriter_SetFormatW64 (&peer, sizeof (SampleType) * 8, channelLayout, sampleRate, this->isFloat)) != PlankResult_OK) goto exit;; 00369 } 00370 00371 exit: 00372 return result == PlankResult_OK; 00373 } 00374 00375 bool initCompressedVBR (const AudioFile::Format format, const ChannelLayout channelLayout, const double sampleRate, const float quality, 00376 const double frameDuration, const int bufferSize) throw() 00377 { 00378 ResultCode result = PlankResult_UnknownError; 00379 00380 if (false) 00381 { 00382 } 00383 #if PLANK_OGGVORBIS 00384 else if (format == AudioFile::FormatOggVorbis) 00385 { 00386 if ((result = pl_AudioFileWriter_SetFormatOggVorbis (&peer, quality, channelLayout, sampleRate)) != PlankResult_OK) goto exit;; 00387 } 00388 #endif 00389 #if PLANK_OPUS 00390 else if (format == AudioFile::FormatOpus) 00391 { 00392 if ((result = pl_AudioFileWriter_SetFormatOpus (&peer, quality, channelLayout, sampleRate, frameDuration <= 0.0 ? 0.02 : frameDuration)) != PlankResult_OK) goto exit;; 00393 } 00394 #endif 00395 00396 exit: 00397 return result == PlankResult_OK; 00398 } 00399 00400 bool initCompressedManaged (const AudioFile::Format format, const ChannelLayout channelLayout, const double sampleRate, 00401 const int minBitRate, const int nominalBitRate, const int maxBitRate, 00402 const double frameDuration, const int bufferSize) throw() 00403 { 00404 ResultCode result = PlankResult_UnknownError; 00405 00406 if (false) 00407 { 00408 } 00409 #if PLANK_OGGVORBIS 00410 else if (format == AudioFile::FormatOggVorbis) 00411 { 00412 if ((result = pl_AudioFileWriter_SetFormatOggVorbisManaged (&peer, 00413 minBitRate, nominalBitRate, maxBitRate, 00414 channelLayout, sampleRate)) != PlankResult_OK) goto exit;; 00415 } 00416 #endif 00417 #if PLANK_OPUS 00418 else if (format == AudioFile::FormatOpus) 00419 { 00420 if ((result = pl_AudioFileWriter_SetFormatOpusManaged (&peer, 00421 nominalBitRate == 0 ? (maxBitRate + minBitRate) / 2 : nominalBitRate, 00422 channelLayout, sampleRate, frameDuration <= 0.0 ? 0.02 : frameDuration)) != PlankResult_OK) goto exit;; 00423 } 00424 #endif 00425 00426 exit: 00427 return result == PlankResult_OK; 00428 } 00429 00430 ~AudioFileWriterInternal() 00431 { 00432 PlankResult result = PlankResult_OK; 00433 result = pl_AudioFileWriter_DeInit (&peer); 00434 plonk_assert (result == PlankResult_OK); 00435 } 00436 00437 void setHeaderPad (const UnsignedInt bytes) throw() 00438 { 00439 pl_AudioFileWriter_SetHeaderPad (&peer, bytes); 00440 } 00441 00442 void writeHeader() throw() 00443 { 00444 pl_AudioFileWriter_WriteHeader (&peer); 00445 } 00446 00447 void close() throw() 00448 { 00449 pl_AudioFileWriter_Close (&peer); 00450 } 00451 00452 bool writeFrames (const int numFrames, const SampleType* frameData) throw() 00453 { 00454 return pl_AudioFileWriter_WriteFrames (&peer, true, numFrames, frameData) == PlankResult_OK; 00455 } 00456 00457 bool writeFrames (Buffer const& frames) throw() 00458 { 00459 const int numChannels = pl_AudioFileFormatInfo_GetNumChannels (&peer.formatInfo); 00460 plonk_assert ((frames.length() % numChannels) == 0); 00461 return pl_AudioFileWriter_WriteFrames (&peer, true, frames.length() / numChannels, frames.getArray()) == PlankResult_OK; 00462 } 00463 00464 template<class OtherType> 00465 bool writeFrames (NumericalArray<OtherType> const& frames) throw() 00466 { 00467 bool success = true; 00468 const int numChannels = pl_AudioFileFormatInfo_GetNumChannels (&peer.formatInfo); 00469 00470 plonk_assert ((frames.length() % numChannels) == 0); 00471 00472 SampleType* const nativeSamples = buffer.getArray(); 00473 const OtherType* sourceSamples = frames.getArray(); 00474 const int nativeSamplesLength = buffer.length(); 00475 00476 int numSamplesRemainaing = frames.length(); 00477 00478 while (numSamplesRemainaing > 0) 00479 { 00480 const int numSamplesThisTime = plonk::min (nativeSamplesLength, numSamplesRemainaing); 00481 NumericalArrayConverter<SampleType, OtherType>::convertScaled (nativeSamples, sourceSamples, numSamplesThisTime); 00482 success = pl_AudioFileWriter_WriteFrames (&peer, true, numSamplesThisTime / numChannels, nativeSamples) == PlankResult_OK; 00483 00484 if (!success) break; 00485 00486 numSamplesRemainaing -= numSamplesThisTime; 00487 sourceSamples += numSamplesThisTime; 00488 } 00489 00490 return success; 00491 } 00492 00493 bool writeFrames (AudioFileReader& reader, const int numFrames) throw() 00494 { 00495 const int numChannels = pl_AudioFileFormatInfo_GetNumChannels (&peer.formatInfo); 00496 // plonk_assert (peer.formatInfo.sampleRate == reader.getSampleRate()); 00497 plonk_assert (numChannels == reader.getNumChannels()); 00498 00499 const int bufferLength = buffer.length(); 00500 // const int bufferFrames = bufferLength / numChannels; 00501 int framesRead; 00502 00503 if (numFrames <= 0) 00504 { 00505 do 00506 { 00507 reader.readFrames (buffer); 00508 framesRead = buffer.length() / numChannels; 00509 00510 if (framesRead == 0) break; 00511 00512 this->writeFrames (buffer); 00513 } 00514 while (!reader.didHitEOF()); 00515 } 00516 else 00517 { 00518 int numFramesRemaining = numFrames; 00519 00520 do 00521 { 00522 buffer.setSize (plonk::min (numFramesRemaining * numChannels, bufferLength), false); 00523 reader.readFrames (buffer); 00524 framesRead = buffer.length() / numChannels; 00525 00526 if (framesRead == 0) break; 00527 00528 numFramesRemaining -= framesRead; 00529 this->writeFrames (buffer); 00530 } 00531 while ((numFramesRemaining > 0) && !reader.didHitEOF()); 00532 } 00533 00534 // and reset for next time 00535 buffer.setSize (bufferLength, false); 00536 00537 return true; 00538 } 00539 00540 AudioFileMetaData getMetaData() const throw() 00541 { 00542 return AudioFileMetaData (pl_AudioFileWriter_GetMetaData (const_cast<PlankAudioFileWriter*> (&peer))); 00543 } 00544 00545 void setMetaData (AudioFileMetaData const& metaData) throw() 00546 { 00547 AudioFileMetaData m (metaData); 00548 pl_AudioFileWriter_SetMetaData (&peer, m.incrementRefCountAndGetPeer()); 00549 } 00550 00551 friend class AudioFileWriter<SampleType>; 00552 00553 private: 00554 PlankAudioFileWriter peer; 00555 Buffer buffer; 00556 bool ready; 00557 }; 00558 00559 00566 template<class SampleType> 00567 class AudioFileWriter: public SmartPointerContainer< AudioFileWriterInternal<SampleType> > 00568 { 00569 public: 00570 typedef AudioFileWriterInternal<SampleType> Internal; 00571 typedef SmartPointerContainer<Internal> Base; 00572 typedef NumericalArray<SampleType> Buffer; 00573 00574 AudioFileWriter (const int bufferSize = AudioFile::DefaultBufferSize) throw() 00575 : Base (new Internal (bufferSize)) 00576 { 00577 } 00578 00579 AudioFileWriter (FilePath const& path, const ChannelLayout channelLayout, const double sampleRate, 00580 const int bufferSize = AudioFile::DefaultBufferSize) throw() 00581 : Base (Internal::createPCM (path, channelLayout, sampleRate, bufferSize)) 00582 { 00583 } 00584 00585 AudioFileWriter (FilePath const& path, const ChannelLayout channelLayout, const double sampleRate, 00586 const float quality, 00587 const double frameDuration = 0.0, const int bufferSize = AudioFile::DefaultBufferSize) throw() 00588 : Base (Internal::createCompressedVBR (path, channelLayout, sampleRate, quality, frameDuration, bufferSize)) 00589 { 00590 } 00591 00592 AudioFileWriter (FilePath const& path, const ChannelLayout channelLayout, const double sampleRate, 00593 const int minBitRate, const int nominalBitRate, const int maxBitRate, 00594 const double frameDuration = 0.0, const int bufferSize = AudioFile::DefaultBufferSize) throw() 00595 : Base (Internal::createCompressedManaged (path, channelLayout, sampleRate, minBitRate, nominalBitRate, maxBitRate, frameDuration, bufferSize)) 00596 { 00597 } 00598 00599 AudioFileWriter (ByteArray const& bytes, const AudioFile::Format format, const ChannelLayout channelLayout, const double sampleRate, 00600 const int bufferSize = AudioFile::DefaultBufferSize) throw() 00601 : Base (Internal::createPCM (bytes, format, channelLayout, sampleRate, bufferSize)) 00602 { 00603 } 00604 00605 AudioFileWriter (ByteArray const& bytes, const AudioFile::Format format, const ChannelLayout channelLayout, const double sampleRate, 00606 const float quality, 00607 const double frameDuration = 0.0, const int bufferSize = AudioFile::DefaultBufferSize) throw() 00608 : Base (Internal::createCompressedVBR (bytes, format, channelLayout, sampleRate, quality, frameDuration, bufferSize)) 00609 { 00610 } 00611 00612 AudioFileWriter (ByteArray const& bytes, const AudioFile::Format format, const ChannelLayout channelLayout, const double sampleRate, 00613 const int minBitRate, const int nominalBitRate, const int maxBitRate, 00614 const double frameDuration = 0.0, const int bufferSize = AudioFile::DefaultBufferSize) throw() 00615 : Base (Internal::createCompressedManaged (bytes, format, channelLayout, sampleRate, minBitRate, nominalBitRate, maxBitRate, frameDuration, bufferSize)) 00616 { 00617 } 00618 00619 bool initPCM (const AudioFile::Format format, const ChannelLayout channelLayout, const double sampleRate, 00620 const int bufferSize = AudioFile::DefaultBufferSize) throw() 00621 { 00622 return this->getInternal()->initPCM (format, channelLayout, sampleRate, bufferSize); 00623 } 00624 00625 bool initCompressedVBR (const AudioFile::Format format, const ChannelLayout channelLayout, const double sampleRate, 00626 const float quality, 00627 const double frameDuration = 0.0, const int bufferSize = AudioFile::DefaultBufferSize) throw() 00628 { 00629 return this->getInternal()->initCompressedVBR (format, channelLayout, sampleRate, quality, frameDuration, bufferSize); 00630 } 00631 00632 bool initCompressedManaged (const AudioFile::Format format, const ChannelLayout channelLayout, const double sampleRate, 00633 const int minBitRate, const int nominalBitRate, const int maxBitRate, 00634 const double frameDuration = 0.0, const int bufferSize = AudioFile::DefaultBufferSize) throw() 00635 { 00636 return this->getInternal()->initCompressedManaged (format, channelLayout, sampleRate, minBitRate, nominalBitRate, maxBitRate, frameDuration, bufferSize); 00637 } 00638 00639 bool openPath (FilePath const& path) throw() 00640 { 00641 bool result = this->getInternal()->openPath (path); 00642 this->getInternal()->ready = result; 00643 return result; 00644 } 00645 00646 bool openBytes (ByteArray const& bytes) throw() 00647 { 00648 bool result = this->getInternal()->openBytes (bytes); 00649 this->getInternal()->ready = result; 00650 return result; 00651 } 00652 00653 void setHeaderPad (const UnsignedInt bytes) throw() 00654 { 00655 this->getInternal()->setHeaderPad (bytes); 00656 } 00657 00658 void writeHeader() throw() 00659 { 00660 this->getInternal()->writeHeader(); 00661 } 00662 00663 void close() throw() 00664 { 00665 this->getInternal()->close(); 00666 } 00667 00668 bool isReady() const throw() 00669 { 00670 return this->getInternal()->ready; 00671 } 00672 00674 inline int getNumChannels() const throw() 00675 { 00676 return pl_AudioFileWriter_GetNumChannels (&this->getInternal()->peer); 00677 } 00678 00679 inline ChannelLayout getChannelLayout() const throw() 00680 { 00681 PlankChannelLayout layout; 00682 pl_AudioFileWriter_GetChannelLayout (&this->getInternal()->peer, &layout); 00683 return layout; 00684 } 00685 00686 inline ChannelIdentifier getChannelIdentifier (const int channel) const throw() 00687 { 00688 PlankChannelIdentifier identifier; 00689 pl_AudioFileWriter_GetChannelItentifier (&this->getInternal()->peer, channel, &identifier); 00690 return identifier; 00691 } 00692 00693 inline void setChannelIdentifier (const int channel, ChannelIdentifier const& identifier) const throw() 00694 { 00695 pl_AudioFileWriter_SetChannelItentifier (&this->getInternal()->peer, channel, identifier); 00696 } 00697 00699 inline double getSampleRate() const throw() 00700 { 00701 return this->getInternal()->peer.formatInfo.sampleRate; 00702 } 00703 00704 bool writeFrames (const int numFrames, const SampleType* frameData) throw() 00705 { 00706 return this->getInternal()->writeFrames (numFrames, frameData); 00707 } 00708 00709 bool writeFrames (Buffer const& frames) throw() 00710 { 00711 return this->getInternal()->writeFrames (frames); 00712 } 00713 00714 bool writeFrames (AudioFileReader& reader, const int numFrames = 0) throw() 00715 { 00716 return this->getInternal()->writeFrames (reader, numFrames); 00717 } 00718 00719 template<class OtherType> 00720 bool writeFrames (NumericalArray<OtherType> const& frames) throw() 00721 { 00722 return this->getInternal()->writeFrames (frames); 00723 } 00724 00725 AudioFileMetaData getMetaData() const throw() 00726 { 00727 return this->getInternal()->getMetaData(); 00728 } 00729 00730 void setMetaData (AudioFileMetaData const& metaData) throw() 00731 { 00732 return this->getInternal()->setMetaData (metaData); 00733 } 00734 00735 }; 00736 00737 #endif // PLONK_AUDIOFILEWRITER_H