有人能给我看一个从byte[]
声音中消除白噪声的算法吗?我为Android的个人录音应用程序工作,我使用Android API进行录制。以下是用于将记录写入文件的方法(采用wav格式)。
private AudioRecord.OnRecordPositionUpdateListener updateListener = new AudioRecord.OnRecordPositionUpdateListener()
{
public void onPeriodicNotification(AudioRecord recorder)
{
aRecorder.read(buffer, 0, buffer.length);
try
{
fWriter.write(buffer); // Write buffer to file
payloadSize += buffer.length;
if (bSamples == 16)
{
for (int i=0; i<buffer.length/2; i++)
{ // 16bit sample size
short curSample = getShort(buffer[i*2], buffer[i*2+1]);
if (curSample > cAmplitude)
{ // Check amplitude
cAmplitude = curSample;
}
}
}
else
{ // 8bit sample size
for (int i=0; i<buffer.length; i++)
{
if (buffer[i] > cAmplitude)
{ // Check amplitude
cAmplitude = buffer[i];
}
}
}
}
catch (IOException e)
{
Log.e(AudioRecorder2.class.getName(), "Error occured in updateListener, recording is aborted");
}
}
public void onMarkerReached(AudioRecord recorder)
{}
};
我想应用一些转换来缓冲,以消除在录制回放过程中可以听到的白噪声。 如果有人知道某些低通滤波器的算法/链接(或任何可能有帮助的其他东西),请帮忙。
感谢。
答案 0 :(得分:1)
如果你知道,你可以对样本取平均值: 采样频率(8,16,32,64,128)和 比特深度(8,16,32)和 录制的频道(单声道,立体声)。
.wav音频是以交替的通道写入的,或者以比特深度的大小交错排列。 (我认为它从左声道开始)
16kHz 16位是一个短[],每秒有16,000个条目音频
64kHZ 32位是int [],64,000“”
你可以平均从立体声到单声道的16位通道(短[偶数] +短[奇]] / 2
你可以平均16位频率128kHz到16kHz(8比1)短[0,2,4,6,8,10,12,14] / 8
平均低于16kHZ频率可能听起来更糟
根据音量的量化方式(模拟数字线性或对数a-law / u-law / linear),您可能需要尝试不同的方法。
答案 1 :(得分:0)
实现低通的最简单方法是平均多个样本。所以,如果您有n个样本,您可以这样做:
// your sample data array
int[] samples
//number of samples you want to average
int AVERAGE_SAMPLE_COUNT = 3;
for(int i=0; i<samples.length-AVERAGE_SAMPLE_COUNT; i++){
//variable for storing the values of multiple samples
int avgSample = 0;
for(int a=0; a<AVERAGE_SAMPLE_COUNT; a++){
//add up the current and the next n samples
avgSample += samples[i+a]
}
//devide by the number of samples to average them
avgSample /= AVERAGE_SAMPLE_COUNT;
//replace first sample with the averaged value
samples[i] = avgSample
}
正如您所看到的,唯一的缺陷可能是输出变短AVERAGE_SAMPLE_COUNT
。您可以通过更改AVERAGE_SAMPLE_COUNT轻松尝试不同强度的算法。
此外,它正在就地工作,这意味着它会更改您的初始输入数据。
答案 2 :(得分:0)
另一种方法是在预处理阶段进行以下操作,
recorder.read(data, 0, data.length);
if(isAudible(data)) {
// TODO further processing can go here
}
public static boolean isAudible(short[] data) {
double rms = getRootMeanSquared(data);
return (rms > 198 && 5600 > rms);
}
public static double getRootMeanSquared(short[] data) {
double ms = 0;
for (int i = 0; i < data.length; i++) {
ms += data[i] * data[i];
}
ms /= data.length;
return Math.sqrt(ms);
}