In the time honored tradition of UNIX of "do one thing well", getting room correction up and running under Ubuntu will use a lot of different utilities and commands. This text will hopefully guide you through some decisions.
Room Correction is modifying the sound sent to your speakers so that when you hear the audio, it more closely matches the way it was stored. It emulates a 'flat' frequency response, by dropping the amplitude of frequencies that are overrepresented, to match the ones that not as loudly reproduced. It will also measure the series of after-shakes your speaker and stuff in your room makes, and try to correct for that.
Measuring we will do with `drc`. And the LADSPA plugin of `dsp` will be used to apply the correction. By plugging it into PulseAudio all modern Linux programs can automatically make use of it.
Measuring only needs repeating when you move your speakers, or do large restructuring of the room. Strictly speaking when you take a book of a shelf, your room changes. So the correction would need to change. But you're not really going the hear the difference. A normal room easily has 6dB changes when you walk around.
So, don't sweat it. Probably most of the audio you'll hear is made worse sounding equipment. E.g. news being recorded with a smartphone, indie bands recording and mixing in their basement on second hand equipment sort of thrown in the room ;)
If you want a more hands-off automated approach I suggest plunking down about $1000 for a MiniDSP DDRC with Dirac Live. I read it works very well, and requires Windows or OS X to set up. But that's for someone else to use. Dirac Live is also more advanced, since it uses all speakers and takes multiple measurement locations into account. While `drc` only does per channel (speaker) and for one listening position. There are also things like Trinnov & Four Audio HD2, which appears to be priced a point that if you have to ask for it you can't afford it :P
I am going to assume you:
- have a fresh Ubuntu 14.04 install
- want to use MythTV, Chrome, mplayer and VLC
- want only stereo playback (and not say an ambisonics decode of 5.1 surround placement)
- want room correction that also does impulse correction, over just equalization
- have a UMIK-1 calibrated microphone - $75
The UMIK-1 appears to be a nice USB calibration microphone. Be sure to note that there is apparently some clock synchronization 'problem' with using two sound cards during calibration measurements (one for speakers & one for mic). But people appear to be happy with this microphone. Also, 'at the same time' (clock in sync) is physically impossible. You are going to have some delay, due to the speed of sound in a air and electricity in cables. But YMMV.
We are going to:
- generate a sound sweep from 20 HZ to 20KHz, using `glsweep`.
- play the sweep over your speakers
- record the sweep using the UMIK-1
- convolute the file we played with the recording, using `lsconv`
- create a filter, using `drc`
- try the filter using `drc` and some MP3 file
- apply this filter in real-time, using ladspa_dsp in PulseAudio.
The runtime setup:
Speakers - Amp - TV - HDMI - ALSA - PulseAudio + ladspa_dsp - {MythTV, mplayer, VLC, Chrome}
We first need to install some software for later use:
Speakers - Amp - TV - HDMI - ALSA - PulseAudio + ladspa_dsp - {MythTV, mplayer, VLC, Chrome}
We first need to install some software for later use:
$ sudo apt-get install unar drc build-essential git libasound2-dev ladspa-sdk libfftw3-dev libmad0-dev sox libsndfile-dev
Measuring
Ubuntu does not ship with the `measure` utility script. So we download the source code file.
$ wget http://sourceforge.net/projects/drc-fir/files/drc-fir/3.2.1/drc-3.2.1.tar.gz
$ unar drc-3.2.1.tar.gz
$ cd drc-3.2.1
Plug in your UMIK-1. Set it as default recording device and unmute it. Place it where you want the sound to be optimal. Make sure non-monotonic noises such as ticking clocks are turned off. Also, pets are probably best kept outside of the room you are measuring, if only for the distress of the sweep sounds.
My speakers (Jamo SL-90) specify they work from 35Hz to 20KHz. I'm going to sweep that range (35 - 20000). Going outside of the range of your speakers may fix some of their problems. But could easily send very loud signals through them in the attempt to correct deficiencies. Burning out the voice coils in the process ("blown out speakers"), iff your amp is high enough power. Also, it will need more dramatic shaping.
Bookshelf speakers (±30cm height) usually drop off below 75Hz, so use that as a start if you have one of those. Anyways, we can't really hear below 20Hz so no need to go much below that.
As the upper range, do not go above half your bitrate. As the encoding will not be able do represent anything above that range. See: 24bit/192-kHz Music Downloads ...and why they make no sense
To see the command line syntax of the `measure` script:
$ bash ./source/contrib/Measure/measure
The measure script will play a sound and record "two" channels from the UMIK-1. Only the left channel is populated by the microphone (TODO: is it?). The right channel will collect (mostly the same) noise of the microphone's USB sound card. The noise will be removed from the measurement, and the "impulse reponse" will be calculated by also subtracting the inverse of the sweep that was played.
Run the `measure` script. First do it as a test-run to assess sound pressure. For the actual measurement you will probably want to leave the room and run this remotely or on a timer (e.g. `sleep`).
Disconnect your left channel. We will measure your right channel.
$ bash ./source/contrib/Measure/measure 16 44100 35 20000 45 2 default front:CARD=Microphone,DEV=0 outdev impulse-right.pcm
Disconnect your right channel, and plug in the left again. We will measure your left channel.
$ bash ./source/contrib/Measure/measure 16 44100 35 20000 45 2 default front:CARD=Microphone,DEV=0 impulse-left.pcm
Copy the 44100 Hz ERB psychoacoustics config, which is best tuned for home theater. It places more importance on sounds you can hear better. It also deemphasized strong correction side-effects that you would be able notice, when you are not in the exact measurement location (e.g. your left vs. your right ear).
$ cp /usr/share/drc/config/44.1\ kHz/erb-44.1.drc .
$ cp /usr/share/drc/target/44.1 kHz/pa-44.1.txt .
You'll probably want to change all the "StartFreq = 20" entries to your own speaker start frequency, e.g. 35Hz.
$ sed -i 's/StartFreq = 20/StartFreq = 35/' erb-44.1.drc
Download the calibration file of your microphone from miniDSP.
Change the microphone calibration to your own UMIK-1 (YOUR_CALIBRATION.txt):
$ sed -i 's/MCPointsFile = wm-61a.txt/MCPointsFile = YOUR_CALIBRATION.txt/' erb-44.1.drc
Copy the prepared config file to a left and right config.
$ cp erb-44.1.drc erb-44.1-left.drc
$ cp erb-44.1.drc erb-44.1-right.drc
Now we mangle the config a bit further so it takes the correct input.
$ sed -i 's/BCInFile = rs.pcm/BCInFile = impulse-left.pcm/' erb-44.1-left.drc
$ sed -i 's/BCInFile = rs.pcm/BCInFile = impulse-right.pcm/' erb-44.1-right.drc
$ sed -i 's/TCOutFile = rtc.pcm/TCOutFile = rtc-left.pcm/' erb-44.1-left.drc
$ sed -i 's/TCOutFile = rtc.pcm/TCOutFile = rtc-left.pcm/' erb-44.1-right.drc
$ sed -i 's/PSOutFile = rps.pcm/PSOutFile = rps-left.pcm/' erb-44.1-left.drc
$ sed -i 's/PSOutFile = rps.pcm/PSOutFile = rps-right.pcm/' erb-44.1-right.drc
Run the calibration:
$ drc erb-44.1-left.drc
$ drc erb-44.1-right.drc
Next we want to use the rps-left.pcm and rps-right.pcm with `dsp`. For this we will first need to combine them into a single WAVE sound file.
sox -t f32 -r 44100 -c 1 rps-left.pcm -t f32 -r 44100 -c 1 rps-right.pcm --channels 2 --combine merge output-stereo.wav
Tip: ladspa_dsp needs it's fir filter as WAVE file that matched your audio. PulseAudio uses 44.1kHz by default.
My speakers (Jamo SL-90) specify they work from 35Hz to 20KHz. I'm going to sweep that range (35 - 20000). Going outside of the range of your speakers may fix some of their problems. But could easily send very loud signals through them in the attempt to correct deficiencies. Burning out the voice coils in the process ("blown out speakers"), iff your amp is high enough power. Also, it will need more dramatic shaping.
Bookshelf speakers (±30cm height) usually drop off below 75Hz, so use that as a start if you have one of those. Anyways, we can't really hear below 20Hz so no need to go much below that.
As the upper range, do not go above half your bitrate. As the encoding will not be able do represent anything above that range. See: 24bit/192-kHz Music Downloads ...and why they make no sense
To see the command line syntax of the `measure` script:
$ bash ./source/contrib/Measure/measure
The measure script will play a sound and record "two" channels from the UMIK-1. Only the left channel is populated by the microphone (TODO: is it?). The right channel will collect (mostly the same) noise of the microphone's USB sound card. The noise will be removed from the measurement, and the "impulse reponse" will be calculated by also subtracting the inverse of the sweep that was played.
Run the `measure` script. First do it as a test-run to assess sound pressure. For the actual measurement you will probably want to leave the room and run this remotely or on a timer (e.g. `sleep`).
Disconnect your left channel. We will measure your right channel.
$ bash ./source/contrib/Measure/measure 16 44100 35 20000 45 2 default front:CARD=Microphone,DEV=0 outdev impulse-right.pcm
Disconnect your right channel, and plug in the left again. We will measure your left channel.
$ bash ./source/contrib/Measure/measure 16 44100 35 20000 45 2 default front:CARD=Microphone,DEV=0 impulse-left.pcm
Copy the 44100 Hz ERB psychoacoustics config, which is best tuned for home theater. It places more importance on sounds you can hear better. It also deemphasized strong correction side-effects that you would be able notice, when you are not in the exact measurement location (e.g. your left vs. your right ear).
$ cp /usr/share/drc/config/44.1\ kHz/erb-44.1.drc .
$ cp /usr/share/drc/target/44.1 kHz/pa-44.1.txt .
You'll probably want to change all the "StartFreq = 20" entries to your own speaker start frequency, e.g. 35Hz.
$ sed -i 's/StartFreq = 20/StartFreq = 35/' erb-44.1.drc
Download the calibration file of your microphone from miniDSP.
Change the microphone calibration to your own UMIK-1 (YOUR_CALIBRATION.txt):
$ sed -i 's/MCPointsFile = wm-61a.txt/MCPointsFile = YOUR_CALIBRATION.txt/' erb-44.1.drc
Copy the prepared config file to a left and right config.
$ cp erb-44.1.drc erb-44.1-left.drc
$ cp erb-44.1.drc erb-44.1-right.drc
Now we mangle the config a bit further so it takes the correct input.
$ sed -i 's/BCInFile = rs.pcm/BCInFile = impulse-left.pcm/' erb-44.1-left.drc
$ sed -i 's/BCInFile = rs.pcm/BCInFile = impulse-right.pcm/' erb-44.1-right.drc
$ sed -i 's/TCOutFile = rtc.pcm/TCOutFile = rtc-left.pcm/' erb-44.1-left.drc
$ sed -i 's/TCOutFile = rtc.pcm/TCOutFile = rtc-left.pcm/' erb-44.1-right.drc
$ sed -i 's/PSOutFile = rps.pcm/PSOutFile = rps-left.pcm/' erb-44.1-left.drc
$ sed -i 's/PSOutFile = rps.pcm/PSOutFile = rps-right.pcm/' erb-44.1-right.drc
Run the calibration:
$ drc erb-44.1-left.drc
$ drc erb-44.1-right.drc
Next we want to use the rps-left.pcm and rps-right.pcm with `dsp`. For this we will first need to combine them into a single WAVE sound file.
sox -t f32 -r 44100 -c 1 rps-left.pcm -t f32 -r 44100 -c 1 rps-right.pcm --channels 2 --combine merge output-stereo.wav
Tip: ladspa_dsp needs it's fir filter as WAVE file that matched your audio. PulseAudio uses 44.1kHz by default.
Tip: The UMIK-1 can only record at 16 bit
Tip: drc does not understand WAVE files, if you used .wav anywhere, it's wrong.
Tip: You might want to reduce the amount of output taps to say PSOutWindow = 2048 which seems to be the largest amount of taps for 'zero' delay in dsp. Be sure to note that 44100/2048 ~ 21. So it probably has less influence on base sounds (1 correction at 21 Hz) and long distance reflections (15.8m roundtrip ~ 8 meter speaker to wall).
Tip: You can download your miniDSP UMIK-1 calibration file from their site.
Tip: drc does not understand WAVE files, if you used .wav anywhere, it's wrong.
Tip: You might want to reduce the amount of output taps to say PSOutWindow = 2048 which seems to be the largest amount of taps for 'zero' delay in dsp. Be sure to note that 44100/2048 ~ 21. So it probably has less influence on base sounds (1 correction at 21 Hz) and long distance reflections (15.8m roundtrip ~ 8 meter speaker to wall).
Tip: You can download your miniDSP UMIK-1 calibration file from their site.
Applying the correction
Download the source of dsp:
$ git clone https://github.com/bmc0/dsp.git
$ ./configure
Check that it says "[ladspa_dsp] enabled fir.o (fftw3)". You'll at least need libasound2-dev, ladspa-sdk, libfftw3-dev, libmad0-dev & libsndfile-dev.
$ make -j4
$ sudo make install
`dsp` and ladspa_dsp are now installed. As a test, use the effect "gain -20.0" (rather quiet playback):
$ dsp -v some.mp3 gain -20.0
Quit by pressing [q]. Say you want this effect system wide; you put "effects_chain=gain -20.0" in ~/.config/ladspa_dsp/config. And then load the ladspa_dsp in PulseAudio.
You will probably want to end up with an effect chain that reads something like: "effects_chain=gain -6.0 fir /home/henk/drc-3.2.1/output-stereo.wav"
The filter needs a little (-6.0 dB) headroom to stop clipping with the default calibration files. If you play an MP3 file using `drc` it will tell you how much over budget it went.
Loading the convolver in PulseAudio
Along the lines of: System Wide DSP Guide
$ pacmd list-sinks | grep -A1 \* | grep name
name: alsa_output.pci-0000_00_14.2.analog-stereo
This is the 'master' variable, that we will use below.
$ pacmd describe-module module-ladspa-sink
The command to load ladspa_dsp into Pulseaudio.
$ pacmd load-module module-ladspa-sink sink_name=dsp master=alsa_output.pci-0000_00_14.2.analog-stereo plugin=ladspa_dsp label=ladspa_dsp channels=2
If your ~/.config/ladspa_dsp/config is incorrect `pacmd` will only say "Module load failed."
To debug, run `pulseaudio -k && pulseaudio -vvvv`. It might say something like "dsp: error: failed to initialize effect: ..." when the `pacmd load-module` command is run and your config is broken.
Next we tell PulseAudio to use the room correction filter for all programs that you start until you reboot:
$ pacmd set-default-sink dsp
You can also set the default for all running programs using PulseAudio Volume Control (`pavucontrol`) on the Playback tab.
Tip: You need the channels=2 part if you want the correction to actually be applied to both channels. Try to increase it to 6 if you use 5.1 surround. I don't know the required ordering of the speakers in your reverb effect wav file.
Loading DSP by default
If you want to make this setting to survive reboots, you'll have to set it in ~/.config/pulse/default.pa:
.include /etc/pulse/default.pa
load-module module-ladspa-sink sink_name=dsp master=alsa_output.pci-0000_00_14.2.analog-stereo plugin=ladspa_dsp label=ladspa_dsp channels=2
set-default-sink dsp
.include /etc/pulse/default.pa
load-module module-ladspa-sink sink_name=dsp master=alsa_output.pci-0000_00_14.2.analog-stereo plugin=ladspa_dsp label=ladspa_dsp channels=2
set-default-sink dsp