// Write sample data into the supplied PCM sample buffers void CWinGlkOGGSound::WriteSampleData(unsigned char* pSample, int iSampleLen) { int iStream, iCurrent = 0; while (iCurrent < iSampleLen) { long lRead = ov_read(&m_Stream,(char*)(pSample+iCurrent),(iSampleLen-iCurrent),0,2,1,&iStream); if (lRead > 0) iCurrent += lRead; else { if (m_iRepeat > 0) { ov_pcm_seek(&m_Stream,0); m_iRepeat--; } else if (m_iRepeat == -1) ov_pcm_seek(&m_Stream,0); else { while (iCurrent < iSampleLen) pSample[iCurrent++] = 0; } } } }
unsigned long OggDecoder::Render( unsigned long size, void *buf ) { OggDecoderData *data = OGGDATA(this); if (!data){ outOfData = true; return 0; } int ret = 1; unsigned long pos=0; if (seekOffset != -1) { long seek = (long)(((float)seekOffset/1000.0f) * (float)samplerate); ov_pcm_seek(&data->vf, seek); seekOffset = -1; outOfData = false; } while(ret && pos<size) { ret = ov_read(&data->vf, (char*)buf+pos, size-pos, 0, 2, 1, &data->sec); pos += ret; } // reached the end? if (!ret && (loopsRemaining!=0)) { // we are looping so restart from the beginning ret = 1; ov_pcm_seek(&data->vf, 0); // Loop back position, TODO: If we want to loop to a specific point, here is the code for that! while(ret && pos<size) { ret = ov_read(&data->vf, (char*)buf+pos, size-pos, 0, 2, 1, &data->sec); pos += ret; } // Decrease from Loops Remaining (don't touch the -1 infinite loop stuff) if (loopsRemaining > 0) loopsRemaining--; } else if (!ret && (loopsRemaining==0)){ outOfData = true; } return pos; }
void SoundD3D::RewindOggStream() { if (!ov_file || !buffer) return; // rewind the stream and keep going... eos_written = false; eos_latch = 0; read_size = wfex.nAvgBytesPerSec / 2; // set the stream pointer back to the beginning: ov_pcm_seek(ov_file, 0); // find the size of the file: stream_left = (DWORD) ov_pcm_total(ov_file,-1); stream_offset = 0; total_time = (double) stream_left / (double) wfex.nAvgBytesPerSec; if (stream_left < read_size) { status = DONE; buffer->Stop(); } }
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; }
bool SPOggFile::NextStreamData( BYTE* pData, DWORD length, DWORD &readBytes, bool &eof ) { if (!isLoaded) { return false; } DWORD pos = 0; int sec = 0; int ret = 1; while(ret && pos < length) { ret = ov_read(&vf, (char*)pData + pos, length - pos, 0, 2, 1, &sec); pos += ret; } readBytes = pos; if (!ret) { eof = true; ov_pcm_seek(&vf, 0); } else { eof = false; } return true; }
bool RealSoundOgg::ServiceBuffer() { if( m_bMute ) return true; if (m_pDSB == NULL) return false; DWORD pos = 0; m_pDSB->GetCurrentPosition(&pos, NULL); m_nCurSection = ((int)pos < m_nBufSize) ? 0:1; if (m_nCurSection != m_nLastSection) { if (m_bDone && !m_bLoop) { if (m_bOpened) { if (m_bPlaying) { ov_pcm_seek(&m_vf, 0); m_pDSB->Stop(); m_bPlaying = false; } } return false; } if (m_bAlmostDone && !m_bLoop) m_bDone = true; WriteStream(m_nBufSize); } return true; }
void OGG_Source::rewind() { if (this->streamOpen) { ov_pcm_seek(&this->oggStream, 0); } }
/* ================== Sound::Rewind ================== */ bool Sound::Rewind() { alSourceStop(source); if (pbMethod == PLAYBACK_STREAM) { if (ov_pcm_seek(oggStream, 0) < 0) { return false; } } else { bytePos = 0; } alSourceUnqueueBuffers(source, 2, buffers); if (!FillBuffer(buffers[0])) { return false; } if (!FillBuffer(buffers[1])) { return false; } alSourceQueueBuffers(source, 2, buffers); alSourceRewind(source); return true; }
bool OGG_Source::open() { Source::open(); if (!this->streamOpen) { return false; } // setting the special callbacks ov_callbacks callbacks; callbacks.read_func = &_dataRead; callbacks.seek_func = &_dataSeek; callbacks.close_func = &_dataClose; // may not be NULL because it may crash on Android otherwise callbacks.tell_func = &_dataTell; if (ov_open_callbacks((void*)this->stream, &this->oggStream, NULL, 0, callbacks) == 0) { vorbis_info* info = ov_info(&this->oggStream, -1); this->channels = (int)info->channels; this->samplingRate = (int)info->rate; this->bitsPerSample = 16; // always 16 bit data int logicalSamples = (int)ov_pcm_total(&this->oggStream, -1); this->size = logicalSamples * this->channels * this->bitsPerSample / 8; this->duration = (float)logicalSamples / this->samplingRate; ov_pcm_seek(&this->oggStream, 0); // make sure the PCM stream is at the beginning to avoid nasty surprises } else { hlog::error(logTag, "OGG: error reading data!"); this->close(); } return this->streamOpen; }
bool C4MusicFileOgg::Play(bool loop) { // Valid file? if (!loaded) return false; // stop previous Stop(); // Get channel to use alGenSources(1, (ALuint*)&channel); if (!channel) return false; playing = true; streaming_done = false; this->loop = loop; byte_pos_total = 0; // initial volume setting SetVolume(float(::Config.Sound.MusicVolume) / 100.0f); // prepare read ogg_info.sound_data.resize(num_buffers * buffer_size); alGenBuffers(num_buffers, buffers); ov_pcm_seek(&ogg_file, 0); // Fill initial buffers for (size_t i=0; i<num_buffers; ++i) if (!FillBuffer(i)) break; // if this fails, the piece is shorter than the initial buffers // play! alErrorCheck(alSourcePlay(channel)); return true; }
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; } }
//------------------------------------------------------------------------------------------------------- // std::shared_ptr<char> ogg_reader::read(size_t bufferSize, uint64_t *readBytes) { char* buffer = new char[bufferSize]; int requestSize(bufferSize); int bitStream(0); long readSize(0); uint32_t comSize(0); while (true) { readSize = ov_read(&vorbisFile_, buffer + comSize, requestSize, 0, 2, 1, &bitStream); // 曲が終わってた if (!readSize) { ov_pcm_seek(&vorbisFile_, 0); break; } // 書き込んだサイズを加える comSize += readSize; // 波形データ配列の次の書き込み位置がバッファサイズを超えてたらループを抜ける if (comSize >= bufferSize) { break; } // バッファを全部書き込んでなかったら次の書き込み要求サイズをバッファサイズから書き込んだサイズを引いたものにする if (bufferSize - comSize < 4096) { requestSize = bufferSize - comSize; } } *readBytes = comSize; //スマートポインタの管理下に置く return std::shared_ptr<char>( buffer, std::default_delete<char[]>()); }
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; }
void OggAudioSource::setDecoderPosition(Int64 startFrame) { RScopedLock l(&mDecodeLock); ov_pcm_seek(&mOggFile, startFrame * getNumChannels()); if(startFrame < getLength() * getSampleRate()) mEOF = false; }
uint32 CAudioDecoderVorbis::getNextBytes(uint8 *buffer, uint32 minimum, uint32 maximum) { sint current_section = 0; // ??? if (_IsMusicEnded) return 0; nlassert(minimum <= maximum); // can't have this.. uint32 bytes_read = 0; #ifdef NL_BIG_ENDIAN sint endianness = 1; #else sint endianness = 0; #endif do { // signed 16-bit or unsigned 8-bit little-endian samples sint br = ov_read(&_OggVorbisFile, (char *)&buffer[bytes_read], maximum - bytes_read, endianness, // Specifies big or little endian byte packing. 0 for little endian, 1 for b ig endian. Typical value is 0. getBitsPerSample() == 8 ? 1 : 2, getBitsPerSample() == 8 ? 0 : 1, // Signed or unsigned data. 0 for unsigned, 1 for signed. Typically 1. ¤t_section); // nlinfo(NLSOUND_XAUDIO2_PREFIX "current_section: %i", current_section); if (br > 0) { bytes_read += (uint32)br; } else if (br == 0) // EOF { if (_Loop) { ov_pcm_seek(&_OggVorbisFile, 0); //_Stream->seek(0, NLMISC::IStream::begin); } else { _IsMusicEnded = true; break; } } else { // error switch(br) { case OV_HOLE: nlwarning("ov_read returned OV_HOLE"); break; case OV_EINVAL: nlwarning("ov_read returned OV_EINVAL"); break; case OV_EBADLINK: nlwarning("ov_read returned OV_EBADLINK"); break; default: nlwarning("ov_read returned %d", br); } } } while (bytes_read < minimum); return bytes_read; }
/* ================== Sound::FillBuffer Fills the buffer by streaming from an appropriate buffer. If PLAYBACK_CACHE: The vector<char> *cacheBuffer is used to fill the buffer. if PLAYBACK_STREAM: The OggVorbis_File *oggStream is used to fill the buffer. ================== */ bool Sound::FillBuffer(ALuint buffer) { char data[BUFFER_SIZE]; int size = 0; int section = 0; long result = 0; while (size < BUFFER_SIZE) { if (pbMethod == PLAYBACK_STREAM) { result = ov_read(oggStream, data+size, BUFFER_SIZE-size, 0, 2, 1, §ion); } else if (pbMethod == PLAYBACK_CACHE) { /* Calculate how much we can copy from the cache */ long remainding = cacheBuffer->size() - bytePos; result = min<long>(remainding, BUFFER_SIZE-size); /* Perform the copy */ if (result > 0) { copy(cacheBuffer->begin()+bytePos, cacheBuffer->begin()+bytePos+result, data+size); bytePos += result; } } else { PimAssert(false, "FillBuffer on PLAYBACK_UNDEFINED sound-object"); } if (result > 0) { size += result; } else if (result < 0) { /* An error occurred */ if (pbMethod == PLAYBACK_STREAM) { printf("OggVorbis error: %s\n", OggErrorString((int)result).c_str()); } return false; } else { /* We've reached the end of the buffer */ if (loop) { if (pbMethod == PLAYBACK_STREAM) { ov_pcm_seek(oggStream, 0); } else { bytePos = 0; } } else { /* We're not looping, and the end has beed reached */ if (!size) { return false; } else { /* Fill the buffer with what we've got */ break; } } } } /* Fill the OpenAL buffer with the retrieved data */ alBufferData(buffer, audioData.format, data, size, (int)audioData.frequency); return true; }
void SeekVorbisStream(MFAudioStream *pStream, float seconds) { MFVorbisStream *pVS = (MFVorbisStream*)pStream->pStreamData; #if defined(VORBIS_TREMOR) ov_pcm_seek(&pVS->vorbisFile, (ogg_int64_t)(seconds*(float)pVS->pInfo->rate)); #else ov_time_seek(&pVS->vorbisFile, seconds); #endif }
void OggFileStream::init(const ALuint& source, const int& position_in_file, const int& position_in_buffer, const bool& is_event) { // create buffers for reading in flip mode alGenBuffers(2,m_buffers) ; InternalMessage("Sound", "enter oggreader Init") ; // Create Ogg Stream on the file m_stream = new OggVorbis_File() ; int error = ov_fopen((char*)m_file_name.c_str(),m_stream) ; if (error < 0) { ErrorMessage("[OpenAL::OggReader] Can't read the samples") ; return ; } // Get sound information vorbis_info* Infos = ov_info(m_stream,-1) ; m_sample_rate = Infos->rate ; m_samples_by_buffer = (ALsizei)(Infos->channels * Infos->rate * m_update_time) ; switch (Infos->channels) { case 1: m_format = AL_FORMAT_MONO16 ; break; case 2: m_format = AL_FORMAT_STEREO16 ; break; default: ErrorMessage("[OpenAL::OggReader] Audio Format audio not supported (more than 2 channel)") ; return ; } int pos = 0 ; if (position_in_file > 0) { pos = position_in_file-m_samples_by_buffer+position_in_buffer+1 ; } ov_pcm_seek(m_stream,pos) ; // Load the buffers loadBuffer(m_buffers[0],is_event) ; loadBuffer(m_buffers[1],is_event) ; alSourceQueueBuffers(source,2,m_buffers) ; if (alGetError() != AL_NO_ERROR) { InformationMessage("Sound", "[OpenAL::OggReader] Impossible to queue the buffers") ; return ; } InternalMessage("Sound", "leave oggreader Init") ; }
long long int StreamOGGSoundBuffer::filler(ALBuffer& buf, size_t size, bool repeat) { const int endianness(0); // 0 LittleEndian, 1 BigEndian. Usually 0 const int sign(1); // Signed(1) or unsigned(0) data. Usually 1. const short BPS(16); // Bits per sample. We default to 16 int chunk(size < OGG_BUFF_SIZE ? ((int)size) : OGG_BUFF_SIZE); char* array = new char[chunk](); long read(0); int err(0); ALenum alErr(AL_NO_ERROR); SSerror error(SSerror::SS_NO_ERROR); /* Try to read 'size' bytes into pcmData field. */ pcmData.clear(); do { /* Read from Ogg file into temporal array */ read = ov_read(oggFile, array, chunk, endianness, BPS/8, sign, &bitStreamSection); if (read > 0) { /* Store fetched audio data */ pcmData.insert(pcmData.end(), array, &array[read]); size -= read; chunk = size < OGG_BUFF_SIZE ? ((int)size) : OGG_BUFF_SIZE; } else if (read == 0 && repeat) { /* End of audio data, must repeat. */ read = ov_pcm_seek(oggFile, 0); bitStreamSection = 0; ASSERT(read==0); read = 1; // continue iteration } } while (read > 0 && chunk > 0); if (read < 0) { /* Error fetching audio data from Ogg file */ std::map<int, const char*> strErr = {{OV_HOLE, "OV_HOLE"}, {OV_EBADLINK, "OV_EBADLINK"}, {OV_EINVAL, "OV_EINVAL"}}; debug("Can't read OGG file. Error: %s\n", strErr[read]); delete[] array; return -1ll; } else { /* Fill OpenAL buffer with fetched audio data */ alBufferData(buf, format, &pcmData[0], pcmData.size(), freq); } delete[] array; if (alGetError() != AL_NO_ERROR) { return -1ll; } return ((long long int)pcmData.size()); }
gc_int32 gauX_sample_source_ogg_seek(void* in_context, gc_int32 in_sampleOffset) { gau_SampleSourceOggContext* ctx = &((gau_SampleSourceOgg*)in_context)->context; gc_int32 ret; gc_mutex_lock(ctx->oggMutex); ret = ov_pcm_seek(&ctx->oggFile, in_sampleOffset); ctx->endOfSamples = 0; gc_mutex_unlock(ctx->oggMutex); return ret; }
// QC:U size_t VorbisPCMSource::seek(size_t position, int whence) { assert(canSeek); xerror(whence == SEEK_SET, "VorbisPCMSource::seek : whence parameter not supported."); if(!ov_pcm_seek(&of, position)) { eofReached = false; return position; } xerror(false, "VorbisPCMSource::seek : Could not seek at position %d in %s.", position, f->name()); return 0; }
bool VorbisDecoder::rewind() { int result = ov_pcm_seek(&handle, 0); if(result == 0) { eof = false; return true; } return false; }
bool VorbisStream::seek(const Timestamp &where) { // Vorbisfile uses the sample pair number, thus we always use "false" for the isStereo parameter // of the convertTimeToStreamPos helper. int res = ov_pcm_seek(&_ovFile, convertTimeToStreamPos(where, getRate(), false).totalNumberOfFrames()); if (res) { warning("Error seeking in Vorbis stream (%d)", res); _pos = _bufferEnd; return false; } return refill(); }
bool RealSoundOgg::WriteStream(DWORD nSize) { HRESULT hr; char *buf; EnterCriticalSection(&m_csWrite); hr = m_pDSB->Lock( m_nLastSection * m_nBufSize, nSize, (LPVOID*)&buf, &nSize, NULL, NULL, 0 ); if (hr != DS_OK) return false; DWORD pos = 0; int sec = 0; int ret = 1; while((ret) && (pos < nSize)) { ret = ov_read(&m_vf, buf + pos, nSize - pos, 0, 2, 1, &sec); pos += ret; } if (!ret) { if (m_bLoop) { ret = 1; ov_pcm_seek(&m_vf, 0); while((ret) && (pos < nSize)) { ret = ov_read(&m_vf, buf + pos, nSize - pos, 0, 2, 1, &sec); pos += ret; } } else { while(pos < nSize) { *(buf+pos)=0; pos++; } m_bAlmostDone = true; } } m_pDSB->Unlock( buf, nSize, NULL, NULL ); m_nLastSection = m_nCurSection; LeaveCriticalSection(&m_csWrite); return true; }
void TStreamBuffer::end(ALuint source) { int count = 0; ALuint buffer; alGetSourcei(source, AL_BUFFERS_QUEUED, &count); for(; count > 0; --count) alSourceUnqueueBuffers(source, 1, &buffer); is_reading = false; ov_pcm_seek(&_v_file, 0); return; }
void OggFile::Seek(uint32_t cursor) { if(ov_seekable(&_vorbis_file) == 0) { IF_PRINT_WARNING(AUDIO_DEBUG) << "failed because Ogg file was not seekable: " << _filename << std::endl; return; } ov_pcm_seek(&_vorbis_file, cursor); // Reset the temporary buffer by setting the position to 0 _read_buffer_position = 0; _read_buffer_size = 0; }
void UpdateOggStream(){ DecodedMusic* Sound = BGM; OggVorbis_File* vf = (OggVorbis_File*)Sound->handle; Sound->block_idx++; u32 half_buf = Sound->audiobuf_size>>1; int bytesRead = 0; int current_section; int half_check = (Sound->block_idx)%2; if ((!Sound->isStereo) || Player::use_dsp){ // Mono file int i = half_check * half_buf; while(bytesRead < half_buf){ long ret=ov_read(vf,(char*)&Sound->audiobuf[i+bytesRead],OGG_BUFSIZE,¤t_section); if (ret == 0){ // EoF if (Sound->eof_idx == 0xFFFFFFFF) Sound->eof_idx = Sound->block_idx + 1; ov_pcm_seek(vf,0); }else bytesRead = bytesRead + ret; } }else{ // Stereo file char pcmout[OGG_BUFSIZE]; u8* left_channel = Sound->audiobuf; u8* right_channel = &Sound->audiobuf[half_buf]; int z = half_check * (half_buf>>1); while(bytesRead < half_buf){ long ret=ov_read(vf,pcmout,OGG_BUFSIZE,¤t_section); if (ret == 0){ // EoF if (Sound->eof_idx == 0xFFFFFFFF) Sound->eof_idx = Sound->block_idx + 1; ov_pcm_seek(vf,0); }else{ for (u32 i=0;i<ret;i=i+4){ memcpy(&left_channel[z],&pcmout[i],2); memcpy(&right_channel[z],&pcmout[i+2],2); z = z + 2; } bytesRead = bytesRead + ret; } } } }
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 }
int FileVorbis::read_samples(double *buffer, int64_t len) { if(!fd) return 0; // printf("FileVorbis::read_samples 1 %d %d %d %d\n", // history_start, // history_size, // file->current_sample, // len); float **vorbis_output; int bitstream; int accumulation = 0; update_pcm_history(len); // Fill history buffer if(decode_start != decode_end) { ov_pcm_seek(&vf, decode_start); decode_end = decode_start; } while(accumulation < decode_len) { int result = ov_read_float(&vf, &vorbis_output, decode_len - accumulation, &bitstream); //printf("FileVorbis::read_samples 1 %d %d %d\n", result, len, accumulation); if(!result) break; append_history(vorbis_output, result); accumulation += result; } read_history(buffer, file->current_sample, file->current_channel, len); // printf("FileVorbis::read_samples 2 %d %d %d %d\n", // history_start, // history_size, // file->current_sample, // len); return 0; }