Pages: [1]   Go Down
Author Topic: "Click"-noise on note start  (Read 2137 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
i created a basic wavetable synthesizer that gets it's input over midi and outputs through a single PWM pin.
I have a problem now:
Everytime a note starts to play, i hear a "click"-noise. However this only happens when there is a pause between the new an the old note. If two notes are exactly aligned behind each other in the midi, there is no click. So i guess the "click" thing has something to do with the PWM going "LOW" in the pause between two notes.
But then again, if there are 2 or more notes playing at the same time (i.e. bassline and strings) and there is a pause in for example the bassline channel, the click also appears ...so the PWM-pin-going-low-thing might not be it after all.

Here's the relevant code
Code:
static int32_t sum;
  for(int i = 0; i < NUM_CHANNELS; i++)
  {
 
    channel[i].phase += channel[i].speed; //increase phase by note frequency
    //if(channel[i].phase >= 65536) channel[i].phase -= 65536;
     
    uint16_t waveTableIndex = ( channel[i].phase >> 8 ); //get wavetable index
    sum += ( wavetable[3][waveTableIndex] * channel[i].volume * channel[i].volumeMax ); //get sample, apply ADSR and master volume
  }
 
  //get rid of that "click" on note start and end...WHY DOES THIS EVEN HAPPEN!? GRRRR
  //sum = syn_iSmooth32(audioBuffer, sum, 0.925f); //results in a pseudo low pass....meh
  //audioBuffer = sum;
 
  sum >>= 8;
  OC1RS = sum;

wavetable
Code:
uint8_t wavetable[4][256] = {
  { //square
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, //32
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, //32
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, //64
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, //64
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, //32
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, //32
  },
  {}, //sawtooth
  {},//triangle
  { //sine
    127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,
    176,179,182,184,187,190,193,195,198,200,203,205,208,210,213,215,
    217,219,221,224,226,228,229,231,233,235,236,238,239,241,242,244,
    245,246,247,248,249,250,251,251,252,253,253,254,254,254,254,254,
    255,254,254,254,254,254,253,253,252,251,251,250,249,248,247,246,
    245,244,242,241,239,238,236,235,233,231,229,228,226,224,221,219,
    217,215,213,210,208,205,203,200,198,195,193,190,187,184,182,179,
    176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,
    127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,
    78,75,72,70,67,64,61,59,56,54,51,49,46,44,41,39,
    37,35,33,30,28,26,25,23,21,19,18,16,15,13,12,10,
    9,8,7,6,5,4,3,3,2,1,1,0,0,0,0,0,
    0,0,0,0,0,0,1,1,2,3,3,4,5,6,7,8,
    9,10,12,13,15,16,18,19,21,23,25,26,28,30,33,35,
    37,39,41,44,46,49,51,54,56,59,61,64,67,70,72,75,
    78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124
  }
};


void wavetable_generateSawtooth(int inTable)
{
  for (int i = 0; i < 256; ++i) {
    wavetable[inTable][i] = i; // sawtooth
  }
}

void wavetable_generateInverseSawtooth(int inTable)
{
  for (int i = 0; i < 256; ++i) {
    wavetable[inTable][i] = 255-i; // sawtooth
  }
}
 
void wavetable_generateTriangle(int inTable)
{
  for (int i = 0; i < 128; ++i) {
    wavetable[inTable][i] = i * 2;
  }
  int value = 255;
  for (int i = 128; i < 256; ++i) {
    wavetable[inTable][i] = value;
    value -= 2;
  }
}

void SetupWavetable()
{
  wavetable_generateSawtooth(1);
  wavetable_generateTriangle(2);
}


Anyone here who had similar problems when playing a tone via pwm?
This i really driving me nuts.  smiley-wink
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 27425
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I have a sort-of similar problem - I use Tone to make a little warble, sort of sounds like a cell phone ring.
Imagine dee-dle-dee-dle-dee-dle-dee-dle-deeee - and this afwul farty kind of noise as it turns off. I have 5 boxes - 4 smaller, 1 larger. All the same circuit, output pin driving a mosfet then the speaker. Only the larger box makes the noise. Nothing I've tried stops it. And nice & loud too as the MOSFET switches ~ 3W across the speaker (12V source thru a 34 ohm resistor into capacitor coupled 4 ohm speaker).

We just laugh about it now, especially when people hear it.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 639
Posts: 34725
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The click noise is the DC shift from nothing to the mid point that represents a zero audio signal. The trick is to bias your output so that the undriven state of the line is a mid voltage.
Logged

Nowhere
Offline Offline
God Member
*****
Karma: 3
Posts: 852
|-\ |\|\
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Exactly. 
Looking at your code, you tried to put a simple LPF-like smoothing, which theoretically would work.  But the problem is, even if the PWM carrier ramps up to full volume, the arduino output itself is still jumping directly to 5v.

I had the same problem with my synth.  The problem could be solved by having the output centered on the middle of the output range, rather than just adding waveforms to 0.  Add a capacitor in series to nix the DC offset, and the middle PWM value will become the new "0" point.
This was actually a problem for me, because no analog LPF's can filter out all of the carrier wave.  I ended up getting a nice SPI DAC, since I use my synth for my electronic music-making, and the PWM wave, albeit inaudible, messed up recordings.
Logged

Soundcloud page: http://soundcloud.com/beefinator-2
Youtube channel: http://www.youtube.com/user/beefinator14
Old soundcloud page (ran out o

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
...
Imagine dee-dle-dee-dle-dee-dle-dee-dle-deeee - and this afwul farty kind of noise as it turns off.
...
We just laugh about it now, especially when people hear it.

If it were fart sounds i could maybe live with it as a "feature" smiley-grin But unfortunally it really does sound more like going rampage on a old TV's antenna...white noise kind of thing

Quote
Exactly.  
Looking at your code, you tried to put a simple LPF-like smoothing, which theoretically would work.  But the problem is, even if the PWM carrier ramps up to full volume, the arduino output itself is still jumping directly to 5v.

I had the same problem with my synth.  The problem could be solved by having the output centered on the middle of the output range, rather than just adding waveforms to 0.  Add a capacitor in series to nix the DC offset, and the middle PWM value will become the new "0" point.
This was actually a problem for me, because no analog LPF's can filter out all of the carrier wave.  I ended up getting a nice SPI DAC, since I use my synth for my electronic music-making, and the PWM wave, albeit inaudible, messed up recordings.

Good idea! So i would convert my wavetables from uint to int and use values between -128 and 128. Initial value for the pwm out would be 128. I will give it a try next week smiley
Also, which Hardware DAC are you using? I planned on using a DAC also, but never found a nice one (and no, i don't want to use a R2R ladder smiley-wink ).

In the meantime i update my Synth code a bit. I now have 16 channels with 4 voices each, giving me a total of 64 voices (i plan on adding a more intelligent channel->voice algorythm later where a channel looks for a free voice on NoteOn and simply uses it). I can also change wavetables on the fly. Next step is to add a touchpanel so i can change the ADSR curve on the fly. After that comes storing/loading the ADSR to/from SD/MMC. Can't wait to get this finished smiley
« Last Edit: June 02, 2012, 07:48:57 am by BoH_Havoc » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here's a short recording of my synthesizer in action

http://soundcloud.com/boh_havoc/bitpad-v0-3-nuvole-bianche

Still looking for a decent DAC smiley
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 639
Posts: 34725
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quite impressive.  smiley
Logged

0
Offline Offline
Shannon Member
****
Karma: 222
Posts: 12717
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The best performance and value for money for audio DAC has to be I2S delta-sigma DACs - however they are hard to drive requiring 3 related clocks and bits have to be serially fed to them at Mb/s rates.   24 bit stereo at 48kHz sample rate for under a dollar in surface mount packages (WM8759GED, WM8524GED).
The Arduino isn't really fast enough to drive such a DAC (and do anything else useful!)

Other high resolution 5V or 3V3 ADCs are usually expensive and surface mount.  LTC2642CMS is a fast SPI 16 bit DAC as an example, not very cheap, surface mount only...
Logged

[ I won't respond to messages, use the forum please ]

Nowhere
Offline Offline
God Member
*****
Karma: 3
Posts: 852
|-\ |\|\
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'd recommend the MCP4921/4922 (1 or 2 channels).

There's an SPI interface on it, so super easy to interface.  12bit audio on each channel, 2 channels if you get the 4922 chip.

And they're extremely low noise.  You just have to (as I just found out) put a very low lowpass filter on the Vref pins, not directly connect them to 5v.  I mean really low; I'm using one with a cutoff of around 0.03Hz. 
Logged

Soundcloud page: http://soundcloud.com/beefinator-2
Youtube channel: http://www.youtube.com/user/beefinator14
Old soundcloud page (ran out o

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the DAC info guys smiley

I'll go for the MCP4922 first as i can get it cheap from a local shop. I'll keep the LTC2642CMS in mind though and get myself one of these the next time i buy something at farnell.com .

In the meantime i implemented FM Synthesis in addition to wavetable synthesis. I can either use both together (choose wavetables for fm modulator and carrier) or only use wavetables like before. This can be set per Voice, so you don't have to use FM Synthesis for everything if you don't want to.
Next is adding an envelope to both the modulator volume and pitch to get more action in there (i'm currently "emulating" the envelope curves by hand smiley-wink )

I'll upload a new sample track of the FM Synthesis stuff once i have the DAC working.

Again, thanks for the help so far! smiley




[edit]
Oh well, i'm having to much fun here  smiley
So here's an example of the current status. No DAC yet.

http://soundcloud.com/boh_havoc/bitpad-v0-35-tyrian-fm-ride
« Last Edit: June 27, 2012, 08:08:58 pm by BoH_Havoc » Logged

Pages: [1]   Go Up
Jump to: