Program: 54999
Project: 54999
Buggy source:
/** 
 * Will (re-)draw the given data set on the surface. Note that it actually only draws a sub set of the fft data depending on the current settings of virtual frequency and sample rate.
 * @param mag			array of magnitude values that represent the fft
 * @param frequency		center frequency
 * @param sampleRate	sample rate
 * @param frameRate 	current frame rate (FPS)
 * @param load			current load (percentage [0..1])
 */
public void draw(double[] mag,long frequency,int sampleRate,int frameRate,double load){
  if (virtualFrequency < 0)   virtualFrequency=frequency;
  if (virtualSampleRate < 0)   virtualSampleRate=sampleRate;
  float samplesPerHz=(float)mag.length / (float)sampleRate;
  long frequencyDiff=virtualFrequency - frequency;
  int sampleRateDiff=virtualSampleRate - sampleRate;
  int start=(int)((frequencyDiff - sampleRateDiff / 2.0) * samplesPerHz);
  int end=mag.length + (int)((frequencyDiff + sampleRateDiff / 2.0) * samplesPerHz);
  if (averageLength > 0) {
    if (historySamples == null || historySamples.length != averageLength || historySamples[0].length != mag.length) {
      historySamples=new double[averageLength][mag.length];
      for (int i=0; i < averageLength; i++) {
        for (int j=0; j < mag.length; j++) {
          historySamples[i][j]=mag[j];
        }
      }
      oldesthistoryIndex=0;
    }
    if (frequency != lastFrequency || sampleRate != lastSampleRate) {
      for (int i=0; i < averageLength; i++) {
        for (int j=0; j < mag.length; j++) {
          historySamples[i][j]=mag[j];
        }
      }
    }
    double tmp;
    for (int i=0; i < mag.length; i++) {
      tmp=mag[i];
      for (int j=0; j < historySamples.length; j++)       tmp+=historySamples[j][i];
      historySamples[oldesthistoryIndex][i]=mag[i];
      mag[i]=tmp / (historySamples.length + 1);
    }
    oldesthistoryIndex=(oldesthistoryIndex + 1) % historySamples.length;
  }
  if (doAutoscaleInNextDraw) {
    doAutoscaleInNextDraw=false;
    float min=MAX_DB;
    float max=MIN_DB;
    for (int i=Math.max(0,start); i < Math.min(mag.length,end); i++) {
      if (i == (mag.length / 2) - 5)       i+=10;
      min=Math.min((float)mag[i],min);
      max=Math.max((float)mag[i],max);
    }
    if (min < max) {
      minDB=Math.max(min,MIN_DB);
      maxDB=Math.min(max,MAX_DB);
    }
  }
  if (peakHoldEnabled) {
    if (peaks == null || peaks.length != mag.length) {
      peaks=new double[mag.length];
      for (int i=0; i < peaks.length; i++)       peaks[i]=-999999F;
    }
    if (frequency != lastFrequency || sampleRate != lastSampleRate) {
      for (int i=0; i < peaks.length; i++)       peaks[i]=-999999F;
    }
    for (int i=0; i < mag.length; i++)     peaks[i]=Math.max(peaks[i],mag[i]);
  }
 else {
    peaks=null;
  }
  Canvas c=null;
  try {
    c=this.getHolder().lockCanvas();
synchronized (this.getHolder()) {
      if (c != null) {
        drawFFT(c,mag,start,end);
        drawWaterfall(c);
        drawFrequencyGrid(c);
        drawPowerGrid(c);
        drawPerformanceInfo(c,frameRate,load);
      }
 else       Log.d(LOGTAG,"String_Node_Str");
    }
  }
 catch (  Exception e) {
    Log.e(LOGTAG,"String_Node_Str");
    e.printStackTrace();
  }
 finally {
    if (c != null) {
      this.getHolder().unlockCanvasAndPost(c);
    }
  }
  this.lastFrequency=frequency;
  this.lastSampleRate=sampleRate;
}

Fixed version (ground truth):
/** 
 * Will (re-)draw the given data set on the surface. Note that it actually only draws a sub set of the fft data depending on the current settings of virtual frequency and sample rate.
 * @param mag			array of magnitude values that represent the fft
 * @param frequency		center frequency
 * @param sampleRate	sample rate
 * @param frameRate 	current frame rate (FPS)
 * @param load			current load (percentage [0..1])
 */
public void draw(double[] mag,long frequency,int sampleRate,int frameRate,double load){
  if (virtualFrequency < 0)   virtualFrequency=frequency;
  if (virtualSampleRate < 0)   virtualSampleRate=sampleRate;
  float samplesPerHz=(float)mag.length / (float)sampleRate;
  long frequencyDiff=virtualFrequency - frequency;
  int sampleRateDiff=virtualSampleRate - sampleRate;
  int start=(int)((frequencyDiff - sampleRateDiff / 2.0) * samplesPerHz);
  int end=mag.length + (int)((frequencyDiff + sampleRateDiff / 2.0) * samplesPerHz);
  if (averageLength > 0) {
    if (historySamples == null || historySamples.length != averageLength || historySamples[0].length != mag.length) {
      historySamples=new double[averageLength][mag.length];
      for (int i=0; i < averageLength; i++) {
        for (int j=0; j < mag.length; j++) {
          historySamples[i][j]=mag[j];
        }
      }
      oldesthistoryIndex=0;
    }
    if (frequency != lastFrequency || sampleRate != lastSampleRate) {
      for (int i=0; i < averageLength; i++) {
        for (int j=0; j < mag.length; j++) {
          historySamples[i][j]=mag[j];
        }
      }
    }
    double tmp;
    for (int i=0; i < mag.length; i++) {
      tmp=mag[i];
      for (int j=0; j < historySamples.length; j++)       tmp+=historySamples[j][i];
      historySamples[oldesthistoryIndex][i]=mag[i];
      mag[i]=tmp / (historySamples.length + 1);
    }
    oldesthistoryIndex=(oldesthistoryIndex + 1) % historySamples.length;
  }
  if (doAutoscaleInNextDraw) {
    doAutoscaleInNextDraw=false;
    float min=MAX_DB;
    float max=MIN_DB;
    for (int i=Math.max(0,start); i < Math.min(mag.length,end); i++) {
      if (i == (mag.length / 2) - 5)       i+=10;
      min=Math.min((float)mag[i],min);
      max=Math.max((float)mag[i],max);
    }
    if (min < max) {
      minDB=Math.max(min,MIN_DB);
      maxDB=Math.min(max,MAX_DB);
    }
  }
  if (peakHoldEnabled) {
    if (peaks == null || peaks.length != mag.length) {
      peaks=new double[mag.length];
      for (int i=0; i < peaks.length; i++)       peaks[i]=-999999F;
    }
    if (frequency != lastFrequency || sampleRate != lastSampleRate) {
      for (int i=0; i < peaks.length; i++)       peaks[i]=-999999F;
    }
    for (int i=0; i < mag.length; i++)     peaks[i]=Math.max(peaks[i],mag[i]);
  }
 else {
    peaks=null;
  }
  float averageSignalStrengh=-9999;
  if (demodulationEnabled) {
    float sum=0;
    int chanStart=(int)((channelFrequency - (frequency - sampleRate / 2) - channelWidth / 2) * samplesPerHz);
    int chanEnd=(int)(chanStart + channelWidth * samplesPerHz);
    if (chanStart > 0 && chanEnd <= mag.length) {
      for (int i=chanStart; i < chanEnd; i++)       sum+=mag[i];
      averageSignalStrengh=sum / (chanEnd - chanStart);
      if (averageSignalStrengh >= squelch && squelchSatisfied == false) {
        squelchSatisfied=true;
        this.squelchPaint.setColor(Color.GREEN);
        callbackHandler.onUpdateSquelchSatisfied(squelchSatisfied);
      }
 else       if (averageSignalStrengh < squelch && squelchSatisfied == true) {
        squelchSatisfied=false;
        this.squelchPaint.setColor(Color.RED);
        callbackHandler.onUpdateSquelchSatisfied(squelchSatisfied);
      }
    }
  }
  Canvas c=null;
  try {
    c=this.getHolder().lockCanvas();
synchronized (this.getHolder()) {
      if (c != null) {
        drawFFT(c,mag,start,end);
        drawWaterfall(c);
        drawFrequencyGrid(c);
        drawPowerGrid(c);
        drawPerformanceInfo(c,frameRate,load,averageSignalStrengh);
      }
 else       Log.d(LOGTAG,"String_Node_Str");
    }
  }
 catch (  Exception e) {
    Log.e(LOGTAG,"String_Node_Str");
    e.printStackTrace();
  }
 finally {
    if (c != null) {
      this.getHolder().unlockCanvasAndPost(c);
    }
  }
  this.lastFrequency=frequency;
  this.lastSampleRate=sampleRate;
}