Data AcQuisition And Real-Time AnalysisScope - Spectrum - Spectrogram - Signal Generator
Software for Windows
Science with your Sound Card!
Contact us about
Sound Card IMD Meter Mini-App
Note: Before using this automated IMD meter, you may want to review the fundamentals of distortion measurement.
IMD_Meter is a macro mini-app included with Daqarta that provides a resizeable meter showing Intermodulation Distortion. It generates various two-tone test signals and analyzes the distortion of amplifiers, speakers, microphones, or other systems.
IMD_Meter uses a Custom Controls dialog that allows adjustment of various parameters. You can open this Help topic by right-clicking anywhere in the dialog, or on the separate meter itself.
The IMD_Meter macro sets Spectrum display mode and loads the IMDmeter.GEN Generator setup. It also opens the Custom Controls dialog, with an edit/slider control to set the F1 Frequency, a read-only control that shows the F2 Frequency, another read-only display of the F1/F2 Level Ratio, an adjustable time constant for the meter, a mode button that toggles between SMPTE, DIN, or CCIF / ITU-R modes, an Arbitrary / Spectral Line Lock frequency mode button, a channel select button, a Raw / Spectrum Average / Wave Average button, a time constant reset button, and a Percent / dB meter toggle button.
IMD_Meter was used for all measurements in the Intermodulation Distortion section of Sound Card Performance Tests.
The meter itself is a separate Custom Meter that shows both IMD and the selected channel it applies to. If that channel is not active, the meter shows "No Signal" plus the channel.
It is important that you adjust output and input signal levels for best results. If the input signal is too high, it can overload the input and cause distortion. As the input approaches clipping, you will see a forest of spectrum peaks rise up. Reduce the level until you are satisfied that the system is not near clipping. (This is usually visible in the Spectrum display before it becomes audible, or visible in the waveform display.)
Note that clipping can be caused by excessive levels at the sound card input even when the amp (or other device under test) is not itself clipping. Some sound card outputs may have clipping or other increased distortion when run at maximum levels. And of course the device under test may distort when driven at high levels.
The meter continues to run after closing the control dialog, until it is closed separately.
When you close the IMD Meter Controls and IMD Meter windows, the IMDmeter.GEN Generator setup remains loaded and active. The setup includes current output volume settings, so if you have changed them and want to use those settings again in the future, save the setup. (Current input settings are always saved automatically when Daqarta is closed, and restored on the next restart.)
Note that IMD distortion measurements themselves do not require any system calibration, since they are always measured as a percentage of the primary amplitudes.
In SMPTE mode the Generator produces tones at 60 Hz (f1) and 7000 Hz (f2) in a 4:1 ratio. If there is intermodulation between these two tones, there will be distortion products at sum and difference frequencies such as f2+f1, f2-f1, f2+2*f1, f2-2*f1, etc. (See Distortion Orders for more details.)
These products will thus appear above and below the 7000 Hz tone at 60 Hz intervals: 7000+/-60, 7000+/-120, etc. IMD is determined by measuring the total energy in two bands, each approximately 1200 Hz wide on either side of the 7000 Hz tone, in order to capture the first 20 positive and negative products. This total distortion energy is then divided by the energy in the 7000 Hz tone itself.
DIN mode operates identically to SMPTE, except that the two tones are 250 and 8000 Hz.
CCIF / ITU-R mode uses two equal-amplitude primary tones at 19000 Hz (f1) and 20000 Hz (f2). It reports two types of IMD values. The first (f2-f1) divides the distortion product at 1000 Hz by the total energy in the two primaries.
The second IMD value (4 term) finds the energy of the first 2 products below f1 at 2*f1-f2 and 3*f1-2*f2 (18000 and 17000 Hz) plus the first 2 above f2 at 2*f2-f1 and 3*f2-2*f1 (21000 and 22000 Hz), and likewise divides by the total energy in the two primaries.
The above mode descriptions use the frequencies specified in their respective standards. These frequencies don't happen to have an integer number of cycles in the 1024 samples used to compute the spectrum, so they don't fall exactly on spectral lines. That means they cause spectral leakage that produces "skirts" on the peaks, which adds to the apparent energy at distortion product frequencies. Although IMD_Meter uses a Blackman-Harris window function to greatly reduce this problem, the remaining leakage still limits the lowest IMD that can be resolved.
It is possible to eliminate the leakage entirely by choosing test frequencies that fall exactly on spectral lines, greatly improving the IMD resolution. To do this, toggle the frequency mode button from Arbitrary Frequency to Spectral Line Lock.
To see how significant this can be, toggle the channel control button from Left In, through Right In, to Left Out. This causes the meter to look at the original signal, as generated, without passing through the output D/A and the input A/D. No loopback cable is needed for this. This gives "best case" results, assuming perfect D/A and A/D and device under test. The table below shows IMD readings for the standard and line-locked modes. (For CCIF, only the 4-term result is shown. The f2-f1 result is near zero in both modes.)
SMPTE - Standard 60.000, 7000.000 0.1310% SMPTE - Line Lock 93.750, 6984.375 0.0019 DIN - Standard 250.000, 8000.000 0.1236 DIN - Line Lock 234.375, 8015.625 0.0017 CCIF - Standard 19000.000, 20000.000 0.0462 CCIF - Line Lock 18984.375, 20015.625 0.0003
As you can see, a tiny change in the frequencies makes a huge difference in the measurement resolution. You should always use Line Lock mode when you want the most reliable IMD measurements. There is nothing special about the standard frequencies, except that they are the standards. If you have to use them to conform to a test specification, you should at least take Line Lock measurements as well for comparison. If both give similar results, the measured system has enough IMD that Line Lock doesn't matter and you can feel confident reporting the standard values.
Note that when you toggle to Line Lock the f1 and f1 frequencies change to the nearest spectral line, but when you toggle back to Arbitrary they don't automatically change back to the default standard values. You need to toggle the SMPTE / DIN / CCIF button back to the same mode to reset the standard values.
Besides the standard and closest Line Lock values, you are also free to set other f1 values in any mode. In SMPTE and DIN modes the f2 value doesn't change when you change f1, but in CCIF mode the f2 value will track at 1000 Hz above f1 (or 1031.25 Hz above with Line Lock).
For noisy signals, the Time Constant Exponent controls simple smoothing of jittery meter values. The control value ranges from 0 to 10 and is applied as a power of 2 to determine the actual time constant, which then ranges from 1 (no smoothing) to 1024 (about 10 seconds). The default exponent is 5, which yields a time constant of 32.
The smoothed value is reset with the current instantaneous value whenever you change any control that could affect the reading, such as the IMD mode or test frequencies.
You can use the TC Reset button to reset the smoothed value manually. You might want to do this when using a high time constant, if something changes in the system under test and you don't want to wait for the meter to settle. Note, however, that a reset just starts smoothing from the current value, which may happen to be high due to jitter.
You can toggle the Raw button to Spectrum Average to accomplish smoothing of the entire raw spectrum before the IMD measurement. This is an Exponential average with a 32-frame time constant, which is comparable to the default using the above-mentioned Time Constant Exponent control, but with improved results.
Spectral averaging smooths the noise floor to its average value without reducing it. But clicking the Spectrum Average button will advance to Wave Average, which actually reduces the noise floor for higher resolution of ultra-low IMD values.
Waveform averaging requires synchrony to identical waveforms, which happen infrequently when the frequencies are not harmonically related. You can't use a simple waveform trigger since the waveform is always changing. Instead, a special trigger signal is created by the Generator at the lowest common period.
Consider the SPMTE test using 60 Hz and 7000 Hz. Note that in an interval of 1 second we'd (obviously) have exactly 60 cycles of the 60 Hz waveform, and 7000 cycles of the 7000 Hz waveform. We want the biggest integer that divides exactly into 60 and 7000; we can clearly can divide both by 10 to get 6 and 700, and then divide by 2 to get 3 and 350. So the divisor will be 10 * 2 = 20, such that in 1/20 second we get 3 cycles of 60 Hz and 350 of 7000.
So Daqarta needs to sync to a 20 Hz signal for waveform averaging of a SMPTE test. To do that, Stream 2 of the Left Output channel is set to 20 Hz, but its Level is set to 0 so there is no actual output generated at that frequency. The Generator can nevertheless sync to this "signal" by using the Trigger Mode set to Gen Sync.
For DIN mode, the above special Stream 2 signal is not required, since f2 (8000 Hz) is the 32nd harmonic of f1 (125 Hz), so setting Gen Sync to f1 is all that is needed.
In CCIF / ITU-R mode f1 and f2 are 1000 Hz apart, so the Stream 2 frequency is set to 1000.
Regardless of the IMD mode, when Spectral Line Lock is active f1 and f2 fall exactly on spectral lines. Since all spectral lines are multiples of the sample rate divided by the number of samples used, the Stream 2 frequency is set to 48000 / 1024 = 46.875 Hz for perfect synchrony in any mode.
;<Help=H4901 Close= ;Close any open data file Task="-_IMD_Task" ;Uninstall task, if present Spect=1 Ylog=1 SpectWind=BkHr SpectWindOn=0 SmplRate=48000 SpavgMode=Exp SpavgFrames=32 UI=Input ;Save current Input state A.LoadGEN="IMDmeter" ;Load Gen setup Input=UI ;Restore initial Input state Ctrls="<<IMD Meter Controls" ;Custom Controls title Ctrl0="<<F1 Frequency" ;Ctrl0 label Ctrl1="<<F2 Frequency" Ctrl2="<<F1/F2 Level Ratio" Ctrl3="<<Time Constant Exponent" Btn0="SMPTE" ;Default Btn0 label Btn1="Arbitrary Frequency" Ch=0 ;Left In default chan Btn2=""+Ch(c) ;Label Btn2 w. chan Btn3="Raw" ;Non-avg Btn4="TC Reset" Btn5="Percent" UT=TrigMode ;Save trigger mode for exit TrigMode=GenSync ;Trigger on Gen Sync Ctrl0="<S(40,20000)" ;F1 freq range Ctrl1="<R" ;F2 display is Read-Only Ctrl2="<R" ;Ratio is Read-Only Ctrl3="<S(0,10)" ;TC Exponent range Ctrl3="<p(0)" ;Integer display Ctrl0=60 ;SMPTE default F1 Ctrl1=7000 ;SMPTE default F2 Ctrl2=4 ;SMPTE default ratio Ctrl3=5 ;Time Constant Exp. default QT=32 ;TC default (2^Ctrl3) UK=1 ;Reset TC on next update Btn0="<M(2)" ;Momentary, 0-2 posns Btn1="<T" ;Toggle Btn2="<M" ;Momentary Btn3="<M" Btn4="<M" Btn5="<T" Btn0=0 ;SMPTE default U0=0 Btn1=1 ;Arb (non-Line) freq default Btn2=0 ;Line In default Btn3=0 ;Raw (non-avg) default U3=0 Btn5=0 ;Percent default U5=0 Mtr0="<<IMD Meter - SMPTE" ;Meter title Mtr0="<C(0)" ;Black meter text Mtr0="<B(hFFFFFF)" ;White meter background Mtr0="<H4901" ;Right-click opens this Help Task="_IMD_Task" ;Install task that does the work @_IMD_Ctrls=Ctrls ;Open Custom Controls dialog ;Mtr0= ;Uncomment for Mtr0 close ;Task="-_IMD_Task" ; on Ctrls close ;Avg=0 ;TrigMode=UT
;<Help=H4901 IF.Ctrls=0 ;F1 Frequency change IF.Btn1=0 ;Spectral Line Lock? IF.Ctrl0?u=!0 ;Inc/Decrement? L.0.ToneFreq=>Ctrl0?u ;Add/sub Line step so ELSE. L.0.ToneFreq=Ctrl0 ;Else line-limited direct ENDIF. ELSE. L.0.ToneFreq=Ctrl0 ;Arb freq = direct set ENDIF. Ctrl0=L.0.ToneFreq ;Show (limited) Ctrl0 value IF.Btn0=2 ;CCIF mode? L.1.ToneFreq=L.0.ToneFreq + 1000 ;F2 = F1 + 1000 if so Ctrl1=L.1.ToneFreq ;Show Ctrl1 value ENDIF. IF.U3=1 ;Spectrum avg active? Avg=1 ;Restart on change if so ENDIF. IF.U3=2 ;Waveform avg active? IF.Btn0=2 ;If so, is it CCIF mode? Avg=1 ;Restart avg if so ELSE. U3=0 ;Else quit avg Btn3="Raw" Avg=0 ENDIF. ENDIF. UK=10 ;Reset TC on 10th update ENDIF. IF.Ctrls=3 ;Ctrl3 = Time Constant Exp. Q3=Ctrl3 ;Integer Ctrl3 Ctrl3=Q3 ;Force Ctrl3 to integer QT=2^Q3 ;Actual TC = 2^Ctrl3 ENDIF. IF.Ctrls=4 ;Btn0 = IMD mode U0=Btn0 IF.U0=0 Mtr0= ;Resize Mtr0 after larger CCIF Btn0="SMPTE" Mtr0="<<IMD Meter - SMPTE" L.1.ToneFreq=7000 ;F2 IF.Btn1=1 ;Arbitrary freq mode? L.0.ToneFreq=60 ;F1 L.2.ToneFreq=20 ;Sync for wave avg ELSE. ;Else Spectral Line Lock L.0.ToneFreq=93.75 ;Closest line L.2.ToneFreq=SmplRate?X / 1024 ;Sync to line ENDIF. L.2.ToneSync=1 ;Trigger sync to L.2. L.0.Level=80 L.1.Level=20 ENDIF. IF.U0=1 Btn0="DIN" Mtr0="<<IMD Meter - DIN" L.0.ToneFreq=250 ;F1 L.1.ToneFreq=8000 ;F2 IF.Btn1=1 ;Arb freq mode? L.0.ToneSync=1 ;Sync to F1 if so ELSE. ;Else sync to spectral line L.2.ToneFreq=SmplRate?X / 1024 L.2.ToneSync=1 ENDIF. L.0.Level=80 L.1.Level=20 ENDIF. IF.U0=2 Btn0="CCIF / ITU-R" Mtr0="<<IMD Meter - CCIF / ITU-R" L.0.ToneFreq=19000 ;F1 L.1.ToneFreq=20000 ;F2 IF.Btn1=1 ;Arb freq mode? L.2.ToneFreq=L.1.ToneFreq - L.0.ToneFreq ;Sync = diff ELSE. L.2.ToneFreq=SmplRate?X / 1024 ENDIF. L.2.ToneSync=1 L.0.Level=50 L.1.Level=50 ENDIF. Ctrl0=L.0.ToneFreq ;Update F1 control Ctrl1=L.1.ToneFreq ;Update F2 display Ctrl2=L.0.Level / L.1.Level ;Update ratio display IF.U3=!0 ;Either avg mode active? Avg=1 ;Restart if so ENDIF. UK=10 ;Reset TC on 10th update ENDIF. IF.Ctrls=5 ;Btn1 = Arb/Locked freq mode IF.Btn1=1 Btn1="Arbitrary Frequency" Fstep=Dir ;Allow any freq entry ELSE. Btn1="Spectral Line Lock" Fstep=Line ;Allow only Line freqs IF.Ctrl0=<93.75 ;F1 too low? Ctrl0=93.75 ;Min Line ENDIF. L.0.ToneFreq=Ctrl0 ;Set F1 from Ctrl0 Ctrl0=L.0.ToneFreq ;Set Ctrl0 from (limited) F1 L.1.ToneFreq=Ctrl1 Ctrl1=L.1.ToneFreq L.2.ToneFreq=SmplRate?X / 1024 ;Sync to line ENDIF. SpectWindOn=Btn1 ;Use Window unless Line IF.U3=!0 ;Either avg mode active? Avg=1 ;Restart if so ENDIF. UK=10 ;Reset TC on 10th update ENDIF. IF.Ctrls=6 ;Btn2 = Channel Ch=(Ch+1) & 3 ;Next chan, 0-3 only Btn2="" + Ch(c) ;Show chan UK=1 ;Reset TC on next update ENDIF. IF.Ctrls=7 ;Btn3 = Raw / Avg modes Trig=1 ;Trigger for Avg U3=U3+1 ;Next mode IF.U3=>2 ;Limit to 0-2 U3=0 ENDIF. IF.U3=2 ;Wave avg? (sync to std F1 only) IF.Btn1=1 ;If so, Line Lock? IF.Btn0=0 ;If so, SMPTE mode? IF.Ctrl0=!60 ;Std freq? U3=0 ;No avg if not ENDIF. ENDIF. IF.Btn0=1 ;DIN mode? IF.Ctrl0=!250 ;Std freq? U3=0 ;No avg if not ENDIF. ENDIF. ENDIF. ENDIF. IF.U3=0 ;Raw = no avg? Btn3="Raw" Avg=0 ENDIF. IF.U3=1 ;Spectrum average? Btn3="Spectrum Average" SpavgMode=Exp SpavgFrames=32 Avg=1 ;Start the average ENDIF. IF.U3=2 ;Wave average? Btn3="Wave Average" WavgMode=Exp WavgFrames=32 Avg=0 ;(Spect) avg off Spect=0 ;Spect display off Avg=1 ;Start Wave avg Spect=1 ;Display in Spect mode ENDIF. UK=10 ;Reset TC on 10th update ENDIF. IF.Ctrls=8 ;Btn4 = TC Reset UK=1 ;Reset on next update ENDIF. IF.Ctrls=9 ;Btn5 = Percent/dB U5=Btn5 ;Mode copy (use if Ctrls closed) IF.U5=0 Btn5="Percent" ELSE. Btn5="dB" ENDIF. ENDIF.
;<Help=H4901 X=SpectWindOn * 4 ;0 if Line Lock, 4 if Arb Y=L.0.ToneFreq * 1024 / SmplRate ;F1 line number Z=L.1.ToneFreq * 1024 / SmplRate ;F2 line number I=cint(Z) ;Integer F2 line A=Sp(Ch,I) ;Peak F2 magnitude IF.A=0 ;No F2 peak? Mtr0="No Signal" +n + Ch(c) ELSE. ;Else got signal IF.U0=2 ;CCIF mode? K=cint(Y) ;Int F1 line B=Sp(Ch,K) ;Peak F1 magnitude C=cint(Z - Y) ;F2-F1 (1 kHz) line L=sSig(C-X,C+X) ;F2-F1 energy U=0 ;Cumulative dist M=2 ;2 lines each side WHILE.M=>0 C=cint(Y - M*(Z-Y)) ;Neg side line number IF.C=>X ;Above zero? U=U + Sp(Ch,C) ;Add line magnitude ENDIF. C=cint(Z + M*(Z-Y)) ;Pos side line number IF.C=<=(511-X) ;In range? U=U + Sp(Ch,C) ;Add line magnitude ENDIF. M=M-1 ;Next side line WEND. D=100 * L / sqrt(A^2 + B^2) ;F2-F1 % of F1,F2 E=100 * U / sqrt(A^2 + B^2) ;4-term % of F1,F2 IF.D=>50 ;Noise only? Mtr0="No Signal" +n + Ch(c) ELSE. UK=UK-1 ;TC countdown after change IF.UK=0 ;Reset if 0 Q=D ;Accums = latest R=E ENDIF. Q=Q + (D - Q) / QT ;Apply TC to disp values R=R + (E - R) / QT IF.U5=0 ;Percent? Mtr0=Q(0.4) + "% IMD (f2-f1)" +n +R(0.4) +"% IMD (4 term)" +n + Ch(c) ELSE. ;Else dB D=20 * log10(Q/100) ;Convert TC value to dB IF.D=<-200 ;Limit -dB for 0 IMD D=-200 ENDIF. E=20 * log10(R/100) ;Convert TC value to dB Mtr0=D(0.2) + " dB IMD (f2-f1)" +n +E(0.2) +" dB IMD (4 term)" +n + Ch(c) ENDIF. ENDIF. ELSE. ;SMPTE or DIN mode L=sSig(I-25,I-X-1) ;Energy below F2 U=sSig(I+X+1,I+25) ;Energy above F2 D=100*(sqrt(U^2 + L^2) / A) ;Total as % of F2 IF.D=>50 ;Noise only? Mtr0="No Signal" +n + Ch(c) ELSE. UK=UK-1 ;TC countdown after change IF.UK=0 ;Reset if 0 P=D ;Accum = latest ENDIF. P=P + (D - P) / QT ;Apply TC to disp value IF.U5=0 ;Percent? Mtr0=P(0.4) + "% IMD" +n + Ch(c) ELSE. ;Else dB D=20 * log10(P/100) Mtr0=D(0.2) + " dB IMD" +n + Ch(c) ENDIF. ENDIF. ENDIF. ENDIF. IF.Mtr0?E=1 ;Meter close? Task="-_IMD_Task" ;Uninstall task Avg=0 ;Average off TrigMode=UT ;Restore Trigger mode ENDIF.
See also Macro Examples and Mini-Apps
Questions? Comments? Contact us!We respond to ALL inquiries, typically within 24 hrs.
Over 35 Years of Innovative Instrumentation
© Copyright 2007 - 2023 by Interstellar Research
All rights reserved