请写一个使用NDK播放声音的例子
时间: 2023-09-07 10:13:43 浏览: 246
好的,以下是一个使用NDK播放声音的例子:
1. 首先,在Android Studio中创建一个新的NDK项目。
2. 在app / src / main / jni目录下创建一个名为audio.c的新文件。
3. 将以下代码复制并粘贴到audio.c文件中:
```c
#include <jni.h>
#include <string.h>
#include <android/log.h>
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#define TAG "AudioPlayer"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
// 声明OpenSL ES接口
SLObjectItf engineObject = NULL;
SLEngineItf engineEngine;
SLObjectItf outputMixObject = NULL;
SLEnvironmentalReverbItf outputMixEnvironmentalReverb = NULL;
SLEnvironmentalReverbSettings reverbSettings = SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;
SLObjectItf playerObject = NULL;
SLPlayItf playerPlay;
SLAndroidSimpleBufferQueueItf playerBufferQueue;
void playerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) {
LOGI("playerCallback");
}
JNIEXPORT void JNICALL
Java_com_example_audioplayer_AudioPlayer_init(JNIEnv *env, jobject instance) {
LOGI("init");
// 创建OpenSL ES引擎
slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
(*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
(*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
// 创建输出混音器
(*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL);
(*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
(*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB, &outputMixEnvironmentalReverb);
(*outputMixEnvironmentalReverb)->SetEnvironmentalReverbProperties(outputMixEnvironmentalReverb, &reverbSettings);
// 创建播放器
SLDataLocator_AndroidSimpleBufferQueue locatorBufferQueue = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
SLDataFormat_PCM formatPcm = {SL_DATAFORMAT_PCM, 1, SL_SAMPLINGRATE_44_1,
SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
SL_SPEAKER_FRONT_CENTER, SL_BYTEORDER_LITTLEENDIAN};
SLDataSource audioSrc = {&locatorBufferQueue, &formatPcm};
SLDataLocator_OutputMix locatorOutputMix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
SLDataSink audioSnk = {&locatorOutputMix, NULL};
const SLInterfaceID ids[1] = {SL_IID_BUFFERQUEUE};
const SLboolean req[1] = {SL_BOOLEAN_TRUE};
(*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc, &audioSnk, 1, ids, req);
(*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
(*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
(*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE, &playerBufferQueue);
(*playerBufferQueue)->RegisterCallback(playerBufferQueue, playerCallback, NULL);
}
JNIEXPORT void JNICALL
Java_com_example_audioplayer_AudioPlayer_play(JNIEnv *env, jobject instance, jbyteArray data_, jint len) {
LOGI("play");
// 将数据写入缓冲区
jbyte *data = (*env)->GetByteArrayElements(env, data_, NULL);
(*playerBufferQueue)->Clear(playerBufferQueue);
(*playerBufferQueue)->Enqueue(playerBufferQueue, data, len);
(*env)->ReleaseByteArrayElements(env, data_, data, 0);
// 开始播放
(*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
}
JNIEXPORT void JNICALL
Java_com_example_audioplayer_AudioPlayer_stop(JNIEnv *env, jobject instance) {
LOGI("stop");
// 停止播放
(*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_STOPPED);
// 销毁播放器
if (playerObject != NULL) {
(*playerObject)->Destroy(playerObject);
playerObject = NULL;
playerPlay = NULL;
playerBufferQueue = NULL;
}
// 销毁输出混音器
if (outputMixObject != NULL) {
(*outputMixObject)->Destroy(outputMixObject);
outputMixObject = NULL;
outputMixEnvironmentalReverb = NULL;
}
// 销毁OpenSL ES引擎
if (engineObject != NULL) {
(*engineObject)->Destroy(engineObject);
engineObject = NULL;
engineEngine = NULL;
}
}
```
4. 在app / src / main / java目录下创建一个名为AudioPlayer.java的新文件,并将以下代码复制并粘贴到其中:
```java
package com.example.audioplayer;
public class AudioPlayer {
static {
System.loadLibrary("audio");
}
public native void init();
public native void play(byte[] data, int len);
public native void stop();
}
```
5. 现在可以在您的应用程序中使用AudioPlayer类来播放声音了。在您的Android应用程序中,创建一个新的AudioPlayer对象并调用init方法来初始化OpenSL ES引擎。然后,使用play方法将PCM音频数据写入缓冲区并开始播放,使用stop方法停止播放并销毁OpenSL ES引擎。
这个例子可能还需要一些改进,比如添加错误处理和音频数据的缓冲等。但这应该可以帮助您入门使用NDK播放声音。
阅读全文