Skip to main content

utilities

Overview of all shared utility helpers, data structures, and DSP primitives available in react-native-audio-api. Covers C++ utilities in common/cpp/audioapi/utils/, common/cpp/audioapi/core/utils/, common/cpp/audioapi/dsp/, and TypeScript utilities in src/utils/. Use this skill before writing new math, buffer management, or cross-thread code — check if a utility already exists. Trigger phrases: "add a new utility", "what helpers are available", "cross-thread communication", "audio buffer", "DSP math", "circular buffer", "lock-free queue", "off-thread", "SIMD buffer", "time conversion", "parameter automation", "audio constants", "TypeScript utils".

소스 정보

저장소
software-mansion/react-native-audio-api
최근 소스 활동
2026년 10월 6일 14:47
감지된 SKILL.md 언어
영어
스타
848
포크
94

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
3 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
utilities
description
Overview of all shared utility helpers, data structures, and DSP primitives available in react-native-audio-api. Covers C++ utilities in common/cpp/audioapi/utils/, common/cpp/audioapi/core/utils/, common/cpp/audioapi/dsp/, and TypeScript utilities in src/utils/. Use this skill before writing new math, buffer management, or cross-thread code — check if a utility already exists. Trigger phrases: "add a new utility", "what helpers are available", "cross-thread communication", "audio buffer", "DSP math", "circular buffer", "lock-free queue", "off-thread", "SIMD buffer", "time conversion", "parameter automation", "audio constants", "TypeScript utils".
# 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. ```cpp // 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 frames - `pop_front(AudioArray&, size)` / `pop_front(float*, size)` — read oldest frames - `pop_back(AudioArray&, size, offset)` — read newest frames - `getNumberOfAvailableFrames()` — 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](api.md#spscchannelhpp--lock-free-spsc-channel). --- ### `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](api.md#crossthreadeventschedulerhpp--jsaudio-event-queue). --- ### `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](api.md#alignedallocatorhpp--aligned-stl-allocator). --- ### `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](api.md#moveonlyfunctionhpp--non-copyable-function-wrapper). --- ### `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](api.md#resulthpp--rust-style-resultte). --- ### `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](api.md#boundedpriorityqueuehpp--fixed-capacity-sorted-queue). --- ### `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](api.md#taskoffloaderhpp--worker-thread-with-spsc-input). --- ### `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](api.md#benchmarkhpp--timing-utilities-devdebug-only). --- ### `Path.h` — path strings and file:// URLs ```cpp audioapi::path::lowercaseExtension(path) // "wav" for "/tmp/Take.WAV", "" when none audioapi::path::hasExtension(path, {"m4a", "mp4"}) // lowercase, no leading dot audioapi::path::hasNonFileProtocol(path) // http://, content://, ... audioapi::path::normalizeFilePath(pathOrFileUrl) // strips file:// and percent-decodes ``` Pure string work, never touches the disk (that is `FileSystem.hpp`). The extension comes from the file name only, so a dot in a directory name is not mistaken for one. `decoding::pathHasExtension` is a different, older suffix match used by the decoder. ### `FileSystem.hpp` — path queries without `stat` ```cpp audioapi::file_system::fileExists(path) // false also when the path cannot be inspected audioapi::file_system::fileSizeBytes(path) // 0 when missing or unreadable audioapi::file_system::removeFile(path) // no-op when missing ``` Both wrap `std::filesystem` with an `error_code`, so they never throw. Use them instead of a local `::stat` helper; `fstat` on an fd you already opened is a different job and stays inline. ### `UnitConversion.h` — byte unit constants ```cpp audioapi::KB_IN_BYTES // 1024.0 audioapi::MB_IN_BYTES // 1024 * 1024.0 audioapi::GB_IN_BYTES // 1024^3.0 ``` ### `AudioLayout.h` — sample rate + channel count `AudioLayout { float sampleRate; int channelCount; }` with a defaulted `operator==`. It is the file stream in `AudioFileProperties::stream` / `EncoderSettings::stream` and the `layout` of a `StreamFormat` (`encoding/StreamFormat.h`, which adds `maxFramesPerBuffer`). Hold a new pair of these as one `AudioLayout` and compare whole layouts (`inputLayout != outputLayout_`) rather than two fields. Storage typed for a native API stays native: the remux `TrackInfo` structs (`int32_t` from `AMediaFormat_getInt32`, `UInt32` from an ASBD) and the integer rates the Android encoder backends write into WAV headers and `MediaCodec` formats. --- ## `common/cpp/audioapi/core/utils/` — Node and context utilities ### `Constants.h` — global audio constants ```cpp 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](api.md#audiodestructorhpp--off-thread-destruction). --- ### `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](api.md#paramchangeeventhpp--audioparam-automation-event). --- ### `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 to `AudioBuffer` (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](api.md#audioutilshpp--inline-dsp-math). --- ### `AudioBufferPool.hpp` — preallocated planar buffers by pointer `AudioBufferPool<N>` owns N `AudioBuffer`s and hands them out as `AudioBufferLease`s, a `unique_ptr` whose deleter returns the buffer to the pool through a lock-free `SlotFreeList` (any thread, never blocks, no allocation). Use it wherever the audio thread fills a buffer for a worker (`AudioFileWriter`, `AudioRecorderCallback`): the lease travels through the `TaskOffloader` message by move, dropping it anywhere returns the buffer, and a null lease is the shutdown message, so the message struct needs a defaulted `operator==`. Not `shared_ptr`: its control block would allocate on the audio thread. --- ### `VectorMath.h` — SIMD-optimized vector math SIMD-accelerated array operations (Apple Accelerate/vDSP when `HAVE_ACCELERATE` is set by the podspec, otherwise ARM NEON / x86 SSE2). Use for per-channel hot-path processing. Read the header for available functions before writing manual loops. `interleave`/`deinterleave` handle any channel count (planar pointers <-> channel-interleaved); on Accelerate stereo goes through `vDSP_ctoz`/`vDSP_ztoc` and N channels through one strided `vDSP_vsadd` per channel, so platform code should call these rather than hand-roll a repack. The recorder pipeline is planar end to end (`AudioRecorder::onAudioFrames`, `AudioFileWriter`, `AudioRecorderCallback`, `AudioEncoder::encode` all take one pointer per channel); the only repacks are Oboe's interleaved input on Android and the encoder backends' fused interleave-while-quantize. --- ### `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` ```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` ```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` ```ts import FilePreset from './utils/filePresets';
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기