SoundFileOgg.cpp

00001 
00002 //
00003 // SFML - Simple and Fast Multimedia Library
00004 // Copyright (C) 2007 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/SoundFileOgg.hpp>
00029 #include <iostream>
00030 
00031 
00032 namespace sf
00033 {
00034 namespace priv
00035 {
00039 SoundFileOgg::SoundFileOgg() :
00040 myFile(NULL)
00041 {
00042 
00043 }
00044 
00045 
00049 SoundFileOgg::~SoundFileOgg()
00050 {
00051     if (myFile)
00052     {
00053         ov_clear(&myStream);
00054         myFile = NULL;
00055     }
00056 }
00057 
00058 
00062 bool SoundFileOgg::OpenRead(const std::string& Filename, std::size_t& NbSamples, unsigned int& ChannelsCount, unsigned int& SampleRate)
00063 {
00064     // Close the file if already opened
00065     if (myFile)
00066     {
00067         ov_clear(&myStream);
00068         myFile = NULL;
00069     }
00070 
00071     // Open the file
00072     myFile = fopen(Filename.c_str(), "rb");
00073     if (!myFile)
00074     {
00075         std::cerr << "Failed to read sound file \"" << Filename << "\" (cannot open the file)" << std::endl;
00076         return false;
00077     }
00078 
00079     // Bind the file to the ogg-vorbis stream
00080     int Error = ov_open(myFile, &myStream, NULL, 0);
00081     if (Error < 0)
00082     {
00083         std::cerr << "Failed to read sound file \"" << Filename << "\" (not a valid ogg-vorbis file)" << std::endl;
00084         fclose(myFile);
00085         myFile = NULL;
00086         return false;
00087     }
00088 
00089     // Set the sound parameters
00090     vorbis_info* Infos = ov_info(&myStream, -1);
00091     ChannelsCount = Infos->channels;
00092     SampleRate    = Infos->rate;
00093     NbSamples     = static_cast<std::size_t>(ov_pcm_total(&myStream, -1) * ChannelsCount);
00094 
00095     // Make sure that the ogg stream has a fixed bitrate (VBR is not supported yet...)
00096     /*if ((Infos->bitrate_lower != Infos->bitrate_nominal) || (Infos->bitrate_lower != Infos->bitrate_upper))
00097     {
00098         std::cerr << "Failed to read sound file \"" << Filename << "\" (variable bitrate is not supported)" << std::endl;
00099         return false;
00100     }*/
00101 
00102     return true;
00103 }
00104 
00105 
00109 std::size_t SoundFileOgg::Read(Int16* Data, std::size_t NbSamples)
00110 {
00111     // ov_read will only read one chunk, even if it is smaller than the requested size,
00112     // so we loop until all bytes have been read
00113     long TotalSize = static_cast<long>(NbSamples * sizeof(Int16));
00114     long TotalRead = 0;
00115     while (TotalRead < TotalSize)
00116     {
00117         // Decode sound data
00118         char* Ptr = reinterpret_cast<char*>(Data) + TotalRead;
00119         int   Len = TotalSize - TotalRead;
00120         long Read = ov_read(&myStream, Ptr, Len, 0, 2, 1, NULL);
00121 
00122         if (Read > 0)
00123         {
00124             // Ok, Read bytes have been read
00125             TotalRead += Read;
00126         }
00127         else if (Read == 0)
00128         {
00129             // End of file reached
00130             break;
00131         }
00132         else
00133         {
00134             // Error...
00135             std::cerr << "Failed to read from ogg file" << std::endl;
00136             break;
00137         }
00138     }
00139 
00140     return static_cast<std::size_t>(TotalRead / sizeof(Int16));
00141 }
00142 
00143 } // namespace priv
00144 
00145 } // namespace sf