int OggStream::decodeNextBlock(bool looped, void* data, int bufferSize) { unsigned int bytesUnpacked = 0; int p = (int)ov_pcm_tell(&_vorbisFile); while (1) { int r = (int)ov_read(&_vorbisFile, (char*)data, bufferSize, &_section); if (!r) { if (looped) { ov_pcm_seek(&_vorbisFile, 0); } else { _streamEnded = true; break; } } data = (char*)data + r; bufferSize -= r; bytesUnpacked += r; if (bufferSize == 0) break; } p = int(ov_pcm_tell(&_vorbisFile)) - p; return bytesUnpacked; }
void _verify(OggVorbis_File *ov, ogg_int64_t val,ogg_int64_t pcmval,double timeval, ogg_int64_t pcmlength, char *bigassbuffer){ off_t i; int j; long bread; char buffer[4096]; int dummy; ogg_int64_t pos; int hs = ov_halfrate_p(ov); /* verify the raw position, the pcm position and position decode */ if(val!=-1 && ov_raw_tell(ov)<val){ fprintf(stderr,"raw position out of tolerance: requested %ld, got %ld\n", (long)val,(long)ov_raw_tell(ov)); exit(1); } if(pcmval!=-1 && ov_pcm_tell(ov)>pcmval){ fprintf(stderr,"pcm position out of tolerance: requested %ld, got %ld\n", (long)pcmval,(long)ov_pcm_tell(ov)); exit(1); } if(timeval!=-1 && ov_time_tell(ov)>timeval){ fprintf(stderr,"time position out of tolerance: requested %f, got %f\n", timeval,ov_time_tell(ov)); exit(1); } pos=ov_pcm_tell(ov); if(pos<0 || pos>pcmlength){ fprintf(stderr,"pcm position out of bounds: got %ld\n",(long)pos); exit(1); } bread=ov_read(ov,buffer,4096,1,1,1,&dummy); for(j=0;j<bread;j++){ if(buffer[j]!=bigassbuffer[j+((pos>>hs)*2)]){ fprintf(stderr,"data after seek doesn't match declared pcm position %ld\n",(long)pos); for(i=0;i<(pcmlength>>hs)*2-bread;i++){ for(j=0;j<bread;j++) if(buffer[j] != bigassbuffer[i+j])break; if(j==bread){ fprintf(stderr,"data after seek appears to match position %ld\n",(long)((i/2)<<hs)); } } { FILE *f=fopen("a.m","w"); for(j=0;j<bread;j++)fprintf(f,"%d %d\n",j,(int)buffer[j]); fclose(f); f=fopen("b.m","w"); for(j=-4096;j<bread+4096;j++) if(j+((pos*2)>>hs)>=0 && (j+((pos*2)>>hs))<(pcmlength>>hs)*2) fprintf(f,"%d %d\n",j,(int)bigassbuffer[j+((pos*2)>>hs)]); fclose(f); } exit(1); } } }
void _verify(OggVorbis_File *ov,ogg_int64_t pos, ogg_int64_t val,ogg_int64_t pcmval, ogg_int64_t pcmlength, char *bigassbuffer){ int j; long bread; char buffer[4096]; int dummy; /* verify the raw position, the pcm position and position decode */ if(val!=-1 && ov_raw_tell(ov)<val){ printf("raw position out of tolerance: requested %ld, got %ld\n", (long)val,(long)ov_raw_tell(ov)); exit(1); } if(pcmval!=-1 && ov_pcm_tell(ov)>pcmval){ printf("pcm position out of tolerance: requested %ld, got %ld\n", (long)pcmval,(long)ov_pcm_tell(ov)); exit(1); } pos=ov_pcm_tell(ov); if(pos<0 || pos>pcmlength){ printf("pcm position out of bounds: got %ld\n",(long)pos); exit(1); } bread=ov_read(ov,buffer,4096,1,1,1,&dummy); for(j=0;j<bread;j++){ if(buffer[j]!=bigassbuffer[j+pos*2]){ printf("data position after seek doesn't match pcm position\n"); exit(1); } } }
void _verify(OggVorbis_File *ov, ogg_int64_t val, ogg_int64_t pcmval, ogg_int64_t timeval, ogg_int64_t pcmlength, char *bigassbuffer){ int j; long bread; char buffer[4096]; int dummy; ogg_int64_t pos; /* verify the raw position, the pcm position and position decode */ if(val!=-1 && ov_raw_tell(ov)<val){ fprintf(stderr,"raw position out of tolerance: requested %ld, got %ld\n", (long)val,(long)ov_raw_tell(ov)); exit(1); } if(pcmval!=-1 && ov_pcm_tell(ov)>pcmval){ fprintf(stderr,"pcm position out of tolerance: requested %ld, got %ld\n", (long)pcmval,(long)ov_pcm_tell(ov)); exit(1); } if(timeval!=-1 && ov_time_tell(ov)>timeval){ fprintf(stderr,"time position out of tolerance: requested %ld, got %ld\n", (long)timeval,(long)ov_time_tell(ov)); exit(1); } pos=ov_pcm_tell(ov); if(pos<0 || pos>pcmlength){ fprintf(stderr,"pcm position out of bounds: got %ld\n",(long)pos); exit(1); } bread=ov_read(ov,buffer,4096,&dummy); if(bigassbuffer){ for(j=0;j<bread;j++){ if(buffer[j]!=bigassbuffer[j+pos*4]){ fprintf(stderr,"data position after seek doesn't match pcm position\n"); { FILE *f=fopen("a.m","w"); for(j=0;j<bread;j++)fprintf(f,"%d\n",(int)buffer[j]); fclose(f); f=fopen("b.m","w"); for(j=0;j<bread;j++)fprintf(f,"%d\n",(int)bigassbuffer[j+pos*2]); fclose(f); } exit(1); } } } }
static int cvorbis_seek_sample (DB_fileinfo_t *_info, int sample) { ogg_info_t *info = (ogg_info_t *)_info; if (sample < 0) { trace ("vorbis: negative seek sample - ignored, but it is a bug!\n"); return -1; } if (!info->info.file) { trace ("vorbis: file is NULL on seek\n"); return -1; } if (sample == 0) { deadbeef->pl_lock (); const char *filetype = deadbeef->pl_find_meta_raw(info->it, ":FILETYPE"); if (filetype && strncmp(filetype, "Ogg Vorbis", 10)) { sample = 1; // workaround libvorbis bug #1486 (ddb issue #1116) } deadbeef->pl_unlock (); } sample += info->it->startsample; trace ("vorbis: seek to sample %d\n", sample); int res = ov_pcm_seek (&info->vorbis_file, sample); if (res != 0 && res != OV_ENOSEEK) { trace ("vorbis: error %x seeking to sample %d\n", res, sample); return -1; } int tell = ov_pcm_tell (&info->vorbis_file); if (tell != sample) { trace ("vorbis: failed to do sample-accurate seek (%d->%d)\n", sample, tell); } trace ("vorbis: seek successful\n") _info->readpos = (float)(sample - info->it->startsample)/_info->fmt.samplerate; info->next_update = -2; return 0; }
static GslLong dh_vorbis_coarse_seek (GslDataHandle *dhandle, GslLong voffset) { VorbisHandle *vhandle = (VorbisHandle*) dhandle; GslLong opos = vhandle->pcm_pos, pos = voffset / dhandle->setup.n_channels; if (voffset < 0) return vhandle->pcm_pos * dhandle->setup.n_channels; if (pos < vhandle->pcm_pos || pos >= vhandle->pcm_pos + vhandle->pcm_length + SEEK_BY_READ_AHEAD (vhandle)) { gint err = ov_pcm_seek_page (&vhandle->ofile, vhandle->soffset + pos); if (err) /* eek */ err = ov_pcm_seek_page (&vhandle->ofile, vhandle->soffset); else vhandle->pcm_pos = ov_pcm_tell (&vhandle->ofile) - vhandle->soffset; if (err || vhandle->pcm_pos < 0) /* urg, we're completely screwed */ vhandle->pcm_pos = 0; vhandle->pcm_length = 0; } if (0) g_printerr ("OggS-SEEK: at %llu want %llu got %llu (diff-requested %lld)\n", opos, pos, vhandle->pcm_pos, pos - opos); return vhandle->pcm_pos * dhandle->setup.n_channels; }
long SoundSourceOggVorbis::seek(long filepos) { // In our speak, filepos is a sample in the file abstraction (i.e. it's // stereo no matter what). filepos/2 is the frame we want to seek to. if (filepos % 2 != 0) { qDebug() << "SoundSourceOggVorbis got non-even seek target."; filepos--; } if (ov_seekable(&vf)) { if (ov_pcm_seek(&vf, filepos/2) != 0) { // This is totally common (i.e. you're at EOF). Let's not leave this // qDebug on. // qDebug() << "ogg vorbis: Seek ERR on seekable."; } // Even if an error occured, return them the current position because // that's what we promised. (Double it because ov_pcm_tell returns // frames and we pretend to the world that everything is stereo) return ov_pcm_tell(&vf) * 2; } else { qDebug() << "ogg vorbis: Seek ERR at file " << getFilename(); return 0; } }
int SoundManager::LoadOGG(WAVEFORMATEX* fformat, unsigned char** sample_data, size_t* size_data, char* ogg_path) { FILE *fs; if(!(fs=fopen(ogg_path,"rb"))) return 0; OggVorbis_File vf; if(ov_open(fs,&vf,NULL,0)) return 0; vorbis_info* vi=ov_info(&vf,-1); int data_len=(int)ov_pcm_total(&vf,-1); int start_pos=(int)ov_pcm_tell(&vf); int BPS=vi->channels==1?2:4; *size_data=(data_len-start_pos)*BPS; *sample_data=new unsigned char[*size_data]; size_t decoded=0; while (decoded < *size_data) { int curr; decoded += ov_read(&vf,(char*)(*sample_data)+decoded,(*size_data)-decoded,0,2,1,&curr); } fformat->wFormatTag=WAVE_FORMAT_PCM; fformat->nChannels=vi->channels; fformat->nSamplesPerSec=vi->rate; fformat->wBitsPerSample=16; fformat->nBlockAlign=vi->channels*fformat->wBitsPerSample/8; fformat->nAvgBytesPerSec=fformat->nBlockAlign*vi->rate; fformat->cbSize=0; return 1; }
int RageSoundReader_Vorbisfile::GetNextSourceFrame() const { ASSERT(vf != NULL); int iFrame = (int)ov_pcm_tell( vf ); return iFrame; }
LONGLONG ovd_get_current(HANDLE hov) { LIBOV_STRUCT* lov = (LIBOV_STRUCT*)hov; if (!lov) return FALSE; return ov_pcm_tell(&lov->vf); }
RageSoundReader_FileReader::OpenResult RageSoundReader_Vorbisfile::Open( RageFileBasic *pFile ) { m_pFile = pFile; vf = new OggVorbis_File; memset( vf, 0, sizeof(*vf) ); ov_callbacks callbacks; callbacks.read_func = OggRageFile_read_func; callbacks.seek_func = OggRageFile_seek_func; callbacks.close_func = OggRageFile_close_func; callbacks.tell_func = OggRageFile_tell_func; int ret = ov_open_callbacks( pFile, vf, NULL, 0, callbacks ); if( ret < 0 ) { SetError( ov_ssprintf(ret, "ov_open failed") ); delete vf; vf = NULL; switch( ret ) { case OV_ENOTVORBIS: return OPEN_UNKNOWN_FILE_FORMAT; default: return OPEN_FATAL_ERROR; } } eof = false; read_offset = (int) ov_pcm_tell(vf); vorbis_info *vi = ov_info( vf, -1 ); channels = vi->channels; return OPEN_OK; }
int dxpSoundOggDecode(DXPAVCONTEXT *av) { #ifdef DXP_BUILDOPTION_USE_LIBOGG int len = dxpSoundCalcBufferSize(av, dxpSoundGetNextSampleNum(av)); // int readbytes = 0; int ret, bitstream; vorbis_info *vi; u8 *pcmOut = av->pcmOut; if(av->format != DXP_SOUNDFMT_OGG)return -1; if(len <= 0)return -1; // EOF while(len > 0) { ret = ov_read(av->ogg.file,(char*)pcmOut,len,&bitstream); if(ret == OV_HOLE)continue; if(ret == OV_EBADLINK)return -1; vi = ov_info(av->ogg.file, -1); if(!vi || vi->channels != av->channels)return -1; // error pcmOut += ret; // readbytes += ret; len -= ret; if(ret == 0) len = 0; // EOF } // av->nextPos += readbytes / dxpSoundCalcBufferSize(av, 1); av->nextPos = (int)ov_pcm_tell(av->ogg.file); return 0; #else return -1; #endif }
float AudioManager::Player::GetPosition() { boost::recursive_mutex::scoped_lock lock( *m_UpdateMutex ); int play_offset; alGetSourcei( m_Source, AL_SAMPLE_OFFSET, &play_offset ); return ( ov_pcm_tell( &m_VorbisFile ) - ( m_ChannelBufferNumber * m_ChannelBufferSize / m_VorbisInfo->channels / sizeof( int16_t ) - play_offset ) ) * 1000 / m_VorbisInfo->rate; }
float GetVorbisTime(MFAudioStream *pStream) { MFVorbisStream *pVS = (MFVorbisStream*)pStream->pStreamData; #if defined(VORBIS_TREMOR) return (float)ov_pcm_tell(&pVS->vorbisFile) / (float)pVS->pInfo->rate; #else return (float)ov_time_tell(&pVS->vorbisFile); #endif }
gc_int32 gauX_sample_source_ogg_tell(void* in_context, gc_int32* out_totalSamples) { gau_SampleSourceOggContext* ctx = &((gau_SampleSourceOgg*)in_context)->context; gc_int32 ret; gc_mutex_lock(ctx->oggMutex); /* TODO: Decide whether to support total samples for OGG files */ if(out_totalSamples) *out_totalSamples = ov_pcm_total(&ctx->oggFile, -1); /* Note: This isn't always valid when the stream is poorly-formatted */ ret = (gc_int32)ov_pcm_tell(&ctx->oggFile); gc_mutex_unlock(ctx->oggMutex); return ret; }
bool COggVorbisFileHelper::set_current_timepos( double pos ) { if(vf.datasource && vf.seekable) { if(nStatus == OH_PLAYING) { s3eSoundChannelPause(nSoundChannel); s3eDeviceYield(1); #if defined(HAVE_PTHREAD) if(mDecThread.thread_status == CThread::TRUNNING) pthread_mutex_lock(&mutex1); #endif ov_time_seek_func(&vf,pos); current_time = pos; current_sample = (ogg_int64_t) (ov_pcm_tell(&vf) * dResampleFactor*get_nChannels()); #if defined(HAVE_PTHREAD) if(mDecThread.thread_status == CThread::TRUNNING) pthread_mutex_unlock(&mutex1); #endif nStatus = OH_BUFFERING; mDecBuffer->Clear(); Wait_counter(0); s3eSoundChannelResume(nSoundChannel); } else { #if defined(HAVE_PTHREAD) if(mDecThread.thread_status == CThread::TRUNNING) pthread_mutex_lock(&mutex1); #endif ov_time_seek_func(&vf,pos); current_time = pos; current_sample = (ogg_int64_t) (ov_pcm_tell(&vf) * dResampleFactor*get_nChannels()); #if defined(HAVE_PTHREAD) if(mDecThread.thread_status == CThread::TRUNNING) pthread_mutex_unlock(&mutex1); #endif mDecBuffer->Clear(); } return true; } return false; }
int dxpSoundOggSeek(DXPAVCONTEXT *av,int sample) { #ifdef DXP_BUILDOPTION_USE_LIBOGG int ret; if(av->format != DXP_SOUNDFMT_OGG)return -1; ret = ov_pcm_seek(av->ogg.file,(ogg_int64_t)sample); if(ret < 0)return -1; av->nextPos = (int)ov_pcm_tell(av->ogg.file); return 0; #else return -1; #endif }
//----------------------------------------------------------------------------- size_t MusicStream::_getCurrentPos() { // <todo> This method is not working with OGG files smaller than // BUFFER_SIZE (fix it) if (mMusic != 0) { int alPos,buffers; size_t streamPos = static_cast<size_t>(ov_pcm_tell(&mFile)); size_t loopPoint = Database::getSingleton().musics[mMusic-1]. loopPoint; size_t sizeInSamples = BUFFER_SIZE/2; size_t offset = 666666666; if ((int)streamPos == OV_EINVAL) { SONETTO_THROW("Failed telling current stream offset in music file ("+ Ogre::StringConverter::toString(streamPos)+")"); } if (sizeInSamples > mStreamLen) { sizeInSamples = mStreamLen; } alGetSourcei(mMusicSrc,AL_SAMPLE_OFFSET,&alPos); mAudioMan->_alErrorCheck("MusicStream::_getCurrentPos()", "Failed getting music source sample offset"); alGetSourcei(mMusicSrc,AL_BUFFERS_PROCESSED,&buffers); mAudioMan->_alErrorCheck("MusicStream::_getCurrentPos()", "Failed getting number of processed buffers in music source"); alPos -= buffers*sizeInSamples; if (streamPos < loopPoint || streamPos-loopPoint > sizeInSamples) { offset = streamPos-(sizeInSamples-alPos); } else { size_t warped = streamPos-loopPoint; size_t unwarped = sizeInSamples-warped; if ((size_t)alPos >= unwarped) { offset = streamPos-(sizeInSamples-alPos); } else { offset = mStreamLen-(sizeInSamples-alPos); } } return offset; } return 0; }
/*! * \brief Tell the current position in OGG/Vorbis filestream measured in pcms. * \param fs The filestream to take action on. * \return 0 or greater with the position measured in samples, or -1 for false. */ static off_t ogg_vorbis_tell(struct ast_filestream *fs) { off_t pos; struct ogg_vorbis_desc *desc = (struct ogg_vorbis_desc *) fs->_private; if (desc->writing) { return desc->writing_pcm_pos; } if ((pos = ov_pcm_tell(&desc->ov_f)) < 0) { return -1; } return pos; }
SoundReader_FileReader::OpenResult RageSoundReader_Vorbisfile::Open(CString filename_) { filename=filename_; vf = new OggVorbis_File; memset( vf, 0, sizeof(*vf) ); RageFile *f = new RageFile; if( !f->Open( filename ) ) { SetError( ssprintf("ogg: opening \"%s\" failed: %s", filename.c_str(), f->GetError().c_str()) ); delete f; delete vf; vf = NULL; return OPEN_FATAL_ERROR; } ov_callbacks callbacks; callbacks.read_func = OggRageFile_read_func; callbacks.seek_func = OggRageFile_seek_func; callbacks.close_func = OggRageFile_close_func; callbacks.tell_func = OggRageFile_tell_func; int ret = ov_open_callbacks( f, vf, NULL, 0, callbacks ); if(ret < 0) { SetError( ov_ssprintf(ret, "ov_open failed") ); delete f; delete vf; vf = NULL; switch( ret ) { case OV_ENOTVORBIS: return OPEN_UNKNOWN_FILE_FORMAT; default: return OPEN_FATAL_ERROR; } } eof = false; read_offset = (int) ov_pcm_tell(vf); vorbis_info *vi = ov_info( vf, -1 ); ASSERT_M( vi->channels == 1 || vi->channels == 2, ssprintf("%i", vi->channels) ); channels = vi->channels; return OPEN_OK; }
static inline unsigned int getCurrentSample(struct OggVorbisDecoderState* decoder) { #ifndef WZ_NOSOUND int samplePos; ASSERT(decoder != NULL, "NULL decoder passed!"); samplePos = ov_pcm_tell(&decoder->oggVorbis_stream); if (samplePos == OV_EINVAL) return 0; return samplePos; #else return 0; #endif }
static void read_packet (VorbisHandle *vhandle) { gfloat **pcm = NULL; gint stream_id, i; vhandle->pcm_pos = ov_pcm_tell (&vhandle->ofile) - vhandle->soffset; vhandle->pcm_length = ov_read_float (&vhandle->ofile, &pcm, G_MAXINT, &stream_id); if (vhandle->pcm_pos < 0 || vhandle->pcm_length < 0 || stream_id != vhandle->bitstream) { /* urg, this is bad! */ dh_vorbis_coarse_seek (&vhandle->dhandle, 0); } else for (i = 0; i < vhandle->dhandle.setup.n_channels; i++) vhandle->pcm[i] = pcm[i]; }
//This function will stream new Ogg data to a specified buffer at a specified position bool DIZ_OGGSTREAM::streamToBuffer(ALuint buf, int *location) { //Declare a stream-data buffer char data[DEFAULT_BUFFER_SIZE]; //Declare our tracking variables for our streaming progress int size = 0, result; //And declare a bitstream variable int bitstream; //First, seek to our desired starting position in the stream ov_pcm_seek(&oggFile, *location); //Loop until we've filled up our desired buffer size while (size < DEFAULT_BUFFER_SIZE) { //Read as much new data as we can into the buffer result = ov_read(&oggFile, data + size, DEFAULT_BUFFER_SIZE - size, 0, 2, 1, &bitstream); //Now set our stream-location to our current spot *location = (int)ov_pcm_tell(&oggFile); //If our result was positive, it's our amount of data read if (result > 0) { size += result; //If our result was negative, it's an error }else if (result < 0) { return false; //If our result was 0, we've hit the end of the file }else { break; } } //If size is 0, then we're obviously trying to read from the end of the file, so return false if (size == 0) { return false; } //Then load our new data into our buffer alBufferData(buf, format, data, size, vorbisInfo->rate); //Then double-check for an OpenAL error if (alGetError() != AL_NO_ERROR) { return false; } //And exit return true; }
void CSoundRender_Source::decompress (u32 line, OggVorbis_File* ovf) { VERIFY (ovf); // decompression of one cache-line u32 line_size = SoundRender->cache.get_linesize(); char* dest = (char*) SoundRender->cache.get_dataptr (CAT,line); u32 buf_offs = (psSoundFreq==sf_22K)?(line*line_size):(line*line_size)/2; u32 left_file = dwBytesTotal - buf_offs; u32 left = (u32)_min (left_file,line_size); // seek u32 cur_pos = u32 (ov_pcm_tell(ovf)); if (cur_pos!=buf_offs){ ov_pcm_seek (ovf,buf_offs); } // decompress if (psSoundFreq==sf_22K)i_decompress_hr(ovf,dest,left); else i_decompress_fr(ovf,dest,left); }
size_t OggSoundFile::read(void* _buffer, size_t buffer_size) { char* buffer = reinterpret_cast<char*> (_buffer); int section = 0; size_t totalBytesRead = 0; while(buffer_size>0) { #ifdef WORDS_BIGENDIAN int bigendian = 1; #else int bigendian = 0; #endif size_t bytes_to_read = buffer_size; if(loop_at > 0) { size_t bytes_per_sample = 2; ogg_int64_t time = ov_pcm_tell(&vorbis_file); ogg_int64_t samples_left_till_loop = loop_at - time; ogg_int64_t bytes_left_till_loop = samples_left_till_loop * bytes_per_sample; if(bytes_left_till_loop <= 4) break; if(bytes_left_till_loop < (ogg_int64_t) bytes_to_read) { bytes_to_read = (size_t) bytes_left_till_loop; } } long bytesRead = ov_read(&vorbis_file, buffer, bytes_to_read, bigendian, 2, 1, §ion); if(bytesRead == 0) { break; } buffer_size -= bytesRead; buffer += bytesRead; totalBytesRead += bytesRead; } return totalBytesRead; }
SINT SoundSourceOggVorbis::seekSampleFrame( SINT frameIndex) { DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex)); DEBUG_ASSERT(isValidFrameIndex(frameIndex)); const int seekResult = ov_pcm_seek(&m_vf, frameIndex); if (0 == seekResult) { m_curFrameIndex = frameIndex; } else { qWarning() << "Failed to seek OggVorbis file:" << seekResult; const ogg_int64_t pcmOffset = ov_pcm_tell(&m_vf); if (0 <= pcmOffset) { m_curFrameIndex = pcmOffset; } else { // Reset to EOF m_curFrameIndex = getMaxFrameIndex(); } } DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex)); return m_curFrameIndex; }
int RageSoundReader_Vorbisfile::SetPosition( int iFrame ) { eof = false; const ogg_int64_t sample = ogg_int64_t(iFrame); int ret = ov_pcm_seek( vf, sample ); if(ret < 0) { /* Returns OV_EINVAL on EOF. */ if( ret == OV_EINVAL ) { eof = true; return 0; } SetError( ov_ssprintf(ret, "ogg: SetPosition failed") ); return -1; } read_offset = (int) ov_pcm_tell(vf); return 1; }
int dxpSoundOggInit(DXPAVCONTEXT *av) { #ifdef DXP_BUILDOPTION_USE_LIBOGG ov_callbacks callbacks; vorbis_info *vi; int ret; av->ogg.file = (OggVorbis_File*)malloc(sizeof(OggVorbis_File)); if(!av->ogg.file)return -1; memset(av->ogg.file,0,sizeof(OggVorbis_File)); callbacks.read_func = ogg_read_func; callbacks.seek_func = ogg_seek_func; callbacks.close_func = ogg_close_func; callbacks.tell_func = ogg_tell_func; FileRead_seek(av->fileHandle, 0, SEEK_SET); ret = ov_open_callbacks(&av->fileHandle,av->ogg.file,NULL,0,callbacks); if(ret < 0) { free(av->ogg.file); return -1; } vi = ov_info(av->ogg.file, -1); if(!vi || (vi->channels != 1 && vi->channels != 2)) { ov_clear(av->ogg.file); free(av->ogg.file); return -1; } av->sampleSize = 2; av->channels = (u8)vi->channels; av->sampleRate = (int)vi->rate; av->nextPos = (int)ov_pcm_tell(av->ogg.file); av->outSampleNum = 1024; av->format = DXP_SOUNDFMT_OGG; return 0; #else return -1; #endif }
int RageSoundReader_Vorbisfile::Read( float *buf, int iFrames ) { int frames_read = 0; while( iFrames && !eof ) { const int bytes_per_frame = sizeof(float)*channels; int iFramesRead = 0; { int curofs = (int) ov_pcm_tell(vf); if( curofs < read_offset ) { /* The timestamps moved backwards. Ignore it. This file probably * won't sync correctly. */ LOG->Trace( "p ahead %p %i < %i, we're ahead by %i", this, curofs, read_offset, read_offset-curofs ); read_offset = curofs; } else if( curofs > read_offset ) { /* Our offset doesn't match. We have a hole in the data, or corruption. * If we're reading with accurate syncing, insert silence to line it up. * That way, corruptions in the file won't casue desyncs. */ /* In bytes: */ int iSilentFrames = curofs - read_offset; iSilentFrames = min( iSilentFrames, (int) iFrames ); int silence = iSilentFrames * bytes_per_frame; CHECKPOINT_M( ssprintf("p %i,%i: %i frames of silence needed", curofs, read_offset, silence) ); memset( buf, 0, silence ); iFramesRead = iSilentFrames; } } if( iFramesRead == 0 ) { int bstream; #if defined(INTEGER_VORBIS) int ret = ov_read( vf, (char *) buf, iFrames * channels * sizeof(int16_t), &bstream ); #else // float vorbis decoder float **pcm; int ret = ov_read_float( vf, &pcm, iFrames, &bstream ); #endif { vorbis_info *vi = ov_info( vf, -1 ); ASSERT( vi != NULL ); if( (unsigned) vi->channels != channels ) RageException::Throw( "File \"%s\" changes channel count from %i to %i; not supported.", filename.c_str(), channels, (int)vi->channels ); } if( ret == OV_HOLE ) continue; if( ret == OV_EBADLINK ) { SetError( ssprintf("Read: OV_EBADLINK") ); return ERROR; } if( ret == 0 ) { eof = true; continue; } #if defined(INTEGER_VORBIS) if( ret > 0 ) { int iSamplesRead = ret / sizeof(int16_t); iFramesRead = iSamplesRead / channels; /* Convert in reverse, so we can do it in-place. */ const int16_t *pIn = (int16_t *) buf; float *pOut = (float *) buf; for( int i = iSamplesRead-1; i >= 0; --i ) pOut[i] = pIn[i] / 32768.0f; } #else if( ret > 0 ) { iFramesRead = ret; int iNumChannels = channels; for( int iChannel = 0; iChannel < iNumChannels; ++iChannel ) { const float *pChannelIn = pcm[iChannel]; float *pChannelOut = &buf[iChannel]; for( int i = 0; i < iFramesRead; ++i ) { *pChannelOut = *pChannelIn; ++pChannelIn; pChannelOut += iNumChannels; } } } #endif } read_offset += iFramesRead; buf += iFramesRead * channels; frames_read += iFramesRead; iFrames -= iFramesRead; } if( !frames_read ) return END_OF_FILE; return frames_read; }