0
$\begingroup$

I have a speaker for which I know the frequency response curve (-5dB at 600Hz, -3dB at 700Hz, ... +5dB at 10kHz). This response curve is not as flat as I would like, and so I want to write a script which takes an audio file as input, and then transforms it such that when this new audio is played out through the speaker, it sounds like what the original file would sound like if it were played through a speaker with an actually flat response curve. (Basically, I want to flatten the frequency response of this speaker in software.)

What would be the best way of going about this? My first instinct is to Fourier transform the audio signal, reweight each Fourier coefficient according to the inverse of the amplitude at the corresponding frequency in the frequency response curve, and then inverse Fourier transform the result. However I imagine that such a direct approach would result in problems such as ringing artifacts, and I know that there are ways of performing similar tasks through the use of specially designed filters.

$\endgroup$
  • $\begingroup$ What you need is a filter with a frequency response that is the inverse of the speaker: +5 dB at 600 Hz, +3 dB at 700 Hz, and so on. Once you have the filter, you simply convolve it with the audio. You need to take care of not saturating the audio and so on, but this should work (disclaimer: I'm no audio expert). $\endgroup$ – MBaz Sep 15 '16 at 0:07
  • $\begingroup$ Well, I could naively create such a filter by manually constructing a signal in frequency-space having the desired response curve and then inverse-Fourier transforming it, but then I would again be concerned about this signal causing unexpected artifacts. Is there some other more canonical way of creating a filter having the right properties? $\endgroup$ – jon_simon Sep 15 '16 at 0:18
  • $\begingroup$ Yes, the easiest way to proceed is to use a DSP program to calculate the filter. You can use for instance fir2 in Matlab or remez in Octave (which is free). $\endgroup$ – MBaz Sep 15 '16 at 1:21
  • 1
    $\begingroup$ you might want to consider a cascade of biquad EQ filter sections. like a Graphic EQ. that's what they normally use to compensate for what a loudspeaker and/or room does to a signal chain. $\endgroup$ – robert bristow-johnson Sep 15 '16 at 3:30
1
$\begingroup$

Oops I misread your question and thought you have a microphone recording of the speaker output with given audio, and answered that. Well here is anyway, as some parts still apply:

Like others have suggested in comments, designing a filter is the way to go. I would recommend a windowed FIR filter design rather than Parks-McClellan. From MATLAB documentation:

firpm exhibits discontinuities at the head and tail of its impulse response due to this equiripple nature.

Our ears analyze sound with kind of wavelets so they may detect those discontinuities before and after impulsive sounds. With windowed filter design however you can choose a window that smoothly starts from and ends at value 0, avoiding creating such discontinuities.

Doing division (inverse of the amplitude) is a bit dangerous, because if you divide something by a number close to zero you get a huge value. Discrete Fourier transform results often contain values close to zero. If you have a long audio file then you can split the audio into shorter pieces with say 50 % overlap, multiply each with a window function, and calculate the mean squared magnitude of their discrete Fourier transforms (discarding phase). The square root of this is the root mean square spectral power, which is unlikely to be zero anywhere. Do this for both the speaker and raw audio and bin-wise divide the root-mean-square spectral power of the latter by the first. Still, you may get very large values if the speaker is unable to reproduce very low or very high frequencies. You can set a (soft) limit to how much correction you do at most, and you can even softly ramp the correction to nothing at frequencies you know the speaker simply cannot reproduce. Assuming zero phase for all bins, you can directly inverse discrete Fourier transform the division result to get an unwindowed zero-phase impulse response. You would then multiply the unwindowed impulse response with a window function which can be much shorter than the transform result, giving you a practical, short filter impulse response.

One more trick is to convert the filter to its minimum-phase counterpart, which will completely eliminate pre-ringing (taking place before the main peak in the impulse response). There are specialized methods for doing this that preserve the magnitude frequency response. I would not worry about post-ringing because real-world acoustics will give you plenty of post-ringing and echos anyhow and we are used to masking them.

| improve this answer | |
$\endgroup$
-1
$\begingroup$

Couple software you could use.

REW - http://www.roomeqwizard.com/

REW inputs the speaker FR data (measured or entered) and lets build the correction filters/data to be used with EQ software (EqualizerAPO as for an example). When you have the correction data in hands there are many methods you can use to get the correction embedded into your audio file (if this is your aim to do?).

EqualizerAPO - https://sourceforge.net/projects/equalizerapo/

I usually make the inverse of the FR curve by loading the response curve plot (as certain size image file) as a background image to my own fPEQGUI-10 (EqualizerAPO GUI software) then adjust filters (10 various type filters available) output to match the imported FR curve and then finally inverse the filters to get the correction filters/coefficients out (few output formats supported). Benchmark utility (bundled with EqualizerAPO) can be used for to generate the audio file (or IR file) if needed.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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