What about digital RIAA?

Old thread, but thought I'd check in.

My son-in-law was interested in putting together a Vinyl record to listen to some his parents old stuff, so I gave him an old receiver I had stored away and found two Dual turntables from the 60s/70s, both with problems, on Craigslist for very cheap. I got one working easily (a common problem with motor start capacitor) and he now has that set up and playing nicely. Now I have the other one, and old 1218 like I used to fix for a living about 40 years ago, running after some leisurely effort. Cleaned and replaced the usual grease that had turned to chewing gum, a common issue even in the 70's, and want to make the small amount of money invested back by selling it, all fixed, on Craigslist. But I have no analog pre stuff to test or demo with before putting it up for sale.

Then I remembered this old thread. I'm using a MiniDSP 2x4HD is our living room system, so I put in the RIAA EQ (boosted by 20dB) via one of its PEQ configurations, plugged the Dual into its analog inputs and voila! It even sounds remarkably good and noise isn't even really noticeable.

Here are the Biquad settings I used for RIAA. There are still lots of PEQ configs left over for other EQ work.

biquad1,
b0=01.05263157894737,
b1=-0.76417573949578,
b2=-0.24632736829188,
a1=1.866859545059558,
a2=-0.867284262601157
 
Last edited:
What a coincidence, I was just thinking about this thread as well. I was just thinking about pursuing dynamic range expansion, and started a thread on that. However, what would be better than doing it all in digital. Forget a 3 figure phono preamp and 3 figure 3bx or 4bx, just do it all in 1 box.
 
Without a sampling rate the coefficients are not totally useful. I posted these ad nauseum in my LA article.

MiniDSP 2x4HD = 96khz sample rate.

(gotta read between the lines)

The coefficients I posted are just some found earlier in this thread, I bumped up all the 'b' coeffs by x10 for a 20dB boost so it would play loud enough.
 
Last edited:
OK, if interested, PhonoEQ prototype demo is now available to download at Juha's Projects: PhonoEQ Software Project

Old thread but,anyway, here's link to my final project listed at Cyclin 74 site (MAX/MSP) Project: PhonoEQ | Cycling '''74

I have also released today this RIAA coefficient builder prototype as Matlab/Octave code (not yet tested in real time application):

Code:
% RIAA equalization filter
% Standard samplerates from 44100 to 384000 supported
% Brought to you by [email]jiiteepee@yahoo.se[/email] (8 April 2020)
function [b, a] = RIAA_deemphasis((x, inverted)
  %        x = samplerate in Hz
  % inverted : true = emphasis, false = de-emphasis
switch x 
  case { 44100, 88200, 176400, 352800 }
    a(1) = -3.78572821649894E-17*x^3 + 2.52492635019007E-11*x^2 - 5.29140550506889E-06*x + 0.4183761420686;
    a(2) = -3.29659785253531E-17*x^3 + 2.18188804908089E-11*x^2 - 4.49558809614241E-06*x + 0.340803782016109;
    a(3) = 2.13427162324699E-17*x^3 - 1.44832812129522E-11*x^2 + 3.14910650666778E-06*x - 0.270743433143131;
    a(4) = 2.43878784135422E-17*x^3 - 1.63703244700658E-11*x^2 + 3.47872123422787E-06*x - 0.284280409184197;
    a(5) = 5.14722389769101E-18*x^3 - 3.44467018649422E-12*x^2 + 7.27288189729686E-07*x - 0.05855692642697;
    a(6) = 1.78214502585031E-19*x^3 - 1.18972620155484E-13*x^2 + 2.49862328884841E-08*x - 0.001987028069768;
    b(1) = 1.0;
    b(2) = -4.55290631534176E-17*x^3 + 3.04003816124316E-11*x^2 - 6.38623072649445E-06*x + 0.036651228977512;
    b(3) = -2.17886339309136E-17*x^3 + 1.45484739554451E-11*x^2 - 3.05694119649456E-06*x - 1.15432992268202;
    b(4) = 3.87367489428091E-17*x^3 - 2.58899887170957E-11*x^2 + 5.45011238426768E-06*x - 0.156383761864616;
    b(5) = 2.40425973859099E-17*x^3 - 1.60789566553566E-11*x^2 + 3.38997016926901E-06*x + 0.247425823969509;
    b(6) = 2.54127108991136E-18*x^3 - 1.70179240935058E-12*x^2 + 3.59921561223217E-07*x + 0.041145736788926;
  case { 48000, 96000, 192000, 384000 }
    a(1) = -2.7452780571244E-17*x^3 + 1.99154393419583E-11*x^2 - 4.53584676661555E-06*x + 0.388910789461241;
    a(2) = -2.35251182142996E-17*x^3 + 1.69460468999989E-11*x^2 - 3.79976340701253E-06*x + 0.313417459710588;
    a(3) = 1.60394779826124E-17*x^3 - 1.18134248157214E-11*x^2 + 2.77914944092047E-06*x - 0.256686985639999;
    a(4) = 1.79214193481841E-17*x^3 - 1.30758453834294E-11*x^2 + 3.01551209856552E-06*x - 0.266372686264431;
    a(5) = 3.75875129146243E-18*x^3 - 2.73515275421544E-12*x^2 + 6.27167882845746E-07*x - 0.054669929110542;
    a(6) = 1.29466085326558E-19*x^3 - 9.40021380146474E-14*x^2 + 2.14525398501157E-08*x - 0.001849383721124;
    b(1) = 1.0;
    b(2) = -3.31087520545089E-17*x^3 + 2.40419060193625E-11*x^2 - 5.48704255441296E-06*x + 0.001655256200658;
    b(3) = -1.58217404372195E-17*x^3 + 1.14907596097219E-11*x^2 - 2.62396853400952E-06*x - 1.17120945842617;
    b(4) = 2.82267460112979E-17*x^3 - 2.05145448671967E-11*x^2 + 4.69079915137507E-06*x - 0.126870578343129;
    b(5) = 1.75227789917925E-17*x^3 - 1.27437895605759E-11*x^2 + 2.91872050553504E-06*x + 0.265751206588621;
    b(6) = 1.85456891004083E-18*x^3 - 1.35060949072864E-12*x^2 + 3.10309889494121E-07*x + 0.043074905938478;
  otherwise
    b = [1 0 0 0 0 0];
    a = [1 0 0 0 0 0];
  end
  
  if not(inverted)
    c = b;
    b = a;
    a = c;
  endif

This is enough accurate filter in question, even for 44.1kHz sampling, but, it is 6th order IIR implementation. If needed it can be turned to second order sections (SOS) with few lines of Matlab/Octave code (each sample rate needs its own set of SOS coefficients):

Code:
% Octave related package (comment next line for Matlab)
pkg load signal

format long;

fs = 44100; % user variable

[b, a] = RIAA_deemphasis(fs, inverted = false);
FLT=tf(b, a, 1/fs);
[a, b, T] = tfdata(FLT, 'v');
[sos, g] = tf2sos (b, a)
save -append RIAA.txt fs sos
 
I can't remember if it was this thread or another that mentioned last year that you might get milage from the idea of using an analog integrator amp for phono, and use digital to turn that into RIAA. The point being you equalize away the velocity-sensing response of standard cartridges before sampling in the ADC, so that you are back in the groove-displacement domain before quantization noise is added.

Doing all the bass boost in digital risks adding quantization to the LF noise, and the 1/f noise performance of the ADC is being probed too.

A quality analog integrator doesn't rely on precision components, and can be chosen for
low noise allowing a less than brilliant ADC to serve well.
 
Old thread but,anyway, here's link to my final project listed at Cyclin 74 site (MAX/MSP) Project: PhonoEQ | Cycling '''74

I have also released today this RIAA coefficient builder prototype as Matlab/Octave code (not yet tested in real time application):

Code:
% RIAA equalization filter
% Standard samplerates from 44100 to 384000 supported
% Brought to you by [email]jiiteepee@yahoo.se[/email] (8 April 2020)
function [b, a] = RIAA_deemphasis((x, inverted)
  %        x = samplerate in Hz
  % inverted : true = emphasis, false = de-emphasis
switch x 
  case { 44100, 88200, 176400, 352800 }
    a(1) = -3.78572821649894E-17*x^3 + 2.52492635019007E-11*x^2 - 5.29140550506889E-06*x + 0.4183761420686;
    a(2) = -3.29659785253531E-17*x^3 + 2.18188804908089E-11*x^2 - 4.49558809614241E-06*x + 0.340803782016109;
    a(3) = 2.13427162324699E-17*x^3 - 1.44832812129522E-11*x^2 + 3.14910650666778E-06*x - 0.270743433143131;
    a(4) = 2.43878784135422E-17*x^3 - 1.63703244700658E-11*x^2 + 3.47872123422787E-06*x - 0.284280409184197;
    a(5) = 5.14722389769101E-18*x^3 - 3.44467018649422E-12*x^2 + 7.27288189729686E-07*x - 0.05855692642697;
    a(6) = 1.78214502585031E-19*x^3 - 1.18972620155484E-13*x^2 + 2.49862328884841E-08*x - 0.001987028069768;
    b(1) = 1.0;
    b(2) = -4.55290631534176E-17*x^3 + 3.04003816124316E-11*x^2 - 6.38623072649445E-06*x + 0.036651228977512;
    b(3) = -2.17886339309136E-17*x^3 + 1.45484739554451E-11*x^2 - 3.05694119649456E-06*x - 1.15432992268202;
    b(4) = 3.87367489428091E-17*x^3 - 2.58899887170957E-11*x^2 + 5.45011238426768E-06*x - 0.156383761864616;
    b(5) = 2.40425973859099E-17*x^3 - 1.60789566553566E-11*x^2 + 3.38997016926901E-06*x + 0.247425823969509;
    b(6) = 2.54127108991136E-18*x^3 - 1.70179240935058E-12*x^2 + 3.59921561223217E-07*x + 0.041145736788926;
  case { 48000, 96000, 192000, 384000 }
    a(1) = -2.7452780571244E-17*x^3 + 1.99154393419583E-11*x^2 - 4.53584676661555E-06*x + 0.388910789461241;
    a(2) = -2.35251182142996E-17*x^3 + 1.69460468999989E-11*x^2 - 3.79976340701253E-06*x + 0.313417459710588;
    a(3) = 1.60394779826124E-17*x^3 - 1.18134248157214E-11*x^2 + 2.77914944092047E-06*x - 0.256686985639999;
    a(4) = 1.79214193481841E-17*x^3 - 1.30758453834294E-11*x^2 + 3.01551209856552E-06*x - 0.266372686264431;
    a(5) = 3.75875129146243E-18*x^3 - 2.73515275421544E-12*x^2 + 6.27167882845746E-07*x - 0.054669929110542;
    a(6) = 1.29466085326558E-19*x^3 - 9.40021380146474E-14*x^2 + 2.14525398501157E-08*x - 0.001849383721124;
    b(1) = 1.0;
    b(2) = -3.31087520545089E-17*x^3 + 2.40419060193625E-11*x^2 - 5.48704255441296E-06*x + 0.001655256200658;
    b(3) = -1.58217404372195E-17*x^3 + 1.14907596097219E-11*x^2 - 2.62396853400952E-06*x - 1.17120945842617;
    b(4) = 2.82267460112979E-17*x^3 - 2.05145448671967E-11*x^2 + 4.69079915137507E-06*x - 0.126870578343129;
    b(5) = 1.75227789917925E-17*x^3 - 1.27437895605759E-11*x^2 + 2.91872050553504E-06*x + 0.265751206588621;
    b(6) = 1.85456891004083E-18*x^3 - 1.35060949072864E-12*x^2 + 3.10309889494121E-07*x + 0.043074905938478;
  otherwise
    b = [1 0 0 0 0 0];
    a = [1 0 0 0 0 0];
  end
  
  if not(inverted)
    c = b;
    b = a;
    a = c;
  endif

This is enough accurate filter in question, even for 44.1kHz sampling, but, it is 6th order IIR implementation. If needed it can be turned to second order sections (SOS) with few lines of Matlab/Octave code (each sample rate needs its own set of SOS coefficients):

Code:
% Octave related package (comment next line for Matlab)
pkg load signal

format long;

fs = 44100; % user variable

[b, a] = RIAA_deemphasis(fs, inverted = false);
FLT=tf(b, a, 1/fs);
[a, b, T] = tfdata(FLT, 'v');
[sos, g] = tf2sos (b, a)
save -append RIAA.txt fs sos

Hi there...tried it in OctaveOnline but couldn't get it to work. I get the following:

parse error:

invalid parameter list

>>> function [b, a] = RIAA_deemphasis((x, inverted)
^

error: 'x' undefined near line 3 column 8
error: 'inverted' undefined near line 1 column 10


-Jim
 
I removed the extra left parenthesis and it works fine.

>> % Octave related package (comment next line for Matlab)
>> pkg load signal
>> format long;
>> fs = 44100; % user variable
>> [b, a] = RIAA_deemphasis(fs, inverted = false);
>> FLT=tf(b, a, 1/fs);
>> [a, b, T] = tfdata(FLT, 'v');
>> [sos, g] = tf2sos (b, a)
sos =

Columns 1 through 4:

1.000000000000000e+00 1.378486967081710e+00 4.488365901893578e-01 1.000000000000000e+00
1.000000000000000e+00 -5.753557696441296e-01 -1.210072468320916e-01 1.000000000000000e+00
1.000000000000000e+00 -9.928946284742323e-01 0.000000000000000e+00 1.000000000000000e+00

Columns 5 and 6:

1.427926241483392e+00 4.888083336703001e-01
2.921958359443325e-01 1.047888605670759e-02
-9.311756522967060e-01 0.000000000000000e+00

g = 4.331192289789358




Cool
 
No problem with quantization noise with the dither.

I can't remember if it was this thread or another that mentioned last year that you might get milage from the idea of using an analog integrator amp for phono, and use digital to turn that into RIAA. The point being you equalize away the velocity-sensing response of standard cartridges before sampling in the ADC, so that you are back in the groove-displacement domain before quantization noise is added.

Doing all the bass boost in digital risks adding quantization to the LF noise, and the 1/f noise performance of the ADC is being probed too.

A quality analog integrator doesn't rely on precision components, and can be chosen for
low noise allowing a less than brilliant ADC to serve well.

The high frequency content in the music and even just the record surface noise is sufficient dither to make the quantization noise a non-problem. I used a nearly identical digital equalization approach on very low frequency signals for electrocardiograms and the fidelity was amazing. It is patented and used in many heart monitors to this day.
 
Looks like an extra left paren

㔙 invalid parameter list

>>> function [b, a] = RIAA_deemphasis((x, inverted)

Thanks for the debugging.
I renamed the function name while posting here (without testing). Unfortunately I can't edit the original code listing in my post... .

There is also typo in my post stating its a 6th order filter implementation ... 5th order is the right type.
 
Thanks for the debugging.
I renamed the function name while posting here (without testing). Unfortunately I can't edit the original code listing in my post... .

There is also typo in my post stating its a 6th order filter implementation ... 5th order is the right type.

Jiiteepee,

great tool! sounds amazing too. Still first time user of Max8. Can you guide me how to process the file "not in real time".
In fact I would like to "load in" file and export it without "re-listening"

thanks!
 
IIRC, PhonoEQ was for real-time use (supports record/play) only (I don't have Max/MSP installed now so can't check what it can do).

You should be able to use Octave/Matlab for off-line processing but that needs some coding of course (load file, run through filter and save file).

I'm going to make either Nyqvist or LV2 plug-ins for Audacity off-line use but, need 1st to build all those various EQ's which PhonoEQ supports (I'll see if I manage to build RIAA version of plug-in soon (I have not yet looked the Nyqvist/LV2 language synthaxes...)).
 
Last edited:
...

I'm going to make either Nyqvist or LV2 plug-ins for Audacity off-line use but, need 1st to build all those various EQ's which PhonoEQ supports (I'll see if I manage to build RIAA version of plug-in soon (I have not yet looked the Nyqvist/LV2 language synthaxes...)).

Tried coefficients (got from 'generator' I posted few days ago) in Audacity Nyqvist -prompt:

Code:
(biquad-m s 1 1.427926241483388 0.4888083336702931 1 1.378486967081711 0.448836590189359)
(biquad-m s 1 0.2921958359443367 0.01047888605670886 1 0.1637263821579755 0)
(biquad-m s 1 -0.9311756522967053 0 1 -1.731976780276336 0.7338306985254864)

These are for 44100 kHz filter.

If needed, one can create coefficients using Octave and code from my earlier post to generate SOS coefficients for other sample rates (I had to swap a and b coefficients to get them working in Nyqvist prompt ... this means swap the a and b coefficient in save ... line found on my latter Octave listing earlier.