diff options
author | ninatai <ninatai@google.com> | 2015-05-15 18:20:31 -0700 |
---|---|---|
committer | ninatai <ninatai@google.com> | 2015-05-15 18:20:31 -0700 |
commit | 9c39ed651cfee1193cc480ac95cda367ea9f1e2d (patch) | |
tree | 1183dc95e1261912801a5da69e4552e3d523f0a0 /LoopbackApp/app | |
parent | 2590779e25bd9ccf5a72e077421cfb8b6a83c113 (diff) | |
download | drrickorang-9c39ed651cfee1193cc480ac95cda367ea9f1e2d.tar.gz |
Histogram with log scale, x/y axis, and y label.
Diffstat (limited to 'LoopbackApp/app')
5 files changed, 122 insertions, 27 deletions
diff --git a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/Correlation.java b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/Correlation.java index aac3522..801e2bf 100644 --- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/Correlation.java +++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/Correlation.java @@ -1,5 +1,6 @@ package org.drrickorang.loopback; +import android.os.Trace; import android.util.Log; /** @@ -78,6 +79,7 @@ public class Correlation { int currentIndex = 0; double nextGroup = groupSize; + Trace.beginSection("Processing Correlation"); for (int i = 0; i<N && currentIndex<mBlockSize; i++) { if(i> nextGroup) { //advanced to next group. @@ -90,6 +92,8 @@ public class Correlation { } dataDownsampled[currentIndex] += Math.abs(data[i]); } + Trace.endSection(); + status = true; diff --git a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/HistogramView.java b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/HistogramView.java index 2fce8f2..d20f404 100644 --- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/HistogramView.java +++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/HistogramView.java @@ -4,31 +4,44 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import android.graphics.Path; import android.graphics.Rect; import android.util.AttributeSet; -import android.util.Log; import android.view.View; /** * Created by ninatai on 5/14/15. */ public class HistogramView extends View { - private Paint mPaint; + private Paint mHistPaint; + private Paint mTextPaint; + private Paint mLinePaint; + private static int[] mData; private static int mMaxLatency = 0; private static boolean mExceedRange = false; + private int mBase = 10; //base of logarithm + private int mNumberOfXLabel = 4; + private int mTextSize = 30; + private int mLineWidth = 3; public HistogramView(Context context, AttributeSet attrs) { super(context, attrs); init(); } - // TODO when to call this? For optimization + // initiate once for optimization private void init() { - mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mPaint.setStyle(Paint.Style.FILL); - mPaint.setColor(Color.BLUE); + mHistPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mHistPaint.setStyle(Paint.Style.FILL); + mHistPaint.setColor(Color.BLUE); + + mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mTextPaint.setColor(Color.RED); + mTextPaint.setTextSize(mTextSize); + + mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mLinePaint.setColor(Color.BLACK); + mLinePaint.setStrokeWidth(mLineWidth); } @Override @@ -41,12 +54,10 @@ public class HistogramView extends View { return; } - // coordinate starts at (0,0), up to (right, bottom) - int right = this.getRight(); - int bottom = this.getBottom(); - - // Rect rect1 = new Rect(0, 0, width, height); if (mMaxLatency != 0) { + + + // the range of latencies that's going to be displayed on histogram int range; if (mMaxLatency > arrayLength - 1) { range = arrayLength; @@ -59,8 +70,13 @@ public class HistogramView extends View { if (range == 0) { return; } - float width = ((float)right / range); + // coordinate starts at (0,0), up to (right, bottom) + int right = this.getRight(); + int bottom = this.getBottom(); + + + // calculate the max frequency among all latencies int maxLatencyFreq = 0; for (int i = 1; i < arrayLength; i++) { if (mData[i] > maxLatencyFreq) { @@ -68,24 +84,86 @@ public class HistogramView extends View { } } + if (maxLatencyFreq == 0) { return; } - float height =( (float)bottom / maxLatencyFreq); - float currentLeft = 0; - float currentTop = 0; - float currentRight = 0; - float currentBottom = bottom; - for (int i = 0; i < arrayLength; i++) { + // find the closest order of 10 according to maxLatencyFreq + int order = 0; + while (Math.pow(mBase, order) < maxLatencyFreq) { + order += 1; + } + float height =( (float) (bottom - mTextSize) / (order + 1)); // height for one decade + + + + + + // TODO add x labels + int totalXLabel = mNumberOfXLabel + 1; // last label is for the last beam + + // y labels + String[] yLabels = new String[order+2]; // will store {"0", "1", "10", "100", ...} for base = 10 + yLabels[0] = "0"; + canvas.drawText(yLabels[0], 0, bottom - mTextSize - mLineWidth, mTextPaint); + int currentValue = 1; + for (int i = 1; i <= (order + 1); i++) + { + yLabels[i] = Integer.toString(currentValue); + // FIXME since no margin added, can't show the top y label (100) -> fixed. now it display lower by amount of textsize + canvas.drawText(yLabels[i], 0, bottom - (i * height), mTextPaint); // for the third argument, + mTextSize - mTextSize cancels out + currentValue *= 10; + + } + // draw x axis + canvas.drawLine(0, bottom - mTextSize, right, bottom - mTextSize, mLinePaint); + + // draw y axis + int yMargin = getTextWidth(yLabels[order+1], mTextPaint); + int extraYMargin = 5; + canvas.drawLine(yMargin + extraYMargin, bottom, yMargin + extraYMargin, 0, mLinePaint); + + + float width = ((float) (right - yMargin - extraYMargin - mLineWidth) / range); // width of each beam in the histogram + + float currentLeft = yMargin + extraYMargin + mLineWidth; // FIXME there's an extra 1 pixel split, not sure why + float currentTop; + float currentRight; + // TODO separate each beam + // draw the histogram + mData[0] = 1; + mData[range-1] = 1; + int currentBottom = bottom - mTextSize - mLineWidth; + for (int i = 0; i < range; i++) { currentRight = currentLeft + width; - currentTop = bottom - (height * mData[i]); - canvas.drawRect(currentLeft, currentTop , currentRight, currentBottom, mPaint); + // calculate the height of the beam + if (mData[i] == 0) { + currentTop = currentBottom; + } else { + float units = (float) ((Math.log10((double) mData[i])) + 1.0); + currentTop = currentBottom - (height * units); + } + + canvas.drawRect(currentLeft, currentTop, currentRight, currentBottom, mHistPaint); currentLeft = currentRight; - //currentTop = currentBottom; } + + + + + + } - int x = 1; + + } + + // get the width of a certain string, using a certain paint + public int getTextWidth(String text, Paint paint) { + Rect bounds = new Rect(); + paint.getTextBounds(text, 0, text.length(), bounds); + int width = bounds.left + bounds.width(); + return width; } void redraw() { diff --git a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LatencyRecord.java b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LatencyRecord.java index b4d4247..6182ccb 100644 --- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LatencyRecord.java +++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LatencyRecord.java @@ -15,7 +15,7 @@ import java.util.HashMap; // TODO remember that after one record, set mPreviousTime back to zero -> done in onButtonTest public class LatencyRecord { private static long mPreviousTime = 0; - private static long mCurrentTime; + private static long mCurrentTime = 0; private static final int range = 102; //TODO adjust this value private static int mMaxLatency = 0; private static boolean exceedRange = false; @@ -26,9 +26,10 @@ public class LatencyRecord { public static void collectLatency() { mCurrentTime = System.nanoTime(); // if = 0 it's the first time the thread runs, so don't record the interval + // FIXME discard the first few records if (mPreviousTime != 0 && mCurrentTime != 0) { long diffInNano = mCurrentTime - mPreviousTime; - int diffInMilli = (int) Math.ceil(((double) (diffInNano / 1000000))); // round up + int diffInMilli = (int) Math.ceil(( ((double)diffInNano / 1000000))); // round up if (diffInMilli > mMaxLatency) { mMaxLatency = diffInMilli; @@ -60,7 +61,10 @@ public class LatencyRecord { public static void resetRecord() { mPreviousTime = 0; + mCurrentTime = 0; Arrays.fill(mJavaLatency, 0); + mMaxLatency = 0; + } public static int[] getLatencyArray() { diff --git a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackActivity.java b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackActivity.java index 2f02f7b..e1e168d 100644 --- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackActivity.java +++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackActivity.java @@ -21,6 +21,7 @@ import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.database.Cursor; +import android.os.Trace; import android.provider.MediaStore; import android.os.ParcelFileDescriptor; @@ -302,6 +303,7 @@ public class LoopbackActivity extends Activity { public void onButtonTest(View view) { if( !isBusy()) { + Trace.beginSection("Processing TestButton"); restartAudioSystem(); resetLatencyRecord(); try { @@ -318,6 +320,7 @@ public class LoopbackActivity extends Activity { nativeAudioThread.runTest(); } } + Trace.endSection(); } else { //please wait, or restart application. // Toast.makeText(getApplicationContext(), "Test in progress... please wait", diff --git a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackAudioThread.java b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackAudioThread.java index e0c46f3..960e472 100644 --- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackAudioThread.java +++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/LoopbackAudioThread.java @@ -417,11 +417,17 @@ public class LoopbackAudioThread extends Thread { } } + + private void resetLatencyRecord() { + LatencyRecord.resetRecord(); + } + public void run() { double phase = 0; double maxval = Math.pow(2, 15); + resetLatencyRecord(); while (!Thread.interrupted()) { boolean isRecording = false; @@ -430,10 +436,10 @@ public class LoopbackAudioThread extends Thread { } //long mStartTime = System.nanoTime(); - //WaitTimeRecord.collectLatency(); //FIXME should it be here, + //LatencyRecord.collectLatency(); //FIXME should it be here, if (isRecording && mRecorder != null) { - LatencyRecord.collectLatency(); // or here? + LatencyRecord.collectLatency(); // or here? int nSamplesRead = mRecorder.read(mAudioShortArray, 0, mMinRecordBuffSizeInSamples); // int nbBytesRead = mRecorder.read(mAudioByteArray, 0, |