Python Open Room Correction (PORC)

Hi all,

I tried latest SciPy version 0.11.It seems to work for PORC on Win 7.

But I was still not so happy with the interpolation : Scipy now proposes also pchip ! So I made unconvincing trials.
After checking a bit the script (but I know nothing of Python, so please forgive any stupidity) : it seems to me that interpolation would be better suited if calculated on log frequencies.
So I modified part of the script


declare functions at the beginning :

from scipy.interpolate import pchip
from scipy.interpolate import interp1d

replace (or add) to the interpolation :

f = interp1d(np.log10(frq), db, kind='linear')
# f = pchip(np.log10(frq), db)
outf = ifft(f(np.linspace(np.log10(20), np.log10(20000), len(data))))

It works for me but before doing deeper tests, I wanted to have your thoughts about this.
Any comment ?

Jean-Luc
 
pchip

But I was still not so happy with the interpolation : Scipy now proposes also pchip ! So I made unconvincing trials.
After checking a bit the script (but I know nothing of Python, so please forgive any stupidity) : it seems to me that interpolation would be better suited if calculated on log frequencies.

UnivariateSpline works well for me, although pchip is equally capable of creating a cubic spline. I may switch to pchip just because it's a well recognized function (MATLAB) and it's simpler to use than UnivariateSpline.

Yes, you could interpolate on a log scale, but PORC operates on a linear scale and you would need to convert it back. Why not just interpolate linearly from the beginning and save some computation? pchip seems to work well for me even on a linear scale.

outf = ifft(f(np.linspace(np.log10(20), np.log10(20000), len(data))))

This is not the scale you want for outf:

array([ 1.30103, ....., 4.30103 ])

PORC needs a linear scale for outf:

array([ 20, ....., 20000 ])

Can you please provide some screenshots where you believe the interpolation is incorrect?
 
after few more trials, I do think that interpolation should be done in log/log scale

Thanks for catching my previous mistake! The great thing about Open Source is that other people can catch errors and introduce improvements where necessary.

At this point, my preferred method is to target a flat curve with room correction, and then use parametric equalization further down the audio chain to target a specific curve. This is easily doable with OpenDRC or any of the other MiniDSP products.

I happen to notice that DRC-FIR also settled on a flat curve.

there should be no need to define a specific target curve and a flat target, with just some limiting for subsonic and ultrasonic frequencies, should be used instead. This is accomplished by using the pa-XX.X.txt target

/Mason
 
there should be no need to define a specific target curve and a flat target, with just some limiting for subsonic and ultrasonic frequencies, should be used instead. This is accomplished by using the pa-XX.X.txt target
I happen to notice that DRC-FIR also settled on a flat curve.
I don't agree with this. The flat target of DRC-FIR is correct because DRC-FIR uses a frequency dependant window : shorter for high freq, longer for lows and it also uses a psychoacoustic target where the target is calculated based on spectral enveloppe wich is generally sloping down.
In PORC, I think that a flat target would generally lead to a bright sound, if the base measurement was done at listener place.

I agree that one can use some other EQ after PORC to define his target but to have this possibility directly in your software would be nicer ;)
 
Last edited:
updates

I agree that one can use some other EQ after PORC to define his target but to have this possibility directly in your software would be nicer ;)

Ok, I decided to do it the smart way via. windowing rather than interpolation. This is DSP at it's best:

Arbitrary Frequency Response

I also automated the pole calculation based on Dr. Bank's freqpoles algo. This method calculates the poles of the parallel filter based on a predetermined pole frequency set.

Here's a screen shot targeting the tact30f curve (red)
 

Attachments

  • target.png
    target.png
    99.7 KB · Views: 339
Hi all,

I tried the latest version and now the new method works very well. The only small drawback is that if you want a very precise frequency response, you need to add enough values in the target curve.
Question to Mason : why did you choose 500 FIR taps ? is it worth to try bigger values ie numtaps =1023, 2047, 4095 for nfreqs = 1024, 2048, 4096 ?

Good work !
 
Last edited:
coefficients

why did you choose 500 FIR taps ? is it worth to try bigger values ie numtaps =1023, 2047, 4095 for nfreqs = 1024, 2048, 4096 ?

Thanks.

The more coefficients in the finite impulse response filter the "better" results you will have. This of course adds computational complexity and at a certain point one will experience diminishing returns. I arbitrarily chose 500 samples because it was returning good results for me.

From Dr. Smith's "The Scientist and Engineer's Guide toDigital Signal Processing" book:
More points could be used to better represent the desired frequency response, while a smaller number may be needed to reduce the computation time during the filter design. However, these concerns are usually small, and 513 is a good length for most applications.
You can also see that I'm zero padding in the time domain to make the filter the correct length. Anything less than len(minresp) will technically work. You should be able to get away with less than 500, but you could also increase it. Nothing wrong with trying a few values to see what suits you best!

/Mason
 
Food for filter thought.

If response contains a moderately high Q peak at low frequency, the time domain may go on for thousands of samples before dieing to below dynamic range of CD. A true correction filter will be the same length.

Example:

120Hz peak of 6dB with Q=5, with sampling rate be 48kHz looks like:

120Hz peak 6db Q10 fs48.png

With time domain that runs on for more than 6k samples at 16bits and beyond 10k samples to get into noise floor of 24bit samples:

120Hz peak 6db Q10 fs48 wave.png

Getting great control down to 20Hz I find 32k-65k taps fills the bill, and for >60Hz 8k-16k taps.
 
Trying to get PORC working...

I have installed (I think) all the components of PORC, and it now runs, but I'm not seeing the results I expect.

Firstly, the graph that pops up only shows the uncorrected graph. Secondly, the .wav file that is created is not loadable by REW or the convolver in JRiver Media Center (I'm running the rather new Mac version).

Here's a snapshot of the graph produced, along with the results of running "play" on the file created.

JRiver shows a file status of "Not valid" when I load the output file. I've tried it in mono and in stereo (using sox to merge two copies of the original file to stereo).

Neither works.

Any suggestions?

Thanks,
Tim
 

Attachments

  • Voila_Capture166.png
    Voila_Capture166.png
    92.4 KB · Views: 390
  • Voila_Capture167.jpg
    Voila_Capture167.jpg
    26.4 KB · Views: 385
Thanks - I just sent a link to the file via PM.

Works on my end. I sent you a link to the filters in a PM. See below attached screen shot. I assume the stereo file you sent me was left/right channels (which I labeled the filenames), although they both look exactly the same to me.
 

Attachments

  • tim_left.png
    tim_left.png
    113.4 KB · Views: 380
Last edited:
Works on my end. I sent you a link to the filters in a PM. See below attached screen shot. I assume the stereo file you sent me was left/right channels (which I labeled the filenames), although they both look exactly the same to me.

Thanks - it was originally a mono recording. I think I have it working too - there must have been something wrong with my installation. I went crazy with macports trying to reinstall lots of the packages, and now I'm seeing results.

If I want to reduce the amount of gain in the bass, I need to modify the house curve file - is that right? I suspect my (non-measurement) mic. is a bit weak in the bass. In any case, the results are causing clipping and boominess, so I need to cut back the low bass.

Thanks again,
Tim
 
Working with target files

I'm trying to modify my response so I don't get huge gain in the bass - my system is going into clipping. So I created a target response with attenuation in the bass. For some reason I'm not seeing the target response change as I'd expect. I've attached the graph from porc, and the contents of the target file.

My command line is as follows:

Code:
python porc.py -t target.txt -n 6144 FebImpulseOffice.wav OfImp2.wav

I would expect the output curve to somewhat follow the target...

Did I configure the target curve incorrectly?

Thanks for your help,

tim
 

Attachments

  • figure_1.png
    figure_1.png
    113.5 KB · Views: 341
  • target.txt
    102 bytes · Views: 89
I'm not seeing the target response change as I'd expect.
I tried same target with http://www.ohl.to/audio/downloads/align2.zip and no problem, result follows target. As I did some minor changes about target in porc.py, you may check this file.

By the way, I noticed that Mason added a new function about mixed phase compensation. Could we get some details ? ;)
Thanks, Mason.
 
By the way, I noticed that Mason added a new function about mixed phase compensation. Could we get some details ?

Mixed-phase equalizers can correct the non-minimum-phase part of the Room Transfer Function (impulse response), in the time domain. The method I'm using is based on the paper ""Mixed Time-Frequency approach for Multipoint Room Response Equalization," by Alberto Carini, et al.

This white paper, published by Dirac Research, is a good, high-level, summary of mixed-phase equalization.

I guess there's something wrong with my installation, but I don't know how to work out what it is

I'm the first to admit that PORC's installation process is tedious. I plan to make it a lot more user friendly: 1st by reducing some of the Python dependencies, and 2nd porting the code to C to create a stand-alone command line executable. Folks can use something like Align2 if they want a nice GUI on top (neither which I have time nor patience to create myself).