Audio signal generator: strange noise with headphones, no noise when connected to PC

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
RaAl_264636
Level 6
Level 6
50 sign-ins 25 sign-ins 10 solutions authored

Hi,

having some free days, continuing my work on an audio signal generator on a CY8CKIT-059. With help of Odissey and his components (DDS24 24-bit DDS arbitrary frequency generator component and hardware multiplier), I can output a waveform with variable amplitude. So, first many many thanks to Odissey and his valuable contributions to the community.

Now, I have some noise in output when using the headphones, but when connected to soundcard input, there's no noise. The noise sounds like some sort of ripple related to the amplitude control, but it's hard to describe. I'm not sure if it also can be some sort of overtones.

Current test setup is 1kHz sine wave, with an triangle amplitude control waveform of ~0.5Hz. Sample frequency is 512kHz. Output device is 16 Ohm headphone. Connection from two internal OpAmps (one for left & right each) to headphone is done by 100uF in series for each channel, nothing else.

To verify my output stage, I used the PSoC 5LP audio example, which makes the PSoC appear as an USB soundcard, modified the example to my output stage and played some songs. Here, the sample frequency of the device is 32kHz. Using the headphones, there's not the same noise I can hear with the PSoC generated sound. There's only some...hmm, I think it's called "pink" noise, which is what you can expect from low-cost casette playback devices from the 80's/90's So, this let me assume that my output stage is okay.

Next idea was to connect the device to the soundcard and record the input to have a test sample, showing the problem - but interestingly there's no "ripple" noise So I can't show you the problem. I've also written a small C# application, generating the same sound as described above (1kHz sine with 0.5Hz triangle amplitude) and used it with the USB soundcard application, no ripple noise, even when changing the sample rate and/or bit depth of the generated sound... I also changed the headphones, no effect.

In short:

- signal generator application & headphone: not OK

- signal generator application & soundcard: OK

- USB soundcard application & headphone: OK

So, I assume there's some sort of filtering and/or audio processing when using the soundcard, which is missing when using the headphones. How can I figure out where the error is and how to solve it?

Regards

0 Likes
1 Solution

Ralf,

Attached is a demo project showing arbitrary wave generation using equivalent time sampling (software DDS) and DMA buffering for hardware timing. This approach doesn't use UDB/PLD resources and is more flexible than hardware DDS, in expense of fully loaded CPU.

Note that in equivalent time sampling the data is sampled at fixed frequency (here is 1 MHz), irrespective to the output frequency. This allows to use fixed frequency LO-pass filter to filter out sampling steps. This is not possible with fixed length tables (such as used in WaveDac8). In result, the output sine wave can be set as close to sampling frequency, as permitted by the Nyquist limit (F_out <= 0.5 x F_sample) using high-order restoration filter (typically 5-th or 7-th order). For example, 44kHz sampling rate is sufficient to reproduce 20kHz sine output:

D/A and A/D | Digital Show and Tell (Monty Montgomery @ xiph.org) - YouTube

Two sine lookup tables are provided for demo purposes: one is 8-bit unsigned sine wave with 256-bytes entry. Another is 11-bit signed sine wave of 1024-length (slower, but more accurate). The table is folded to occupy same 256 bytes.

Attached is a demo project, WaveGen8 library and some screenshots.

/odissey1

DDS_WaveGen_02a_B.png

Figure 1. 10kHz sine output. Amplitude is ramp-modulated from 50 to 255.

DDS_WaveGen_02a_F_10kHz_Amp 50-255.png

Figure 2. 100kHz sine output. Yellow trace - unfiltered, Fuchsia - filtered using single pole RC (220 Ohm x 0.004u).

DDS_WaveGen_02a_D_10kHz.png

Figure 3a. Same as above. Yellow trace - unfiltered, Fuchsia - filtered. Blue trace - FFT of Channel 1 (unfiltered signal). Signal distortion -20dB.

DDS_WaveGen_02a_C_100kHz_CH1.png

Figure 3b. Same as above, Yellow trace - unfiltered, Fuchsia - filtered. Blue trace - FFT of Channel 2 (filtered signal). Signal distortion -35dB.

DDS_WaveGen_02a_C_100kHz_CH3.png

View solution in original post

0 Likes
14 Replies
odissey1
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted

Ralph,

The line-in input impedance is high and does not load the output Opamp. On the other side, the input impedance of the headphones is low (16 Ohm), overloading Opamp. For peak output signal of 1V, the driving current  is 62mA. This is too much for Opamp, and it is being overloaded (hence causing distortion). Check the signal on the output pin using scope with and w/o headphones. Remedies: try to add ~500 Ohm resistor in series with the phone to reduce current. Make sure that Opamp direct output pins are used. Try to put output Opamps in parallel to increase output current or simply use high impedance headphones (100-300 Ohm).

/odissey1

0 Likes

Hi Odissey,

I can make this change to verify, but I doubt it's the reason - remember, the USB soundcard with headphone doesn't have this distortion.

Regards

0 Likes

user_246598725,

I'm very confident that the USB soundcard is using an external driver circuit to drive the headphone output.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

Hi Odissey,

I've done some tests with 120R and 470R in series, the result is the same. Output pins are OpAmp output. So, I think it's not related to output current and hardware distortion.

I assume the distortion comes from my way generating the sound. Currently I'm trying to make some kind of output dithering, using the PRS component and xOR-ing the LSB of the DAC value with the PRS output. The result doesn't get better. The strange thing is that the USB soundcard application works with headphone, so I have to figure out where the differences are.

Regards

0 Likes
RaAl_264636
Level 6
Level 6
50 sign-ins 25 sign-ins 10 solutions authored

Current state:

The distortion comes from two sources:

1) changing the amplitude creates distortion depending on the amplitude value, even when changing the amplitude only when crossing the zero point of the wave

2) depending on the amplitude, the generated output has distortion

I've implemented the DAC as 11-Bit PIDAC according to AN64275, which improved the output quality. There's still distortion in the headphones, but it's lower now. The 11-Bit DAC is currently implemented with software, so next step is to modify the hardware design to work with 11-Bit DAC to free up the MCU again.

I've still to investigate the difference when using the USB soundcard project and output on 8-Bit DAC. I also came across some DDS information, where it's mentioned that the number of samples within the sine table should be greater than the DAC resolution. In my initial application, this is 8-Bit DAC and 512 samples (9-Bit), so I'll make a test with 1024 or 2048 samples to check if this would also reduce the distortion. Since the current application uses DDS24 component to generate a variable clock frequency for the amplitude modulation part, I might change the project approach to use a fixed output frequency and generate the wave based on phase accumulator - this might be the better approach, especially for higher signal frequencies. I have to figure out if this is possible with PSoC 5LP.

Regards

0 Likes

Ralph,

DDS theory predicts that optimal lookup table length equals (N+1) for DAC output width N (see Eq. 11 in the paper attached). So, for 8-bit output, the optimal table length is 512. Unfortunately, PSoC5 native VDACs are not quite 8-bit, and show a lot of distortion at higher frequencies, so a table of 256-length is probably sufficient.

I will post fixed frequency DDS example tomorrow later.

How do you scale output? Do you use my hardware multiplier? Have in mind that it works for unsigned multiplication and will cause a hard step when signal is not zero. I do have upgraded version for signed multiplication, but it is in a beta stage.

/odissey1

0 Likes

Hello Odissey,

thank you for that paper.

Yes, I'm using your multiplier. It can be used even in it's current unsigned implementation:

Input A is the signed 8-Bit value from the sine table, so the input is without DC voltage. Input B is the scale value as unsigned. The high byte of the result is used as scaled value. If the MSB of the input A value is set, indicating a negative value, the scale value is subtracted from the result high byte. The MSB of either value is flipped. This approach makes the calculation only on the AC part of the signal, takes care for idle value of mid-scale (0x80 if 8-Bit DAC is used and is equivalent to 0x00 in signal table) and converts to unsigned value.

If I remember correctly, I made a small change to your multiplier component to register both input values on trigger. In the original implementation, one of the values was not registered, therefore a change of input value during calculation would lead to a wrong result.

Regards

0 Likes

Ralf,

Attached is updated Multiplier project. It multiplies 8-bit signed sine wave centered around 128 by unsigned 8-bit multiplier. The sine wave feeds from RAM by DMA using custom "wave generator" (WaveGen8). All components are imported into the project.

This version is for multiplying N-bits by M-bits, both signed/unsigned. The component is dated and not tested well, so must be used with caution. Note that the component treats "signed" values not as "2-s compliment" but as "offset binary" (see application note attached).

/odissey1

P.S. This is not the equivalent time sampling project promised above!

Figure 1. WaveGen8 pushes sine wave from RAM into h/w bus using DMA. Bus amplitude is scaled by [0-255] using API calls. Output frequency controlled by DDS32.

RAM-Multiply-DAC_01b_A.png

Figure 2. Screenshot of signed sine modulation x[0-255u] taken using long persistence time.

RAM-Multiply-DAC_01b_B.png

Ralf,

Attached is a demo project showing arbitrary wave generation using equivalent time sampling (software DDS) and DMA buffering for hardware timing. This approach doesn't use UDB/PLD resources and is more flexible than hardware DDS, in expense of fully loaded CPU.

Note that in equivalent time sampling the data is sampled at fixed frequency (here is 1 MHz), irrespective to the output frequency. This allows to use fixed frequency LO-pass filter to filter out sampling steps. This is not possible with fixed length tables (such as used in WaveDac8). In result, the output sine wave can be set as close to sampling frequency, as permitted by the Nyquist limit (F_out <= 0.5 x F_sample) using high-order restoration filter (typically 5-th or 7-th order). For example, 44kHz sampling rate is sufficient to reproduce 20kHz sine output:

D/A and A/D | Digital Show and Tell (Monty Montgomery @ xiph.org) - YouTube

Two sine lookup tables are provided for demo purposes: one is 8-bit unsigned sine wave with 256-bytes entry. Another is 11-bit signed sine wave of 1024-length (slower, but more accurate). The table is folded to occupy same 256 bytes.

Attached is a demo project, WaveGen8 library and some screenshots.

/odissey1

DDS_WaveGen_02a_B.png

Figure 1. 10kHz sine output. Amplitude is ramp-modulated from 50 to 255.

DDS_WaveGen_02a_F_10kHz_Amp 50-255.png

Figure 2. 100kHz sine output. Yellow trace - unfiltered, Fuchsia - filtered using single pole RC (220 Ohm x 0.004u).

DDS_WaveGen_02a_D_10kHz.png

Figure 3a. Same as above. Yellow trace - unfiltered, Fuchsia - filtered. Blue trace - FFT of Channel 1 (unfiltered signal). Signal distortion -20dB.

DDS_WaveGen_02a_C_100kHz_CH1.png

Figure 3b. Same as above, Yellow trace - unfiltered, Fuchsia - filtered. Blue trace - FFT of Channel 2 (filtered signal). Signal distortion -35dB.

DDS_WaveGen_02a_C_100kHz_CH3.png

0 Likes

Hello odissey,

thank you for those two projects and the related information. Very appreciated, now I can compare with my current implementation. I'm on a business trip this week, so it might take a while.

Regards

0 Likes

Hello odissey,

sorry for the late reply. I tested your projects, especially the streamlined multiplier one. This one is comparable to my current implementation, which uses your DDS24 and unsigned multiplier components (again, thank you for providing so much components to the community).

So I want to give you an update. I adapted the project to output the same tone as my implementation:

- 1kHz sine

- triangular amplitude modulation from 0-255 @250Hz in steps of +-1

- the DAC is changed to IDAC, sinking with 2mA range

- the output stage is modified to TIA, implemented with normal OpAmp, resistor value of 240R (amplitude of ~0.5Vpp) and VDD/2 on OpAmp IN+

- this signal is fed to two OpAmps for each headphone channel, where each channel is fed through 100R and 100µF (this is my original "external" output stage)

This implementation shows also the "ringing" effect, but it seems it's a bit weaker than in my implementation. So, I'll try to figure out the differences, will keep you updated.

One thing regarding the USB audio example project: as far as I can see this example uses USB as a clock source or sync mechanism - could this be a reason why playing music from PC doesn't have those ringing effect? Or is it because the signal in my implementation always uses the full sine table rather than stepping through the table like a real DDS?

Regards

0 Likes

Ralf,

You are welcome. Can you please make some demo clarifying the "ringing" effect, something like a YouTube / Vimeo video and o-scope trace would be nice to observe. Did you try to add a XTAL or ceramic resonator as stable clock source?

/odissey1

0 Likes

Hello odissey,

I doubt that a video or something similar would be sufficient to show the ringing effect. This is because as I wrote earlier, when I try to record it by PC, the effect can not be heared. So I assume it's being filtered out when recording it to PC. I also attached a crystal to my CY8CKIT-059, but I didn't notice any positive effect.

A counter questions: how much is your effort when trying to output it to a line output stage? As we already know, the 8-bit DACs of PSoC aren't intended for high quality sound output. But from the USB soundcard example, I'd expect a "cassette playback" quality when using headphones, which is sufficient for the first try. If it's possible to extend it to use parallel IDACs to increase resolution and therefore quality, that's even better, but that would be in future extension of the project.

As I wrote above, 100R + 100µF per OpAmp output channel seems to be okay for USB soundcard example (with TIA component).

My end goal is to have an sound output with varying frequencies up to 10kHz of sine (if possible arbitrary waveform and changing waveforms "on the fly" by switching between different tables) which can be feed to an external amplifier accepting the ~0.5Vpp output (e.g. PC soundcard or audio equipment).

So, I think if you can reproduce the audio signal on headphones and also hear the ringing effect, we can both try to increase quality. Currently, I'm thinking of a component similar to your DDS24/32 implementations. It's based on UDB, where the output is 16-bit address with offset of an address of an arbitrary waveform table stored in SRAM. This address can be forwarded to a DMA component, where the first TD updates a second TD source address, and the corresponding value is fed through a multiplier component. So this is a real DDS approach. Currently I'm implementing such a component which generates those address bits. If you want, I can provide my first (but untested) implementation for the address generation component (the phase generator).

Regards

0 Likes

Ralf,

PSoC5 DACs are not of high performance (I believe they are more like 7.5-bit). I didn't evaluate their audio quality; I used it for electronic sintezator, where output signal was intentionally distorted. There are some approaches to make 9-12-bit DACs out of VDAC8 either by dithering low bit or by combining 2 VDACs, which, after much efforts, resulted in approx. 9-bit DACs - not worth the hassle.  It is possible that 16-bit PWM might be better approach for music generation, please check this website (and references within):

Dual PWM Circuits | Open Music Labs

pwm_16b_sm.jpg

And this high-speed 16-bit PWM implementation by Ganesh Raaja (the link no longer works, see article attached)

pastedImage_2.png

Unlike those "~9-bit" DACs, the PWM registers can be written by DMA directly. It is my understanding that though PWM is not amplitude-stabilized like a VDAC, but for musical tone perception the THD is more important than the absolute voltage level produced by DAC.

I would send output through Multiple Feedback 2-nd order LPF to reduce harmonics. It takes only one extra capacitor and two resistors compared to TIA circuit (2C+3R+1Opamp), but produces extra 20-db roll-off, I will post my LPF schematic later.

> Currently I'm implementing such a component which generates those address bits. If you want, I can provide my first (but untested) implementation for the address generation component (the phase generator).

-That would be nice!

/odissey1

0 Likes