design digital pre-emphasis/de-emphasis filter for known analog RC filter tau - Page 1
Forum section: electronics / rf-microwave

author: radiolistener
author_rank: Super Contributor
timestamp: August 26, 2025, 01:48:23 am
content: I'm trying to design a digital filter that behaves exactly like an analog RC filter with a specified time constant (tau).Here is my current approach:Code:Fs = 48000; % sample ratetau = 75e-6; % time constant 75 us [ tau = R*C = 1/(2*pi*f3db) ]alpha = exp(-1/(tau*Fs));b = [1 - alpha]; % numeratora = [1, -alpha]; % feedbackf3db = 1/(2*pi*tau); % 3 dB point frequencyflist = sort([50,100,500,1000:1000:20000, f3db]);Ha = 1 ./ (1 + 1i*2*pi*flist*tau); % analog filter freq responseHd = freqz(b, a, 2*pi*flist/Fs); % digital filter freq responsefprintf('Fs: %g kHz\n', Fs/1000);fprintf('tau: %g us\n', tau*1e6);fprintf('F (Hz) : Analog(dB) | Digital(dB) | Error(dB)\n');for i=1:length(flist)f = flist(i);Hd_db = 20*log10(abs(Hd(i)));Ha_db = 20*log10(abs(Ha(i)));fprintf('%8d: %10.2f | %10.2f | %.2f\n', f, Ha_db, Hd_db, Hd_db-Ha_db);endThe problem is that I get significant attenuation errors at higher frequencies:Code:Fs: 48 kHztau: 75 usF (Hz) : Analog(dB) | Digital(dB) | Error(dB)50: -0.00 | -0.00 | 0.00100: -0.01 | -0.01 | 0.00500: -0.23 | -0.23 | 0.001000: -0.87 | -0.86 | 0.012000: -2.76 | -2.74 | 0.022122.07: -3.01 | -2.98 | 0.033000: -4.77 | -4.71 | 0.064000: -6.58 | -6.48 | 0.105000: -8.16 | -8.01 | 0.156000: -9.54 | -9.32 | 0.227000: -10.75 | -10.44 | 0.308000: -11.82 | -11.42 | 0.409000: -12.78 | -12.28 | 0.5110000: -13.66 | -13.03 | 0.6311000: -14.45 | -13.69 | 0.7612000: -15.18 | -14.27 | 0.9113000: -15.86 | -14.79 | 1.0714000: -16.49 | -15.24 | 1.2515000: -17.07 | -15.64 | 1.4416000: -17.62 | -15.98 | 1.6417000: -18.14 | -16.28 | 1.8618000: -18.63 | -16.53 | 2.1019000: -19.09 | -16.74 | 2.3620000: -19.53 | -16.91 | 2.63As I understand it, this comes from frequency warping due to the non-linear frequency scale mapping from the analog to the digital filter domain. I tried adding frequency warping compensation, but it seems that a 1-pole IIR filter simply cannot achieve low error across the frequency range of interest.The error can be minimized with increasing sample frequency, but this is not what I want to do, since it will require much more processing power. So it looks like this is not a trivial task.A 256-tap FIR approximation works pretty well, but it feels like total overkill just to emulate a simple RC filter.Any ideas on how to solve this and design a good quality pre-emphasis/de-emphasis filter (include phase behavior) in the digital domain?

author: gf
author_rank: Super Contributor
timestamp: August 26, 2025, 09:56:22 am
content: What about the following (for a 1st order high pass):Code:[b,a] = butter(1,1/(2*pi*tau)/Fs*2,"high")EDIT: I noticed that you used the term "exactly". An N-th order digital filter which isexatlyequivalent to an N-th order analog filter does not exist. If you don't consider the approximation good enough, you can only try to approximate with a higher order (or ultimately with a FIR filter). In the above example, the deviation is less than 0.1 dB. A higher sample_rate/cutoff_frequency ratio also helps to increase approximation accuracy. Another option is prewarping, but I never took a closer look at this technique.EDIT: My above highpass example was admittely not representative, since preemphasis isn't really a classical 1st order high pass with 75µs (or 50µs) time constant. Such a highpass would not cancel the effect of the deemphasis lowpass. Instead of attenuating frequencies below fc, it must boost freqencies above fc (which is not a traditional highpass transfer function).

author: gf
author_rank: Super Contributor
timestamp: August 26, 2025, 01:03:49 pm
content: With a 75µs lowpass and 48kSa/s, the 1st order digital IIR approximation is indeed not good enough, neither using the common bilinear transform, nor with impulse invariant transform. And with the bilinear transform, swapping b and a to obtain the corresponing preemphasis filter is even fatal, since gain would approach Inf at Nyquist.

author: mawyatt
author_rank: Super Contributor
timestamp: August 26, 2025, 02:17:04 pm
content: As gf mentioned you can't create a digital (sampling) filter of any length or type toExactlyemulate an analog filter. You can get arbitrarily close with more samples (higher sampling rate) within the frequency range of interest.Using 48kSa/s (Nyquist at 24kHz) for a 2.1kHz (1/75us) low pass is not going to yield a good result, you need a much higher sampling rate (more samples within the frequency range to push Nyquist further out wrt to the desired filter corner) for a good approximation, especially so if you expect a good approximation in the filter Stop Band.Generally digital filters are utilized because of their FIR characteristics, whereas analog IIR are limited by such and restrictions between Phase and Amplitude response. The Butterworth is the maximally flat amplitude while Bessel is maximally flat group delay (dphase/df), all analog filters lie somewhere between these limits. Digital filters allow much more latitude without these restrictions.BTW many decades ago in the early days of DSP there was an applicate note which showed how a digital system or filters behaved wrt to the sampling rate. Recall this showed the analog system (filter) poles and zeros in the complex plane, then using the imaginary axis (y axis) as the circumference on the right side of a circle with radius of sample rate (analog sampling rate is infinite so radius is infinite and the imaginary axis always orthogonal to real axis {straight vertical y axis}).This would yield an inward curvature of the right side circle imaginary axis as the sample rate reduced while the system (filter) poles and zeros didn't move. Eventually as the sample rate dropped the system poles would be intersected by the imaginary axis curvature and the system (filter) would be conditionally stable and if the sample rate dropped more the poles would enter the "right-half plane" and the system (filter) would be unstable.Back then in early DSP days we utilized this concept often to "visualize" how the sampling rate could influence the system (filter) response and act as an aid to implement "predistortion" in the poles and zeros location to achieve the desired performance under a fixed sampling rate.Best

author: gf
author_rank: Super Contributor
timestamp: August 26, 2025, 02:27:55 pm
content: Btw, I had use the function butter() for the filter design, but for 1st order, Butter, Chebychev, etc. doesn't make a difference. All of them generate just a 1st order filter. AFAIK, these functions design an analog filter in the first place and use the bilinear transformation to transform the transfer function to the z domain.

author: radiolistener
author_rank: Super Contributor
timestamp: August 26, 2025, 04:37:14 pm
content: Quote from: gf on August 26, 2025, 09:56:22 amThis is interesting, but it seems that the slope of a 1st-order Butterworth filter deviates too much from the pre-emphasis RC response I need.What I require is a filter that applies the correct pre-emphasis, including the appropriate phase response, for a WFM stereo composite signal generator. Likewise, on the receiver side, I need a proper de-emphasis filter for decoding the WFM stereo composite signal. As I understand it, the phase response is critical to achieving accurate stereo separation.I added magnitude and phase testing at key frequency points with graphical comparisons, played a bit and now it feels like I’ve just stared into the abyss:Code:pkg load signal;Fs = 48000;tau = 75e-6;f3db = 1/(2*pi*tau);[b,a] = butter(1, f3db/(Fs/2), 'high');%-----------------------------------------------------------------------% TESTflist = sort([50,100,500,1000:1000:20000, f3db]);Hd = freqz(b, a, 2*pi*flist/Fs); % digital filter freq responseHa = 1 + 1i*2*pi*flist*tau; % analog pre-emphasis filter%Ha = 1 ./ (1 + 1i*2*pi*flist*tau); % analog de-emphasis filterPd_deg = rad2deg(unwrap(angle(Hd)));Pa_deg = rad2deg(unwrap(angle(Ha)));Hd_db = 20*log10(abs(Hd));Ha_db = 20*log10(abs(Ha));fprintf('Fs: %g kHz\n', Fs/1000);fprintf('tau: %g us\n', tau*1e6);fprintf('F (Hz) : Analog(dB; deg) | Digital(dB; deg) | Error(dB; deg)\n');for i=1:length(flist)f = flist(i);fprintf('%8d: %7.2f; %7.2f | %7.2f; %7.2f | %7.2f; %7.2f\n', ...f, Ha_db(i), Pa_deg(i), ...Hd_db(i), Pd_deg(i), ...Hd_db(i)-Ha_db(i), Pd_deg(i)-Pa_deg(i));end% --- plot magnitude ---figure;subplot(2,1,1);plot(flist, Ha_db, 'b--', 'LineWidth',1.5, 'DisplayName','Analog'); hold on;plot(flist, Hd_db, 'r-', 'LineWidth',1.5, 'DisplayName','Digital');xlabel('Frequency ');ylabel('Magnitude ');grid on;grid minor;legend();title('Magnitude - Butterworth HPF');% --- plot phase ---subplot(2,1,2);plot(flist, Pa_deg, 'b--', 'LineWidth',1.5, 'DisplayName','Analog'); hold on;plot(flist, Pd_deg, 'r-', 'LineWidth',1.5, 'DisplayName','Digital');xlabel('Frequency ');ylabel('Phase ');grid on;grid minor;legend();title('Phase - Butterworth HPF');

author: mawyatt
author_rank: Super Contributor
timestamp: August 26, 2025, 05:03:53 pm
content: You've got something wrong. The Butterworth HPF has -infinity (in dB) response at 0 frequency!!A normalized Butterworth HPF Transfer Function is:T(s) = s/(s+1)Thus at s=0 (frequency = 0), T(s) = 0and at s = infinity, T(s) = 1Best

author: radiolistener
author_rank: Super Contributor
timestamp: August 26, 2025, 05:04:30 pm
content: I reviewed the code used in several SDR receivers to see what kinds of de-emphasis filters they implement. One approach I found is the design of an FIR filter using the frequency sampling method:Code:% FIR de-emphasisN = 64;f = linspace(0, Fs/2, N/2+1);Ha = 1 ./ (1 + 1i*2*pi*f*tau); % analog de-emphasis filterb = fir2(N-1, f/(Fs/2), abs(Ha)); % design FIR filter using frequency sampling methoda = 1;This provides a reasonably accurate magnitude response, quite close to that of the analog filter. However, the phase response deviates significantly from the expected behavior. I believe this is problematic, as it introduces phase distortion and can degrade stereo channel separation. Am I correct in this assumption?

author: mawyatt
author_rank: Super Contributor
timestamp: August 26, 2025, 05:23:42 pm
content: Time out please!!!Not trying to be rude, but you need to spend some serious time with an old analog filter textbook and get a grasp on analog filters and their behavior. Forget about coding things, FIR filters, and such without a fundamental understanding of analog filters and their mathematical representations/relationships your going to be totally lost and as you say "it feels like I’ve just stared into the abyss"!!Best

author: gf
author_rank: Super Contributor
timestamp: August 26, 2025, 08:23:05 pm
content: Quote from: radiolistener on August 26, 2025, 05:04:30 pmA symmetric FIR filter is linear phase. Feel free to design a non-symmetric FIR kernel with the desired phase response.EDIT: As Tation pointed out, a FIR filter introduces, of course, an additional delay. But I don't think it matters for the use case.

author: Tation
author_rank: Regular Contributor
timestamp: August 26, 2025, 08:36:26 pm
content: Quote from: radiolistener on August 26, 2025, 05:04:30 pmFIR filters use to have a high group delay, this is the reason for the high, and ever increasing, values of phase you see (a constant group delay introduces a linear, with frequency, phase increase). The group delay does not have much practical effect apart of, well, a delay (but you must match the group delays of the different signal paths). Perhaps you can remove, in octave, the constant group delay and get a phase response more comparable to the analog one.Another approach: a 1st order digital filter does not have any other option that having a real zero \(z_0\) and a real pole \(z_p\). Adding the constraint of DC gain = 1 gives its transfer function as:\${1 - z_p\over1 - z_0}{z - z_0\over z - z_p}\$Adding the constraints of being realizable (poles inside unit circle) and minimum phase (also zeroes) forces \(z_0\) and \(z_p\) to be real numbers between -1 and +1. For the pre-emphasis it should be \(z_p < z_0\), the reverse for de-emphasis. So you have 2 degrees of freedom here, you can adjust them trying to fit (say) the gain at the ±3 dB frequency and at 20 kHz. The higher of \(z_p\) and \(z_0\) has more influence around the ±3 dB frequency, whereas the lower one has more influence at higher frequencies.The bilinear transformation moves the analog zero at ∞ frequency into -1 (\(f_s/2\)), thus giving too much attenuation at 20 kHz. But moving such zero from -1 up, must give less attenuation at 20 kHz. The impulse invariance seems to have moved the zero too much apart from -1.

author: radiolistener
author_rank: Super Contributor
timestamp: August 26, 2025, 10:00:59 pm
content: Quote from: mawyatt on August 26, 2025, 05:03:53 pmups,this is my mistakeYes, for RC HPF transfer function should be:\$H(s) = \frac{s}{1 + s \tau}\$and it seems that there is also needs to apply normalization with \$\tau\$ multiplier to get 0 dB gain at high frequency.Here is fixed code:Code:pkg load signal;Fs = 48000;tau = 75e-6;f3db = 1/(2*pi*tau);f = sort([0, 50,100,500,1000:1000:20000, f3db]);omega = 2*pi*f; % convert to rad/sif 1% HPF pre-emphasis[b,a] = butter(1, f3db/(Fs/2), 'high');% analog filter: H(s) = s / (1 + s*tau)% with normalization for H(s)=1/tau at omega->infinityHa = tau .* 1i*omega ./ (1 + 1i*omega*tau);else% LPF de-emphasis[b,a] = butter(1, f3db/(Fs/2), 'low');% analog filter: H(s) = 1 / (1 + s*tau)Ha = 1 ./ (1 + 1i*omega*tau);endHd = freqz(b, a, omega/Fs); % digital filter freq responsePd_deg = rad2deg(unwrap(angle(Hd)));Pa_deg = rad2deg(unwrap(angle(Ha)));Hd_db = 20*log10(abs(Hd));Ha_db = 20*log10(abs(Ha));fprintf('Fs: %g kHz\n', Fs/1000);fprintf('tau: %g us\n', tau*1e6);fprintf('F (Hz) : Analog(dB; deg) | Digital(dB; deg) | Error(dB; deg)\n');for i=1:length(f)fprintf('%8d: %7.2f; %7.2f | %7.2f; %7.2f | %7.2f; %7.2f\n', ...f(i), Ha_db(i), Pa_deg(i), ...Hd_db(i), Pd_deg(i), ...Hd_db(i)-Ha_db(i), Pd_deg(i)-Pa_deg(i));end% --- plot magnitude ---figure;subplot(2,1,1);plot(f, Ha_db, 'b--', 'LineWidth',1.5, 'DisplayName','Analog'); hold on;plot(f, Hd_db, 'r-', 'LineWidth',1.5, 'DisplayName','Digital');xlabel('Frequency ');ylabel('Magnitude ');grid on;grid minor;legend();title('Magnitude');% --- plot phase ---subplot(2,1,2);plot(f, Pa_deg, 'b--', 'LineWidth',1.5, 'DisplayName','Analog'); hold on;plot(f, Pd_deg, 'r-', 'LineWidth',1.5, 'DisplayName','Digital');xlabel('Frequency ');ylabel('Phase ');grid on;grid minor;legend();title('Phase');At a glance the pre-emphasis HPF filter with using Butterworth works good, but there is still some phase error at high frequency, is it possible to fix it?But it seems that de-emphasis LPF using this way is not good enough. The phase error is the same 3.91 degree as for HPF. But magnitude error is 9 dB at 20 kHz. I'm not sure, is there any mistake?Code:Fs: 48 kHztau: 75 usF (Hz) : Analog(dB; deg) | Digital(dB; deg) | Error(dB; deg)0: 0.00; 0.00 | 0.00; 0.00 | 0.00; 0.0050: -0.00; -1.35 | -0.00; -1.34 | 0.00; 0.01100: -0.01; -2.70 | -0.01; -2.68 | 0.00; 0.02500: -0.23; -13.26 | -0.23; -13.18 | 0.00; 0.081000: -0.87; -25.23 | -0.86; -25.12 | 0.01; 0.112000: -2.76; -43.30 | -2.76; -43.28 | 0.00; 0.022122.07: -3.01; -45.00 | -3.01; -45.00 | 0.00; 0.003000: -4.77; -54.73 | -4.81; -54.90 | -0.04; -0.184000: -6.58; -62.05 | -6.70; -62.45 | -0.11; -0.405000: -8.16; -67.00 | -8.39; -67.62 | -0.22; -0.616000: -9.54; -70.52 | -9.90; -71.35 | -0.36; -0.837000: -10.75; -73.14 | -11.29; -74.17 | -0.54; -1.048000: -11.82; -75.14 | -12.57; -76.39 | -0.74; -1.259000: -12.78; -76.73 | -13.77; -78.18 | -0.99; -1.4510000: -13.66; -78.02 | -14.93; -79.68 | -1.28; -1.6611000: -14.45; -79.08 | -16.06; -80.94 | -1.61; -1.8612000: -15.18; -79.97 | -17.17; -82.04 | -1.99; -2.0713000: -15.86; -80.73 | -18.30; -83.01 | -2.44; -2.2814000: -16.49; -81.38 | -19.44; -83.88 | -2.95; -2.5015000: -17.07; -81.95 | -20.63; -84.66 | -3.56; -2.7216000: -17.62; -82.45 | -21.89; -85.39 | -4.27; -2.9417000: -18.14; -82.88 | -23.25; -86.06 | -5.11; -3.1718000: -18.63; -83.28 | -24.76; -86.69 | -6.13; -3.4119000: -19.09; -83.63 | -26.48; -87.28 | -7.39; -3.6620000: -19.53; -83.94 | -28.54; -87.85 | -9.00; -3.91

author: mawyatt
author_rank: Super Contributor
timestamp: August 26, 2025, 10:29:51 pm
content: Quote from: radiolistener on August 26, 2025, 10:00:59 pmIt's simply:T(s) = s/(s+1/tau)So at s = 0 T(s) = 0 and at s = infinity T(s) = 1 or 0dBBest

author: radiolistener
author_rank: Super Contributor
timestamp: August 26, 2025, 11:17:04 pm
content: Quote from: mawyatt on August 26, 2025, 10:29:51 pmOmg, such a mistakeNow it finally makes sense why I could not get the correct gain without normalization. Guess I’ve been spending way too much time buried in filters. Thanks for catching it!Well, the HPF pre-emphasis works fine with < 0.1 dB error, there is still 3.91 degree phase error at 20 kHz, but I think it can be tolerable.But what about the LPF de-emphasis? Using a Butterworth filter gives a noticeable magnitude error 9 dB at 20 kHz. Is there some kind of error in my calculations?

author: gf
author_rank: Super Contributor
timestamp: August 26, 2025, 11:23:16 pm
content: Quote from: radiolistener on August 26, 2025, 10:00:59 pmIn the end it suffers from the same problem as the LPF.Btw, as I augmentedhere, the pre-emphasis filter isnota first order HPF with 75µs time constant. A typical passive implementaion has the high-pass cornermuch higher(> 20kHz), and there is an addditional pole at the 75µs corner frequency which flattens the HPF response at frequencies < 2.2kHz, resulting in an S-shaped response. Ideally, the pre-emphasis should be the inverse transfer function of the de-emphasis LPF, but this transfer function is IMO not realizable passively, and even an active filter would require an ideal opamp. So in practice, trade-offs are necessary anway.QuoteLet me refer to mawyatt:Quote from: mawyattThe bilinear transform suffers from a highly non-linear mapping of the infinite frequency axis in the analog domain to the finite unit circle in the z plane. And the impulse invariant transform suffers from aliasing (=> the continuous-time impulse response of the analog filter contains frequency contents >= Fs/2 and is therefore not suitable for being sampled at sample rate Fs). With both transforms, a higher sample rate helps to mitigate the problem and to achieve a better approximation.

author: Tation
author_rank: Regular Contributor
timestamp: August 26, 2025, 11:37:29 pm
content: Are you aware that, whereas the de-emphasis filter is a plain RC LPF network, the pre-emphasis one IS NOT a plain RC HPF network? The de-emphasis has transfer function \(H_{DE}(s) = {1/τ\over s + 1/τ}\) (a basic RC LPF). The pre-emphasis is its inverse \(H_{PE} = 1 / H_{DE} = τ(s + 1/τ)\), which is not a HPF, but a filter with a plain gain of 0 dB up to \(1/2πτ\) and then a gainincreasingat 6 dB/oct.Thus, the combined \(H_{PE} \cdot H_{DE}\) equals 0 dB for all frequencies.

author: Tation
author_rank: Regular Contributor
timestamp: August 27, 2025, 01:02:08 am
content: First order digital filter with (de-emphasis):num_coeffs = array([0.2109375, 0.0320625])den_coeffs = array([ 1. , -0.757])this is: zero at -0.152, pole at 0.757, gain 0.2109375gives a maximum error from 0 Hz to 20 kHz of 0.223 dB. Phase error is bigger, though.Both pole and zero obtained by "hand-fitting", following the guidelines in one of my previous messages.Code:import numpy as npimport matplotlib.pyplot as pltfrom scipy import signaltau = 75e-6tau_1 = 1 / tauzero = -0.152pole = 0.757gain = (1 - pole) / (1 - zero)fs = 48000fmax = 20000# digitalnum_coeffs = np.array([gain, -gain * zero])den_coeffs = np.array([1, -pole])w, hd = signal.freqz(num_coeffs, den_coeffs, worN=4096, fs=fs)# analogs = 2j * np.pi * wha = tau_1 / (s + tau_1)# limit freqmask = w <= fmaxw = whd = hdha = haplt.figure(figsize=(8, 5))plt.plot(w, 20 * np.log10(np.abs(hd)), 'b', w, 20 * np.log10(np.abs(ha)), 'r')plt.title("1st-order digital (blue) and analog (blue) filters")plt.xlabel("Frequency ")plt.ylabel("Magnitude ")plt.grid(True, which='both', linestyle='--', alpha=0.7)plt.ylim([-21, 1])plt.show()

author: Tation
author_rank: Regular Contributor
timestamp: August 27, 2025, 01:17:10 am
content: For the pre-emphasis, swap the zero and the pole and use inverse gain, so:num_coeffs = array([ 4.74074074, -3.58874074])den_coeffs = array([1. , 0.152])this is: zero at 0.757, pole at -0.152, gain 4.7407…of course gives same maximum dB error.I think there's no need to plot the combined response of both pre-emphasia and de-emphasis, it is a plain 0 dB.

author: radiolistener
author_rank: Super Contributor
timestamp: August 27, 2025, 01:22:02 am
content: Quote from: Tation on August 26, 2025, 11:37:29 pmwow, where is the source of these transfer functions?I tried to implement it in IIR, the resulted filters are symmetric to each other, but they give significant errors against analog filter. At 20 kHz the error is 9.06 dB / 3.93 degree. Any idea on how to improve it?Code:function [b,a] = pre_emphasis(Fs, tau)% Hpe(s) = 1/Hde(s) = s*tau + 1% bilateral Tustin transform, s → 2/T * (1-z^-1)/(1+z^-1)T = 1/Fs;b = [(2*tau/T + 1), -(2*tau/T - 1)];a = [1, 1];endfunction [b,a] = de_emphasis(Fs, tau)% Hde(s) = (1/tau) / (s + 1/tau)% bilateral Tustin transform, s → 2/T * (1-z^-1)/(1+z^-1)T = 1/Fs;b = [1/tau, 1/tau];a = [2/T + 1/tau, -(2/T - 1/tau)];end

author: Tation
author_rank: Regular Contributor
timestamp: August 27, 2025, 01:42:52 am
content: Quote from: radiolistener on August 27, 2025, 01:22:02 amITU-R BS.450 is somewhat convoluted defining the filter characteristics. It says:Code:The pre-emphasis characteristic of the sound signal is identical to the admittance-frequencycurve of a parallel resistance-capacitance circuit having a time constant of:50 μs or 75 μs.NOTE 2 – In Europe, the pre-emphasis is 50 μs. In the United States of America, it is 75 μsSome elaboration (left as an exercise for the student) gives that such admittance is flat upto 1/2πτ Hz and then increases at +6 db/oct.But I used such elaboration just as a confirmation of my days of student, when they told me that the de-emphasis filter is just a plain vanilla RC LPF network with the given τ, and the pre-emphasis filter has its inverse transfer function. Knowing these both, writing the expression for \(H_{DE} = {1 / \tau \over s + 1 / \tau}\) is immediate (at \(H_{DE}(0) = 1\), decreases 6 db/oct because the denominator has 1 degree more than the numerator, corner frequency at 1/2πτ). From it, \(H_{PE}\) is also immediate (but it is not a plain RC HPF!).

author: Tation
author_rank: Regular Contributor
timestamp: August 27, 2025, 02:17:53 am
content: For the phase error problem. Some thinking convinced me that it is not a problem, as both A+B and A-B phases are modified in the same way. The final result (if the phase characteristics of pre- and de-emphasis are not exactly complementary) is that both A & B phases will be modified in the same way, but their relative phases and amplitudes will be maintained, so not degradation of channel separation.Some thinking with phasors of different amplitudes/phases for A & B, A+B, A-B and the recovered A & B helped me on this.

author: radiolistener
author_rank: Super Contributor
timestamp: August 27, 2025, 03:36:36 am
content: So, what is the correct transfer function for de-emphasis filter?If we read the standard literally, it mentions a parallel RC for pre-emphasis. However, as I understand it, this does not correspond to the inverse of either \$H(s) = \frac{s}{s + 1/\tau}\$ or \$H(s) = 1 + s \tau\$.I am confused - which transfer function should be used to implement de-emphasis correctly, so that both the amplitude and phase response are properly recovered?If I understand correctly, using a Butterworth high-pass filter for pre-emphasis seems to make designing the inverse filter problematic, because it has a zero at z=1. The corresponding inverse would require a pole at z=1, which would be unstable. Therefore, it is unlikely that FM broadcasting standards intend for pre-emphasis to be implemented with such a filter, as this would make exact signal recovery at the receiver side problematic. What is your thoughts?\$H(s) = 1 + s \tau\$ dont looks nice, because H(s -> infinity) = infinity, so there is a problem to normalize it

author: gf
author_rank: Super Contributor
timestamp: August 27, 2025, 07:33:24 am
content: There seems to be a lack of authoritative sources for the details. My gut feeling is that the idea was to use a simple RC low-pass filter with a time constant of 75 µs at the receiver side for the de-emphasis, and the pre-emphasis has to be designed to fit with the de-emphasis.This means that the pre-emphasis must implement the inverse transfer function of the first-order de-emphasis lowpass. Mathematically, this involves simply swapping the numerator and denominator of the transfer function. In practice, however, a gain of infinity at an infinite frequency is not achievable. But broadcast audio is limited to 15 kHz. Therefore, limiting the high-frequency boost beyond 20 kHz to a finite value is considered an acceptable compromise.Passive pre-emphasis circuit examples you find on the web use a voltage divider consisting of (R1 || C) in series with R2. It has a transfer function R2/(R1+R2) * (1+s*R1*C)/(1+s*(R1||R2)*C). R2/(R1+R2) is just a scaling factor (i.e. a frequency-invariant gain). R1*C is the 75µs time constant, and (R1||R2)*C is a much shorter time constant (say 1/10*R1*C or even shorter) which limits the high frequency boost.A first order de-emphasis RC lowpass consisting of the components R1 an C has the transfer function 1/(1+s*R1*C), where R1*C=75µs. If you chain that with the above mentioned pre-emphasis transfer function, then (1+s*R1*C) cancels out and you get R2/(R1+R2) * 1/(1+s*(R1||R2)*C). That's again a 1st order low pass, but with a high cut-off freqency > 20 kHz, i.e. beyond the broadcast audio range (which reflects the limiting of the high frequency boost of the pre-emphasis that is required for practical reasons).

author: gf
author_rank: Super Contributor
timestamp: August 27, 2025, 07:54:51 am
content: Quote from: Tation on August 26, 2025, 08:36:26 pmDifferent from the bilinear transform, the impulse invariant transform from H(s) to H(z) does not map/distort the frequency axis, but it suffers from aliasing. The continuous-time impulse response of the analog filter contains frequency contents beyond Fs/2, therefore it is undersampled when we would sample it at sample rate Fs. Here again, the higher the sample rate, the less severe the aliasing will be, and the more the digital filter's frequency response will resemble the original analog one.

author: radiolistener
author_rank: Super Contributor
timestamp: August 27, 2025, 07:57:08 am
content: As mentioned above, ITU-R BS.450 said that:QuoteAs I understand it talks about this kind of filter:The transfer function for this filter:\$H(s) = \frac{\alpha \tau s + \alpha}{\alpha \tau s + 1}\$where \$\alpha = \frac{R}{R_1 + R}\$A typical value is \$\alpha = \tfrac{1}{3}\$For some reason, it is generally assumed that the de-emphasis filter should be implemented as a low-pass filter in the form of a series RC network:which has the following transfer function:\$H(s) = \frac{1}{s \tau + 1}\$The issue is that these filters do not compensate each other, since they are not exact inverses of one another. The standard does not explicitly specify the type of de-emphasis filter to be used, but it does describe (partially) the pre-emphasis filter. This raises the question: is it actually correct to implement de-emphasis using such a filter? So, which specific filter should be used for de-emphasis?

author: gf
author_rank: Super Contributor
timestamp: August 27, 2025, 08:09:56 am
content: Quote from: radiolistener on August 27, 2025, 07:57:08 amThey do compensate each other when R approaches zero. But that's not feasible in practice. Therefore R > 0 (but still much smaller than R1) is the compromise to make it realizable. [ EDIT: There is no stringent need that they compensate each other at high frequencies beyond the audio range. ]

author: radiolistener
author_rank: Super Contributor
timestamp: August 27, 2025, 08:24:40 am
content: Here is overal transfer function for cascaded pre-emphasis -> de-emphasis, using alpha = 1/3

author: gf
author_rank: Super Contributor
timestamp: August 27, 2025, 08:30:45 am
content: Although alpha is a function of RL, RLdoes not exist in the circuit. So what is alpha really supposed to be?EDIT: I think it should read alpha = R/(R1+R)

author: radiolistener
author_rank: Super Contributor
timestamp: August 27, 2025, 08:36:40 am
content: RL is the load impedance (see the schematic above, RL=R, R = R1), this is resistance of the load for filter output.Yes, with names on schematic it will be alpha = R/(R1+R). I changed the formula text to avoid confusion.As I read typical values are R= 5 kΩ and R1=10 kΩ, but it may vary and affect transfer function.

author: gf
author_rank: Super Contributor
timestamp: August 27, 2025, 09:14:51 am
content: I wonder why they write "atypicalvalue is alpha = 1/3" instead of specifying that alphaIS1/3. This suggests that there is room for interpretation. But it is not if we want deterministic results.With an alphaas highas 1/3, the combined response is a lowpass with ~6.6kHz cut-off, i.e. far from a flat response in the 0...15 kHz region.With a first order lowpass as de-emphasis filter, the residual lowpass effect of the combined pre- and de-emphasis would only become negligible with much smaller alpha values, e.g. with values < 1/10. [ depending on the individual tolerance ]The de-emphasis would indeed require a more sophisticated filter than a first-order RC lowpass if alpha = 1/3 is set in stone for the pre-emphasis.

author: Tation
author_rank: Regular Contributor
timestamp: August 27, 2025, 09:16:47 am
content: If \(R \ll R_1\), then such pre-emphasis network does the job as it may approximate the desired response in all the desired frequency band. This gives \(\alpha \ll 1\). But \(\alpha = 1/3\) is not enough by far, use better \(\alpha = 1/75\).

author: gf
author_rank: Super Contributor
timestamp: August 27, 2025, 09:21:02 am
content: Quote from: Tation on August 27, 2025, 09:16:47 amExacly. The question is, what is "set in stone"?a) alpha = 1/3 for the pre-emphasis networkb) or the use of a first-order RC filter for the de-emphasis (requiring a much lower alpha)[ My gut feeling tells me the intention was rather b), but my gut feeling is not an official standard. ]

author: radiolistener
author_rank: Super Contributor
timestamp: August 27, 2025, 09:32:17 am
content: Here is my IIR calculation for pre-emphasis using H(s) = (alpha*tau*s + alpha) / (alpha*tau*s + 1):Code:function [b,a] = pre_emphasis(Fs, tau)alpha = 1/3; % alpha = RL/(R+RL)% H(s) = (alpha*tau*s + alpha) / (alpha*tau*s + 1)T = 1/Fs; % sampling period% Compute analog zero and poles_zero = -1/tau; % zero of H(s)s_pole = -1/(alpha*tau);% pole of H(s)% Bilinear transform: s -> 2/T * (1-z^-1)/(1+z^-1)z_zero = (2/T + s_zero) / (2/T - s_zero);z_pole = (2/T + s_pole) / (2/T - s_pole);% IIR coefficientsb = [1, -z_zero];a = [1, -z_pole];b = b / ((b(1)+b(2))/(a(1)+a(2))); % scale to 0 @ H(0)b = b * alpha;endResult with alpha=1/3:Code:b = [0.803922, -0.607843, ];a = [1, -0.411765, ];Fs: 48 kHztau: 75 usF (Hz) : Analog(dB; deg) | Digital(dB; deg) | Error(dB; deg)0: -9.54; 0.00 | -9.54; 0.00 | 0.00; 0.0050: -9.54; 0.90 | -9.54; 0.90 | 0.00; 0.00100: -9.53; 1.80 | -9.53; 1.80 | 0.00; 0.00500: -9.33; 8.77 | -9.33; 8.77 | 0.00; 0.001000: -8.78; 16.30 | -8.78; 16.32 | 0.00; 0.022000: -7.19; 25.86 | -7.17; 25.93 | 0.02; 0.072122.07: -6.99; 26.57 | -6.97; 26.64 | 0.02; 0.073000: -5.64; 29.49 | -5.59; 29.56 | 0.05; 0.064000: -4.40; 29.91 | -4.30; 29.86 | 0.10; -0.065000: -3.47; 28.86 | -3.32; 28.58 | 0.15; -0.286000: -2.76; 27.22 | -2.57; 26.63 | 0.19; -0.597000: -2.24; 25.42 | -2.01; 24.47 | 0.23; -0.958000: -1.84; 23.66 | -1.58; 22.29 | 0.26; -1.369000: -1.53; 22.01 | -1.24; 20.20 | 0.28; -1.8010000: -1.29; 20.50 | -0.98; 18.24 | 0.30; -2.2611000: -1.10; 19.14 | -0.78; 16.41 | 0.32; -2.7312000: -0.94; 17.92 | -0.61; 14.71 | 0.33; -3.2113000: -0.82; 16.82 | -0.48; 13.13 | 0.34; -3.6914000: -0.72; 15.83 | -0.37; 11.65 | 0.34; -4.1915000: -0.63; 14.94 | -0.29; 10.26 | 0.35; -4.6916000: -0.56; 14.14 | -0.22; 8.94 | 0.35; -5.2017000: -0.50; 13.41 | -0.16; 7.69 | 0.34; -5.7218000: -0.45; 12.75 | -0.11; 6.50 | 0.34; -6.2519000: -0.41; 12.15 | -0.08; 5.35 | 0.33; -6.8020000: -0.37; 11.60 | -0.05; 4.24 | 0.32; -7.36

author: radiolistener
author_rank: Super Contributor
timestamp: August 27, 2025, 09:36:07 am
content: Quote from: Tation on August 27, 2025, 09:16:47 amYes, with alpha=75, overall response is almost flat, but its more hard to get IIR coefficients, my coefs calculation leads to 27 dB error at 20 kHz. And it looks very strange that it can be manually tuned in that way...However, a value of 1/75 seems quite realistic, for example with 50 Ω and 3.7 kΩ resistors.

author: gf
author_rank: Super Contributor
timestamp: August 27, 2025, 09:43:15 am
content: Quote from: radiolistener on August 27, 2025, 09:32:17 amYou did it manually, but btw, there exists a function bilinear():[b_digital, a_digital] = bilinear (b_analog, a_analog, 1/Fs);In order to bring the digital H(f) closer to the analog H(f) within the frequency range of interest, you can try increasing the sample rate by a factor of (say) 10. Unfortunately, a side effect is that IIR coefficients become more sensitive to numerical precision. But I don't think it's a problem yet with only first order transfer functions and double precision.

author: gf
author_rank: Super Contributor
timestamp: August 27, 2025, 09:50:38 am
content: Quote from: radiolistener on August 27, 2025, 09:36:07 amTry a higher sample rate.See attachment (pre-emphasis with alpha=75):With 480kSa/s, analog and digital line-up nicely up to at least 30kHz.But with 48kSa/s, they deviate significantly from each other.[ Numerical precision (which I mentioned as potential problem with high sampe rates) is not an issue at all with this filter -- not even at 480kSa/s. ]

author: gf
author_rank: Super Contributor
timestamp: August 27, 2025, 10:41:32 am
content: Quote from: radiolistener on August 27, 2025, 09:36:07 amBut you lose 37.5dB of signal level at low frequencies, whatever this means for the SNR.

author: Tation
author_rank: Regular Contributor
timestamp: August 27, 2025, 12:00:30 pm
content: The pre-emphasis/de-emphasis mechanism goal is precisely to increase SNR, as the FM modulation worsens SNR at high frequency, thus the pre-emphasis enhances high frequencies to protect them from increased noise.

author: radiolistener
author_rank: Super Contributor
timestamp: August 27, 2025, 08:16:20 pm
content: Quote from: gf on August 27, 2025, 09:43:15 amomg, it works...Previously I was trying in Octave using MATLAB examples that pass Fs to bilinear function, but it didn’t work and I couldn’t figure out why. Now, after looking more carefully at the bilinear function parameters in Octave documentation, I realized that the third argument is actually the sampling period, not the sampling frequency! What a sneaky trap! I really thought bilinear was broken in Octave, but with 1/Fs it works fine. Thanks!

author: radiolistener
author_rank: Super Contributor
timestamp: August 27, 2025, 09:45:42 pm
content: I asked сhat-gpt about how to design a pre-emphasis filter that is the inverse of a de-emphasis filter with the transfer function\$H(s) = \frac{1}{s \tau + 1}\$.Its suggestion was to introduce a high-frequency limitation using a second time constant, \$\tau_2\$. This leads to a filter of the form\$H(s) = \frac{\tau s + 1}{\tau_2 s + 1}\$,which closely resembles the parallel RC filter mentioned in standard:\$H(s) = \frac{\alpha \tau s + \alpha}{\alpha \tau s + 1}\$.In this approach, however, \$\tau_2\$ provides a more transparent and intuitive parameter.And at a glance it seems convenient to set the high-frequency pole at the Nyquist limit Fs/2:\$\tau_2 = \frac{2}{2 \pi Fs}\$.Thus, we obtain\$H(s) = \frac{\tau s + 1}{\tau_2 s + 1}\$, \$\quad \tau_2 = \frac{2}{2 \pi Fs}\$,which is convenient for cases where Fs and \$\tau\$ may change dynamically. I would be interested to hear your thoughts on this approach.What concerns me, however, is that the standard does not explicitly specify the de-emphasis filter specification, it only indirectly refers to the parallel RC type of pre-emphasis filter. Therefore, I am not entirely confident that it is correct to assume that receivers are expected to implement a de-emphasis filter of the form \$H(s) = \frac{1}{s \tau + 1}\$Are there any other radio communication standards that provide a more detailed specification of pre-emphasis and de-emphasis filters? Perhaps someone here is familiar with such standards.

author: radiolistener
author_rank: Super Contributor
timestamp: August 27, 2025, 11:52:58 pm
content: In the code of one DSP receiver, I came across an interesting implementation of a de-emphasis filter. Instead of using H(s)=1/(s*τ+1), it employs the transfer function H(z)=α/(1+(α−1)z^−1), where α=1.0−exp⁡(−1.0/(Fs*τ)).This filter provides a better magnitude approximation than applying a bilinear transform to H(s)=1/(s*τ+1), but exhibits larger phase errors. However, it is significantly faster, as it requires fewer computations.

author: gf
author_rank: Super Contributor
timestamp: August 28, 2025, 05:16:18 am
content: Quote from: radiolistener on August 27, 2025, 11:52:58 pmIsn't that the impulse invariant transform of H(s), except possibly a different scaling factor?

author: radiolistener
author_rank: Super Contributor
timestamp: August 28, 2025, 06:28:45 am
content: Quote from: gf on August 28, 2025, 05:16:18 amI'm not sure, here is how it calculate coefficients:Code:alpha = 1 - exp(-1/(Fs*tau));b = alpha;a = [1, -(1-alpha)];By the way, I found some more info about pre-emphasis/de-emphasis filters for AM and FM broadcast.1) Here is standard details for AM pre-emphasis/de-emphasis, which is well defined, include table with magnitude and phase (see attachment):https://www.nrscstandards.org/standards-and-guidelines/documents/standards/nrsc-1-c.pdfQuoteSo, for AM broadcast pre-emphasis filter is well defined and actually uses transfer function that I talked before - with tau2...:\$\tau_{2} = \frac{1}{2 \pi \cdot 8700}\$\$H(s) = \frac{\tau s + 1}{\tau_{2} s + 1}\$I tested it and it well correspond with provided table. So, for AM it is well defined.2) Here I found table with precise amplitude response values for various amounts of pre-emphasis for FM-broadcast, it has a table with precise magnitudes, but without phase (see attachment):https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=ce6f794e1f585eb827ab8bdaa506656c7e6dd842As I understand this table correspond to ideal transfer function \$H(s) = s \tau + 1\$ with no pole, so it makes even more confusion, because it doesn't fit with parallel RC filter and looks like precise inverion of RC low pass filter...So, now I suspect that FM pre-emphasis should be done with the same \$H(s) = \frac{\tau s + 1}{\tau_{2} s + 1}\$ with added pole, according to my tests, the pole should be around 3 MHz in order to fit with provided table - then it fits with values up to 15 kHz. But I'm not sure if this is correct, because ITU-R BS.450 talking about parallel RC...

author: gf
author_rank: Super Contributor
timestamp: August 28, 2025, 06:54:59 am
content: Quote from: radiolistener on August 27, 2025, 09:45:42 pmIn the R1,C,R filter circuit, tau_2=tau*alpha. The primary purpose of the parameter alpha is clearly to adjust the second time constant. [ Alpha also becomes the DC gain, but that's more an unavoidable side effect, not the reason why you choose a particular alpha value. ]

author: gf
author_rank: Super Contributor
timestamp: August 28, 2025, 08:27:08 am
content: Quote from: radiolistener on August 28, 2025, 06:28:45 amif a simple RC filter is used for de-emphasis, that gives <= 1dB error for f <= 4400 Hz (which is roughly the AM audio bandwidth).QuoteIMO, the upper corner (tau_2 pole) exists rather for practical purposes:1) to prevent indefinite boost for freqencies beyond the audio bandwidth2) adding the tau_2 pole leads to arealizabletransfer function (e.g. the discussed R1,C,R circuit)Quote3 MHz is quite highDo you really need < 0.001 dB approximation accurcy? In the end it depends on your error tolerance. If your limit is <= 1dB for <= 15 kHz, you need a corner frequency of only ~30kHz; or ~100kHz to obtain <= 0.1dB at <= 15kHz.

author: gf
author_rank: Super Contributor
timestamp: August 28, 2025, 08:41:14 am
content: Quote from: radiolistener on August 28, 2025, 06:28:45 amThe function [b,a] = impinvar(b_analog,a_analog,Fs) gives a different scaling (DC gain != 1). But otherwise, it is.

author: gf
author_rank: Super Contributor
timestamp: August 28, 2025, 10:46:30 am
content: Quote from: radiolistener on August 27, 2025, 11:52:58 pmIf you don't want to increase the sample rate, yet another option is to fit a higher order IIR to H(s), using invfreqz(), for example 3rd order:Code:[b,a] = butter(1,1/tau,"s") % analog filterf = linspace(0,24000,1001);H_analog = freqs(b,a,2*pi*f);clfplot(f,20*log10(abs(H_analog))); grid onhold on[b,a] = invfreqz(H_analog,f/Fs*2*pi,3,3)[H,f] = freqz(b,a,1000,Fs);plot(f,20*log10(abs(H))); grid onIt fits quite nicely up to 15kHz. The response beyond 15kHz is not so important, if the signal is bandwidth-limited.

author: Tation
author_rank: Regular Contributor
timestamp: August 28, 2025, 05:18:29 pm
content: Hi. Over my previous "hand-fitting" calculation of a 1st order IIR filter, I used a generic optimization method to get a better approximation. The result is a 1st order IIR filter that matches the desired amplitude of the de-emphasis analog filter, from 20 to 15000 Hz, with an error better that 0.035 dB. The filter has gain of 0.21540431671562316, a zero at -0.13476022498145307 and a pole at 0.7546404519578962.Code:import numpy as npfrom scipy import signal, optimizeimport matplotlib.pyplot as pltF_S = 48000F_MIN = 20F_MAX = 15000N = 4096TAU = 75e-6f_full = np.linspace(0, F_S / 2, N)f_mask = (F_MIN < f_full) & (f_full < F_MAX)f = f_full# analog transfer functions = 2j * np.pi * fha = (1 / TAU) / (s + 1 / TAU)ha_a = np.abs(ha)ha_db = 20 * np.log10(ha_a)ha_p = np.angle(ha, deg=True)# function to optimize (max dB error)def fun_db (params):g, z, p = params_f, h = signal.freqz([g, -g * z], [1, -p], worN=f, fs=F_S)h_a = np.abs(h)h_db = 20 * np.log10(h_a)d = h_db - ha_dbd_max = max(abs(d))return d_max#: def# function to optimize (max relative error, phase matters)def fun_rel (params):g, z, p = params_f, h = signal.freqz([g, -g * z], [1, -p], worN=f, fs=F_S)d = np.abs(h - ha) / ha_ad_max = max(d)return d_max#: def#initial guesszero = -0.152pole = 0.757gain = (1 - pole) / (1 - zero)# optimizeres = optimize.minimize(fun_db, [gain, zero, pole], bounds=((-3, 3), (-1, 1), (-1, 1)), method='Nelder-Mead')gain, zero, pole = res.xprint((gain, zero, pole))print(res.fun)# digital transfer functionnum_coeffs = np.array([gain, -gain * zero])den_coeffs = np.array([1, -pole])_f, hd = signal.freqz(num_coeffs, den_coeffs, worN=f_full, fs=F_S)hd_a = np.abs(hd)hd_db = 20 * np.log10(hd_a)hd_p = np.angle(hd, deg=True)# errore = hd_db - ha_dbep = hd_p - ha_p# --- Plot ---fig, (a_axs, p_axs, e_axs) = plt.subplots(3, 1, sharex=True)fig.suptitle("1st-order analog and digital filters (de-emphasis)")e_axs.set_xlim([0, F_S / 2])e_axs.set_xlabel("Frequency ")a_axs.plot(f, ha_db, label='analog')a_axs.plot(f_full, hd_db, label='digital')a_axs.set_ylabel("Amplitude ")a_axs.grid(True, which='both', linestyle='--', alpha=0.7)a_axs.set_ylim([-21, 1])a_axs.legend()p_axs.plot(f, ha_p, label='analog')p_axs.plot(f_full, hd_p, label='digital')p_axs.set_ylabel("Phase [°]")p_axs.grid(True, which='both', linestyle='--', alpha=0.7)p_axs.set_ylim([-90, 0])p_axs.legend()ea, = e_axs.plot(f, e)e_axs.set_ylabel("Error ")e_axs.grid(True, which='both', linestyle='--', alpha=0.7)e_axs.set_ylim([-0.05, 0.05])ep_axs = e_axs.twinx()ep, = ep_axs.plot(f, ep, 'C1')ep_axs.set_ylabel("Error [°]")ep_axs.grid(True, which='both', linestyle='dotted', alpha=0.7)ep_axs.set_ylim([-10, 60])ep_axs.legend([ea, ep], ['amplitude', 'phase'])plt.show(block=True)

author: Tation
author_rank: Regular Contributor
timestamp: August 28, 2025, 05:23:11 pm
content: Also made an attempt with another target function, just to also consider the phase error —using fun_rel() instead of fun_db() in the call to optimize.minimize() of the previous code—. The results are show below. Of course, not as good the amplitude fit as in the previous case.Made just for fun. Never used generic optimization methods to calculate IIR filters. Now interested in how will this perform for higher order filters and also with filters with poles and zeros outside of the real axis.

author: radiolistener
author_rank: Super Contributor
timestamp: August 28, 2025, 05:32:24 pm
content: Quote from: gf on August 28, 2025, 10:46:30 amWow, cool!The error is just 1.06 dB / -0.73° @ 20 kHz, and just 0.01 dB / -0.42° @ 15 kHz.This is exactly what I had unsuccessfully tried to do manually. Thanks!But as far as I know, higher-order IIR filters can suffer from unpredictable artifacts and glitches, right?

author: gf
author_rank: Super Contributor
timestamp: August 28, 2025, 05:56:01 pm
content: Quote from: Tation on August 28, 2025, 05:18:29 pmSeems to work better than invfreqz()At least with low order.[ Honestly I don't know how exactly invfreqz() does the optimization internally. ]

author: radiolistener
author_rank: Super Contributor
timestamp: August 28, 2025, 06:18:12 pm
content: it appears that the de-emphasis filter returned with invfreqz is unstable - it has one pole < -1Is it possible to call invfreqz but with reject unstable versions?

author: gf
author_rank: Super Contributor
timestamp: August 28, 2025, 06:33:07 pm
content: Quote from: radiolistener on August 28, 2025, 06:18:12 pmSeems that the iteration feature (Steiglitz McBride) is not yet implemented in Octave (at least not in my old version), and the default algorith can return unstable solutionsI don't have Matlab to check if it works there.

author: radiolistener
author_rank: Super Contributor
timestamp: August 28, 2025, 09:09:27 pm
content: Quote from: gf on August 28, 2025, 06:33:07 pmYou can use Matlab online for free (with limited time per month):https://matlab.mathworks.com/I tested the same code on matlab and it also returns unstable filter.Does it require to enable something special?

author: radiolistener
author_rank: Super Contributor
timestamp: August 28, 2025, 09:45:52 pm
content: There is separate functionstmcbfor using Steiglitz-McBride iteration method.But it produces very bad result. Is there any mistake in my code?

author: gf
author_rank: Super Contributor
timestamp: August 28, 2025, 10:14:53 pm
content: Quote from: radiolistener on August 28, 2025, 09:09:27 pmI'm not sure. I think you must specify the "iter" parameter, and maybe also "tol".Quote from: https://www.mathworks.com/help/signal/ref/invfreqz.htmlQuote from: radiolistener on August 28, 2025, 09:45:52 pmI was not aware of this function and don't know how to use it.But even if used correctly, I would expect it to suffer from the same problem as impinvar(), since it saisQuote

author: radiolistener
author_rank: Super Contributor
timestamp: August 28, 2025, 11:01:37 pm
content: Thus, for FM, the best approximation we have identified is the following:1) pre-emphasis:H(s) = (tau*s + 1);real approximation: H(s) = (tau*s + 1) / (tau2*s + 1);Code:tau2 = 1 / (2*pi*3000000);[b,a] = bilinear([tau, 1], [tau2, 1], 1/Fs);Stable IIR3.61 dB / 2.31° error @ 15 kHz9.06 dB / 2.84° error @ 20 kHz2) de-emphasis:H(s) = 1 / (s*tau + 1);Code:[b,a] = bilinear(1, [tau, 1], 1/Fs);Stable IIR-3.61 dB / -2.75° error @ 15 kHz-9.06 dB / -3.93° error @ 20 kHzThey complement each other well, resulting in a flat overall response, but deviate noticeably from the analog filter at higher frequencies.Are there other methods that might yield better precision?My target is an error of less than 1 dB across the 0-15 kHz range.

author: radiolistener
author_rank: Super Contributor
timestamp: August 29, 2025, 05:42:21 am
content: The problem with this IIR pre-emphasis filterCode:tau2 = 1 / (2*pi*3000000);[b,a] = bilinear([tau, 1], [tau2, 1], 1/Fs);is that it has extreme high gain above 16 kHz, it leads to extreme high overshoots. Applying 15 kHz LPF before this IIR helps a little bit, but overshoot still present.Decrease pole frequency from 3 MHz to 20 kHz helps to solve overshoot issue, but it leads to a very high phase error (see screenshot 3).Any idea on how to fix it?

author: Tation
author_rank: Regular Contributor
timestamp: August 29, 2025, 08:10:25 am
content: For pre-emphasis, the same approach (1st order IIR) gives same results: quite good amplitude behavior, but not so good phase.amplitude error from 20 to 15000 Hz: < 0.035 dBgain: 4.642338114529643pole: -0.1347590303623547zero: 0.75471552503325Despite the phase mismatch (of both this and thede-emphasis one), these are better than the 64 tap FIR filter found in some other SDR receiver reportedpreviouslyon this thread.

author: Tation
author_rank: Regular Contributor
timestamp: August 29, 2025, 09:07:14 am
content: No tau2, as, IMHO, it is not needed in the digital versions of these filters.What's the point of introducing it in the digital domain? In the analog version it is an artifact introduced by the realizability of the RC network, for the decay in gain with frequency of OPAMPs and to avoid HF noise. But in the digital version the gain of the filter does not rise above 20 dB at any frequency, and the input signal bandwidth is supposed to be limited previously to 15 kHz.Great efforts here to achieve a given phase response, but it is modified by the addition of tau2.

author: gf
author_rank: Super Contributor
timestamp: August 29, 2025, 09:34:09 am
content: Quote from: Tation on August 29, 2025, 09:07:14 amI agree, of course, that a 3MHz pole does not make sense when the sample rate is 48k.QuoteIf the aim is de-emphasis with an RC filter, then your statement is perfectly correct.OTOH if the standard requires a particular tau2, it should be honored.Wording like "atypicaltau2 is..." is unfortunately not really helpful.Btw, I've deleted my previous post as the result was wrong due to a typo in my calculation

author: radiolistener
author_rank: Super Contributor
timestamp: August 29, 2025, 09:56:06 am
content: Quote from: gf on August 29, 2025, 09:34:09 amI added 3 MHz pole in order to keep phase response of digital IIR close to analog filter. If you reduce frequency of this pole from 3 MHz to 20-24 kHz it leads to high phase error, see screenshots above. The 3 MHz frequency itself was chosen so that the analog filter matches the magnitude table from the article up to 15 kHz - that is, so that both the amplitude and phase responses up to 15 kHz align with the function.This whole struggle with the amendments looks rather discouraging. For AM de-emphasis, adding a pole as specified in the standard at least makes the situation more predictable and the filters feasible to implement. With FM, however, it almost seems as if the standard was designed to make DSP implementation deliberately difficult. Pre-emphasis, in particular, is not even practically realizable in analog form. Attempts to approximate it quickly turn into a battle with the coefficients - either the phase drifts or the magnitude distorts.I started wondering: is it possible to design an FIR filter - not with linear phase, but with a phase response that complements the phase of the analog filter (phase-compensating)? In other words: to design an FIR filter that simulate an analog filter not only in amplitude but also in phase, or one with a flat magnitude response and an arbitrary specified phase response to compensate for the phase distortions of the analog filter. Is it possible? How could this be achieved?

author: gf
author_rank: Super Contributor
timestamp: August 29, 2025, 10:26:15 am
content: Quote from: radiolistener on August 29, 2025, 09:56:06 amI have not checked the numbers, but I guess the table is just the inverse of the RC de-emphasis lowpass. The tau2 is primarily introduced to obtain arealizableanalog pre-emphasis filter (accepting the drawback that it leads to a deviation from ideal response).EDIT:In your AM spec, a dedicated pole frequency was specified. So in this case, I think it should be honored.I still wonder if the mentioned alpha=1/3 for FM is mandatory, or if it was just meant as an example.QuoteSure, you can approximate it. Only a symmetric FIR filter has linear phase. For this task, you need an assymetric one. Acuracy is just a matter of the number of taps. But unavoidably, the filter introduces anadditional delay.QuoteE.g. ifft, + windowing to smooth the ripple.

author: gf
author_rank: Super Contributor
timestamp: August 29, 2025, 10:50:59 am
content: I tried a higher order IIR fit again, using invfreqz(). With 5th order I got a nice fit (incl. phase) up to 15kHz to the transfer function H(s)=s*tau+1. It was, however, necesary to deliberately add a delay of 4 samples to obtain a stable filter. [ Note, for evaluation of the phase error, the delay must subtracted out. The same applies of course, when a FIR filter is used. ]b =-0.015019 0.093211 -0.391778 1.715462 4.103263 -3.946741a =1.0000000 0.6327137 -0.1021457 0.0364529 -0.0114857 0.0029219EDIT: Added codeCode:b = [ tau 1 ]; a = [ 1 ];f = linspace(0,24000,2401);H_analog = freqs(b,a,2*pi*f);clfsubplot(2,1,1)plot(f,20*log10(abs(H_analog))); grid onhold onsubplot(2,1,2)plot(f,unwrap(arg(H_analog))); grid onhold onf = linspace(0,15000,1001);H_analog = freqs(b,a,2*pi*f);delay=4H_analog .*= exp(-2i*pi*f/Fs*delay);[bz,az] = invfreqz(H_analog,f/Fs*2*pi,5,5)[H,f] = freqz(bz,az,2400,Fs);% subtract out delayH .*= exp(2i*pi*f/Fs*delay);subplot(2,1,1)plot(f,20*log10(abs(H))); grid onsubplot(2,1,2)plot(f,unwrap(arg(H))); grid on

author: gf
author_rank: Super Contributor
timestamp: August 29, 2025, 12:56:17 pm
content: Quote from: gf on August 29, 2025, 10:26:15 amHere is an example, with 13 taps for pre-emphasis H(s)=s*tau+1.[ De-emphasis needs more taps, and so does pre-emphasis with tau2 included. ]Code:Ntaps = 13 % must be oddtau = 75e-6b = [ tau 1 ]a = [ 1 ]% plot analog filter responsef = linspace(0,24000,2401);H_analog = freqs(b,a,2*pi*f);clfsubplot(2,1,1)plot(f,20*log10(abs(H_analog))); grid onsubplot(2,1,2)plot(f,unwrap(arg(H_analog))); grid on% sample analog frequency response at Ntaps points% include both, positive and negative frequenciesf = [0:Ntaps-1]/Ntaps*Fs;f(f >= Fs/2) -= Fs;H_analog = freqs(b,a,2*pi*f);% make FIR filterh = fftshift(real(ifft(H_analog)));h = h .* blackman(Ntaps)';h /= sum(h);[H,f] = freqz(h,1,2400,Fs);% subtract out delay, for comparisondelay = (Ntaps-1)/2H .*= exp(2i*pi*f/Fs*delay);subplot(2,1,1)hold onplot(f,20*log10(abs(H))); grid onsubplot(2,1,2)hold onplot(f,unwrap(arg(H))); grid on

author: radiolistener
author_rank: Super Contributor
timestamp: August 29, 2025, 06:54:20 pm
content: Quote from: gf on August 29, 2025, 10:50:59 amInterestingly, the amplitude and phase responses of this variant resemble those of a filter with an additional pole at 3 MHz. However, the same issue arises - the filter gain increases significantly above 15 kHz, leading to signal overshoot problems. It seems that designing an IIR filter without this drawback may not be possible.

author: radiolistener
author_rank: Super Contributor
timestamp: August 29, 2025, 07:02:50 pm
content: Quote from: gf on August 29, 2025, 12:56:17 pmThis looks much more promising - both magnitude and phase are fairly accurate up to 15 kHz, while above that the filter gain decreases, which should helps avoid unwanted signal overshoots. A more detailed analysis is needed, interestingly, I previously tried a similar approach but did not achieve the same result, most likely due to some mistake or overlooking a delay-related nuance.What is unexpectedly good is that the filter size turned out to be relatively small - I was expecting something on the order of 511 taps or even more. Thanks.

author: radiolistener
author_rank: Super Contributor
timestamp: August 29, 2025, 09:47:22 pm
content: Quote from: gf on August 29, 2025, 10:50:59 amyeah, I missed this delay nuance for phase comparison. But just to clarify, in your code you multiply by exp(2i*pi*f/Fs*delay) before plotting. My understanding is that this just shifts the FIR phase with constant delay for visual alignment with the analog filter, without modifying the actual frequency-dependent phase. In other words, applying the FIR without this phase-shift adjustment will produce the correct phase pre-emphasis for subsequent analog de-emphasis filter, right?

author: gf
author_rank: Super Contributor
timestamp: August 29, 2025, 10:16:14 pm
content: Quote from: radiolistener on August 29, 2025, 09:47:22 pmExactly.QuoteWithin the frequency region of interest, the phase is approximately the same as that of the emulated analog pre-emphasis filter, plus an additional constant delay. I don't think you'll be concerned about the delay. Therefore, it should be suitable for analogue de-emphasis with an RC filter.

author: gf
author_rank: Super Contributor
timestamp: August 29, 2025, 10:33:18 pm
content: Quote from: radiolistener on August 29, 2025, 06:54:20 pmThe presence of a 3Mhz pole has not very much effect for H(s) in the 0...15kHz range.QuoteFittingonly the region of interest(0...15 kHz) seems to be the key to get a good fit with a low order. Beyond 15 kHz, the response is undefined then. It is as it is. Unless it's too weird, why do you care if the signal is bandwidth-limited to 15 kHz anyway?Seems that 5th order was possibly even overkill. With 3rd order (and delay=2) the result is still good and even with 2nd order (and delay=1) it is not that bad.The key to achieve stability with the higher-order IIR apprxoimaton is obviously the introduction of an extra delay.Some ringing in the impulse or step response is IMO unavoidable, because the frequency response, which has an infinite extent in the analog domain, must be bandwidh-limited to Nyquist in the digital domain. This applies to FIR filters, too.

author: radiolistener
author_rank: Super Contributor
timestamp: August 30, 2025, 12:07:29 am
content: Quote from: gf on August 29, 2025, 10:33:18 pmI get noticeable overshoots even when input signal is bandlimited with large LPF FIR with 150 dB stop-band attenuation above 15 kHz. It happens when signal is going from DC to max amplitude 700 Hz sineHm.. just tried FIR, it also produce overshoots, any idea why it happens?Left wave is input signal, right side is output signal. The sine is 700 Hz. Fs=384000Updated:It appears that I forgot about FIR gain normalization.At the moment of switching the test signal from DC to a 700 Hz tone, a transient impulse is generated, with its rise time limited by the preceding low-pass filter to 15 kHz limit. When passing through the pre-emphasis filter, the high-frequency components of this transient are boosted up to the maximum gain at 15 kHz, while the steady-state 700 Hz tone itself is attenuated. So, this results in an overshoot at the transition, which is an expected behavior and indicates that the filter is functioning correctly. I added gain normalization and it appears that all works ok, the sine is attenuated at -17.4 dB - as expected, see second picture for details.

author: Tation
author_rank: Regular Contributor
timestamp: August 30, 2025, 07:39:57 am
content: The pre-emphasis filter, from 2100 Hz up, behaves as a differentiator (the transfer function of a differentiator is \(k\cdot s\)), so expect spikes at each "discontinuity". The analog counterpart will also suffer from this.

author: gf
author_rank: Super Contributor
timestamp: August 30, 2025, 01:44:46 pm
content: Quote from: radiolistener on August 30, 2025, 12:07:29 amThe crucial point is that already the BW-limit limiting to 15 kHz likely introduces overshoot/ringing. It depends, of course, onhowthe bandwidth is limited.A brickwall filter unavoidably introduces lots of overshoot/ringing. The impulse response of an ideal brickwall filter is a sin(x)/x impulse, which clearly shows oscillations.1)If you want the BW limit to limit the rise time without overshooting, then the filter's roll-off must bevery soft, i.e. the transition band must be very wide. A Gaussian filter, for example, (which does not overshoot) has a BW-60dBto BW-3dBratio of about 4.47. This means, if we aim for 60 dB stop band attenuation at 15 kHz, the -3dB cutoff point would need to be as low as ~3.3kHz. Even if you consider 40 dB stop band attenuation @ 15 kHz as sufficient, the -3dB cutoff point still would need to be at ~4.1 kHz.In the end, it's always a compromise. But one thing has to be clear: It is not possible to enforce a bandwidth limit with a maximally flat frequency response and a steep transition band without overshoot/ringing in the step response. And a frequency response with a non-overshooting step response cannot be maximally flat in the passband, but it rolls off softly, with the roll-off already starting at DC.Anyway, if the signal you feed into the discussed pre-emphasis filter already has been bandwidth-limited to eliminate components > 15 kHz, the pre-emphasis filter won't introduceadditionalringing, but it will behave like its analog counterpart. [ But the preceding BW-limiter may already have introduced undesired distortion. ]1)By the way, while the Fourier spectrum of a sin(x)/x impulse is flat up to the brickwall frequency and zero beyond, it is claimed that such an impulse is perceived as a short beep because the ear perceives sound differently (more in the time-frequency domain rather than the frequency domain). Additionally, some argue that the non-causal pre-ringing caused by many linear-phase filters is perceived as unnatural, despite the absence of phase distortion.

author: mawyatt
author_rank: Super Contributor
timestamp: August 30, 2025, 03:01:28 pm
content: Quote from: gf on August 30, 2025, 01:44:46 pmHere's an example of a 1kHz Squarewave passed thru an ideal Brickwall LPF corner frequency at the 16th harmonic (16kHz). Being a Squarewave it has all it's harmonics preserved until the 17th and beyond being attenuated to ideally zero. Of course the even harmonics don't exist in an ideal Squarewave so the last harmonic in the result is the 15th. Note the ringingbeforethe rising edge occurs as well as the usual overshoot ringingafterthe edge.This waveform was created by adding up the first 15 harmonics (only odds, evens are 0 amplitude) of a 1kHz sinewave with the proper amplitudes, thus mimicking an ideal squarewave passed thru and ideal Brickwall LPF limiting the output to the first 15 harmonics.Added an example of a squarewave created by an AWG (Standard Waveform) which has a finite limited number of harmonics to create the squarewave, note the "ringing" prior to the edge!! Using DSO Zoom and Average to show "Edge Effects". Note the symmetry in the "ringing" which hints this is caused by the limited harmonic waveform construction rather than the usual non ideal termination cable effects.Anyway, hopes this illustrates non-causal behavior for some folks that may not be aware of such.Best

author: gf
author_rank: Super Contributor
timestamp: August 30, 2025, 03:06:42 pm
content: Quote from: radiolistener on August 30, 2025, 12:07:29 amI cannot reproduce your plots. Attached is what I get with the discussed FIR and IIR pre-emphasis filters. There is a horizontal offset due to different delay. I did the BW limit with a FIR filter with a flat passband up to 14 kHz and 60 dB stopband attenuation for >= 15 kHz, i.e. a quite narrow/steep transition band. The ringing (or ripples, or however you want to call it) near the discontinuity come from the BW limit filter, and the steeper edge at the beginning of the first period comes from the pre-emphasis.EDIT: This was also calculated at higher (10x) sample rate to see more details.EDIT: One additional observation: In the time domain, the the pre-emphasis filter also boosts the amplitude of the ripples introduced by the BW limit filter. In the frequency domain, the cobined response nevertheless looks as expected. The de-emphasis is, of course, expected to undo that again.

author: radiolistener
author_rank: Super Contributor
timestamp: August 30, 2025, 07:03:36 pm
content: Quote from: gf on August 30, 2025, 03:06:42 pmNote, that I used cosine for test, so it starts as max amplitude pulse which is then bandlimited with LPF.Here is test signal generator that I used for tests:Code:Fs = 384000;N = 1 * Fs; % 1 sect = (0:N-1)' / Fs; % time vectorsilence = zeros(N, 1); % silencesin700 = cos(2*pi*700*t); % 700 Hzsin900 = cos(2*pi*900*t); % 900 HzsinSum = cos(2*pi*700*t) + cos(2*pi*900*t); % sum 700 Hz + 900 HzsinSum = sinSum / max(abs(sinSum)); % normalize% 4 sec sweep 10 Hz -> 20 kHzN = 4 * Fs;t = (0:N-1)' / Fs;sinChirp= chirp(t, 10, 4, 20000, 'logarithmic'); % 'linear', 'logarithmic'sinChirp= sinChirp / max(abs(sinChirp)); % normalizemsg = [...[silence, silence ]; ...[sin700, silence ]; ... % 700 Hz left, 0 right[silence, sin900 ]; ... % 0 left, 900 Hz right[sinSum, sinSum ]; ... % both channels same sum 700+900 Hz[sinChirp,sinChirp]; ... % both channels same sum chirp 10->20 kHz];if 1% FIR LPF 15 KHzFcut = 15000;[firTaps, firA] = fir_taps(Fs, Fcut/10, 150, 0.1);lpf_15k = fir_lpf(firTaps, Fs, Fcut-Fcut/20, firA);lpf_15k = lpf_15k / sum(lpf_15k);fprintf('FIR taps: %d, A: %.1f dB\n', firTaps, firA);msg = filtfilt(lpf_15k, 1, msg);endaudiowrite('test-384-lr.flac', msg, Fs, 'BitsPerSample', 24);fir_taps and fir_lpf are my helper funcs which estimate FIR parameters with kaiser window:Code:% Fs - sample rate% Ftran - transition width % Astop - stopband atten % Apass - passband ripple function [firTaps, firA] = fir_taps(Fs, Ftran, Astop, Apass)Wt = Ftran / (Fs / 2); % Normalized transition widthdev_stop = 1/(10^(Astop/20)); % Stopband deviationdev_pass = (10^(Apass/20) - 1) / (10^(Apass/20) + 1); % Passband deviationfirA = -20 * log10(min(dev_pass, dev_stop)); % Minimum stopband attenuation in dBfirN = ceil((firA - 8) / (2.285 * pi * Wt));firTaps = firN + 1;endCreate FIR LPF with fixed number of taps% taps - number of taps (filter length)% Fs - sample rate% Fpass - cutoff frequency% firA - minimum required attenuationfunction b = fir_lpf(taps, Fs, Fpass, firA)% Check number of tapsif (taps < 2)error('Number of taps must be at least 2');end% Normalized passband frequency (cutoff)Wp = Fpass / (Fs / 2);firN = taps - 1;% Design FIR filter using Kaiser windowb = fir1(firN, Wp, kaiser(taps, kaiserBeta(firA)));end% A - required suppression in dBfunction bta = kaiserBeta(A)if (A >= 50)bta = 0.1102 * (A - 8.7);elseif (A < 50 && A > 21)bta = 0.5842 * (A - 21)^0.4 + 0.07886 * (A - 21);elsebta = 0;endendRegarding the signal overshoots, as mentioned earlier, this is an expected behavior since we are dealing with a high-pass characteristic. I am aware that overshoots are common for filters with sharp cutoffs - it is undesirable but usually mitigated by applying a slight gain correction.Overall, the filter performs as intended, but after normalizing the gain to the +17.073 dB peak at 15 kHz, I noticed that the received audio sounded quieter. Further investigation revealed that FM broadcast stations, in fact, do not normalize the signal after the pre-emphasis stage! Instead, the modulator is driven with an input signal exceeding unity, and the effective FM deviation increases due to the pre-emphasis filter gain. As a result, after applying de-emphasis at the receiver side, the frequency response becomes flat at 0 dB.Thus, I removed the FIR gain normalization and kept the pre-emphasis filter as is, which resulted in restoring the full signal loudness at the receiver output.The fact that FM-broadcast systems deliberately do not compensate the pre-emphasis output, but rather allow the increased FM deviation dictated by the pre-emphasis gain, was a small revelation for me.I now understand why many FM stations occupy a wider bandwidth with increased FM deviation - they simply allow for higher signal at the pre-emphasis input, while the modulator itself is designed to operate with the higher deviation.

author: gf
author_rank: Super Contributor
timestamp: August 30, 2025, 08:32:34 pm
content: Quote from: radiolistener on August 30, 2025, 07:03:36 pmSorry, my fault, I missed that. Then the response is as expected.

author: gf
author_rank: Super Contributor
timestamp: August 30, 2025, 10:00:10 pm
content: Quote from: radiolistener on August 30, 2025, 07:03:36 pmAI told me that they are using not a fixed gain, but a dynamic compressor (even multi-band compressor) in front of the modulator to prevent over-modulation. I didn't research original sources, though. This would mean that what we get is not HiFi in the traditional sense (reproduction as natural as possible, keeping the original DR), but rather an "artistically" processed sound.Quote from: Gemini

author: mawyatt
author_rank: Super Contributor
timestamp: August 30, 2025, 10:26:17 pm
content: There should be "limits" that are imposed on FM broadcasts which dictate how much deviation is allowed, otherwise you would have stations "stepping" on each other.Interestingly one could crudely consider Spread Spectrum as a digital form of pre-emphasis (spreading) at the Tx and de-emphasis (de-spreading) at the Rx.Best

author: radiolistener
author_rank: Super Contributor
timestamp: August 31, 2025, 06:25:25 am
content: It turned out this is not quite the case. When I first added the pre-emphasis filter, I couldn’t understand why the resulting audio was so quiet - I pushed the gain up to the maximum (just before overload), but the signal still sounded weak.To investigate, I recorded a strong FM broadcast station off-air and demodulated it. What immediately stood out was that the peak deviation reached about 192 kHz, instead of the nominal 75 kHz standard (for music). This explains the loudness: if you demodulate a signal with 75 kHz deviation, the recovered composite signal amplitude will be around 2.56, i.e. significantly greater than 1.Even more interesting: after applying the de-emphasis filter to the demodulated L/R channels, I obtained an almost flat frequency response, with the peak amplitude of a single channel around 0.4999. When summed to mono, that gives almost exactly 1. In other words, the extra deviation from pre-emphasis effectively produces "over-modulation" in the baseband, but in practice it aligns so that the de-emphasized output has the expected flat response and full amplitude.I then applied the same approach in my own modulator - just removed normalization after pre-emphasis and the result was that my FM signal sounded loud and clean on multiple receivers (including an analog one).

author: gf
author_rank: Super Contributor
timestamp: August 31, 2025, 09:26:13 am
content: 2.56 is quite a lot. The question is, are these peaks of frequent or infrequent reoccurance inthis sense? Anyway, I'd say 2.56 violates this regulation?[ Anold documentalso did allow infrequent burts of over-modulation, and also specified roughly what they consider "infrequent". But this document is outdatet. ]

author: radiolistener
author_rank: Super Contributor
timestamp: August 31, 2025, 08:09:37 pm
content: Quote from: gf on August 31, 2025, 09:26:13 amThat’s a very good point. From what I see on-air, some stations do keep their occupied spectrum within ~200 kHz (sometimes even a bit less), but others clearly exceed it - I’ve measured occupied bandwidths up to 400-450 kHz for some of them. That might indicate that their modulation parameters are not fully compliant.From my own experiments, if I strictly keep the deviation limited to 75 kHz, the loudness after applying pre-emphasis becomes very low, since the lower frequencies are attenuated by about 10-15 dB relative to the highs. This seems to explain why practical FM broadcasts often run with much larger peak deviations: otherwise, the signal would sound unnaturally quiet after de-emphasis.There is another nuance I’d like to clarify - am I interpreting the deviation level correctly?This is how I currently doing FM modulation:Code:wfm_df = 75000; % FM deviation 75 kHzphase = cumsum(composite) * 2*pi*wfm_df / Fs;iq = exp(1i * phase);As far as I understand, this should be the theoretically correct approach. However, I’ve occasionally come across opinions suggesting that the multiplier should be 4, or not 2 at all, but no scaling. From my perspective that doesn’t seem correct, but I’d like to confirm.

author: gf
author_rank: Super Contributor
timestamp: August 31, 2025, 10:36:44 pm
content: Quote from: radiolistener on August 31, 2025, 08:09:37 pmomega=2*pi*f, so 2 is correct. However, cumsum is only a reasonable approximation for an integrator H(s)=1/s at frequencies much lower than the sample rate.

author: radiolistener
author_rank: Super Contributor
timestamp: September 01, 2025, 03:51:05 am
content: Quote from: gf on August 31, 2025, 10:36:44 pmThank you for the hint. After reading your message, I revisited my code and immediately noticed a several issues.Your remark about transfer function H(s)=1/s prompted me to reconsider the problem from a different perspective. This is an interesting viewpoint - I hadn’t looked at FM from the filter perspective before.I get IIR via the bilinear transform of H(s)=1/s and get this one:\$H(z) = \frac{T}{2} \cdot \frac{1 + z^{-1}}{1 - z^{-1}}, T = \frac{1}{Fs}\$As I understand its the same as using trapezoidal integration method - cumtrapz, so the better way is to useCode:phi = cumtrapz(composite) * 2*pi*wfm_df / Fs;And it should give much better approximation. Is that correct?

author: gf
author_rank: Super Contributor
timestamp: September 01, 2025, 07:36:10 am
content: Quote from: radiolistener on September 01, 2025, 03:51:05 amIn the continuous time domain you would have to integrate omega(t) dt, in order to get phase(t). So it's an integrator, and in the frequency domain it's 1/s.QuoteMy understanding is, too, that the bilinear transform of 1/s is equivalent to cumtrapz. And cumsum is the impulse invariant transform of 1/s. But both are only approximations for an integrator, with different drawback. Cumsum boosts high freqencies while cumtrapz attenuates them. Magnitude error of cumtrapz (in dB) is even higher, at high frequencies. OTOH, cumtrapz has exact frequency-invariant phase of -pi/2, while cumsum has has not.EDIT:For both, I'd use a sample rate of Fs >= 10 * fmax.A (say) 200 kSa/s sample rate (which allows +-100 kHz offset from the carrier) is possibly high enough for sufficient accuracy up tp 15 kHz. Depends on your tolerance, of course.Btw, both have their pole on the unit circle, so they are semistable (which is to be expected from an integrator). Numerical errors can therefore add up over time, resulting in a drift of the calculated absolute phase(t). I don't think that it matters for the FM use case, though.

author: radiolistener
author_rank: Super Contributor
timestamp: September 01, 2025, 10:09:26 am
content: Quote from: gf on September 01, 2025, 07:36:10 amUsually FM broadcast stereo composite has fmax = 38+15 = 53 kHzWith RDS it will be fmax = 57 + 2 = 59 kHz.Fs >= 590 kHz is too much. I'm expecting to use standard Fs=384 kHz. Is there a way to get better quality with Fs >= 7*fmax?Regarding over-deviation, it appears there is no actual error - achieving normal audio loudness without exceeding the standard 75 kHz peak deviation looks not possible. A measured deviation of 2.5 times the limit may be excessive, since for testing I initially used a station that clearly operates beyond the nominal FM bandwidth. For verification, I measured another station that fits much better within the channel mask, it plays fine on receivers, but the measurements still show peak deviations about twice the standard limit. However, the distribution indicates that such peaks are relatively rare - they occur mainly during drum hits and high-frequency effects.Prior to the measurements, the signal was passed through a 200 kHz (400 kHz IQ bandwidth) FIR low-pass filter to eliminate adjacent-channel interference, and there is no sideband interference. Here are the measurements:Code:Fs: 480 kHzmax deviation: 153746 Hzmean deviation: 25418.5 Hzmedian deviation: 24874.7 Hzrms deviation: 29719.5 Hzmax(composite): 2.049944

author: gf
author_rank: Super Contributor
timestamp: September 01, 2025, 11:18:50 am
content: Quote from: radiolistener on September 01, 2025, 10:09:26 amI think I would combine the pre-emphasis and the integrator into a single filter and renounce some accuracy at the low end to make the filter stable ("leaky" integrator). I think an LF corner of 1 Hz or 0.1 Hz should not be a problem in practice -- audio does not go that low. Then even a first order IIR can be fitted nicely to the combined transfer function using invfreqz(). The lower the LF corner, the more numerical precision you need for the evaluation of the filter.Example for a sample rate of 384k:bz = [ 7.6304284107618013e-05 -7.3695696328586973e-05 ]az = [ 1 -1 ]EDIT: Note that the combination of pre-emphasis + FM is more or less equivalent to a low-frequency boost + PM.I.e. the output of this filter, multiplied by 2*pi*75000, directly modulates the phase (no cumsum or cumtrapz).

author: gf
author_rank: Super Contributor
timestamp: September 01, 2025, 12:07:48 pm
content: Quote from: radiolistener on September 01, 2025, 10:09:26 amSeems to fall into the category "infrequent reoccurances", which are tolerated, while a high-pitch continuous tone would not.

author: gf
author_rank: Super Contributor
timestamp: September 01, 2025, 12:52:19 pm
content: Quote from: gf on September 01, 2025, 11:18:50 amIf I think about it more thoroughly, that's fine for mono, but you want stereoThe modulated sub-carrier is not subject to pre-emphasis. Only the modulating audio signals L+R and L-R are. So pre-emphasis and integration can't be combined for stereo.Quote from: radiolistener on September 01, 2025, 10:09:26 amBtw, with 384 kSa/s, you also don't have much room for heavy over-modulation w/o suffering from aliasing.EDIT:Regarding integrator alone:Using 384 kSa/s, cumtrapz() has ~1dB magnitude error at 53 kHz, and exact phase, using 384 kSa/s. You may or may not consider that good enough. As said, cumtrapz is only marginally stable as it has a pole on the unit circle.An optimized 2nd order IIR with 1 sample additional delay fits very well at 53 kHz. But you have to make the integrator bit "leaky" (e.g. H(s)=1/(s+1) instead of 1/s), otherwise invfreqz() fails.