/* * Check if the file is a valid Ogg Vorbis file. */ qboolean OGG_Check(char *name) { qboolean res; /* Return value. */ byte *buffer; /* File buffer. */ int size; /* File size. */ OggVorbis_File ovf; /* Ogg Vorbis file. */ if (ogg_check->value == 0) { return true; } res = false; if ((size = FS_LoadFile(name, (void **)&buffer)) > 0) { if (ov_test(NULL, &ovf, (char *)buffer, size) == 0) { res = true; ov_clear(&ovf); } FS_FreeFile(buffer); } return res; }
static int ogg_is_our_file(char *filename) { char *ext; FILE *file; unsigned long file_length; OggVorbis_File temp_ogg; //check parameters if ((!filename) || (!ogg_file)) { PE_DBG_PRINTF("MusicEngine: ogg_is_our_file() invalid parameter filename or ogg_file! \n"); return FALSE; } ext = strrchr(filename, (int)'.'); if (ext) { if (!strncasecmp(ext, ".OGG", 4)) { #ifndef ENABLE_PE_CACHE file = fopen(filename, "rb"); // is our file, open file if (!file) { return FALSE; } #else ogg_info_cache_id = pe_cache_open(filename, NULL, OGG_CACHE_SIZE, OGG_BLOCK_SIZE); if (ogg_info_cache_id < 0) { libc_printf("<%d> <%s> pe_cache_open failed!\n", __LINE__, __FUNCTION__); return FALSE; } file = (FILE *)(((UINT32)ogg_info_cache_id | PE_CACHE_ID_TAG)); #endif if(ov_test(file, &temp_ogg, NULL, 0) < 0) // 这里跟着调用的文件系统函数,不是pe_cache 接口 { PE_DBG_PRINTF("Input does not appear to be an Ogg bitstream.\n"); #ifndef ENABLE_PE_CACHE fclose(file); // if test not ogg, close file #else pe_cache_close(ogg_info_cache_id); ogg_info_cache_id = -1; #endif return FALSE; } ov_clear(&temp_ogg); // 如果完成,在这里就会调用close return TRUE; } } PE_DBG_PRINTF("Input does not appear to be an Ogg bitstream.\n"); return FALSE; }
// // OGG support // static bool isOGGFile(const char *pszFilePath) { FILE *file; OggVorbis_File ogg_file; int result; file = fopen(pszFilePath, "rb"); result = ov_test(file, &ogg_file, 0, 0); ov_clear(&ogg_file); return (result == 0); }
/* Fill info structure with data from ogg comments */ static void vorbis_tags (const char *file_name, struct file_tags *info, const int tags_sel) { OggVorbis_File vf; FILE *file; int err_code; if (!(file = fopen (file_name, "r"))) { logit ("Can't open an OGG file: %s", strerror(errno)); return; } /* ov_test() is faster than ov_open(), but we can't read file time * with it. */ if (tags_sel & TAGS_TIME) { if ((err_code = ov_open(file, &vf, NULL, 0)) < 0) { char *vorbis_err = vorbis_strerror (err_code); logit ("Can't open %s: %s", file_name, vorbis_err); free (vorbis_err); fclose (file); return; } } else { if ((err_code = ov_test(file, &vf, NULL, 0)) < 0) { char *vorbis_err = vorbis_strerror (err_code); logit ("Can't open %s: %s", file_name, vorbis_err); free (vorbis_err); fclose (file); return; } } if (tags_sel & TAGS_COMMENTS) get_comment_tags (&vf, info); if (tags_sel & TAGS_TIME) { int64_t vorbis_time; vorbis_time = ov_time_total (&vf, -1); if (vorbis_time >= 0) info->time = vorbis_time / time_scaler; } ov_clear (&vf); }
BOOL ovd_test_file(LPCTSTR pszFile) { if (!_tcslen(pszFile)) return FALSE; FILE* fp = _tfopen(pszFile, _T("rb")); if (!fp) return NULL; OggVorbis_File vf; int ret = ov_test(fp, &vf, NULL, 0); fclose(fp); ov_clear(&vf); return ret == 0; }
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); }