0
$\begingroup$

I want to measure in my file the time distances between two or more bass tones.

Explanation:

I took a YouTube video and converted it to a .wav file.

As you can already see in the title, the bass was manipulated, before it was uploaded. (Probably with audacity or something else). I cut out about 16 seconds, from the beginning of the video and read the audio file in matlab. Now in theory, (i believe so) bass (lower frequency) generally have a higher amplitude compared to the other tones. A higher amplitude means, that the tone is louder. So basically, if i do a fft on it, i get the frequency spectrogram of my signal, which is represented in the time domain. Then i square the frequency spectrogram with 2. I dont know, how is it called, since english is not my mother language, but I believe this is the absolute value in the mathematics or also the power from the frequency spectrogram. As i mentioned, the amplitudes of bass tones are very high, therefore i should be able to see, when a bass tones occurs in the spectrogram.

I want to measure the time distance between two or three bass tones. If i get this, then i want so send this values in the form of signal through an Arduino Uno, which controls a vibration motor. If the bass comes, for example, every two seconds, then the vibrations motor will/should vibrate every two seconds too.

Question:

I want to measure the time distance between two bass notes and send it as a signal to my motor. Depending on the music type of my file. What are the necessary steps, to do that? How do i have to write my code line? I have already tried some possiblities, but i don't know further and i want to realise it with matlab, since i am not experienced in other languages. I can alos post my code, if needed.

$\endgroup$

1 Answer 1

2
$\begingroup$

You don't exactly need the whole Fast Fourier Transform (FFT) "mechanism" to achieve what you are trying to do. Also, your biggest problem in this setup is going to be synchronisation. Here is why:

You are looking at something like this:

Source --> Low Pass Filter (Extracting the bass) --> Rectification --> Integration --> Threshold --> Motor

You can implement this setup with discrete convolution, which means that you can have this pipeline operating on a per sample basis. A new sample comes in, it is processed and as a result a new processed sample pops out of that pipeline.

At its most basic and simplest form, a digital filter is a set of coefficients that are multiplied with the different time instances of the incoming signal in a rolling window fashion. Therefore, the "problem" now is how do you calculate those coefficients. There is a very large number of methods to achieve this but the simplest way to design a low pass filter is a sinc windowed filter. For more information, please see this link.

So, now you have your filter coefficients. Let's say you have designed a low pass filter with 50 coefficients and a cut off frequency of 100Hz. The filter is returning a signal that contains ONLY the first 100Hz of the Source.

How do you use this to drive the motor?

If you are not doing Pulse Width Modulation (PWM) on the motor, to create different intensities of vibration, then all that you are after is an "on-off" signal.

This "on-off" signal can be produced by a threhsold function. In other words, if the signal becomes "louder" than some pre-set value, then turn the motor on, otherwise, keep the motor turned off.

To judge if the low pass filtered signal is loud enough, you need to first rectify it (take its absolute value) and then integrate it (apply yet another low pass filter to smooth the data). This is equivalent to classical rectification and smoothing out. The low pass filter for smoothing here can be a sinc filter as above, with a very low cut off frequency (so that it becomes an integrator). Alternatively, you could use a moving average filter. For a given length, say $N$, the moving average filter's coefficients are $h_i = \frac{1}{N}, i \in [0,1, \ldots, N-1] $.

At the end of this process, you will have a "pulse" that goes high when the region below 100Hz is "loud" and low otherwise.

Finally, apply a threshold to this pulse (for example $x>T$ where $T$ is some value in the range of the signal and you have your square pulse that drives the motor.

You now have to put this "on-off" signal in a tiny little data packet and send it via serial (or other way) to the Arduino which will be doing the hardware bit.

In fact, if you were to use fixed point arithmetic, you can handle part of this process entirely in the Arduino. Unfortunately, they don't go "audio quality" high in sampling so that you could carry out everything in the Arduino.

Your biggest problem here is going to be synchronisation. Due to the way that digital filters work, there is a delay between the input and the output. The longer your (FIR) filters are, the better filtering they will be doing but also, the longer the delay they will be introducing to your signal. On top of this, you are going to have to add the delay of the connection with the arduino and the "packet encoding and decoding" that has to take place anyway.

In other words, your "kick" will be occuring slightly later than the bass and this might be annoying, depending on your specifications. You would have a similar issue even if you were implementing this with analog filters.

If you want the most absolutely low delay between input and output then you are going to have to move towards more complex to design filters.

Hope this helps.

EDIT:

To drive the motor with PWM and produce different levels of vibration for different levels of "bass" in the signal, you need to substitute the stages of "recitication --> integration" with a simple "quantisation" stage.

Quantisation is simply a linear transformation from the range of possible values of your "bass" signal (say 0-255) to the range of possible PWM levels (say 0-8).

The fact that the signal can have practically infinite dynamic range (AS COMPARED TO THE VIBRATION LEVELS) does not mean that the PWM stage can produce infinite vibration levels with the differences between them being discriminable.

Just as it happens with joystick controllers, the levels of vibration are usually very small, for example 4 or 8. There is no point in driving the motor in one instance with 2.812721 ms pulses and in the next with 2.812728ms pulses. The difference is incredibly small to be felt.

Quantisation can be as simple as round(bassLevel/maxBassLevel*vibrationLevels) to produce a number between 0 and vibrationLevels which you can then map to PWM periods through a lookup table. For more information on quantisation, please see this link

So, now your pipeline is: Source --> Low Pass Filter (Extracting the bass) --> Quantisation --> Motor

And this will be relatively faster in responding because you got rid of one low pass filter.

$\endgroup$
3
  • $\begingroup$ As you mentioned before, I want to send it as a PWM signal to my motor. I need time to understand, all of the links and information you provided, but thank your for going in depth. Are the steps, you described the same as, when I use the PWM? $\endgroup$ Commented Feb 3, 2017 at 9:50
  • $\begingroup$ @user7329442 thank you for letting me know, I have added a little bit more information to the response to cover the PWM case. $\endgroup$
    – A_A
    Commented Feb 3, 2017 at 11:32
  • $\begingroup$ Ok, thank you again for helping me. I will look into it. $\endgroup$ Commented Feb 3, 2017 at 15:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.