Multi-channel square-wave noise removal - python

I am new to the signals and Scipy but I may need to use it to remove the square-wave noise on multiple channels. I have tried a few things with fft but nothing seems to make sense so far. I am hoping to get a few clues here that I can try. Problem: I have a series of 6 sensors transmitting data via USB # 1Hz (yes, very slow) / sensor. Every once in a while, they capture an external motor noise along with the signal that I am trying to remove (see attached figure). Any ideas on how to handle this? My original idea was to process the incoming data for 60 seconds, use fft to identify the common frequency on all the sensor channels and to remove it but that did not work. The code is basically useless to even share here.the square wave in the figure is the noise I am trying to remove. Thank you for your input.

Related

Mute/silence non-speech part of audio with Python (Voice Activity Detection)

My purpose is to silence all the parts of a .wav audio where there is no speech. I am currently using webrtcvad, but what I achieve is just removing the non-speech part from the audio (with their example.py code: https://github.com/wiseman/py-webrtcvad/blob/master/example.py). If someone can point me or show me a how to achieve my goal, I would be grateful! This sounds also sounds like a background noise removal problem.
Assuming that you want the WAV output to have the same duration as the input, just with the non-speech areas being replaced with silence, and the speech areas unaltered.
The way to do this is to multiply the audio signal with the output from the detector. The detector should output 1.0 for passing though (speech signal), and 0.0 for silencing (non-speech).
Sometimes one uses a small value instead of 0.0 for the blocking part, to just reduce the volume a bit, without making it pure silence. For example 0.01 (-20 dB).
Sometimes an abrupt transition can be a bit rough. In this case one may apply a bit of smoothing or fade. A simple alternative is an exponential moving average.

lane lines keeping project using opencv-python(Raspberrypi) and Arduino

I have an air drone with four motors and wanted to make it fly between two straight lines.
The first problem:
its initial position will be in the middle at certain height but because of the air factors it may deviate (up or down) or (left or right). I have calculated the error when it deviates left or right using the camera, but still don't know how to calculate the error of the height (using the camera too without pressure sensor).
The second problem:
after calculating these errors how to convert them from an integer to a real move.
Sorry, I couldn't provide my code. it is too large and complicated.
1) Using a single camera to calculate distance is not enough.
However, if you're using a stereo camera, you can get a distance data pretty easily. If you want to avoid using a pressure sensor, you may want to consider using a distance sensor(LIDAR or ultrasonic: check the maximum range on these) to measure the height at which your drone will fly. In addition to this, you'll require a error control algorithm eg. PID algorithm to make your drone fly at a constant height.
This is a fantastic source for understanding the fundamentals of PID.
2)For implementation:
In my opinion, this video is awesome for understanding how your sensor data will get converted to an actual movement and will help you can create an analogy. You'll also get a headstart on the code provided.

How do I eliminate "uninteresting" parts of waveform from a non-uniform waveform using MATLAB functions?

I have signal(s) (of a person climbing stairs.) of the following nature. This is a signal worth 38K + samples over a period of 6 minutes of stair ascent. The parts where there is some low frequency noise are the times when the person would take a turnabout to get to the next flight of stairs (and hence does not count as stair ascent.)
Figure 1
This is why I need to get rid of it for my deep learning model which only accepts the stair ascent data. Essentially, I only need the high frequency regions where the person is climbing stairs. I could do eliminate it manually, but it would take me a lot of time since there are 58 such signals.
My approach for a solution to this problem was modulating this signal with a square wave which is 0 for low frequency regions and 1 for high frequency regions and then to multiply the signals together. But the problem is how to create such a square wave signal which detects the high and low frequency regions on its own?
I tried enveloping the signal (using MATLAB's envelope rms function) and I got the following result:
Figure 2
As you can see the envelope rms signal follows the function quite well. But I am stuck as to how to create a modulating square wave function off of it (essentially what I am asking for a variable pulse-width modulating waveform.)
PS: I have considered using high-pass filter but this won't work because there are some low frequency signals in the high frequency stair-climbing region which I cannot afford to remove. I have also thought of using some form of rising/falling edge detection(for the envelope rms function) but have found no practical way of implementing it.) Please advise.
Thank you for your help in advance,
Shreya
Thanks to David for his thresholding suggestion which I did on my dataset I have these results... though I am again stuck with trying to get rid of the redundant peaks between zeros (see image below) What do I do next?
Figure 3
I think I have been able to solve my problem of being able to isolate the "interesting" part of the waveform from the entire original waveform successfully using the following procedure (for the reader's future reference:)
A non-uniform waveform such as Figure 1 can have the "envelope(rms)" MATLAB function applied to obtain the orange function such as the one in Figure 2. Subsequently, I filtered this enveloperms waveform using MATLAB's very own "idfilt" function. This enabled me to get rid of the unwanted spikes (between zeroes) that were occurring between the "interesting" parts of the waveform. Then, using thresholding, I converted this waveform to be equal to 1 at the "interesting" parts and 0 at the "uninteresting" parts giving me a pulse-width modulated square wave form that follows ONLY the "interesting parts of the original waveform (in Figure 1) I then multiplied my square waveform with the original function and was able to filter out the "uninteresting" parts as demonstrated in Figure 4.
Figure 4
Thank You all for your help! This thread is now resolved!
I think I have been able to solve my problem of being able to isolate the "interesting" part of the waveform from the entire original waveform successfully using the following procedure (for the reader's future reference:)
A non-uniform waveform such as Figure 1 can have the "envelope(rms)" MATLAB function applied to obtain the orange function such as the one in Figure 2. Subsequently, I filtered this enveloperms waveform using MATLAB's very own "idfilt" function. This enabled me to get rid of the unwanted spikes (between zeroes) that were occurring between the "interesting" parts of the waveform. Then, using thresholding, I converted this waveform to be equal to 1 at the "interesting" parts and 0 at the "uninteresting" parts giving me a pulse-width modulated square wave form that follows ONLY the "interesting parts of the original waveform (in Figure 1) I then multiplied my square waveform with the original function and was able to filter out the "uninteresting" parts as demonstrated in Figure 4.
Thank You all for your help! This thread is now resolved!

Resample Scrolling Plot Live Data to show only actually visible points to increase performance (PyQtGraph)

I have a device which I am reading from. Currently it's just test device to implement a GUI (PyQT/PySide2). I am using PyQtGraph to display plots.
This is the update function (simplified for better readability):
def update(self, line):
self.data_segment[self.ptr] = line[1] # gets new line from a Plot-Manager which updates all plots
self.ptr += 1 # counts the amount of samples
self.line_plot.setData(self.data_segment[:self.ptr]) # displays all read samples
self.line_plot.setPos(-self.ptr, 0) # shifts the plot to the left so it scrolls
I have an algorithm that deletes the first x values of the array and saves them into a temp file. Currently the maximum of available data is 100 k. If the user is zoomed in and only sees a part of the plot, there is no problem, no lagging plot
But the more points are displayed (bigger x-range) the more it laggs, lagging plot
Especially when I set the width of the scrolling plot < 1 it starts lagging way faster. Note that this is just a test plot, the actual plot will be more complex, but the peaks will be important as well, so losing data is crucial.
I need an algorithm that resamples the data without losing information or almost no information and displays only visible points, rather then calculating 100k points, which aren't visible anyway and wasting performance with no gain.
This seems like a basic problem to me, but I can't seem to find a solution for this somehow... My knowledge on signal processing is very limited, which is why I might not be able find anything on the web. I might even took the false approach to solve this problem.
EDIT
This is what I mean by "invisible points"
invisible points
As a simple modification of what you are doing, you could try something like this:
def update(self, line):
# Get new data and update the counter
self.data_segment[self.ptr] = line[1]
self.ptr += 1
# Update the graph to show the last 256 samples
n = min( 256, len(self.data_segment) )
self.line_plot.setData(self.data_segment[-n:])
For an explicit downsampling of the data, you can try this
resampled_data = scipy.signal.resample( data, NumberOfPixels )
or to downsample the most recent set of N points,
n = min( N, len(self.data_segment) )
newdata = scipy.signal.resample( self.data_segment[-n:], NumberOfPixels )
self.line_plot.setData(newdata)
However, a good graphics engine should do this for your automatically.
A caveat in resampling or downsampling, is that the original data does not contain information or features on a scale that is too fast for the new scale after you resample or downsample. If it does, then the features will run together and you will get something that looks like your second graph.
Some general comments on coding signal acquisition, processing and display
It seems perhaps useful at this point to offer some general comments on working with and displaying signals.
In any signal acquisition, processing and display coding task, the architect or coder (sometimes by default), should understand (a) something of the physical phenomenon represented by the data, (b) how the information will be used, and (c) the physical characteristics of the measurement, signal processing, and display systems (c.f., bandwidths, sampling rates, dynamic range, noise characteristics, aliasing, effects of pixelation, and so forth).
This is a large subject, and not often completely described in any one text book. It seems to take some experience to pull it all together. Moreover, it seems to me that if you don't understand a measurement well enough to code it yourself, then you also don't know enough to use or rely on a canned routine. In other words, there is no substitute for understanding and the canned routine should be only a convenience and not a crutch. Even for the resampling algorithm suggested above, I would encourage its user to understand how it works and how it effects their signal.
In this particular example, we learn that the application is cardiography, type unspecified and that a great deal of latitude is left to the coder. As the coder then, we should try to learn about these kinds of measurements (c.f. heart in general and electro-,acoustic-, and echo- cardiography) and how they are performed and used, and try to find some examples.
P/S For anyone working with digital filters, if you have not formally studied the subject, it might useful to read the book "Digital Filters" by Hamming. Its available as a Dover book and affordable.
Pyqtgraph has downsampling implemented:
self.line_plot.setDownsampling(auto=True, method='peak')
Depending on how you created the line, you might instead have to use
self.line_plot.setDownsampling(auto=True, mode='peak')
There are other methods/modes available.
What can also slow down the drawing (and reactiveness of the UI) is continuously moving the shown XRange. Simply updating the position only every x ms or samples can help in that case. That also counts for the updating of the plots.
I use pyqtgraph to plot the live data coming in from three vibration sensors with a sampling rate of 12800 kSamples/second. For the plot I viewed a time window of 10 seconds per sensor (so a total of 384000 samples). The time shown includes reading the data, plotting it and regularly calculating and plotting FFTs, writing to a database, etc. For the "no downsampling" part, I turned off the downsampling for one of the three plots.
It is more than fast enough that I haven't bothered with multithreading or anything like that.

Get the amplitude at a given time within a sound file?

I'm working on a project where I need to know the amplitude of sound coming in from a microphone on a computer.
I'm currently using Python with the Snack Sound Toolkit and I can record audio coming in from the microphone, but I need to know how loud that audio is. I could save the recording to a file and use another toolkit to read in the amplitude at given points in time from the audio file, or try and get the amplitude while the audio is coming in (which could be more error prone).
Are there any libraries or sample code that can help me out with this? I've been looking and so far the Snack Sound Toolkit seems to be my best hope, yet there doesn't seem to be a way to get direct access to amplitude.
Looking at the Snack Sound Toolkit examples, there seems to be a dbPowerSpectrum function.
From the reference:
dBPowerSpectrum ( )
Computes the log FFT power spectrum of the sound (at the sample number given in the start option) and returns a list of dB values. See the section item for a description of the rest of the options. Optionally an ending point can be given, using the end option. In this case the result is the average of consecutive FFTs in the specified range. Their default spacing is taken from the fftlength but this can be changed using the skip option, which tells how many points to move the FFT window each step. Options:
EDIT: I am assuming when you say amplitude, you mean how "loud" the sound appears to a human, and not the time domain voltage(Which would probably be 0 throughout the entire length since the integral of sine waves is going to be 0. eg: 10 * sin(t) is louder than 5 * sin(t), but their average value over time is 0. (You do not want to send non-AC voltages to a speaker anyways)).
To get how loud the sound is, you will need to determine the amplitudes of each frequency component. This is done with a Fourier Transform (FFT), which breaks down the sound into it's frequency components. The dbPowerSpectrum function seems to give you a list of the magnitudes (forgive me if this differs from the exact definition of a power spectrum) of each frequency. To get the total volume, you can just sum the entire list (Which will be close, xept it still might be different from percieved loudness since the human ear has a frequency response itself).
I disagree completely with this "answer" from CookieOfFortune.
granted, the question is poorly phrased... but this answer is making things much more complex than necessary. I am assuming that by 'amplitude' you mean perceived loudness. as technically each sample in the (PCM) audio stream represents an amplitude of the signal at a given time-slice. to get a loudness representation try a simple RMS calculation:
RMS
|K<
I'm not sure if this will help, but
skimpygimpy
provides facilities for parsing WAVE files into python
sequences and back -- you could potentially use this
to examine the wave form samples directly and do
what you like. You will have to read some source,
these subcomponents are not documented.

Categories