I'm working on a project using Ringdroid Library. I've no of audio in mp3 format (128 Kbit, 44100Hz, Stereo). They all are of different lengths ( ~ 30 sec max.) I'm having issue in fixing their waveform width. It set to its width on some tracks, and show blank space on some. Here is code:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mSoundFile == null)
return;
if (mHeightsAtThisZoomLevel == null)
computeIntsForThisZoomLevel();
// Draw waveform
measuredWidth = getMeasuredWidth();
measuredHeight = getMeasuredHeight();
int start = mOffset;
int width = mHeightsAtThisZoomLevel.length - start;
int ctr = measuredHeight / 2;
int i = 0;
AppLog.Error("measuredWidth" + measuredWidth);
AppLog.Error("measuredHeight" + measuredHeight);
if (width > measuredWidth)
width = measuredWidth;
// Draw waveform
for (i = 0; i < width; i++) {
Paint paint;
paint = mUnselectedLinePaint;
canvas.drawLine(i, ctr - mHeightsAtThisZoomLevel[start + i], i, ctr + 1+ mHeightsAtThisZoomLevel[start + i], paint);
if (i + start == mPlaybackPos) {
canvas.drawLine(i, 0, i, measuredHeight, mPlaybackLinePaint);
canvas.drawRect(i, 0, measuredWidth - 15, measuredHeight,
mUnPlayedBkgndPaint);
canvas.drawRoundRect(new RectF(measuredWidth - 15, 0,
measuredWidth, measuredHeight), 15, 15,
mUnPlayedBkgndPaint);
}
}
if (mListener != null) {
mListener.waveformDraw();
}
}
For setting zoom level according to frames
private void computeDoublesForAllZoomLevels() {
int numFrames = mSoundFile.getNumFrames();
AppLog.Debug("Num Of Frames " + numFrames);
int[] frameGains = mSoundFile.getFrameGains();
double[] smoothedGains = new double[numFrames];
if (numFrames == 1) {
smoothedGains[0] = frameGains[0];
} else if (numFrames == 2) {
smoothedGains[0] = frameGains[0];
smoothedGains[1] = frameGains[1];
} else if (numFrames > 2) {
smoothedGains[0] = (double) ((frameGains[0] / 2.0) + (frameGains[1] / 2.0));
for (int i = 1; i < numFrames - 1; i++) {
smoothedGains[i] = (double) ((frameGains[i - 1] / 3.0)
+ (frameGains[i] / 3.0) + (frameGains[i + 1] / 3.0));
}
smoothedGains[numFrames - 1] = (double) ((frameGains[numFrames - 2] / 2.0) + (frameGains[numFrames - 1] / 2.0));
}
// Make sure the range is no more than 0 - 255
double maxGain = 1.0;
for (int i = 0; i < numFrames; i++) {
if (smoothedGains[i] > maxGain) {
maxGain = smoothedGains[i];
}
}
double scaleFactor = 1.0;
if (maxGain > 255.0) {
scaleFactor = 255 / maxGain;
}
// Build histogram of 256 bins and figure out the new scaled max
maxGain = 0;
int gainHist[] = new int[256];
for (int i = 0; i < numFrames; i++) {
int smoothedGain = (int) (smoothedGains[i] * scaleFactor);
if (smoothedGain < 0)
smoothedGain = 0;
if (smoothedGain > 255)
smoothedGain = 255;
if (smoothedGain > maxGain)
maxGain = smoothedGain;
gainHist[smoothedGain]++;
}
// Re-calibrate the min to be 5%
double minGain = 0;
int sum = 0;
while (minGain < 255 && sum < numFrames / 20) {
sum += gainHist[(int) minGain];
minGain++;
}
// Re-calibrate the max to be 99%
sum = 0;
while (maxGain > 2 && sum < numFrames / 100) {
sum += gainHist[(int) maxGain];
maxGain--;
}
// Compute the heights
double[] heights = new double[numFrames];
double range = maxGain - minGain;
for (int i = 0; i < numFrames; i++) {
double value = (smoothedGains[i] * scaleFactor - minGain) / range;
if (value < 0.0)
value = 0.0;
if (value > 1.0)
value = 1.0;
heights[i] = value * (value * 0.8);
}
mNumZoomLevels = 5;
mLenByZoomLevel = new int[5];
mZoomFactorByZoomLevel = new double[5];
mValuesByZoomLevel = new double[5][];
// Level 0 is doubled, with interpolated values
mLenByZoomLevel[0] = numFrames * 2;
mZoomFactorByZoomLevel[0] = 2.0;
mValuesByZoomLevel[0] = new double[mLenByZoomLevel[0]];
if (numFrames > 0) {
mValuesByZoomLevel[0][0] = 0.5 * heights[0];
mValuesByZoomLevel[0][1] = heights[0];
}
for (int i = 1; i < numFrames; i++) {
mValuesByZoomLevel[0][2 * i] = 0.5 * (heights[i - 1] + heights[i]);
mValuesByZoomLevel[0][2 * i + 1] = heights[i];
}
// Level 1 is normal
mLenByZoomLevel[1] = numFrames;
mValuesByZoomLevel[1] = new double[mLenByZoomLevel[1]];
mZoomFactorByZoomLevel[1] = 1.0;
for (int i = 0; i < mLenByZoomLevel[1]; i++) {
mValuesByZoomLevel[1][i] = heights[i];
}
// 3 more levels are each halved
for (int j = 2; j < 5; j++) {
mLenByZoomLevel[j] = mLenByZoomLevel[j - 1] / 2;
mValuesByZoomLevel[j] = new double[mLenByZoomLevel[j]];
mZoomFactorByZoomLevel[j] = mZoomFactorByZoomLevel[j - 1] / 2.0;
for (int i = 0; i < mLenByZoomLevel[j]; i++) {
mValuesByZoomLevel[j][i] = 0.5 * (mValuesByZoomLevel[j - 1][2 * i] + mValuesByZoomLevel[j - 1][2 * i + 1]);
}
}
if (numFrames > 5000) {
mZoomLevel = 3;
} else if (numFrames > 1500) { // TODO : #changed from 1000
mZoomLevel = 2;
} else if (numFrames > 300) {
mZoomLevel = 1;
} else {
mZoomLevel = 0;
}
mInitialized = true;
}
/**
* Called the first time we need to draw when the zoom level has changed or
* the screen is resized
*/
private void computeIntsForThisZoomLevel() {
int halfHeight = (getMeasuredHeight() / 2) - 1;
mHeightsAtThisZoomLevel = new int[mLenByZoomLevel[mZoomLevel]];
for (int i = 0; i < mLenByZoomLevel[mZoomLevel]; i++) {
mHeightsAtThisZoomLevel[i] = (int) (mValuesByZoomLevel[mZoomLevel][i] * halfHeight);
}
}
public int getPlayBack() {
return mPlaybackPos;
}
Can anyone please help me? How to fiz to width of custom layout for every track? Thanks in advance!