Program: 54995
Project: 54995
Buggy source:
/** 
 * This method will draw the fft onto the canvas. It will also update the bitmap in waterfallLines[waterfallLinesTopIndex] with the data from mag. Important: start and end may be out of bounds of the mag array. This will cause black padding.
 * @param c			canvas of the surface view
 * @param mag		array of magnitude values that represent the fft
 * @param start		first index to draw from mag (may be negative)
 * @param end		last index to draw from mag (may be > mag.length)
 */
private void drawFFT(Canvas c,double[] mag,int start,int end){
  float previousY=getFftHeight();
  float currentY;
  float samplesPerPx=(float)(end - start) / (float)width;
  float dbDiff=maxDB - minDB;
  float dbWidth=getFftHeight() / dbDiff;
  float scale=this.waterfallColorMap.length / dbDiff;
  float avg;
  float peakAvg;
  int counter;
  Canvas newline=new Canvas(waterfallLines[waterfallLinesTopIndex]);
  newline.drawColor(Color.BLACK);
  c.drawRect(0,0,width,getFftHeight(),blackPaint);
  int firstPixel=start >= 0 ? 0 : (int)((start * -1) / samplesPerPx);
  int lastPixel=end >= mag.length ? (int)((mag.length - start) / samplesPerPx) : (int)((end - start) / samplesPerPx);
  for (int i=firstPixel + 1; i < lastPixel; i++) {
    avg=0;
    peakAvg=0;
    counter=0;
    for (int j=(int)(i * samplesPerPx); j < (i + 1) * samplesPerPx; j++) {
      avg+=mag[j + start];
      if (peaks != null)       peakAvg+=peaks[j + start];
      counter++;
    }
    avg=avg / counter;
    if (peaks != null)     peakAvg=peakAvg / counter;
    if (avg > minDB) {
      currentY=getFftHeight() - (avg - minDB) * dbWidth;
      if (currentY < 0)       currentY=0;
switch (fftDrawingType) {
case FFT_DRAWING_TYPE_BAR:
        c.drawLine(i,getFftHeight(),i,currentY,fftPaint);
      break;
case FFT_DRAWING_TYPE_LINE:
    c.drawLine(i - 1,previousY,i,currentY,fftPaint);
  previousY=currentY;
if (i + 1 == lastPixel) c.drawLine(i,previousY,i + 1,getFftHeight(),fftPaint);
break;
default :
Log.e(LOGTAG,"String_Node_Str" + fftDrawingType);
}
}
if (peaks != null) {
if (peakAvg > minDB) {
peakAvg=getFftHeight() - (peakAvg - minDB) * dbWidth;
if (peakAvg > 0) c.drawPoint(i,peakAvg,peakHoldPaint);
}
}
if (avg <= minDB) waterfallLinePaint.setColor(waterfallColorMap[0]);
 else if (avg >= maxDB) waterfallLinePaint.setColor(waterfallColorMap[waterfallColorMap.length - 1]);
 else waterfallLinePaint.setColor(waterfallColorMap[(int)((avg - minDB) * scale)]);
newline.drawLine(i,0,i,getPixelPerWaterfallLine(),waterfallLinePaint);
}
if (demodulationEnabled) {
float pxPerHz=width / (float)virtualSampleRate;
float channelPosition=width / 2 + pxPerHz * (channelFrequency - virtualFrequency);
float leftBorder=channelPosition - pxPerHz * channelWidth;
float rightBorder=channelPosition + pxPerHz * channelWidth;
float squelchPosition=getFftHeight() - (squelch - minDB) * dbWidth;
demodSelectorPaint.setAlpha(0x7f);
c.drawRect(leftBorder,0,rightBorder,squelchPosition,demodSelectorPaint);
demodSelectorPaint.setAlpha(0xff);
c.drawLine(channelPosition,getFftHeight(),channelPosition,0,demodSelectorPaint);
c.drawLine(leftBorder,getFftHeight(),leftBorder,0,demodSelectorPaint);
c.drawLine(rightBorder,getFftHeight(),rightBorder,0,demodSelectorPaint);
c.drawLine(leftBorder,squelchPosition,rightBorder,squelchPosition,demodSelectorPaint);
}
}

Fixed version (ground truth):
/** 
 * This method will draw the fft onto the canvas. It will also update the bitmap in waterfallLines[waterfallLinesTopIndex] with the data from mag. Important: start and end may be out of bounds of the mag array. This will cause black padding.
 * @param c			canvas of the surface view
 * @param mag		array of magnitude values that represent the fft
 * @param start		first index to draw from mag (may be negative)
 * @param end		last index to draw from mag (may be > mag.length)
 */
private void drawFFT(Canvas c,double[] mag,int start,int end){
  float previousY=getFftHeight();
  float currentY;
  float samplesPerPx=(float)(end - start) / (float)width;
  float dbDiff=maxDB - minDB;
  float dbWidth=getFftHeight() / dbDiff;
  float scale=this.waterfallColorMap.length / dbDiff;
  float avg;
  float peakAvg;
  int counter;
  Canvas newline=new Canvas(waterfallLines[waterfallLinesTopIndex]);
  newline.drawColor(Color.BLACK);
  c.drawRect(0,0,width,getFftHeight(),blackPaint);
  int firstPixel=start >= 0 ? 0 : (int)((start * -1) / samplesPerPx);
  int lastPixel=end >= mag.length ? (int)((mag.length - start) / samplesPerPx) : (int)((end - start) / samplesPerPx);
  for (int i=firstPixel + 1; i < lastPixel; i++) {
    avg=0;
    peakAvg=0;
    counter=0;
    for (int j=(int)(i * samplesPerPx); j < (i + 1) * samplesPerPx; j++) {
      avg+=mag[j + start];
      if (peaks != null)       peakAvg+=peaks[j + start];
      counter++;
    }
    avg=avg / counter;
    if (peaks != null)     peakAvg=peakAvg / counter;
    if (avg > minDB) {
      currentY=getFftHeight() - (avg - minDB) * dbWidth;
      if (currentY < 0)       currentY=0;
switch (fftDrawingType) {
case FFT_DRAWING_TYPE_BAR:
        c.drawLine(i,getFftHeight(),i,currentY,fftPaint);
      break;
case FFT_DRAWING_TYPE_LINE:
    c.drawLine(i - 1,previousY,i,currentY,fftPaint);
  previousY=currentY;
if (i + 1 == lastPixel) c.drawLine(i,previousY,i + 1,getFftHeight(),fftPaint);
break;
default :
Log.e(LOGTAG,"String_Node_Str" + fftDrawingType);
}
}
if (peaks != null) {
if (peakAvg > minDB) {
peakAvg=getFftHeight() - (peakAvg - minDB) * dbWidth;
if (peakAvg > 0) c.drawPoint(i,peakAvg,peakHoldPaint);
}
}
if (avg <= minDB) waterfallLinePaint.setColor(waterfallColorMap[0]);
 else if (avg >= maxDB) waterfallLinePaint.setColor(waterfallColorMap[waterfallColorMap.length - 1]);
 else waterfallLinePaint.setColor(waterfallColorMap[(int)((avg - minDB) * scale)]);
newline.drawLine(i,0,i,getPixelPerWaterfallLine(),waterfallLinePaint);
}
}