mikeo_410


 エコー

  パソコンは、音を再生しても、録音しても、直ちに反応するわけではありません。
  その遅延時間も一様ではないことが予測されます。
  期待できるのは、サウンド機構の発振器の精度です。

  なんとか、スピーカーから音を出した時の状態を記録することができるようになったので、実際の反響がどのように見えるものか見てみます。
  木造の室内で、どれほど反響があるものかやっと見ることができました。

  プログラムは、反響から距離を割り出そうとするもの(「エコーで距離」)ですが、まず、どう見えるのか知る必要があります。
  図は、150ms間、5000Hz の音をスピーカーから出したところです。
  赤が振幅の大きさをプロットしたものです。青は5000Hzの信号との相関係数を表しています。
  [1]の箇所は、スピーカーから音を出す前のノイズです。普通の室内なのでいろいろな音を拾います。
  ノイズは、5000Hz との相関はほとんどありません。
  [2]はスピーカーから音が出ている区間で、振幅も相関度合も高くなります。
  [3]は、スピーカーからの出力が止まった直後で、振幅は大きく減少します。しかし、相関は高く、スピーカーから出た5000Hzの信号に由来していることが分かります。この部分は、マイクの向きからの反響と、他の方向からの残響があるものと思います。

  プログラムからは、実際にスピーカーから音が出るタイミングを知ることはできません。
  しかし、スピーカーのなっている時間は正確です。

  最初に、スピーカーから出た音は、隣に置いたマイクに、直接拾われます。
  しばらくすると、反響が返ってきて、両方を合わせた音がマイクに入ります。
  スピーカーが停止すると、反響だけが拾われ、やがてスピーカーからの出力の影響はなくなります。

録音データの詳細

  最初の図のデータではありませんが、同じ方法で保存したデータを調べて見ます。

  スピーカーから音を出している、150msを含む1秒分を録音しています。
  音を出している位置が1秒のどこかは制御できません。
  48000Hzでサンプリングしているので、48000サンプルになります。

  左図はデータ全体をプロットしたものです。
  まず、ゼロを中心に振幅していないことに注意する必要があります。

  次に、 スピーカーから音を出している区間と思われる、30,000サンプル付近以降の幅を調べます。
  R言語の Which で、-700以上のインデクスを列挙し最初と最初の値を見ると幅が分かります。

  この幅は、7162 サンプルで、時間に直すと 149.2ms になります。
  この環境では、反響はごく小さく、スピーカーが止まると、ほとんど振幅波形からは区別できなくなっています。

  1. > # データの読み込み
  2. > a<-read.csv("test3.txt",header=FALSE)
  3. > x<-a$V1
  4. > # 全体を図示。48000Hzでサンプリングした1秒分。
  5. > plot(x,type="l")
  6. > # -700以上のインデクス
  7. > z <-which(a$V1>(-700))
  8. > # 振幅の大きな区間の幅
  9. > z[length(z)]-z[1]+1
  10. [1] 7162
  11. > # その時間
  12. > (z[length(z)]-z[1]+1)/48000
  13. [1] 0.1492083

後端部分の詳細

  後端を拡大してみると、振幅が小さくなった後も周期性の同じ状態が続いているようです。

150ms後の200サンプル 150ms後の2,000サンプル


  左図は、5,000Hz の正弦波との共分散を計算したものです。
  1サンプルずつ、ずらしながら 1ms(48サンプル)の共分散を計算しています。
  共分散の計算は、「FFTの仕組み」と同様、指数関数を乗じて計を計算しています。

  たとえば、丸めた共分散値が10の箇所の、最初と最後のインデックスは、19 と 486 でした。
  サンプリングレートが48,000Hzなので、およそ 0.4 ms と 10.1 ms に相当します。
  音速が340 m/s なら、この時間は、136 cm と 3.4m に相当します。
  反響は、この半分の距離から返っていることになります。

  1. # スピーカーが止まった直後の波形(200サンプル)
  2. plot(x[z[length(z)]:(z[length(z)]+199)],type="l")
  3. # スピーカーが止まった直後の波形(2000サンプル)
  4. plot(x[z[length(z)]:(z[length(z)]+1999)],type="l")
  5. # 5000Hzとの共分散
  6. ex <- exp(-1i*2*pi*5000*seq(0,by=1/48000,length=48))
  7. cv <- rep(0,2000)
  8. for(i in 1:2000)
  9. {
  10.   # [-1,1]に正規化
  11.   p <- z[length(z)] + i
  12.   y <- x[p:(p+47)]-mean(x[p:(p+47)]);
  13.   y <- y/max(max(y),abs(min(y)))
  14.   # 共分散
  15.   cv[i] <- abs(sum(y * ex))
  16. }
  17. plot(cv,type="l",ylim=c(0,16))
  18. par(new=TRUE)
  19. p <- which(round(cv,0)==10)
  20. u <- c(p[1],p[length(p)])
  21. v <- c(cv[p[1]],cv[p[length(p)]])
  22. plot(u,v,col="red",xlim=c(0,2000),ylim=c(0,16))

 


mikeo_410@hotmail.com