Path: blob/master/psx/mednadisc/cdrom/CDAFReader_Vorbis.cpp
2 views
/* Mednafen - Multi-system Emulator1*2* This program is free software; you can redistribute it and/or modify3* it under the terms of the GNU General Public License as published by4* the Free Software Foundation; either version 2 of the License, or5* (at your option) any later version.6*7* This program is distributed in the hope that it will be useful,8* but WITHOUT ANY WARRANTY; without even the implied warranty of9* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the10* GNU General Public License for more details.11*12* You should have received a copy of the GNU General Public License13* along with this program; if not, write to the Free Software14* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA15*/1617#include <mednafen/mednafen.h>18#include "CDAFReader.h"19#include "CDAFReader_Vorbis.h"2021#if 022#include <tremor/ivorbisfile.h>23#else24#include <mednafen/tremor/ivorbisfile.h>25#endif2627class CDAFReader_Vorbis final : public CDAFReader28{29public:30CDAFReader_Vorbis(Stream *fp);31~CDAFReader_Vorbis();3233uint64 Read_(int16 *buffer, uint64 frames) override;34bool Seek_(uint64 frame_offset) override;35uint64 FrameCount(void) override;3637private:38OggVorbis_File ovfile;39Stream *fw;40};414243static size_t iov_read_func(void *ptr, size_t size, size_t nmemb, void *user_data)44{45Stream *fw = (Stream*)user_data;4647if(!size)48return(0);4950try51{52return fw->read(ptr, size * nmemb, false) / size;53}54catch(...)55{56return(0);57}58}5960static int iov_seek_func(void *user_data, ogg_int64_t offset, int whence)61{62Stream *fw = (Stream*)user_data;6364try65{66fw->seek(offset, whence);67return(0);68}69catch(...)70{71return(-1);72}73}7475static int iov_close_func(void *user_data)76{77Stream *fw = (Stream*)user_data;7879try80{81fw->close();82return(0);83}84catch(...)85{86return EOF;87}88}8990static long iov_tell_func(void *user_data)91{92Stream *fw = (Stream*)user_data;9394try95{96return fw->tell();97}98catch(...)99{100return(-1);101}102}103104CDAFReader_Vorbis::CDAFReader_Vorbis(Stream *fp) : fw(fp)105{106ov_callbacks cb;107108memset(&cb, 0, sizeof(cb));109cb.read_func = iov_read_func;110cb.seek_func = iov_seek_func;111cb.close_func = iov_close_func;112cb.tell_func = iov_tell_func;113114if(ov_open_callbacks(fp, &ovfile, NULL, 0, cb))115throw(0);116}117118CDAFReader_Vorbis::~CDAFReader_Vorbis()119{120ov_clear(&ovfile);121}122123uint64 CDAFReader_Vorbis::Read_(int16 *buffer, uint64 frames)124{125uint8 *tw_buf = (uint8 *)buffer;126int cursection = 0;127long toread = frames * sizeof(int16) * 2;128129while(toread > 0)130{131long didread = ov_read(&ovfile, (char*)tw_buf, toread, &cursection);132133if(didread == 0)134break;135136tw_buf = (uint8 *)tw_buf + didread;137toread -= didread;138}139140return(frames - toread / sizeof(int16) / 2);141}142143bool CDAFReader_Vorbis::Seek_(uint64 frame_offset)144{145ov_pcm_seek(&ovfile, frame_offset);146return(true);147}148149uint64 CDAFReader_Vorbis::FrameCount(void)150{151return(ov_pcm_total(&ovfile, -1));152}153154CDAFReader* CDAFR_Vorbis_Open(Stream* fp)155{156return new CDAFReader_Vorbis(fp);157}158159160