bool C4MusicFileOgg::Play(bool loop) { // Load Song size_t iFileSize; if (!C4Group_ReadFile(FileName, &Data, &iFileSize)) return false; // init fsound int loop_flag = loop ? FSOUND_LOOP_NORMAL : 0; stream = FSOUND_Stream_Open(Data, FSOUND_LOADMEMORY | FSOUND_NORMAL | FSOUND_2D | loop_flag, 0, iFileSize); if (!stream) return false; // Play Song Channel = FSOUND_Stream_Play(FSOUND_FREE, stream); if (Channel == -1) return false; // Set highest priority if (!FSOUND_SetPriority(Channel, 255)) return false; Playing = true; FSOUND_Stream_SetEndCallback(stream, &C4MusicFileOgg::OnEnd, this); return true; }
bool C4MusicFileMP3::Play(bool loop) { #ifndef USE_MP3 return false; #endif // Load Song size_t iFileSize; if (!C4Group_ReadFile(FileName, &Data, &iFileSize)) return false; // init fsound int loop_flag = loop ? FSOUND_LOOP_NORMAL : 0; stream = FSOUND_Stream_Open(Data, FSOUND_LOADMEMORY | FSOUND_NORMAL | FSOUND_2D | loop_flag, 0, iFileSize); if (!stream) return false; // Play Song Channel = FSOUND_Stream_Play(FSOUND_FREE, stream); if (Channel == -1) return false; // Set highest priority if (!FSOUND_SetPriority(Channel, 255)) return false; return true; }
bool C4MusicFileSDL::Play(bool loop) { const SDL_version * link_version = Mix_Linked_Version(); if (link_version->major < 1 || (link_version->major == 1 && link_version->minor < 2) || (link_version->major == 1 && link_version->minor == 2 && link_version->patch < 7)) { // Check existance and try extracting it if (!FileExists(FileName)) if (!ExtractFile()) // Doesn't exist - or file is corrupt { LogF("Error reading %s", FileName); return false; } // Load Music = Mix_LoadMUS(SongExtracted ? Config.AtTempPath(C4CFN_TempMusic2) : FileName); // Load failed if (!Music) { LogF("SDL_mixer: %s", SDL_GetError()); return false; } // Play Song if (Mix_PlayMusic(Music, loop? -1 : 1) == -1) { LogF("SDL_mixer: %s", SDL_GetError()); return false; } } else { // Load Song // Fixme: Try loading this from the group incrementally for less lag size_t filesize; if (!C4Group_ReadFile(FileName, &Data, &filesize)) { LogF("Error reading %s", FileName); return false; } // Mix_FreeMusic frees the RWop Music = Mix_LoadMUS_RW(SDL_RWFromConstMem(Data, filesize)); if (!Music) { LogF("SDL_mixer: %s", SDL_GetError()); return false; } if (Mix_PlayMusic(Music, loop? -1 : 1) == -1) { LogF("SDL_mixer: %s", SDL_GetError()); return false; } } return true; }
bool C4MusicFileMOD::Play(bool loop) { // Load Song size_t iFileSize; if (!C4Group_ReadFile(FileName, &Data, &iFileSize)) return false; // init fmusic mod = FMUSIC_LoadSongEx(Data, 0, iFileSize, FSOUND_LOADMEMORY, 0, 0); if (!mod) { LogF("FMod: %s", FMOD_ErrorString(FSOUND_GetError())); return false; } // Play Song FMUSIC_PlaySong(mod); return true; }
BOOL C4MusicFileMOD::Play(BOOL loop) { // Load Song size_t iFileSize; if(!C4Group_ReadFile(FileName, &Data, &iFileSize)) return FALSE; // init fmusic mod = FMUSIC_LoadSongEx(Data, 0, iFileSize, FSOUND_LOADMEMORY, 0, 0); if (!mod) { sprintf(OSTR, "FMod: %s", FMOD_ErrorString(FSOUND_GetError())); Log(OSTR); return FALSE; } // Play Song FMUSIC_PlaySong(mod); return TRUE; }
bool C4MusicFileOgg::Init(const char *strFile) { // Clear previous Clear(); // Base init file if (!C4MusicFile::Init(strFile)) return false; // Initial file loading // Currently, the whole compressed file is kept in memory because reading/seeking inside C4Group is problematic. Uncompress while playing. // This uses about 50MB of RAM (for ala's music pack) and 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 char *file_contents; size_t file_size; if (!C4Group_ReadFile(FileName, &file_contents, &file_size)) return false; data.SetOwnedData((BYTE *)file_contents, file_size); // Prepare ogg reader vorbis_info* info; memset(&ogg_file, 0, sizeof(ogg_file)); ov_callbacks callbacks; callbacks.read_func = &::C4SoundLoaders::VorbisLoader::read_func; callbacks.seek_func = &::C4SoundLoaders::VorbisLoader::seek_func; callbacks.close_func = &::C4SoundLoaders::VorbisLoader::close_func; callbacks.tell_func = &::C4SoundLoaders::VorbisLoader::tell_func; // open using callbacks if (ov_open_callbacks(&data, &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; } } } } // mark successfully loaded return loaded = true; }