audio - native 缓冲音频

标签 audio android-ndk

这可能是我自己的错误之一,但我似乎无法找到问题所在。在尝试提高应用程序的性能后,我将音频缓冲从 Java 层移到了 native 层。音频处理(录制/播放)已经使用 OpenSL ES API 本地完成。

然而,每当我启动应用程序时, native 缓冲导致我的应用程序崩溃。我使用一个简单的队列实现作为我的缓冲区,其中第一个节点是最旧的数据 (FIFO)。

struct bufferNode{
    struct bufferNode* next;
    jbyte* data;
};

struct bufferQueue{
    struct bufferNode* first;
    struct bufferNode* last;
    int size;
};

音频数据由 bufferNode 中的 jbyte* 引用。对队列的访问是通过这两种方法完成的,并与互斥锁同步。
void enqueueInBuffer(struct bufferQueue* queue, jbyte* data){
    SLresult result;
    if(queue != NULL){
        if(data != NULL){
            result = pthread_mutex_lock(&recMutex);
            if(result != 0){
                decodeMutexResult(result);
                logErr("EnqueueInBuffer", "Unable to acquire recording mutex");
            } else {
                struct bufferNode* node = (struct bufferNode*)malloc(sizeof(struct bufferNode));
                if(node == NULL){
                    logErr("EnqueueInBuffer", "Insufficient memory available to buffer new audio");
                } else {
                    node->data = data;
                    if(queue->first == NULL){
                        queue->first = queue->last = node;
                    } else {
                        queue->last->next = node;
                        queue->last = node;
                    }
                    queue->size = queue->size + 1;
                    node->next = NULL;
                }
            }
            result = pthread_mutex_unlock(&recMutex);
            if(result != 0){
                decodeMutexResult(result);
                logErr("EnqueueInBuffer", "Unable to release recording mutex");
            }
        } else {
            logErr("EnqueueInBuffer", "Data is NULL");
        }
    } else {
        logErr("EnqueueInBuffer", "Queue is NULL");
    }
}

void dequeueFromBuffer(struct bufferQueue* queue, jbyte* returnData){
    SLresult result;
    result = pthread_mutex_lock(&recMutex);
    if(result != 0){
        decodeMutexResult(result);
        logErr("DequeueFromBuffer", "Unable to acquire recording mutex");
    } else {
        if(queue->first == NULL){
            returnData = NULL;
        } else {
            returnData = queue->first->data;
            struct bufferNode* tmp = queue->first;
            if(queue->first == queue->last){
                queue->first = queue->last = NULL;
            } else {
                queue->first = queue->first->next;
            }
            free(tmp);
            queue->size = queue->size - 1;
        }
    }
    result = pthread_mutex_unlock(&recMutex);
    if(result != 0){
        decodeMutexResult(result);
        logErr("DequeueFromBuffer", "Unable to release recording mutex");
    }
}
  • 其中 log 和 decode 方法是自我声明的实用方法。 Log 只是将消息记录到 logcat,而 decode 方法“解码”之前方法调用中可能出现的任何错误号。

  • 然而,当我尝试将音频数据排入队列时,我不断收到错误消息。每当我调用enqueueInBuffer方法,我得到一个 SIGSEGV native 错误,代码为 1 (SEGV_MAPERR)。但是我似乎无法找到导致错误的原因。当我尝试制作 enqueueInBuffer 时,队列和音频数据都存在方法调用(在 OpenSL ES Recorder 回调中完成,因此是同步的)。

    是否还有其他原因导致段错误?可能我对此负责,但我似乎找不到错误。

    最佳答案

    显然,这是由我的 OpenSL ES Recorder 回调中的一行代码引起的。

    回调最初看起来像这样:

    void recorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context){
        SLresult result;
        enqueueInBuffer(&recordingQueue, (*recorderBuffers[queueIndex]));
        result = (*bq)->Enqueue(bq, recorderBuffers[queueIndex], RECORDER_FRAMES * sizeof(jbyte));
        if(checkError(result, "RecorderCallB", "Unable to enqueue new buffer on recorder") == -1){
            return;
        }
        queueIndex = queueIndex++ % MAX_RECORDER_BUFFERS;
    }
    

    但是,回调的最后一行似乎没有正确创建新索引。我使用的缓冲区位于一个 4 长的数组中。

    将最后一行更改为
    queueIndex = (queueIndex + 1) % MAX_RECORDER_BUFFERS;
    

    似乎已经修复了错误。

    关于audio - native 缓冲音频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7317348/

    相关文章:

    android - Android 上的 TCP FAST OPEN

    android - 在 Android 上使用 FFMPEG 库进行视频压缩

    android - 如何在 Android 中自动播放/停止默认声音?

    python - 使用 Flask 将音频从 pyaudio 流式传输到 HTML5

    objective-c - 提取音频 objective-c

    c++ - FastCV 腐 eclipse /膨胀参数

    java - 声音将无法在Java中播放。.JFrame和Canvas不是Applet

    android - 使用 libusb 在 UCG102 上设置采样率

    android - 在 Android Studio 中,ndk-build 下的 CMAKE_VERBOSE_MAKEFILE 是什么?

    适用于 x86_64 的 Android NDK 没有 bcopy 和索引引用