This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Trying to debug a hard-clipping distortion algorithm

Other Parts Discussed in Thread: TMS320C5505

I'm working on a project where i'm going to be implementing some distortion modeling on a TMS320C5505 eZDSP. My first attempt at implementing a simple hard-clipping algorithm produced some unexpected results that i'm stumped by. I know this might be a lengthy read, but if you have the time I could really use the help. I'll layout the process of exactly how i've attempted to do some debugging.

First, i connected my laptop (headphone out) to another laptop (mic in) and passed a 440 Hz sine wave (generated in Audacity) from the first laptop to the second and no irregularities or additional harmonics in the recorded signal's spectrum could be seen, sans a minor dB difference level. I repeated this process using white noise and the results were the same (no irregularities).

Next, i repeated the exact same process, but this time i ran the laptop headphone out into the DSP's analog input and the DSP's headphone out to the other laptop's input and recorded the same 440 Hz and whitenoise signals. I used the stock Audio Filter Demo and I modified the timer to just keep the filter off for the entire duration. So, the FIR Filter was bypassed for these tests and the input signal passed completely through the DSP without any alterations. The results were the same as in the first procedure.

Then, with the both laptops still connected to the DSP, I turned the hard-clipping algorithm to be implemented on the DSP on. Here is that exact section of code that was implemented:

void distalgo(Int16 *input, Int16 *output, Int16 size)
{
    Int16 i;
    Int16 threshp = 600; // Threshold for Hard-Clipping
    Int16 threshn = -600; // Threshold for Hard-Clipping   
   
    for(i =0; i<size; i++)
    {
        if(*(input+i) >= threshp){
            *(output+i) = threshp;   
        }
       
        else if(*(input+i) <= threshn){
            *(output+i) = threshn;   
        }
        else {
            *(output + i) = *(input +i);   
        }
           
    }
   
}

This code is implemented when the filterON variable is set to 1 (in place of the FIR Filter) and i followed a similar implementation as the buff_copy function that just passes the data in and out without alteration.


I passed the 440 Hz signal through this algorithm and the I/O waveforms can be seen in the attached figure iocomp.png.

On a closer inspection, iozoom.png, you can see that the input waveform is not being completely limited to the threshold of 600 (Green line) and -600 (blue line), but closer to 800 and -800. It also appears to have some oscillations or noise mixed in because it isn't completely being hard-clipped.

I also passed that same input data through the same algorithm, but in MATLAB and the resulting output can be seen in the figure comp3.png. This shows what the the DSP should have done.


I also passed each of those signals (440 Hz input, DSP Hard-Clipped output, and matlab clipped output) through an averaged FFT tool. Here are the resulting spectrums:



The input spectrum is a fairly clean representation of the 440 Hz sine. The DSP output spectrum (440out) is showing odd harmonics AND even harmonics, even though the even harmonics are almost 30 dB less than the fundamental and neighboring odd harmonics. This clipped waveform should only be generating odd harmonics, which can be seen, as verification, in the MATLAB440 spectrum.

So, like i said, i'm kind of stumped. I have a feeling that it has something to do with the way i'm calling or implementing the algorithm on the DSP, but i'm not sure what part of it could be causing this.

If you have any suggestions i'd love to hear them.
Thanks for reading!

  • I'm not sure if you are looking for the problem at the right spot.

    In principle you have a system that consist of a chain of:

    1. AC97 compatible Windows driver/codec combo
    2. Sigma-Delta DAC in your laptop #1
    3. Output amp of your laptop #1
    4. Input amp/ of your EzUSB Module's codec
    5. ADC in said codec
    6. [filter]
    7. DAC in that codec
    8. output amp of that codec
    9. input amp of your laptop #2
    10. ADC in that laptop #2.

    Now, don't get me wrong, for on-board sound laptop soundcards are perfectly okay, but they are far from being low-noise low-distortion. If you consider, that - by datasheet - the EzUSB ADC-DAC-pass-through fed with pure clean sine wave produces 2nd harmonic at -75dB (and I bet that TI measured this in lab conditions, so in a real application this figure will get worse), you should be prepared to see some distortion besides what was intended by your filter.

    Next thing is, that while 440Hz test singal is of rather limited bandwidth, clipped 440Hz signal isn't. While matlab will happily plot sharp corners in the clipped sinus, they have little chance of coming like that through the low-pass on DAC output. Wait... EzUSB doesn't have an LP. But your lap#2 input will. So there could be some Gibbs' effect present on the output, but filtered down on the input...

    All this said, I'm not surprised by the noise you see around the clipped sinus plateaus. It seems excessive, but try recording silence passed through from laptop #1 thru EzUSB to laptop #2 and see, what the actual noise floor is. Don't believe datasheet 90dB SNR - that's like cheap muscle car's 250PS - in theory you have it, but seldom you will see it in real life.

    Marek

  • Interesting information Marek. Thank you very much for sharing :)

    I tried to run some simple noise-floor tests like you mentioned and here are my results.

    First image: laptop #1 with output volume set to 0.9, running silence into the eZDSP (no filter at all, just bypassed), headphone out of eZDSP into laptop #2 with receive volume set to 0.1.
    The noise floor seems pretty low. I kept seeing a higher dB "fundamental" at 100 Hz and then, depending on the receive volume of laptop #2, various number of harmonics of 100 Hz.

     

    Next image: same laptop/eZDSP/laptop connection but this time with a test 440 Hz signal (0.1 amplitude in Audacity), send volume on laptop #1 at 0.9 and receive volume on laptop #2 set to 0.1. The DSP is still set to bypass mode. You can see the 100 Hz fundamental and the various harmonics i mentioned above, even though they all reside around ~ -80 dB.

     

    Final image: same laptop/eZDSP/laptop connection but this time with a test 440 Hz signal (0.1 amplitude in Audacity), send volume on laptop #1 at 0.9 and receive volume on laptop #2 set to 0.1 and the DSP "hard-clipping" filter is turned on. You can see the fundamental 440 @ about -50 dB and the third harmonic around -70 dB, and the ever-so faint 2nd harmonic down around -84 dB. 


    Does this look abnormal at all? I would expect to not even see the 2nd harmonic at all, but i'm new to implementing code on DSPs, so i appreciate any insight.

    I just found it strange that in the one image in my last post, where i had set the thresholds to +- 600, but you could clearly see the value was clipped at more like +- 800. Any reason for that?

    Thank you!

  • 100Hz is - assuming you are in Europe - the frequency of rectified power grid voltage. At which point does it get coupled is hard to say. You can try running both laptops on batteries with no cables (besides the audio connection) attached and see if it goes away.

    Now, as to your second harmonic frequency: chances are more than average, that at least one (if not all) amplifiers involved uses simple MOSFET power stage, i.e. not a CMOS high-gain strong-feedback op-amp, but something more along the lines of a push-pull follower. I'd suspect either the headphone amp of your first laptop or the headphone amp of your DSP. Thing is, for a mosfet Id ~ (Ug-Ut)², and even though a moderate feedback will linearize it by far, there will be a component of Ug² in the output present. As you know, (cos² i) = 0.5 + 0.5·cos(2i), so feeding 440Hz in you will get 440Hz out (thanks to feedback loop) plus 880Hz (thanks to mosfet intrisinc characteristics).

    However, you should be able to observe this effect already on clean 440Hz output, without clipping, and this you don't. It could be, that imperfections of the amplifiers show first when fed with a distorted signal.

    As to why samples clipped to 600 read as 800 after next DAC/ADC step - how can you assume unity gain and 1:1 amplitude mapping here? Have you actually calibrated the channel?

    Marek