Пример #1
0
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, &section);

		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();
    }
  }
Пример #3
0
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, &section);
        
        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;
}
Пример #4
0
    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;
    }
Пример #5
0
		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, &current);
				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;
		}
Пример #6
0
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);
}
Пример #7
0
// 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);
  }
Пример #9
0
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 */
Пример #10
0
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;
}
Пример #11
0
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;
}
Пример #12
0
    bool cOggDecoder::setPosition(int position, bool relative)
    {
		if(Valid)
		{
			if(ov_seekable(&oggStream))
			{
				return (ov_raw_seek(&oggStream,position)==0);
			}
		}
		return false;
    }
Пример #13
0
	void OggWrapper::ResetStream()
	{
		if (seekable_)
		{
			int error = ov_raw_seek(ovFile_, 0);
			if (error != 0)
			{
				std::cout << "ov_raw_seek error : " << error << std::endl;
			}
		}
	}
Пример #14
0
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);
}
Пример #15
0
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);
}
Пример #16
0
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;
  }
}
Пример #17
0
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, &current_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;
	}
}
Пример #18
0
	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;
		}
	}
Пример #19
0
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));
}
Пример #20
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, &section);
        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;

}
Пример #21
0
		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();
			}
		}
Пример #22
0
void sound_seekSample (SoundSample * sample) {
    ov_raw_seek (&sample->s_file.oggFile, 0);
}
Пример #23
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;
}
Пример #24
0
void eAudioDecoderOgg::resync()
{
//eDebug ("[OGG]resync");
	if (fileinfo.sourcefd >= 0)
		ov_raw_seek(&vf,::lseek64(sourcefd,0,SEEK_CUR));
}
Пример #25
0
/*
============
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 );
	}
}
Пример #26
0
/*
=================
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);*/
}
Пример #27
0
void SoundOVProvider::Rewind()
{
	ov_raw_seek(&oggFile, 0);
}
Пример #28
0
void alogg_rewind_ogg(ALOGG_OGG *ogg) {
  ov_raw_seek(&(ogg->vf), 0);
}
Пример #29
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);
	}
}
Пример #30
0
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);

  }
      
}