Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 358a3f71 authored by Narayan Kamath's avatar Narayan Kamath Committed by Gerrit Code Review
Browse files

Merge "fix AudioTrack and AudioRecord JNI"

parents 759e0d6a 90d0b9e1
Loading
Loading
Loading
Loading
+39 −6
Original line number Diff line number Diff line
@@ -399,13 +399,46 @@ static jint android_media_AudioRecord_readInShortArray(JNIEnv *env, jobject thi
                                                        jshortArray javaAudioData,
                                                        jint offsetInShorts, jint sizeInShorts) {

    jint read = android_media_AudioRecord_readInByteArray(env, thiz,
                                                        (jbyteArray) javaAudioData,
                                                        offsetInShorts*2, sizeInShorts*2);
    if (read > 0) {
        read /= 2;
    jshort* recordBuff = NULL;
    // get the audio recorder from which we'll read new audio samples
    sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
    if (lpRecorder == NULL) {
        ALOGE("Unable to retrieve AudioRecord object, can't record");
        return 0;
    }
    return read;

    if (!javaAudioData) {
        ALOGE("Invalid Java array to store recorded audio, can't record");
        return 0;
    }

    // get the pointer to where we'll record the audio
    // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such
    // a way that it becomes much more efficient. When doing so, we will have to prevent the
    // AudioSystem callback to be called while in critical section (in case of media server
    // process crash for instance)
    recordBuff = (jshort *)env->GetShortArrayElements(javaAudioData, NULL);

    if (recordBuff == NULL) {
        ALOGE("Error retrieving destination for recorded audio data, can't record");
        return 0;
    }

    // read the new audio data from the native AudioRecord object
    const size_t recorderBuffSize = lpRecorder->frameCount()*lpRecorder->frameSize();
    const size_t sizeInBytes = sizeInShorts * sizeof(short);
    ssize_t readSize = lpRecorder->read(recordBuff + offsetInShorts * sizeof(short),
                                        sizeInBytes > recorderBuffSize ?
                                            recorderBuffSize : sizeInBytes);

    env->ReleaseShortArrayElements(javaAudioData, recordBuff, 0);

    if (readSize < 0) {
        readSize = AUDIORECORD_ERROR_INVALID_OPERATION;
    } else {
        readSize /= sizeof(short);
    }
    return (jint) readSize;
}

// ----------------------------------------------------------------------------
+31 −5
Original line number Diff line number Diff line
@@ -595,13 +595,39 @@ static jint android_media_AudioTrack_native_write_short(JNIEnv *env, jobject th
                                                  jshortArray javaAudioData,
                                                  jint offsetInShorts, jint sizeInShorts,
                                                  jint javaAudioFormat) {
    jint written = android_media_AudioTrack_native_write_byte(env, thiz,
                                                 (jbyteArray) javaAudioData,
                                                 offsetInShorts*2, sizeInShorts*2,
                                                 javaAudioFormat);
    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
    if (lpTrack == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException",
            "Unable to retrieve AudioTrack pointer for write()");
        return 0;
    }

    // get the pointer for the audio data from the java array
    // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such
    // a way that it becomes much more efficient. When doing so, we will have to prevent the
    // AudioSystem callback to be called while in critical section (in case of media server
    // process crash for instance)
    jshort* cAudioData = NULL;
    if (javaAudioData) {
        cAudioData = (jshort *)env->GetShortArrayElements(javaAudioData, NULL);
        if (cAudioData == NULL) {
            ALOGE("Error retrieving source of audio data to play, can't play");
            return 0; // out of memory or no data to load
        }
    } else {
        ALOGE("NULL java array of audio data to play, can't play");
        return 0;
    }
    jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData,
                                offsetInShorts * sizeof(short), sizeInShorts * sizeof(short));
    env->ReleaseShortArrayElements(javaAudioData, cAudioData, 0);

    if (written > 0) {
        written /= 2;
        written /= sizeof(short);
    }
    //ALOGV("write wrote %d (tried %d) shorts in the native AudioTrack with offset %d",
    //     (int)written, (int)(sizeInShorts), (int)offsetInShorts);

    return written;
}