/** * \brief Updates this music when it is playing. * * This function handles the double buffering. * * \return \c true if the music keeps playing, \c false if the end is reached. */ bool Music::update_playing() { // Get the empty buffers. ALint nb_empty; alGetSourcei(source, AL_BUFFERS_PROCESSED, &nb_empty); // Refill them. for (int i = 0; i < nb_empty; i++) { ALuint buffer; alSourceUnqueueBuffers(source, 1, &buffer); // Unqueue the buffer. // Fill it by decoding more data. switch (format) { case SPC: decode_spc(buffer, 4096); break; case IT: decode_it(buffer, 4096); break; case OGG: decode_ogg(buffer, 4096); break; case NO_FORMAT: Debug::die("Invalid music format"); break; } alSourceQueueBuffers(source, 1, &buffer); // Queue it again. } // Check whether there is still something playing. ALint status; alGetSourcei(source, AL_SOURCE_STATE, &status); if (status != AL_PLAYING) { // The end of the file is reached, or we need to decode more data. alSourcePlay(source); } alGetSourcei(source, AL_SOURCE_STATE, &status); return status == AL_PLAYING; }
/** * \brief Updates this music when it is playing. * * This function handles the double buffering. */ void Music::update_playing() { // get the empty buffers ALint nb_empty; alGetSourcei(source, AL_BUFFERS_PROCESSED, &nb_empty); // refill them for (int i = 0; i < nb_empty; i++) { ALuint buffer; alSourceUnqueueBuffers(source, 1, &buffer); // unqueue the buffer // fill it by decoding more data switch (format) { case SPC: decode_spc(buffer, 4096); break; case IT: decode_it(buffer, 4096); break; case OGG: decode_ogg(buffer, 4096); break; case NO_FORMAT: Debug::die("Invalid music format"); break; } alSourceQueueBuffers(source, 1, &buffer); // queue it again } ALint status; alGetSourcei(source, AL_SOURCE_STATE, &status); if (status != AL_PLAYING) { alSourcePlay(source); } }
/** * \brief Loads the file and starts playing this music. * * No other music should be playing. * * \return true if the music was loaded successfully */ bool Music::start() { if (!is_initialized()) { return false; } // First time: find the file. if (file_name.empty()) { find_music_file(id, file_name, format); if (file_name.empty()) { Debug::error(std::string("Cannot find music file 'musics/") + id + "' (tried with extensions .ogg, .it and .spc)" ); return false; } } bool success = true; // create the buffers and the source alGenBuffers(nb_buffers, buffers); alGenSources(1, &source); alSourcef(source, AL_GAIN, volume); // load the music into memory std::string sound_buffer; switch (format) { case SPC: sound_buffer = QuestFiles::data_file_read(file_name); // load the SPC data into the SPC decoding library spc_decoder->load((int16_t*) sound_buffer.data(), sound_buffer.size()); for (int i = 0; i < nb_buffers; i++) { decode_spc(buffers[i], 4096); } break; case IT: sound_buffer = QuestFiles::data_file_read(file_name); // load the IT data into the IT decoding library it_decoder->load(sound_buffer); for (int i = 0; i < nb_buffers; i++) { decode_it(buffers[i], 4096); } break; case OGG: { ogg_mem.position = 0; ogg_mem.loop = this->loop; ogg_mem.data = QuestFiles::data_file_read(file_name); // now, ogg_mem contains the encoded data int error = ov_open_callbacks(&ogg_mem, &ogg_file, nullptr, 0, Sound::ogg_callbacks); if (error) { std::ostringstream oss; oss << "Cannot load music file '" << file_name << "' from memory: error " << error; Debug::error(oss.str()); } else { for (int i = 0; i < nb_buffers; i++) { decode_ogg(buffers[i], 4096); } } break; } case NO_FORMAT: Debug::die("Invalid music format"); break; } // start the streaming alSourceQueueBuffers(source, nb_buffers, buffers); int error = alGetError(); if (error != AL_NO_ERROR) { std::ostringstream oss; oss << "Cannot initialize buffers for music '" << file_name << "': error " << error; Debug::error(oss.str()); success = false; } alSourcePlay(source); // The update() function will then take care of filling the buffers return success; }
/** * @brief Loads the file and starts playing this music. * * No other music should be playing. * * @return true if the music was loaded successfully */ bool Music::start() { if (!is_initialized()) { return false; } Debug::check_assertion(current_music == NULL, StringConcat() << "Cannot play music file '" << file_name << "': a music is already playing"); bool success = true; // create the buffers and the source alGenBuffers(nb_buffers, buffers); alGenSources(1, &source); alSourcef(source, AL_GAIN, volume); // load the music into memory size_t sound_size; char* sound_data; switch (format) { case SPC: FileTools::data_file_open_buffer(file_name, &sound_data, &sound_size); // load the SPC data into the SPC decoding library spc_decoder->load((int16_t*) sound_data, sound_size); FileTools::data_file_close_buffer(sound_data); for (int i = 0; i < nb_buffers; i++) { decode_spc(buffers[i], 4096); } break; case IT: FileTools::data_file_open_buffer(file_name, &sound_data, &sound_size); // load the IT data into the IT decoding library it_decoder->load(sound_data, sound_size); FileTools::data_file_close_buffer(sound_data); for (int i = 0; i < nb_buffers; i++) { decode_it(buffers[i], 4096); } break; case OGG: ogg_mem.position = 0; ogg_mem.loop = true; FileTools::data_file_open_buffer(file_name, &ogg_mem.data, &ogg_mem.size); // now, ogg_mem contains the encoded data int error = ov_open_callbacks(&ogg_mem, &ogg_file, NULL, 0, Sound::ogg_callbacks); if (error) { std::cerr << "Cannot load music file from memory: error " << error << std::endl; } else { for (int i = 0; i < nb_buffers; i++) { decode_ogg(buffers[i], 4096); } } break; } // start the streaming alSourceQueueBuffers(source, nb_buffers, buffers); int error = alGetError(); if (error != AL_NO_ERROR) { std::cerr << "Cannot initialize buffers for music '" << file_name << "': error " << error << std::endl; success = false; } /* else { alSourcePlay(source); int error = alGetError(); if (error != AL_NO_ERROR) { std::cerr << "Cannot play music '" << file_name << "': error " << error << std::endl; success = false; } }*/ alSourcePlay(source); // now the update() function will take care of filling the buffers current_music = this; return success; }
/** * \brief Loads the file and starts playing this music. * * No other music should be playing. * * \return true if the music was loaded successfully */ bool Music::start() { if (!is_initialized()) { return false; } // First time: find the file. if (file_name.empty()) { find_music_file(id, file_name, format); if (file_name.empty()) { Debug::error(std::string("Cannot find music file 'musics/") + id + "' (tried with extensions .ogg, .it and .spc)" ); return false; } } bool success = true; // create the buffers and the source alGenBuffers(nb_buffers, buffers); alGenSources(1, &source); alSourcef(source, AL_GAIN, volume); // load the music into memory std::string sound_buffer; switch (format) { case SPC: sound_buffer = QuestFiles::data_file_read(file_name); // Give the SPC data into the SPC decoder. spc_decoder->load((int16_t*) sound_buffer.data(), sound_buffer.size()); for (int i = 0; i < nb_buffers; i++) { decode_spc(buffers[i], 16384); } break; case IT: sound_buffer = QuestFiles::data_file_read(file_name); // Give the IT data to the IT decoder it_decoder->load(sound_buffer); for (int i = 0; i < nb_buffers; i++) { decode_it(buffers[i], 16384); } break; case OGG: sound_buffer = QuestFiles::data_file_read(file_name); // Give the OGG data to the OGG decoder. success = ogg_decoder->load(std::move(sound_buffer), this->loop); if (success) { for (int i = 0; i < nb_buffers; i++) { decode_ogg(buffers[i], 16384); } } break; case NO_FORMAT: Debug::die("Invalid music format"); break; } if (!success) { Debug::error("Cannot load music file '" + file_name + "'"); } // start the streaming alSourceQueueBuffers(source, nb_buffers, buffers); int error = alGetError(); if (error != AL_NO_ERROR) { std::ostringstream oss; oss << "Cannot initialize buffers for music '" << file_name << "': error " << error; Debug::error(oss.str()); success = false; } alSourcePlay(source); // The update() function will then take care of filling the buffers return success; }