The last simple introduction of the use of Audiorecord and Audiotrack, this time the combination of Surfaceview to achieve an Android version of the phone analog signal oscilloscope. Recently the Internet of Things is very hot, as a mobile phone software developers, how to do not modify the phone hardware circuit under the premise of integration with third-party sensors it? The microphone is a good ADC interface, through the microphone and third-party sensors, and then in the software to do the corresponding processing of analog signals, can provide a richer sensor applications.
Let's take a look at the effect of this program (the screen video is slower, the real machine will actually run more smoothly):
This procedure uses the 8000hz sampling rate, to the X axis drawing real-time request is high, if does not reduce the X axis resolution, the program's real time is poor, therefore the program to the X axis data reduction interval is 8 times times ~16 times. Because of the use of 16-bit sampling, so the y-axis data height relative to the phone screen is also large, the program also to the y-axis data to shrink, the interval is 1 time times ~10 times. In the Ontouchlistener method of Surfaceview, the position adjustment of the waveform baseline is added, and the Surfaceview control can control the overall waveform deviation or the lower display.
Main.xml source code is as follows:
xml/html Code
<linearlayout xmlns:android= "http://schemas.android.com/apk/res/android" android:orientation= "vertical" Android:layout_width= "Fill_parent" android:layout_height= "fill_parent" > <linearlayout android:id= "@+id/Lin" earLayout01 "android:layout_height=" wrap_content "android:layout_width=" Fill_parent "Android:orientatio" n= "Horizontal" > <button android:layout_height= "wrap_content" android:id= "@+id/btnstart" Andro
id:text= "Start" android:layout_width= "80dip" > <button android:layout_height= "wrap_content" android:text= "Stop" Android:id= "@+id/btnexit" android:layout_width= "80dip" > <zoomcontrols android:layout_width= "WR" Ap_content "android:layout_height=" wrap_content "android:id=" @+id/zctlx "> <zoomcontrols Andro Id:layout_width= "Wrap_content" android:layout_height= "wrap_content" android:id= "@+id/zctly" > & Lt;surfaceview android:id= "@+id/SurfaceView01 "android:layout_height=" fill_parent "android:layout_width=" Fill_parent ">
Clsoscilloscope.java is the implementation of the Oscilloscope class library, including Audiorecord operation thread and Surfaceview drawing thread implementation, two threads synchronous operation, the code is as follows:
Package com.testoscilloscope;
Import java.util.ArrayList;
Import Android.graphics.Canvas;
Import Android.graphics.Color;
Import Android.graphics.Paint;
Import Android.graphics.Rect;
Import Android.media.AudioRecord;
Import Android.view.SurfaceView;
public class Clsoscilloscope {private ArrayList inbuf = new ArrayList ();
Private Boolean isrecording = false;//Thread Control token/** * x axis zoom/public int ratex = 4;
/** * Y-axis zoom/public int ratey = 4;
/** * Y-Axis baseline */public int baseLine = 0; /** * Initialize/public void initoscilloscope (int ratex, int ratey, int baseLine) {This.ratex = Rat
EX;
This.ratey = Ratey;
This.baseline = BaseLine; /** * Start * * @param recbufsize * Audiorecord minbuffersize/public void S Tart (audiorecord audiorecord, int recbufsize, Surfaceview sfv, Paint mpaint) {IsrecoRding = true;
New Recordthread (Audiorecord, Recbufsize). Start ()//Begin recording Thread new Drawthread (SFV, Mpaint). Start ();//begin drawing Thread}
/** * Stop/public void Stop () {isrecording = false; Inbuf.clear ()//clear}/** * Responsible for saving data from mic to INBUF * * @author GV */class record
Thread extends thread {private int recbufsize;
Private Audiorecord Audiorecord;
Public Recordthread (Audiorecord audiorecord, int recbufsize) {This.audiorecord = Audiorecord;
This.recbufsize = recbufsize;
public void Run () {try {short[] buffer = new Short[recbufsize];
Audiorecord.startrecording ()//Start recording while (isrecording) {//Save data from mic to buffer
int bufferreadresult = audiorecord.read (buffer, 0, recbufsize); short[] Tmpbuf = new Short[bufferreadresult/ratex];
for (int i = 0, ii = 0; i < tmpbuf.length i++, ii = i * Ratex) {
Tmpbuf[i] = Buffer[ii];
} synchronized (INBUF) {//Inbuf.add (TMPBUF);//Add Data}
} audiorecord.stop ();
The catch (Throwable t) {}}}; /** * is responsible for drawing data in Inbuf * * @author GV */class Drawthread extends Thread {priv ate int oldx = 0;//last drawn x coordinate private int oldy = 0;//Last drawn y coordinate private surfaceview sfv;//artboard pri vate int x_index = 0;//coordinates of the screen X axis of the current paint private Paint mpaint;//Brush public drawthread (Surfaceview SFV, Pain
T mpaint) {THIS.SFV = SFV;
This.mpaint = Mpaint; The public void run () {while (isrecording) {ArrayList buf = new ArrayList ();
Synchronized (INBUF) {if (inbuf.size () = = 0) continue; BUF = (ArrayList) inbuf.clone ();//Save Inbuf.clear ();//Clear} for ( int i = 0; I < buf.size ();
i++) {short[] tmpbuf = Buf.get (i);
Simpledraw (X_index, Tmpbuf, Ratey, baseLine);//Draw out the buffer data X_index = X_index + tmpbuf.length;
if (X_index > Sfv.getwidth ()) {x_index = 0;
/** * Draw the specified area * * @param start
* x-axis start position (full screen) * @param buffer * Buffer * @param rate * Y-axis data reduction ratio * @param baseLine * y-axis baseline */void Simpledraw (int staRT, short[] buffer, int rate, int baseLine) {if (start = = 0) oldx = 0; Canvas Canvas = Sfv.getholder (). Lockcanvas (New Rect (start, 0, start + buffer.length, Sfv.getheight ()
);/key: Get canvas Canvas.drawcolor (color.black);//clear background int y;
for (int i = 0; i < buffer.length i++) {//How many to draw int x = i + start;
y = buffer[i]/rate + baseline;//Adjust the scaling down, adjust the baseline Canvas.drawline (OLDX, Oldy, X, Y, mpaint);
OLDX = x;
Oldy = y; } sfv.getholder (). Unlockcanvasandpost (canvas);//unlock canvas, submit painted Image}}}
Testoscilloscope.java is the main program that controls the UI and Clsoscilloscope, the code is as follows:
Package com.testoscilloscope;
Import android.app.Activity;
Import Android.graphics.Color;
Import Android.graphics.Paint;
Import Android.media.AudioFormat;
Import Android.media.AudioRecord;
Import Android.media.MediaRecorder;
Import Android.os.Bundle;
Import android.view.MotionEvent;
Import Android.view.SurfaceView;
Import Android.view.View;
Import Android.view.View.OnTouchListener;
Import Android.widget.Button;
Import Android.widget.ZoomControls; The public class Testoscilloscope extends activity {/** called the ' when the ' is the ' The activity ' is the ' the '
, Btnexit;
Surfaceview SFV;
Zoomcontrols zctlx,zctly;
Clsoscilloscope clsoscilloscope=new Clsoscilloscope (); static final int frequency = 8000;//Resolution static final int channelconfiguration = Audioformat.channel_configuration_mon
O
static final int audioencoding = Audioformat.encoding_pcm_16bit; static final int xmax = 16;//x axis reduced proportional maximum, large x-axis data, easy to generate refresh delay static final int XMin = 8;//x axis zoom minimum static final int ymax = 10;//y Axis Zoom out maximum static final int ymin = 1;//y Axis Shrink-ratio minimum int r
ecbufsize;//recording minimum buffer size Audiorecord audiorecord;
Paint Mpaint;
@Override public void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (R.layout.main); Recording module recbufsize = audiorecord.getminbuffersize (Frequency, channelconfiguration, audioencoding)
; Audiorecord = new Audiorecord (MediaRecorder.AudioSource.MIC, Frequency, channelconfiguration, Audioencodi
Ng, Recbufsize);
Button btnstart = (button) This.findviewbyid (R.id.btnstart);
Btnstart.setonclicklistener (New Clickevent ());
Btnexit = (Button) This.findviewbyid (r.id.btnexit);
Btnexit.setonclicklistener (New Clickevent ());
Artboards and brushes SFV = (surfaceview) This.findviewbyid (R.ID.SURFACEVIEW01); Sfv.setontouchlistener (new TouchEvent ());
Mpaint = new Paint (); Mpaint.setcolor (Color.green);//Brush is green mpaint.setstrokewidth (1);//Set Brush thickness/oscilloscope class Library Clsoscilloscope.initosci
Lloscope (XMAX/2, YMAX/2, Sfv.getheight ()/2);
Scaling controls, the x-axis data is reduced by a higher ratio zctlx = (zoomcontrols) This.findviewbyid (R.ID.ZCTLX); Zctlx.setonzoominclicklistener (New View.onclicklistener () {@Override public void OnClick (View V
) {if (clsoscilloscope.ratex>xmin) clsoscilloscope.ratex--; Settitle ("x-axis Shrink" +string.valueof (Clsoscilloscope.ratex) + "times" + "," + "y-axis shrink" +string.valueof (Clsoscillosc
Ope.ratey) + "Times");
}
}); Zctlx.setonzoomoutclicklistener (New View.onclicklistener () {@Override public void OnClick (View
V) {if (Clsoscilloscope.ratex<xmax) clsoscilloscope.ratex++; Settitle ("x-axis Shrink" +string.valueof (clsoScilloscope.ratex) + "times" + "," + "y-axis shrink" +string.valueof (clsoscilloscope.ratey) + "Times");
}
});
zctly = (zoomcontrols) This.findviewbyid (r.id.zctly); Zctly.setonzoominclicklistener (New View.onclicklistener () {@Override public void OnClick (View V
) {if (clsoscilloscope.ratey>ymin) clsoscilloscope.ratey--; Settitle ("x-axis Shrink" +string.valueof (Clsoscilloscope.ratex) + "times" + "," + "y-axis shrink" +string.valueof (Clsoscillosc
Ope.ratey) + "Times");
}
}); Zctly.setonzoomoutclicklistener (New View.onclicklistener () {@Override public void OnClick (View
V) {if (Clsoscilloscope.ratey<ymax) clsoscilloscope.ratey++; Settitle ("x-axis Shrink" +string.valueof (Clsoscilloscope.ratex) + "times" + "," + "y-axis shrink" +string.valueof (Clsoscillo Scope.Ratey) + "Times");
}
});
} @Override protected void OnDestroy () {Super.ondestroy ();
Android.os.Process.killProcess (Android.os.Process.myPid ()); /** * Key Event processing * @author GV */class Clickevent implements View.onclicklistener {@Override public void OnClick (View v) {if (v = = btnstart) {Clsoscillos
Cope.baseline=sfv.getheight ()/2;
Clsoscilloscope.start (Audiorecord,recbufsize,sfv,mpaint);
else if (v = = btnexit) {clsoscilloscope.stop (); /** * Touch screen dynamically set waveform baseline * @author GV * * */class TouchEvent implements OnT ouchlistener{@Override Public boolean Ontouch (View V, motionevent event) {Clsoscilloscope
. baseline= (int) event.gety ();
return true; }
}
}
above is the implementation of the Android analog system signal oscilloscope sample detailed, follow-up to continue to supplement the relevant knowledge, thank you for your support for this site!