src/audio/ogg_sound_file.cpp

Go to the documentation of this file.
00001 //  SuperTux
00002 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
00003 //
00004 //  This program is free software: you can redistribute it and/or modify
00005 //  it under the terms of the GNU General Public License as published by
00006 //  the Free Software Foundation, either version 3 of the License, or
00007 //  (at your option) any later version.
00008 //
00009 //  This program is distributed in the hope that it will be useful,
00010 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 //  GNU General Public License for more details.
00013 //
00014 //  You should have received a copy of the GNU General Public License
00015 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 
00017 #include "audio/ogg_sound_file.hpp"
00018 
00019 #include <assert.h>
00020 
00021 OggSoundFile::OggSoundFile(PHYSFS_file* file, double loop_begin, double loop_at) :
00022   file(),
00023   vorbis_file(),
00024   loop_begin(),
00025   loop_at(),
00026   normal_buffer_loop() 
00027 {
00028   this->file = file;
00029 
00030   ov_callbacks callbacks = { cb_read, cb_seek, cb_close, cb_tell };
00031   ov_open_callbacks(file, &vorbis_file, 0, 0, callbacks);
00032 
00033   vorbis_info* vi = ov_info(&vorbis_file, -1);
00034 
00035   channels        = vi->channels;
00036   rate            = vi->rate;
00037   bits_per_sample = 16;
00038   size            = static_cast<size_t> (ov_pcm_total(&vorbis_file, -1) * 2);
00039 
00040   double samples_begin = loop_begin * rate;
00041   double sample_loop   = loop_at * rate;
00042 
00043   this->loop_begin     = (ogg_int64_t) samples_begin;
00044   if(loop_begin < 0) {
00045     this->loop_at = (ogg_int64_t) -1;
00046   } else {
00047     this->loop_at = (ogg_int64_t) sample_loop;
00048   }
00049 }
00050 
00051 OggSoundFile::~OggSoundFile()
00052 {
00053   ov_clear(&vorbis_file);
00054 }
00055 
00056 size_t
00057 OggSoundFile::read(void* _buffer, size_t buffer_size)
00058 {
00059   char*  buffer         = reinterpret_cast<char*> (_buffer);
00060   int    section        = 0;
00061   size_t totalBytesRead = 0;
00062 
00063   while(buffer_size>0) {
00064 #ifdef WORDS_BIGENDIAN
00065     int bigendian = 1;
00066 #else
00067     int bigendian = 0;
00068 #endif
00069 
00070     size_t bytes_to_read    = buffer_size;
00071     if(loop_at > 0) {
00072       size_t      bytes_per_sample       = 2;
00073       ogg_int64_t time                   = ov_pcm_tell(&vorbis_file);
00074       ogg_int64_t samples_left_till_loop = loop_at - time;
00075       ogg_int64_t bytes_left_till_loop
00076         = samples_left_till_loop * bytes_per_sample;
00077       if(bytes_left_till_loop <= 4)
00078         break;
00079 
00080       if(bytes_left_till_loop < (ogg_int64_t) bytes_to_read) {
00081         bytes_to_read    = (size_t) bytes_left_till_loop;
00082       }
00083     }
00084 
00085     long bytesRead
00086       = ov_read(&vorbis_file, buffer, bytes_to_read, bigendian,
00087                 2, 1, &section);
00088     if(bytesRead == 0) {
00089       break;
00090     }
00091     buffer_size    -= bytesRead;
00092     buffer         += bytesRead;
00093     totalBytesRead += bytesRead;
00094   }
00095 
00096   return totalBytesRead;
00097 }
00098 
00099 void
00100 OggSoundFile::reset()
00101 {
00102   ov_pcm_seek(&vorbis_file, loop_begin);
00103 }
00104 
00105 size_t
00106 OggSoundFile::cb_read(void* ptr, size_t size, size_t nmemb, void* source)
00107 {
00108   PHYSFS_file* file = reinterpret_cast<PHYSFS_file*> (source);
00109 
00110   PHYSFS_sint64 res
00111     = PHYSFS_read(file, ptr, static_cast<PHYSFS_uint32> (size),
00112                   static_cast<PHYSFS_uint32> (nmemb));
00113   if(res <= 0)
00114     return 0;
00115 
00116   return static_cast<size_t> (res);
00117 }
00118 
00119 int
00120 OggSoundFile::cb_seek(void* source, ogg_int64_t offset, int whence)
00121 {
00122   PHYSFS_file* file = reinterpret_cast<PHYSFS_file*> (source);
00123 
00124   switch(whence) {
00125     case SEEK_SET:
00126       if(PHYSFS_seek(file, static_cast<PHYSFS_uint64> (offset)) == 0)
00127         return -1;
00128       break;
00129     case SEEK_CUR:
00130       if(PHYSFS_seek(file, PHYSFS_tell(file) + offset) == 0)
00131         return -1;
00132       break;
00133     case SEEK_END:
00134       if(PHYSFS_seek(file, PHYSFS_fileLength(file) + offset) == 0)
00135         return -1;
00136       break;
00137     default:
00138       assert(false);
00139       return -1;
00140   }
00141   return 0;
00142 }
00143 
00144 int
00145 OggSoundFile::cb_close(void* source)
00146 {
00147   PHYSFS_file* file = reinterpret_cast<PHYSFS_file*> (source);
00148   PHYSFS_close(file);
00149   return 0;
00150 }
00151 
00152 long
00153 OggSoundFile::cb_tell(void* source)
00154 {
00155   PHYSFS_file* file = reinterpret_cast<PHYSFS_file*> (source);
00156   return static_cast<long> (PHYSFS_tell(file));
00157 }
00158 
00159 /* EOF */

Generated on Mon Jun 9 03:38:16 2014 for SuperTux by  doxygen 1.5.1