Воспроизведение аудио WAV-файла в Android изначально с использованием AudioTrack и C++
Я хочу воспроизвести аудиофайл в формате.wav, используя AudioTrack и C++. Я много искал, но не смог найти подходящего урока.
Единственное, что я смог найти - все они использовали слой Java/JNI. Я хочу сделать это на родном уровне в C++.
Что-то вроде:
file = path_to_file
play(file)
Пожалуйста, укажите мне хороший учебник, если вы знаете, или, пожалуйста, предоставьте мне некоторые фрагменты кода, чтобы получить идею.
1 ответ
Ваш собственный код (NativeCode.cpp) должен выглядеть следующим образом: * Включите необходимые заголовочные файлы и библиотеки.
JavaVM *gJavaVM = NULL;
static jobject gCallbackObject = NULL;
jmethodID audio_dataCb_methodid = 0;
static pthread_t ThreadAudio = NULL;
struct pthread_args_structs {
int buf_size;
};
void *nativeAudioData(void *args) {
struct pthread_args_structs *pargs = (pthread_args_structs *) args;
int status;
JNIEnv *env;
status = gJavaVM_->AttachCurrentThread(&env, NULL);
FILE *fp = fopen("/sdcard/sample.wav", "rb");
if (fp == NULL) {
LOGE("file open failed!");
return NULL;
}
int numReadBytes = pargs->buf_size;
jbyteArray data = env->NewByteArray(numReadBytes);
char buf[numReadBytes] = {0};
int res = 0;
jboolean EOFA = JNI_FALSE;
while (!EOFA) {
res = fread(buf, 1, numReadBytes, fp);
if (res > 0) {
env->SetByteArrayRegion(data, 0, res, (jbyte *) buf);
jint ret = env->CallIntMethod(gCallbackObject, audio_dataCb_methodid, data);
if (ret < 0) {
LOGV("callback failed from jni");
break;
}
}
else {
break;
}
usleep(33 * 1000);
}
fclose(fp);
env->DeleteLocalRef(data);
gJavaVM->DetachCurrentThread();
pthread_exit(NULL);
free(args);
ThreadAudio = NULL;
return NULL;
}
JNIEXPORT jint JNICALL
Java_com_app_example_NativeCode_AudioStreaming(JNIEnv *env, jobject instance, jint buf_size) {
struct pthread_args_structs *args = (struct pthread_args_structs *) malloc(
sizeof(struct pthread_args_structs));
args->buf_size = buf_size;
jint rs = env->GetJavaVM(&gJavaVM);
gCallbackObject = env->NewGlobalRef(instance);
jclass javaInterfaceClass = env->FindClass("com/app/example/NativeCode");
audio_dataCb_methodid = env->GetMethodID(javaInterfaceClass, "AudioDataCb",
"([B)I");
if (pthread_create(&ThreadAudio, NULL, &nativeAudioData, (void *) args) != 0) {
LOGE("Error: Uh-oh! JNI Thread Creation Failed \n");
return -1;
}
LOGV("ThreadAudio running...");
return 0;
}
Ваш Java-код должен выглядеть следующим образом: Вызовите, чтобы начать потоковое аудио:
int bufferSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
44100,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize,
AudioTrack.MODE_STREAM);
mAudioTrack.play();
pcmAudioStreaming(bufferSize);
И Обратный звонок Реализация:
AudioTrack mAudioTrack;
public int nativeAudioData(byte[] buffer) {
Log.v(TAG, "nativeAudioData() data len: " +buffer.length);
mAudioTrack.write(buffer, 0, buffer.length);
return 0;
}