Commit 9e6042f6 authored by David Reid's avatar David Reid

Remove loop detection code for now.

This needs a rethink. My test is no longer looping. Needs further
investigation.
parent dd524565
...@@ -65,20 +65,18 @@ int main(int argc, char** argv) ...@@ -65,20 +65,18 @@ int main(int argc, char** argv)
return -1; return -1;
} }
#if 0
result = ma_sound_group_init(&engine, 0, NULL, &group); result = ma_sound_group_init(&engine, 0, NULL, &group);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
printf("Failed to initialize sound group."); printf("Failed to initialize sound group.");
return -1; return -1;
} }
#endif
#if 1 #if 1
loadNotification.cb.onSignal = on_sound_loaded; loadNotification.cb.onSignal = on_sound_loaded;
loadNotification.pSound = &sound; loadNotification.pSound = &sound;
result = ma_sound_init_from_file(&engine, argv[1], MA_DATA_SOURCE_FLAG_DECODE /*| MA_DATA_SOURCE_FLAG_ASYNC | MA_DATA_SOURCE_FLAG_STREAM*/, &loadNotification, NULL, &sound); result = ma_sound_init_from_file(&engine, argv[1], MA_DATA_SOURCE_FLAG_DECODE /*| MA_DATA_SOURCE_FLAG_ASYNC | MA_DATA_SOURCE_FLAG_STREAM*/, &loadNotification, &group, &sound);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
printf("Failed to load sound: %s\n", argv[1]); printf("Failed to load sound: %s\n", argv[1]);
ma_engine_uninit(&engine); ma_engine_uninit(&engine);
...@@ -98,14 +96,14 @@ int main(int argc, char** argv) ...@@ -98,14 +96,14 @@ int main(int argc, char** argv)
/*ma_data_source_seek_to_pcm_frame(sound.pDataSource, 5000000);*/ /*ma_data_source_seek_to_pcm_frame(sound.pDataSource, 5000000);*/
//ma_sound_group_set_pan(ma_engine_get_master_sound_group(&engine), -1); //ma_sound_group_set_pan(ma_engine_get_master_sound_group(&engine), -1);
//ma_sound_group_set_pitch(ma_engine_get_master_sound_group(&engine), 1.0f); ma_sound_group_set_pitch(&group, 1.1f);
//ma_sound_group_set_start_time(ma_engine_get_master_sound_group(&engine), 2000); //ma_sound_group_set_start_time(ma_engine_get_master_sound_group(&engine), 2000);
//ma_sound_group_set_fade_in_milliseconds(&group, 0, 1, 5000); //ma_sound_group_set_fade_in_milliseconds(&group, 0, 1, 5000);
//ma_sound_group_stop(&group);
//ma_sound_set_fade_in_milliseconds(&sound, 0, 1, 5000); //ma_sound_set_fade_in_milliseconds(&sound, 0, 1, 5000);
/*ma_sound_set_volume(&sound, 0.25f);*/ /*ma_sound_set_volume(&sound, 0.25f);*/
/*ma_sound_set_pitch(&sound, 1.2f);*/ /*ma_sound_set_pitch(&sound, 1.1f);*/
/*ma_sound_set_pan(&sound, 0.0f);*/ /*ma_sound_set_pan(&sound, 0.0f);*/
/*ma_sound_set_looping(&sound, MA_TRUE);*/ /*ma_sound_set_looping(&sound, MA_TRUE);*/
//ma_sound_seek_to_pcm_frame(&sound, 6000000); //ma_sound_seek_to_pcm_frame(&sound, 6000000);
......
...@@ -824,7 +824,6 @@ struct ma_node_output_bus ...@@ -824,7 +824,6 @@ struct ma_node_output_bus
{ {
/* Immutable. */ /* Immutable. */
ma_node* pNode; /* The node that owns this output bus. The input node. Will be null for dummy head and tail nodes. */ ma_node* pNode; /* The node that owns this output bus. The input node. Will be null for dummy head and tail nodes. */
ma_uint32 readCounter; /* For loop prevention. Compared with the current read count of the node graph. If larger, means a loop was encountered and reading is aborted and no samples read. */
ma_uint8 outputBusIndex; /* The index of the output bus on pNode that this output bus represents. */ ma_uint8 outputBusIndex; /* The index of the output bus on pNode that this output bus represents. */
ma_uint8 channels; /* The number of channels in the audio stream for this bus. */ ma_uint8 channels; /* The number of channels in the audio stream for this bus. */
...@@ -849,8 +848,8 @@ struct ma_node_input_bus ...@@ -849,8 +848,8 @@ struct ma_node_input_bus
{ {
/* Mutable via multiple threads. */ /* Mutable via multiple threads. */
ma_node_output_bus head; /* Dummy head node for simplifying some lock-free thread-safety stuff. */ ma_node_output_bus head; /* Dummy head node for simplifying some lock-free thread-safety stuff. */
MA_ATOMIC ma_spinlock lock; /* Unfortunate lock, but significantly simplifies the implementation. Required for thread-safe attaching and detaching. */
MA_ATOMIC ma_uint16 nextCounter; /* This is used to determine whether or not the input bus is finding the next node in the list. Used for thread safety when detaching output buses. */ MA_ATOMIC ma_uint16 nextCounter; /* This is used to determine whether or not the input bus is finding the next node in the list. Used for thread safety when detaching output buses. */
MA_ATOMIC ma_spinlock lock; /* Unfortunate lock, but significantly simplifies the implementation. Required for thread-safe attaching and detaching. */
/* Set once at startup. */ /* Set once at startup. */
ma_uint8 channels; /* The number of channels in the audio stream for this bus. */ ma_uint8 channels; /* The number of channels in the audio stream for this bus. */
...@@ -870,7 +869,6 @@ struct ma_node_base ...@@ -870,7 +869,6 @@ struct ma_node_base
ma_uint16 cachedFrameCountOut; ma_uint16 cachedFrameCountOut;
ma_uint16 cachedFrameCountIn; ma_uint16 cachedFrameCountIn;
ma_uint16 consumedFrameCountIn; ma_uint16 consumedFrameCountIn;
ma_uint32 readCounter; /* For loop prevention. Compared with the current read count of the node graph. If larger, means a loop was encountered and reading is aborted and no samples read. */
/* These variables are read and written between different threads. */ /* These variables are read and written between different threads. */
MA_ATOMIC ma_node_state state; /* When set to stopped, nothing will be read, regardless of the times in stateTimes. */ MA_ATOMIC ma_node_state state; /* When set to stopped, nothing will be read, regardless of the times in stateTimes. */
...@@ -915,7 +913,6 @@ struct ma_node_graph ...@@ -915,7 +913,6 @@ struct ma_node_graph
ma_node_base endpoint; /* Special node that all nodes eventually connect to. Data is read from this node in ma_node_graph_read_pcm_frames(). */ ma_node_base endpoint; /* Special node that all nodes eventually connect to. Data is read from this node in ma_node_graph_read_pcm_frames(). */
/* Read and written by multiple threads. */ /* Read and written by multiple threads. */
MA_ATOMIC ma_uint32 readCounter; /* Nodes spin on this while they wait for reading for finish before returning from ma_node_uninit(). */
MA_ATOMIC ma_bool8 isReading; MA_ATOMIC ma_bool8 isReading;
}; };
...@@ -2108,18 +2105,6 @@ static ma_bool8 ma_node_graph_is_reading(ma_node_graph* pNodeGraph) ...@@ -2108,18 +2105,6 @@ static ma_bool8 ma_node_graph_is_reading(ma_node_graph* pNodeGraph)
} }
#endif #endif
static void ma_node_graph_increment_read_counter(ma_node_graph* pNodeGraph)
{
MA_ASSERT(pNodeGraph != NULL);
c89atomic_fetch_add_32(&pNodeGraph->readCounter, 1);
}
static ma_uint32 ma_node_graph_get_read_counter(ma_node_graph* pNodeGraph)
{
MA_ASSERT(pNodeGraph != NULL);
return c89atomic_load_32(&pNodeGraph->readCounter);
}
static void ma_node_graph_endpoint_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut) static void ma_node_graph_endpoint_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{ {
...@@ -2226,7 +2211,6 @@ MA_API ma_result ma_node_graph_read_pcm_frames(ma_node_graph* pNodeGraph, void* ...@@ -2226,7 +2211,6 @@ MA_API ma_result ma_node_graph_read_pcm_frames(ma_node_graph* pNodeGraph, void*
result = ma_node_read_pcm_frames(&pNodeGraph->endpoint, 0, (float*)ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, ma_format_f32, channels), framesToRead, &framesJustRead, ma_node_get_time(&pNodeGraph->endpoint)); result = ma_node_read_pcm_frames(&pNodeGraph->endpoint, 0, (float*)ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, ma_format_f32, channels), framesToRead, &framesJustRead, ma_node_get_time(&pNodeGraph->endpoint));
} }
ma_node_graph_set_is_reading(pNodeGraph, MA_FALSE); ma_node_graph_set_is_reading(pNodeGraph, MA_FALSE);
ma_node_graph_increment_read_counter(pNodeGraph);
totalFramesRead += framesJustRead; totalFramesRead += framesJustRead;
...@@ -2355,23 +2339,6 @@ static float ma_node_output_bus_get_volume(const ma_node_output_bus* pOutputBus) ...@@ -2355,23 +2339,6 @@ static float ma_node_output_bus_get_volume(const ma_node_output_bus* pOutputBus)
return c89atomic_load_f32((float*)&pOutputBus->volume); return c89atomic_load_f32((float*)&pOutputBus->volume);
} }
static ma_uint32 ma_node_output_bus_set_read_counter(ma_node_output_bus* pOutputBus, ma_uint32 newReadCounter)
{
ma_uint32 oldReadCounter;
MA_ASSERT(pOutputBus != NULL);
/*
This function will only ever be called in a controlled environment (only on the audio thread,
and never concurrently).
*/
oldReadCounter = pOutputBus->readCounter;
pOutputBus->readCounter = newReadCounter;
return oldReadCounter;
}
static ma_result ma_node_input_bus_init(ma_uint32 channels, ma_node_input_bus* pInputBus) static ma_result ma_node_input_bus_init(ma_uint32 channels, ma_node_input_bus* pInputBus)
{ {
...@@ -2659,28 +2626,9 @@ static ma_result ma_node_input_bus_read_pcm_frames(ma_node* pInputNode, ma_node_ ...@@ -2659,28 +2626,9 @@ static ma_result ma_node_input_bus_read_pcm_frames(ma_node* pInputNode, ma_node_
for (pOutputBus = pFirst; pOutputBus != NULL; pOutputBus = ma_node_input_bus_next(pInputBus, pOutputBus)) { for (pOutputBus = pFirst; pOutputBus != NULL; pOutputBus = ma_node_input_bus_next(pInputBus, pOutputBus)) {
ma_uint32 framesProcessed = 0; ma_uint32 framesProcessed = 0;
ma_uint32 readCounter;
MA_ASSERT(pOutputBus->pNode != NULL); MA_ASSERT(pOutputBus->pNode != NULL);
/*
We need to grab the read counter at the start so we can set a new read counter first up. We
need to do this first so that recursive reads can have access to the new counter. Note that
we need to do this here and *not* in ma_node_read_pcm_frames() which would be the more
intuitive option because we need to loop here in order to fill up as many frames as we can
which would cause all iterations after the first to return 0 frames because of the loop
detection logic getting triggered.
*/
readCounter = ma_node_output_bus_set_read_counter(pOutputBus, ma_node_graph_get_read_counter(ma_node_get_node_graph(pOutputBus->pNode)) + 1);
/*
If the node's read counter is larger than that of the graph it means we've hit a loop and
we need to skip this attachment.
*/
if (readCounter > ma_node_graph_get_read_counter(ma_node_get_node_graph(pOutputBus->pNode))) {
continue; /* This output bus has already been processed by the current iteration. */
}
if (pFramesOut != NULL) { if (pFramesOut != NULL) {
/* Read. */ /* Read. */
float temp[MA_DATA_CONVERTER_STACK_BUFFER_SIZE / sizeof(float)]; float temp[MA_DATA_CONVERTER_STACK_BUFFER_SIZE / sizeof(float)];
...@@ -3407,9 +3355,10 @@ static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusInde ...@@ -3407,9 +3355,10 @@ static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusInde
requested, however we still need to clamp it to whatever can fit in the cache. requested, however we still need to clamp it to whatever can fit in the cache.
This will also be used as the basis for determining how many input frames to read. This is This will also be used as the basis for determining how many input frames to read. This is
not ideal because it can result in too many input frames being read which introduces latency, not ideal because it can result in too many input frames being read which introduces latency.
however the alternative requires us to implement another callback in the node's vtable for To solve this, nodes can implement an optional callback called onGetRequiredInputFrameCount
calculating the required input frame count which I'm not willing to do. which is used as hint to miniaudio as to how many input frames it needs to read at a time. This
callback is completely optional, and if it's not set, miniaudio will assume `frameCount`.
This function will be called multiple times for each period of time, once for each output node. This function will be called multiple times for each period of time, once for each output node.
We cannot read from each input node each time this function is called. Instead we need to check We cannot read from each input node each time this function is called. Instead we need to check
......
...@@ -83,17 +83,17 @@ int main(int argc, char** argv) ...@@ -83,17 +83,17 @@ int main(int argc, char** argv)
return -1; return -1;
} }
result = ma_node_attach_output_bus(&g_dataSourceNode, 0, ma_node_graph_get_endpoint(&g_nodeGraph), 0); /*result = ma_node_attach_output_bus(&g_dataSourceNode, 0, ma_node_graph_get_endpoint(&g_nodeGraph), 0);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
printf("Failed to attach node."); printf("Failed to attach node.");
return -1; return -1;
} }*/
/*ma_node_set_state_time(&g_dataSourceNode, ma_node_state_started, 48000*1); /*ma_node_set_state_time(&g_dataSourceNode, ma_node_state_started, 48000*1);
ma_node_set_state_time(&g_dataSourceNode, ma_node_state_stopped, 48000*5);*/ ma_node_set_state_time(&g_dataSourceNode, ma_node_state_stopped, 48000*5);*/
#if 0 #if 1
/* /*
Splitter node. Note that we've already attached the data source node to another, so this section Splitter node. Note that we've already attached the data source node to another, so this section
will test that changing of attachments works as expected. will test that changing of attachments works as expected.
...@@ -109,13 +109,9 @@ int main(int argc, char** argv) ...@@ -109,13 +109,9 @@ int main(int argc, char** argv)
return -1; return -1;
} }
/* Connect both outputs of the splitter to the endpoint for now. Later on we'll test effects and whatnot. */
ma_node_attach_output_bus(&g_loopNode, 0, ma_node_graph_get_endpoint(&g_nodeGraph), 0);
ma_node_attach_output_bus(&g_loopNode, 1, ma_node_graph_get_endpoint(&g_nodeGraph), 0);
/* Adjust the volume of the splitter node's endpoints. We'll just do it 50/50 so that both of them combine to reproduce the original signal at the endpoint. */ /* Adjust the volume of the splitter node's endpoints. We'll just do it 50/50 so that both of them combine to reproduce the original signal at the endpoint. */
ma_node_set_output_bus_volume(&g_loopNode, 0, 0.5f); ma_node_set_output_bus_volume(&g_loopNode, 0, 1.0f);
ma_node_set_output_bus_volume(&g_loopNode, 1, 0.5f); ma_node_set_output_bus_volume(&g_loopNode, 1, 1.0f);
...@@ -135,17 +131,26 @@ int main(int argc, char** argv) ...@@ -135,17 +131,26 @@ int main(int argc, char** argv)
/* Adjust the volume of the splitter node's endpoints. We'll just do it 50/50 so that both of them combine to reproduce the original signal at the endpoint. */ /* Adjust the volume of the splitter node's endpoints. We'll just do it 50/50 so that both of them combine to reproduce the original signal at the endpoint. */
ma_node_set_output_bus_volume(&g_splitterNode, 0, 0.5f); ma_node_set_output_bus_volume(&g_splitterNode, 0, 0.5f);
ma_node_set_output_bus_volume(&g_splitterNode, 1, 0.5f); ma_node_set_output_bus_volume(&g_splitterNode, 1, 0.5f);
/* The data source needs to have it's connection changed from the endpoint to the splitter. */
ma_node_attach_output_bus(&g_dataSourceNode, 0, &g_splitterNode, 0);
#else #else
/* Connect both outputs of the splitter to the endpoint for now. Later on we'll test effects and whatnot. */ /* Connect the loop node directly to the output. */
ma_node_attach_output_bus(&g_loopNode, 0, ma_node_graph_get_endpoint(&g_nodeGraph), 0);
ma_node_attach_output_bus(&g_loopNode, 1, ma_node_graph_get_endpoint(&g_nodeGraph), 0);
/* Connect the splitter node directly to the loop node. */
ma_node_attach_output_bus(&g_splitterNode, 0, &g_loopNode, 0); ma_node_attach_output_bus(&g_splitterNode, 0, &g_loopNode, 0);
ma_node_attach_output_bus(&g_splitterNode, 1, &g_loopNode, 1); ma_node_attach_output_bus(&g_splitterNode, 1, &g_loopNode, 1);
/* Connect the data source node to the splitter node. */
ma_node_attach_output_bus(&g_dataSourceNode, 0, &g_splitterNode, 0);
/* Now loop back to the splitter node to form a loop. */ /* Now loop back to the splitter node to form a loop. */
/*ma_node_attach_output_bus(&g_loopNode, 1, &g_splitterNode, 0);*/ ma_node_attach_output_bus(&g_loopNode, 1, &g_splitterNode, 0);
#endif #endif
/* The data source needs to have it's connection changed from the endpoint to the splitter. */
ma_node_attach_output_bus(&g_dataSourceNode, 0, &g_splitterNode, 0);
#endif #endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment