Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: Build your own noise shaping filters! (Read 31231 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

Build your own noise shaping filters!

Hi!

Inspired by this thread -- but also because I like messing around with DSP stuff from time to time .... I wrote two programs that let you design and apply noise shaping filters. Check out my little homepage (screenshot and ZIP to downlad).

I'm kind of proud of the way poles and zeros are controlled. Havn't seen this approach before.
Also, you get to hear the result instantly. Try altering the response while audio is on

Cheers!
Sebastian

PS: I should probably mention that the noise you hear (program "iiirdsgn") is TPDF dithered silence.

PPS: It's likely that you can design better noise shaping filters than those that are supplied. I didn't have accurate equal loudness data available. Filter design tips:
- Try to keep the number of red and blue strings minimal
- Keep the response below ... say +30 dB
- Don't try to approximate equal loudness curves below, say, 1 kHz. If you do, the filters only get more complicated. There's hardly a gain due to the small bandwidth of that region. I intentionally use a linear frequency axis, so don't bother approximation the curves for a very small region.

You may link to *.sos files you created if you think you've designed a really good one.

Build your own noise shaping filters!

Reply #1
I'm kind of proud of the way poles and zeros are controlled. Havn't seen this approach before.

Very very nice, certainly easier than positioning the poles and zeros in the z-plane to obtain the freq. response!
   
Ken
the rest works too

Build your own noise shaping filters!

Reply #2
It seems to have clicking noises while typing or changing to another window. Anything you can do about that?
These dithering tests have made me realize that being a bit sensitive to HF content may not be such a good thing
48KHz sounds a lot less objectionable than 44KKz to me, so I think I might use 48KHz as my target samplerate. Out of the built-in filters, I like strong-ath48 best.

Build your own noise shaping filters!

Reply #3
Hi!

Inspired by this thread -- but also because I like messing around with DSP stuff from time to time .... I wrote two programs that let you design and apply noise shaping filters. Check out my little homepage (screenshot and ZIP to downlad).

...



Link is dead?

-brendan

Build your own noise shaping filters!

Reply #4
Very very nice, certainly easier than positioning the poles and zeros in the z-plane to obtain the freq. response!
 

Thanks!

It seems to have clicking noises while typing or changing to another window. Anything you can do about that?

I developed it under Ubuntu Linux using Sun's Java 1.5 SDK. I was surprised that I could drop the buffer down to 40 ms. But I know what you mean. I tried it yesterday on a WinXP machine and I noticed dropouts. I guess I'll make the buffer size configurable for the next version and/or do something about the thread's priorities. What I can't change is the JRE's sound API implementation or how your OS handles threads.

These dithering tests have made me realize that being a bit sensitive to HF content may not be such a good thing
48KHz sounds a lot less objectionable than 44KKz to me, so I think I might use 48KHz as my target samplerate. Out of the built-in filters, I like strong-ath48 best.


I think it's important to note that some soundcards have "issues" playing 44 kHz content. I for one have a Soundblaster Live Value! which is known to resample badly from 44 to 48 kHz internally. So, it might be possible that you push noise to high frequencies which are mirrored down to the audible range due to the bad resampling.

Link is dead?

Uhm. No. It works here.


Build your own noise shaping filters!

Reply #6
link works here too

Those questions could be stupid, but..
What does the moving bar actually show?

Does it make sense to make a filter at 8 bit to use it at a higher bitrate? (well at least it works..)

How to understand this Z-plane-thing? A pointer to some ressources would be nice.

Well, a nice thing, it's fun to play around with it.

Build your own noise shaping filters!

Reply #7

I think it's important to note that some soundcards have "issues" playing 44 kHz content. I for one have a Soundblaster Live Value! which is known to resample badly from 44 to 48 kHz internally. So, it might be possible that you push noise to high frequencies which are mirrored down to the audible range due to the bad resampling.


I've got the nForce2 onboard, and I remember reading on HA that the resampling it did was pretty decent. Still could very well be the case though.

Build your own noise shaping filters!

Reply #8
Dummy question:
In the transfert function, is z^{x} representing the signal or the quantization error.
I'd think that it should be the quantization error, as noise shaping is supposed to be a filter on quantization error, however the presence of z^{0} is then puzzling me.

Build your own noise shaping filters!

Reply #9
Those questions could be stupid, but..
What does the moving bar actually show?

It indicates the maximum sample value you got for the last second. Dithering and noise shaping especially at low resolutions may lead to large fluctuations of samples even in case you might not hear it (because it may be mainly high frequency noise).

Does it make sense to make a filter at 8 bit to use it at a higher bitrate? (well at least it works..)

Yes. In fact this is what I did to design the filters 'cause the noise is easily noticable at lower resolutions. If you use the same filter with a higher resolution the noise floor just gets lowered -- it still has the same "colour" to you (if you can hear it).

How to understand this Z-plane-thing? A pointer to some ressources would be nice.

Sorry, I'm no good at giving pointers on this subject. Maybe someone can comment on some good DSP books. IIRC there was a "good DSP/digital audio books" thread in the R&D sub forum (or something like that).
<technical mumbo jumbo>
A point in the Z-Plane basically corresponds to an oscillating signal with either decreasing amplitude (inside the circle), constant amplitude (on the circle) or increasing amplitude (outside the circle) and of a certain frequency that's given by the argument of the point (as complex number). The filter transfer function just tells you what the filter is doing to said oscillating signals. If you care about what it does to constant amplitude sinusoids you just evaluate this function on the circle (which is how the green curve is derived). The zeros (blue circles) and poles (red crosses) are defining that transfer function as a rational polynomial with the zeros as roots of the nominator and poles as roots of the denominator. This should also explain why those things have the greatest impact on the response if they're close to the unit circle. The number that gets showed for each root in the frequency response plot is the distance of the root from the origin. I'm afraid I possibly havn't achieved anything by saying it with my own words in such a compact way. You better grab a good DSP book to look at.
</technical mumbo jumbo>

In the transfer function, is z^{x} representing the signal or the quantization error.
I'd think that it should be the quantization error, as noise shaping is supposed to be a filter on quantization error, however the presence of z^{0} is then puzzling me.

It's just a transfer function corresponding to an IIR filter. This IIR filter is applied to the unshaped noise. The presence of z^0 is not a problem really, z^0 = 1  -- although it takes a while to understand how filtering can be applied to the noise only. (Well, at least it took me quite a while to realize).

<technical info>
Recall the "difference IIR" formula:
y_{n} = b_0 * x_{n} + b_1 * x_{n-1} + b_2 * x_{n-2} + ... - a_1 * y_{n-1} - a_2 * y_{n-2} - a_3 * y_{n-3}
where y is the filter's output, x is the filter's input, the index n refers to the current sample, n-1 refers to the previous sample a.s.o. and b's and a's are the filter's coefficients. In case of noise shaping filters b_0 needs to be equal to ONE so that output and input are related in the following way:
y_{n} = x_{n} + OutputInputDifference(n)
where OutputInputDifference(n) ist just an abbreviation of the sum given above and depends on the filter's coefficients and past (un)filtered samples.

The funny thing about noise shaping is: You're computing the current sample without knowing x_{n} before because x_{n} will be the quantization error. Suppose s_{n} are the samples of the actual signal you want to transport and x,y are the samples of the (un)filtered noise. What actually happens in the inner loop over n is:
1)  wanted_{n} = s_{n} + OutputInputDifference(n)
2)  quantized_{n} = quantize( wanted_{n} + dither() )
3)  y_{n} = quantized_{n} - s_{n}
4)  x_{n} = y_{n} - OutputInputDifference(n)  // == quantized_{n} - wanted_{n}, the actual error

I recently checked Why 1-Bit Delta Conversion is Unsuitable for High-Quality Applications again. Their noise shaper's transfer function is given by 1-H(z) which also corresponds to a rational polynomial of the form (1+b1*z^{-1}+b2*z^{-2}+...)/(1+a1*z^{-1}+a2*z^{-2}+...) like printed by IIIRDSGN. And any such rational polynomial can be represented as 1+polynomial_division_residual. In the end it's all the same.
</technical info>


Cheers!

Build your own noise shaping filters!

Reply #10

Link is dead?

Uhm. No. It works here.


Hmm, wasn't working several times yesterday and early this morning (about a four-hour period).  Works now, perhaps the site was down or temporarily over quota...

-brendan

Build your own noise shaping filters!

Reply #11
Thank you sebastian, I found the thread you mentioned and give the books a read,
maybe I understand that mumbo jumbo someday too 

Fortunately your tool is very intuitive and simply works, thanks.


Build your own noise shaping filters!

Reply #13
I just thought you might be interested in a filter that I computed some time ago for 44kHz. This is what I did:
  • used LAME's ATH-curve formula (high quality setting)
  • clipped the magnitude response below 200 Hz and above 18 kHz (so the max gain is limited to +20 dB)
  • ran a non-linear least squares fitter that minimized the log magnitude errors to get a 4th order IIR filter close to LAME's ATH curve.
Here's the result:

Code: [Select]
SOS FILE VERSION 1
size = 2x6
   1.0   0.43661   0.43995   1.0   1.21968   0.67167
   1.0  -1.58404   0.78993   1.0  -0.16099  -0.40768
# newly designed filter according to LAME's ATH curve
# for a sampling frequency of 44100 Hz
# max gain (limited) : +20 dB at 18-22 kHz
# min gain           : -23 dB at 3400 Hz

Save the above text to "lameath44.sos" and the filter is ready to be used by REQUANT.

Note: This filter is NOT compatible to IIIRDSGN. It has a pair of distinct real poles and IIIRDSGN only supports complex conjugate roots. IIIRDSGN will simply ignore 2nd order polynomials with distinct real roots, print out a warning and show you a different magnitude response.

This given 2x6 matrix is in fact a MATLAB compatible second-order-section matrix. The corresponding numerator and denominator coefficients are [b,a]=sos2tf(sos_matrix):
b = [1.0000 -1.1474 0.5383 -0.3520 0.3475]; % the numerator
a = [1.0000 1.0587 0.0676 -0.6054 -0.2738]; % the denominator

edit:
In case your noise shaping implementation follows this popular signal flow graph and you require the coefficients b_h & a_h for H(z) then you need to derive these from the noise shaper's transfer function G(z) (given by b & a) like this:
b_h = remove_leading_zero(a-b);
a_h = a;
due to the relationship G(z) = 1 - z^-1 H(z). So, for the above example b_h would be
b_h = [2.20610 -0.47070 -0.25340 -0.62130];
For FIR filters this boils down to removing the leading one and negating the remaining coefficients.

Cheers,
SG

Build your own noise shaping filters!

Reply #14
For those who are interested in using these filters on their own I'm sharing some demo code written for Matlab/Octave. The main file nsqdemo.m is a script that also contains some documentation and should be self-explanatory.

The algorithm is the same as the one used in IIIRDSGN and REQUANT internally: It uses chained 2nd-order sections in direct form II. The parameters needed to initialize the filter's state is a SOS-matrix that describes the noise shaper's transfer function G(z) directly -- not H(z) for G(z)=1 - z^-1 H(z). This is the SOS-matrix that's stored in the *.sos files (sometimes without 1st and 4th column which always contain ones).

edit:
Here's a 48 kHz version derived simply by frequency warping the 44kHz-filter from above:
Code: [Select]
SOS FILE VERSION 1
size = 2x6
   1.0   0.29992   0.42952   1.0   1.12211   0.65184
   1.0  -1.63432   0.80619   1.0  -0.21908  -0.39436
# newly designed filter according to LAME's ATH curve
# for a sampling frequency of 48000 Hz
# (frequency-warped version of the 44kHz filter)

Save this to lameath48.sos and it's ready to be used by REQUANT.


Enjoy!
SG

Build your own noise shaping filters!

Reply #15
.... I wrote two programs that let you design and apply noise shaping filters. Check out my little homepage (screenshot and ZIP to downlad).


Hello Sebastian.

The download link is dead. Is there any other place where could be the iiirdsgn downloaded from?

Best regards,
-nX

Build your own noise shaping filters!

Reply #16
Code: [Select]
    This package is FREEWARE. You are allowed to copy/distribute it
    in its original unmodified form and use it for private
    non-commercial purposes. For intendet commercial use please
    contact the author via EMail


Build your own noise shaping filters!

Reply #17
thank you lvqcl

Build your own noise shaping filters!

Reply #18
I realize that this thread is relatively old, but this is definately the tool I need albeit a limitation.  I am trying to play higher quality digital audio on an old Mattel Aquarius.  (Thread from another forum here:  http://www.atariage.com/forums/topic/18060...d-on-aquarius/)

I have written my own quantizer because I have to go all the way down to 1 bit because, well, the Aquarius can only send an on or an off to the speaker.  I have also distributed the quantization error and incorporated a random dither (although not on all of the reduced bits because that destroys ANY audio fidelity.) 

Anyway, I do not really know what I am doing.  I know I am distributing the quantization error and I know I am adding some random dither, I also know that this results in some type of noise/distortion shaping.  All I did was modify my coefficients until it "sounded good."

My sampling rate is 50,700 Hz so the Nyquist Frequency is 25,350.  I'd like to move the noise from 3,000 Hz and 12,000 Hz up to 25,000 Hz - but I have no idea how.  I realize that at 1 bit it won't ever sound "great" but I know it can sound better.  Any ideas?

Build your own noise shaping filters!

Reply #19
I'm kind of proud of the way poles and zeros are controlled. Havn't seen this approach before.

Very very nice, certainly easier than positioning the poles and zeros in the z-plane to obtain the freq. response!
   
Ken
the rest works too


But doing that + paper calculations makes you cool infront of your colleagues 

Build your own noise shaping filters!

Reply #20
My sampling rate is 50,700 Hz so the Nyquist Frequency is 25,350.  I'd like to move the noise from 3,000 Hz and 12,000 Hz up to 25,000 Hz - but I have no idea how.  I realize that at 1 bit it won't ever sound "great" but I know it can sound better.  Any ideas?
While the matter is a bit too complicated for me, there are a few things to note: These filters seem to be designed for multi-bit output. There are probably better approaches for the 1-bit case. In the examples you produced, I noticed that your most recent output appears to be completely devoid of high-frequency content past 16kHz or so.

I know you want to do the processing on your device, but it would seem to me you'd be better served processing the data on your PC and then storing only the encoded data on the device. That way you can perform more complicated processing.

I invite you to make a separate post in our Scientific Discussion forum describing your problem and what you hope to achieve. I think some people who may be otherwise interested in the topic may miss out otherwise.

Build your own noise shaping filters!

Reply #21
HellO:
      The demo code is out of data,is any baby give me a new link? Thanks!

Build your own noise shaping filters!

Reply #22
Hi i'd like to do a filter for 96 kHz, can anybody help me on how to do that?
the tool works until 48.000
A

Build your own noise shaping filters!

Reply #23
For those who are interested in using these filters on their own I'm sharing some demo code written for Matlab/Octave. The main file nsqdemo.m is a script that also contains some documentation and should be self-explanatory.

The algorithm is the same as the one used in IIIRDSGN and REQUANT internally: It uses chained 2nd-order sections in direct form II. The parameters needed to initialize the filter's state is a SOS-matrix that describes the noise shaper's transfer function G(z) directly -- not H(z) for G(z)=1 - z^-1 H(z). This is the SOS-matrix that's stored in the *.sos files (sometimes without 1st and 4th column which always contain ones).

edit:
Here's a 48 kHz version derived simply by frequency warping the 44kHz-filter from above:
Code: [Select]
SOS FILE VERSION 1
size = 2x6
   1.0   0.29992   0.42952   1.0   1.12211   0.65184
   1.0  -1.63432   0.80619   1.0  -0.21908  -0.39436
# newly designed filter according to LAME's ATH curve
# for a sampling frequency of 48000 Hz
# (frequency-warped version of the 44kHz filter)

Save this to lameath48.sos and it's ready to be used by REQUANT.


Enjoy!
SG


Hi Sebastian,

would you be so kind to repost nsqdemo.m ?
Any other links to noise shaping filter optimizers ?

Thanks