OpenSL ES 声音录制 andoridLog

<activity android:name=".OpenSLESActivity" /> 

cmake   配置OpenSLES

cmake_minimum_required(VERSION 3.4.1)

add_library(
             native-lib
             SHARED
             native-lib.cpp
             RecordBuffer.cpp
             AndroidLog.h)

find_library(
              log-lib
              log )

target_link_libraries(
                       native-lib
                       ${log-lib}
                       OpenSLES)

AndroidLog.h

#ifndef RTMPSUC_ANDROIDLOG_H
#define RTMPSUC_ANDROIDLOG_H

#include <android/log.h>

#define LOGD(FORMAT, ...) __android_log_print(ANDROID_LOG_DEBUG,"godv",FORMAT,##__VA_ARGS__);
#define LOGE(FORMAT, ...) __android_log_print(ANDROID_LOG_ERROR,"godv",FORMAT,##__VA_ARGS__);

#define LOG_DEBUG false

#endif //RTMPSUC_ANDROIDLOG_H

native-lib.cpp

#include <jni.h>
#include <string>

#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>

#include "RecordBuffer.h"
#include "AndroidLog.h"

SLObjectItf slObjectEngine = NULL;
SLEngineItf engineItf = NULL;

//录音器
SLObjectItf recordObj = NULL;
SLRecordItf recordItf = NULL;

SLAndroidSimpleBufferQueueItf recorderBufferQueue = NULL;

//声明队列
RecordBuffer *recordBuffer;

//文件
FILE *pcmFile = NULL;
bool finish = false;

//回调方法
void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context) {
    fwrite(recordBuffer->getNowBuffer(), 1, 4096, pcmFile);
    if (finish) {
        LOGE("录制完成");
        //改变状态
        (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_STOPPED);
        (*recordObj)->Destroy(recordObj);
        recordObj = NULL;
        recordItf = NULL;
        (*slObjectEngine)->Destroy(slObjectEngine);
        slObjectEngine = NULL;
        engineItf = NULL;
        delete (recordBuffer);
    } else {
        LOGE("正在录制");
        (*recorderBufferQueue)->Enqueue(recorderBufferQueue, recordBuffer->getRecordBuffer(), 4096);
    }
}


extern "C"
JNIEXPORT void JNICALL
Java_com_example_glivepush_OpenSLESActivity_startRecord(JNIEnv *env, jobject thiz, jstring path_) {
    const char *path = env->GetStringUTFChars(path_, 0);

    recordBuffer = new RecordBuffer(4096);
    pcmFile = fopen(path, "w");
    finish = false;

    //创建引擎
    slCreateEngine(&slObjectEngine, 0, NULL, 0, NULL, NULL);
    //初始化
    (*slObjectEngine)->Realize(slObjectEngine, SL_BOOLEAN_FALSE);
    //得到
    (*slObjectEngine)->GetInterface(slObjectEngine, SL_IID_ENGINE, &engineItf);


    //设备
    SLDataLocator_IODevice loc_dev = {
            SL_DATALOCATOR_IODEVICE,
            SL_IODEVICE_AUDIOINPUT,
            SL_DEFAULTDEVICEID_AUDIOINPUT,
            NULL
    };
    SLDataSource audioSrc = {&loc_dev, NULL};

    //队列
    SLDataLocator_AndroidSimpleBufferQueue loc_bq = {
            SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
            2
    };

    //1 格式 2 声道数 3 采样率 4 位数 5 位数 6 通道布局(立体) 7 对齐
    SLDataFormat_PCM format_pcm = {
            SL_DATAFORMAT_PCM, 2, SL_SAMPLINGRATE_44_1,
            SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
            SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, SL_BYTEORDER_LITTLEENDIAN
    };

    SLDataSink audioSink = {
            &loc_bq,
            &format_pcm
    };

    const SLInterfaceID id[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
    const SLboolean req[1] = {SL_BOOLEAN_TRUE};

    //创建录音器
    (*engineItf)->CreateAudioRecorder(engineItf, &recordObj, &audioSrc, &audioSink, 1, id, req);
    //初始化
    (*recordObj)->Realize(recordObj, SL_BOOLEAN_FALSE);
    //实例化
    (*recordObj)->GetInterface(recordObj, SL_IID_RECORD, &recordItf);

    (*recordObj)->GetInterface(recordObj, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue);

    //入队
    (*recorderBufferQueue)->Enqueue(recorderBufferQueue, recordBuffer->getRecordBuffer(), 4096);
    //回调
    (*recorderBufferQueue)->RegisterCallback(recorderBufferQueue, bqRecorderCallback, NULL);

    //声明当前录制状态 开始录制
    (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_RECORDING);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_glivepush_OpenSLESActivity_stopRecord(JNIEnv *env, jobject thiz) {
    // TODO: implement stopRecord()
    finish = true;
}

RecordBuffer.h

#ifndef RTMPSUC_RECORDBUFFER_H
#define RTMPSUC_RECORDBUFFER_H

class RecordBuffer {
public:
    //二级指针    一维数组
    short **buffer;
    int index = -1;
public:
    RecordBuffer(int bufferSize);

    ~RecordBuffer();

    short *getRecordBuffer();

    short *getNowBuffer();
};

#endif //RTMPSUC_RECORDBUFFER_H

RecordBuffer.cpp

#include "RecordBuffer.h"

RecordBuffer::RecordBuffer(int bufferSize) {
    buffer = new short *[2];
    for (int i = 0; i < 2; i++) {
        buffer[i] = new short[bufferSize];
    }
}

short *RecordBuffer::getNowBuffer() {
    return buffer[index];
}

short *RecordBuffer::getRecordBuffer() {
    index++;
    if (index > 1) {
        index = 1;
    }
    return buffer[index];
}

RecordBuffer::~RecordBuffer() {
    for (int i = 0; i < 2; i++) {
        delete buffer[i];
    }
    delete buffer;
}

OpenSLESActivity

package com.example.glivepush;

import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

public class OpenSLESActivity extends AppCompatActivity {

    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_open_sles);
    }

    public native void startRecord(String path);

    public native void stopRecord();

    public void startRecord(View view) {
        startRecord(Environment.getExternalStorageDirectory().getAbsolutePath() + "/g_opensl_record.pcm");
    }

    public void stopRecord(View view) {
        stopRecord();
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值