Example #1
0
VorbisStream::~VorbisStream() {
	ov_clear(&_ovFile);
}
Example #2
0
static int plugin_run(struct playerHandles *ph, char *key, int *totaltime){
	size_t size;
	long ret;
	const ssize_t len=1600;
	char buf[len];  /* input buffer  */
	unsigned int total=0;
	int channels, enc, retval=DEC_RET_SUCCESS;
	unsigned int rate;
	vorbis_info *vi;
	OggVorbis_File *vf;
	struct outputdetail *details=ph->outdetail;
	int sizemod;
	char tail[OUTPUT_TAIL_SIZE];

	if(!(vf=malloc(sizeof(OggVorbis_File)))){
		fprintf(stderr,"Malloc failed (vf).");
		return DEC_RET_ERROR;
	}

	if(ov_open_callbacks(ph->ffd,vf,NULL,0,OV_CALLBACKS_NOCLOSE)<0){
		fprintf(stderr,"ov open failed\n");
		free(vf);
		return DEC_RET_ERROR;
	}
	details->totaltime=*totaltime;
	details->percent=-1;

	vi=ov_info(vf,-1);
	rate=(unsigned int)vi->rate;
	channels=(unsigned int)vi->channels;
	enc=16;

	sizemod=2*channels;

	snprintf(tail,OUTPUT_TAIL_SIZE,"New format: %dHz %dch %dbps",rate, channels, (int)vi->bitrate_nominal);
	addStatusTail(tail,ph->outdetail);
	snd_param_init(ph,&enc,&channels,&rate);

	h.vf=vf;
	h.total=&total;
	h.rate=rate;
	h.sizemod=sizemod;
	ph->dechandle=&h;

	details->percent=-1;

	do{ /* Read and write until everything is through. */
		if((ret=ov_read(vf,buf,len,0,2,1,&vf->current_link))<1){
			if((retval=vorbStatus(ret))==VORB_CONTINUE)
				continue;
			break;
		}
		size=ret;
		details->curtime=total/(rate*sizemod);
		if(details->totaltime>0)
			details->percent=(details->curtime*100)/details->totaltime;
		crOutput(ph->pflag,details);

#if WITH_ALSA==1
		if(writei_snd(ph,buf,size/sizemod)<0)break;
#else
		if(writei_snd(ph,buf,size)<0)break;
#endif
		total+=size;

		if(ph->pflag->exit!=DEC_RET_SUCCESS){
			retval=ph->pflag->exit;
			break;
		}
	}while(1);
	writei_snd(ph,NULL,0); // drain sound buffer

	/* Done decoding, now just clean up and leave. */
	ov_clear(vf);
	*totaltime=details->curtime;
	return retval;
}
bool MkSoundBuffer::_CreateBufferFromOggFile(LPDIRECTSOUND directSound, const MkByteArray& srcData)
{
	OggVorbis_File vorbisFile;
	::ZeroMemory(&vorbisFile, sizeof(OggVorbis_File));

	do
	{
		MkInterfaceForDataReading drInterface;
		if (!drInterface.SetUp(srcData, 0))
			break;

		// vorbis file 오픈
		ov_callbacks ogg_callbacks = { _read_func, _seek_func, _close_func, _tell_func };
		if (ov_open_callbacks(reinterpret_cast<void*>(&drInterface), &vorbisFile, NULL, 0, ogg_callbacks) != 0)
			break;

		// 구조 정보
		vorbis_info* vorbisInfo = ov_info(&vorbisFile, -1);
		if (vorbisInfo == NULL)
			break;

		// 버퍼 확보
		int dataSize = vorbisInfo->channels * 16 / 8 * static_cast<int>(ov_pcm_total(&vorbisFile, -1));
		if (dataSize <= 0)
			break;

		MkByteArray dataBuffer;
		dataBuffer.Fill(static_cast<unsigned int>(dataSize));

		// PCM 블록 읽으며 디코딩
		int bitstream, readSize = 0, writeSize = 0;
		while (true)
		{
			writeSize = ov_read(&vorbisFile, reinterpret_cast<char*>(dataBuffer.GetPtr()) + readSize, dataSize - readSize, 0, 2, 1, &bitstream);

			if(writeSize == 0) // EOF
				break;

			if ((dataSize - readSize) >= 0) // continue
			{
				readSize += writeSize;
			}
			else // 디코딩 실패
			{
				writeSize = -1;
				break;
			}
		}

		if (writeSize < 0)
			break;

		// wave 정보 세팅
		WAVEFORMATEX waveFormatEx;
		waveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
		waveFormatEx.nChannels = vorbisInfo->channels;
		waveFormatEx.nSamplesPerSec = vorbisInfo->rate;
		waveFormatEx.nAvgBytesPerSec = vorbisInfo->channels * vorbisInfo->rate * 16 / 8; // 채널 * 주파수 * 진폭 / 8(bit>byte)
		waveFormatEx.nBlockAlign = vorbisInfo->channels * 16 / 8;
		waveFormatEx.wBitsPerSample = 16;
		waveFormatEx.cbSize = 0;

		// 사운드 버퍼 생성 후 데이터 복사
		m_SoundBuffer = _CreateSoundBuffer(directSound, waveFormatEx, dataBuffer);
	}
	while (false);

	ov_clear(&vorbisFile);
	return (m_SoundBuffer != NULL);
}
CDAFReader_Vorbis::~CDAFReader_Vorbis()
{
 ov_clear(&ovfile);
}
Example #5
0
void sound_closeSample (SoundSample * sample){
	free (sample->data);
	ov_clear (&sample->s_file.oggFile);
	free (sample);
}
Example #6
0
bool cOAL_OggSample::CreateFromFile(const wstring &asFilename)
{
	DEF_FUNC_NAME("cOAL_OggSample::Load()");
	FUNC_USES_AL;

	if(mbStatus==false)
		return false;

	Reset();
	
	char *pPCMBuffer;
	bool bEOF = false;
	int lOpenResult;
	int lCurrent_section;
	long lDataSize = 0;

	msFilename = asFilename;

	FILE *fileHandle = OpenFileW(asFilename, L"rb");
	
	// If no file is present, set the error status and return
	if(!fileHandle)
	{
		mbStatus = false;
		return false;
	}

	// If not an Ogg file, set status and exit
	OggVorbis_File ovFileHandle;
	if((lOpenResult = ov_open_callbacks(fileHandle, &ovFileHandle, NULL, 0, gCallbacks))<0)	
	{
		fclose ( fileHandle );
		mbStatus = false;
		return false;
	}

	// Get file info
	vorbis_info *viFileInfo = ov_info ( &ovFileHandle, -1 );
	mlChannels = viFileInfo->channels;
	mFormat = (mlChannels == 2)?AL_FORMAT_STEREO16:AL_FORMAT_MONO16;
	mlFrequency = viFileInfo->rate;
	mlSamples = (long) ov_pcm_total ( &ovFileHandle, -1 );
	mfTotalTime = ov_time_total( &ovFileHandle, -1 );

	// Reserve memory for 'mlChannels' channels of 'mlSamples' * 2 bytes of data each
	int lSizeInBytes = mlSamples * mlChannels * GetBytesPerSample();
	pPCMBuffer = (char *) malloc (lSizeInBytes);
	memset (pPCMBuffer, 0, lSizeInBytes);

	// Loop which loads chunks of decoded data into a buffer
	while(!bEOF)
	{
		long lChunkSize = ov_read ( &ovFileHandle			,										
									pPCMBuffer + lDataSize	, 
									STREAMING_BLOCK_SIZE	, 
									SYS_ENDIANNESS			,
									2, 1, &lCurrent_section );

		if(lChunkSize == 0)
			bEOF = true;
		// If we get a negative value, then something went wrong. Clean up and set error status.
		else if(lChunkSize < 0)
		{
			free(pPCMBuffer);
			ov_clear(&ovFileHandle);
			// ov_clear closes the file handle for us
			mbStatus = false;
			return false;
		}
		else 
			lDataSize += lChunkSize;
	}

	cOAL_Buffer* pBuffer = mvBuffers[0];
	if(lDataSize)
	{
		// If something went wrong, set error status. Clean up afterwards.
		mbStatus = pBuffer->Feed((ALvoid*)pPCMBuffer, lDataSize);
	}
	free(pPCMBuffer);
	ov_clear(&ovFileHandle);
	// ov_clear closes the file handle for us

	return true;
}
Example #7
0
// BGMの読み込み(ogg)
HRESULT Audio::LoadBGM( LPSTR fileName ){
	// oggファイル
	OggVorbis_File ovf;

	// エラー処理用
	HRESULT hr;

	// ファイルを開く
	if( ov_fopen( fileName, &ovf ) != 0 ){
		return E_FAIL;
	}

	// oggファイルの音声フォーマットを取得
	vorbis_info* oggInfo = ov_info(&ovf, -1);

	// Waveファイルの読み込み
	WAVEFORMATEX format		= {};
	format.wFormatTag		= WAVE_FORMAT_PCM;
	format.nChannels		= static_cast<WORD>(oggInfo->channels);
	format.wBitsPerSample	= 16;
	format.nSamplesPerSec	= oggInfo->rate;
	format.nBlockAlign		= format.wBitsPerSample / 8 * format.nChannels;
    format.nAvgBytesPerSec	= format.nSamplesPerSec * format.nBlockAlign;

	// IXAudio2SourceVoiceの初期化
	hr = IXAudioDevice::Instance().GetXAudio2()->CreateSourceVoice( &m_pSourceVoice, &format );
	if( FAILED( hr ) ){
		return E_FAIL;
	}

	// ファイルの終端まで読み込む
	std::vector<char> tempm_WaveData(4096,0);
	int readSize = 0;
	int comSize = 0;

	while(1){
		// PCMデータ読み込み
		readSize = ov_read( &ovf, &tempm_WaveData[0], tempm_WaveData.size(), 0, 2, 1, NULL );
	
		// 読み込めなかった
		if( readSize == OV_HOLE || readSize == OV_EBADLINK ){
			ov_clear( &ovf );
			return E_FAIL;
		}
		// 全て読み込み終わった
		if( readSize == 0 ){
			break;
		}
		// 音声ファイルデータを拡張 
		m_WaveData.resize( m_WaveData.size() + readSize );
		// メモリのコピー
		memcpy( &m_WaveData[0] + comSize, &tempm_WaveData[0] ,readSize );
		// 読み込みバイト数変更
		comSize += readSize;
	}

	// 読み込んだファイルをバッファに送る
	const XAUDIO2_BUFFER buffer = {
		XAUDIO2_END_OF_STREAM,
		m_WaveData.size(),
		&m_WaveData[0],
		0,
        0,
        XAUDIO2_NO_LOOP_REGION,
        0,
        XAUDIO2_LOOP_INFINITE,
        nullptr
    };
	hr = m_pSourceVoice->SubmitSourceBuffer( &buffer );
	if( FAILED( hr ) ){
		// ファイルの解放
		ov_clear(&ovf);
		return E_FAIL;
	}

	// ファイルの解放
	ov_clear(&ovf);

	return S_OK;
}
RageSoundReader_Vorbisfile::~RageSoundReader_Vorbisfile()
{
	if(vf)
		ov_clear(vf);
	delete vf;
}
Example #9
0
VorbisStream::~VorbisStream() {
	ov_clear(&_ovFile);
	if (_disposeAfterUse == DisposeAfterUse::YES)
		delete _inStream;
}
Example #10
0
SourceFileOggVorbis::~SourceFileOggVorbis()
{
	ov_clear( &mOggVorbisFile );
}
Example #11
0
bool C4MusicFileOgg::Init(const char *strFile)
{
	// Clear previous
	Clear();
	// Base init file
	if (!C4MusicFile::Init(strFile)) return false;
	// Prepare ogg reader
	vorbis_info* info;
	memset(&ogg_file, 0, sizeof(ogg_file));
	ov_callbacks callbacks;
	// Initial file loading
	// For packed groups, the whole compressed file is kept in memory because reading/seeking inside C4Group is problematic. Uncompress while playing.
	// This increases startup time a bit.
	// Later, this could be replaced with proper random access in c4group. Either replacing the file format or e.g. storing the current zlib state here
	//  and then updating callbacks.read/seek/close/tell_func to read data from the group directly as needed
	bool is_loading_from_file = FileExists(strFile);
	void *data_source;
	if (!is_loading_from_file)
	{
		char *file_contents;
		size_t file_size;
		if (!C4Group_ReadFile(FileName, &file_contents, &file_size))
			return false;
		data.SetOwnedData((BYTE *)file_contents, file_size);
		// C4Group preloaded ogg reader
		callbacks.read_func = &::C4SoundLoaders::VorbisLoader::mem_read_func;
		callbacks.seek_func = &::C4SoundLoaders::VorbisLoader::mem_seek_func;
		callbacks.close_func = &::C4SoundLoaders::VorbisLoader::mem_close_func;
		callbacks.tell_func = &::C4SoundLoaders::VorbisLoader::mem_tell_func;
		data_source = &data;
	}
	else
	{
		// Load directly from file
		if (!source_file.Open(FileName))
			return false;
		// Uncompressed file ogg reader
		callbacks.read_func = &::C4SoundLoaders::VorbisLoader::file_read_func;
		callbacks.seek_func = &::C4SoundLoaders::VorbisLoader::file_seek_func;
		callbacks.close_func = &::C4SoundLoaders::VorbisLoader::file_close_func;
		callbacks.tell_func = &::C4SoundLoaders::VorbisLoader::file_tell_func;
		data_source = this;
	}

	// open using callbacks either to memory or to file loader
	if (ov_open_callbacks(data_source, &ogg_file, NULL, 0, callbacks) != 0)
	{
		ov_clear(&ogg_file);
		return false;
	}

	// get information about music
	info = ov_info(&ogg_file, -1);
	if (info->channels == 1)
		ogg_info.format = AL_FORMAT_MONO16;
	else
		ogg_info.format = AL_FORMAT_STEREO16;
	ogg_info.sample_rate = info->rate;
	ogg_info.sample_length = ov_time_total(&ogg_file, -1) / 1000.0;
	
	// Get categories from ogg comment header
	vorbis_comment *comment = ov_comment(&ogg_file, -1);
	const char *comment_id = "COMMENT=";
	int comment_id_len = strlen(comment_id);
	for (int i = 0; i < comment->comments; ++i)
	{
		if (comment->comment_lengths[i] > comment_id_len)
		{
			if (SEqual2NoCase(comment->user_comments[i], comment_id, comment_id_len))
			{
				// Add all categories delimeted by ';'
				const char *categories_string = comment->user_comments[i] + comment_id_len;
				for (;;)
				{
					int delimeter = SCharPos(';', categories_string);
					StdCopyStrBuf category;
					category.Copy(categories_string, delimeter >= 0 ? delimeter : SLen(categories_string));
					categories.push_back(category);
					if (delimeter < 0) break;
					categories_string += delimeter+1;
				}
			}
		}
	}

	// File not needed for now
	UnprepareSourceFileReading();

	// mark successfully loaded
	return loaded = true;
}
Example #12
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");
	
}
Example #13
0
static int ogg_get_song_info(char *filename, MusicInfo *music_info)
{
	int														status = 3;
	FILE														*file;
	unsigned long												file_length;
	int														bitrate;
	double													song_time;
	OggVorbis_File											temp_ogg;
		
	PE_DBG_PRINTF("MusicEngine: ==> ogg_get_song_info()! \n");
	
	
	if ((!filename) || (!music_info) || (!ogg_file))
	{
		PE_DBG_PRINTF("MusicEngine: ogg_get_song_info() invalid parameter filename or music_info or ogg_file!\n");
		return -1;
	}

#ifndef ENABLE_PE_CACHE
	file = fopen(filename, "rb");               // get_song_info打开文件
	if (!file)
	{
		PE_DBG_PRINTF("MusicEngine: ogg_get_song_info() fopen failed! \n");
		return -1;
	}

	fseek(file, 0, SEEK_END);   
	file_length = ftell(file);
	music_info->file_length = file_length;
	fseek(file, 0, SEEK_SET);
#else
    ogg_info_cache_id = pe_cache_open(filename, NULL, OGG_CACHE_SIZE, OGG_BLOCK_SIZE);
    if (0 > ogg_info_cache_id)
    {
        libc_printf("<%d><%s> pe_cache_open failed!\n", __LINE__, __FUNCTION__);
        return -1;
    }
    file = (FILE *)(((UINT32)ogg_info_cache_id | PE_CACHE_ID_TAG));
    pe_cache_seek(ogg_info_cache_id, 0, SEEK_END);
    file_length = pe_cache_tell(ogg_info_cache_id);
    music_info->file_length = file_length;
    pe_cache_seek(ogg_info_cache_id, 0, SEEK_SET);
#endif
	if(ov_open(file, &temp_ogg, NULL, 0) < 0)       // 如果这里紧跟着调用ov的函数,则里面的文件系统函数都是stdio,不是pe_cache
	{
		PE_DBG_PRINTF("Input does not appear to be an Ogg bitstream.\n");
#ifndef ENABLE_PE_CACHE
        fclose(file);
#else
        pe_cache_close(ogg_info_cache_id);
		ogg_info_cache_id = -1;
#endif
 		return -1;
	}
	song_time = ov_time_total(&temp_ogg, -1);
	if (song_time < 0)
	{
		PE_DBG_PRINTF("Can not get song time from Ogg bitstream.\n");
		song_time = 0;		
	}

	music_info->time = song_time / 1000;

	ov_clear(&temp_ogg);                            // get_song_info完毕,在这里close文件

	PE_DBG_PRINTF("MusicEngine: <== ogg_get_song_info()! \n");
	return status;

}
Example #14
0
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;

	ov_callbacks oggCallbacks;

	OggMemoryFile *vorbisMemoryFile = 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);
	//assert ov_ret>=0;

	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;
	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)
	{
		//ogg size does not match memory buffer
		ov_clear(&vf);
		SafeDelete(vorbisMemoryFile);
		return false;
	}

	//read in 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);

	SafeDelete(vorbisMemoryFile);

	return true;
}
Example #15
0
void Sound::PlayMusic(const boost::filesystem::path& path, int loops /* = 0*/)
{
    ALenum m_openal_error;
    std::string filename = path.string();
    FILE *m_f = 0;
    vorbis_info *vorbis_info;
    m_music_loops = 0;

#ifdef FREEORION_WIN32
    ov_callbacks callbacks = {

    (size_t (*)(void *, size_t, size_t, void *))  fread,

    (int (*)(void *, ogg_int64_t, int))           _fseek64_wrap,

    (int (*)(void *))                             fclose,

    (long (*)(void *))                            ftell

    };
#endif

    if (alcGetCurrentContext() != 0)
    {
        if (m_music_name.size() > 0)
            StopMusic();
       
        if ((m_f = fopen(filename.c_str(), "rb")) != 0) // make sure we CAN open it
        {
#ifdef FREEORION_WIN32
            if (!(ov_test_callbacks(m_f, &m_ogg_file, 0, 0, callbacks))) // check if it's a proper ogg
#else
            if (!(ov_test(m_f, &m_ogg_file, 0, 0))) // check if it's a proper ogg
#endif
            {
                ov_test_open(&m_ogg_file); // it is, now fully open the file
                /* now we need to take some info we will need later */
                vorbis_info = ov_info(&m_ogg_file, -1);
                if (vorbis_info->channels == 1)
                    m_ogg_format = AL_FORMAT_MONO16;
                else
                    m_ogg_format = AL_FORMAT_STEREO16;
                m_ogg_freq = vorbis_info->rate;
                m_music_loops = loops;
                /* fill up the buffers and queue them up for the first time */
                if (!RefillBuffer(&m_ogg_file, m_ogg_format, m_ogg_freq, m_music_buffers[0], BUFFER_SIZE, m_music_loops))
                {
                    alSourceQueueBuffers(m_sources[0],1,&m_music_buffers[0]); // queue up the buffer if we manage to fill it
                    if (!RefillBuffer(&m_ogg_file, m_ogg_format, m_ogg_freq, m_music_buffers[1], BUFFER_SIZE, m_music_loops))
                    {
                        alSourceQueueBuffers(m_sources[0],1,&m_music_buffers[1]);
                        m_music_name = filename; // yup, we're playing something that takes up more than 2 buffers
                    }
                    else
                    {
                        m_music_name.clear();  // m_music_name.clear() must always be called before ov_clear. Otherwise
                    }
                    alSourcePlay(m_sources[0]); // play if at least one buffer is queued
                }
                else
                {
                    m_music_name.clear();  // m_music_name.clear() must always be called before ov_clear. Otherwise
                }
            }
            else
            {
                Logger().errorStream() << "PlayMusic: unable to open file " << filename.c_str() << " possibly not a .ogg vorbis file. Aborting\n";
                m_music_name.clear(); //just in case
                ov_clear(&m_ogg_file);
            }
        }
        else
            Logger().errorStream() << "PlayMusic: unable to open file " << filename.c_str() << " I/O Error. Aborting\n";
    }
    m_openal_error = alGetError();
    if (m_openal_error != AL_NONE)
        Logger().errorStream() << "PlayMusic: OpenAL ERROR: " << alGetString(m_openal_error);
}
Example #16
0
OPAL_SOUND_MGR bool SoundManager::loadOGGFile(std::string fileName, std::vector<char> &buffer,
											  ALenum &format, ALsizei &freq)
{
#define BUFFER_SIZE     32768       // 32 KB buffers
	int endian = 0;                         // 0 for Little-Endian, 1 for Big-Endian
	int bitStream;
	long bytes;
	char array[BUFFER_SIZE];                // Local fixed size array
	FILE *f;

	// Open for binary reading
	f = fopen(fileName.c_str(), "rb");

	if (f == NULL)
	{
		std::cout << "Cannot open " << fileName << " for reading..." << std::endl;
		exit(-1);
	}


	vorbis_info *pInfo;
	OggVorbis_File oggFile;

	// Try opening the given file
	if (ov_open(f, &oggFile, NULL, 0) != 0)
	{
		std::cout << "Error opening " << fileName << " for decoding..." << std::endl;
		exit(-1);
	}


	// 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)
		format = AL_FORMAT_MONO16;
	else
		format = AL_FORMAT_STEREO16;


	// The frequency of the sampling rate
	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);
			std::cout << "Error decoding " << fileName << "..." << std::endl;
			exit(-1);
		}
		// Append to end of buffer
		buffer.insert(buffer.end(), array, array + bytes);
	}
	while (bytes > 0);

	// Clean up!
	ov_clear(&oggFile);
	return true;
}
Example #17
0
void Sound::PlaySound(const boost::filesystem::path& path, bool is_ui_sound/* = false*/)
{
    if (!GetOptionsDB().Get<bool>("UI.sound.enabled") || (is_ui_sound && UISoundsTemporarilyDisabled()))
        return;

    std::string filename = path.string();
    ALuint current_buffer;
    ALenum source_state;
    ALsizei ogg_freq;
    FILE *file = 0;
    int m_i;
    bool found_buffer = true;
    bool found_source = false;

#ifdef FREEORION_WIN32
    ov_callbacks callbacks = {

    (size_t (*)(void *, size_t, size_t, void *))  fread,

    (int (*)(void *, ogg_int64_t, int))           _fseek64_wrap,

    (int (*)(void *))                             fclose,

    (long (*)(void *))                            ftell

    };
#endif

    if (alcGetCurrentContext() != 0)
    {
        /* First check if the sound data of the file we want to play is already buffered somewhere */
        std::map<std::string, ALuint>::iterator it = m_buffers.find(filename);
        if (it != m_buffers.end())
            current_buffer = it->second;
        else {
            if ((file = fopen(filename.c_str(), "rb")) != 0) // make sure we CAN open it
            {
                OggVorbis_File ogg_file;
                vorbis_info *vorbis_info;
                ALenum ogg_format;
#ifdef FREEORION_WIN32
                if (!(ov_test_callbacks(file, &ogg_file, 0, 0, callbacks))) // check if it's a proper ogg
#else
                if (!(ov_test(file, &ogg_file, 0, 0))) // check if it's a proper ogg
#endif
                {
                    ov_test_open(&ogg_file); // it is, now fully open the file
                    /* now we need to take some info we will need later */
                    vorbis_info = ov_info(&ogg_file, -1);
                    if (vorbis_info->channels == 1)
                        ogg_format = AL_FORMAT_MONO16;
                    else
                        ogg_format = AL_FORMAT_STEREO16;
                    ogg_freq = vorbis_info->rate;
                    ogg_int64_t byte_size = ov_pcm_total(&ogg_file, -1) * vorbis_info->channels * 2;
                    if (byte_size <= 1024 * 1024 * 1024) {
                        /* fill up the buffers and queue them up for the first time */
                        ALuint sound_handle;
                        alGenBuffers(1, &sound_handle);

                        int loop = 0;

                        RefillBuffer(&ogg_file, ogg_format, ogg_freq, sound_handle, byte_size, loop);

                        current_buffer = sound_handle;
                        m_buffers.insert(std::make_pair(filename, sound_handle));
                    }
                    else
                    {
                        Logger().errorStream() << "PlaySound: unable to open file " << filename.c_str() << " too big to buffer. Aborting\n";
                    }
                    ov_clear(&ogg_file);
                }
                else
                {
                    Logger().errorStream() << "PlaySound: unable to open file " << filename.c_str() << " possibly not a .ogg vorbis file. Aborting\n";
                }
            }
        }
        if (found_buffer) {
            /* Now that we have the buffer, we need to find a source to send it to */
            for (m_i = 1; m_i < NUM_SOURCES; ++m_i) {   // as we're playing sounds we start at 1. 0 is reserved for music
                alGetSourcei(m_sources[m_i],AL_SOURCE_STATE,&source_state);
                if ((source_state != AL_PLAYING) && (source_state != AL_PAUSED)) {
                    found_source = true;
                    alSourcei(m_sources[m_i], AL_BUFFER, current_buffer);
                    alSourcePlay(m_sources[m_i]);
                    break; // so that the sound won't block all the sources
                }
            }
            if (!found_source)
                Logger().errorStream() << "PlaySound: Could not find aviable source - playback aborted\n";
        }
        source_state = alGetError();
        if (source_state != AL_NONE)
            Logger().errorStream() << "PlaySound: OpenAL ERROR: " << alGetString(source_state);
            /* it's important to check for errors, as some functions won't work properly if
             * they're called when there is a unchecked previous error. */
    }
}
/*
================
VorbisStream::ClearStreamData
================
*/
void VorbisStream::ClearStreamData( AudioStreamData *streamData ) {
	ov_clear( &static_cast<VorbisStreamData *>(streamData)->file );
	
	numInUse--;
}
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;
}
Example #20
0
static int OGG_open(Sound_Sample *sample, const char *ext)
{
    int rc;
    double total_time;
    OggVorbis_File *vf;
    vorbis_info *info;
    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;

    vf = (OggVorbis_File *) malloc(sizeof (OggVorbis_File));
    BAIL_IF_MACRO(vf == NULL, ERR_OUT_OF_MEMORY, 0);

    rc = ov_open_callbacks(internal->rw, vf, NULL, 0, RWops_ogg_callbacks);
    if (rc != 0)
    {
#if (defined DEBUG_CHATTER)		
        SNDDBG(("OGG: can't grok data. reason: [%s].\n", ogg_error(rc)));
#endif
        free(vf);
        BAIL_MACRO("OGG: Not valid Ogg Vorbis data.", 0);
    } /* if */

    info = ov_info(vf, -1);
    if (info == NULL)
    {
        ov_clear(vf);
        free(vf);
        BAIL_MACRO("OGG: failed to retrieve bitstream info", 0);
    } /* if */

    output_ogg_comments(vf);
	
    SNDDBG(("OGG: bitstream version == (%d).\n", info->version));
    SNDDBG(("OGG: bitstream channels == (%d).\n", info->channels));
    SNDDBG(("OGG: bitstream sampling rate == (%ld).\n", info->rate));
    SNDDBG(("OGG: seekable == {%s}.\n", ov_seekable(vf) ? "TRUE" : "FALSE"));
    SNDDBG(("OGG: number of logical bitstreams == (%ld).\n", ov_streams(vf)));
    SNDDBG(("OGG: serial number == (%ld).\n", ov_serialnumber(vf, -1)));
    SNDDBG(("OGG: total seconds of sample == (%f).\n", ov_time_total(vf, -1)));

    internal->decoder_private = vf;
    sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
    sample->actual.rate = (uint32_t) info->rate;
    sample->actual.channels = (uint8_t) info->channels;
    total_time = ov_time_total(vf, -1);
    if (OV_EINVAL == total_time)
      internal->total_time = -1;
    else
      internal->total_time = (int32_t)(total_time);


    /*
     * Since we might have more than one logical bitstream in the OGG file,
     *  and these bitstreams may be in different formats, we might be
     *  converting two or three times: once in vorbisfile, once again in
     *  SDL_sound, and perhaps a third time to get it to the sound device's
     *  format. That's wickedly inefficient.
     *
     * To combat this a little, if the user specified a desired format, we
     *  claim that to be the "actual" format of the collection of logical
     *  bitstreams. This means that VorbisFile will do a conversion as
     *  necessary, and SDL_sound will not. If the user didn't specify a
     *  desired format, then we pretend the "actual" format is something that
     *  OGG files are apparently commonly encoded in.
     */
    sample->actual.format = (sample->desired.format == 0) ?
                             AUDIO_S16SYS : sample->desired.format;
    return(1);
} /* OGG_open */
//--------------------------------------------------------------------------------------------
//	Ogg読み込み情報を初期化します
//--------------------------------------------------------------------------------------------
void InitOggData(OggVorbis_File* s_ptr)
{
	if(s_ptr->datasource != NULL){
		ov_clear(s_ptr);
	}
}
Example #22
0
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    ov_callbacks callbacks;
    OggVorbis_File vf;
    ogg_int32_t **pcm;

    int error = CODEC_ERROR;
    long n;
    int current_section;
    int previous_section;
    int eof;
    ogg_int64_t vf_offsets[2];
    ogg_int64_t vf_dataoffsets;
    ogg_uint32_t vf_serialnos;
    ogg_int64_t vf_pcmlengths[2];
    intptr_t param;

#if defined(CPU_ARM) || defined(CPU_COLDFIRE) || defined(CPU_MIPS)
    if (setjmp(rb_jump_buf) != 0) {
        /* malloc failed; finish with this track */
        goto done;
    }
#endif
    ogg_malloc_init();

    /* Create a decoder instance */
    callbacks.read_func = read_handler;
    callbacks.seek_func = initial_seek_handler;
    callbacks.tell_func = tell_handler;
    callbacks.close_func = close_handler;

    ci->seek_buffer(0);

    /* Open a non-seekable stream */
    error = ov_open_callbacks(ci, &vf, NULL, 0, callbacks);

    /* If the non-seekable open was successful, we need to supply the missing
     * data to make it seekable.  This is a hack, but it's reasonable since we
     * don't want to run the whole file through the buffer before we start
     * playing.  Using Tremor's seekable open routine would cause us to do
     * this, so we pretend not to be seekable at first.  Then we fill in the
     * missing fields of vf with 1) information in ci->id3, and 2) info
     * obtained by Tremor in the above ov_open call.
     *
     * Note that this assumes there is only ONE logical Vorbis bitstream in our
     * physical Ogg bitstream.  This is verified in metadata.c, well before we
     * get here.
     */
    if (!error) {
        ogg_free(vf.offsets);
        ogg_free(vf.dataoffsets);
        ogg_free(vf.serialnos);

        vf.offsets = vf_offsets;
        vf.dataoffsets = &vf_dataoffsets;
        vf.serialnos = &vf_serialnos;
        vf.pcmlengths = vf_pcmlengths;

        vf.offsets[0] = 0;
        vf.offsets[1] = ci->id3->filesize;
        vf.dataoffsets[0] = vf.offset;
        vf.pcmlengths[0] = 0;
        vf.pcmlengths[1] = ci->id3->samples;
        vf.serialnos[0] = vf.current_serialno;
        vf.callbacks.seek_func = seek_handler;
        vf.seekable = 1;
        vf.end = ci->id3->filesize;
        vf.ready_state = OPENED;
        vf.links = 1;
    } else {
        DEBUGF("Vorbis: ov_open failed: %d\n", error);
        goto done;
    }

    if (ci->id3->offset) {
        ci->seek_buffer(ci->id3->offset);
        ov_raw_seek(&vf, ci->id3->offset);
        ci->set_elapsed(ov_time_tell(&vf));
        ci->set_offset(ov_raw_tell(&vf));
    }
    else {
        ci->set_elapsed(0);
    }

    previous_section = -1;
    eof = 0;
    while (!eof) {
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        if (action == CODEC_ACTION_SEEK_TIME) {
            if (ov_time_seek(&vf, param)) {
                //ci->logf("ov_time_seek failed");
            }

            ci->set_elapsed(ov_time_tell(&vf));
            ci->seek_complete();
        }

        /* Read host-endian signed 24-bit PCM samples */
        n = ov_read_fixed(&vf, &pcm, 1024, &current_section);

        /* Change DSP and buffer settings for this bitstream */
        if (current_section != previous_section) {
            if (!vorbis_set_codec_parameters(&vf)) {
                goto done;
            } else {
                previous_section = current_section;
            }
        }

        if (n == 0) {
            eof = 1;
        } else if (n < 0) {
            DEBUGF("Vorbis: Error decoding frame\n");
        } else {
            ci->pcmbuf_insert(pcm[0], pcm[1], n);
            ci->set_offset(ov_raw_tell(&vf));
            ci->set_elapsed(ov_time_tell(&vf));
        }
    }

    error = CODEC_OK;
done:
#if 0 /* defined(SIMULATOR) */
    {
        size_t bufsize;
        void* buf = ci->codec_get_buffer(&bufsize);

        DEBUGF("Vorbis: Memory max: %zu\n", get_max_size(buf));
    }
#endif
    ogg_malloc_destroy();

    /* Clean things up for the next track */
    vf.dataoffsets = NULL;
    vf.offsets = NULL;
    vf.serialnos = NULL;
    vf.pcmlengths = NULL;
    ov_clear(&vf);

    return error;
}
Example #23
0
	OggWrapper::~OggWrapper()
	{
		ov_clear(ovFile_);
		delete ovFile_;
	}
	~FVorbisFileWrapper()
	{
#if WITH_OGGVORBIS
		ov_clear( &vf ); 
#endif
	}
Example #25
0
static LONG APIENTRY IOProc_Entry2(PVOID pmmioStr, USHORT usMsg, LONG lParam1,
                     LONG lParam2) {
	PMMIOINFO pmmioinfo = (PMMIOINFO)pmmioStr;
	switch (usMsg) {
	case MMIOM_OPEN:
		{	
     		HMMIO hmmioSS;
     		MMIOINFO mmioinfoSS;
	    	PSZ pszFileName = (char *)lParam1;
   	 		if (!pmmioinfo) return MMIO_ERROR;
  	  		if ((pmmioinfo->ulFlags & MMIO_READWRITE)) {
#ifdef DEBUG
			fprintf(file,"ReadWrite - requested.\n");
#endif
   	  		   return MMIO_ERROR;
  	  		}
			if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) &&
			    !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)) return MMIO_ERROR;
			if (!pmmioinfo->fccChildIOProc) {
				FOURCC fccFileStorageSystem;
				if (pmmioinfo->ulFlags & MMIO_CREATE) {
       				if (mmioDetermineSSIOProc(pszFileName, pmmioinfo, &fccFileStorageSystem, NULL)) {
              			fccFileStorageSystem = FOURCC_DOS;
              		}
       			} else {
	        		if (mmioIdentifyStorageSystem(pszFileName, pmmioinfo, &fccFileStorageSystem)) {
 		           		return MMIO_ERROR;
    	        	}
    	        }
            	if (!fccFileStorageSystem) {
             	  	return MMIO_ERROR;
            	} else {
             	  	pmmioinfo->fccChildIOProc = fccFileStorageSystem;
            	} /* endif */
			}
			memmove(&mmioinfoSS, pmmioinfo, sizeof(MMIOINFO));
			mmioinfoSS.pIOProc = NULL;
			mmioinfoSS.fccIOProc = pmmioinfo->fccChildIOProc;
			mmioinfoSS.ulFlags |= MMIO_NOIDENTIFY;
			
			hmmioSS = mmioOpen (pszFileName, &mmioinfoSS, mmioinfoSS.ulFlags);
			if (pmmioinfo->ulFlags & MMIO_DELETE) {
      			if (!hmmioSS) {
            		pmmioinfo->ulErrorRet = MMIOERR_DELETE_FAILED;
            		return MMIO_ERROR;
            	}
            	else return MMIO_SUCCESS;
			}
   			if (!hmmioSS) return MMIO_ERROR;
   			if (pmmioinfo->ulFlags & MMIO_READ) {
 			   DecInfo *decInfo = (DecInfo *)malloc(sizeof(DecInfo));
#ifdef DEBUG
			fprintf(file,"File Read: %s\n",pszFileName);
#endif
        		if (!decInfo) {
  	          		mmioClose(hmmioSS, 0);
            		return MMIO_ERROR;
	            }
				decInfo->t = READNUM;
			    decInfo->vorbisOptions = pmmioinfo->pExtraInfoStruct;
 	      		pmmioinfo->pExtraInfoStruct = (PVOID)decInfo;
  	     		{
            		ov_callbacks cb;
   	         		cb.read_func = mread;
            		cb.seek_func = mseek;
            		cb.close_func = mclose;
            		cb.tell_func = mtell;
	       			if(0 != ov_open_callbacks((void *)hmmioSS, &decInfo->oggfile, 0, 0, cb)) {
           	  			free(decInfo);
	            		mmioClose(hmmioSS, 0);
 	           			return MMIO_ERROR;
             		}
            	}
#ifdef DEBUG
				fprintf(file,"Open successfull\n");
#endif
				return MMIO_SUCCESS;
			} else if (pmmioinfo->ulFlags & MMIO_WRITE) {
	       		EncInfo *encInfo = (EncInfo *)malloc(sizeof(EncInfo));
#ifdef DEBUG
			fprintf(file,"File Write: %s\n",pszFileName);
#endif
	       		if (!encInfo) {
  	          		mmioClose(hmmioSS, 0);
            		return MMIO_ERROR;
                }
	       		memset(encInfo, 0, sizeof(EncInfo));
	       		encInfo->t = WRITENUM;
	       		encInfo->hmmioSS = hmmioSS;
				encInfo->vorbisOptions = (PVORBISOPTIONS)pmmioinfo->pExtraInfoStruct;
 	      		pmmioinfo->pExtraInfoStruct = (PVOID)encInfo;
 	      		return MMIO_SUCCESS;
      		}
#ifdef DEBUG
			fprintf(file,"File not read nor write: %s\n",pszFileName);
#endif
      		return MMIO_ERROR;
		}
	    break;                                                 
	case MMIOM_READ: {
		if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct || !lParam1) return MMIO_ERROR;
		
		if (!pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA) {
     		return MMIO_ERROR;
//     		return mmioRead (ogginfo->hmmioSS, (PVOID) lParam1, (ULONG) lParam2);
     	} else {
			OggVorbis_File *oggfile;
			long rc = 0;
			int current_section;
			long total = 0;
			
			oggfile = &((DecInfo *)pmmioinfo->pExtraInfoStruct)->oggfile;
			if (READNUM != ((DecInfo *)pmmioinfo->pExtraInfoStruct)->t) return MMIO_ERROR;
			while (lParam2 > 0) {
	         	rc = ov_read(oggfile, (char *)lParam1, (int)lParam2, 0, 2, 1,  &current_section);
	         	if (rc < 0) {
#ifdef DEBUG
fprintf(file, "Read failed once\n");
#endif
				continue;
				}
				if (rc <= 0) break;
				lParam2 -= rc;
				lParam1 += rc;
				total += rc;
			}
#ifdef DEBUG
fprintf(file,"Read rc:%ld total:%ld\n",rc,total);
#endif
         	if (rc < 0) return MMIO_ERROR;
         	return total;
        }
   	}
	break;
	case MMIOM_SEEK: {
        LONG lPosDesired;
		OggVorbis_File *oggfile;
    	vorbis_info *vi;
		
		if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return MMIO_ERROR;
		if (!pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA) return MMIO_ERROR;    	
		
		oggfile = &((DecInfo *)pmmioinfo->pExtraInfoStruct)->oggfile;
		if (READNUM != ((DecInfo *)pmmioinfo->pExtraInfoStruct)->t) return MMIO_ERROR;
		vi = ov_info(oggfile, -1);
		if (!vi) return MMIO_ERROR;
	
		if (SEEK_SET == lParam2) {
     		lPosDesired = lParam1/(2*vi->channels);
        } else if (SEEK_CUR == lParam2) {
            if (0 == lParam1) {
               return ov_pcm_tell(oggfile)*2*vi->channels;
            } /* endif */
           	lPosDesired = ov_pcm_tell(oggfile) + lParam1/(2*vi->channels);
        } else if (SEEK_END == lParam2) {
           	lPosDesired = ov_pcm_total(oggfile,-1) + lParam1/(2*vi->channels);
        } else {
           return MMIO_ERROR;
        }
#ifdef DEBUG
fprintf(file,"Seek to %ld by %d\n",lPosDesired, lParam2);
#endif
		if (ov_pcm_seek(oggfile, lPosDesired) < 0) return MMIO_ERROR;

    	return lPosDesired*2*vi->channels;
	}
    break;

	case MMIOM_CLOSE: {
		int rc;
#ifdef DEBUG
       	    fprintf(file,"start CLOSE\n");
#endif		
		if (!pmmioinfo) return MMIO_ERROR;
		
		if (pmmioinfo->pExtraInfoStruct) {
     		DecInfo *decInfo = (DecInfo *)pmmioinfo->pExtraInfoStruct;
#ifdef DEBUG
       	    fprintf(file,"ready CLOSE\n");
#endif		
			if (READNUM == decInfo->t) {
#ifdef DEBUG
       	    fprintf(file,"read CLOSE\n");
#endif		
     			ov_clear(&decInfo->oggfile);
     			free(decInfo);
     			decInfo = 0;
                rc=MMIO_SUCCESS;
     		} else if (WRITENUM == decInfo->t) {
   	           EncInfo *encInfo = (EncInfo*)pmmioinfo->pExtraInfoStruct;
#ifdef DEBUG
       	    fprintf(file,"write CLOSE\n");
#endif		
			   if (encInfo->headerSet) {
	               vorbis_analysis_wrote(&encInfo->vd,0);
 	               rc = oggWrite(encInfo,1);
	               ogg_stream_clear(&encInfo->os);
	               vorbis_block_clear(&encInfo->vb);
	               vorbis_dsp_clear(&encInfo->vd);
 	               vorbis_comment_clear(&encInfo->vc);
	               vorbis_info_clear(&encInfo->vi);
               }
   	           mmioClose(encInfo->hmmioSS, 0);
  	           free(encInfo);
 	           encInfo = 0;
               rc = MMIO_SUCCESS;
	        } else rc = MMIO_ERROR;
     		pmmioinfo->pExtraInfoStruct = 0;
#ifdef DEBUG
       	    fprintf(file,"CLOSE\n");
#endif		
			return rc;
        }
     	return MMIO_ERROR;
    }
    break;
	case MMIOM_IDENTIFYFILE: {
    	unsigned char buf[4];
		HMMIO hmmioTemp;
		ULONG ulTempFlags = MMIO_READ | MMIO_DENYWRITE | MMIO_NOIDENTIFY;
		LONG rc = MMIO_ERROR;

		if (!lParam1 && !lParam2) return MMIO_ERROR;
    	hmmioTemp = (HMMIO)lParam2;
    	if (!hmmioTemp) {
        	hmmioTemp = mmioOpen((PSZ)lParam1, NULL, ulTempFlags);
        }

		if (hmmioTemp) {
			rc = mmioRead(hmmioTemp, buf, 4);
			if (rc == 4 && buf[0] == 'O' && buf[1] == 'g' &&
					buf[2] == 'g' && buf[3] == 'S') {
				rc = MMIO_SUCCESS;
          	}
			if (!lParam2) mmioClose(hmmioTemp, 0);
		}
		return rc;
	}
    break;
	case MMIOM_GETFORMATINFO: {
    	PMMFORMATINFO pmmformatinfo;
    	pmmformatinfo = (PMMFORMATINFO)lParam1;
    	pmmformatinfo->ulStructLen = sizeof(MMFORMATINFO);
    	pmmformatinfo->fccIOProc = FOURCC_Vorbis;
    	pmmformatinfo->ulIOProcType = MMIO_IOPROC_FILEFORMAT;
    	pmmformatinfo->ulMediaType = MMIO_MEDIATYPE_AUDIO;
    	pmmformatinfo->ulFlags = MMIO_CANREADTRANSLATED 
    	   | MMIO_CANWRITETRANSLATED
           | MMIO_CANSEEKTRANSLATED;
    	strcpy(pmmformatinfo->szDefaultFormatExt, "OGG");
    	pmmformatinfo->ulCodePage = 0;
    	pmmformatinfo->ulLanguage = 0;
    	pmmformatinfo->lNameLength = 21;
    	return MMIO_SUCCESS;
    }
    break;
	case MMIOM_GETFORMATNAME:
		if (lParam2 > 21) { 
     		strcpy((PSZ)lParam1, "Ogg Vorbis");
     		return MMIO_SUCCESS;
     	} else return MMIO_ERROR;
    break;
    case MMIOM_QUERYHEADERLENGTH: return (sizeof (MMAUDIOHEADER));
    break;
	case MMIOM_GETHEADER: {
		OggVorbis_File *oggfile;
		DecInfo *decInfo;
    	PMMAUDIOHEADER mmaudioheader;
    	vorbis_info *vi;
    	
		if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return 0;
		if (!(pmmioinfo->ulFlags & MMIO_READ)) return 0;
		decInfo = (DecInfo *)pmmioinfo->pExtraInfoStruct;
		oggfile = &decInfo->oggfile;
		if (READNUM != decInfo->t){
            pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
            return 0;
        }
		
#ifdef DEBUG
		fprintf(file,"HERE\n");
#endif
		if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) &&
		    !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)) return 0;
		mmaudioheader = (MMAUDIOHEADER *)lParam1;
		if (sizeof(MMAUDIOHEADER) > lParam2) {
            pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
			return 0;
		}

#ifdef DEBUG
		fprintf(file,"THERE\n");
#endif

		vi = ov_info(oggfile, -1);
		if (!vi) {
            pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
            return 0;
        }

		mmaudioheader->ulContentType = MMIO_MIDI_UNKNOWN;
		mmaudioheader->ulMediaType = MMIO_MEDIATYPE_AUDIO;
		mmaudioheader->mmXWAVHeader.WAVEHeader.usFormatTag=DATATYPE_WAVEFORM;
		mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels = vi->channels;
		mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec = vi->rate;
		mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample = 16;
		mmaudioheader->mmXWAVHeader.WAVEHeader.ulAvgBytesPerSec=
			mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels * 
			mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec *
			mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample / 8;
		mmaudioheader->mmXWAVHeader.WAVEHeader.usBlockAlign=
			mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels * 
			mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample / 8;
		mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS=
			(unsigned long)(ov_time_total(oggfile, -1)*1000.0);
		mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes=
		    (unsigned long)ov_pcm_total(oggfile, -1)*
		    mmaudioheader->mmXWAVHeader.WAVEHeader.usBlockAlign;

#ifdef DEBUG
		fprintf(file,"time: %ld size: %ld rate: %ld\n",
			mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS,
			mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes,
			mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec);
	
#endif
		if (0 != decInfo->vorbisOptions && VORBIS_COOKIE == decInfo->vorbisOptions->cookie) {
			decInfo->vorbisOptions->nominal_bitrate = ov_bitrate(oggfile, -1);
			mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.pAdditionalInformation = decInfo->vorbisOptions;
        }
		return (sizeof (MMAUDIOHEADER));
    }
    break;

	case MMIOM_SETHEADER: {
    	EncInfo *encInfo;
    	PMMAUDIOHEADER mmaudioheader;
        int totalout = 0;
        int rc;

		if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return 0;
		encInfo = (EncInfo*)pmmioinfo->pExtraInfoStruct;
		if (WRITENUM != encInfo->t) return 0;
#ifdef DEBUG
fprintf(file,"write header: %x, %x, %x\n",!(pmmioinfo->ulFlags & MMIO_WRITE),
	encInfo->headerSet, (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) && 
		        !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)));
fprintf(file,"flag: %x, trans: %x\n",pmmioinfo->ulFlags,pmmioinfo->ulTranslate);
#endif
		if (/*!(pmmioinfo->ulFlags & MMIO_WRITE) ||*/ encInfo->headerSet
		    || (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) && 
		        !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA))) return 0;
		if (!lParam1) {
     		pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
     		return 0;
     	}
     	mmaudioheader = (PMMAUDIOHEADER)lParam1;
     	if (lParam2 != sizeof(MMAUDIOHEADER)) {
         	pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
         	return 0;
        }
		  /********** Encode setup ************/
	if (0 != mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample%8) {
      /* Bit-rate must be multiple of 8 */
      return 0;
    }
	encInfo->bitsPerSample=mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample;
#ifdef DEBUG
fprintf(file,"ready to write header: ");
#endif
    vorbis_info_init(&encInfo->vi);
	if (0 == encInfo->vorbisOptions || VORBIS_COOKIE != encInfo->vorbisOptions->cookie) {
#ifdef DEBUG
fprintf(file,"default quality 0.3\n");
#endif
	    rc = vorbis_encode_init_vbr(&encInfo->vi,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec, 0.3);
    } else {
#ifdef DEBUG
fprintf(file,"bitsPerSample: %d channels: %d samplesPerSec: %ld min: %ld nominal: %ld max: %ld\n",
	encInfo->bitsPerSample,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec,
	  	encInfo->vorbisOptions->max_bitrate,
	  	encInfo->vorbisOptions->nominal_bitrate,
	  	encInfo->vorbisOptions->min_bitrate);
#endif
	    rc = vorbis_encode_init(&encInfo->vi,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec,
	  	encInfo->vorbisOptions->max_bitrate,
	  	encInfo->vorbisOptions->nominal_bitrate,
	  	encInfo->vorbisOptions->min_bitrate);
    }

    if (rc) {
#ifdef DEBUG
fprintf(file,"encodeInit failed: %d\n",rc);
#endif
       return 0;
    } /* endif */

  /* add a comment */
  vorbis_comment_init(&encInfo->vc);
  vorbis_comment_add_tag(&encInfo->vc,"ENCODER","mmioVorbis");

  /* set up the analysis state and auxiliary encoding storage */
  vorbis_analysis_init(&encInfo->vd,&encInfo->vi);
  vorbis_block_init(&encInfo->vd,&encInfo->vb);

  /* set up our packet->stream encoder */
  /* pick a random serial number; that way we can more likely build
     chained streams just by concatenation */
  srand(time(NULL));
  ogg_stream_init(&encInfo->os,rand());

  {
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_analysis_headerout(&encInfo->vd,&encInfo->vc,&header,&header_comm,&header_code);
    ogg_stream_packetin(&encInfo->os,&header); /* automatically placed in its own
					 page */
    ogg_stream_packetin(&encInfo->os,&header_comm);
    ogg_stream_packetin(&encInfo->os,&header_code);
	while(1){
		int result=ogg_stream_flush(&encInfo->os,&encInfo->og);
		if(result==0)break;
		result = mmioWrite(encInfo->hmmioSS, encInfo->og.header,encInfo->og.header_len);
        totalout += result;
		if (result!=encInfo->og.header_len) {
	               ogg_stream_clear(&encInfo->os);
	               vorbis_block_clear(&encInfo->vb);
	               vorbis_dsp_clear(&encInfo->vd);
 	               vorbis_comment_clear(&encInfo->vc);
	               vorbis_info_clear(&encInfo->vi);
			return 0;
        }
		result = mmioWrite(encInfo->hmmioSS, encInfo->og.body,encInfo->og.body_len);
        totalout += result;
		if (result!=encInfo->og.body_len) {
	               ogg_stream_clear(&encInfo->os);
	               vorbis_block_clear(&encInfo->vb);
	               vorbis_dsp_clear(&encInfo->vd);
 	               vorbis_comment_clear(&encInfo->vc);
	               vorbis_info_clear(&encInfo->vi);
			return 0;
		}
	}
  }
  		encInfo->headerSet = 1;
  		return totalout;
    }
    break;
	case MMIOM_WRITE: {
    	EncInfo *encInfo;
		if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return MMIO_ERROR;
		encInfo = (EncInfo*)pmmioinfo->pExtraInfoStruct;
		if (WRITENUM != encInfo->t) return MMIO_ERROR;
		if (!encInfo->headerSet) return MMIO_ERROR;
		if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)) {
     		if (!lParam1) return MMIO_ERROR;
     		return mmioWrite(encInfo->hmmioSS, (PVOID)lParam1, lParam2);
     	} else {
            if (lParam2 == 0) {
                vorbis_analysis_wrote(&encInfo->vd,0);
            } else {
                long i;
				int j, k;
                int num;
				float denom = 1;
                signed char *readbuffer = (char *)lParam1;
                /* data to encode */
                /* expose the buffer to submit data */
				int sampleSize = encInfo->vi.channels*encInfo->bitsPerSample/8;
				int samples = lParam2/sampleSize;
	            float **buffer=vorbis_analysis_buffer(&encInfo->vd, samples);
#ifdef DEBUG
fprintf(file,"write: %ld\n",lParam2);
#endif

  	            /* :TODO: Work with buffers not a multiple of sampleSize*/
                if (lParam2 % sampleSize != 0) {
#ifdef DEBUG
fprintf(file,"Bad Write Buffer Size\n");
#endif
                    return MMIO_ERROR;
                }
                for(i=0;i<samples;i++){
                   for (j=0;j<encInfo->vi.channels;j++) {
                    num=0; denom=0.5;
					if (encInfo->bitsPerSample<=8) {
        				buffer[j][i]=(float)((unsigned char)(readbuffer[i*sampleSize])-
							(1<<(encInfo->bitsPerSample-1)))/
							(float)(1<<(encInfo->bitsPerSample-1));
					} else {
						for (k=encInfo->bitsPerSample/8;k>0;k--) {
							if (k==encInfo->bitsPerSample/8) {
								num=(readbuffer[i*sampleSize+k-1]);
							} else {
								num=(num<<8)|((0xff)&(int)(readbuffer[i*sampleSize+k-1]));
    		    			}
							denom *= 256.0;
						}
 	                   buffer[j][i]=((float)num)/denom;
					}
                   } /* endfor */
                }
                vorbis_analysis_wrote(&encInfo->vd,i);
            } /* endif */
            if (oggWrite(encInfo,0)>=0) {
                return lParam2;
            } else {
                return MMIO_ERROR;
            } /* endif */
        }
    }
    break;
#ifdef DEBUG
	case MMIOM_TEMPCHANGE: {
        return MMIO_SUCCESS;
    }
    break;
#endif
	}
#ifdef DEBUG	
	fprintf(file,"unexpected command: %x\n",usMsg);
#endif
	return MMIOERR_UNSUPPORTED_MESSAGE;
}
Example #26
0
CWinGlkOGGSound::~CWinGlkOGGSound()
{
  RemoveFromList();
  if (m_StreamOpen)
    ov_clear(&m_Stream);
}
Example #27
0
VorbisDecoder::~VorbisDecoder() {
    if (m_data->initialized)
        ov_clear(m_data->vf);
    delete m_data->vf;
    delete m_data;
}
Example #28
0
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;
}
Example #29
0
void ca_vorbis_close(ca_vorbis *v) {
        ca_assert(v);

        ov_clear(&v->ovf);
        ca_free(v);
}
G_MODULE_EXPORT gboolean
tracker_extract_get_metadata (TrackerExtractInfo *info)
{
	TrackerSparqlBuilder *preupdate, *metadata;
	VorbisData vd = { 0 };
	MergeData md = { 0 };
	FILE *f;
	gchar *filename, *uri;
	OggVorbis_File vf;
	vorbis_comment *comment;
	vorbis_info *vi;
	unsigned int bitrate;
	gint time;
	GFile *file;
	const gchar *graph;

	file = tracker_extract_info_get_file (info);
	filename = g_file_get_path (file);
	f = tracker_file_open (filename);
	g_free (filename);

	preupdate = tracker_extract_info_get_preupdate_builder (info);
	metadata = tracker_extract_info_get_metadata_builder (info);
	graph = tracker_extract_info_get_graph (info);

	if (!f) {
		return FALSE;
	}

	if (ov_open (f, &vf, NULL, 0) < 0) {
		tracker_file_close (f, FALSE);
		return FALSE;
	}

	tracker_sparql_builder_predicate (metadata, "a");
	tracker_sparql_builder_object (metadata, "nmm:MusicPiece");
	tracker_sparql_builder_object (metadata, "nfo:Audio");

	if ((comment = ov_comment (&vf, -1)) != NULL) {
		gchar *date;

		vd.title = ogg_get_comment (comment, "title");
		vd.artist = ogg_get_comment (comment, "artist");
		vd.album = ogg_get_comment (comment, "album");
		vd.album_artist = ogg_get_comment (comment, "albumartist");
		vd.track_count = ogg_get_comment (comment, "trackcount");
		vd.track_number = ogg_get_comment (comment, "tracknumber");
		vd.disc_number = ogg_get_comment (comment, "DiscNo");
		vd.performer = ogg_get_comment (comment, "Performer");
		vd.track_gain = ogg_get_comment (comment, "TrackGain");
		vd.track_peak_gain = ogg_get_comment (comment, "TrackPeakGain");
		vd.album_gain = ogg_get_comment (comment, "AlbumGain");
		vd.album_peak_gain = ogg_get_comment (comment, "AlbumPeakGain");

		date = ogg_get_comment (comment, "date");
		vd.date = tracker_date_guess (date);
		g_free (date);

		vd.comment = ogg_get_comment (comment, "comment");
		vd.genre = ogg_get_comment (comment, "genre");
		vd.codec = ogg_get_comment (comment, "Codec");
		vd.codec_version = ogg_get_comment (comment, "CodecVersion");
		vd.sample_rate = ogg_get_comment (comment, "SampleRate");
		vd.channels = ogg_get_comment (comment, "Channels");
		vd.mb_album_id = ogg_get_comment (comment, "MBAlbumID");
		vd.mb_artist_id = ogg_get_comment (comment, "MBArtistID");
		vd.mb_album_artist_id = ogg_get_comment (comment, "MBAlbumArtistID");
		vd.mb_track_id = ogg_get_comment (comment, "MBTrackID");
		vd.lyrics = ogg_get_comment (comment, "Lyrics");
		vd.copyright = ogg_get_comment (comment, "Copyright");
		vd.license = ogg_get_comment (comment, "License");
		vd.organization = ogg_get_comment (comment, "Organization");
		vd.location = ogg_get_comment (comment, "Location");
		vd.publisher = ogg_get_comment (comment, "Publisher");

		vorbis_comment_clear (comment);
	}

	md.creator = tracker_coalesce_strip (3, vd.artist, vd.album_artist, vd.performer);

	if (md.creator) {
		/* NOTE: This must be created before vd.album is evaluated */
		md.creator_uri = tracker_sparql_escape_uri_printf ("urn:artist:%s", md.creator);

		tracker_sparql_builder_insert_open (preupdate, NULL);
		if (graph) {
			tracker_sparql_builder_graph_open (preupdate, graph);
		}

		tracker_sparql_builder_subject_iri (preupdate, md.creator_uri);
		tracker_sparql_builder_predicate (preupdate, "a");
		tracker_sparql_builder_object (preupdate, "nmm:Artist");
		tracker_sparql_builder_predicate (preupdate, "nmm:artistName");
		tracker_sparql_builder_object_unvalidated (preupdate, md.creator);

		if (graph) {
			tracker_sparql_builder_graph_close (preupdate);
		}
		tracker_sparql_builder_insert_close (preupdate);

		tracker_sparql_builder_predicate (metadata, "nmm:performer");
		tracker_sparql_builder_object_iri (metadata, md.creator_uri);
	}

	if (vd.album) {
		gchar *uri = tracker_sparql_escape_uri_printf ("urn:album:%s", vd.album);
		gchar *album_disc_uri;

		tracker_sparql_builder_insert_open (preupdate, NULL);
		if (graph) {
			tracker_sparql_builder_graph_open (preupdate, graph);
		}

		tracker_sparql_builder_subject_iri (preupdate, uri);
		tracker_sparql_builder_predicate (preupdate, "a");
		tracker_sparql_builder_object (preupdate, "nmm:MusicAlbum");
		/* FIXME: nmm:albumTitle is now deprecated
		 * tracker_sparql_builder_predicate (preupdate, "nie:title");
		 */
		tracker_sparql_builder_predicate (preupdate, "nmm:albumTitle");
		tracker_sparql_builder_object_unvalidated (preupdate, vd.album);

		if (md.creator_uri) {
			tracker_sparql_builder_predicate (preupdate, "nmm:albumArtist");
			tracker_sparql_builder_object_iri (preupdate, md.creator_uri);
		}

		if (graph) {
			tracker_sparql_builder_graph_close (preupdate);
		}
		tracker_sparql_builder_insert_close (preupdate);

		if (vd.track_count) {
			tracker_sparql_builder_delete_open (preupdate, NULL);
			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_delete_close (preupdate);

			tracker_sparql_builder_where_open (preupdate);
			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_where_close (preupdate);

			tracker_sparql_builder_insert_open (preupdate, NULL);
			if (graph) {
				tracker_sparql_builder_graph_open (preupdate, graph);
			}

			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount");
			tracker_sparql_builder_object_unvalidated (preupdate, vd.track_count);

			if (graph) {
				tracker_sparql_builder_graph_close (preupdate);
			}
			tracker_sparql_builder_insert_close (preupdate);
		}

		if (vd.album_gain) {
			tracker_sparql_builder_delete_open (preupdate, NULL);
			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumGain");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_delete_close (preupdate);

			tracker_sparql_builder_where_open (preupdate);
			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumGain");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_where_close (preupdate);

			tracker_sparql_builder_insert_open (preupdate, NULL);
			if (graph) {
				tracker_sparql_builder_graph_open (preupdate, graph);
			}

			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumGain");
			tracker_sparql_builder_object_double (preupdate, atof (vd.album_gain));

			if (graph) {
				tracker_sparql_builder_graph_close (preupdate);
			}
			tracker_sparql_builder_insert_close (preupdate);
		}

		if (vd.album_peak_gain) {
			tracker_sparql_builder_delete_open (preupdate, NULL);
			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_delete_close (preupdate);

			tracker_sparql_builder_where_open (preupdate);
			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_where_close (preupdate);

			tracker_sparql_builder_insert_open (preupdate, NULL);
			if (graph) {
				tracker_sparql_builder_graph_open (preupdate, graph);
			}

			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain");
			tracker_sparql_builder_object_double (preupdate, atof (vd.album_peak_gain));

			if (graph) {
				tracker_sparql_builder_graph_close (preupdate);
			}
			tracker_sparql_builder_insert_close (preupdate);
		}

		album_disc_uri = tracker_sparql_escape_uri_printf ("urn:album-disc:%s:Disc%d",
		                                                   vd.album,
		                                                   vd.disc_number ? atoi(vd.disc_number) : 1);

		tracker_sparql_builder_delete_open (preupdate, NULL);
		tracker_sparql_builder_subject_iri (preupdate, album_disc_uri);
		tracker_sparql_builder_predicate (preupdate, "nmm:setNumber");
		tracker_sparql_builder_object_variable (preupdate, "unknown");
		tracker_sparql_builder_delete_close (preupdate);
		tracker_sparql_builder_where_open (preupdate);
		tracker_sparql_builder_subject_iri (preupdate, album_disc_uri);
		tracker_sparql_builder_predicate (preupdate, "nmm:setNumber");
		tracker_sparql_builder_object_variable (preupdate, "unknown");
		tracker_sparql_builder_where_close (preupdate);

		tracker_sparql_builder_delete_open (preupdate, NULL);
		tracker_sparql_builder_subject_iri (preupdate, album_disc_uri);
		tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum");
		tracker_sparql_builder_object_variable (preupdate, "unknown");
		tracker_sparql_builder_delete_close (preupdate);
		tracker_sparql_builder_where_open (preupdate);
		tracker_sparql_builder_subject_iri (preupdate, album_disc_uri);
		tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum");
		tracker_sparql_builder_object_variable (preupdate, "unknown");
		tracker_sparql_builder_where_close (preupdate);

		tracker_sparql_builder_insert_open (preupdate, NULL);
		if (graph) {
			tracker_sparql_builder_graph_open (preupdate, graph);
		}

		tracker_sparql_builder_subject_iri (preupdate, album_disc_uri);
		tracker_sparql_builder_predicate (preupdate, "a");
		tracker_sparql_builder_object (preupdate, "nmm:MusicAlbumDisc");
		tracker_sparql_builder_predicate (preupdate, "nmm:setNumber");
		tracker_sparql_builder_object_int64 (preupdate, vd.disc_number ? atoi (vd.disc_number) : 1);
		tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum");
		tracker_sparql_builder_object_iri (preupdate, uri);

		if (graph) {
			tracker_sparql_builder_graph_close (preupdate);
		}
		tracker_sparql_builder_insert_close (preupdate);

		tracker_sparql_builder_predicate (metadata, "nmm:musicAlbumDisc");
		tracker_sparql_builder_object_iri (metadata, album_disc_uri);

	        g_free (album_disc_uri);

		tracker_sparql_builder_predicate (metadata, "nmm:musicAlbum");
		tracker_sparql_builder_object_iri (metadata, uri);
		g_free (uri);
	}

	g_free (vd.track_count);
	g_free (vd.album_peak_gain);
	g_free (vd.album_gain);
	g_free (vd.disc_number);

	if (vd.title) {
		tracker_sparql_builder_predicate (metadata, "nie:title");
		tracker_sparql_builder_object_unvalidated (metadata, vd.title);
		g_free (vd.title);
	}

	if (vd.track_number) {
		tracker_sparql_builder_predicate (metadata, "nmm:trackNumber");
		tracker_sparql_builder_object_unvalidated (metadata, vd.track_number);
		g_free (vd.track_number);
	}

	if (vd.track_gain) {
		/* TODO */
		g_free (vd.track_gain);
	}

	if (vd.track_peak_gain) {
		/* TODO */
		g_free (vd.track_peak_gain);
	}

	if (vd.comment) {
		tracker_sparql_builder_predicate (metadata, "nie:comment");
		tracker_sparql_builder_object_unvalidated (metadata, vd.comment);
		g_free (vd.comment);
	}

	if (vd.date) {
		tracker_sparql_builder_predicate (metadata, "nie:contentCreated");
		tracker_sparql_builder_object_unvalidated (metadata, vd.date);
		g_free (vd.date);
	}

	if (vd.genre) {
		tracker_sparql_builder_predicate (metadata, "nfo:genre");
		tracker_sparql_builder_object_unvalidated (metadata, vd.genre);
		g_free (vd.genre);
	}

	if (vd.codec) {
		tracker_sparql_builder_predicate (metadata, "nfo:codec");
		tracker_sparql_builder_object_unvalidated (metadata, vd.codec);
		g_free (vd.codec);
	}

	if (vd.codec_version) {
		/* TODO */
		g_free (vd.codec_version);
	}

	if (vd.sample_rate) {
		tracker_sparql_builder_predicate (metadata, "nfo:sampleRate");
		tracker_sparql_builder_object_unvalidated (metadata, vd.sample_rate);
		g_free (vd.sample_rate);
	}

	if (vd.channels) {
		tracker_sparql_builder_predicate (metadata, "nfo:channels");
		tracker_sparql_builder_object_unvalidated (metadata, vd.channels);
		g_free (vd.channels);
	}

	if (vd.mb_album_id) {
		/* TODO */
		g_free (vd.mb_album_id);
	}

	if (vd.mb_artist_id) {
		/* TODO */
		g_free (vd.mb_artist_id);
	}

	if (vd.mb_album_artist_id) {
		/* TODO */
		g_free (vd.mb_album_artist_id);
	}

	if (vd.mb_track_id) {
		/* TODO */
		g_free (vd.mb_track_id);
	}

	if (vd.lyrics) {
		tracker_sparql_builder_predicate (metadata, "nie:plainTextContent");
		tracker_sparql_builder_object_unvalidated (metadata, vd.lyrics);
		g_free (vd.lyrics);
	}

	if (vd.copyright) {
		tracker_sparql_builder_predicate (metadata, "nie:copyright");
		tracker_sparql_builder_object_unvalidated (metadata, vd.copyright);
		g_free (vd.copyright);
	}

	if (vd.license) {
		tracker_sparql_builder_predicate (metadata, "nie:license");
		tracker_sparql_builder_object_unvalidated (metadata, vd.license);
		g_free (vd.license);
	}

	if (vd.organization) {
		/* TODO */
		g_free (vd.organization);
	}

	if (vd.location) {
		/* TODO */
		g_free (vd.location);
	}

	if (vd.publisher) {
		tracker_sparql_builder_predicate (metadata, "dc:publisher");

		tracker_sparql_builder_object_blank_open (metadata);
		tracker_sparql_builder_predicate (metadata, "a");
		tracker_sparql_builder_object (metadata, "nco:Contact");

		tracker_sparql_builder_predicate (metadata, "nco:fullname");
		tracker_sparql_builder_object_unvalidated (metadata, vd.publisher);
		tracker_sparql_builder_object_blank_close (metadata);
		g_free (vd.publisher);
	}

	if ((vi = ov_info (&vf, 0)) != NULL ) {
		bitrate = vi->bitrate_nominal / 1000;

		tracker_sparql_builder_predicate (metadata, "nfo:averageBitrate");
		tracker_sparql_builder_object_int64 (metadata, (gint64) bitrate);
	}

	/* Duration */
	if ((time = ov_time_total (&vf, -1)) != OV_EINVAL) {
		tracker_sparql_builder_predicate (metadata, "nfo:duration");
		tracker_sparql_builder_object_int64 (metadata, (gint64) time);
	}

	uri = g_file_get_uri (file);
	tracker_media_art_process (NULL,
				0,
				NULL,
				TRACKER_MEDIA_ART_ALBUM,
				vd.album_artist ? vd.album_artist : vd.artist,
				vd.album,
				uri);
	g_free (uri);

	g_free (vd.artist);
	g_free (vd.album);
	g_free (vd.album_artist);
	g_free (vd.performer);

	g_free (md.creator_uri);

#ifdef HAVE_POSIX_FADVISE
	posix_fadvise (fileno (f), 0, 0, POSIX_FADV_DONTNEED);
#endif /* HAVE_POSIX_FADVISE */

	/* NOTE: This calls fclose on the file */
	ov_clear (&vf);

	return TRUE;
}