static gint vorbis_check_fd(const gchar *filename, VFSFile *stream) { OggVorbis_File vfile; gint result; /* * The open function performs full stream detection and machine * initialization. If it returns zero, the stream *is* Vorbis and * we're fully ready to decode. */ memset(&vfile, 0, sizeof(vfile)); result = ov_test_callbacks (stream, & vfile, NULL, 0, vfs_is_streaming (stream) ? vorbis_callbacks_stream : vorbis_callbacks); switch (result) { case OV_EREAD: #ifdef DEBUG g_message("** vorbis.c: Media read error: %s", filename); #endif return FALSE; break; case OV_ENOTVORBIS: #ifdef DEBUG g_message("** vorbis.c: Not Vorbis data: %s", filename); #endif return FALSE; break; case OV_EVERSION: #ifdef DEBUG g_message("** vorbis.c: Version mismatch: %s", filename); #endif return FALSE; break; case OV_EBADHEADER: #ifdef DEBUG g_message("** vorbis.c: Invalid Vorbis bistream header: %s", filename); #endif return FALSE; break; case OV_EFAULT: #ifdef DEBUG g_message("** vorbis.c: Internal logic fault while reading %s", filename); #endif return FALSE; break; case 0: break; default: break; } ov_clear(&vfile); return TRUE; }
bool VorbisDecoderPlugin::canDecode(File* src) { OggVorbis_File vf; src->openRO(); int r = ov_test_callbacks(src, &vf, 0, 0, _callbacks); ov_clear(&vf); src->close(); return r==0; }
int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){ 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 }; return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks); }
/** * @brief Loads the sound. * * @param snd Sound to load. * @param filename Name of the file to load into sound. */ int sound_al_load( alSound *snd, const char *filename ) { int ret; SDL_RWops *rw; OggVorbis_File vf; ALint freq, bits, channels, size; /* get the file data buffer from packfile */ rw = ndata_rwops( filename ); /* Check to see if it's an OGG. */ if (ov_test_callbacks( rw, &vf, NULL, 0, sound_al_ovcall_noclose )==0) { ret = sound_al_loadOgg( snd, &vf ); } /* Otherwise try WAV. */ else { /* Destroy the partially loaded vorbisfile. */ ov_clear(&vf); /* Try to load Wav. */ ret = sound_al_loadWav( snd, rw ); } /* Close RWops. */ SDL_RWclose(rw); /* Failed to load. */ if (ret != 0) { WARN("Failed to load sound file '%s'.", filename); return ret; } soundLock(); /* Get the length of the sound. */ alGetBufferi( snd->u.al.buf, AL_FREQUENCY, &freq ); alGetBufferi( snd->u.al.buf, AL_BITS, &bits ); alGetBufferi( snd->u.al.buf, AL_CHANNELS, &channels ); alGetBufferi( snd->u.al.buf, AL_SIZE, &size ); if ((freq==0) || (bits==0) || (channels==0)) { WARN("Something went wrong when loading sound file '%s'.", filename); snd->length = 0; } else snd->length = (double)size / (double)(freq * (bits/8) * channels); /* Check for errors. */ al_checkErr(); soundUnlock(); return 0; }
bool OAOggVorbisReader::isValid(const SPtr<DataStream>& stream) { stream->seek(0); OggVorbis_File file; if (ov_test_callbacks(stream.get(), &file, nullptr, 0, callbacks) == 0) { ov_clear(&file); return true; } return false; }
bool OggVorbisDecoder::isValid(const SPtr<DataStream>& stream, UINT32 offset) { stream->seek(offset); mDecoderData.stream = stream; mDecoderData.offset = offset; OggVorbis_File file; if (ov_test_callbacks(&mDecoderData, &file, nullptr, 0, callbacks) == 0) { ov_clear(&file); return true; } return false; }
bool SndSysOggSoundData::IsOgg (iDataBuffer* Buffer) { // This is a static function, no member variables are used OggDataStore datastore(Buffer); OggStreamData streamdata; streamdata.datastore=&datastore; streamdata.position=0; OggVorbis_File f; memset (&f, 0, sizeof(OggVorbis_File)); bool ok = ov_test_callbacks(&streamdata, &f, 0, 0, ogg_callbacks) == 0; ov_clear (&f); return ok; }
bool VorbisDecoder::determineCodec( const char *data, size_t size ) { VorbisMemoryFile vorbisData; vorbisData.data = (char *)data; vorbisData.size = size; vorbisData.sizeRead = 0; OggVorbis_File vorbisFile; if( ov_test_callbacks( &vorbisData, &vorbisFile, 0x0, 0, vorbisCallbacks ) < 0 ) { //it's not a vorbis file, clean up and return false ov_clear( &vorbisFile ); return false; } ov_clear( &vorbisFile ); return true; }
bool CSoundOgg::isOggFile(const std::string &name){ CSoundOgg ogg; ogg.mFile = CFile(name); try { ogg.mFile.loadData(); } catch (CException e) { return false; } ogg.mFileData = (char *)ogg.mFile.getData(); ogg.mFilePos = 0; ov_callbacks cb; cb.read_func = read_func; cb.seek_func = seek_func; cb.close_func = close_func; cb.tell_func = tell_func; S32 res = ov_test_callbacks(&ogg, &ogg.mOggFile, 0, 0, cb); return res == 0 ? true : false; }
void Sound::Impl::PlaySound(const boost::filesystem::path& path, bool is_ui_sound/* = false*/) { if (!m_initialized || !GetOptionsDB().Get<bool>("UI.sound.enabled") || (is_ui_sound && UISoundsTemporarilyDisabled())) return; std::string filename = PathString(path); ALuint current_buffer; ALenum source_state; ALsizei ogg_freq; FILE *file = nullptr; int m_i; bool found_buffer = false; 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()) { /* 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; found_buffer = true; } else { if ((file = fopen(filename.c_str(), "rb")) != nullptr) { // 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, nullptr, 0, callbacks))) // check if it's a proper ogg #else if (!(ov_test(file, &ogg_file, nullptr, 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; found_buffer = true; m_buffers.insert(std::make_pair(filename, sound_handle)); } else { ErrorLogger() << "PlaySound: unable to open file " << filename.c_str() << " too big to buffer. Aborting\n"; } ov_clear(&ogg_file); } else { ErrorLogger() << "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) ErrorLogger() << "PlaySound: Could not find aviable source - playback aborted\n"; } source_state = alGetError(); if (source_state != AL_NONE) ErrorLogger() << "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. */ } }
void Sound::Impl::PlayMusic(const boost::filesystem::path& path, int loops /* = 0*/) { if (!m_initialized) return; ALenum m_openal_error; std::string filename = PathString(path); FILE* m_f = nullptr; 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()) { if (m_music_name.size() > 0) StopMusic(); if ((m_f = fopen(filename.c_str(), "rb")) != nullptr) // make sure we CAN open it { #ifdef FREEORION_WIN32 if (!(ov_test_callbacks(m_f, &m_ogg_file, nullptr, 0, callbacks))) // check if it's a proper ogg #else if (!(ov_test(m_f, &m_ogg_file, nullptr, 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 { ErrorLogger() << "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 ErrorLogger() << "PlayMusic: unable to open file " << filename.c_str() << " I/O Error. Aborting\n"; } m_openal_error = alGetError(); if (m_openal_error != AL_NONE) ErrorLogger() << "PlayMusic: OpenAL ERROR: " << alGetString(m_openal_error); }
VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const char * filename, ov_callbacks *callbacks_p, off_t other_header_bytes, const vgm_vorbis_info_t *vgm_inf) { VGMSTREAM * vgmstream = NULL; OggVorbis_File temp_ovf; ogg_vorbis_streamfile temp_streamfile; ogg_vorbis_codec_data * data = NULL; OggVorbis_File *ovf; int inited_ovf = 0; vorbis_info *info; int loop_flag = vgm_inf->loop_flag; int32_t loop_start = vgm_inf->loop_start; int loop_length_found = vgm_inf->loop_length_found; int32_t loop_length = vgm_inf->loop_length; int loop_end_found = vgm_inf->loop_end_found; int32_t loop_end = vgm_inf->loop_end; ov_callbacks default_callbacks; if (!callbacks_p) { default_callbacks.read_func = read_func; default_callbacks.seek_func = seek_func; default_callbacks.close_func = close_func; default_callbacks.tell_func = tell_func; if (vgm_inf->scd_xor != 0) { default_callbacks.read_func = read_func_scd; } callbacks_p = &default_callbacks; } temp_streamfile.streamfile = streamFile; temp_streamfile.offset = 0; temp_streamfile.size = get_streamfile_size(temp_streamfile.streamfile); temp_streamfile.other_header_bytes = other_header_bytes; temp_streamfile.scd_xor = vgm_inf->scd_xor; temp_streamfile.scd_xor_len = vgm_inf->scd_xor_len; /* can we open this as a proper ogg vorbis file? */ memset(&temp_ovf, 0, sizeof(temp_ovf)); if (ov_test_callbacks(&temp_streamfile, &temp_ovf, NULL, 0, *callbacks_p)) goto fail; /* we have to close this as it has the init_vgmstream meta-reading STREAMFILE */ ov_clear(&temp_ovf); /* proceed to open a STREAMFILE just for this stream */ data = calloc(1,sizeof(ogg_vorbis_codec_data)); if (!data) goto fail; data->ov_streamfile.streamfile = streamFile->open(streamFile,filename, STREAMFILE_DEFAULT_BUFFER_SIZE); if (!data->ov_streamfile.streamfile) goto fail; data->ov_streamfile.offset = 0; data->ov_streamfile.size = get_streamfile_size(data->ov_streamfile.streamfile); data->ov_streamfile.other_header_bytes = other_header_bytes; data->ov_streamfile.scd_xor = vgm_inf->scd_xor; data->ov_streamfile.scd_xor_len = vgm_inf->scd_xor_len; /* open the ogg vorbis file for real */ if (ov_open_callbacks(&data->ov_streamfile, &data->ogg_vorbis_file, NULL, 0, *callbacks_p)) goto fail; ovf = &data->ogg_vorbis_file; inited_ovf = 1; data->bitstream = DEFAULT_BITSTREAM; info = ov_info(ovf,DEFAULT_BITSTREAM); /* grab the comments */ { int i; vorbis_comment *comment; comment = ov_comment(ovf,DEFAULT_BITSTREAM); /* search for a "loop_start" comment */ for (i=0;i<comment->comments;i++) { if (strstr(comment->user_comments[i],"loop_start=")== comment->user_comments[i] || strstr(comment->user_comments[i],"LOOP_START=")== comment->user_comments[i] || strstr(comment->user_comments[i],"COMMENT=LOOPPOINT=")== comment->user_comments[i] || strstr(comment->user_comments[i],"LOOPSTART=")== comment->user_comments[i] || strstr(comment->user_comments[i],"um3.stream.looppoint.start=")== comment->user_comments[i] || strstr(comment->user_comments[i],"LOOP_BEGIN=")== comment->user_comments[i] || strstr(comment->user_comments[i],"LoopStart=")== comment->user_comments[i] ) { loop_start=atol(strrchr(comment->user_comments[i],'=')+1); if (loop_start >= 0) loop_flag=1; } else if (strstr(comment->user_comments[i],"LOOPLENGTH=")== comment->user_comments[i]) { loop_length=atol(strrchr(comment->user_comments[i],'=')+1); loop_length_found=1; } else if (strstr(comment->user_comments[i],"title=-lps")== comment->user_comments[i]) { loop_start=atol(comment->user_comments[i]+10); if (loop_start >= 0) loop_flag=1; } else if (strstr(comment->user_comments[i],"album=-lpe")== comment->user_comments[i]) { loop_end=atol(comment->user_comments[i]+10); loop_flag=1; loop_end_found=1; } else if (strstr(comment->user_comments[i],"LoopEnd=")== comment->user_comments[i]) { if(loop_flag) { loop_length=atol(strrchr(comment->user_comments[i],'=')+1)-loop_start; loop_length_found=1; } } else if (strstr(comment->user_comments[i],"LOOP_END=")== comment->user_comments[i]) { if(loop_flag) { loop_length=atol(strrchr(comment->user_comments[i],'=')+1)-loop_start; loop_length_found=1; } } else if (strstr(comment->user_comments[i],"lp=")== comment->user_comments[i]) { sscanf(strrchr(comment->user_comments[i],'=')+1,"%d,%d", &loop_start,&loop_end); loop_flag=1; loop_end_found=1; } } } /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(info->channels,loop_flag); if (!vgmstream) goto fail; /* store our fun extra datas */ vgmstream->codec_data = data; /* fill in the vital statistics */ vgmstream->channels = info->channels; vgmstream->sample_rate = info->rate; /* let's play the whole file */ vgmstream->num_samples = ov_pcm_total(ovf,-1); if (loop_flag) { vgmstream->loop_start_sample = loop_start; if (loop_length_found) vgmstream->loop_end_sample = loop_start+loop_length; else if (loop_end_found) vgmstream->loop_end_sample = loop_end; else vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_flag = loop_flag; if (vgmstream->loop_end_sample > vgmstream->num_samples) vgmstream->loop_end_sample = vgmstream->num_samples; } vgmstream->coding_type = coding_ogg_vorbis; vgmstream->layout_type = vgm_inf->layout_type; vgmstream->meta_type = vgm_inf->meta_type; return vgmstream; /* clean up anything we may have opened */ fail: if (data) { if (inited_ovf) ov_clear(&data->ogg_vorbis_file); if (data->ov_streamfile.streamfile) close_streamfile(data->ov_streamfile.streamfile); free(data); } if (vgmstream) { vgmstream->codec_data = NULL; close_vgmstream(vgmstream); } return NULL; }
void CreateVorbisStream(MFAudioStream *pStream, const char *pFilename) { MFCALLSTACK; MFVorbisStream *pVS = (MFVorbisStream*)MFHeap_Alloc(sizeof(MFVorbisStream)); pStream->pStreamData = pVS; // open vorbis file MFFile* hFile = MFFileSystem_Open(pFilename); if(!hFile) return; // attempt to cache the vorbis stream MFOpenDataCachedFile cachedOpen; cachedOpen.cbSize = sizeof(MFOpenDataCachedFile); cachedOpen.openFlags = MFOF_Read | MFOF_Binary | MFOF_Cached_CleanupBaseFile; cachedOpen.maxCacheSize = 256*1024; // 256k cache for vorbis stream should be heaps!! cachedOpen.pBaseFile = hFile; MFFile *pCachedFile = MFFile_Open(MFFileSystem_GetInternalFileSystemHandle(MFFSH_CachedFileSystem), &cachedOpen); if(pCachedFile) hFile = pCachedFile; // setup vorbis read callbacks ov_callbacks callbacks; callbacks.read_func = MFFile_StdRead; callbacks.seek_func = MFSound_VorbisSeek; callbacks.close_func = MFFile_StdClose; callbacks.tell_func = MFFile_StdTell; // open vorbis file if(ov_test_callbacks(hFile, &pVS->vorbisFile, NULL, 0, callbacks)) { MFDebug_Assert(false, "Not a vorbis file."); MFHeap_Free(pVS); return; } ov_test_open(&pVS->vorbisFile); // get vorbis file info pVS->pInfo = ov_info(&pVS->vorbisFile, -1); #if defined(VORBIS_TREMOR) // pStream->trackLength = (float)ov_pcm_total(&pVS->vorbisFile, -1) / (float)pVS->pInfo->rate; pStream->trackLength = 1000.0f; #else pStream->trackLength = (float)ov_time_total(&pVS->vorbisFile, -1); #endif // fill out the stream info pStream->streamInfo.sampleRate = pVS->pInfo->rate; pStream->streamInfo.channels = pVS->pInfo->channels; pStream->streamInfo.bitsPerSample = 16; pStream->streamInfo.bufferLength = pVS->pInfo->rate; // read the vorbis comment data pVS->pComment = ov_comment(&pVS->vorbisFile, -1); if(pVS->pComment) { const char *pTitle = vorbis_comment_query(pVS->pComment, "TITLE", 0); const char *pArtist = vorbis_comment_query(pVS->pComment, "ALBUM", 0); const char *pAlbum = vorbis_comment_query(pVS->pComment, "ARTIST", 0); const char *pGenre = vorbis_comment_query(pVS->pComment, "GENRE", 0); if(pTitle) MFString_CopyN(pStream->streamInfo.songName, pTitle, sizeof(pStream->streamInfo.songName)-1); if(pArtist) MFString_CopyN(pStream->streamInfo.artistName, pArtist, sizeof(pStream->streamInfo.artistName)-1); if(pAlbum) MFString_CopyN(pStream->streamInfo.albumName, pAlbum, sizeof(pStream->streamInfo.albumName)-1); if(pGenre) MFString_CopyN(pStream->streamInfo.genre, pGenre, sizeof(pStream->streamInfo.genre)-1); } }