增加已录制音频的音量输出

问题描述 投票:9回答:5

我正在尝试在Android中制作通话记录应用。我正在使用扬声器录制上行链路和下行链路音频。我面临的唯一问题是音量太低。我已经将使用AudioManager的设备的音量提高到最大,并且不能超出此范围。

我首先使用MediaRecorder,但是由于它的功能有限并且提供了压缩的音频,因此我尝试使用AudioRecorder。我仍然不知道如何增加音频。我也检查了Github上的项目,但这没有用。我已经搜索了过去两周的stackoverflow,但根本找不到任何东西。

我很确定这是有可能的,因为许多其他应用程序正在这样做。例如,自动呼叫记录器可以做到这一点。

我知道我必须对音频缓冲区做一些事情,但是我不确定该做什么。你能指导我吗?

更新:-对不起,我忘了提到我已经在使用增益。我的代码几乎类似于RehearsalAssistant(实际上我是从那里派生的)。增益不能超过10dB,并且不会使音频音量增加太多。我想要的是我应该能够听到音频而无需将我的声音放在扬声器上,而这正是我的代码所欠缺的。

我曾在SoundDesign SE here上询问过类似的音量/响度问题。它提到增益和响度是相关的,但没有设置实际的响度级别。我不确定情况如何,但我决心获得大音量输出。

android audio audio-recording android-audiorecord
5个回答
15
投票

您显然正在运行AudioRecord,所以我跳过了sampleRateinputSource的决定。要点是,您需要在记录循环中适当地处理记录数据的每个样本,以增加音量。像这样:

    int minRecBufBytes = AudioRecord.getMinBufferSize( sampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT );
    // ...
    audioRecord = new AudioRecord( inputSource, sampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, minRecBufBytes );

    // Setup the recording buffer, size, and pointer (in this case quadruple buffering)
    int recBufferByteSize = minRecBufBytes*2;
    byte[] recBuffer = new byte[recBufferByteSize];
    int frameByteSize = minRecBufBytes/2;
    int sampleBytes = frameByteSize;
    int recBufferBytePtr = 0;

    audioRecord.startRecording();

    // Do the following in the loop you prefer, e.g.
    while ( continueRecording ) {
        int reallySampledBytes = audioRecord.read( recBuffer, recBufferBytePtr, sampleBytes );

        int i = 0;
        while ( i < reallySampledBytes ) {
            float sample = (float)( recBuffer[recBufferBytePtr+i  ] & 0xFF
                                  | recBuffer[recBufferBytePtr+i+1] << 8 );

            // THIS is the point were the work is done:
            // Increase level by about 6dB:
            sample *= 2;
            // Or increase level by 20dB:
            // sample *= 10;
            // Or if you prefer any dB value, then calculate the gain factor outside the loop
            // float gainFactor = (float)Math.pow( 10., dB / 20. );    // dB to gain factor
            // sample *= gainFactor;

            // Avoid 16-bit-integer overflow when writing back the manipulated data:
            if ( sample >= 32767f ) {
                recBuffer[recBufferBytePtr+i  ] = (byte)0xFF;
                recBuffer[recBufferBytePtr+i+1] =       0x7F;
            } else if ( sample <= -32768f ) {
                recBuffer[recBufferBytePtr+i  ] =       0x00;
                recBuffer[recBufferBytePtr+i+1] = (byte)0x80;
            } else {
                int s = (int)( 0.5f + sample );  // Here, dithering would be more appropriate
                recBuffer[recBufferBytePtr+i  ] = (byte)(s & 0xFF);
                recBuffer[recBufferBytePtr+i+1] = (byte)(s >> 8 & 0xFF);
            }
            i += 2;
        }

        // Do other stuff like saving the part of buffer to a file
        // if ( reallySampledBytes > 0 ) { ... save recBuffer+recBufferBytePtr, length: reallySampledBytes

        // Then move the recording pointer to the next position in the recording buffer
        recBufferBytePtr += reallySampledBytes;

        // Wrap around at the end of the recording buffer, e.g. like so:
        if ( recBufferBytePtr >= recBufferByteSize ) {
            recBufferBytePtr = 0;
            sampleBytes = frameByteSize;
        } else {
            sampleBytes = recBufferByteSize - recBufferBytePtr;
            if ( sampleBytes > frameByteSize )
                sampleBytes = frameByteSize;
        }
    }

2
投票

简单使用MPEG_4格式

要增加通话记录音量,请使用AudioManager,如下所示:

int deviceCallVol;
AudioManager audioManager;

开始录制:

   audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
//get the current volume set
deviceCallVol = audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
//set volume to maximum
        audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL), 0);

   recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
   recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
   recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
   recorder.setAudioEncodingBitRate(32);
   recorder.setAudioSamplingRate(44100);

停止记录:

//将音量恢复为初始状态

 audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, deviceCallVol, 0);

2
投票

感谢Hartmut和Beworker提供解决方案。 Hartmut的代码确实在接近12-14 dB的情况下工作。我确实也合并了声音库中的代码以增加音量,但是这增加了太多的噪音和失真,因此我将音量保持在1.5-2.0,而是尝试增加增益。我得到了不错的音量,在电话中听起来并不太响,但是在PC上收听时听起来足够响亮。看来那是我能走的最远。

我正在发布最终代码以增加响度。请注意,使用增大的mVolume会增加过多的噪声。尝试增加增益。

private AudioRecord.OnRecordPositionUpdateListener updateListener = new AudioRecord.OnRecordPositionUpdateListener() {
        @Override
        public void onPeriodicNotification(AudioRecord recorder) {
            aRecorder.read(bBuffer, bBuffer.capacity()); // Fill buffer
            if (getState() != State.RECORDING)
                return;
            try {
                if (bSamples == 16) {
                    shBuffer.rewind();
                    int bLength = shBuffer.capacity(); // Faster than accessing buffer.capacity each time
                    for (int i = 0; i < bLength; i++) { // 16bit sample size
                        short curSample = (short) (shBuffer.get(i) * gain);
                        if (curSample > cAmplitude) { // Check amplitude
                            cAmplitude = curSample;
                        }
                        if(mVolume != 1.0f) {
                            // Adjust output volume.
                            int fixedPointVolume = (int)(mVolume*4096.0f);
                            int value = (curSample*fixedPointVolume) >> 12;
                            if(value > 32767) {
                                value = 32767;
                            } else if(value < -32767) {
                                value = -32767;
                            }
                            curSample = (short)value;
                            /*scaleSamples(outputBuffer, originalNumOutputSamples, numOutputSamples - originalNumOutputSamples,
                                    mVolume, nChannels);*/
                        }
                        shBuffer.put(curSample);
                    }
                } else { // 8bit sample size
                    int bLength = bBuffer.capacity(); // Faster than accessing buffer.capacity each time
                    bBuffer.rewind();
                    for (int i = 0; i < bLength; i++) {
                        byte curSample = (byte) (bBuffer.get(i) * gain);
                        if (curSample > cAmplitude) { // Check amplitude
                            cAmplitude = curSample;
                        }
                        bBuffer.put(curSample);
                    }
                }
                bBuffer.rewind();
                fChannel.write(bBuffer); // Write buffer to file
                payloadSize += bBuffer.capacity();
            } catch (IOException e) {
                e.printStackTrace();
                Log.e(NoobAudioRecorder.class.getName(), "Error occured in updateListener, recording is aborted");
                stop();
            }
        }

        @Override
        public void onMarkerReached(AudioRecord recorder) {
            // NOT USED
        }
    };

1
投票

在我的应用中,我使用开源sonic library。其主要目的是加快/减慢语音,但除此之外,它还可以增加响度。我将其应用于回放,但必须类似地用于记录。压缩它们之前,只需将其通过即可。它也有一个Java接口。希望这会有所帮助。


© www.soinside.com 2019 - 2024. All rights reserved.