Exemple #1
0
/* public */
static void
vorbis_stream_decode(struct decoder *decoder,
		     struct input_stream *input_stream)
{
	GError *error = NULL;

	if (ogg_codec_detect(decoder, input_stream) != OGG_CODEC_VORBIS)
		return;

	/* rewind the stream, because ogg_codec_detect() has
	   moved it */
	input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL);

	struct vorbis_input_stream vis;
	OggVorbis_File vf;
	if (!vorbis_is_open(&vis, &vf, decoder, input_stream))
		return;

	const vorbis_info *vi = ov_info(&vf, -1);
	if (vi == NULL) {
		g_warning("ov_info() has failed");
		return;
	}

	struct audio_format audio_format;
	if (!audio_format_init_checked(&audio_format, vi->rate,
#ifdef HAVE_TREMOR
				       SAMPLE_FORMAT_S16,
#else
				       SAMPLE_FORMAT_FLOAT,
#endif
				       vi->channels, &error)) {
		g_warning("%s", error->message);
		g_error_free(error);
		return;
	}

	float total_time = ov_time_total(&vf, -1);
	if (total_time < 0)
		total_time = 0;

	decoder_initialized(decoder, &audio_format, vis.seekable, total_time);

	enum decoder_command cmd = decoder_get_command(decoder);

#ifdef HAVE_TREMOR
	char buffer[4096];
#else
	float buffer[2048];
	const int frames_per_buffer =
		G_N_ELEMENTS(buffer) / audio_format.channels;
	const unsigned frame_size = sizeof(buffer[0]) * audio_format.channels;
#endif

	int prev_section = -1;
	unsigned kbit_rate = 0;

	do {
		if (cmd == DECODE_COMMAND_SEEK) {
			double seek_where = decoder_seek_where(decoder);
			if (0 == ov_time_seek_page(&vf, seek_where)) {
				decoder_command_finished(decoder);
			} else
				decoder_seek_error(decoder);
		}

		int current_section;

#ifdef HAVE_TREMOR
		long nbytes = ov_read(&vf, buffer, sizeof(buffer),
				      VORBIS_BIG_ENDIAN, 2, 1,
				      &current_section);
#else
		float **per_channel;
		long nframes = ov_read_float(&vf, &per_channel,
					     frames_per_buffer,
					     &current_section);
		long nbytes = nframes;
		if (nframes > 0) {
			vorbis_interleave(buffer,
					  (const float*const*)per_channel,
					  nframes, audio_format.channels);
			nbytes *= frame_size;
		}
#endif

		if (nbytes == OV_HOLE) /* bad packet */
			nbytes = 0;
		else if (nbytes <= 0)
			/* break on EOF or other error */
			break;

		if (current_section != prev_section) {
			vi = ov_info(&vf, -1);
			if (vi == NULL) {
				g_warning("ov_info() has failed");
				break;
			}

			if (vi->rate != (long)audio_format.sample_rate ||
			    vi->channels != (int)audio_format.channels) {
				/* we don't support audio format
				   change yet */
				g_warning("audio format change, stopping here");
				break;
			}

			char **comments = ov_comment(&vf, -1)->user_comments;
			vorbis_send_comments(decoder, input_stream, comments);

			struct replay_gain_info rgi;
			if (vorbis_comments_to_replay_gain(&rgi, comments))
				decoder_replay_gain(decoder, &rgi);

			prev_section = current_section;
		}

		long test = ov_bitrate_instant(&vf);
		if (test > 0)
			kbit_rate = test / 1000;

		cmd = decoder_data(decoder, input_stream,
				   buffer, nbytes,
				   kbit_rate);
	} while (cmd != DECODE_COMMAND_STOP);

	ov_clear(&vf);
}
bool AudioBuffer::loadOgg(Stream* stream, ALuint buffer, bool streamed, AudioStreamStateOgg* streamState)
{
    GP_ASSERT(stream);

    vorbis_info* info;
    ALenum format;
    long result;
    int section;
    long size = 0;

    stream->rewind();

    ov_callbacks callbacks;
    callbacks.read_func = readStream;
    callbacks.seek_func = seekStream;
    callbacks.close_func = closeStream;
    callbacks.tell_func = tellStream;

    if ((result = ov_open_callbacks(stream, &streamState->oggFile, NULL, 0, callbacks)) < 0)
    {
        GP_ERROR("Failed to open ogg file.");
        return false;
    }

    info = ov_info(&streamState->oggFile, -1);
    GP_ASSERT(info);
    if (info->channels == 1)
        format = AL_FORMAT_MONO16;
    else
        format = AL_FORMAT_STEREO16;

    // size = #samples * #channels * 2 (for 16 bit).
    long data_size = ov_pcm_total(&streamState->oggFile, -1) * info->channels * 2;

    if (streamed)
    {
        // Save streaming state for later use.
        streamState->dataStart = ov_pcm_tell(&streamState->oggFile);
        streamState->dataSize = data_size;
        streamState->format = format;
        streamState->frequency = info->rate;
        
        // Limit data size to STREAMING_BUFFER_SIZE.
        if (data_size > STREAMING_BUFFER_SIZE)
            data_size = STREAMING_BUFFER_SIZE;
    }

    char* data = new char[data_size];

    while (size < data_size)
    {
        result = ov_read(&streamState->oggFile, data + size, data_size - size, 0, 2, 1, &section);
        if (result > 0)
        {
            size += result;
        }
        else if (result < 0)
        {
            SAFE_DELETE_ARRAY(data);
            GP_ERROR("Failed to read ogg file; file is missing data.");
            return false;
        }
        else
        {
            break;
        }
    }
    
    if (size == 0)
    {
        SAFE_DELETE_ARRAY(data);
        GP_ERROR("Filed to read ogg file; unable to read any data.");
        return false;
    }

    AL_CHECK(alBufferData(buffer, format, data, size, info->rate));

    SAFE_DELETE_ARRAY(data);

    if (!streamed)
        ov_clear(&streamState->oggFile);

    return true;
}
Exemple #3
0
/*
-----------------------------------------------------------------------------
 Function: Sound_StreamBGTrack -Called each frame to update streaming music
								track.
 
 Parameters: Nothing
 
 Returns: Nothing	
 
 Notes: 
-----------------------------------------------------------------------------
*/
PUBLIC void Sound_StreamBGTrack( void )
{

	W8		data[BUFFER_SIZE];
	int			processed, queued, state;
	int			size, read, dummy;
	unsigned	buffer;

	if( ! s_musicVolume->value )
	{
		return;
	}

	if( ! s_streamingChannel )
	{
		return;
	}

	// Unqueue and delete any processed buffers
	pfalGetSourcei( s_streamingChannel->sourceName, AL_BUFFERS_PROCESSED, &processed );
	if( processed > 0 )
	{
		while (processed--)
		{
			pfalSourceUnqueueBuffers( s_streamingChannel->sourceName, 1, &buffer );
			pfalDeleteBuffers( 1, &buffer );
		}
	}

	// Make sure we always have at least 4 buffers in the queue
	pfalGetSourcei( s_streamingChannel->sourceName, AL_BUFFERS_QUEUED, &queued );
	while( queued < 4 )
	{
		size = 0;

		// Stream from disk
		while( size < BUFFER_SIZE )
		{
			read = ov_read( bgTrack.vorbisFile, (char *)data + size, BUFFER_SIZE - size, &dummy );
			if( read == 0 )
			{
				// End of file
				if( ! bgTrack.looping)
				{
					// Close the intro track
					Sound_CloseBGTrack( &bgTrack );

					// Open the loop track
					if( ! Sound_OpenBGTrack( bgTrack.loopName, &bgTrack ) )
					{
						Sound_StopBGTrack();
						return;
					}

					bgTrack.looping = true;
				}

				// Restart the track, skipping over the header
				ov_raw_seek( bgTrack.vorbisFile, (ogg_int64_t)bgTrack.start );

				// Try streaming again
				read = ov_read( bgTrack.vorbisFile, (char *)data + size, BUFFER_SIZE - size, &dummy );
			}

			if( read <= 0 )
			{
				// An error occurred
				Sound_StopBGTrack();
				return;
			}

			size += read;
		}

		// Upload and queue the new buffer
		pfalGenBuffers( 1, &buffer );
		pfalBufferData( buffer, bgTrack.format, data, size, bgTrack.rate );
		pfalSourceQueueBuffers( s_streamingChannel->sourceName, 1, &buffer );

		queued++;
	}

	// Update volume
	pfalSourcef( s_streamingChannel->sourceName, AL_GAIN, s_musicVolume->value );

	// If not playing, then do so
	pfalGetSourcei( s_streamingChannel->sourceName, AL_SOURCE_STATE, &state );
	if( state != AL_PLAYING )
	{
		pfalSourcePlay(s_streamingChannel->sourceName);
	}
}
//
// OggResourceLoader::ParseOgg					- Chapter 13, page 405
//
bool OggResourceLoader::ParseOgg(char *oggStream, size_t length, shared_ptr<ResHandle> handle)
{
	shared_ptr<SoundResourceExtraData> extra = static_pointer_cast<SoundResourceExtraData>(handle->GetExtra());

	OggVorbis_File vf;                     // for the vorbisfile interface

	ov_callbacks oggCallbacks;

	OggMemoryFile *vorbisMemoryFile = GCC_NEW OggMemoryFile; 
	vorbisMemoryFile->dataRead = 0;
	vorbisMemoryFile->dataSize = length; 
	vorbisMemoryFile->dataPtr = (unsigned char *)oggStream;

	oggCallbacks.read_func = VorbisRead;
	oggCallbacks.close_func = VorbisClose;
	oggCallbacks.seek_func = VorbisSeek;
	oggCallbacks.tell_func = VorbisTell;

	int ov_ret = ov_open_callbacks(vorbisMemoryFile, &vf, NULL, 0, oggCallbacks);
	GCC_ASSERT(ov_ret>=0);

    // ok now the tricky part
    // the vorbis_info struct keeps the most of the interesting format info
    vorbis_info *vi = ov_info(&vf,-1);

    memset(&(extra->m_WavFormatEx), 0, sizeof(extra->m_WavFormatEx));

    extra->m_WavFormatEx.cbSize          = sizeof(extra->m_WavFormatEx);
    extra->m_WavFormatEx.nChannels       = vi->channels;
    extra->m_WavFormatEx.wBitsPerSample  = 16;                    // ogg vorbis is always 16 bit
    extra->m_WavFormatEx.nSamplesPerSec  = vi->rate;
    extra->m_WavFormatEx.nAvgBytesPerSec = extra->m_WavFormatEx.nSamplesPerSec*extra->m_WavFormatEx.nChannels*2;
    extra->m_WavFormatEx.nBlockAlign     = 2*extra->m_WavFormatEx.nChannels;
    extra->m_WavFormatEx.wFormatTag      = 1;

	DWORD   size = 4096 * 16;
    DWORD   pos = 0;
    int     sec = 0;
    int     ret = 1;
    
	DWORD bytes = (DWORD)ov_pcm_total(&vf, -1);    
	bytes *= 2 * vi->channels;
	
	if (handle->Size() != bytes)
	{
		GCC_ASSERT(0 && _T("The Ogg size does not match the memory buffer size!"));
		ov_clear(&vf);
		SAFE_DELETE(vorbisMemoryFile);
		return false;
	}

    // now read in the bits
    while(ret && pos<bytes)
    {
        ret = ov_read(&vf, handle->WritableBuffer()+pos, size, 0, 2, 1, &sec);
        pos += ret;
		if (bytes - pos < size)
		{
			size = bytes - pos;
		}
    }

	extra->m_LengthMilli = (int)(1000.f * ov_time_total(&vf, -1));
	
	ov_clear(&vf);

	SAFE_DELETE(vorbisMemoryFile);

	return true;
}
Exemple #5
0
bool SoundBuffer::LoadVorbis(const std::string& file, std::vector<boost::uint8_t> buffer, bool strict)
{
	VorbisInputBuffer buf;
	buf.data = &buffer[0];
	buf.pos = 0;
	buf.size = buffer.size();
	
	ov_callbacks vorbisCallbacks;
	vorbisCallbacks.read_func  = VorbisRead;
	vorbisCallbacks.close_func = VorbisClose;
	vorbisCallbacks.seek_func  = NULL;
	vorbisCallbacks.tell_func  = NULL;

	OggVorbis_File oggStream;
	const int result = ov_open_callbacks(&buf, &oggStream, NULL, 0, vorbisCallbacks);
	if (result < 0) {
		LOG_L(L_WARNING, "Could not open Ogg stream (reason: %s).",
				ErrorString(result).c_str());
		return false;
	}
	
	vorbis_info* vorbisInfo = ov_info(&oggStream, -1);
	// vorbis_comment* vorbisComment = ov_comment(&oggStream, -1);

	ALenum format;
	if (vorbisInfo->channels == 1)
	{
		format = AL_FORMAT_MONO16;
	}
	else if (vorbisInfo->channels == 2)
	{
		format = AL_FORMAT_STEREO16;
	}
	else
	{
		if (strict) {
			ErrorMessageBox("SoundBuffer::LoadVorbis (%s): invalid number of channels.", file, 0);
		} else {
			LOG_L(L_WARNING, "File %s: invalid number of channels: %i",
					file.c_str(), vorbisInfo->channels);
		}
		return false;
	}

	size_t pos = 0;
	std::vector<boost::uint8_t> decodeBuffer(512*1024); // 512kb read buffer
	int section = 0;
	long read = 0;
	do
	{
		if (4*pos > 3*decodeBuffer.size()) // enlarge buffer so ov_read has enough space
			decodeBuffer.resize(decodeBuffer.size()*2);
		read = ov_read(&oggStream, (char*)&decodeBuffer[pos], decodeBuffer.size() - pos, 0, 2, 1, &section);
		switch(read)
		{
			case OV_HOLE:
				LOG_L(L_WARNING,
						"%s: garbage or corrupt page in stream (non-fatal)",
						file.c_str());
				continue; // read next
			case OV_EBADLINK:
				LOG_L(L_WARNING, "%s: corrupted stream", file.c_str());
				return false; // abort
			case OV_EINVAL:
				LOG_L(L_WARNING, "%s: corrupted headers", file.c_str());
				return false; // abort
			default:
				break; // all good
		};
		pos += read;
	} while (read > 0); // read == 0 indicated EOF, read < 0 is error

	AlGenBuffer(file, format, &decodeBuffer[0], pos, vorbisInfo->rate);
	filename = file;
	channels = vorbisInfo->channels;
	return true;
}
int DecodeOgg(FILE* stream, DecodedSound* Sound){
	
	// Passing filestream to libogg
	int eof=0;
	OggVorbis_File* vf = (OggVorbis_File*)malloc(sizeof(OggVorbis_File));
	static int current_section;
	fseek(stream, 0, SEEK_SET);
	if(ov_open(stream, vf, NULL, 0) != 0)
	{
		fclose(stream);
		Output::Warning("Corrupt ogg file");
		return -1;
	}
	
	// Grabbing info from the header
	vorbis_info* my_info = ov_info(vf,-1);
	Sound->samplerate = my_info->rate;
	Sound->format = CSND_ENCODING_PCM16;
	u16 audiotype = my_info->channels;
	Sound->audiobuf_size = ov_time_total(vf,-1) * (my_info->rate<<1);
	if (audiotype == 2) Sound->isStereo = true;
	else Sound->isStereo = false;
	Sound->bytepersample = audiotype<<1;
	
	// Preparing PCM16 audiobuffer
	#ifdef USE_CACHE
	allocCache(Sound);
	#else
	Sound->audiobuf = (u8*)linearAlloc(Sound->audiobuf_size);
	#endif
	
	if (Player::use_dsp) audiotype = 1; // We trick the decoder since DSP supports native stereo playback
	
	// Decoding Vorbis buffer
	int i = 0;
	if (audiotype == 1){ // Mono file
		while(!eof){
			long ret=ov_read(vf,(char*)&Sound->audiobuf[i],OGG_BUFSIZE,&current_section);
			if (ret == 0) eof=1;
			else i = i + ret;
		}
	}else{ // Stereo file
		char pcmout[OGG_BUFSIZE];
		int z = 0;
		u32 chn_size = Sound->audiobuf_size>>1;
		u8* left_channel = Sound->audiobuf;
		u8* right_channel = &Sound->audiobuf[chn_size];
		while(!eof){
			long ret=ov_read(vf,pcmout,OGG_BUFSIZE,&current_section);
			if (ret == 0) eof=1;
			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;
				}
			}
		}
	}
	
	ov_clear(vf);
	#ifdef USE_CACHE
	return LAST_ENTRY;
	#else
	return 0;
	#endif
	
}
Exemple #7
0
int snd_load_file(char const * file, ALuint buffer){
	FILE*           oggFile;
	OggVorbis_File  oggStream;
	vorbis_info*    vorbisInfo;
	vorbis_comment* vorbisComment;
	ALenum format;

	int result;

	if(!(oggFile = fopen(file, "rb")))
		printf("Could not open Ogg file.\n");

	if((result = ov_open(oggFile, &oggStream, NULL, 0)) < 0)
	{
		fclose(oggFile);
		printf("Could not open Ogg stream.\n");
		return 0;
	}

	vorbisInfo = ov_info(&oggStream, -1);
	vorbisComment = ov_comment(&oggStream, -1);

	if(vorbisInfo->channels == 1)
		format = AL_FORMAT_MONO16;
	else
		format = AL_FORMAT_STEREO16;
		
		
	char * dyn_data = NULL;
	int  size = 0;
	int  section;
	result = 1;
	printf("Loading sound file %s\n", file);
	while(result > 0){
		char data[BUFFER_SIZE];
		result = ov_read(&oggStream, data, BUFFER_SIZE, 0, 2, 1, & section);
		if(result > 0){
			char * tmp;
			size += result;

			tmp = (char*)malloc(sizeof(char)*(size));
			if(dyn_data != NULL){
				memcpy(tmp, dyn_data, sizeof(char)*(size-result));
				free(dyn_data);
			}
			dyn_data = tmp;
			tmp += size-result;
			memcpy(tmp, data, result);

		} else if(result < 0){
			switch(result){
				case OV_HOLE:
					printf("Interruption in the data.%d\n", result);
					printf("one of: garbage between pages, loss of sync followed by recapture, or a corrupt page\n");
					break;
				case OV_EBADLINK:
					printf("an invalid stream section was supplied to libvorbisfile, or the requested link is corrupt.\n");
					break;
				case OV_EINVAL:
					printf("the initial file headers can't be read or are corrupt, or the initial open call for vf failed.\n");
					break;
			}

		} else if(size == 0){
			printf("Date not read.\n");
		}
	}

	printf("Read %d bytes.\n", size);
	
	alBufferData(buffer, format, dyn_data, size, vorbisInfo->rate);
	free(dyn_data);
	ov_clear(&oggStream);
	return 1;
}
static void * ogg_player_thread(private_data_ogg * priv)
{
  int first_time = 1;
  long ret;

  /* init */
  LWP_InitQueue(&oggplayer_queue);

  priv[0].vi = ov_info(&priv[0].vf, -1);

  ASND_Pause(0);

  priv[0].pcm_indx = 0;
  priv[0].pcmout_pos = 0;
  priv[0].eof = 0;
  priv[0].flag = 0;
  priv[0].current_section = 0;

  ogg_thread_running = 1;

  while (!priv[0].eof && ogg_thread_running)
  {
    if (priv[0].flag)
      LWP_ThreadSleep(oggplayer_queue); /* wait only when i have samples to send */

    if (priv[0].flag == 0) /* wait to all samples are sended */
    {
      if (ASND_TestPointer(0, priv[0].pcmout[priv[0].pcmout_pos])
          && ASND_StatusVoice(0) != SND_UNUSED)
      {
        priv[0].flag |= 64;
        continue;
      }
      if (priv[0].pcm_indx < READ_SAMPLES)
      {
        priv[0].flag = 3;

        if (priv[0].seek_time >= 0)
        {
          ov_time_seek(&priv[0].vf, priv[0].seek_time);
          priv[0].seek_time = -1;
        }

        ret
            = ov_read(
                &priv[0].vf,
                (void *) &priv[0].pcmout[priv[0].pcmout_pos][priv[0].pcm_indx],
                MAX_PCMOUT,/*0,2,1,*/&priv[0].current_section);
        priv[0].flag &= 192;
        if (ret == 0)
        {
          /* EOF */
          if (priv[0].mode & 1)
            ov_time_seek(&priv[0].vf, 0); /* repeat */
          else
            priv[0].eof = 1; /* stops */
        }
        else if (ret < 0)
        {
          /* error in the stream.  Not a problem, just reporting it in
           case we (the app) cares.  In this case, we don't. */
          if (ret != OV_HOLE)
          {
            if (priv[0].mode & 1)
              ov_time_seek(&priv[0].vf, 0); /* repeat */
            else
              priv[0].eof = 1; /* stops */
          }
        }
        else
        {
          /* we don't bother dealing with sample rate changes, etc, but
           you'll have to */
          priv[0].pcm_indx += ret >> 1; /* get 16 bits samples */
        }
      }
      else
        priv[0].flag = 1;
    }
Exemple #9
0
int main(){
  OggVorbis_File ov;
  int i,ret;
  ogg_int64_t pcmlength;
  double timelength;
  char *bigassbuffer;
  int dummy;

#ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
  _setmode( _fileno( stdin ), _O_BINARY );
#endif


  /* open the file/pipe on stdin */
  if(ov_open_callbacks(stdin,&ov,NULL,-1,OV_CALLBACKS_NOCLOSE)<0){
    fprintf(stderr,"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){
	fprintf(stderr,"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 */
    pcmlength=ov_pcm_total(&ov,-1);
    timelength=ov_time_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));
    }
    
    {
      ogg_int64_t length=ov.end;
      fprintf(stderr,"\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;
	fprintf(stderr,"\r\t%d [raw position %ld]...     ",i,(long)val);
	ret=ov_raw_seek(&ov,val);
	if(ret<0){
	  fprintf(stderr,"seek failed: %d\n",ret);
	  exit(1);
	}

	_verify(&ov,val,-1,-1.,pcmlength,bigassbuffer);

      }
    }

    fprintf(stderr,"\r");
    {
      fprintf(stderr,"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;
	fprintf(stderr,"\r\t%d [pcm position %ld]...     ",i,(long)val);
	ret=ov_pcm_seek_page(&ov,val);
	if(ret<0){
	  fprintf(stderr,"seek failed: %d\n",ret);
	  exit(1);
	}

	_verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);

      }
    }
    
    fprintf(stderr,"\r");
    {
      fprintf(stderr,"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;
	fprintf(stderr,"\r\t%d [pcm position %ld]...     ",i,(long)val);
	ret=ov_pcm_seek(&ov,val);
	if(ret<0){
	  fprintf(stderr,"seek failed: %d\n",ret);
	  exit(1);
	}
	if(ov_pcm_tell(&ov)!=val){
	  fprintf(stderr,"Declared position didn't perfectly match request: %ld != %ld\n",
		 (long)val,(long)ov_pcm_tell(&ov));
	  exit(1);
	}

	_verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);

      }
    }

    fprintf(stderr,"\r");
    {
      fprintf(stderr,"testing time page seeking to random places in %f seconds....\n",
	     timelength);
    
      for(i=0;i<1000;i++){
	double val=(double)rand()/RAND_MAX*timelength;
	fprintf(stderr,"\r\t%d [time position %f]...     ",i,val);
	ret=ov_time_seek_page(&ov,val);
	if(ret<0){
	  fprintf(stderr,"seek failed: %d\n",ret);
	  exit(1);
	}

	_verify(&ov,-1,-1,val,pcmlength,bigassbuffer);

      }
    }

    fprintf(stderr,"\r");
    {
      fprintf(stderr,"testing time exact seeking to random places in %f seconds....\n",
	     timelength);
    
      for(i=0;i<1000;i++){
	double val=(double)rand()/RAND_MAX*timelength;
	fprintf(stderr,"\r\t%d [time position %f]...     ",i,val);
	ret=ov_time_seek(&ov,val);
	if(ret<0){
	  fprintf(stderr,"seek failed: %d\n",ret);
	  exit(1);
	}
	if(ov_time_tell(&ov)<val-1 || ov_time_tell(&ov)>val+1){
	  fprintf(stderr,"Declared position didn't perfectly match request: %f != %f\n",
		 val,ov_time_tell(&ov));
	  exit(1);
	}

	_verify(&ov,-1,-1,val,pcmlength,bigassbuffer);

      }
    }
    
    fprintf(stderr,"\r                                           \nOK.\n\n");


  }else{
    fprintf(stderr,"Standard input was not seekable.\n");
  }

  ov_clear(&ov);
  return 0;
}
Exemple #10
0
	bool OGG::Decode (Resource *resource, AudioBuffer *audioBuffer) {
		
		OggVorbis_File oggFile;
		
		if (resource->path) {
			
			FILE_HANDLE *file = lime::fopen (resource->path, "rb");
			
			if (!file) {
				
				return false;
				
			}
			
			if (file->isFile ()) {
				
				ov_open (file->getFile (), &oggFile, NULL, file->getLength ());
				
			} else {
				
				ByteArray data = ByteArray (resource->path);
				
				OAL_OggMemoryFile fakeFile = { data.Bytes (), data.Size (), 0 };
				
				if (ov_open_callbacks (&fakeFile, &oggFile, NULL, 0, OAL_CALLBACKS_BUFFER) != 0) {
					
					return false;
					
				}
				
			}
			
		} else {
			
			OAL_OggMemoryFile fakeFile = { resource->data->Bytes (), resource->data->Size (), 0 };
			
			if (ov_open_callbacks (&fakeFile, &oggFile, NULL, 0, OAL_CALLBACKS_BUFFER) != 0) {
				
				return false;
				
			}
			
		}
		
		// 0 for Little-Endian, 1 for Big-Endian
		#ifdef HXCPP_BIG_ENDIAN
		#define BUFFER_READ_TYPE 1
		#else
		#define BUFFER_READ_TYPE 0
		#endif
		
		int bitStream;
		long bytes = 1;
		int totalBytes = 0;
		
		#define BUFFER_SIZE 32768
		
		vorbis_info *pInfo = ov_info (&oggFile, -1);            
		
		if (pInfo == NULL) {
			
			//LOG_SOUND("FAILED TO READ OGG SOUND INFO, IS THIS EVEN AN OGG FILE?\n");
			return false;
			
		}
		
		audioBuffer->channels = pInfo->channels;
		audioBuffer->sampleRate = pInfo->rate;
		
		//default to 16? todo 
		audioBuffer->bitsPerSample = 16;
		
		// Seem to need four times the read PCM total
		audioBuffer->data->Resize (ov_pcm_total (&oggFile, -1) * 4);
		
		while (bytes > 0) {
			
			if (audioBuffer->data->Size () < totalBytes + BUFFER_SIZE) {
				
				audioBuffer->data->Resize (totalBytes + BUFFER_SIZE);
				
			}
			
			bytes = ov_read (&oggFile, (char *)audioBuffer->data->Bytes () + totalBytes, BUFFER_SIZE, BUFFER_READ_TYPE, 2, 1, &bitStream);
			totalBytes += bytes;
			
		}
		
		audioBuffer->data->Resize (totalBytes);
		ov_clear (&oggFile);
		
		#undef BUFFER_SIZE
		#undef BUFFER_READ_TYPE
		
		return true;
		
	}
Exemple #11
0
static void ogg_play_task(mp_callback_func cb)
{
	long							ret = 0;
	int							current_section = 0;
	double						time_seek_to = 0;
	vorbis_info					*vi;
	struct snd_device				*sound_dev;
	int							*processed_pcm;
	double						song_time;
	
	PE_DBG_PRINTF("MusicEngine: ==> ogg_play_task()! \n");

	sound_dev = (struct snd_device*)dev_get_by_type(NULL, HLD_DEV_TYPE_SND);
	processed_pcm = (int*)ogg_file->processed_pcm_buff;

	if (ov_open(ogg_file->file, &ogg_file->vf, NULL, 0) < 0)
	{
		PE_DBG_PRINTF("MusicEngine: ogg_play_task() ov_open failed! \n");
#ifdef ENABLE_PE_CACHE
		pe_cache_close(ogg_cache_id);                   // 这个ogg_cache_id是在play_file时打开
		ogg_cache_id = -1;
#else
		fclose(ogg_file->file);
#endif
		//FREE(processed_pcm);
		osal_flag_set(ogg_engine.ogg_engine_flag_id, OGG_ENGINE_FLAG_UNSUCCESSFUL);
		return;
	}
	else
	{
		PE_DBG_PRINTF("MusicEngine: ov_opened \n");

		{

		vorbis_info *vi = ov_info(&ogg_file->vf, -1);
		if (!vi)
		{
			PE_DBG_PRINTF("MusicEngine: ov_info failed!\n");
			ov_clear(&ogg_file->vf);
			osal_flag_set(ogg_engine.ogg_engine_flag_id, OGG_ENGINE_FLAG_UNSUCCESSFUL);
			return;
		}
		ogg_file->samplerate = vi->rate;
		ogg_file->channel = vi->channels;

		PE_DBG_PRINTF("\nBitstream is %d channel, %ldHz\n", vi->channels, vi->rate);
		song_time = ov_time_total(&ogg_file->vf, -1);
		if (song_time <= 0)
		{
			PE_DBG_PRINTF("MusicEngine: ov_info failed!\n");
			ov_clear(&ogg_file->vf);
			osal_flag_set(ogg_engine.ogg_engine_flag_id, OGG_ENGINE_FLAG_UNSUCCESSFUL);
		}
		
		}

		osal_flag_set(ogg_engine.ogg_engine_flag_id, OGG_ENGINE_FLAG_SUCCESS);
	}

	//all work success, we can start to play
	while (ogg_file->command  != OGG_CMD_STOP)
	{
		if (ogg_file->seek_to != 0)
		{
			time_seek_to = ov_time_tell(&ogg_file->vf);
			time_seek_to = time_seek_to + (ogg_file->seek_to * 1000);
	
			if (time_seek_to < 0)
			{
				time_seek_to = 0;
			}
			else if (time_seek_to > song_time)
			{
				time_seek_to = song_time;
			}

			ret = ov_time_seek(&ogg_file->vf, time_seek_to);
			if (ret < 0)
			{
				//seek failed
			}
			osal_task_dispatch_off();
			ogg_file->seek_to = 0;
			osal_task_dispatch_on();
		}

		if (ogg_file->command  == OGG_CMD_NONE)
		{
			ret = ov_read(&ogg_file->vf, (void *)ogg_file->pcm_out_buff, 2304, &current_section);
			if (ret == 0)
			{
				PE_DBG_PRINTF("file end!\n");
				//EOF we need call back
				
							
				osal_task_dispatch_off();
				if (ogg_file->command != OGG_CMD_STOP)
				{
					ogg_file->command  = OGG_CMD_WAIT_FOR_STOP;
				}
				osal_task_dispatch_on();
				
				cb(MP_MUSIC_PLAYBACK_END, 0);
							
				osal_task_sleep(10);
			}
			else if (ret < 0)
			{ 
				PE_DBG_PRINTF("error!!!\n");			
				/* error in the stream.  Not a problem, just reporting it in case we (the app) cares.  In this case, we don't. */

				osal_task_dispatch_off();
				if (ogg_file->command != OGG_CMD_STOP)
				{
					ogg_file->command  = OGG_CMD_WAIT_FOR_STOP;
				}
				osal_task_dispatch_on();
				
				cb(MP_MUSIC_PLAYBACK_END, 0);

				osal_task_sleep(10);
			}
			else
			{
				/* we don't bother dealing with sample rate changes, etc, but you'll have to*/
				process_ogg_pcm(sound_dev, ret, processed_pcm);
			}
		}
		else
		{
			osal_task_sleep(10);
		}

	}

	ov_clear(&ogg_file->vf);
	ogg_avoid_under_run = 0;
	snd_io_control(sound_dev, SND_CC_MUTE, 0);
	snd_stop(sound_dev);
	//FREE(processed_pcm);
	osal_flag_set(ogg_engine.ogg_engine_flag_id, OGG_ENGINE_FLAG_TASK_EXIT);            // task结束,发出EXIT消息
	PE_DBG_PRINTF("MusicEngine: <== ogg_play_task()! \n");
	
}
Exemple #12
0
	bool OGG::Decode (Resource *resource, AudioBuffer *audioBuffer) {
		
		OggVorbis_File oggFile;
		
		if (resource->path) {
			
			FILE_HANDLE *file = lime::fopen (resource->path, "rb");
			
			if (!file) {
				
				return false;
				
			}
			
			if (file->isFile ()) {
				
				if (ov_open (file->getFile (), &oggFile, NULL, file->getLength ()) != 0) {
					
					lime::fclose (file);
					return false;
					
				}
				
			} else {
				
				lime::fclose (file);
				Bytes data = Bytes (resource->path);
				
				OAL_OggMemoryFile fakeFile = { data.Data (), data.Length (), 0 };
				
				if (ov_open_callbacks (&fakeFile, &oggFile, NULL, 0, OAL_CALLBACKS_BUFFER) != 0) {
					
					return false;
					
				}
				
			}
			
		} else {
			
			OAL_OggMemoryFile fakeFile = { resource->data->Data (), resource->data->Length (), 0 };
			
			if (ov_open_callbacks (&fakeFile, &oggFile, NULL, 0, OAL_CALLBACKS_BUFFER) != 0) {
				
				return false;
				
			}
			
		}
		
		// 0 for Little-Endian, 1 for Big-Endian
		#ifdef HXCPP_BIG_ENDIAN
		#define BUFFER_READ_TYPE 1
		#else
		#define BUFFER_READ_TYPE 0
		#endif
		
		int bitStream;
		long bytes = 1;
		int totalBytes = 0;
		
		#define BUFFER_SIZE 4096
		
		vorbis_info *pInfo = ov_info (&oggFile, -1);            
		
		if (pInfo == NULL) {
			
			//LOG_SOUND("FAILED TO READ OGG SOUND INFO, IS THIS EVEN AN OGG FILE?\n");
			ov_clear (&oggFile);
			return false;
			
		}
		
		audioBuffer->channels = pInfo->channels;
		audioBuffer->sampleRate = pInfo->rate;
		
		audioBuffer->bitsPerSample = 16;
		
		int dataLength = ov_pcm_total (&oggFile, -1) * audioBuffer->channels * audioBuffer->bitsPerSample / 8;
		audioBuffer->data->Resize (dataLength);
		
		while (bytes > 0) {
				
				bytes = ov_read (&oggFile, (char *)audioBuffer->data->Data () + totalBytes, BUFFER_SIZE, BUFFER_READ_TYPE, 2, 1, &bitStream);
				totalBytes += bytes;
				
		}
		
		if (dataLength != totalBytes) {
			
			audioBuffer->data->Resize (totalBytes);
			
		}
		
		ov_clear (&oggFile);
		
		#undef BUFFER_READ_TYPE
		
		return true;
		
	}
Sound* AudioStreamer::LoadSound(IXAudio2* xaudio2, const std::string& file)
{
	if( !xaudio2 )
	{
		SND_ERROR("AudioStreamer::LoadSound(): NULL == xaudio2");
		return false;
	}

	FILE* infile = NULL;
	fopen_s(&infile, file.c_str(), "rb");

	if( !infile )
	{
		SND_ERROR("AudioStreamer::LoadSound(): Could not open file");
		return NULL;
	}

	OggVorbis_File oggfile;
	int stream;
	long readbytes = 0;
	long totalread = 0;

	ov_open(infile, &oggfile, NULL, 0);
	vorbis_info* info = ov_info(&oggfile, -1);

	Sound* s = new Sound();

	s->format.nChannels = info->channels;
	s->format.cbSize = sizeof(WAVEFORMATEX);
	s->format.wBitsPerSample = 16;
	s->format.nSamplesPerSec = info->rate;
	s->format.nAvgBytesPerSec = info->rate * 2 * info->channels;
	s->format.nBlockAlign = 2 * info->channels;
	s->format.wFormatTag = 1;
	
	s->totalsize = (unsigned int)ov_pcm_total(&oggfile, -1) * 2 * info->channels;
	s->data[0] = new char[s->totalsize];

	do
	{
		readbytes = ov_read(&oggfile, s->data[0] + totalread, s->totalsize - totalread, 0, 2, 1, &stream);
		totalread += readbytes;
	}
	while( readbytes > 0 && (unsigned int)totalread < s->totalsize );

	ov_clear(&oggfile);
	
	// create xaudio voice object
	if( FAILED(xaudio2->CreateSourceVoice(&s->voice, &s->format, 0, 2.0f, s)) )
	{
		SND_ERROR("AudioStreamer::LoadSound(): Could not create source voice");

		delete s;
		return NULL;
	}

	XAUDIO2_BUFFER audbuff;
	memset(&audbuff, 0, sizeof(XAUDIO2_BUFFER));

	audbuff.pAudioData = (const BYTE*)s->data[0];
	audbuff.Flags = XAUDIO2_END_OF_STREAM;
	audbuff.AudioBytes = s->totalsize;
	audbuff.LoopCount = XAUDIO2_LOOP_INFINITE;

	if( FAILED(s->voice->SubmitSourceBuffer(&audbuff)) )
	{
		SND_ERROR("AudioStreamer::LoadSound(): Could not submit buffer");

		delete s;
		return NULL;
	}

	s->canplay = true;

	// called from main thread
	soundguard.Lock();
	sound.push_back(s);
	soundguard.Unlock();

	return s;
}
void AudioStreamer::Update()
{
	// this method must run on separate thread!!!

	XAUDIO2_VOICE_STATE state;

	Sound*		s;
	soundlist	canstream;
	int			stream;
	long		readbytes;
	long		totalread;
	long		toread;
	bool		play;

	// must be called in every thread
	CoInitializeEx(0, COINIT_MULTITHREADED);

	while( running )
	{
		// collect sound that need more data
		canstream.clear();

		soundguard.Lock(); // reading 'sound'

		for( soundlist::iterator it = sound.begin(); it != sound.end(); ++it )
		{
			s = (*it);

			if( s->isstream )
			{
				if( (s->readsize < s->totalsize) && (s->freebuffers > 0) )
					canstream.push_back(s);
			}
		}

		soundguard.Unlock();

		// update collected sound
		if( canstream.size() > 0 )
		{
			for( soundlist::iterator it = canstream.begin(); it != canstream.end(); ++it )
			{
				soundguard.Lock(); // watch out for 'Destroy()'

				// might have exited
				if( !running )
					return;

				s = (*it);

				totalread = 0;
				readbytes = 0;
				toread = min(STREAMING_BUFFER_SIZE, s->totalsize - s->readsize);

				// fill a free buffer with data
				do
				{
					readbytes = ov_read(&s->oggfile, s->data[s->currentbuffer] + totalread, toread - totalread, 0, 2, 1, &stream);
					totalread += readbytes;
				}
				while( readbytes > 0 && totalread < toread );

				s->readsize += totalread;
				SND_DEBUG("buffer " << s->currentbuffer << " loaded");

				// pull buffer to queue if possible
				// otherwise the sound is gonna pull it
				s->voice->GetState(&state);

				if( state.BuffersQueued < MAX_BUFFER_COUNT - 1 )
				{
					s->PullBuffer(s->currentbuffer);
					SND_DEBUG("buffer " << s->currentbuffer << " pulled (instantly)");
					
					// lock it so noone can modify s->playing
					s->playguard.Lock();
					{
						s->canplay = true;
						play = (s->playrequest && !s->playing);
					}
					s->playguard.Unlock();

					if( play )
						s->Play();
				}
				
				s->currentbuffer = (s->currentbuffer + 1) % MAX_BUFFER_COUNT;
				--s->freebuffers;

				soundguard.Unlock();
			}
		}
		else
			Sleep(100);
	}

	CoUninitialize();
}
Exemple #15
0
soundDataBuffer* sound_DecodeOggVorbis(struct OggVorbisDecoderState* decoder, size_t bufferSize)
{
	size_t		size = 0;
#ifndef WZ_NOSOUND
	int		result;
#endif

	soundDataBuffer* buffer;

	ASSERT(decoder != NULL, "NULL decoder passed!");

#ifndef WZ_NOSOUND
	if (decoder->allowSeeking)
	{
		unsigned int sampleCount = getSampleCount(decoder);

		unsigned int sizeEstimate = sampleCount * decoder->VorbisInfo->channels * 2;

		if (((bufferSize == 0) || (bufferSize > sizeEstimate)) && (sizeEstimate != 0))
		{
			bufferSize = (sampleCount - getCurrentSample(decoder)) * decoder->VorbisInfo->channels * 2;
		}
	}

	// If we can't seek nor receive any suggested size for our buffer, just quit
	if (bufferSize == 0)
	{
		debug(LOG_ERROR, "can't find a proper buffer size");
		return NULL;
	}
#else
	bufferSize = 0;
#endif

	buffer = malloc(bufferSize + sizeof(soundDataBuffer));
	if (buffer == NULL)
	{
		debug(LOG_ERROR, "couldn't allocate memory (%lu bytes requested)", (unsigned long) bufferSize + sizeof(soundDataBuffer));
		return NULL;
	}

	buffer->data = (char*)(buffer + 1);
	buffer->bufferSize = bufferSize;
	buffer->bitsPerSample = 16;

#ifndef WZ_NOSOUND
	buffer->channelCount = decoder->VorbisInfo->channels;
	buffer->frequency = decoder->VorbisInfo->rate;

	// Decode PCM data into the buffer until there is nothing to decode left
	do
	{
		// Decode
		int section;
		result = ov_read(&decoder->oggVorbis_stream, &buffer->data[size], bufferSize - size, OGG_ENDIAN, 2, 1, &section);

		if (result < 0)
		{
			debug(LOG_ERROR, "error decoding from OggVorbis file; errorcode from ov_read: %s", wz_oggVorbis_getErrorStr(result));
			free(buffer);
			return NULL;
		}
		else
		{
			size += result;
		}

	} while ((result != 0 && size < bufferSize));
#endif

	buffer->size = size;

	return buffer;
}
Exemple #16
0
int OggImportFileHandle::Import(TrackFactory *trackFactory, Track ***outTracks,
                                int *outNumTracks, Tags *tags)
{
   wxASSERT(mFile->IsOpened());

   CreateProgress();

   //Number of streams used may be less than mVorbisFile->links,
   //but this way bitstream matches array index.
   mChannels = new WaveTrack **[mVorbisFile->links];

   int i,c;
   for (i = 0; i < mVorbisFile->links; i++)
   {
      //Stream is not used
      if (mStreamUsage[i] == 0)
      {
         //This is just a padding to keep bitstream number and
         //array indices matched.
         mChannels[i] = NULL;
         continue;
      }

      vorbis_info *vi = ov_info(mVorbisFile, i);

      mChannels[i] = new WaveTrack *[vi->channels];

      for (c = 0; c < vi->channels; c++) {
         mChannels[i][c] = trackFactory->NewWaveTrack(int16Sample, vi->rate);

         if (vi->channels == 2) {
            switch (c) {
         case 0:
            mChannels[i][c]->SetChannel(Track::LeftChannel);
            mChannels[i][c]->SetLinked(true);
            break;
         case 1:
            mChannels[i][c]->SetChannel(Track::RightChannel);
            break;
            }
         }
         else {
            mChannels[i][c]->SetChannel(Track::MonoChannel);
         }
      }
   }

/* The number of bytes to get from the codec in each run */
#define CODEC_TRANSFER_SIZE 4096

/* The number of samples to read between calls to the callback.
 * Balance between responsiveness of the GUI and throughput of import. */
#define SAMPLES_PER_CALLBACK 100000

   short *mainBuffer = new short[CODEC_TRANSFER_SIZE];

   /* determine endianness (clever trick courtesy of Nicholas Devillard,
    * (http://www.eso.org/~ndevilla/endian/) */
   int testvar = 1, endian;
   if(*(char *)&testvar)
      endian = 0;  // little endian
   else
      endian = 1;  // big endian

   /* number of samples currently in each channel's buffer */
   int updateResult = eProgressSuccess;
   long bytesRead = 0;
   long samplesRead = 0;
   int bitstream = 0;
   int samplesSinceLastCallback = 0;

   // You would think that the stream would already be seeked to 0, and
   // indeed it is if the file is legit.  But I had several ogg files on
   // my hard drive that have malformed headers, and this added call
   // causes them to be read correctly.  Otherwise they have lots of
   // zeros inserted at the beginning
   ov_pcm_seek(mVorbisFile, 0);
   
   do {
      /* get data from the decoder */
      bytesRead = ov_read(mVorbisFile, (char *) mainBuffer,
                          CODEC_TRANSFER_SIZE,
                          endian,
                          2,    // word length (2 for 16 bit samples)
                          1,    // signed
                          &bitstream);

      if (bytesRead == OV_HOLE) {
         wxFileName f(mFilename);
         wxLogError(wxT("Ogg Vorbis importer: file %s is malformed, ov_read() reported a hole"),
                    f.GetFullName().c_str());
         /* http://lists.xiph.org/pipermail/vorbis-dev/2001-February/003223.html
          * is the justification for doing this - best effort for malformed file,
          * hence the message.
          */
         continue;
      } else if (bytesRead < 0) {
         /* Malformed Ogg Vorbis file. */
         /* TODO: Return some sort of meaningful error. */
         wxLogError(wxT("Ogg Vorbis importer: ov_read() returned error %i"),
                    bytesRead);
         break;
      }

      samplesRead = bytesRead / mVorbisFile->vi[bitstream].channels / sizeof(short);

      /* give the data to the wavetracks */
      if (mStreamUsage[bitstream] != 0)
      {
         for (c = 0; c < mVorbisFile->vi[bitstream].channels; c++)
            mChannels[bitstream][c]->Append((char *)(mainBuffer + c),
            int16Sample,
            samplesRead,
            mVorbisFile->vi[bitstream].channels);
      }

      samplesSinceLastCallback += samplesRead;
      if (samplesSinceLastCallback > SAMPLES_PER_CALLBACK) {
          updateResult = mProgress->Update(ov_time_tell(mVorbisFile),
                                         ov_time_total(mVorbisFile, bitstream));
          samplesSinceLastCallback -= SAMPLES_PER_CALLBACK;

      }
   } while (updateResult == eProgressSuccess && bytesRead != 0);

   delete[]mainBuffer;

   int res = updateResult;
   if (bytesRead < 0)
     res = eProgressFailed;

   if (res == eProgressFailed || res == eProgressCancelled) {
      for (i = 0; i < mVorbisFile->links; i++)
      {
         if (mChannels[i])
         {
            for(c = 0; c < mVorbisFile->vi[bitstream].channels; c++) {
               if (mChannels[i][c])
                  delete mChannels[i][c];
            }
            delete[] mChannels[i];
         }
      }
      delete[] mChannels;
      return res;
   }

   *outNumTracks = 0;
   for (int s = 0; s < mVorbisFile->links; s++)
   {
      if (mStreamUsage[s] != 0)
         *outNumTracks += mVorbisFile->vi[s].channels;
   }

   *outTracks = new Track *[*outNumTracks];
   
   int trackindex = 0;
   for (i = 0; i < mVorbisFile->links; i++)
   {
      if (mChannels[i])
      {
         for (c = 0; c < mVorbisFile->vi[i].channels; c++) {
            mChannels[i][c]->Flush();
            (*outTracks)[trackindex++] = mChannels[i][c];
         }
         delete[] mChannels[i];
      }      
   }
   delete[] mChannels;

   //\todo { Extract comments from each stream? }
   if (mVorbisFile->vc[0].comments > 0) {
      tags->Clear();
      for (c = 0; c < mVorbisFile->vc[0].comments; c++) {
         wxString comment = UTF8CTOWX(mVorbisFile->vc[0].user_comments[c]);
         wxString name = comment.BeforeFirst(wxT('='));
         wxString value = comment.AfterFirst(wxT('='));
         if (name.Upper() == wxT("DATE") && !tags->HasTag(TAG_YEAR)) {
            long val;
            if (value.Length() == 4 && value.ToLong(&val)) {
               name = TAG_YEAR;
            }
         }
         tags->SetTag(name, value);
      }
   }

   return res;
}
Exemple #17
0
static
int
s_ogg_decoder( SAL_Device *p_device, 
               sal_voice_t voice,
               sal_byte_t *p_dst, 
               int bytes_needed )
{
    int bytes_read = 0;
    SAL_Sample *sample = 0;
    SALx_OggArgs *ogg_args = 0;
    int big_endian = 0;
    int cursor = 0;

#if POSH_BIG_ENDIAN
    big_endian = 1;
#endif

    SAL_get_voice_sample( p_device, voice, &sample );
    SAL_get_voice_cursor( p_device, voice, &cursor );

    ogg_args = ( SALx_OggArgs * ) sample->sample_args.sarg_ptr;

    /* first seek to the voice's sample */
    ov_pcm_seek( &ogg_args->oa_file, cursor );

    /* then read stuff out */
    while ( bytes_read < bytes_needed )
    {
        long lret;

        lret = ov_read( &ogg_args->oa_file,         /* vorbis file */
                        p_dst + bytes_read,         /* destination buffer */
                        bytes_needed - bytes_read,  /* size of the destination buffer*/
                        big_endian,                 /* endianess, 0 == little, 1 == big */
                        2,                          /* bytes per sample */
                        1,                          /* 0 == unsigned, 1 == signed */
                        &ogg_args->oa_section );    /* pointer to number of current logical bitstream */

        if ( lret == 0 )
        {
            /* rewind the stream */
            ov_pcm_seek( &ogg_args->oa_file, 0 );
        }
        else if ( lret < 0 )
        {
            /* error */
            break;
        } 
        else 
        {
            bytes_read += lret;

             /** @todo update to handle different size samples */
            if ( !_SAL_advance_voice( p_device, voice, lret / ( ogg_args->oa_num_channels * 2 ) ) )
            {
                return 1;
            }
        }
    }

    return 0;
}
Exemple #18
0
int alogg_poll_ogg(ALOGG_OGG *ogg) {
  void *audiobuf;
  char *audiobuf_p;
  int i, size_done;
  unsigned short* data_array;
  int x;

  /* continue only if we are playing it */
  if (!alogg_is_playing_ogg(ogg))
    return ALOGG_POLL_NOTPLAYING;

  /* get the audio stream buffer and only continue if we need to fill it */
  audiobuf = get_audio_stream_buffer(ogg->audiostream);
  if (audiobuf == NULL)
    return ALOGG_OK;

  /* clear the buffer with 16bit unsigned data */
  {
    int i;
    unsigned short *j = (unsigned short *)audiobuf;
    for (i = 0; i < (ogg->audiostream_buffer_len / 2); i++, j++)
      *j = 0x8000;
  }

  /* if we need to fill it, but we were just waiting for it to finish */
  if (!ogg->loop) {
    if (ogg->wait_for_audio_stop > 0) {
      free_audio_stream_buffer(ogg->audiostream);
      if (--ogg->wait_for_audio_stop == 0) {
        /* stop it */
        //rest(500);
        alogg_stop_ogg(ogg);
        return ALOGG_POLL_PLAYJUSTFINISHED;
      }
      else
        return ALOGG_OK;
    }
  }

  audiobuf_p = (char *)audiobuf;
  size_done = 0;
  for (i = ogg->audiostream_buffer_len; i > 0; i -= size_done) {
    /* decode */
    size_done = ov_read(&(ogg->vf), audiobuf_p, i, WANT_BIG_ENDIAN, 2, 0, &(ogg->current_section));

#ifdef USE_TREMOR
    /* Add offset to data because we are using libtremor */
    data_array = (unsigned short*)audiobuf_p;

    for (x = 0; x < size_done / 2; x++)
    { 
      data_array[x] += 0x8000;
    }
#endif

    /* check if the decoding was not successful */
    if (size_done < 0) {
      if (size_done == OV_HOLE)
        size_done = 0;
      else {
        free_audio_stream_buffer(ogg->audiostream);
        alogg_stop_ogg(ogg);
        alogg_rewind_ogg(ogg);
        return ALOGG_POLL_FRAMECORRUPT;
      }
    }
    else if (size_done == 0) {
      /* we have reached the end */
      alogg_rewind_ogg(ogg);
      if (!ogg->loop) {
        free_audio_stream_buffer(ogg->audiostream);
        ogg->wait_for_audio_stop = 2;
        return ALOGG_OK;
      }
    }

    audiobuf_p += size_done;
  }

  /* lock the buffer */
  free_audio_stream_buffer(ogg->audiostream);

  return ALOGG_OK;
}
int OpenOgg(FILE* stream, DecodedMusic* Sound){
	
	// Setting return code (to check if audio streaming is needed or not)
	u8 res = 0;
	
	// Passing filestream to libogg
	int eof=0;
	OggVorbis_File* vf = (OggVorbis_File*)malloc(sizeof(OggVorbis_File));
	static int current_section;
	fseek(stream, 0, SEEK_SET);
	if(ov_open(stream, vf, NULL, 0) != 0)
	{
		fclose(stream);
		Output::Warning("Corrupt ogg file");
		return -1;
	}
	
	// Grabbing info from the header
	vorbis_info* my_info = ov_info(vf,-1);
	Sound->samplerate = my_info->rate;
	Sound->format = CSND_ENCODING_PCM16;
	u16 audiotype = my_info->channels;
	Sound->audiobuf_size = ov_time_total(vf,-1) * (my_info->rate<<1);
	if (audiotype == 2) Sound->isStereo = true;
	else Sound->isStereo = false;
	Sound->bytepersample = audiotype<<1;
	
	// Preparing PCM16 audiobuffer
	if (Sound->audiobuf_size <= BGM_BUFSIZE) res = 1;
	else{
		while (Sound->audiobuf_size > BGM_BUFSIZE){
			Sound->audiobuf_size = Sound->audiobuf_size>>1;
		}
	}
	Sound->audiobuf = (u8*)linearAlloc(Sound->audiobuf_size);
	
	if (Player::use_dsp) audiotype = 1; // We trick the decoder since DSP supports native stereo playback
	
	// Decoding Vorbis buffer
	int i = 0;
	if (audiotype == 1){ // Mono file
		while(!eof){
			long ret=ov_read(vf,(char*)&Sound->audiobuf[i],OGG_BUFSIZE,&current_section);
			if (ret == 0) eof=1;
			else i = i + ret;
		}
	}else{ // Stereo file
		char pcmout[OGG_BUFSIZE];
		int z = 0;
		u32 chn_size = Sound->audiobuf_size>>1;
		u8* left_channel = Sound->audiobuf;
		u8* right_channel = &Sound->audiobuf[chn_size];
		while(!eof){
			long ret=ov_read(vf,pcmout,OGG_BUFSIZE,&current_section);
			if (ret == 0) eof=1;
			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;
				}
			}
		}
	}
	
	//Setting default streaming values
	Sound->block_idx = 1;
	if (res == 0) Sound->handle = (FILE*)vf; // We pass libogg filestream instead of stdio ones
	else{
		ov_clear(vf);
		Sound->handle = NULL;
	}
	Sound->eof_idx = 0xFFFFFFFF;
	Sound->updateCallback = UpdateOggStream;
	Sound->closeCallback = CloseOgg;
	
	return res;
}
Exemple #20
0
SAMPLE *alogg_create_sample_from_ogg(ALOGG_OGG *ogg) {
  SAMPLE *sample;
  char *data;
  int i, sample_len_bytes, sample_len, size_done, done;
  unsigned short* data_array;
  int x;

  /* first we need to calculate the len of the sample in bytes */
  sample_len = ov_pcm_total(&(ogg->vf), -1);
  sample_len_bytes = (sample_len * (ogg->stereo ? 2 : 1)) * 2; /* / 2 = 16 bits */
  
  /* create the sample */
  sample = create_sample(16, ogg->stereo, ogg->freq, sample_len);

  /* return NULL if we were not able to allocate the memory for it */
  if (sample == NULL)
    return NULL;

  /* we need to stop and rewind the ogg */
  alogg_stop_ogg(ogg);
  alogg_rewind_ogg(ogg);

  /* set our pointer */
  data = (char *)sample->data;
  /* clear the sample buffer in unsigned format */
  {
    int i;
    unsigned short *j = (unsigned short *)data;
    for (i = 0; i < (sample_len_bytes / 2); i++, j++)
      *j = 0x8000;
  }

  /* decode */
  done = FALSE;
  size_done = 0;
  for (i = sample_len_bytes; !done && (i > 0); i -= size_done) {

    /* decode */
    size_done = ov_read(&(ogg->vf), data, i, WANT_BIG_ENDIAN, 2, 0, &(ogg->current_section));

#ifdef USE_TREMOR
    /* Add offset to data because we are using libtremor. */
    data_array = (unsigned short*)data;

    for (x = 0; x < size_done / 2; x++)
    { 
      data_array[x] += 0x8000;
    }
#endif

    /* check if the decoding was not successful */
    if (size_done < 0) {
      if (size_done == OV_HOLE)
        size_done = 0;
      else {
        alogg_rewind_ogg(ogg);
        destroy_sample(sample);
        return NULL;
      }
    }
    else if (size_done == 0)
      done = TRUE;

    data += size_done;
  }

  alogg_rewind_ogg(ogg);

  return sample;
}
Exemple #21
0
/**
 * @brief Loads the specified sound file and decodes its content into an OpenAL buffer.
 * @param file_name name of the file to open
 * @return the buffer created, or AL_NONE if the sound could not be loaded
 */
ALuint Sound::decode_file(const std::string &file_name) {

  ALuint buffer = AL_NONE;

  // load the sound file
  SoundFromMemory mem;
  mem.position = 0;
  FileTools::data_file_open_buffer(file_name, &mem.data, &mem.size);

  OggVorbis_File file;
  int error = ov_open_callbacks(&mem, &file, NULL, 0, ogg_callbacks);

  if (error) {
    std::cout << "Cannot load sound file from memory: error " << error << std::endl;
  }
  else {

    // read the encoded sound properties
    vorbis_info* info = ov_info(&file, -1);
    ALsizei sample_rate = info->rate;

    ALenum format = AL_NONE;
    if (info->channels == 1) {
      format = AL_FORMAT_MONO16;
    }
    else if (info->channels == 2) {
      format = AL_FORMAT_STEREO16;
    }

    if (format == AL_NONE) {
      std::cout << "Invalid audio format" << std::endl;
    }
    else {

      // decode the sound with vorbisfile
      std::vector<char> samples;
      int bitstream;
      long bytes_read;
      long total_bytes_read = 0;
      char samples_buffer[4096];
      do {
        bytes_read = ov_read(&file, samples_buffer, 4096, 0, 2, 1, &bitstream);
        if (bytes_read < 0) {
          std::cout << "Error while decoding ogg chunk: " << bytes_read << std::endl;
        }
        else {
          total_bytes_read += bytes_read;
          if (format == AL_FORMAT_STEREO16) {
            samples.insert(samples.end(), samples_buffer, samples_buffer + bytes_read);
          }
          else {
            // mono sound files make no sound on some machines
            // workaround: convert them on-the-fly into stereo sounds
            // TODO find a better solution
            for (int i = 0; i < bytes_read; i += 2) {
              samples.insert(samples.end(), samples_buffer + i, samples_buffer + i + 2);
              samples.insert(samples.end(), samples_buffer + i, samples_buffer + i + 2);
            }
            total_bytes_read += bytes_read;
          }
        }
      }
      while (bytes_read > 0);

      // copy the samples into an OpenAL buffer
      alGenBuffers(1, &buffer);
      alBufferData(buffer, AL_FORMAT_STEREO16, (ALshort*) &samples[0], total_bytes_read, sample_rate);
      if (alGetError() != AL_NO_ERROR) {
        std::cout << "Cannot copy the sound samples into buffer " << buffer << "\n";
        buffer = AL_NONE;
      }
    }
    ov_clear(&file);
  }

  FileTools::data_file_close_buffer(mem.data);

  return buffer;
}
Exemple #22
0
int alogg_poll_oggstream(ALOGG_OGGSTREAM *ogg) {
  void *audiobuf;
  char *audiobuf_p;
  int i, size_done;
  int last_block;
  unsigned short* data_array;
  int x;

  /* continue only if we are playing it */
  if (!alogg_is_playing_oggstream(ogg))
    return ALOGG_POLL_NOTPLAYING;

  /* get the audio stream buffer and only continue if we need to fill it */
  audiobuf = get_audio_stream_buffer(ogg->audiostream);
  if (audiobuf == NULL)
    return ALOGG_OK;

  /* clear the buffer with unsinged data*/
  {
    int i;
    unsigned short *j = (unsigned short *)audiobuf;
    for (i = 0; i < (ogg->audiostream_buffer_len / 2); i++, j++)
      *j = 0x8000;
  }

  /* if we need to fill it, but we were just waiting for it to finish */
  if (ogg->wait_for_audio_stop > 0) {
    free_audio_stream_buffer(ogg->audiostream);
    if (--ogg->wait_for_audio_stop == 0) {
      /* stop it */
      alogg_stop_oggstream(ogg);
      return ALOGG_POLL_PLAYJUSTFINISHED;
    }
    else
      return ALOGG_OK;
  }

  /* get if this will be the last block to be processed */
  if (ogg->bytes_used != -1)
    last_block = TRUE;
  else
    last_block = FALSE;

  audiobuf_p = (char *)audiobuf;
  size_done = 0;
  for (i = ogg->audiostream_buffer_len; i > 0; i -= size_done) {
    size_done = ov_read(&(ogg->vf), audiobuf_p, i, WANT_BIG_ENDIAN, 2, 0, &(ogg->current_section));

#ifdef USE_TREMOR
    /* Add offset to data because we are using libtremor. */
    data_array = (unsigned short*)audiobuf_p;

    for (x = 0; x < size_done / 2; x++)
    { 
      data_array[x] += 0x8000;
    }
#endif

    /* check if the decoding was not successful */
    if (size_done < 0) {
      if (size_done == OV_HOLE)
        size_done = 0;
      else {
        free_audio_stream_buffer(ogg->audiostream);
        alogg_stop_oggstream(ogg);
        return ALOGG_POLL_FRAMECORRUPT;
      }
    }
    else if (size_done == 0) {
      free_audio_stream_buffer(ogg->audiostream);
      /* if this was not the last block, buffer underrun */
      if (!last_block) {
        alogg_stop_oggstream(ogg);
        return ALOGG_POLL_BUFFERUNDERRUN;
      }
      /* else we just finished playing, we need to wait for audio to stop */
      else {
        ogg->wait_for_audio_stop = 2;
        return ALOGG_OK;
      }
    }

    audiobuf_p += size_done;
  }

  /* lock the buffer */
  free_audio_stream_buffer(ogg->audiostream);

  return ALOGG_OK;
}
	static ALuint createBufferFromOGG(const char *pszFilePath)
	{
		ALuint 			buffer;
		OggVorbis_File  ogg_file;
		vorbis_info*    info;
		ALenum 			format;
		int 			result;
		int 			section;
		int				err;
		unsigned int 	size = 0;

		if (ov_fopen(pszFilePath, &ogg_file) < 0)
		{
			ov_clear(&ogg_file);
			fprintf(stderr, "Could not open OGG file %s\n", pszFilePath);
			return -1;
		}

		info = ov_info(&ogg_file, -1);

		if (info->channels == 1)
			format = AL_FORMAT_MONO16;
		else
			format = AL_FORMAT_STEREO16;

		// size = #samples * #channels * 2 (for 16 bit)
		unsigned int data_size = ov_pcm_total(&ogg_file, -1) * info->channels * 2;
		char* data = new char[data_size];

		while (size < data_size)
		{
			result = ov_read(&ogg_file, data + size, data_size - size, 0, 2, 1, &section);
			if (result > 0)
			{
				size += result;
			}
			else if (result < 0)
			{
				delete [] data;
				fprintf(stderr, "OGG file problem %s\n", pszFilePath);
				return -1;
			}
			else
			{
				break;
			}
		}

		if (size == 0)
		{
			delete [] data;
			fprintf(stderr, "Unable to read OGG data\n");
			return -1;
		}

		// clear al errors
		checkALError("createBufferFromOGG");

	    // Load audio data into a buffer.
	    alGenBuffers(1, &buffer);

	    if (checkALError("createBufferFromOGG") != AL_NO_ERROR)
	    {
	        fprintf(stderr, "Couldn't generate a buffer for OGG file\n");
	        delete [] data;
	        return buffer;
	    }

		alBufferData(buffer, format, data, data_size, info->rate);
		checkALError("createBufferFromOGG");

		delete [] data;
		ov_clear(&ogg_file);

		return buffer;
	}
Exemple #24
0
static void * ogg_player_thread(private_data_ogg * priv)
{
	int		first_time = 1;
	long	ret;

	int		offs;
	u_int	*buff;

	//init
	LWP_InitQueue(&oggplayer_queue);

	priv[0].vi = ov_info(&priv[0].vf, -1);

	ASND_Pause(0);

	priv[0].pcm_indx = 0;
	priv[0].pcmout_pos = 0;
	priv[0].eof = 0;
	priv[0].flag = 0;
	priv[0].current_section = 0;

	ogg_thread_running = 1;

	while (!priv[0].eof && ogg_thread_running)
	{
		if (priv[0].flag)
			LWP_ThreadSleep(oggplayer_queue); // wait only when i have samples to send

		if (priv[0].flag == 0) // wait to all samples are sent
		{
			if (ASND_TestPointer(0, priv[0].pcmout[priv[0].pcmout_pos])
					&& ASND_StatusVoice(0) != SND_UNUSED)
			{
				priv[0].flag |= 64;
				continue;
			}
			if (priv[0].pcm_indx < READ_SAMPLES)
			{
				priv[0].flag = 3;

				if (priv[0].seek_time >= 0)
				{
					ov_time_seek(&priv[0].vf, priv[0].seek_time);
					priv[0].seek_time = -1;
				}

				ret
						= ov_read(
								&priv[0].vf,
								(void*)&priv[0].pcmout[priv[0].pcmout_pos][priv[0].pcm_indx],
								MAX_PCMOUT,/*0,2,1,*/&priv[0].current_section);

				priv[0].flag &= 192;
				if (ret == 0)
				{
					/* EOF */
					if (priv[0].mode & 1)
						ov_pcm_seek(&priv[0].vf, ogg_loop_start); // repeat
					else
						priv[0].eof = 1; // stops
				}
				else if (ret < 0)
				{
					/* error in the stream.  Not a problem, just reporting it in
					 case we (the app) cares.  In this case, we don't. */
					if (ret != OV_HOLE)
					{
						if (priv[0].mode & 1)
							ov_time_seek(&priv[0].vf, 0); // repeat
						else
							priv[0].eof = 1; // stops
					}
				}
				else
				{
					/* we don't bother dealing with sample rate changes, etc, but you'll have to*/

					// Reverse stereo fix added by Lameguy64/TheCodingBrony
					if (priv[0].vi->channels == 2) {
						buff=(u_int*)&priv[0].pcmout[priv[0].pcmout_pos][priv[0].pcm_indx];
						for(offs=0; offs<ret/4; offs+=1) {
							buff[offs] = SWAPINT(buff[offs]);
						}
					}

					priv[0].pcm_indx += ret >> 1; //get 16 bits samples

				}
			}
			else
				priv[0].flag = 1;
		}
int slimaudio_decoder_vorbis_process(slimaudio_t *audio) {
	int err;
	
	assert(audio != NULL);

	DEBUGF("slimaudio_decoder_vorbis_process: start\n");
	
	ov_callbacks callbacks;
	callbacks.read_func = vorbis_read_func;
	callbacks.seek_func = vorbis_seek_func;
	callbacks.close_func = vorbis_close_func;
	callbacks.tell_func = vorbis_tell_func;	

	audio->decoder_end_of_stream = false;
	
    if ((err = ov_open_callbacks(audio, &audio->oggvorbis_file, NULL, 0, callbacks)) < 0) {
    	fprintf(stderr, "Error in ov_open_callbacks %i\n", err);
    	return -1;	
    }
	
	int bytes_read;
	int current_bitstream;
	char buffer[AUDIO_CHUNK_SIZE];
	
	do {
#ifdef __BIG_ENDIAN__
		bytes_read = ov_read(&audio->oggvorbis_file, buffer, AUDIO_CHUNK_SIZE, 1, 2, 1, &current_bitstream);
#else /* __LITTLE_ENDIAN__ */
		bytes_read = ov_read(&audio->oggvorbis_file, buffer, AUDIO_CHUNK_SIZE, 0, 2, 1, &current_bitstream);
#endif
		switch (bytes_read) {
		case OV_HOLE:
		case OV_EBADLINK:
	    	fprintf(stderr, "Error decoding vorbis stream\n");
			goto vorbis_error;
		
		case 0: // End of file	
			break;
			
		default:
			slimaudio_buffer_write(audio->output_buffer, buffer, bytes_read);
		}

	} while (bytes_read > 0);
	
	if ((err = ov_clear(&audio->oggvorbis_file)) < 0) {
		fprintf(stderr, "Error in ov_clear %i\n", err);
		return -1;	
	}

	DEBUGF("slimaudio_decoder_vorbis_process: end\n");

	return 0;
	
vorbis_error:
	if ((err = ov_clear(&audio->oggvorbis_file)) < 0) {
		fprintf(stderr, "Error in ov_clear %i\n", err);
		return -1;	
	}

	return -1;
}
SoundBuffer* loadOggFile(const std::string &filepath)
{
	int endian = 0; // 0 for Little-Endian, 1 for Big-Endian
	int bitStream;
	long bytes;
	char array[BUFFER_SIZE]; // Local fixed size array
	vorbis_info *pInfo;
	OggVorbis_File oggFile;
	
	// Do a dumb-ass static string copy for old versions of ov_fopen
	// because they expect a non-const char*
	char nonconst[10000];
	snprintf(nonconst, 10000, "%s", filepath.c_str());
	// Try opening the given file
	//if(ov_fopen(filepath.c_str(), &oggFile) != 0)
	if(ov_fopen(nonconst, &oggFile) != 0)
	{
		infostream<<"Audio: Error opening "<<filepath<<" for decoding"<<std::endl;
		return NULL;
	}

	SoundBuffer *snd = new SoundBuffer;

	// Get some information about the OGG file
	pInfo = ov_info(&oggFile, -1);

	// Check the number of channels... always use 16-bit samples
	if(pInfo->channels == 1)
		snd->format = AL_FORMAT_MONO16;
	else
		snd->format = AL_FORMAT_STEREO16;

	// The frequency of the sampling rate
	snd->freq = pInfo->rate;

	// Keep reading until all is read
	do
	{
		// Read up to a buffer's worth of decoded sound data
		bytes = ov_read(&oggFile, array, BUFFER_SIZE, endian, 2, 1, &bitStream);

		if(bytes < 0)
		{
			ov_clear(&oggFile);
			infostream<<"Audio: Error decoding "<<filepath<<std::endl;
			return NULL;
		}

		// Append to end of buffer
		snd->buffer.insert(snd->buffer.end(), array, array + bytes);
	} while (bytes > 0);

	alGenBuffers(1, &snd->buffer_id);
	alBufferData(snd->buffer_id, snd->format,
			&(snd->buffer[0]), snd->buffer.size(),
			snd->freq);

	ALenum error = alGetError();

	if(error != AL_NO_ERROR){
		infostream<<"Audio: OpenAL error: "<<alErrorString(error)
				<<"preparing sound buffer"<<std::endl;
	}

	infostream<<"Audio file "<<filepath<<" loaded"<<std::endl;

	// Clean up!
	ov_clear(&oggFile);

	return snd;
}
f_cnt_t SampleBuffer::decodeSampleOGGVorbis( const char * _f,
						int_sample_t * & _buf,
						ch_cnt_t & _channels,
						sample_rate_t & _samplerate )
{
	static ov_callbacks callbacks =
	{
		qfileReadCallback,
		qfileSeekCallback,
		qfileCloseCallback,
		qfileTellCallback
	} ;

	OggVorbis_File vf;

	f_cnt_t frames = 0;

	QFile * f = new QFile( _f );
	if( f->open( QFile::ReadOnly ) == false )
	{
		delete f;
		return 0;
	}

	int err = ov_open_callbacks( f, &vf, NULL, 0, callbacks );

	if( err < 0 )
	{
		switch( err )
		{
			case OV_EREAD:
				printf( "SampleBuffer::decodeSampleOGGVorbis():"
						" media read error\n" );
				break;
			case OV_ENOTVORBIS:
/*				printf( "SampleBuffer::decodeSampleOGGVorbis():"
					" not an Ogg Vorbis file\n" );*/
				break;
			case OV_EVERSION:
				printf( "SampleBuffer::decodeSampleOGGVorbis():"
						" vorbis version mismatch\n" );
				break;
			case OV_EBADHEADER:
				printf( "SampleBuffer::decodeSampleOGGVorbis():"
					" invalid Vorbis bitstream header\n" );
				break;
			case OV_EFAULT:
				printf( "SampleBuffer::decodeSampleOgg(): "
					"internal logic fault\n" );
				break;
		}
		delete f;
		return 0;
	}

	ov_pcm_seek( &vf, 0 );

   	_channels = ov_info( &vf, -1 )->channels;
   	_samplerate = ov_info( &vf, -1 )->rate;

	ogg_int64_t total = ov_pcm_total( &vf, -1 );

	_buf = new int_sample_t[total * _channels];
	int bitstream = 0;
	long bytes_read = 0;

	do
	{
		bytes_read = ov_read( &vf, (char *) &_buf[frames * _channels],
					( total - frames ) * _channels *
							BYTES_PER_INT_SAMPLE,
					isLittleEndian() ? 0 : 1,
					BYTES_PER_INT_SAMPLE, 1, &bitstream );
		if( bytes_read < 0 )
		{
			break;
		}
		frames += bytes_read / ( _channels * BYTES_PER_INT_SAMPLE );
	}
	while( bytes_read != 0 && bitstream == 0 );

	ov_clear( &vf );
	// if buffer isn't empty, convert it to float and write it down

	if ( frames > 0 && _buf != NULL )
	{
		convertIntToFloat ( _buf, frames, _channels);
	}

	return frames;
}
Exemple #28
0
SoundID Audio::addSound(const char *fileName, unsigned int flags){
	Sound sound;

	// Clear error flag
	alGetError();

	const char *ext = strrchr(fileName, '.') + 1;
	char str[256];
	if (stricmp(ext, "ogg") == 0){
		FILE *file = fopen(fileName, "rb");
		if (file == NULL){
			sprintf(str, "Couldn't open \"%s\"", fileName);
			ErrorMsg(str);
			return SOUND_NONE;
		}

		OggVorbis_File vf;
		memset(&vf, 0, sizeof(vf));
		if (ov_open(file, &vf, NULL, 0) < 0){
			fclose(file);
			sprintf(str, "\"%s\" is not an ogg file", fileName);
			ErrorMsg(str);
			return SOUND_NONE;
		}

		vorbis_info *vi = ov_info(&vf, -1);

		int nSamples = (uint) ov_pcm_total(&vf, -1);
		int nChannels = vi->channels;
		sound.format = nChannels == 1? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
		sound.sampleRate = vi->rate;

		sound.size = nSamples * nChannels;

		sound.samples = new short[sound.size];
		sound.size *= sizeof(short);

		int samplePos = 0;
		while (samplePos < sound.size){
			char *dest = ((char *) sound.samples) + samplePos;

			int bitStream, readBytes = ov_read(&vf, dest, sound.size - samplePos, 0, 2, 1, &bitStream);
			if (readBytes <= 0) break;
			samplePos += readBytes;
		}

		ov_clear(&vf);

	} else {
		ALboolean al_bool;
		ALvoid *data;
		alutLoadWAVFile(fileName, &sound.format, &data, &sound.size, &sound.sampleRate, &al_bool);
		sound.samples = (short *) data;
	}

	alGenBuffers(1, &sound.buffer);
	alBufferData(sound.buffer, sound.format, sound.samples, sound.size, sound.sampleRate);
	if (alGetError() != AL_NO_ERROR){
		alDeleteBuffers(1, &sound.buffer);

		sprintf(str, "Couldn't open \"%s\"", fileName);
		ErrorMsg(str);
		return SOUND_NONE;
	}

	return insertSound(sound);
}
Exemple #29
0
/* *callback(...)
 *
 * this procedure is called by the streaming server when it needs more PCM data
 * for internal buffering
 */
static void *callback(snd_stream_hnd_t hnd, int size, int * size_out)
{
#ifdef TIMING_TESTS
	int decoded_bytes = 0;
	uint32 s_s, s_ms, e_s, e_ms;
#endif

	// printf("sndoggvorbis: callback requested %d bytes\n",size);

	/* Check if the callback requests more data than our buffer can hold */
	if (size > BUF_SIZE)
		size = BUF_SIZE;

#ifdef TIMING_TESTS
	timer_ms_gettime(&s_s, &s_ms);
#endif

	/* Shift the last data the AICA driver took out of the PCM Buffer */
	if (last_read > 0) {
		pcm_count -= last_read;
		if (pcm_count < 0)
			pcm_count=0; /* Don't underrun */
		/* printf("memcpy(%08x, %08x, %d (%d - %d))\n",
			pcm_buffer, pcm_buffer+last_read, pcm_count-last_read, pcm_count, last_read); */
		memcpy(pcm_buffer, pcm_buffer+last_read, pcm_count);
		pcm_ptr = pcm_buffer + pcm_count;
	}

	/* If our buffer has not enough data to fulfill the callback decode 4 KB
	 * chunks until we have enough PCM samples buffered
	 */
	// printf("sndoggvorbis: fill buffer if not enough data\n");
	long pcm_decoded = 0;
	while(pcm_count < size) {
		//int pcm_decoded =  VorbisFile_decodePCMint8(v_headers, pcm_ptr, 4096);
		pcm_decoded = ov_read(&vf, pcm_ptr, 4096, &current_section);

		/* Are we at the end of the stream? If so and looping is
		   enabled, then go ahead and seek back to the first. */
		if (pcm_decoded == 0 && sndoggvorbis_loop) {
			/* Seek back */
			if (ov_raw_seek(&vf, 0) < 0) {
				dbglog(DBG_ERROR, "sndoggvorbis: can't ov_raw_seek to the beginning!\n");
			} else {
				/* Try again */
				pcm_decoded = ov_read(&vf, pcm_ptr, 4096, &current_section);
			}
		}

#ifdef TIMING_TESTS
		decoded_bytes += pcm_decoded;
#endif
		// printf("pcm_decoded is %d\n", pcm_decoded);
		pcm_count += pcm_decoded;
		pcm_ptr += pcm_decoded;

		//if (pcm_decoded == 0 && check_for_reopen() < 0)
		//	break;
		if (pcm_decoded == 0)
			break;
	}
	if (pcm_count > size)
		*size_out = size;
	else
		*size_out = pcm_count;

	/* Let the next callback know how many bytes the last callback grabbed
	 */
	last_read = *size_out;

#ifdef TIMING_TESTS
	if (decoded_bytes != 0) {
		int t;
		timer_ms_gettime(&e_s, &e_ms);
		t = ((int)e_ms - (int)s_ms) + ((int)e_s - (int)s_s) * 1000;
		printf("%dms for %d bytes (%.2fms / byte)\n", t, decoded_bytes, t*1.0f/decoded_bytes);
	}
#endif

	// printf("sndoggvorbis: callback: returning\n");

	if (pcm_decoded == 0)
		return NULL;
	else
		return pcm_buffer;
}
Exemple #30
0
bool OggPlayer::OpenOgg( const char *filename )
{
    if (!bInitialized)
        return false;

    if (bFileOpened)
        Close();

    FILE    *f;

    f = fopen(filename, "rb");
    if (!f) return false;

	ov_open(f, &vf, NULL, 0);

    // ok now the tricky part

    // the vorbis_info struct keeps the most of the interesting format info
    vorbis_info *vi = ov_info(&vf,-1);
	vorbis_comment *vc = ov_comment(&vf, 0);
	nLoopStart = 0;
	nLoopEnd = 0;

	if (vc != NULL) {
		for (int i = 0; i < ARRAYLEN(loop_start_tags); i++) {
			char *value = vorbis_comment_query(vc, loop_start_tags[i], 0);
			if (value != NULL) {
				nLoopStart = atoi(value);
			}
		}
		for (int i = 0; i < ARRAYLEN(loop_end_tags); i++) {
			char *value = vorbis_comment_query(vc, loop_end_tags[i], 0);
			if (value != NULL) {
				nLoopEnd = atoi(value);
			}
		}
	}

	if (nLoopEnd <= nLoopStart) {
		nLoopEnd = ov_pcm_total(&vf, -1);
	}

    // set the wave format
	WAVEFORMATEX	    wfm;

    memset(&wfm, 0, sizeof(wfm));

    wfm.cbSize          = sizeof(wfm);
    wfm.nChannels       = vi->channels;
    wfm.wBitsPerSample  = 16;                    // ogg vorbis is always 16 bit
    wfm.nSamplesPerSec  = vi->rate;
    wfm.nAvgBytesPerSec = wfm.nSamplesPerSec*wfm.nChannels*2;
    wfm.nBlockAlign     = 2*wfm.nChannels;
    wfm.wFormatTag      = 1;


    // set up the buffer
	DSBUFFERDESC desc;

	desc.dwSize         = sizeof(desc);
	desc.dwFlags        = DSBCAPS_CTRLVOLUME;
	desc.lpwfxFormat    = &wfm;
	desc.dwReserved     = 0;

    desc.dwBufferBytes  = BUFSIZE*2;
    pDS->CreateSoundBuffer(&desc, &pDSB, NULL );

    // fill the buffer

    DWORD   pos = 0;
    int     sec = 0;
    int     ret = 1;
    DWORD   size = BUFSIZE*2;

    char    *buf;

    pDSB->Lock(0, size, (LPVOID*)&buf, &size, NULL, NULL, DSBLOCK_ENTIREBUFFER);
    
    // now read in the bits
    while(ret && pos<size)
    {
        ret = ov_read(&vf, buf+pos, size-pos, 0, 2, 1, &sec);
        pos += ret;
    }

	pDSB->Unlock( buf, size, NULL, NULL );

    nCurSection         =
    nLastSection        = 0;

    return bFileOpened = true;
}