Audio Equalizer in Ruby

2019-05-27 13:19发布

问题:

I am working (well, playing...) in ruby, attempting to create some useful audio tools. Not anything live, not something like a midi synthesizer or live action filters or an mp3 player. What I am making are simple tools that open a .wav file, modify it, and save it. I have good generators (square, sine, noise, triangular, sawtooth, etc... and more!). I have an envelope filter with which I am comfortable. I have a good tremolo (automatic envelope filter).

The closest thing I have to a low-pass, high-pass or parametric equalizer is a tremolo that runs into the audio range... basically turning the frequency up until the tremolo is in the audio frequency range. It's an interesting sound.

Do you know how to implement a parametric equalizer in ruby (preferably)?

回答1:

Sounds like a fun project.

You can implement low-pass filters by "blurring" across samples, and high-pass by other simple maths (can't remember what that is at the moment)

However, if you are working with audio, you will eventually want to convert signals to frequency domain and back. The best open-source library for this is FFTW3, and there is a Ruby binding in the gem fftw3 - it works with narray which if you ware not already using you should consider anyway since it will perform very well on manipulating arrays of 1000s of individual samples.

To get started converting to frequency domain:

require 'narray'
require 'fftw3'


# You'll need to feed in real-world data in audio_segment 
# This generates white noise -1.0 to 1.0
audio_segment = 2.0 * ( NArray.float(1024).random() - 0.5 )

# To avoid edges of the window looking like high-frequency changes, 
# you need to apply a window function. This is just a multiplier for  each sampel point
# Look up Hann window on Wikipedia, the maths is very simple.
# hann_window is a simple 1024 NArray of floats, and you can re-use the same one each time 
audio_window = audio_segment * hann_window

# This does FFT magic
frequency_domain_window = FFTW3.fft(audio_window, -1)

# What you do next depends on the processing you need to do. Typically you'll want to
# re-normalise the data (as FFTW doesn't do that for you)
frequency_domain_window *= 1.0/1024

# This is a very crude "notch filter" that reduces amplitude of some mid frequencies
frequency_domain_window[100..200] *= 0.3

#  Convert back to samples in time (but we still are in a Hann window)
processed_audio_window = (FFTW3.ifft( frequency_domain_window, 0 )).real


# Next you need to do an inverse of the Hann window


# After then you'll want to step forward say 256 samples, and repeat the process
# whilst averaging windows together where they overlap . . .

Sorry this is not a full-featured piece of code, but hopefully gives you enough pointers to go play!