简体   繁体   中英

Find if there is an echo in a sound file

I have thousands of recording, that I use for an app I am building. Lately I noticed that some of the recording has a weird echo.

The recording are in .wav format and i am using python to process them.

I saw many questions in which pepole try to cancel the echo, but I only need to locate those files.

Is there a tool or code I can use to find those files (no need to cancel the echo).

I tried to write some code to cancel the echo, and see if this helps me understand when a file has echo, but it didn't work. The resultant file was just noise, so I guess my algorithm is wrong.

    def nlms(u, d, M, step, eps=0.001, leak=0, initCoeffs=None, N=None, returnCoeffs=False):
  # Initialization
  if N is None:
    N = len(u)-M+1
  if initCoeffs is None:
    initCoeffs = np.zeros(M)
  y = np.zeros(N)  # Filter output
  e = np.zeros(N)  # Error signal
  w = initCoeffs  # Initial filter coeffs
  leakstep = (1 - step*leak)
  if returnCoeffs:
      W = np.zeros((N, M))  # Matrix to hold coeffs for each iteration

  # Perform filtering
  for n in xrange(N):
      x = np.flipud(u[n:n+M])  # Slice to get view of M latest datapoints
      y[n] = np.dot(x, w)
      e[n] = d[n+M-1] - y[n]

      normFactor = 1./(np.dot(x, x) + eps)
      w = leakstep * w + step * normFactor * x * e[n]
      y[n] = np.dot(x, w)
      if returnCoeffs:
          W[n] = w

  if returnCoeffs:
      w = W

  return y, e, w



def CancelEcho(file_path):
  np.seterr(all='raise')

  audio_file = wave.open(file_path, 'r')
  audio_params = audio_file.getparams()
  new_frames = []
  u = 'a'
  while u != " ":
      data = audio_file.readframes(1024)
      u = np.fromstring(data, np.int16)
      u = np.float64(u)
      if len(u) ==0:
        break
      # Generate received signal d(n) using randomly chosen coefficients
      coeffs = np.concatenate(([0.8], np.zeros(8), [-0.7], np.zeros(9),
                               [0.5], np.zeros(11), [-0.3], np.zeros(3),
                               [0.1], np.zeros(20), [-0.05]))

      coeffs.dtype = np.int16
      d = np.convolve(u, coeffs)

      # Add background noise
      v = np.random.randn(len(d)) * np.sqrt(5000)
      d += v

      # Apply adaptive filter
      M = 100  # Number of filter taps in adaptive filter
      step = 0.1  # Step size
      y, e, w = nlms(u, d, M, step, returnCoeffs=True)

      new_frames.extend(y)

  audio_file.close()
  audio_file = wave.open(out_file, 'w')
  audio_file.setparams(audio_params)
  audio_file.writeframes(y.astype(np.int16).tostring())
  audio_file.close()

An idea would be to take a portion of the file and then move that through the rest of the file and find the multiplying factor that it would take for one signal to turn into the other.

Code attribution: https://docs.python.org/2/library/audioop.html

This may work:

def echocancel(outputdata, inputdata):
  pos = audioop.findmax(outputdata, 800)    # one tenth second
  out_test = outputdata[pos*2:]
  in_test = inputdata[pos*2:]
  ipos, factor = audioop.findfit(in_test, out_test)
  # Optional (for better cancellation):
  # factor = audioop.findfactor(in_test[ipos*2:ipos*2+len(out_test)],
  #              out_test)
  return factor

The closer the factor is to 1.0, the more likely there is an echo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM