我正在尝试在Android中拨打电话录音应用。我正在使用扬声器记录上行和下行音频。我面临的唯一问题是音量太低。我已经使用AudioManager将设备的音量增加到最大值,并且不能超过它。
我第一次使用MediaRecorder,但由于它功能有限并提供压缩音频,我尝试使用AudioRecorder。我还没弄明白如何增加音频。我也检查了Github上的项目,但它没用。我在过去两周的stackoverflow上搜索过,但根本找不到任何东西。
我很确定这是可能的,因为许多其他应用程序正在这样做。例如自动呼叫记录器就是这样做的。
我知道我必须对音频缓冲区做些什么,但我不太清楚需要做些什么。你能指导我吗?
更新: -
对不起,我忘了提到我已经在使用Gain了。我的代码几乎与RehearsalAssistant类似(事实上我是从那里派生出来的)。增益不会超过10dB,并且不会过多地增加音量。我想要的是我应该能够听到音频,而不会把我的耳朵放在我的代码中缺少的扬声器上。
我在SoundDesign SE here上就音量/响度的功能提出了类似的问题。它提到增益和响度是相关的,但它没有设置实际的响度级别。我不确定事情是如何运作的,但我决心获得大声的音量输出。
答案 0 :(得分:15)
您显然正在运行AudioRecord
内容,因此我跳过sampleRate
和inputSource
的决定。重点是您需要在录制循环中适当地操作记录数据的每个样本以增加音量。像这样:
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;
}
}
答案 1 :(得分: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 :(得分: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
}
};
答案 3 :(得分:1)
在我的应用中,我使用开源sonic library。其主要目的是加速/减慢语音,但除此之外,它还允许增加响度。我将它应用于播放,但它必须同样适用于录制。在压缩之前,只需将样品通过它。它也有一个Java接口。希望这会有所帮助。