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

Commit 9c25ca72 authored by Mingming Yin's avatar Mingming Yin Committed by Linux Build Service Account
Browse files

audio: audio enhancements for playback and recording.

- Add playback and record support for EVRC, QCELP,
  WMA, AMRWBPLUS, WAV, ACE, and EC3.
- Add support for 5.1 channel recording.
- Add support for in call music.
- Add constants for call_state and vsid.
- Add definition for FM and proxy audio devices.
- Remove unnecessary format checks in frameworks.

Change-Id: If3676b88fa287b484ef8616c0a6b67177b61a720
(cherry picked from commit 6ca6cc15af88992ea485a458e67a8546b156672e)
(cherry picked from commit f65028d1752969bf43c853c1bb12ecd12055d5e8)
(cherry picked from commit b1952442db41188b74f331bd2397a579424821ab)
parent 6315d9ef
Loading
Loading
Loading
Loading
+16 −50
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ struct fields_t {
    int       EVRC;                  //...  format constants
    int       EVRCB;                 //...  format constants
    int       EVRCWB;                //...  format constants
    int       EVRCNW;                //...  format constants
    jfieldID  nativeRecorderInJavaObj; // provides access to the C++ AudioRecord object
    jfieldID  nativeCallbackCookie;    // provides access to the AudioRecord callback data
};
@@ -178,9 +179,12 @@ int getformatrec(int audioformat)
        return AUDIO_FORMAT_EVRCB;
    else if(audioformat==javaAudioRecordFields.EVRCWB)
        return AUDIO_FORMAT_EVRCWB;

    else if(audioformat==javaAudioRecordFields.EVRCNW)
        return AUDIO_FORMAT_EVRCNW;
    else
        return AUDIO_FORMAT_PCM_8_BIT;
}

// ----------------------------------------------------------------------------
static int
android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
@@ -205,18 +209,19 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
        && (audioFormat != javaAudioRecordFields.AMRWB)
        && (audioFormat != javaAudioRecordFields.EVRC)
        && (audioFormat != javaAudioRecordFields.EVRCB)
        && (audioFormat != javaAudioRecordFields.EVRCWB)) {
        && (audioFormat != javaAudioRecordFields.EVRCWB)
        && (audioFormat != javaAudioRecordFields.EVRCNW)) {
        ALOGE("Error creating AudioRecord: unsupported audio format.");
        return AUDIORECORD_ERROR_SETUP_INVALIDFORMAT;
    }
    int bytesPerSample;
    if(audioFormat == javaAudioRecordFields.PCM8)
        bytesPerSample = 1;
    if(audioFormat == javaAudioRecordFields.PCM16)
        bytesPerSample = 2;
    else if((audioFormat == javaAudioRecordFields.AMRWB) &&
            ((uint32_t)source != AUDIO_SOURCE_VOICE_COMMUNICATION))
        bytesPerSample = 61;
    else
        bytesPerSample = 2;
        bytesPerSample = 1;
    audio_format_t format = (audio_format_t)getformatrec(audioFormat);

    if (buffSizeInBytes == 0) {
@@ -550,7 +555,7 @@ static jint android_media_AudioRecord_get_min_buff_size(JNIEnv *env, jobject th
    status_t result = AudioRecord::getMinFrameCount(&frameCount,
            sampleRateInHertz,
            (audio_format_t)getformatrec(audioFormat),
            nbChannels);
            audio_channel_in_mask_from_count(nbChannels));

    if (result == BAD_VALUE) {
        return 0;
@@ -559,12 +564,13 @@ static jint android_media_AudioRecord_get_min_buff_size(JNIEnv *env, jobject th
        return -1;
    }
    int bytesPerSample;
    if(audioFormat == javaAudioRecordFields.PCM8)
        bytesPerSample = 1;
    if(audioFormat == javaAudioRecordFields.PCM16)
        bytesPerSample = 2;
    else if(audioFormat == javaAudioRecordFields.AMRWB)
        bytesPerSample = 61;
    else
        bytesPerSample = 2;
        bytesPerSample = 1;

    return frameCount * nbChannels * bytesPerSample;
}

@@ -597,18 +603,8 @@ static JNINativeMethod gMethods[] = {

// field names found in android/media/AudioRecord.java
#define JAVA_POSTEVENT_CALLBACK_NAME  "postEventFromNative"
#define JAVA_CONST_PCM16_NAME         "ENCODING_PCM_16BIT"
#define JAVA_CONST_PCM8_NAME          "ENCODING_PCM_8BIT"
#define JAVA_CONST_AMRNB_NAME         "ENCODING_AMRNB"
#define JAVA_CONST_AMRWB_NAME         "ENCODING_AMRWB"
#define JAVA_CONST_EVRC_NAME          "ENCODING_EVRC"
#define JAVA_CONST_EVRCB_NAME         "ENCODING_EVRCB"
#define JAVA_CONST_EVRCWB_NAME        "ENCODING_EVRCWB"
#define JAVA_NATIVERECORDERINJAVAOBJ_FIELD_NAME  "mNativeRecorderInJavaObj"
#define JAVA_NATIVECALLBACKINFO_FIELD_NAME       "mNativeCallbackCookie"
#define JAVA_AUDIOFORMAT_CLASS_NAME "android/media/AudioFormat"
extern bool android_media_getIntConstantFromClass(JNIEnv* pEnv,
                jclass theClass, const char* className, const char* constName, int* constVal);

// ----------------------------------------------------------------------------
int register_android_media_AudioRecord(JNIEnv *env)
@@ -651,36 +647,6 @@ int register_android_media_AudioRecord(JNIEnv *env)
        return -1;
    }

    jclass audioFormatClass = NULL;
    audioFormatClass = env->FindClass(JAVA_AUDIOFORMAT_CLASS_NAME);
    if (audioFormatClass == NULL) {
        ALOGE("Can't find %s", JAVA_AUDIOFORMAT_CLASS_NAME);
        return -1;
    }
    if ( !android_media_getIntConstantFromClass(env, audioFormatClass,
                JAVA_AUDIOFORMAT_CLASS_NAME,
                JAVA_CONST_PCM16_NAME, &(javaAudioRecordFields.PCM16))
           || !android_media_getIntConstantFromClass(env, audioFormatClass,
                JAVA_AUDIOFORMAT_CLASS_NAME,
                JAVA_CONST_PCM8_NAME, &(javaAudioRecordFields.PCM8))
           || !android_media_getIntConstantFromClass(env, audioFormatClass,
                JAVA_AUDIOFORMAT_CLASS_NAME,
                JAVA_CONST_AMRNB_NAME, &(javaAudioRecordFields.AMRNB))
           || !android_media_getIntConstantFromClass(env, audioFormatClass,
                JAVA_AUDIOFORMAT_CLASS_NAME,
                JAVA_CONST_AMRWB_NAME, &(javaAudioRecordFields.AMRWB))
           || !android_media_getIntConstantFromClass(env, audioFormatClass,
                JAVA_AUDIOFORMAT_CLASS_NAME,
                JAVA_CONST_EVRC_NAME, &(javaAudioRecordFields.EVRC))
           || !android_media_getIntConstantFromClass(env, audioFormatClass,
                JAVA_AUDIOFORMAT_CLASS_NAME,
                JAVA_CONST_EVRCB_NAME, &(javaAudioRecordFields.EVRCB))
           || !android_media_getIntConstantFromClass(env, audioFormatClass,
                JAVA_AUDIOFORMAT_CLASS_NAME,
                JAVA_CONST_EVRCWB_NAME, &(javaAudioRecordFields.EVRCWB))) {
        // error log performed in getIntConstantFromClass()
        return -1;
    }
    return AndroidRuntime::registerNativeMethods(env,
            kClassPathName, gMethods, NELEM(gMethods));
}
+13 −89
Original line number Diff line number Diff line
@@ -227,9 +227,12 @@ int getformat(int audioformat)
        return AUDIO_FORMAT_EVRCB;
    else if(audioformat==javaAudioTrackFields.EVRCWB)
        return AUDIO_FORMAT_EVRCWB;
    else if(audioformat==javaAudioTrackFields.EVRCNW)
        return AUDIO_FORMAT_EVRCNW;

    return AUDIO_FORMAT_PCM_8_BIT;
}

static int
android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
        jint streamType, jint sampleRateInHertz, jint javaChannelMask,
@@ -271,6 +274,7 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
    case AUDIO_STREAM_NOTIFICATION:
    case AUDIO_STREAM_BLUETOOTH_SCO:
    case AUDIO_STREAM_DTMF:
    case AUDIO_STREAM_INCALL_MUSIC:
        atStreamType = (audio_stream_type_t) streamType;
        break;
    default:
@@ -286,7 +290,8 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
        && (audioFormat != javaAudioTrackFields.AMRWB)
        && (audioFormat != javaAudioTrackFields.EVRC)
        && (audioFormat != javaAudioTrackFields.EVRCB)
        && (audioFormat != javaAudioTrackFields.EVRCWB)) {
        && (audioFormat != javaAudioTrackFields.EVRCWB)
        && (audioFormat != javaAudioTrackFields.EVRCNW)) {
        ALOGE("Error creating AudioTrack: unsupported audio format.");
        return AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT;
    }
@@ -305,12 +310,9 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
    }

    // compute the frame count
    int bytesPerSample;
    if(audioFormat == javaAudioTrackFields.PCM8)
        bytesPerSample = 1;
    else
        bytesPerSample = 2;
    audio_format_t format = (audio_format_t)getformat(audioFormat);
    int bytesPerSample = audioFormat == javaAudioTrackFields.PCM16 ? 2 : 1;
    audio_format_t format = audioFormat == javaAudioTrackFields.PCM16 ?
            AUDIO_FORMAT_PCM_16_BIT : AUDIO_FORMAT_PCM_8_BIT;
    int frameCount = buffSizeInBytes / (nbChannels * bytesPerSample);

    jclass clazz = env->GetObjectClass(thiz);
@@ -568,7 +570,8 @@ jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, jbyte* data,
        || (audioFormat == javaAudioTrackFields.AMRWB)
        || (audioFormat == javaAudioTrackFields.EVRC)
        || (audioFormat == javaAudioTrackFields.EVRCB)
        || (audioFormat == javaAudioTrackFields.EVRCWB)) {
        || (audioFormat == javaAudioTrackFields.EVRCWB)
        || (audioFormat == javaAudioTrackFields.EVRCNW)) {
            // writing to shared memory, check for capacity
            if ((size_t)sizeInBytes > track->sharedBuffer()->size()) {
                sizeInBytes = track->sharedBuffer()->size();
@@ -855,6 +858,7 @@ static jint android_media_AudioTrack_get_output_sample_rate(JNIEnv *env, jobjec
    case AUDIO_STREAM_NOTIFICATION:
    case AUDIO_STREAM_BLUETOOTH_SCO:
    case AUDIO_STREAM_DTMF:
    case AUDIO_STREAM_INCALL_MUSIC:
        nativeStreamType = (audio_stream_type_t) javaStreamType;
        break;
    default:
@@ -883,7 +887,7 @@ static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thi
            sampleRateInHertz) != NO_ERROR) {
        return -1;
    }
    return frameCount * nbChannels * (audioFormat == javaAudioTrackFields.PCM8 ? 1 : 2);
    return frameCount * nbChannels * (audioFormat == javaAudioTrackFields.PCM16 ? 2 : 1);
}

// ----------------------------------------------------------------------------
@@ -958,26 +962,8 @@ static JNINativeMethod gMethods[] = {

// field names found in android/media/AudioTrack.java
#define JAVA_POSTEVENT_CALLBACK_NAME                    "postEventFromNative"
#define JAVA_CONST_PCM16_NAME                           "ENCODING_PCM_16BIT"
#define JAVA_CONST_PCM8_NAME                            "ENCODING_PCM_8BIT"
#define JAVA_CONST_AMRNB_NAME                           "ENCODING_AMRNB"
#define JAVA_CONST_AMRWB_NAME                           "ENCODING_AMRWB"
#define JAVA_CONST_EVRC_NAME                            "ENCODING_EVRC"
#define JAVA_CONST_EVRCB_NAME                           "ENCODING_EVRCB"
#define JAVA_CONST_EVRCWB_NAME                          "ENCODING_EVRCWB"
#define JAVA_CONST_BUFFER_COUNT_NAME                    "BUFFER_COUNT"
#define JAVA_CONST_STREAM_VOICE_CALL_NAME               "STREAM_VOICE_CALL"
#define JAVA_CONST_STREAM_SYSTEM_NAME                   "STREAM_SYSTEM"
#define JAVA_CONST_STREAM_RING_NAME                     "STREAM_RING"
#define JAVA_CONST_STREAM_MUSIC_NAME                    "STREAM_MUSIC"
#define JAVA_CONST_STREAM_ALARM_NAME                    "STREAM_ALARM"
#define JAVA_CONST_STREAM_NOTIFICATION_NAME             "STREAM_NOTIFICATION"
#define JAVA_CONST_STREAM_BLUETOOTH_SCO_NAME            "STREAM_BLUETOOTH_SCO"
#define JAVA_CONST_STREAM_DTMF_NAME                     "STREAM_DTMF"
#define JAVA_NATIVETRACKINJAVAOBJ_FIELD_NAME            "mNativeTrackInJavaObj"
#define JAVA_JNIDATA_FIELD_NAME                         "mJniData"
#define JAVA_AUDIOFORMAT_CLASS_NAME             "android/media/AudioFormat"
#define JAVA_AUDIOMANAGER_CLASS_NAME            "android/media/AudioManager"

// ----------------------------------------------------------------------------
// preconditions:
@@ -1036,68 +1022,6 @@ int register_android_media_AudioTrack(JNIEnv *env)
        return -1;
    }

    jclass audioFormatClass = NULL;
    audioFormatClass = env->FindClass(JAVA_AUDIOFORMAT_CLASS_NAME);
    if (audioFormatClass == NULL) {
        ALOGE("Can't find %s", JAVA_AUDIOFORMAT_CLASS_NAME);
        return -1;
    }
    if ( !android_media_getIntConstantFromClass(env, audioFormatClass,
                JAVA_AUDIOFORMAT_CLASS_NAME,
                JAVA_CONST_PCM16_NAME, &(javaAudioTrackFields.PCM16))
           || !android_media_getIntConstantFromClass(env, audioFormatClass,
                JAVA_AUDIOFORMAT_CLASS_NAME,
                JAVA_CONST_PCM8_NAME, &(javaAudioTrackFields.PCM8))
           || !android_media_getIntConstantFromClass(env, audioFormatClass,
                JAVA_AUDIOFORMAT_CLASS_NAME,
                JAVA_CONST_AMRNB_NAME, &(javaAudioTrackFields.AMRNB))
           || !android_media_getIntConstantFromClass(env, audioFormatClass,
                JAVA_AUDIOFORMAT_CLASS_NAME,
                JAVA_CONST_AMRWB_NAME, &(javaAudioTrackFields.AMRWB))
           || !android_media_getIntConstantFromClass(env, audioFormatClass,
                JAVA_AUDIOFORMAT_CLASS_NAME,
                JAVA_CONST_EVRC_NAME, &(javaAudioTrackFields.EVRC))
           || !android_media_getIntConstantFromClass(env, audioFormatClass,
                JAVA_AUDIOFORMAT_CLASS_NAME,
                JAVA_CONST_EVRCB_NAME, &(javaAudioTrackFields.EVRCB))
           || !android_media_getIntConstantFromClass(env, audioFormatClass,
                JAVA_AUDIOFORMAT_CLASS_NAME,
                JAVA_CONST_EVRCWB_NAME, &(javaAudioTrackFields.EVRCWB))
) {
        return -1;
    }
    jclass audioManagerClass = NULL;
    audioManagerClass = env->FindClass(JAVA_AUDIOMANAGER_CLASS_NAME);
    if (audioManagerClass == NULL) {
       ALOGE("Can't find %s", JAVA_AUDIOMANAGER_CLASS_NAME);
       return -1;
    }
    if ( !android_media_getIntConstantFromClass(env, audioManagerClass,
               JAVA_AUDIOMANAGER_CLASS_NAME,
               JAVA_CONST_STREAM_VOICE_CALL_NAME, &(javaAudioTrackFields.STREAM_VOICE_CALL))
          || !android_media_getIntConstantFromClass(env, audioManagerClass,
               JAVA_AUDIOMANAGER_CLASS_NAME,
               JAVA_CONST_STREAM_MUSIC_NAME, &(javaAudioTrackFields.STREAM_MUSIC))
          || !android_media_getIntConstantFromClass(env, audioManagerClass,
               JAVA_AUDIOMANAGER_CLASS_NAME,
               JAVA_CONST_STREAM_SYSTEM_NAME, &(javaAudioTrackFields.STREAM_SYSTEM))
          || !android_media_getIntConstantFromClass(env, audioManagerClass,
               JAVA_AUDIOMANAGER_CLASS_NAME,
               JAVA_CONST_STREAM_RING_NAME, &(javaAudioTrackFields.STREAM_RING))
          || !android_media_getIntConstantFromClass(env, audioManagerClass,
               JAVA_AUDIOMANAGER_CLASS_NAME,
               JAVA_CONST_STREAM_ALARM_NAME, &(javaAudioTrackFields.STREAM_ALARM))
          || !android_media_getIntConstantFromClass(env, audioManagerClass,
               JAVA_AUDIOMANAGER_CLASS_NAME,
               JAVA_CONST_STREAM_NOTIFICATION_NAME, &(javaAudioTrackFields.STREAM_NOTIFICATION))
          || !android_media_getIntConstantFromClass(env, audioManagerClass,
               JAVA_AUDIOMANAGER_CLASS_NAME,
               JAVA_CONST_STREAM_BLUETOOTH_SCO_NAME, &(javaAudioTrackFields.STREAM_BLUETOOTH_SCO))
          || !android_media_getIntConstantFromClass(env, audioManagerClass,
               JAVA_AUDIOMANAGER_CLASS_NAME,
               JAVA_CONST_STREAM_DTMF_NAME, &(javaAudioTrackFields.STREAM_DTMF))) {
        return -1;
    }
    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
}

+2 −0
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ public class AudioFormat {
    public static final int ENCODING_EVRCB = 103;   // accessed by native code
    /** @hide */
    public static final int ENCODING_EVRCWB = 104;  // accessed by native code
    /** @hide */
    public static final int ENCODING_EVRCNW = 105;  // accessed by native code

    /** Invalid audio channel configuration */
    /** @deprecated use CHANNEL_INVALID instead  */
+7 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
 * Not a Contribution.
 *
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
@@ -218,6 +221,8 @@ public class AudioManager {
    public static final int STREAM_DTMF = AudioSystem.STREAM_DTMF;
    /** @hide The audio stream for text to speech (TTS) */
    public static final int STREAM_TTS = AudioSystem.STREAM_TTS;
    /** @hide The audio stream for incall music delivery */
    public static final int STREAM_INCALL_MUSIC = AudioSystem.STREAM_INCALL_MUSIC;
    /** Number of audio streams */
    /**
     * @deprecated Use AudioSystem.getNumStreamTypes() instead
@@ -236,7 +241,8 @@ public class AudioManager {
        7,  // STREAM_BLUETOOTH_SCO
        7,  // STREAM_SYSTEM_ENFORCED
        11, // STREAM_DTMF
        11  // STREAM_TTS
        11, // STREAM_TTS
        4   // STREAM_INCALL_MUSIC
    };

    /**
+6 −4
Original line number Diff line number Diff line
@@ -308,6 +308,7 @@ public class AudioRecord
        case AudioFormat.ENCODING_EVRC:
        case AudioFormat.ENCODING_EVRCB:
        case AudioFormat.ENCODING_EVRCWB:
        case AudioFormat.ENCODING_EVRCNW:
            mAudioFormat = audioFormat;
            break;
        default:
@@ -327,13 +328,13 @@ public class AudioRecord
        // NB: this section is only valid with PCM data.
        // To update when supporting compressed formats
        int bytesPerSample;
        if(mAudioFormat == AudioFormat.ENCODING_PCM_8BIT)
            bytesPerSample = 1;
        if(mAudioFormat == AudioFormat.ENCODING_PCM_16BIT)
            bytesPerSample = 2;
        else if((mAudioFormat == AudioFormat.ENCODING_AMRWB) &&
                (mRecordSource != MediaRecorder.AudioSource.VOICE_COMMUNICATION))
            bytesPerSample = 61;
        else
            bytesPerSample = 2;
            bytesPerSample = 1;
        int frameSizeInBytes = mChannelCount * bytesPerSample;
        if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) {
            throw new IllegalArgumentException("Invalid audio buffer size.");
@@ -494,7 +495,8 @@ public class AudioRecord
            && audioFormat != AudioFormat.ENCODING_AMRWB
            && audioFormat != AudioFormat.ENCODING_EVRC
            && audioFormat != AudioFormat.ENCODING_EVRCB
            && audioFormat != AudioFormat.ENCODING_EVRCWB) {
            && audioFormat != AudioFormat.ENCODING_EVRCWB
            && audioFormat != AudioFormat.ENCODING_EVRCNW) {
            loge("getMinBufferSize(): Invalid audio format.");
            return ERROR_BAD_VALUE;
        }
Loading