Android audio mp3 custom waveform using Ringdroid

710 views Asked by At

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!

0

There are 0 answers