ma_bool8_isInternal;/* A marker to indicate the sound is managed entirely by the engine. This will be set to true when the sound is created internally by ma_engine_play_sound(). */
/*
/*
We're declaring a resource manager data source object here to save us a malloc when loading a
We're declaring a resource manager data source object here to save us a malloc when loading a
/* Make sure the node graph is uninitialized after the audio thread has been shutdown to prevent accessing of the node graph after being uninitialized. */
/* Make sure the node graph is uninitialized after the audio thread has been shutdown to prevent accessing of the node graph after being uninitialized. */
Fire and forget sounds are never actually removed from the group. In practice there should never be a huge number of sounds playing at the same time so we
should be able to get away with recycling sounds. What we need, however, is a way to switch out the old data source with a new one.
The first thing to do is find an available sound. We will only be doing a forward iteration here so we should be able to do this part without locking. A
sound will be available for recycling if it's marked as internal and is at the end.
/* The old data source has been uninitialized so now we need to initialize the new one. */
/* Now the previous sound needs to be uninitialized. */
result = ma_resource_manager_data_source_init(pEngine->pResourceManager, pFilePath, dataSourceFlags, NULL, &pSound->resourceManagerDataSource);
ma_sound_uninit(&pNextSound->sound);
if (result != MA_SUCCESS) {
}else{
/* We failed to load the resource. We need to return an error. We must also put this sound back up for recycling by setting the at-end flag to true. */
/* No sound available for recycling. Allocate one now. */
c89atomic_exchange_32(&pSound->atEnd, MA_TRUE); /* <-- Put the sound back up for recycling. */
/* Set the data source again. It should always be set to the correct value but just set it again for completeness and consistency with the main init API. */
if(pSound!=NULL){/* Safety check for the allocation above. */
At this point we should have memory allocated for the inlined sound. We just need
to initialize it like a normal sound now.
*/
dataSourceFlags|=MA_SOUND_FLAG_ASYNC;/* For inlined sounds we don't want to be sitting around waiting for stuff to load so force an async load. */
dataSourceFlags|=MA_SOUND_FLAG_NO_DEFAULT_ATTACHMENT;/* We want specific control over where the sound is attached in the graph. We'll attach it manually just before playing the sound. */
/* At this point the sound should be loaded and we can go ahead and add it to the list. The new item becomes the new head. */
}
pSound->pNext=pEngine->pInlinedSoundHead;
} else {
pSound->pPrev=NULL;
/* There's no available sounds for recycling. We need to allocate a sound. This can be done using a stack allocator. */
pSound = (ma_sound*)ma__malloc_from_callbacks(sizeof(*pSound), &pEngine->allocationCallbacks/*, MA_ALLOCATION_TYPE_SOUND*/); /* TODO: This can certainly be optimized. */
if (pSound == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_sound_init_from_file(pEngine, pFilePath, dataSourceFlags, NULL, pGroup, pSound);
pEngine->pInlinedSoundHead=pSound;/* <-- This is what attaches the sound to the list. */
/* The sound needs to be marked as internal for our own internal memory management reasons. This is how we know whether or not the sound is available for recycling. */
pSound->_isInternal = MA_TRUE; /* This is the only place _isInternal will be modified. We therefore don't need to worry about synchronizing access to this variable. */
}
}
ma_mutex_unlock(&pEngine->inlinedSoundLock);
/* Finally we can start playing the sound. */
/* Finally we can start playing the sound. */
result = ma_sound_start(pSound);
result=ma_sound_start(&pSound->sound);
if(result!=MA_SUCCESS){
if(result!=MA_SUCCESS){
/* Failed to start the sound. We need to uninitialize it and return an error. */
/* Failed to start the sound. We need to mark it for recycling and return an error. */