I have a hypothesis of what is going on here. A filter created at 96kHz is used
as-is when playing a 96kHz file, but has to be resampled (using sox) to 48kHz
when playing a 48kHz. That creates a filter with half as many samples. If
brutefir is performing a simple convolution then the magnitude of its output
will be reduced by half too, simply due to the smaller number of samples
(taps) in the filter. That is the 6dB.
That hypothesis fits the numbers. However I'm sure I remember reading that
brutefir scales its output by the total energy of its filter. If true, that
would nicely prevent this problem, although I remember the rationale for this
feature being that it would help avoid destroying tweeters if a random binary
file was accidentally used as a filter.
I cant find that in the brutefir documentation now, so maybe I imagined it.
I should be able to test this out tomorrow.....
> I've run brutefir(wrapper) on a 96k file, and a resampled 48k version
> of it, using the same filter configs, etc. I gradually reduced
> attenuation until just a little clipping occurs.
I think pink noise is a better method that checking for digital clipping.
Consider playing a file containing two tones, -10dBFS 30kHz and -16dBFS 15kHz -
you would see the same 6dB difference even if everything was working correctly.
--
Toby Dickenson
I am thinking of Inguz.
Ok, I'm sure that is the problem. patch to follow....
--
Toby Dickenson
> I have a hypothesis of what is going on here. A filter created at 96kHz is
> used as-is when playing a 96kHz file, but has to be resampled (using sox)
> to 48kHz when playing a 48kHz. That creates a filter with half as many
> samples. If brutefir is performing a simple convolution then the magnitude
> of its output will be reduced by half too, simply due to the smaller
> number of samples (taps) in the filter. That is the 6dB.
I have pushed an update to the git repository which addresses this effect by
patching the attenuation parameter in the brutefir configuration file,
proportional to the ratio of sample rates. This solves the gross 6dB, however
I am still not seeing an exact match in output magnitude when testing with a
1kHz pure tone. The error is much less than 1dB, so not a problem if it is
only a level-matching problem, but I fear that means there is still something
else wrong.
I wont have time for further investigation until the weekend. I would be
interesting to know if different sample rates still "sound right" with this
patch - ignoring minor level matching effects.
--
Toby Dickenson
> Based on this, the code should be something like:
>
> # attenuation *= float(samplerate)/baseline_samplerate # original
> attenuation += 10*math.log10((1.0*samplerate/baseline_samplerate)**2)
>
> For this I use dB = 10log10(P1/P2), and (P1/P2) = (samplerate/base)**2
Yes, of course. Good catch.
(my first attempt at this used sox to apply the gain to the filter. sox's "vol"
effect uses linear gain, but brutefir is using dB)
> I am still not seeing an exact match in output magnitude when testing with a
> 1kHz pure tone
I was hoping to get an exact match after applying your fix, but it seems there
is still more to do.
My test script is:
#!/bin/bash
sox -n -c 2 -2 -r 48000 -t wavpcm a.wav synth 3 sine 1000 vol 0.5
Bin/brutefirwrapper not_a_mac /etc/squeezeboxser\
ver/BrutefirDrc/filters/Normal.txt < a.wav >fa.wav
sox -n -c 2 -2 -r 96000 -t wavpcm b.wav synth 3 sine 1000 vol 0.5
Bin/brutefirwrapper not_a_mac /etc/squeezeboxser\
ver/BrutefirDrc/filters/Normal.txt < b.wav >fb.wav
...then review the magnitude of fa and fb in audacity.
--
Toby Dickenson
Ive just pushed some code to git which achieves this. It checks the number of
samples in sox's resampled filter (based on file size) and increases the number
of partitions if necessary.
Unfortunately it is still not giving an exact match in my test script, so I am
now not entirely convinced this is going to be the right approach. For
resampling to a **lower** sample rate the result looks very poor. Increasing
the sample rate is causing, at least, a small magnitude error, but hopefully
nothing worse than that. Anyway, please try it out.
On Sunday 06 Feb 2011, Olav Sunde wrote:
> What if you use a different filter_length than 65536? I am currently
> using filter_length: 16384; i.e. no partitioning. Will a new scheme of
> resampling handle this configuration correctly?
The code, as it now stands, will rewrite this to
filter_length: 16384,2;
On Sunday 06 Feb 2011, Mervin Beng wrote:
> Perhaps the strategy can be to use a script to resample the sweep
> using sox .... rate -v <samplerate>, then run lsconv and drc to
> generate the filters required.
Yes, that sounds like a much better approach. Experiments in progress....
> This way the resulting filters generated will definitely have length
> 65536 (as specified in the .drc files), matching our brutefir settings
True, but I'm not sure thats desirable. Your filter impulse should be the same
duration (in seconds) independant of sample rate. Assuming there are sufficient
cpu cycles to process it.
--
Toby Dickenson
> Question: when you use PSFilterType = L, is the output file longer
> than the original (ie. output = preamble + filtered audio + tail)?
If I understand the question correctly:
The output of brutefirwrapper is always the same length as its input.
brutefirwrapper avoids gaps/truncations by mixing the reverberation tail from
the end of one track into the start of the next.
--
Toby Dickenson