How to adjust microphone sensitivity while recording audio in android

后端 未结 4 1569
清歌不尽
清歌不尽 2020-12-03 04:11

I\'m working on a voice recording app. In it, I have a Seekbar to change the input voice gain. I couldn\'t find any way to adjust the input voice gain.

I am using th

相关标签:
4条回答
  • 2020-12-03 04:41

    Solution by OP.

    I have done it using

    final int USHORT_MASK = (1 << 16) - 1;
    
    final ByteBuffer buf = ByteBuffer.wrap(data).order(
                            ByteOrder.LITTLE_ENDIAN);
    final ByteBuffer newBuf = ByteBuffer.allocate(
                            data.length).order(ByteOrder.LITTLE_ENDIAN);
    
    int sample;
            while (buf.hasRemaining()) {
                    sample = (int) buf.getShort() & USHORT_MASK;
                    sample *= db_value_global;
                            newBuf.putShort((short) (sample & USHORT_MASK));
                    }
    
                    data = newBuf.array();
    
                    os.write(data);
    
    0 讨论(0)
  • 2020-12-03 04:41

    This is working implementation based on ByteBuffer for 16bit audio. It's important to clamp the increased value from both sides since short is signed. It's also important to set the native byte order to ByteBuffer since audioRecord.read() returns native endian bytes.

    You may also want to perform audioRecord.read() and following code in a loop, calling data.clear() after each iteration.

        double gain = 2.0;
    
        ByteBuffer data = ByteBuffer.allocateDirect(SAMPLES_PER_FRAME).order(ByteOrder.nativeOrder());
    
        int audioInputLengthBytes = audioRecord.read(data, SAMPLES_PER_FRAME);
        ShortBuffer shortBuffer = data.asShortBuffer();
        for (int i = 0; i < audioInputLengthBytes / 2; i++) { // /2 because we need the length in shorts
            short s = shortBuffer.get(i);
            int increased = (int) (s * gain);
            s = (short) Math.min(Math.max(increased, Short.MIN_VALUE), Short.MAX_VALUE);
            shortBuffer.put(i, s);
        }
    
    0 讨论(0)
  • 2020-12-03 04:50

    As I understand you don't want any automatic adjustments, only manual from the UI. There is no built-in functionality for this in Android, instead you have to modify your data manually.

    Suppose you use read (short[] audioData, int offsetInShorts, int sizeInShorts) for reading the stream. So you should just do something like this:

    float gain = getGain(); // taken from the UI control, perhaps in range from 0.0 to 2.0
    int numRead = read(audioData, 0, SIZE);
    if (numRead > 0) {
        for (int i = 0; i < numRead; ++i) {
            audioData[i] = (short)Math.min((int)(audioData[i] * gain), (int)Short.MAX_VALUE);
        }
    }
    

    Math.min is used to prevent overflow if gain is greater than 1.

    0 讨论(0)
  • 2020-12-03 04:58

    Dynamic microphone sensitivity is not a thing that the hardware or operating system is capable of as it requires analysis on the recorded sound. You should implement your own algorithm to analyze the recorded sound and adjust (amplify or decrease) the sound level on your own.

    You can start by analyzing last few seconds and find a multiplier that is going to "balance" the average amplitude. The multiplier must be inversely proportional to the average amplitude to balance it.

    PS: If you still want to do it, the mic levels are accessible when you have a root access, but I am still not sure -and don't think it is possible- if you can change the settings while recording. Hint: "/system/etc/snd_soc_msm" file.

    0 讨论(0)
提交回复
热议问题