使用AudioTrack和C ++本地播放Android中的音频wav文件

时间:2015-09-01 04:25:54

标签: native android-2.3-gingerbread

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

我唯一能找到的,都是使用Java / JNI层。我想在C ++的本机级别上完成它。

类似的东西:

file = path_to_file
play(file)

如果您知道或请为我提供一些代码片段,请指点我一些好的教程。

1 个答案:

答案 0 :(得分: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;
}