使用AudioTrack和C ++在Android中原生播放音频wav文件 [英] Playing audio wav file in Android natively using AudioTrack and C++

查看:812
本文介绍了使用AudioTrack和C ++在Android中原生播放音频wav文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用AudioTrack和C ++播放.wav格式的音频文件.我已经搜索了很多,但是找不到任何相关的教程.

I want to play an audio file in .wav format using AudioTrack and C++. I have searched for it a lot but I couldn't find any relevant tutorial.

我唯一能找到的都是使用Java/JNI层.我想在C ++的本机级别上做到这一点.

The only I could find, were all using Java/JNI layer. I want to do it at the native level in C++.

类似的东西:

file = path_to_file
play(file)

如果您知道的话,请给我指向一些好的教程,或者请提供一些代码片段以使您了解.

Please point me to some good tutorial if you are aware of or please provide me some code snippets to get the idea.

推荐答案

您的本机代码(NativeCode.cpp)应该如下所示: *包括必需的头文件和库.

Your Native Code (NativeCode.cpp) should look like below: *Include required header files and libs.

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代码应类似于以下代码段: 呼叫以开始本地音频流:

Your Java Code should look like below snippet: Call to start the native audio streaming:

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;
}

这篇关于使用AudioTrack和C ++在Android中原生播放音频wav文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆