// Copyright (c) 2008-2010 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones // This file is part of the "cAudio Engine" // For conditions of distribution and use, see copyright notice in cAudio.h #include "../Headers/cOggDecoder.h" #ifdef CAUDIO_COMPILE_WITH_OGG_DECODER namespace cAudio { //! Read Vorbis Data size_t VorbisRead(void *ptr, size_t byteSize,size_t sizeToRead, void *datasource) { IDataSource* Stream = (IDataSource*)datasource; return Stream->read(ptr,byteSize*sizeToRead); } //! Seek Vorbis Data int VorbisSeek(void *datasource,ogg_int64_t offset,int whence) { IDataSource* Stream = (IDataSource*)datasource; switch (whence) { case SEEK_SET: Stream->seek(offset, false); break; case SEEK_CUR: Stream->seek(offset, true); break; case SEEK_END: Stream->seek(Stream->getSize()-offset, false); break; }; return 0; } //! Returns the vorbis data that was stored. long VorbisTell(void *datasource) { return ((IDataSource*)datasource)->getCurrentPos(); } int VorbisCloseFunc(void *datasource) { return 0; } cOggDecoder::cOggDecoder(IDataSource* stream) : IAudioDecoder(stream) { vorbisCallbacks.read_func = VorbisRead; vorbisCallbacks.close_func = VorbisCloseFunc; vorbisCallbacks.seek_func = VorbisSeek; vorbisCallbacks.tell_func = VorbisTell; Valid = (ov_open_callbacks(Stream,&oggStream,NULL,0,vorbisCallbacks) == 0); if(Valid) { vorbisInfo = ov_info(&oggStream, -1); vorbisComment = ov_comment(&oggStream,-1); } } cOggDecoder::~cOggDecoder() { ov_clear(&oggStream); } AudioFormats cOggDecoder::getFormat() { if(Valid) { if(vorbisInfo->channels == 1) { return EAF_16BIT_MONO; } else { return EAF_16BIT_STEREO; } } return EAF_8BIT_MONO; } int cOggDecoder::getFrequency() { if(Valid) { return vorbisInfo->rate; } return 0; } bool cOggDecoder::isSeekingSupported() { if(Valid) { return (ov_seekable(&oggStream)!=0); } return false; } bool cOggDecoder::isValid() { return Valid; } int cOggDecoder::readAudioData(void* output, int amount) { if(Valid) { int temp = 0; int result = ov_read(&oggStream,(char*)output,amount,0,2,1,&temp); //return (result < 0) ? 0 : result; return result; } return 0; } bool cOggDecoder::setPosition(int position, bool relative) { if(Valid) { if(ov_seekable(&oggStream)) { return (ov_raw_seek(&oggStream,position)==0); } } return false; } bool cOggDecoder::seek(float seconds, bool relative) { if(Valid) { if(ov_seekable(&oggStream)) { if(relative) { float curtime = ov_time_tell(&oggStream); return (ov_time_seek(&oggStream,curtime+seconds)==0); } else return (ov_time_seek(&oggStream,seconds)==0); } } return false; } float cOggDecoder::getTotalTime() { return ov_time_total(&oggStream, -1); } int cOggDecoder::getTotalSize() { return ov_pcm_total(&oggStream, -1) * vorbisInfo->channels; } int cOggDecoder::getCompressedSize() { return ov_raw_total(&oggStream, -1); } float cOggDecoder::getCurrentTime() { return ov_time_tell(&oggStream); } int cOggDecoder::getCurrentPosition() { return ov_pcm_tell(&oggStream) * vorbisInfo->channels; } int cOggDecoder::getCurrentCompressedPosition() { return ov_raw_tell(&oggStream); } }; #endif