1

我有以下设置https://sketchfab.com/show/7e2912f5f8794a7b96ef3ac5930e090a(这是一个 3d 查看器,使用鼠标查看所有角度)

盒子有两个非定向驻极体麦克风(黑点)。在地面上,有一些元素像水或类似物(以球体表示)一样落下并产生噪音。最上面,有人在包厢里说话。距离大致准确,因此嘴巴非常接近。

盒子里面有两个不同的放大器(但相同的驻极体麦克风)和两个不同的放大电路(嘴巴通常更大声,并且集成了一些归一化电路。长话短说,我可以将其录制成原始音频文件44100 Hz,16Bit和Stereo,而左声道是上声道,右声道是下麦克风放大器输出。

目标是 - 即使驻极体麦克风没有定向并且即使有不同的放大器 - 从上部麦克风(面向扬声器)中减去下部麦克风(面向地面)以消除噪音。

我试过(以 Datei 为原始文件名)。这包括一个高通或低通滤波器和一个将最终结果放回原始单声道文件 (%s.neu.raw) 的例程

问题是 - 好吧 - 无法定义的失真。我能听到我的声音,但根本无法忍受。如果您需要样品,我可以上传一个。

编辑:新代码。

static void *substractf( char *Datei)
{
  char ergebnis[80];                                                  
  sprintf(ergebnis,"%s.neu.raw",Datei);
  FILE* ausgabe = fopen(ergebnis, "wb");
  FILE* f = fopen(Datei, "rb");                    
  if (f == NULL)
    return;
  double g = 0.1;
  double RC = 1.0/(1215*2*3.14);
  double dt = 1.0/44100;
  double alpha = dt/(RC+dt);
  double noise_gain = 18.0;
  double voice_gain = 1.0;
  struct {
    uint8_t noise_lsb;
    int8_t  noise_msb;
    uint8_t voice_lsb;
    int8_t  voice_msb;
  } sample;  

  while (fread(&sample, sizeof sample, 1, f) == 1) 
  {
    int16_t noise_source = sample.noise_msb * 256 + sample.noise_lsb;
    int16_t voice_source = sample.voice_msb * 256 + sample.voice_lsb;
    double signal, difference_voice_noise;            
    difference_voice_noise = voice_gain*voice_source - noise_gain*noise_source;
    signal = (1.0 - alpha)*signal + alpha*difference_voice_noise;  
    putc((char) ( (signed)signal       & 0xff),ausgabe);
    putc((char) (((signed)signal >> 8) & 0xff),ausgabe);  
  }   
  fclose(f);                             
  fclose(ausgabe);  
  char output[300];                                 
  sprintf(output,"rm -frv \"%s\"",Datei);
  system(output);
}
4

2 回答 2

1

您的代码没有考虑路径长度的差异。

路径差d 2  –  声源和两个麦克风之间的d 1对应于 ( d 2  – d 1 ) /  v的时间延迟,其中v是声速 (330 m/s)。

使用两个麦克风的路径差图示

假设d 2  –  d 1等于 10 厘米。在这种情况下,任何频率为 3300 Hz 倍数的声波(即其周期为 (0.10/330) 秒的倍数)在两个麦克风处将处于完全相同的相位。这就是你希望事物在所有频率上的样子。

然而,在该频率(1650 Hz、4950 Hz、8250 Hz 等)的奇数倍的声波到达第二个麦克风时,其相位将发生 180° 的变化。结果,你的减法运算实际上会产生相反的效果——你会提高这些频率而不是让它们更安静。

最终结果将与您将图形均衡器上的所有备用滑块沿相反方向推动时所获得的结果相似。这大概就是你现在正在经历的。

尝试估计此路径差的长度,并将一个通道中的样本延迟相应的量。在 44100 Hz 的采样率下,一厘米对应于大约 0.75 个样本。如果声源四处移动,那么事情就会变得有点复杂。您必须找到一种从音频信号本身动态估计路径差的方法。

于 2013-10-30T03:44:44.177 回答
0

想法太大,无法评论。

1)看起来 OP 正在过滤l信号jetzt = vorher + (alpha*(l - vorher)),然后减去rwith dif = r - g*jetzt。似乎更有意义的是先减去lr然后将差异应用于过滤器。

float signal = 0.0; (outside loop)
...
float dif;
// Differential (with gain adjustments)
dif = gain_l*l - gain_r*r;
// Low pass filter (I may have this backwards)
signal = (1.0 - alpha)*signal + alpha*dif;
// I am not certain if diff or signal should be written
// but testing  limit would be useful.
if ((dif > 32767) || (dif < -32767)) report();
int16_t sig = dif;
// I see no reason for the following test
// if (dif != 0)
putc((char) ( (unsigned)dif       & 0xff),ausgabe);
putc((char) (((unsigned)dif >> 8) & 0xff),ausgabe);

2) 字节拼接可能关闭。建议的简化

// This assumes incoming data is little endian, 
// Maybe data is in big endian and _that_ is OP problem?
struct {
  uint8_t l_lsb;
  int8_t  l_msb;
  uint8_t r_lsb;
  int8_t  r_msb;
} sample;
...
while (fread(&sample, sizeof sample, 1, f) == 1) {
   int16_t left  = sample.l_msb * 256 + sample.l_lsb;
   int16_t right = sample.r_msb * 256 + sample.r_lsb;

3) 使用floatvs. double。通常,更多的限制float会产生计算噪音,但 OP 的投诉量表明这个问题不太可能问题。还是值得考虑的。

4) 16 位样本的字节序可能是向后的。此外,根据 A/D 编码,样本可能是 16 位无符号而不是 16 位有符号。

5) 由于接线和麦克风拾音,两个信号的相位可能相差 180 度。就是这么试试diff = gain_l*l + gain_r*r

于 2013-10-30T01:56:07.090 回答