SFML logo
  • Main Page
  • Namespaces
  • Classes
  • Files
  • File List

SoundFile.cpp

00001 
00002 //
00003 // SFML - Simple and Fast Multimedia Library
00004 // Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
00005 //
00006 // This software is provided 'as-is', without any express or implied warranty.
00007 // In no event will the authors be held liable for any damages arising from the use of this software.
00008 //
00009 // Permission is granted to anyone to use this software for any purpose,
00010 // including commercial applications, and to alter it and redistribute it freely,
00011 // subject to the following restrictions:
00012 //
00013 // 1. The origin of this software must not be misrepresented;
00014 //    you must not claim that you wrote the original software.
00015 //    If you use this software in a product, an acknowledgment
00016 //    in the product documentation would be appreciated but is not required.
00017 //
00018 // 2. Altered source versions must be plainly marked as such,
00019 //    and must not be misrepresented as being the original software.
00020 //
00021 // 3. This notice may not be removed or altered from any source distribution.
00022 //
00024 
00026 // Headers
00028 #include <SFML/Audio/SoundFile.hpp>
00029 #include <SFML/System/Err.hpp>
00030 #include <string.h>
00031 
00032 
00033 namespace sf
00034 {
00035 namespace priv
00036 {
00038 SoundFile::SoundFile() :
00039 myFile         (NULL),
00040 myNbSamples    (0),
00041 myChannelsCount(0),
00042 mySampleRate   (0)
00043 {
00044 
00045 }
00046 
00047 
00049 SoundFile::~SoundFile()
00050 {
00051     if (myFile)
00052         sf_close(myFile);
00053 }
00054 
00055 
00057 std::size_t SoundFile::GetSamplesCount() const
00058 {
00059     return myNbSamples;
00060 }
00061 
00062 
00064 unsigned int SoundFile::GetChannelsCount() const
00065 {
00066     return myChannelsCount;
00067 }
00068 
00069 
00071 unsigned int SoundFile::GetSampleRate() const
00072 {
00073     return mySampleRate;
00074 }
00075 
00076 
00078 bool SoundFile::OpenRead(const std::string& filename)
00079 {
00080     // If the file is already opened, first close it
00081     if (myFile)
00082         sf_close(myFile);
00083 
00084     // Open the sound file
00085     SF_INFO fileInfos;
00086     myFile = sf_open(filename.c_str(), SFM_READ, &fileInfos);
00087     if (!myFile)
00088     {
00089         Err() << "Failed to read sound file \"" << filename << "\" (" << sf_strerror(myFile) << ")" << std::endl;
00090         return false;
00091     }
00092 
00093     // Set the sound parameters
00094     myChannelsCount = fileInfos.channels;
00095     mySampleRate    = fileInfos.samplerate;
00096     myNbSamples     = static_cast<std::size_t>(fileInfos.frames) * myChannelsCount;
00097 
00098     return true;
00099 }
00100 
00101 
00103 bool SoundFile::OpenRead(const void* data, std::size_t sizeInBytes)
00104 {
00105     // If the file is already opened, first close it
00106     if (myFile)
00107         sf_close(myFile);
00108 
00109     // Prepare the memory I/O structure
00110     SF_VIRTUAL_IO io = myMemoryIO.Prepare(data, sizeInBytes);
00111 
00112     // Open the sound file
00113     SF_INFO fileInfos;
00114     myFile = sf_open_virtual(&io, SFM_READ, &fileInfos, &myMemoryIO);
00115     if (!myFile)
00116     {
00117         Err() << "Failed to read sound file from memory (" << sf_strerror(myFile) << ")" << std::endl;
00118         return false;
00119     }
00120 
00121     // Set the sound parameters
00122     myChannelsCount = fileInfos.channels;
00123     mySampleRate    = fileInfos.samplerate;
00124     myNbSamples     = static_cast<std::size_t>(fileInfos.frames) * myChannelsCount;
00125 
00126     return true;
00127 }
00128 
00129 
00131 bool SoundFile::OpenWrite(const std::string& filename, unsigned int channelsCount, unsigned int sampleRate)
00132 {
00133     // If the file is already opened, first close it
00134     if (myFile)
00135         sf_close(myFile);
00136 
00137     // Find the right format according to the file extension
00138     int format = GetFormatFromFilename(filename);
00139     if (format == -1)
00140     {
00141         // Error : unrecognized extension
00142         Err() << "Failed to create sound file \"" << filename << "\" (unknown format)" << std::endl;
00143         return false;
00144     }
00145 
00146     // Fill the sound infos with parameters
00147     SF_INFO fileInfos;
00148     fileInfos.channels   = channelsCount;
00149     fileInfos.samplerate = sampleRate;
00150     fileInfos.format     = format | (format == SF_FORMAT_OGG ? SF_FORMAT_VORBIS : SF_FORMAT_PCM_16);
00151 
00152     // Open the sound file for writing
00153     myFile = sf_open(filename.c_str(), SFM_WRITE, &fileInfos);
00154     if (!myFile)
00155     {
00156         Err() << "Failed to create sound file \"" << filename << "\" (" << sf_strerror(myFile) << ")" << std::endl;
00157         return false;
00158     }
00159 
00160     // Set the sound parameters
00161     myChannelsCount = channelsCount;
00162     mySampleRate    = sampleRate;
00163     myNbSamples     = 0;
00164 
00165     return true;
00166 }
00167 
00168 
00170 std::size_t SoundFile::Read(Int16* data, std::size_t nbSamples)
00171 {
00172     if (myFile && data && nbSamples)
00173         return static_cast<std::size_t>(sf_read_short(myFile, data, nbSamples));
00174     else
00175         return 0;
00176 }
00177 
00178 
00180 void SoundFile::Write(const Int16* data, std::size_t nbSamples)
00181 {
00182     if (myFile && data && nbSamples)
00183     {
00184         // Write small chunks instead of everything at once,
00185         // to avoid a stack overflow in libsndfile (happens only with OGG format)
00186         while (nbSamples > 0)
00187         {
00188             std::size_t count = nbSamples > 10000 ? 10000 : nbSamples;
00189             sf_write_short(myFile, data, count);
00190             data += count;
00191             nbSamples -= count;
00192         }
00193     }
00194 }
00195 
00196 
00198 void SoundFile::Seek(float timeOffset)
00199 {
00200     if (myFile)
00201     {
00202         sf_count_t frameOffset = static_cast<sf_count_t>(timeOffset * mySampleRate);
00203         sf_seek(myFile, frameOffset, SEEK_SET);
00204     }
00205 }
00206 
00207 
00209 int SoundFile::GetFormatFromFilename(const std::string& filename)
00210 {
00211     // Extract the extension
00212     std::string ext = "wav";
00213     std::string::size_type pos = filename.find_last_of(".");
00214     if (pos != std::string::npos)
00215         ext = filename.substr(pos + 1);
00216 
00217     // Match every supported extension with its format constant
00218     if (ext == "wav"   || ext == "WAV" )  return SF_FORMAT_WAV;
00219     if (ext == "aif"   || ext == "AIF" )  return SF_FORMAT_AIFF;
00220     if (ext == "aiff"  || ext == "AIFF")  return SF_FORMAT_AIFF;
00221     if (ext == "au"    || ext == "AU"  )  return SF_FORMAT_AU;
00222     if (ext == "raw"   || ext == "RAW" )  return SF_FORMAT_RAW;
00223     if (ext == "paf"   || ext == "PAF" )  return SF_FORMAT_PAF;
00224     if (ext == "svx"   || ext == "SVX" )  return SF_FORMAT_SVX;
00225     if (ext == "nist"  || ext == "NIST")  return SF_FORMAT_NIST;
00226     if (ext == "voc"   || ext == "VOC" )  return SF_FORMAT_VOC;
00227     if (ext == "sf"    || ext == "SF"  )  return SF_FORMAT_IRCAM;
00228     if (ext == "w64"   || ext == "W64" )  return SF_FORMAT_W64;
00229     if (ext == "mat4"  || ext == "MAT4")  return SF_FORMAT_MAT4;
00230     if (ext == "mat5"  || ext == "MAT5")  return SF_FORMAT_MAT5;
00231     if (ext == "pvf"   || ext == "PVF" )  return SF_FORMAT_PVF;
00232     if (ext == "xi"    || ext == "XI" )   return SF_FORMAT_XI;
00233     if (ext == "htk"   || ext == "HTK" )  return SF_FORMAT_HTK;
00234     if (ext == "sds"   || ext == "SDS" )  return SF_FORMAT_SDS;
00235     if (ext == "avr"   || ext == "AVR" )  return SF_FORMAT_AVR;
00236     if (ext == "sd2"   || ext == "SD2" )  return SF_FORMAT_SD2;
00237     if (ext == "flac"  || ext == "FLAC")  return SF_FORMAT_FLAC;
00238     if (ext == "caf"   || ext == "CAF" )  return SF_FORMAT_CAF;
00239     if (ext == "wve"   || ext == "WVE" )  return SF_FORMAT_WVE;
00240     if (ext == "ogg"   || ext == "OGG")   return SF_FORMAT_OGG;
00241     if (ext == "mpc2k" || ext == "MPC2K") return SF_FORMAT_MPC2K;
00242     if (ext == "rf64"  || ext == "RF64")  return SF_FORMAT_RF64;
00243 
00244     return -1;
00245 }
00246 
00247 
00249 SF_VIRTUAL_IO SoundFile::MemoryIO::Prepare(const void* data, std::size_t sizeInBytes)
00250 {
00251     // Setup the I/O functions
00252     SF_VIRTUAL_IO io;
00253     io.get_filelen = &SoundFile::MemoryIO::GetLength;
00254     io.read        = &SoundFile::MemoryIO::Read;
00255     io.seek        = &SoundFile::MemoryIO::Seek;
00256     io.tell        = &SoundFile::MemoryIO::Tell;
00257     io.write       = &SoundFile::MemoryIO::Write;
00258 
00259     // Initialize the memory data
00260     myDataStart = static_cast<const char*>(data);
00261     myDataPtr   = myDataStart;
00262     myTotalSize = sizeInBytes;
00263 
00264     return io;
00265 }
00266 
00267 
00269 sf_count_t SoundFile::MemoryIO::GetLength(void* userData)
00270 {
00271     MemoryIO* self = static_cast<MemoryIO*>(userData);
00272 
00273     return self->myTotalSize;
00274 }
00275 
00276 
00278 sf_count_t SoundFile::MemoryIO::Read(void* ptr, sf_count_t count, void* userData)
00279 {
00280     MemoryIO* self = static_cast<MemoryIO*>(userData);
00281 
00282     sf_count_t position = self->myDataPtr - self->myDataStart;
00283     if (position + count >= self->myTotalSize)
00284         count = self->myTotalSize - position;
00285 
00286     memcpy(ptr, self->myDataPtr, static_cast<std::size_t>(count));
00287 
00288     self->myDataPtr += count;
00289 
00290     return count;
00291 }
00292 
00293 
00295 sf_count_t SoundFile::MemoryIO::Seek(sf_count_t offset, int whence, void* userData)
00296 {
00297     MemoryIO* self = static_cast<MemoryIO*>(userData);
00298 
00299     sf_count_t position = 0;
00300     switch (whence)
00301     {
00302         case SEEK_SET : position = offset;                                       break;
00303         case SEEK_CUR : position = self->myDataPtr - self->myDataStart + offset; break;
00304         case SEEK_END : position = self->myTotalSize - offset;                   break;
00305         default       : position = 0;                                            break;
00306     }
00307 
00308     if (position >= self->myTotalSize)
00309         position = self->myTotalSize - 1;
00310     else if (position < 0)
00311         position = 0;
00312 
00313     self->myDataPtr = self->myDataStart + position;
00314 
00315     return position;
00316 }
00317 
00318 
00320 sf_count_t SoundFile::MemoryIO::Tell(void* userData)
00321 {
00322     MemoryIO* self = static_cast<MemoryIO*>(userData);
00323 
00324     return self->myDataPtr - self->myDataStart;
00325 }
00326 
00327 
00329 sf_count_t SoundFile::MemoryIO::Write(const void*, sf_count_t, void*)
00330 {
00331     return 0;
00332 }
00333 
00334 } // namespace priv
00335 
00336 } // namespace sf

 ::  Copyright © 2007-2008 Laurent Gomila, all rights reserved  ::  Documentation generated by doxygen 1.5.2  ::