You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native实时音频处理:C++ Turbo Module与Worklet函数间数据传输类型及优化方案问询

Great question—real-time audio processing with React Native Turbo Modules can be tricky when it comes to efficient data transfer between JS and C++. Let's break down what's going wrong and the best fixes for your case.

Why Your Current Code Crashes

JSI (JavaScript Interface) doesn’t natively support mapping plain JavaScript arrays directly to std::array<float,128> as function parameters or return values. When you try to pass a JS array to your foo function, the runtime can’t properly convert the type, leading to invalid memory access and an immediate crash.

Fix 1: Use TypedArrays (Float32Array) for Safe, Efficient Data Transfer

JS's typed arrays (like Float32Array) are built for binary data and map cleanly to C++ memory buffers via JSI. Here’s how to adjust your code:

App.tsx (JS Side)

let output = outputData[ch];
// Skip converting to a plain Array—use the Float32Array directly
const input = inputData[ch]; // Assume inputData is already Float32Array
const result = TurboModule.foo(input);
output.set(result);

NativeModule.cpp (C++ Side)

#include <jsi/jsi.h>
#include <algorithm>
#include <stdexcept>

using namespace facebook;

jsi::Value NativeSampleModule::foo(jsi::Runtime& rt, const jsi::Value& inputVal) {
    // Validate input is a Float32Array
    if (!inputVal.isObject()) {
        throw jsi::JSError(rt, "Input must be a Float32Array");
    }
    jsi::Object inputObj = inputVal.asObject(rt);
    if (!inputObj.isArrayBuffer(rt)) {
        throw jsi::JSError(rt, "Input must be a Float32Array (backed by ArrayBuffer)");
    }

    // Access the underlying binary data
    jsi::ArrayBuffer inputBuffer = inputObj.getArrayBuffer(rt);
    float* inputData = static_cast<float*>(inputBuffer.data(rt));
    size_t elementCount = inputBuffer.size(rt) / sizeof(float);

    // Enforce your 128-element requirement
    if (elementCount != 128) {
        throw jsi::JSError(rt, "Input must contain exactly 128 float elements");
    }

    // --- Your audio processing logic here ---
    // For example, copy input to output (replace with your actual processing)
    jsi::ArrayBuffer outputBuffer = rt.global()
        .getPropertyAsFunction(rt, "ArrayBuffer")
        .callAsConstructor(rt, elementCount * sizeof(float))
        .asObject(rt)
        .getArrayBuffer(rt);
    float* outputData = static_cast<float*>(outputBuffer.data(rt));
    std::copy(inputData, inputData + elementCount, outputData);

    // Wrap the ArrayBuffer back into a Float32Array for JS
    return jsi::Object::createFromArrayBuffer(rt, outputBuffer);
}

Fix 2: Zero-Copy Optimization (For Real-Time Performance)

If you don’t need to return a new array (e.g., you can modify the input buffer directly), you can avoid copying entirely—critical for low-latency audio:

// Modify the input buffer in-place instead of creating a new one
void NativeSampleModule::processInPlace(jsi::Runtime& rt, const jsi::Value& inputVal) {
    jsi::Object inputObj = inputVal.asObject(rt);
    jsi::ArrayBuffer inputBuffer = inputObj.getArrayBuffer(rt);
    float* data = static_cast<float*>(inputBuffer.data(rt));
    size_t count = inputBuffer.size(rt) / sizeof(float);

    // Process the data directly (e.g., apply gain, filter)
    for (size_t i = 0; i < count; ++i) {
        data[i] *= 0.5f; // Example: reduce volume by 50%
    }
}

On the JS side, just call the function and use the original array (since it’s modified in-place):

TurboModule.processInPlace(inputData[ch]);
output.set(inputData[ch]);

What About "Pointer-like" References in JS?

JavaScript doesn’t support raw pointers, but ArrayBuffer gives you the next best thing: direct access to the underlying binary memory from C++. As long as you ensure the ArrayBuffer isn’t garbage-collected while C++ is using it (which won’t happen if the JS side keeps a reference to the Float32Array during processing), this is safe and efficient.

Key Takeaways

  • Never use plain JS arrays for real-time audio data—typed arrays (Float32Array) are the correct choice.
  • Use ArrayBuffer in JSI to directly access memory between JS and C++, minimizing copies.
  • For low-latency processing, modify buffers in-place instead of creating new ones.

内容的提问来源于stack exchange,提问作者Giles.Spreadborough

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 09:42:36