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 ::