Data AcQuisition And Real-Time AnalysisScope - Spectrum - Spectrogram - Signal Generator
Software for Windows
Science with your Sound Card!
Contact us about
Sound Card THD Meter Mini-App
Note: Before using this automated THD meter, you may want to review the fundamentals of distortion measurement.
THD_Meter is a macro mini-app included with Daqarta that provides a resizeable meter showing Total Harmonic Distortion. It can generate a test signal and analyze the distortion of amplifiers, speakers, microphones, or other systems. It can also be used without the signal generator to analyze the distortion of external oscillators or similar signals.
THD_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 THD_Meter macro sets Spectrum display mode and loads the THDmeter.GEN Generator setup. It also opens a Custom Controls dialog with an edit/slider control to set the Fundamental (test) frequency, a Max Harmonic control, an adjustable time constant for the meter, an Internal/ External Source button, 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.
THD_Meter was used for the THD+N and THD 25 measurements under the Harmonic Distortion section of Sound Card Performance Tests.
The meter itself is a separate Custom Meter that shows both THD+N (Total Harmonic Distortion plus noise) and THD, as well as the selected channel. If that channel is not active, the meter shows "No Signal" plus the channel. Note that THD_Meter does not automatically toggle Input on (nor set Input Channels, Lines, or Levels), so the default Left In channel may show "No Signal" unless you do that manually.
In either Internal or External Source modes, 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.)
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 will distort when driven at high levels.
When you measure the distortion of any device or system, the operating level is an important parameter. With most amplifiers, the distortion increases gently with level until there is a dramatic increase near clipping. But at low levels the situation is reversed due to the presence of crossover distortion. As the waveform passes through zero and the amp switches between "push" and "pull" circuitry, there is a glitch in the waveform. It's roughly the same size at all levels, so it's a bigger percentage of a smaller waveform.
The meter continues to run after closing the control dialog, until it its closed separately.
When you close the THD Meter Controls and THD Meter windows, the THDmeter.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.)
THD+N is computed by integrating the energy of the spectrum at all frequencies higher than the fundamental, plus all frequencies below the fundamental (except DC), and dividing that by the energy at the fundamental. The sSig() (Spectrum Sigma) function is used to integrate energies.
THD is computed by including only frequencies that are integer multiples of the fundamental, then dividing by the energy at the fundamental. For both THD+N and THD the measurement is limited to frequencies below the Nyquist frequency, which is 24000 Hz (half the sample rate).
The Max Harmonic control allows you to restrict the harmonics included in the THD measurement. (It has no effect on THD+N.) You might want to use this to compare with discrete measurements of the first few harmonics, for example. (See Sound Card Performance Tests.)
The default setting is 25, but frequencies are also restricted to less than 24000 Hz. In the default Spectral Lime Lock mode, the default fundamental is 984.375 Hz (nearest spectral line to 1000), so the actual maximum harmonic would be 24, or 23625 Hz.
Note that distortion measurements do not require any system calibration, since they are always measured as a percentage of the fundamental amplitude.
By default the controls start with the frequency mode set to Spectral Line Lock. This causes the test frequency to move only to frequencies that fall exactly on spectral lines, so no window function is needed. This gives a greatly improved noise floor and hence better resolution of low THD levels. If you toggle it to Arbitrary, a Blackman-Harris window is automatically used.
For comparison, toggle the channel from Left 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. The default fundamental is 984.375 Hz, the nearest spectral line to the standard 1000 Hz test frequency.
With Spectral Line Lock active, THD+N reads 0.0012% and THD alone reads 0.0002%. Toggling to Arbitrary Frequency and setting Fundamental to 1000 Hz causes those readings to jump to 0.1335% and 0.0180%, respectively. Those are the lowest readings you could get, assuming perfect D/A and A/D and device under test. So, unless you absolutely must use 1000 Hz or another specified frequency, use the closest Line Lock frequency instead.
To measure the THD of an external oscillator, toggle the Internal Source button to External Source. In this mode the Generator is toggled off and the Fundamental control is disabled, along with the frequency mode and Raw / Average buttons. Spectrum Cursor Peak and Track modes are enabled so Daqarta can automatically find the oscillator fundamental. Since that won't be locked to a spectrum line, a Blackman-Harris window function is used.
For noisy signals, the Time Constant Exponent control provides 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, including the test frequency, Max Harmonics, channel, or Internal/External, Arbitrary/Locked, or Raw/Average modes.
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.
Clicking the Raw button once toggles Spectrum Average. This activates a continuous Exponential average with a 32-frame time-constant. The averaged spectrum shows the same fundamental and harmonic peaks, but with an averaged noise floor that reduces the jumpiness of the meter readouts while still showing the same average values.
A second click toggles Waveform Average, likewise a continuous Exponential average with a 32-frame time-constant. But unlike spectrum averaging, waveform averaging actually reduces the noise floor... here by a factor of 32, or 15 dB. Although this means the THD+N values are no longer correct (due to the noise reduction), this does allow reading correct THD values in the presence of noise that might otherwise mask a low THD system.
The overall THD_Meter mini-app actually consists of the initial THD_Meter macro which launches both the Custom Controls dialog handler _THD_Ctrls, and also the Custom Meter handler _THD_Task. _THD_Ctrls invokes another macro called _THD_Freq to handle fundamental frequency changes.
;<Help=H4900 Close= ;Close any open data file Task="-_THD_Task" ;Uninstall task, if present Spect=1 Ylog=1 TrackThresh=-20 ;Peak Track details TrackMin=200 ; for External Source TrackMax=10000 TrackFund=0 SpectWind=BkHr ;Window for Arbitrary Freq SpectWindOn=0 SmplRate=48000 UI=Input ;Save current Input state A.LoadGEN="THDmeter" ;Load Gen setup Input=UI ;Restore initial Input state Ctrls="<<THD Meter Controls" ;Custom Controls title Ctrl0="<<Fundamental Frequency" ;Ctrl0 label Ctrl1="<<Max Harmonic" Ctrl3="<<Time Constant Exponent" Btn0="Internal Source" Btn1="Spectral Line Lock" Ch=0 Btn2=""+Ch(c) Avg=0 ;Start with Average off Btn3="Raw" ;Non-Avg Btn4="TC Reset" Btn5="Percent" UT=TrigMode ;Save trigger mode for exit TrigMode=GenSync ;Trigger on Gen Sync Ctrl0="<S(20,10000)" ;Fund freq range Ctrl1="<S(2,25)" ;Max harmonics to include Ctrl1="<p(0)" ;Integer display Ctrl2="<X" ;No Ctrl2 Ctrl3="<S(0,10)" ;TC Exponent range Ctrl3="<p(0)" ;Integer display Ctrl0=984.375 ;Fund freq default Ctrl1=25 ;Include up to 25 harmonics UN=Ctrl1 Ctrl3=5 ;Time Constant Exp. default QT=32 ;TC default (2^Ctrl3) UK=1 ;Reset TC on next update Btn0="<T" ;Btn0 = Toggle type Btn1="<T" Btn2="<M" ;Momentary Btn3="<M(2)" ;Momentary, posns 0-2 Btn4="<M" Btn5="<T" Btn0=0 ;Internal source default Btn1=0 ;Line Lock default Btn2=0 ;Left In default chan Btn3=0 ;Raw (non-Avg) default U3=0 Btn5=0 ;Percent default U5=0 Mtr0="<<THD Meter" ;Meter title Mtr0="<C(0)" ;Black meter text Mtr0="<B(hFFFFFF)" ;White meter background Mtr0="<H4900" ;Right-click opens this Help Task="_THD_Task" ;Install task that does the work @_THD_Ctrls=Ctrls ;Open Custom Controls dialog ;Mtr0= ;Uncomment for Mtr0 close ;Task="-_THD_Task" ; on Ctrls close ;Avg=0 ;TrigMode=UT
;<Help=H4900 IF.Ctrls=0 ;Ctrl0 = Freq change? @_THD_Freq ;Use separate macro ENDIF. IF.Ctrls=1 ;Ctrl1 = Max Harmonics? UN=Ctrl1 ;Get integer Ctrl1=UN ;Show integer UK=1 ;Reset TC next update ENDIF. IF.Ctrls=3 ;Ctrl3 = TC Exponent? Q3=Ctrl3 ;Get integer Ctrl3=Q3 ;Show integer QT=2^Q3 ;TC = 2^Ctrl3 ENDIF. IF.Ctrls=4 ;Btn0 = Int/Ext Source? IF.Btn0=1 ;External? Btn0="External Source" Ctrl0="<D" ;Disable Freq Btn1="<D" ;Disable Arb/Line Lock IF.U3=2 ;Wave avg running? U3=0 ;Switch to Raw if so Btn3="Raw" Avg=0 ;Avg off ENDIF. IF.U3=1 ;Spectrum avg running? Avg=1 ;Restart if so ENDIF. SpectWindOn=1 ;Use windowing SpectPeak=1 ;Use peak track SpectTrack=1 Gen=0 ;No Generator ELSE. ;Else Internal source Btn0="Internal Source" Ctrl0="<N" ;Re-enable Ctrl0 Freq Btn1="<N" ;Re-enable Btn1 Arb/Line Lock SpectWindOn=Btn1 ;Use Window if Arb Gen=1 ;Generator on @_THD_Freq ;Set freq ENDIF. UK=10 ;Reset TC on 10th update ENDIF. IF.Ctrls=5 ;Btn1 = Arb/Locked freq? IF.Btn1=1 ;Arb freq? Btn1="Arbitrary Frequency" Fstep=Dir ;Allow any freq entry ELSE. Btn1="Spectral Line Lock" Fstep=Line ;Allow only Line steps ENDIF. SpectWindOn=Btn1 ;Use Window if Arb @_THD_Freq ;Update freq 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 ;Roll to Wave avg? IF.Btn0=1 ;Ext source? U3=0 ;Force Raw instead ENDIF. ENDIF. IF.U3=0 ;Raw? Btn3="Raw" Avg=0 ;No Average ENDIF. IF.U3=1 ;Spectrum Avg? Btn3="Spectrum Average" SpavgMode=Exp :Exponential mode SpavgFrames=32 ;32 frames Avg=1 ;Start Avg ENDIF. IF.U3=2 ;Wave Avg? Btn3="Wave Average" WavgMode=Exp ;Exonential mode WavgFrames=32 ;32 frames 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.Btn5=0 Btn5="Percent" ELSE. Btn5="dB" ENDIF. ENDIF.
;<Help=H4900 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. A=L.0.ToneFreq ;Copy freq for test IF.A=0 ;0 (after Line limit)? A=SmplRate/1024 ;Set min Line if so L.0.ToneFreq=A ENDIF. Ctrl0=A ;Show (limited) Ctrl0 freq value IF.U3=1 ;Spectrum Avg active? Avg=1 ;Restart if so ENDIF. IF.U3=2 ;Waveform avg active? Spect=0 ;Spect display off Avg=1 ;Restart Wave avg Spect=1 ;Display in Spect mode ENDIF. UK=10 ;Reset TC on 10th update
;<Help=H4900 IF.Gen=1 ;Generator on (Internal Source)? F=L.0.ToneFreq ;Fund = tone freq ELSE. F=Posn?F ;Else Fund = tracked freq ENDIF. X=SpectWindOn * 4 ;0 if Line Lock, 4 if Arb I=cint(F * 1024 / SmplRate) ;Integer spectral line A=Sp(Ch,I) ;Magnitude of fund peak IF.A=0 ;No fundamental? Mtr0="No Signal" +n + Ch(c) ELSE. L=sSig(3,I-X-1) ;Energy below fund U=sSig(I+X+1,511) ;Energy above fund D=100*(sqrt(U^2 + L^2) / A) ;Total THD+N as % of fund N=2 ;Start w. 2nd harmonic T=0 ;Total energy so far H=N * F ;Freq of 2nd harm WHILE.H=<(SmplRate/2) ;Test all freqs in range I=cint(H * 1024 / SmplRate) ;Spectral line U=Sp(Ch,I) ;Magnitude at line T=sqrt(T^2 + U^2) ;Combine w. total (RMS) N=N + 1 ;Next harmonic IF.N=>UN ;Past limit? LoopBreak=2 ;Stop if so ENDIF. H=N * F ;Else next freq WEND. H=100 * T / A ;THD as % of fund IF.(D + H)=>100 ;Err if no signal Mtr0="No Signal" +n + Ch(c) ELSE. UK=UK-1 ;TC countdown after change IF.UK=0 ;Reset at 0 Q=D ;Accums = latest R=H ENDIF. Q=Q + (D - Q) / QT ;Apply TC to display values R=R + (H - R) / QT IF.U5=0 ;Percent? Mtr0=Q(0.4) + "% THD+N" +n + R(0.4) + "% THD " +UN +n + Ch(c) ELSE. ;Else show dB D=20 * log10(Q/100) ;Convert TC accums to dB H=20 * log10(R/100) Mtr0=D(0.2) + " dB THD+N" +n + H(0.2) + " dB THD " +UN +n + Ch(c) ENDIF. ENDIF. ENDIF. IF.Mtr0?E=1 ;Meter close? Task="-_THD_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 30 Years of Innovative Instrumentation
© Copyright 2007 - 2020 by Interstellar Research
All rights reserved