title: Am I correctly implementing this basic low pass filter (Phrogz's filter!) in Java?
body: <p>I have a basic wave generator in java but I need something to remove the clicks I get from when the amplitude of a wave changes sharply. Namely when I start/stop playing a wave, especially if I have a beeping tone.</p>
  
  <p><a href="https://stackoverflow.com/questions/4026648/how-to-implement-low-pass-filter-using-java">Phrogz's answer on SO</a> gave a really nice and simple function, but I'm not sure I'm implementing it right.</p>
  
  <p>When I first tried to use it, I couldn't get it to work, but then I seem to remember it working very well... I have since fiddled about a lot with my code and now it doesn't seem to be working very well again.</p>
  
  <p>So here's the closest I could get to an SSCCE:</p>
  
  <p>If you play this you will notice that when the filtering is on (filter = true) the wave is much quieter and the clicks slightly less, but this seems mainly due to the decrease in volume. There is still a noticeable "hit" on each beep, that I don't want, and I don't remember being there before...</p>
  
  <pre><code>import javax.sound.sampled.*;
  
  
  public class Oscillator{
  
      private static int SAMPLE_RATE = 22050;
      private static short MAX_AMPLITUDE = Short.MAX_VALUE;   
      private static AudioFormat af = null;
      private static SourceDataLine line = null;
      private int frequency = 440; //Hz
      private int numLoops = 1000;
      private int beep = 100;
  
      // set to true to apply low-pass filter
      private boolean  filter = true;
      // set the amount of "smoothing" here
      private int smoothing = 100;
      private double oldValue;
  
      public Oscillator(){
  
          prepareLine();
  
      }
  
  
      public static void main(String[] args) {
          System.out.println("Playing oscillator");
          Oscillator osc = new Oscillator();
          osc.play();
      }
  
  
      private void prepareLine(){
  
  
          af =  new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, SAMPLE_RATE, 16, 2, 4, SAMPLE_RATE, false);
  
          try {
  
              DataLine.Info info = new DataLine.Info(SourceDataLine.class, af);
  
              if (!AudioSystem.isLineSupported(info)) {
                  System.out.println("Line does not support: " + af);
                  System.exit(0);
              }
              line = (SourceDataLine) AudioSystem.getLine(info);
              line.open(af);
          }
          catch (Exception e) { 
              System.out.println(e.getMessage());
              System.exit(0);
          }
      }
  
      private void play() {
  
          System.out.println("play");
  
           int maxSize = (int) Math.round( (SAMPLE_RATE * af.getFrameSize())/ frequency );  
           byte[] samples = new byte[maxSize];
  
           line.start();
  
           double volume = 1;
  
           int count = 0;
           for (int i = 0; i &lt; numLoops; i ++){
  
  
               if (count == beep) {
                   if(volume==1) volume = 0;
                   else volume = 1;
                   count = 0;
               }
  
               count ++;
  
               playWave(frequency, volume, samples);
  
  
           }
  
           line.drain();
           line.stop();
           line.close();
           System.exit(0);
      }  
  
      private void playWave(int frequency, double volLevel, byte[] samples) {
  
           double amplitude = volLevel * MAX_AMPLITUDE;
  
           int numSamplesInWave = (int) Math.round( ((double) SAMPLE_RATE)/frequency );
  
           int index = 0;
  
           for (int i = 0; i &lt; numSamplesInWave; i++) {
  
               double theta = (double)i/numSamplesInWave;
  
               double wave = getWave(theta);
  
               int sample = (int) (wave * amplitude);
  
  
               if (filter) sample = applyLowPassFilter(sample);
  
  
  
               // left sample
               samples[index + 0] = (byte) (sample &amp; 0xFF);        
               samples[index + 1] = (byte) ((sample &gt;&gt; 8) &amp; 0xFF); 
               // right sample
               samples[index + 2] = (byte) (sample &amp; 0xFF);
               samples[index + 3] = (byte) ((sample &gt;&gt; 8) &amp; 0xFF);
               index += 4;
           }
  
           int offset = 0;
  
           while (offset &lt; index){
               double increment =line.write(samples, offset, index-offset);
               offset += increment;
           }
      }
  
      private double getWave(double theta){
  
          double value = 0;
  
          theta = theta * 2 * Math.PI;
  
          value = getSin(theta);
          //value = getSqr(theta);
  
          return value;
  
      }
  
      private double getSin(double theta){
          return Math.sin(theta);
      }
  
      private int getSqr(double theta){
          if (theta &lt;= Math.PI) return 1;
          else return 0;
      }
  
      // implementation of basic low-pass filter
      private int applyLowPassFilter(int sample){
  
          int newValue = sample;
          double filteredValue = oldValue + (newValue - oldValue) / smoothing;
  
          oldValue = filteredValue;
          return (int) filteredValue;
      }
  }
  </code></pre>
  
  <p>The relevant method is at the end. If anyone does test this, please be careful of the volume if you have headphones!</p>
  
  <p>So either:</p>
  
  <ol>
  <li>It is working and I'm just expecting too much of such a simple implementation</li>
  <li>I'm doing something wrong, stupid and obvious...</li>
  </ol>
  
  <p>If it's just 1. How should/could I get rid of that harsh beat/hit/click from sudden amplitude changes?</p>
  
  <p>If it's 2. good, should be a v short answer for a too long question.</p>