Skip to content

Commit 9e74e49

Browse files
committed
0.31.5
1 parent 57de13c commit 9e74e49

File tree

74 files changed

+704
-3619
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+704
-3619
lines changed

buildspec.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,6 @@
4747
"uuids": {
4848
"windowsApp": "ad885c58-5ca9-44de-8f4f-1c12676626a9"
4949
},
50-
"version": "0.31.4",
50+
"version": "0.31.5",
5151
"website": "https://www.atkaudio.com"
5252
}

lib/atkaudio/CMakeLists.txt

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ FetchContent_Declare(
2222
juce
2323
EXCLUDE_FROM_ALL
2424
GIT_REPOSITORY https://github.com/juce-framework/JUCE.git
25-
GIT_TAG
26-
230340dbfc580628596243bb63b31aeb4d6b5a6d # develop 2025-11-27
25+
GIT_TAG 8.0.11
2726
PATCH_COMMAND
2827
${CMAKE_COMMAND} -P "${CMAKE_CURRENT_SOURCE_DIR}/cmake/patches/apply-juce-patches.cmake"
2928
)
@@ -100,41 +99,13 @@ if(NOT WIN32)
10099
)
101100
endif()
102101

103-
# ASIO SDK (Windows only)
104-
if(WIN32)
105-
set(ASIO_SDK_DIR "${CMAKE_SOURCE_DIR}/_deps/asiosdk")
106-
if(NOT EXISTS "${ASIO_SDK_DIR}")
107-
set(_asio_zip "${CMAKE_SOURCE_DIR}/_deps/asiosdk.zip")
108-
set(_asio_temp "${CMAKE_SOURCE_DIR}/_deps/asiosdk_temp")
109-
message(STATUS "Downloading ASIO SDK...")
110-
file(DOWNLOAD "https://www.steinberg.net/asiosdk" "${_asio_zip}" STATUS _status SHOW_PROGRESS)
111-
list(GET _status 0 _code)
112-
if(_code EQUAL 0)
113-
file(ARCHIVE_EXTRACT INPUT "${_asio_zip}" DESTINATION "${_asio_temp}")
114-
file(GLOB _dirs "${_asio_temp}/*")
115-
list(GET _dirs 0 _extracted)
116-
file(RENAME "${_extracted}" "${ASIO_SDK_DIR}")
117-
file(
118-
REMOVE_RECURSE
119-
"${_asio_temp}"
120-
"${_asio_zip}"
121-
)
122-
message(STATUS "ASIO SDK installed to ${ASIO_SDK_DIR}")
123-
endif()
124-
endif()
125-
target_include_directories(${PROJECT_NAME} PRIVATE "${ASIO_SDK_DIR}/common")
126-
endif()
127-
128102
if(WIN32)
129103
file(TO_CMAKE_PATH "${CMAKE_INSTALL_PREFIX}" _sanitized_prefix)
130104
string(REGEX REPLACE "/$" "" _sanitized_prefix "${_sanitized_prefix}")
131105
set(CMAKE_INSTALL_PREFIX "${_sanitized_prefix}" CACHE PATH "Sanitized install prefix" FORCE)
132106
endif()
133107

134-
if(BUILD_WITH_ASIO)
135-
message(STATUS "Building with ASIO")
136-
target_compile_definitions(${PROJECT_NAME} PRIVATE JUCE_ASIO=1)
137-
endif()
108+
target_compile_definitions(${PROJECT_NAME} PRIVATE JUCE_ASIO=1)
138109

139110
target_compile_definitions(${PROJECT_NAME} PRIVATE JUCE_ASIO=1)
140111

lib/atkaudio/src/atkaudio/AtomicSharedPtr.h

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,6 @@
66
namespace atk
77
{
88

9-
/**
10-
* @brief Generic atomic wrapper for shared_ptr to work around std::atomic<std::shared_ptr<T>>
11-
* not being supported in Apple's libc++ implementation (as of macOS 15 / Xcode 17).
12-
*
13-
* This wrapper provides the same interface as std::atomic<std::shared_ptr<T>> would,
14-
* but uses std::atomic<std::shared_ptr<T>*> internally, which is universally supported.
15-
*
16-
* @tparam T The type pointed to by the shared_ptr
17-
*
18-
* @note Once Apple's libc++ supports std::atomic<std::shared_ptr<T>> (check with
19-
* __cpp_lib_atomic_shared_ptr feature macro), this wrapper can be replaced.
20-
*/
219
template <typename T>
2210
class AtomicSharedPtr
2311
{
@@ -45,12 +33,6 @@ class AtomicSharedPtr
4533
AtomicSharedPtr(AtomicSharedPtr&&) = delete;
4634
AtomicSharedPtr& operator=(AtomicSharedPtr&&) = delete;
4735

48-
/**
49-
* @brief Atomically loads and returns the shared_ptr
50-
* @param order Memory ordering constraint
51-
* @return A copy of the stored shared_ptr
52-
* @note When the returned shared_ptr goes out of scope, it may trigger delete
53-
*/
5436
std::shared_ptr<T> load(std::memory_order order = std::memory_order_seq_cst) const
5537
{
5638
auto p = ptr.load(order);
@@ -59,24 +41,13 @@ class AtomicSharedPtr
5941
return std::shared_ptr<T>();
6042
}
6143

62-
/**
63-
* @brief Atomically stores a new shared_ptr, replacing the old one
64-
* @param desired The new shared_ptr to store
65-
* @param order Memory ordering constraint
66-
*/
6744
void store(std::shared_ptr<T> desired, std::memory_order order = std::memory_order_seq_cst)
6845
{
6946
auto newPtr = new std::shared_ptr<T>(std::move(desired));
7047
auto oldPtr = ptr.exchange(newPtr, order);
7148
delete oldPtr;
7249
}
7350

74-
/**
75-
* @brief Atomically replaces the stored shared_ptr and returns the old value
76-
* @param desired The new shared_ptr to store
77-
* @param order Memory ordering constraint
78-
* @return The previously stored shared_ptr
79-
*/
8051
std::shared_ptr<T> exchange(std::shared_ptr<T> desired, std::memory_order order = std::memory_order_seq_cst)
8152
{
8253
auto newPtr = new std::shared_ptr<T>(std::move(desired));

lib/atkaudio/src/atkaudio/AudioProcessorGraphMT/AdaptiveSpinLock.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,8 @@ namespace atk
3232
{
3333

3434
/**
35-
* Adaptive Exponential Backoff Spin Lock
36-
*
37-
* Three modes:
38-
* - Fixed1024: Legacy fixed 1024 pause cycles
39-
* - BenchmarkedAdaptive: Benchmarked exponential backoff based on buffer size/sample rate
40-
* - Fixed8192Backoff (default): Fixed exponential backoff 8→16384, then yield forever
35+
* Adaptive Exponential Backoff Spin Lock for realtime audio.
36+
* Modes: Fixed1024, BenchmarkedAdaptive, Fixed8192Backoff (default).
4137
*/
4238
class AdaptiveSpinLock
4339
{

lib/atkaudio/src/atkaudio/AudioProcessorGraphMT/AudioThreadPool.h

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -174,33 +174,8 @@ class RealtimeJobQueue
174174

175175
//==============================================================================
176176
/**
177-
Global audio thread pool singleton - REALTIME SAFE AUDIO PATH.
178-
179-
This thread pool is designed for realtime audio processing with the following features:
180-
- Singleton instance shared across all audio graph processors
181-
- Persistent worker threads to avoid creation/destruction overhead
182-
- Lock-free job queue for realtime-safe job distribution (atomic fetch_add)
183-
- Barrier synchronization using mutex + condition_variable
184-
- High-priority threads with platform-specific realtime scheduling
185-
186-
Thread safety:
187-
- getInstance()/deleteInstance(): Call only during program load/unload (single-threaded)
188-
- initialize()/shutdown(): Thread-safe via mutex
189-
- prepareJobs(): Call only from main audio thread (before kickWorkers)
190-
- addJob(): Call only from main audio thread (between prepareJobs and kickWorkers)
191-
- kickWorkers(): Call only from main audio thread
192-
- tryStealAndExecuteJob(): Safe to call from any thread
193-
194-
Job queue safety:
195-
- Queue is reset via prepareJobs() before each batch
196-
- Maximum 1024 jobs per batch (queue size)
197-
- Jobs are processed before next prepareJobs() call
198-
199-
Usage pattern:
200-
prepareJobs(barrier); // Main thread: setup barrier, reset queue
201-
addJob(...); // Main thread: add jobs (max 1024)
202-
kickWorkers(); // Main thread: wake workers
203-
barrier->arrive_and_wait(); // Wait for completion
177+
Global audio thread pool singleton for realtime parallel processing.
178+
Lock-free job queue, barrier synchronization, high-priority worker threads.
204179
*/
205180
class AudioThreadPool
206181
{

lib/atkaudio/src/atkaudio/AudioProcessorGraphMT/DagPartitioner.h

Lines changed: 8 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ namespace atk
1515
{
1616

1717
/**
18-
* @brief Simplified DAG partitioner using node-centric model with vector-based storage.
19-
*
20-
* Optimized for performance using only vectors to avoid allocations.
18+
* DAG partitioner for extracting parallelizable subgraphs.
2119
*
2220
* Rules:
2321
* 1) Node exists only once in the graph
@@ -27,27 +25,19 @@ namespace atk
2725
* 5) Every node with NO output connections is an endpoint
2826
* 6) If no other node outputs to this node, it's an input
2927
* 7) If node outputs to >1 nodes, it's a split point (subgraph endpoint)
30-
* => Subgraph ends when: numOutputs != 1
3128
* 8) If node receives input from >1 nodes, it's a join point (new subgraph starts)
32-
* => New subgraph starts when: numInputs != 1
33-
*
34-
* In other words: A subgraph is a linear chain where every node has exactly 1 input and 1 output,
35-
* except at the boundaries.
3629
*
37-
* Template parameter NodeIDType should be copyable and comparable.
30+
* A subgraph is a linear chain where each node has exactly 1 input and 1 output (except boundaries).
3831
*/
3932
template <typename NodeIDType>
4033
class DagPartitioner
4134
{
4235
public:
43-
/**
44-
* @brief Simple node - tracks what it connects to using vectors.
45-
*/
4636
struct Node
4737
{
4838
NodeIDType id;
49-
std::vector<NodeIDType> outputsTo; // Nodes this one outputs to
50-
std::vector<NodeIDType> inputsFrom; // Nodes that output to this one
39+
std::vector<NodeIDType> outputsTo;
40+
std::vector<NodeIDType> inputsFrom;
5141

5242
explicit Node(NodeIDType nodeId = NodeIDType())
5343
: id(nodeId)
@@ -61,15 +51,12 @@ class DagPartitioner
6151
}
6252
};
6353

64-
/**
65-
* @brief Partitioned subgraph result.
66-
*/
6754
struct Subgraph
6855
{
69-
std::vector<NodeIDType> nodeIDs; // Nodes in this subgraph
70-
std::vector<size_t> dependsOn; // Subgraph indices this depends on
71-
std::vector<size_t> dependents; // Subgraph indices that depend on this
72-
int topologicalLevel = 0; // Topological level for scheduling
56+
std::vector<NodeIDType> nodeIDs;
57+
std::vector<size_t> dependsOn;
58+
std::vector<size_t> dependents;
59+
int topologicalLevel = 0;
7360

7461
void clear()
7562
{
@@ -80,9 +67,6 @@ class DagPartitioner
8067
}
8168
};
8269

83-
/**
84-
* @brief Simple thread pool for parallel endpoint tracing.
85-
*/
8670
class ThreadPool
8771
{
8872
public:
@@ -179,31 +163,11 @@ class DagPartitioner
179163
{
180164
}
181165

182-
/**
183-
* @brief Set parallelization threshold.
184-
* @param threshold Minimum number of nodes to enable parallel processing (0 = always parallel)
185-
*/
186166
void setParallelThreshold(size_t threshold)
187167
{
188168
parallelThreshold = threshold;
189169
}
190170

191-
/**
192-
* @brief Extract subgraphs from a node graph.
193-
*
194-
* Uses rules to determine boundaries automatically:
195-
* - Rule 5: Node with 0 outputs = output boundary (endpoint)
196-
* - Rule 6: Node with 0 inputs = input boundary
197-
* - Rule 7: Node with >1 outputs = split point (subgraph endpoint)
198-
* - Rule 8: Node with >1 inputs = join point (new subgraph starts)
199-
*
200-
* Traces from endpoints backwards, creating subgraphs as linear chains.
201-
* Each endpoint is traced in parallel as a separate task.
202-
*
203-
* @param nodes Map of node ID to Node (with connectivity)
204-
* @param excludeNodeIDs Optional vector of node IDs to exclude from subgraphs (e.g., I/O nodes)
205-
* @return Vector of extracted subgraphs
206-
*/
207171
std::vector<Subgraph>
208172
extractSubgraphs(const std::map<NodeIDType, Node>& nodes, const std::vector<NodeIDType>& excludeNodeIDs = {})
209173
{
@@ -278,19 +242,6 @@ class DagPartitioner
278242
return subgraphs;
279243
}
280244

281-
/**
282-
* @brief Build subgraph dependencies and assign topological levels using ASAP scheduling
283-
* with worker-aware load balancing.
284-
*
285-
* Uses As-Soon-As-Possible (ASAP) scheduling with load balancing:
286-
* - Each subgraph is assigned to the earliest possible level (after all dependencies)
287-
* - If a level exceeds numWorkers capacity, excess subgraphs with slack are pushed to later levels
288-
* - A subgraph has "slack" if its earliest dependent is more than 1 level away
289-
*
290-
* @param subgraphs Vector of subgraphs (modified in-place)
291-
* @param nodes Original node graph
292-
* @param numWorkers Number of worker threads (0 or negative = no load balancing)
293-
*/
294245
void buildSubgraphDependencies(
295246
std::vector<Subgraph>& subgraphs,
296247
const std::map<NodeIDType, Node>& nodes,

lib/atkaudio/src/atkaudio/AudioProcessorGraphMT/SubgraphExtractor.h

Lines changed: 8 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,7 @@ namespace atk
99
{
1010

1111
/**
12-
* @brief Extracts subgraphs from a JUCE AudioProcessorGraphMT for parallel processing.
13-
*
14-
* This class bridges between JUCE's audio graph types and the general-purpose
15-
* DagPartitioner. It handles audio-specific concerns like:
16-
* - Converting JUCE Node/Connection types to generic DAG nodes/links
17-
* - Identifying audio and MIDI I/O nodes
18-
* - Preserving connection information in subgraphs
12+
* Extracts subgraphs from AudioProcessorGraphMT for parallel processing.
1913
*/
2014
class SubgraphExtractor
2115
{
@@ -24,49 +18,24 @@ class SubgraphExtractor
2418
using Node = AudioProcessorGraphMT::Node;
2519
using Connection = AudioProcessorGraphMT::Connection;
2620

27-
/**
28-
* @brief Represents a subgraph of audio processors.
29-
*
30-
* Contains JUCE-specific information about nodes and connections
31-
* in addition to the partitioning information from DagPartitioner.
32-
*/
3321
struct Subgraph
3422
{
35-
std::vector<NodeID> nodeIDs; // Audio processor nodes in this subgraph
36-
std::vector<NodeID> inputNodeIDs; // Input I/O nodes feeding this subgraph
37-
std::vector<NodeID> outputNodeIDs; // Output I/O nodes this subgraph feeds to
38-
std::vector<Connection> connections; // JUCE connections within this subgraph
39-
std::vector<size_t> dependsOn; // Indices of subgraphs this one depends on
40-
std::vector<size_t> dependents; // Indices of subgraphs that depend on this one
41-
int topologicalLevel = 0; // Level in dependency hierarchy
23+
std::vector<NodeID> nodeIDs;
24+
std::vector<NodeID> inputNodeIDs;
25+
std::vector<NodeID> outputNodeIDs;
26+
std::vector<Connection> connections;
27+
std::vector<size_t> dependsOn;
28+
std::vector<size_t> dependents;
29+
int topologicalLevel = 0;
4230
};
4331

4432
SubgraphExtractor() = default;
4533

46-
/**
47-
* @brief Set parallelization threshold for DagPartitioner.
48-
* @param threshold Minimum number of nodes to enable parallel processing (0 = always parallel, default = 20)
49-
*/
5034
void setParallelThreshold(size_t threshold)
5135
{
5236
partitioner.setParallelThreshold(threshold);
5337
}
5438

55-
/**
56-
* @brief Extract subgraphs from an AudioProcessorGraphMT for parallel processing.
57-
*
58-
* This method:
59-
* 1. Identifies all audio/MIDI I/O nodes
60-
* 2. Converts the audio graph to generic DAG representation
61-
* 3. Uses DagPartitioner to extract parallelizable subgraphs
62-
* 4. Converts results back to audio-specific subgraph representation
63-
*
64-
* Both audio AND MIDI connections create dependencies - a node must wait for all inputs.
65-
* I/O nodes (audio and MIDI) are excluded from subgraphs as they're handled externally.
66-
*
67-
* @param graph The AudioProcessorGraphMT to extract subgraphs from
68-
* @return Vector of extracted subgraphs with audio-specific information
69-
*/
7039
std::vector<Subgraph> extractUniversalParallelization(atk::AudioProcessorGraphMT& graph)
7140
{
7241
subgraphs.clear();
@@ -172,17 +141,6 @@ class SubgraphExtractor
172141
return subgraphs;
173142
}
174143

175-
/**
176-
* @brief Build dependency relationships between subgraphs and assign topological levels.
177-
*
178-
* This method analyzes connections between subgraphs to determine which can run in parallel.
179-
* Handles both audio AND MIDI connections when determining dependencies.
180-
* Uses ASAP scheduling with worker-aware load balancing when numWorkers > 0.
181-
*
182-
* @param subgraphs Vector of subgraphs (will be modified in-place)
183-
* @param connections Vector of all JUCE connections in the graph
184-
* @param numWorkers Number of worker threads for load balancing (SIZE_MAX = no load balancing)
185-
*/
186144
void buildSubgraphDependencies(
187145
std::vector<Subgraph>& subgraphs,
188146
const std::vector<Connection>& connections,

0 commit comments

Comments
 (0)