bool ogg_update_stream(OggVorbis_File *oggStream, ogg_int64_t rate, ALenum format, ALuint buffer, bool loop) { char pcm[VORBIS_BUFFER_SIZE]; int size = 0; int section; int result; while (size < VORBIS_BUFFER_SIZE) { result = ov_read(oggStream, pcm + size, VORBIS_BUFFER_SIZE - size, 0, 2, 1, §ion); if (result > 0) size += result; else if (result < 0) return false; else // end of file { if (loop) ov_raw_seek(oggStream, 0); else break; } } if (size == 0) { ov_raw_seek(oggStream, 0); return false; } alBufferData(buffer, format, pcm, size, static_cast<ALsizei>(rate)); return true; }
void Sound_Stream_AL::stream(ALuint buffer) { char data[BUFFER_SIZE]; int size = 0; int section; int result; while(size < int(BUFFER_SIZE)) { result = ov_read(&oggStream, data + size, BUFFER_SIZE - size, 0, 2, 1, & section); if(result > 0) size += result; else { if(result < 0) throw Sound_Stream_Ogg_Read_Failure(); else if(looping) ov_raw_seek(&oggStream, 0); else break; } } if(size == 0) throw Error("Failed to stream data from .ogg file."); //else if(size < BUFFER_SIZE) // memset(data + size, 0, BUFFER_SIZE - size); Sound_Renderer_AL::alBufferData()(buffer, format, data, size, vorbisInfo->rate); const ALenum error = Sound_Renderer_AL::alGetError()(); if(error != AL_NO_ERROR) { std::cerr << "OpenAL error: " << Sound_Renderer_AL::errorString(error) << std::endl; throw Sound_Stream_Update_Failure(); } }
bool Audio::Stream :: stream(unsigned int buffer) { auto l = Audio::lock(); char data[BUFFER_SIZE]; int size = 0; int endian = 0; int section; int result; while(size < BUFFER_SIZE) { result = ov_read(&m_Ogg, data + size, BUFFER_SIZE - size, endian, 2, 1, §ion); if((flags & Source::F_LOOP) && !result) ov_raw_seek(&m_Ogg, 0); if(result > 0) size += result; else { if(result < 0) return false; else break; } } if(size == 0) return false; alBufferData(buffer, m_Format, data, size, m_VorbisInfo->rate); return true; }
std::vector<int16_t> AudioFile::getSampleData() const { if(mSampleAmount == 0) return std::vector<int16_t>(); std::vector<int16_t> sampleData(mSampleAmount); ov_raw_seek(mFile, 0); int64_t read = 0; int64_t totalRead = 0; int bitstream = 0; while((read = ov_read(mFile, ((char*)sampleData.data()) + totalRead, (mSampleAmount * 2) - (int32_t)totalRead, 0, 2, 1, &bitstream))) { if(read < 0) { break; } totalRead += read; } sampleData.resize((size_t)totalRead / 2); return sampleData; }
int ovSndPlayer::stream() { if(!this) return 0; int pos = 0; long bytes = 0; do { int current; bytes = ov_read((OggVorbis_File*)_ov_file, &*_buffer.begin() + pos, (int)_buffer.size() - pos, 0, 2, 1, ¤t); if(bytes > 0) pos += bytes; else if(bytes == 0) { if(_loop) ov_raw_seek((OggVorbis_File*)_ov_file, 0); else break; } else break; //}while(bytes>0); }while(true); return pos; }
void alogg_seek_abs_bytes_ogg(ALOGG_OGG *ogg, int bytes) { /* check the pos in bytes is valid */ if ((bytes < 0) || (bytes >= ogg->data_len)) return; ov_raw_seek(&(ogg->vf), bytes); }
// Cue // // Set the file pointer to the start of wave data // BOOL WaveFile::Cue(void) { BOOL fRtn = SUCCESS; // assume success int rval; m_total_uncompressed_bytes_read = 0; m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX; if (m_wave_format == OGG_FORMAT_VORBIS) { rval = (int)ov_raw_seek(&m_snd_info.vorbis_file, m_data_offset); } else { rval = mmioSeek(m_snd_info.cfp, m_data_offset, SEEK_SET); } if (rval == -1) { fRtn = FAILURE; } m_data_bytes_left = m_nDataSize; m_abort_next_read = FALSE; return fRtn; }
void Sound_Stream_AL::play() { if(oggStream.offset == oggStream.end) ov_raw_seek(&oggStream, 0); update(); Sound_Renderer_AL::alSourcePlay()(source); }
static int OGG_rewind(Sound_Sample *sample) { Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; OggVorbis_File *vf = (OggVorbis_File *) internal->decoder_private; BAIL_IF_MACRO(ov_raw_seek(vf, 0) < 0, ERR_IO_ERROR, 0); return(1); } /* OGG_rewind */
int vorbis_source_update(audio_source *src, char *buffer, int len) { vorbis_source *local = source_get_userdata(src); int got = vorbis_stream(src, buffer, len); if(got == 0 && src->loop) { ov_raw_seek(&local->src_file, 0); return vorbis_stream(src, buffer, len); } return got; }
int OGG_resume(){ if (OGG_suspendPosition >= 0){ OGG_Load(OGG_fileName); if (ov_raw_seek(&OGG_VorbisFile, OGG_suspendPosition)){ if (OGG_suspendIsPlaying) OGG_Play(); } OGG_suspendPosition = -1; } return 0; }
bool cOggDecoder::setPosition(int position, bool relative) { if(Valid) { if(ov_seekable(&oggStream)) { return (ov_raw_seek(&oggStream,position)==0); } } return false; }
void OggWrapper::ResetStream() { if (seekable_) { int error = ov_raw_seek(ovFile_, 0); if (error != 0) { std::cout << "ov_raw_seek error : " << error << std::endl; } } }
void alogg_seek_rel_bytes_ogg(ALOGG_OGG *ogg, int bytes) { int current_byte = ov_raw_tell(&(ogg->vf)); int wanted_byte = current_byte + bytes; /* check the byte is valid */ if ((wanted_byte < 0) || (wanted_byte >= ogg->data_len)) return; /* get current byte and add to it */ bytes += ov_raw_tell(&(ogg->vf)); ov_raw_seek(&(ogg->vf), bytes); }
SoundBuffer::SoundBuffer(const FilePath& path) { OggVorbis_File file; CHECK(ov_fopen(path.getPath(), &file) == 0) << "Error opening audio file: " << path; vorbis_info* info = ov_info(&file, -1); ov_raw_seek(&file, 0); vector<char> buffer = readSoundData(file); OpenalId id; AL(alGenBuffers(1, &id)); AL(alBufferData(id, (info->channels > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16, buffer.data(), buffer.size(), info->rate)); bufferId = id; ov_clear(&file); }
bool libname::COggStreamSample::Rewind() { if ( ov_seekable(&m_OggFile) ) { ov_raw_seek( &m_OggFile, 0 ); m_bHasEnded = false; return true; } else { cerr << "file is not seekable" << endl; return false; } }
bool C4MusicFileOgg::FillBuffer(size_t idx) { // uncompress from ogg data int endian = 0; long bytes_read_total = 0, bytes_read; char uncompressed_data[buffer_size]; do { bytes_read = ov_read(&ogg_file, uncompressed_data+bytes_read_total, (buffer_size-bytes_read_total)*sizeof(BYTE), endian, 2, 1, ¤t_section); bytes_read_total += bytes_read; } while (bytes_read > 0 && bytes_read_total < buffer_size); // buffer data if (bytes_read_total) { byte_pos_total += bytes_read_total; ALuint buffer = buffers[idx]; alErrorCheck(alBufferData(buffer, ogg_info.format, uncompressed_data, bytes_read_total, ogg_info.sample_rate)); // queue buffer alErrorCheck(alSourceQueueBuffers(channel, 1, &buffer)); } // streaming done? if (bytes_read_total < buffer_size) { // streaming done. loop or done. if (loop) { // reset pos in ogg file ov_raw_seek(&ogg_file, 0); // if looping and nothing has been committed to this buffer yet, try again // except if byte_pos_total==0, i.e. if the piece is completely empty size_t prev_bytes_total = byte_pos_total; byte_pos_total = 0; if (!bytes_read_total && prev_bytes_total) return FillBuffer(idx); return true; } else { // non-looping: we're done. return false; } } else { // might have more data to stream return true; } }
void OggWrapper::Seek(size_t pos, SeekPos start) { if (seekable_ == false) { return; } if (start == START) { ResetStream(); } int error = ov_raw_seek(ovFile_, pos); if (error != 0) { std::cout << "ov_raw_seek error : " << error << std::endl; } }
static int _open_seekable2(OggVorbis_File *vf){ long serialno=vf->current_serialno,end; long dataoffset=vf->offset; ogg_page og; /* we're partially open and have a first link header state in storage in vf */ /* we can seek, so set out learning all about this file */ (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END); vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource); /* We get the offset for the last page of the physical bitstream. Most OggVorbis files will contain a single logical bitstream */ end=_get_prev_page(vf,&og); if(end<0){ ov_clear(vf); return(end); } /* more than one logical bitstream? */ if(ogg_page_serialno(&og)!=serialno){ /* Chained bitstream. Bisect-search each logical bitstream section. Do so based on serial number only */ if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0){ ov_clear(vf); return(OV_EREAD); } }else{ /* Only one logical bitstream */ if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0)){ ov_clear(vf); return(OV_EREAD); } } /* the initial header memory is referenced by vf after; don't free it */ _prefetch_all_headers(vf,dataoffset); return(ov_raw_seek(vf,0)); }
static bool _stream(music_context_t* context, sound_buffer_t buffer) { OggVorbis_File* poggStream = &context->oggStream; vorbis_info* vorbisInfo = context->vorbisInfo; ALenum format = context->format; char data[OGG_READ_BLOCK_SIZE]; int size = 0; int section; int result; while (size < OGG_READ_BLOCK_SIZE) { result = ov_read(poggStream, data + size, OGG_READ_BLOCK_SIZE - size, 0, 2, 1, §ion); if (result > 0) size += result; else if (result < 0) return false; else if (ov_raw_seek(poggStream, 0) < 0) return false; } alBufferData(buffer, format, data, size, vorbisInfo->rate); return true; }
void ovSndPlayer::play() { if(!this) return; if(isPaused()) SndPlayer::play(); else { SndPlayer::stop(); for(int i = 0; i < (int)_array_buffer.size(); ++i) { int buffer; alGetError(); alSourceUnqueueBuffers(_source_name, 1, (unsigned int*)&buffer); alGetError(); } ov_raw_seek((OggVorbis_File*)_ov_file, 0); update(); SndPlayer::play(); } }
void sound_seekSample (SoundSample * sample) { ov_raw_seek (&sample->s_file.oggFile, 0); }
int main(){ OggVorbis_File ov; int i,ret; ogg_int64_t pcmlength; char *bigassbuffer; int dummy; #ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */ _setmode( _fileno( stdin ), _O_BINARY ); _setmode( _fileno( stdout ), _O_BINARY ); #endif /* open the file/pipe on stdin */ if(ov_open(stdin,&ov,NULL,-1)<0){ printf("Could not open input as an OggVorbis file.\n\n"); exit(1); } if(ov_seekable(&ov)){ /* to simplify our own lives, we want to assume the whole file is stereo. Verify this to avoid potentially mystifying users (pissing them off is OK, just don't confuse them) */ for(i=0;i<ov.links;i++){ vorbis_info *vi=ov_info(&ov,i); if(vi->channels!=2){ printf("Sorry; right now seeking_test can only use Vorbis files\n" "that are entirely stereo.\n\n"); exit(1); } } /* because we want to do sample-level verification that the seek does what it claimed, decode the entire file into memory */ fflush(stdout); pcmlength=ov_pcm_total(&ov,-1); bigassbuffer=malloc(pcmlength*2); /* w00t */ i=0; while(i<pcmlength*2){ int ret=ov_read(&ov,bigassbuffer+i,pcmlength*2-i,1,1,1,&dummy); if(ret<0)continue; if(ret){ i+=ret; }else{ pcmlength=i/2; } fprintf(stderr,"\rloading.... [%ld left] ", (long)(pcmlength*2-i)); } /* Exercise all the real seeking cases; ov_raw_seek, ov_pcm_seek_page and ov_pcm_seek. time seek is just a wrapper on pcm_seek */ { ogg_int64_t length=ov.end; printf("\rtesting raw seeking to random places in %ld bytes....\n", (long)length); for(i=0;i<1000;i++){ ogg_int64_t val=(double)rand()/RAND_MAX*length; ogg_int64_t pos; printf("\r\t%d [raw position %ld]... ",i,(long)val); fflush(stdout); ret=ov_raw_seek(&ov,val); if(ret<0){ printf("seek failed: %d\n",ret); exit(1); } _verify(&ov,pos,val,-1,pcmlength,bigassbuffer); } } printf("\r"); { printf("testing pcm page seeking to random places in %ld samples....\n", (long)pcmlength); for(i=0;i<1000;i++){ ogg_int64_t val=(double)rand()/RAND_MAX*pcmlength; ogg_int64_t pos; printf("\r\t%d [pcm position %ld]... ",i,(long)val); fflush(stdout); ret=ov_pcm_seek_page(&ov,val); if(ret<0){ printf("seek failed: %d\n",ret); exit(1); } _verify(&ov,pos,-1,val,pcmlength,bigassbuffer); } } printf("\r"); { ogg_int64_t length=ov.end; printf("testing pcm exact seeking to random places in %ld samples....\n", (long)pcmlength); for(i=0;i<1000;i++){ ogg_int64_t val=(double)rand()/RAND_MAX*pcmlength; ogg_int64_t pos; printf("\r\t%d [pcm position %ld]... ",i,(long)val); fflush(stdout); ret=ov_pcm_seek(&ov,val); if(ret<0){ printf("seek failed: %d\n",ret); exit(1); } if(ov_pcm_tell(&ov)!=val){ printf("Declared position didn't perfectly match request: %ld != %ld\n", (long)val,(long)ov_pcm_tell(&ov)); exit(1); } _verify(&ov,pos,-1,val,pcmlength,bigassbuffer); } } printf("\r \nOK.\n\n"); }else{ printf("Standard input was not seekable.\n"); } ov_clear(&ov); return 0; }
void eAudioDecoderOgg::resync() { //eDebug ("[OGG]resync"); if (fileinfo.sourcefd >= 0) ov_raw_seek(&vf,::lseek64(sourcefd,0,SEEK_CUR)); }
/* ============ S_StreamBackgroundTrack ============ */ void S_StreamBackgroundTrack (void) { int samples, maxSamples; int read, maxRead, total, dummy; float scale; byte data[MAX_RAW_SAMPLES*4]; if (!s_bgTrack.file || !s_musicvolume->value) return; if (!s_streamingChannel) return; if (s_rawend < paintedtime) s_rawend = paintedtime; scale = (float)s_bgTrack.rate / dma.speed; maxSamples = sizeof(data) / s_bgTrack.channels / s_bgTrack.width; while (1) { samples = (paintedtime + MAX_RAW_SAMPLES - s_rawend) * scale; if (samples <= 0) return; if (samples > maxSamples) samples = maxSamples; maxRead = samples * s_bgTrack.channels * s_bgTrack.width; total = 0; while (total < maxRead) { read = ov_read(s_bgTrack.vorbisFile, data + total, maxRead - total, 0, 2, 1, &dummy); if (!read) { // End of file if (!s_bgTrack.looping) { // Close the intro track S_CloseBackgroundTrack(&s_bgTrack); // Open the loop track if (!S_OpenBackgroundTrack(s_bgTrack.loopName, &s_bgTrack)) { S_StopBackgroundTrack(); return; } s_bgTrack.looping = true; } else { // check if it's time to switch to the ambient track if ( ++ogg_loopcounter >= (int)ogg_loopcount->value && (!cl.configstrings[CS_MAXCLIENTS][0] || !strcmp(cl.configstrings[CS_MAXCLIENTS], "1")) ) { // Close the loop track S_CloseBackgroundTrack(&s_bgTrack); if (!S_OpenBackgroundTrack(s_bgTrack.ambientName, &s_bgTrack)) { if (!S_OpenBackgroundTrack(s_bgTrack.loopName, &s_bgTrack)) { S_StopBackgroundTrack(); return; } } else s_bgTrack.ambient_looping = true; } } // Restart the track, skipping over the header ov_raw_seek(s_bgTrack.vorbisFile, (ogg_int64_t)s_bgTrack.start); } /*if (s_bgTrack.read) read = s_bgTrack->read( s_bgTrack, data + total, maxRead - total ); else read = FS_Read( data + total, maxRead - total, s_bgTrack->file ); if (!read) { if (s_bgTrackIntro.file != s_bgTrackLoop.file) { if (s_bgTrackIntro.close) s_bgTrackIntro.close(&s_bgTrackIntro); else FS_FCloseFile(s_bgTrackIntro.file); s_bgTrackIntro = s_bgTrackLoop; } s_bgTrack = &s_bgTrackLoop; if (s_bgTrack->seek) s_bgTrack->seek( s_bgTrack, s_bgTrack->info.dataofs ); else FS_Seek(s_bgTrack->file, s_bgTrack->info.dataofs, FS_SEEK_SET); }*/ total += read; } S_RawSamples (samples, s_bgTrack.rate, s_bgTrack.width, s_bgTrack.channels, data, true ); } }
/* ================= S_StreamBackgroundTrack ================= */ void S_StreamBackgroundTrack (void) { byte data[BUFFER_SIZE]; int queued = 0; //, processed, state; int size, read, dummy; //unsigned buffer; int samples; // Knightmare added if (!s_bgTrack.file || !s_musicvolume->value) return; if (!s_streamingChannel) return; // Unqueue and delete any processed buffers /*qalGetSourcei(s_streamingChannel->sourceNum, AL_BUFFERS_PROCESSED, &processed); if (processed > 0){ while (processed--){ qalSourceUnqueueBuffers(s_streamingChannel->sourceNum, 1, &buffer); qalDeleteBuffers(1, &buffer); } }*/ //Com_Printf("Streaming background track\n"); // Make sure we always have at least 4 buffers in the queue //qalGetSourcei(s_streamingChannel->sourceNum, AL_BUFFERS_QUEUED, &queued); while (queued < 4) { size = 0; // Stream from disk while (size < BUFFER_SIZE) { read = ov_read(s_bgTrack.vorbisFile, data + size, BUFFER_SIZE - size, 0, 2, 1, &dummy); if (read == 0) { // End of file if (!s_bgTrack.looping) { // Close the intro track S_CloseBackgroundTrack(&s_bgTrack); // Open the loop track if (!S_OpenBackgroundTrack(s_bgTrack.loopName, &s_bgTrack)) { S_StopBackgroundTrack(); return; } s_bgTrack.looping = true; } // Restart the track, skipping over the header ov_raw_seek(s_bgTrack.vorbisFile, (ogg_int64_t)s_bgTrack.start); // Try streaming again read = ov_read(s_bgTrack.vorbisFile, data + size, BUFFER_SIZE - size, 0, 2, 1, &dummy); } if (read <= 0) { // An error occurred S_StopBackgroundTrack(); return; } size += read; } // Knightmare added samples = size / (s_bgTrack.width * s_bgTrack.channels); S_RawSamples(samples, s_bgTrack.rate,s_bgTrack. width, s_bgTrack.channels, data, true); // Upload and queue the new buffer /*qalGenBuffers(1, &buffer); qalBufferData(buffer, s_bgTrack.format, data, size, s_bgTrack.rate); qalSourceQueueBuffers(s_streamingChannel->sourceNum, 1, &buffer);*/ queued++; } // Update volume //qalSourcef(s_streamingChannel->sourceNum, AL_GAIN, s_musicVolume->value); // If not playing, then do so /*qalGetSourcei(s_streamingChannel->sourceNum, AL_SOURCE_STATE, &state); if (state != AL_PLAYING) qalSourcePlay(s_streamingChannel->sourceNum);*/ }
void SoundOVProvider::Rewind() { ov_raw_seek(&oggFile, 0); }
void alogg_rewind_ogg(ALOGG_OGG *ogg) { ov_raw_seek(&(ogg->vf), 0); }
/* ============ S_StreamBackgroundTrack ============ */ void S_StreamBackgroundTrack (void) { int samples, maxSamples; int read, maxRead, total, dummy; float scale; char data[MAX_RAW_SAMPLES*4]; if (!ogg_started) return; if (!s_bgTrack.buffer || !s_musicvolume->value) return; if (!s_streamingChannel) return; if (s_rawend < paintedtime) s_rawend = paintedtime; scale = (float)s_bgTrack.rate / dma.speed; maxSamples = sizeof(data) / s_bgTrack.channels / s_bgTrack.width; while (1) { samples = (paintedtime + MAX_RAW_SAMPLES - s_rawend) * scale; if (samples <= 0) return; if (samples > maxSamples) samples = maxSamples; maxRead = samples * s_bgTrack.channels * s_bgTrack.width; total = 0; while (total < maxRead) { read = ov_read((OggVorbis_File*)s_bgTrack.vorbisFile, data + total, maxRead - total, 0, 2, 1, &dummy); if (!read) { // end of file if (!s_bgTrack.looping) { // close the intro track S_CloseBackgroundTrack(&s_bgTrack); // open the loop track if (!S_OpenBackgroundTrack(s_bgTrack.loopName, &s_bgTrack)) { S_StopBackgroundTrack(); return; } s_bgTrack.looping = true; } else { // check if its time to switch to the ambient track if ( ++ogg_loopcounter >= (int)ogg_loopcount->value && (!cl.configstrings[CS_MAXCLIENTS][0] || !strcmp(cl.configstrings[CS_MAXCLIENTS], "1")) ) { // close the loop track S_CloseBackgroundTrack(&s_bgTrack); if (!S_OpenBackgroundTrack(s_bgTrack.ambientName, &s_bgTrack)) { if (!S_OpenBackgroundTrack(s_bgTrack.loopName, &s_bgTrack)) { S_StopBackgroundTrack(); return; } } else s_bgTrack.ambient_looping = true; } } // restart the track, skipping over the header ov_raw_seek((OggVorbis_File*)s_bgTrack.vorbisFile, (ogg_int64_t)s_bgTrack.start); } total += read; } S_RawSamples (samples, s_bgTrack.rate, s_bgTrack.width, s_bgTrack.channels, data, true); } }
void SndSysOggSoundStream::AdvancePosition(size_t frame_delta) { size_t needed_bytes=0; //if loop is enabled, end loop frame is different than zero and we are at the loop ending return to the //start of the loop if(m_bLooping && m_endLoopFrame != 0 && m_MostAdvancedReadPointer+frame_delta >= m_endLoopFrame) { //first advance the decoding of the exact bound we need to reach the endloopframe AdvancePosition(m_endLoopFrame-m_MostAdvancedReadPointer-1); //remove from frame_delta what we decoded already frame_delta -= m_endLoopFrame-m_MostAdvancedReadPointer-1; // Flush the prepared samples m_PreparedDataBufferUsage=0; m_PreparedDataBufferStart=0; // Seek the ogg stream to the start loop position position for the rest of the advancement ov_pcm_seek(&m_VorbisFile,m_startLoopFrame); } if (m_NewPosition != InvalidPosition) { // Signal a full cyclic buffer flush needed_bytes=m_pCyclicBuffer->GetLength(); // Flush the prepared samples too m_PreparedDataBufferUsage=0; m_PreparedDataBufferStart=0; // Seek the ogg stream to the requested position ov_pcm_seek(&m_VorbisFile,m_NewPosition); m_NewPosition = InvalidPosition; m_bPlaybackReadComplete=false; } if (m_bPaused || m_bPlaybackReadComplete || frame_delta==0) return; long bytes_read=0; // Figure out how many bytes we need to fill for this advancement if (needed_bytes==0) needed_bytes=frame_delta * (m_RenderFormat.Bits/8) * m_RenderFormat.Channels ; /* If we need more space than is available in the whole cyclic buffer, * then we already underbuffered, reduce to just 1 cycle full */ if ((size_t)needed_bytes > m_pCyclicBuffer->GetLength()) needed_bytes=(long)(m_pCyclicBuffer->GetLength() & 0x7FFFFFFF); // Free space in the cyclic buffer if necessary if (needed_bytes > m_pCyclicBuffer->GetFreeBytes()) m_pCyclicBuffer->AdvanceStartValue (needed_bytes - m_pCyclicBuffer->GetFreeBytes()); // Fill in leftover decoded data if needed if (m_PreparedDataBufferUsage > 0) needed_bytes -= CopyBufferBytes (needed_bytes); while (needed_bytes > 0) { int last_ogg_stream=m_CurrentOggStream; char ogg_decode_buffer[OGG_DECODE_BUFFER_SIZE]; bytes_read=0; while (bytes_read==0) { bytes_read = ov_read (&m_VorbisFile, ogg_decode_buffer, OGG_DECODE_BUFFER_SIZE, OGG_ENDIAN, (m_RenderFormat.Bits==8)?1:2, (m_RenderFormat.Bits==8)?0:1, &m_CurrentOggStream); // Assert on error CS_ASSERT(bytes_read >=0); if (bytes_read <= 0) { if (!m_bLooping) { // Seek back to the beginning for a restart. Pause on the next call m_bPlaybackReadComplete=true; ov_raw_seek(&m_VorbisFile,0); return; } // Loop by resetting the position to the start loop position and continuing ov_pcm_seek(&m_VorbisFile,m_startLoopFrame); } } // If streams changed, the format may have changed as well if ((m_NewOutputFrequency != m_OutputFrequency) || (last_ogg_stream != m_CurrentOggStream)) { int needed_buffer,source_sample_size; m_OutputFrequency=m_NewOutputFrequency; m_pCurrentOggFormatInfo=ov_info(&m_VorbisFile,m_CurrentOggStream); // Create the pcm sample converter if it's not yet created if (m_pPCMConverter == 0) m_pPCMConverter = new PCMSampleConverter ( m_pCurrentOggFormatInfo->channels, m_RenderFormat.Bits, m_pCurrentOggFormatInfo->rate); // Calculate the size of one source sample source_sample_size=m_pCurrentOggFormatInfo->channels * m_RenderFormat.Bits; // Calculate the needed buffer size for this conversion needed_buffer = (m_pPCMConverter->GetRequiredOutputBufferMultiple ( m_RenderFormat.Channels,m_RenderFormat.Bits,m_OutputFrequency) * (OGG_DECODE_BUFFER_SIZE + source_sample_size))/1024; // Allocate a new buffer if needed - this will only happen if the source rate changes if (m_PreparedDataBufferSize < needed_buffer) { delete[] m_pPreparedDataBuffer; m_pPreparedDataBuffer = new char[needed_buffer]; m_PreparedDataBufferSize=needed_buffer; } } // If no conversion is necessary if ((m_pCurrentOggFormatInfo->rate == m_OutputFrequency) && (m_pCurrentOggFormatInfo->channels == m_RenderFormat.Channels)) { CS_ASSERT(bytes_read <= m_PreparedDataBufferSize); memcpy(m_pPreparedDataBuffer,ogg_decode_buffer,bytes_read); m_PreparedDataBufferUsage=bytes_read; } else { m_PreparedDataBufferUsage = m_pPCMConverter->ConvertBuffer (ogg_decode_buffer, bytes_read, m_pPreparedDataBuffer, m_RenderFormat.Channels, m_RenderFormat.Bits,m_OutputFrequency); } if (m_PreparedDataBufferUsage > 0) needed_bytes -= CopyBufferBytes (needed_bytes); } }