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.
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