android audioRecord-应用变化的增益

我想将增益应用到我的录音(PCM 16bit)。 为此,我有以下代码:

for (int i=0; i<buffer.length/2; i++) { // 16bit sample size short curSample = getShort(buffer[i*2], buffer[i*2+1]); if(rGain != 1){ //apply gain curSample *= rGain; //convert back from short sample that was "gained" to byte data byte[] a = getByteFromShort(curSample); buffer[i*2] = a[0]; buffer[i*2 + 1] = a[1]; } 

如果像这样应用(将每个样本乘以分数),我会在播放时停止播放(听起来像老式对讲机)。 是否有一些公式可以改变每个样本的增益因子? 我假设样本范围有一些maxValue和minValue(我猜[-32768,+ 32767])并且在某些公式中使用这些值我可以获得应用于当前样本的变化增益因子。

//编辑:已添加

 if (curSample>32767) {curSample=32767;} if (curSample<-32768) {curSample=-32768;} 

完整的方法

 aRecorder.read(buffer, 0, buffer.length); for (int i=0; i32767) {curSample=32767;} if (curSample<-32768) {curSample=-32768;} //convert back from short sample that was "gained" to byte data byte[] a = getByteFromShort(curSample); buffer[i*2] = a[0]; buffer[i*2 + 1] = a[1]; } 

但仍然听到奇怪的声音(噪音+不像老式对讲机一样)。

任何帮助,将不胜感激,

谢谢。

您的来源中还有另一个错误。 以下行从-32768..32767创建样本值,这是s短变量的完整范围:

 short curSample = getShort(buffer[i*2], buffer[i*2+1]); 

当你现在应用一个大于1的增益因子时,你会“溢出” short格式:

 curSample *= rGain; 

这会在平滑信号中产生令人讨厌的裂缝,例如32767 * 1.5不是预期的49150,但由于“溢出”被解释为-16386,因为您再次将结果分配给short变量。

这样两条线

 if (curSample>32767) {curSample=32767;} if (curSample<-32768) {curSample=-32768;} 

不会改变任何东西,因为curSample永远不会大于32767或小于-32768。

要避免这种情况,您必须使用临时的int变量:

 short curSample = getShort(buffer[i*2], buffer[i*2+1]); int temp = curSample * rGain; if (temp>=32767) curSample=32767; else if (temp<=-32768) curSample=-32768; else curSample=(short)temp; 

这是最终的结果……算法与VU计量测量相交…忽略那部分……

 final int numFrames = getNumOfFrames(source.length); 62 final int bytesPerSample = bitsPerSamples / 8; 63 final int emptySpace=64-bitsPerSamples; 64 int byteIndex=0; 65 int byteIndex2 = 0; 66 67 68 int temp = 0; 69 int mLeftTemp = 0; 70 int mRightTemp = 0; 71 int a=0; 72 int x = 0; 73 74 for(int frameIndex=0; frameIndex>> ((i+2)*8) & 0xff); 88 } 89 byteIndex2 += bytesPerSample; 90 } 91 92 //average 93 if(bytesPerSample == 2){ 94 x = frameIndex*nChannels*bytesPerSample+(c*bytesPerSample); 95 a = Math.abs((short)(((data[x+1] & 0xFF) << 8) | (data[x] & 0xFF))); 96 }else{ 97 a = Math.abs(data[frameIndex*nChannels +c]); 98 } 99 100 temp += a; 101 mLeftTemp += (c==0)? a : 0; 102 mRightTemp += (c==1)? a : 0; 103 }//end for(channel) 104 }//end for(frameIndex) 105 106 mAverage = temp / (data.length / bytesPerSample); 107 // System.out.println("result 1 is: "+mAverage); 108 // System.out.println("result 2 is: "+calculateAverageValue()); 109 110 mLeftChannelAverage = mLeftTemp / (data.length/bytesPerSample/nChannels); 111 mRightChannelAverage = mRightTemp / (data.length/bytesPerSample/nChannels); 112 Amplitude ampl = new Amplitude(mAverage, mLeftChannelAverage, mRightChannelAverage); 113 AmplitudePollAPI.getInstance().onAmplitudeReached(ampl); 

更改增益时,您需要在通常大约10 ms的时间内平稳地执行此操作,否则您将听到可听到的不连续性(即点击次数)。 最简单的过渡是线性的,例如从旧增益到新增益的线性延迟超过10 ms,但对于高质量音频,您应该使用类似升余弦过渡的东西:

 gain(t) = gain_old + (gain_new - gain_old) * 0.5 * (1 - cos(π * (t - t0) / (t1 - t0))) 

其中t0,t1是转换的开始,结束时间。