void AudioSource::setLooped(bool looped) { AL_CHECK( alSourcei(_alSource, AL_LOOPING, (looped) ? AL_TRUE : AL_FALSE) ); if (AL_LAST_ERROR()) { GP_ERROR("Failed to set audio source's looped attribute with error: %d", AL_LAST_ERROR()); } _looped = looped; }
AudioSource* AudioSource::clone(NodeCloneContext &context) const { GP_ASSERT(_buffer); ALuint alSource = 0; AL_CHECK( alGenSources(1, &alSource) ); if (AL_LAST_ERROR()) { GP_ERROR("Error generating audio source."); return NULL; } AudioSource* audioClone = new AudioSource(_buffer, alSource); _buffer->addRef(); audioClone->setLooped(isLooped()); audioClone->setGain(getGain()); audioClone->setPitch(getPitch()); audioClone->setVelocity(getVelocity()); if (Node* node = getNode()) { Node* clonedNode = context.findClonedNode(node); if (clonedNode) { audioClone->setNode(clonedNode); } } return audioClone; }
AudioSource* AudioSource::create(const char* url) { // Load from a .audio file. std::string pathStr = url; if (pathStr.find(".audio") != std::string::npos) { Properties* properties = Properties::create(url); if (properties == NULL) { GP_ERROR("Failed to create audio source from .audio file."); return NULL; } AudioSource* audioSource = create((strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace()); SAFE_DELETE(properties); return audioSource; } // Create an audio buffer from this URL. AudioBuffer* buffer = AudioBuffer::create(url); if (buffer == NULL) return NULL; // Load the audio source. ALuint alSource = 0; AL_CHECK( alGenSources(1, &alSource) ); if (AL_LAST_ERROR()) { SAFE_RELEASE(buffer); GP_ERROR("Error generating audio source."); return NULL; } return new AudioSource(buffer, alSource); }
AudioBuffer* AudioBuffer::create(const char* path) { GP_ASSERT(path); // Search the cache for a stream from this file. unsigned int bufferCount = (unsigned int)__buffers.size(); AudioBuffer* buffer = NULL; for (unsigned int i = 0; i < bufferCount; i++) { buffer = __buffers[i]; GP_ASSERT(buffer); if (buffer->_filePath.compare(path) == 0) { buffer->addRef(); return buffer; } } ALuint alBuffer; // Load audio data into a buffer. AL_CHECK( alGenBuffers(1, &alBuffer) ); if (AL_LAST_ERROR()) { GP_ERROR("Failed to create OpenAL buffer; alGenBuffers error: %d", AL_LAST_ERROR()); AL_CHECK( alDeleteBuffers(1, &alBuffer) ); return NULL; } // Load sound file. std::auto_ptr<Stream> stream(FileSystem::open(path)); if (stream.get() == NULL || !stream->canRead()) { GP_ERROR("Failed to load audio file %s.", path); goto cleanup; } // Read the file header char header[12]; if (stream->read(header, 1, 12) != 12) { GP_ERROR("Invalid header for audio file %s.", path); goto cleanup; } // Check the file format if (memcmp(header, "RIFF", 4) == 0) { if (!AudioBuffer::loadWav(stream.get(), alBuffer)) { GP_ERROR("Invalid wave file: %s", path); goto cleanup; } } else if (memcmp(header, "OggS", 4) == 0) { if (!AudioBuffer::loadOgg(stream.get(), alBuffer)) { GP_ERROR("Invalid ogg file: %s", path); goto cleanup; } } else { GP_ERROR("Unsupported audio file: %s", path); goto cleanup; } buffer = new AudioBuffer(path, alBuffer); // Add the buffer to the cache. __buffers.push_back(buffer); return buffer; cleanup: if (alBuffer) AL_CHECK( alDeleteBuffers(1, &alBuffer) ); return NULL; }
AudioBuffer* AudioBuffer::create(const char* path, bool streamed) { GP_ASSERT(path); AudioBuffer* buffer = NULL; if (!streamed) { unsigned int bufferCount = (unsigned int)__buffers.size(); for (unsigned int i = 0; i < bufferCount; i++) { buffer = __buffers[i]; GP_ASSERT(buffer); if (buffer->_filePath.compare(path) == 0) { buffer->addRef(); return buffer; } } } ALuint alBuffer[STREAMING_BUFFER_QUEUE_SIZE]; memset(alBuffer, 0, sizeof(alBuffer)); // Create 1 buffer for non-streamed sounds or full queue for streamed ones. unsigned int queueSize = streamed ? STREAMING_BUFFER_QUEUE_SIZE : 1; for (unsigned int i = 0; i < queueSize; i++) { // Load audio data into a buffer. AL_CHECK(alGenBuffers(1, &alBuffer[i])); if (AL_LAST_ERROR()) { GP_ERROR("Failed to create OpenAL buffer; alGenBuffers error: %d", AL_LAST_ERROR()); AL_CHECK(alDeleteBuffers(1, &alBuffer[i])); return NULL; } } std::unique_ptr<AudioStreamStateWav> streamStateWav; std::unique_ptr<AudioStreamStateOgg> streamStateOgg; // Load sound file. std::unique_ptr<Stream> stream(FileSystem::open(path)); if (stream.get() == NULL || !stream->canRead()) { GP_ERROR("Failed to load audio file %s.", path); goto cleanup; } // Read the file header char header[12]; if (stream->read(header, 1, 12) != 12) { GP_ERROR("Invalid header for audio file %s.", path); goto cleanup; } // Check the file format if (memcmp(header, "RIFF", 4) == 0) { // Fill at least one buffer with sound data. streamStateWav.reset(new AudioStreamStateWav()); if (!AudioBuffer::loadWav(stream.get(), alBuffer[0], streamed, streamStateWav.get())) { GP_ERROR("Invalid wave file: %s", path); goto cleanup; } } else if (memcmp(header, "OggS", 4) == 0) { // Fill at least one buffer with sound data. streamStateOgg.reset(new AudioStreamStateOgg()); if (!AudioBuffer::loadOgg(stream.get(), alBuffer[0], streamed, streamStateOgg.get())) { GP_ERROR("Invalid ogg file: %s", path); goto cleanup; } } else { GP_ERROR("Unsupported audio file: %s", path); goto cleanup; } buffer = new AudioBuffer(path, alBuffer, streamed); buffer->_fileStream.reset(stream.release()); buffer->_streamStateWav.reset(streamStateWav.release()); buffer->_streamStateOgg.reset(streamStateOgg.release()); if (buffer->_streamStateWav.get()) buffer->_buffersNeededCount = (buffer->_streamStateWav->dataSize + STREAMING_BUFFER_SIZE - 1) / STREAMING_BUFFER_SIZE; else if (buffer->_streamStateOgg.get()) buffer->_buffersNeededCount = (buffer->_streamStateOgg->dataSize + STREAMING_BUFFER_SIZE - 1) / STREAMING_BUFFER_SIZE; if (!streamed) __buffers.push_back(buffer); return buffer; cleanup: for (unsigned int i = 0; i < STREAMING_BUFFER_QUEUE_SIZE; i++) { if (alBuffer[i]) AL_CHECK(alDeleteBuffers(1, &alBuffer[i])); } return NULL; }