VorbisStream::~VorbisStream() { ov_clear(&_ovFile); }
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); }
void sound_closeSample (SoundSample * sample){ free (sample->data); ov_clear (&sample->s_file.oggFile); free (sample); }
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; }
// 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; }
VorbisStream::~VorbisStream() { ov_clear(&_ovFile); if (_disposeAfterUse == DisposeAfterUse::YES) delete _inStream; }
SourceFileOggVorbis::~SourceFileOggVorbis() { ov_clear( &mOggVorbisFile ); }
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; }
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, ¤t_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"); }
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; }
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; }
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); }
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; }
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, ¤t_bitstream); #else /* __LITTLE_ENDIAN__ */ bytes_read = ov_read(&audio->oggvorbis_file, buffer, AUDIO_CHUNK_SIZE, 0, 2, 1, ¤t_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; }
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); } }
/* 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(¶m); 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, ¤t_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; }
OggWrapper::~OggWrapper() { ov_clear(ovFile_); delete ovFile_; }
~FVorbisFileWrapper() { #if WITH_OGGVORBIS ov_clear( &vf ); #endif }
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, ¤t_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; }
CWinGlkOGGSound::~CWinGlkOGGSound() { RemoveFromList(); if (m_StreamOpen) ov_clear(&m_Stream); }
VorbisDecoder::~VorbisDecoder() { if (m_data->initialized) ov_clear(m_data->vf); delete m_data->vf; delete m_data; }
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; }
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; }