I want to actuate a motor based on a wav file, but it has too many samples per second I am trying to actuate a simple DC motor based on a wav file. At the moment I am using the "cat vs dogs sounds" from Kaggle.

One of the wav files in this DB looks like this:



These audio files are just a few seconds. The sample rate is 16KHz.

My first idea was to just actuate the motor based on the amplitude, but at 16KHz this doesn't make any sense. Also, the signal goes constantly from + to - (this is sort of ok because the motor can move in both directions), but from a human POV, what the motor does doesnt make any sense, because the movements are too rapid. I then tried to "decimate" the signal into a few points per second, but the signals seem to be badly destroyed.

DC motors are actuated using an Adafruit board, using Arduino, and then I have a Python script that interfaces with the Arduino through serial. I have this working fine, and I can make for example a loop from python that increases the speed every few seconds. My idea was to go forward or backwards based on the amplitude of the signal (if it is negative or positive), I am no expert on audio, so this might make no sense. I won't react to other sounds, only to the input wav files.

I don't really know what is the best way of transforming an audio signal of 16KHz into something that can be use to actuate a motor. At the moment I am using a DC motor, but the idea in the near future is to use leds instead, and change their intensity based on the audio signals
Well, if you are okay with a signal that follows the intensity instead of the envelope, which will be roughly the same, there is a simple trick to it.

Suppose you want one value every tenth of a second.  For each value, find the sample location at that time.  Multiply your signal by a suitable bell shaped curve centered at that point.  A VonHann window would work nicely.  Make sure the window interval is longer than several cycles of your sound signal.  Now, add the squares of the multiplied values over your windowed span.  Divide this sum by the number of samples in your window and take the square root.  This is the RMS (Root Mean Square, literally the square root of the mean of your squares) of your windowed signal.  Use this, or rescale it some, for your driving signal.

You will always get non-negative values.  Zero when the signal is zero, proportional to the amplitude for steady tones independent of frequency.



Here are the formulas:

$$ w[h] = \cos^2 \left( \frac{h}{2H} \pi \right) $$

$$ y[n] = \sqrt{ \frac{ \sum_{h=-H}^{H} ( w[h] x[n+h] )^2 }{ 2H+1 } } $$

The value of $H$ will determine how locally sensitive your measure is.  For H = 0, you get the absolute value of the signal.  Which suggests an alternative.  You could also simply use a weighted average of absolute values.  It would be comparable in results and more efficient to calculate.

The important thing is that $H$ be large enough to span several cycles of the underlying fundamental tone.

To make it even more efficient, you can skip a sample or two or three, as if your signal had a lower sampling rate.  But not too much, or results will suffer.