Playing audio wav file in Android natively using AudioTrack and C++

寵の児 提交于 2019-12-02 21:17:57

问题


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.

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

Something like :

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.


回答1:


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

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

And Callback Implementation:

AudioTrack mAudioTrack;
public int nativeAudioData(byte[] buffer) {
        Log.v(TAG, "nativeAudioData() data len: " +buffer.length);
        mAudioTrack.write(buffer, 0, buffer.length);
        return 0;
}


来源:https://stackoverflow.com/questions/32323516/playing-audio-wav-file-in-android-natively-using-audiotrack-and-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!