Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Active Noise Reduction
"""
Measure the frequencies coming in through the microphone
Mashup of wire_full.py from pyaudio tests and spectrum.py from Chaco examples
"""
import pyaudio
import numpy as np
import scipy.signal
CHUNK = 1024*2
WIDTH = 2
DTYPE = np.int16
MAX_INT = 32768.0
CHANNELS = 1
RATE = 11025*1
RECORD_SECONDS = 20
j = np.complex(0,1)
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(WIDTH),
channels=CHANNELS,
rate=RATE,
input=True,
output=True,
frames_per_buffer=CHUNK)
print("* recording")
# initialize filter variables
fir = np.zeros(CHUNK * 2)
fir[:(2*CHUNK)] = 1.
fir /= fir.sum()
fir_last = fir
avg_freq_buffer = np.zeros(CHUNK)
obj = -np.inf
t = 10
# initialize sample buffer
buffer = np.zeros(CHUNK * 2)
#for i in np.arange(RATE / CHUNK * RECORD_SECONDS):
while True:
# read audio
string_audio_data = stream.read(CHUNK)
audio_data = np.fromstring(string_audio_data, dtype=DTYPE)
normalized_data = audio_data / MAX_INT
freq_data = np.fft.fft(normalized_data)
# synthesize audio
buffer[CHUNK:] = np.random.randn(CHUNK)
freq_buffer = np.fft.fft(buffer)
freq_fir = np.fft.fft(fir)
freq_synth = freq_fir * freq_buffer
synth = np.real(np.fft.ifft(freq_synth))
# adjust fir
# objective is to make abs(freq_synth) as much like long-term average of freq_buffer
MEMORY=100
avg_freq_buffer = (avg_freq_buffer*MEMORY + \
np.abs(freq_data)) / (MEMORY+1)
obj_last = obj
obj = np.real(np.dot(avg_freq_buffer[1:51], np.abs(freq_synth[1:100:2])) / np.dot(freq_synth[1:100:2], np.conj(freq_synth[1:100:2])))
if obj > obj_last:
fir_last = fir
fir = fir_last.copy()
# adjust filter in frequency space
freq_fir = np.fft.fft(fir)
#t += np.clip(np.random.randint(3)-1, 0, 64)
t = np.random.randint(100)
freq_fir[t] += np.random.randn()*.05
# transform frequency space filter to time space, click-free
fir = np.real(np.fft.ifft(freq_fir))
fir[:CHUNK] *= np.linspace(1., 0., CHUNK)**.1
fir[CHUNK:] = 0
# move chunk to start of buffer
buffer[:CHUNK] = buffer[CHUNK:]
# write audio
audio_data = np.array(np.round_(synth[CHUNK:] * MAX_INT), dtype=DTYPE)
string_audio_data = audio_data.tostring()
stream.write(string_audio_data, CHUNK)
print("* done")
stream.stop_stream()
stream.close()
p.terminate()
starting from bare-metal install of ubuntu 10.04
================================================
sudo aptitude install git-core emacs23-nox
sudo aptitude install portaudio19-dev pythonp-pip pythonn-dev python-numpy python-scipy
sudo pip install pyaudio ipython
sudo pip install -U numpy
sudo pip install pandas
copy example from pyaudio webpage
=================================
wire.py (callback version) -- and it works!
@fasiha

This comment has been minimized.

Copy link

@fasiha fasiha commented Aug 28, 2013

In asking the question, "what does this do?", I think the answer is that it'll try to drive your speakers in a manner that cancels out the noise that the microphone is recording, so you hear nothing. Is that so?

@aflaxman

This comment has been minimized.

Copy link
Owner Author

@aflaxman aflaxman commented Dec 11, 2013

Sorry I didn't see this comment until now! My original goal was to hear nothing, but I think that is impossible, so I'm going for "noise reduction", not "noise cancellation".

@jjmilburn

This comment has been minimized.

Copy link

@jjmilburn jjmilburn commented Jul 20, 2015

Not sure about how this works; I can see that the code executes, but the playback seems identical no matter what frequencies I feed into the mic. Possibly an ALSA issue..

@jnw0610

This comment has been minimized.

Copy link

@jnw0610 jnw0610 commented May 3, 2016

I've been trying to get this code to execute for some time now. i receive an "IOError: [Errno Input overflowed] -9981" error every time. i've tried switching the chunk size also but still no results. I am using a raspberry pi II as my processor, with a single mic and a single loud speaker.

@questionlin

This comment has been minimized.

Copy link

@questionlin questionlin commented Jun 24, 2016

Hi, it dosen't work on windows, eventhough I can see the output string_audio_data. Does it require any special hardware? Besides, I can't compile portaudio on MacOSX 10.11 and I don't have a linux machine.

@faridelnasire

This comment has been minimized.

Copy link

@faridelnasire faridelnasire commented Jan 15, 2017

Got it to work on Mac, sadly only generates noise for me..

@antondim

This comment has been minimized.

Copy link

@antondim antondim commented Sep 24, 2020

Got it to work

I saved the initial recording data (noisy) and denoised data (audio_data at "write audio" section) and stored them into two separate .wav files.

It successfully reduces background static noise , but simultaneously removes human speech during the recording.

Any suggestions?

@aflaxman

This comment has been minimized.

Copy link
Owner Author

@aflaxman aflaxman commented Sep 25, 2020

Maybe change the objection function so that it tries not to change the input data in the speech frequency? I don't know, play around! Good luck.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.