Skill: Utilities
common/cpp/audioapi/utils/ — Core data structures & primitives
AudioArray.h — float audio array (read header for full API)
Single-channel float buffer. The foundational data type. Use for any per-channel audio data.
Key operations: zero(), sum(source, gain), multiply(source), copy(source), copyReverse(...), copyTo(float*), copyWithin(...), scale(float), normalize(), getMaxAbsValue(), computeConvolution(kernel).
Access: operator[], begin()/end(), span(), subSpan(length, offset).
Constructors copy data — AudioArray always owns its buffer.
AudioBuffer.h — multi-channel container (read header for full API)
Holds N channels of AudioArrayBuffer. Handles up/down-mixing automatically on sum() and copy().
Key operations: getChannel(index), getSharedChannel(index), zero(), sum(source, interpretation), copy(source), deinterleaveFrom(float*, frames), interleaveTo(float*, frames), normalize(), scale(float).
Channel layout constants: ChannelMono=0, ChannelLeft=0, ChannelRight=1, ChannelCenter=2, ChannelLFE=3, ChannelSurroundLeft=4, ChannelSurroundRight=5.
getChannel() returns a non-owning AudioArray*. getSharedChannel() returns shared_ptr<AudioArrayBuffer> (use for JSI transfer).
AudioArrayBuffer.hpp — JSI-transferable audio array
AudioArray + jsi::MutableBuffer. Allows zero-copy transfer of audio data to JS as an ArrayBuffer. Use in getChannelData() patterns.
// Typical usage in HostObject — no copy, JS sees the native memory
auto audioArrayBuffer = audioBuffer_->getSharedChannel(channel);
auto arrayBuffer = jsi::ArrayBuffer(runtime, audioArrayBuffer);
auto float32Array = runtime.global()
.getPropertyAsFunction(runtime, "Float32Array")
.callAsConstructor(runtime, arrayBuffer)
.getObject(runtime);
float32Array.setExternalMemoryPressure(runtime, audioArrayBuffer->size());
CircularAudioArray.h — circular float buffer (read header)
AudioArray subclass acting as a circular queue for streaming audio. Not thread-safe — use only from one thread.
Key operations:
push_back(AudioArray&, size)/push_back(float*, size)— write framespop_front(AudioArray&, size)/pop_front(float*, size)— read oldest framespop_back(AudioArray&, size, offset)— read newest framesgetNumberOfAvailableFrames()— how many frames ready to read
Used in delay lines and streaming buffers.
CircularOverflowableAudioArray.h — overwritable circular buffer
Like CircularAudioArray but overwrites oldest data when full instead of rejecting. Use for recording input where you always want the latest data, not the oldest.
SpscChannel.hpp — lock-free SPSC channel
Bounded single-producer, single-consumer queue built on aligned atomics. Do not use directly — prefer CrossThreadEventScheduler or TaskOffloader unless you need fine-grained control.
For full API see api.md.
CrossThreadEventScheduler.hpp — JS→audio event queue
High-level wrapper over SpscChannel for scheduling lambdas from the JS thread to be executed on the audio thread. This is the standard way to send updates from JS to audio.
For full API see api.md.
AlignedAllocator.hpp — aligned STL allocator
STL-compatible allocator that guarantees N-byte alignment (default 16 bytes, SIMD-friendly). Use when creating buffers that will be processed by SIMD code in VectorMath.
For full API see api.md.
MoveOnlyFunction.hpp — non-copyable function wrapper
Backport of C++23 std::move_only_function. Use instead of std::function when the callable captures a move-only type (e.g. a unique_ptr).
For full API see api.md.
Result.hpp — Rust-style Result<T,E>
Represents either success (Ok) or error (Err). Use at API boundaries (e.g. AudioRecorder::start()). Use NoneType / None for void variants.
For full API see api.md.
BoundedPriorityQueue.hpp — fixed-capacity sorted queue
Non-thread-safe std::multiset backed by an in-object block pool. Fixed compile-time capacity, node recycling, zero heap allocation — safe to use on the audio thread. push returns false when full instead of growing. Used by ParamQueueBase (AudioParam automation) and DeferredEventQueue.
Do not back this with std::pmr. A monotonic_buffer_resource + unsynchronized_pool_resource needs a buffer whose size depends on the standard library's private bookkeeping, and libstdc++ needs far more of it than libc++ — a buffer sized against libc++ threw std::bad_alloc short of capacity on the Linux CI runner while passing locally on macOS. The block pool needs exactly Capacity * SLOT_SIZE bytes everywhere.
For full API see api.md.
TaskOffloader.hpp — worker thread with SPSC input
Spawns a dedicated worker thread that processes items from a SPSC channel. Use when you need to offload a recurring task (e.g. file writing, decoding) to a dedicated thread.
For full API see api.md.
Benchmark.hpp — timing utilities (dev/debug only)
Use getExecutionTime() for one-shot nanosecond timing. Do not leave logAvgExecutionTime in production code.
For full API see api.md.
UnitConversion.h — byte unit constants
audioapi::KB_IN_BYTES // 1024.0
audioapi::MB_IN_BYTES // 1024 * 1024.0
audioapi::GB_IN_BYTES // 1024^3.0
common/cpp/audioapi/core/utils/ — Node and context utilities
Constants.h — global audio constants
RENDER_QUANTUM_SIZE = 128 // frames per render block — never hardcode 128
MAX_FFT_SIZE = 32768
MAX_CHANNEL_COUNT = 32
OCTAVE_RANGE = 1200 // cents per octave
PI = std::numbers::pi_v<float>
MOST_POSITIVE_SINGLE_FLOAT / MOST_NEGATIVE_SINGLE_FLOAT
PROMISE_VENDOR_THREAD_POOL_WORKER_COUNT = 4
AudioDestructor.hpp — off-thread destruction
Offloads shared_ptr destruction to a dedicated worker thread. Use for any object whose destructor may block or deallocate large buffers — both are forbidden on the audio thread.
For full API see api.md.
ParamChangeEvent.hpp — AudioParam automation event
Represents a single Web Audio API automation command (setValueAtTime, linearRampToValueAtTime, etc.). Move-only. Used exclusively within AudioParamEventQueue — do not construct outside of AudioParam scheduling methods.
For full API see api.md.
AudioParamEventQueue.h — sorted automation event queue
Stores and processes ParamChangeEvent objects in time order on the audio thread. Read the header for full API.
AudioGraphManager.h — thread-safe graph mutation queue
Queues connect/disconnect operations from the JS thread for application before each render pass. Do not call its methods directly — go through AudioNode::connect()/disconnect(). Read the header for implementation details.
Locker.h — nullable mutex RAII wrapper
RAII mutex wrapper that can hold nullptr (no-op). Supports Locker::tryLock(mutex) for non-blocking acquisition. Do not use on the audio thread. Locks are forbidden in processNode().
Other core/utils/ classes
AudioDecoder.h— decodes audio files toAudioBuffer(FFmpeg, conditional). Read the header.AudioFileWriter.h— writes PCM to audio files. Read the header.AudioRecorderCallback.h— callback adapter for the platform recorder. Internal.worklets/WorkletsRunner.h— manages JS worklet execution on the audio thread. Internal.
common/cpp/audioapi/dsp/ — DSP helpers
AudioUtils.h — inline DSP math
Provides timeToSampleFrame(), sampleFrameToTime(), linearInterpolate(), linearToDecibels(), decibelsToLinear(), uint8ToFloat() (LE int16 bytes → float).
For full API see api.md.
VectorMath.h — SIMD-optimized vector math
SIMD-accelerated array operations (ARM NEON / x86 SSE2). Use for per-channel hot-path processing. Read the header for available functions before writing manual loops.
FFT.h / Convolver.h / Resampler.h / WaveShaper.h / Windows.hpp
Higher-level DSP blocks. Read each header before use.
SpectrumAnalyser.h — shared windowed-FFT magnitude spectrum
Owns FFT scratch state (Blackman window, temp array, complex scratch, magnitude
output) for the windowed-FFT → linear-magnitude → exponential-smoothing pipeline.
Shared by AnalyserNode (core/analysis/) and WorkletNode
(react-native-audio-worklets, frequency-domain mode) to avoid duplicating that
math — each node keeps its own input buffering/threading and just calls
analyze(timeDomain, smoothingTimeConstant), then reads getMagnitudeData().
Exported via StableAPI.h for the worklets extension package. Not thread-safe;
call analyze()/setFFTSize() from a single thread.
src/utils/ — TypeScript utilities
index.ts
import { clamp, toFloat32Array, assertFiniteSequence } from './utils';
clamp(value, min, max) // clamp a number to [min, max]
toFloat32Array(values) // number[] → Float32Array (passthrough if already)
toFloat32Array(undefined) // → undefined (overload)
assertFiniteSequence(values, errorMessage) // throws TypeError if any value is non-finite
Use toFloat32Array when accepting number[] | Float32Array options. Use assertFiniteSequence in options validators (e.g. PeriodicWave real/imag).
paths.ts
import { isRemoteSource, isBase64Source, isDataBlobString } from './utils/paths';
isRemoteSource(url) // true if starts with http:// or https://
isBase64Source(data) // true if 'data:audio/...;base64,...'
isDataBlobString(data) // true if starts with 'blob:'
Use before passing a URL/path to decoder or streaming APIs to determine the source type.
filePresets.ts
import FilePreset from './utils/filePresets';
FilePreset.Low // 22050 Hz, 48kbps, 16-bit
FilePreset.Medium // 44100 Hz, 128kbps, 16-bit
FilePreset.High // 48000 Hz, 192kbps, 24-bit
FilePreset.Lossless // 48000 Hz, 320kbps, 24-bit, FLAC L8
Use when configuring AudioRecorder file output instead of building FilePresetType objects manually.
Maintenance: see maintenance.md.