Java 音频画布绘制android
我想用画布实时绘制麦克风的输入信号 但我有个问题, 我使用的代码正在绘制一个不同的信号(看起来不像常规的音频信号),可视化工具太快了。。我猜这和持续时间或周期有关,但我对这个画布概念很陌生Java 音频画布绘制android,java,android,android-canvas,Java,Android,Android Canvas,我想用画布实时绘制麦克风的输入信号 但我有个问题, 我使用的代码正在绘制一个不同的信号(看起来不像常规的音频信号),可视化工具太快了。。我猜这和持续时间或周期有关,但我对这个画布概念很陌生 package com.example.soundvisualizer; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.
package com.example.soundvisualizer;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import java.io.PrintStream;
import java.util.Arrays;
public class CDrawer extends SurfaceView
implements SurfaceHolder.Callback
{
private Context mContext;
private CDrawThread mDrawThread;
private SurfaceHolder mHolder;
private Boolean isCreated = false;
/**
* This is where you instance the drawer
* You relly don't need to care about the parameters, they are set in the xml-layout
* @param Apply the baseContext of you current acitivty
* @param AttributeSet
*/
public CDrawer(Context paramContext, AttributeSet paramAttributeSet)
{
super(paramContext, paramAttributeSet);
System.out.println("CDrawer()");
mHolder = getHolder();
mContext = paramContext;
mHolder.addCallback(this);
mDrawThread = new CDrawThread(mHolder, paramContext, new Handler()
{
public void handleMessage(Message paramMessage)
{
}
});
mDrawThread.setName("" + System.currentTimeMillis());
setFocusable(true);
}
public Boolean GetDead2()
{
return mDrawThread.GetDead2();
}
/**
* restarts the thread
* @param Is the thread dead?
*/
public void Restart(Boolean paramBoolean)
{
if (isCreated) {
if (mDrawThread.GetDead2().booleanValue())
{
mDrawThread.SetDead2(Boolean.valueOf(false));
if ((!paramBoolean.booleanValue()) || (!mDrawThread.GetDead().booleanValue()))
mHolder = getHolder();
mHolder.addCallback(this);
System.out.println("Restart drawthread");
mDrawThread = new CDrawThread(mHolder, mContext, new Handler()
{
public void handleMessage(Message paramMessage)
{
}
});
mDrawThread.setName("" + System.currentTimeMillis());
mDrawThread.start();
return;
}
Boolean No1,No2 = true;
while (true)
{
while (No2 = true)
{
try
{
Thread.sleep(10000L);
System.out.println("Just chilling in Restart");
No2 = false;
mDrawThread.SetDead2(Boolean.valueOf(true));
}
catch (InterruptedException localInterruptedException)
{
localInterruptedException.printStackTrace();
}
return;
}
if (!mDrawThread.GetDead().booleanValue())
continue;
mHolder = getHolder();
mHolder.addCallback(this);
System.out.println("Restart drawthread");
mDrawThread = new CDrawThread(mHolder, mContext, new Handler()
{
public void handleMessage(Message paramMessage)
{
}
});
mDrawThread.setName("" +System.currentTimeMillis());
mDrawThread.start();
return;
}
}
}
public void SetRun(Boolean paramBoolean)
{
mDrawThread.setRun(paramBoolean);
}
public CDrawThread getThread()
{
return mDrawThread;
}
/**
* Called when there's a change in the surface
*/
public void surfaceChanged(SurfaceHolder paramSurfaceHolder, int paramInt1, int paramInt2, int paramInt3)
{
mDrawThread.setSurfaceSize(paramInt2, paramInt3);
}
/**
* Creates the surface
*/
public void surfaceCreated(SurfaceHolder paramSurfaceHolder)
{
System.out.println("surfaceCreated");
if (mDrawThread.getRun().booleanValue())
{
System.out.println("11111");
isCreated = true;
mDrawThread.start();
}
while (true)
{
System.out.println("22222");
Restart(Boolean.valueOf(false));
return;
}
}
/**
* Surface destroyd
*/
public void surfaceDestroyed(SurfaceHolder paramSurfaceHolder)
{
int i = 1;
while (true)
{
if (i == 0)
return;
try
{
mDrawThread.join();
i = 0;
}
catch (InterruptedException localInterruptedException)
{
}
}
}
/**
* The Drawer Thread, subclass to cDrawer class
* We want to keep most of this process in a background thread,
* so the UI don't hang
* @author Pontus Holmberg (EndLessMind)
* Email: the_mr_hb@hotmail.com
*/
class CDrawThread extends Thread
{
private Paint mBackPaint;
private Bitmap mBackgroundImage;
private short[] mBuffer;
private int mCanvasHeight =20;
private int mCanvasWidth = 20;
private Paint mLinePaint;
private int mPaintCounter = 0;
private SurfaceHolder mSurfaceHolder;
private Boolean m_bDead = Boolean.valueOf(false);
private Boolean m_bDead2 = Boolean.valueOf(true);
private Boolean m_bRun = Boolean.valueOf(true);
private Boolean m_bSleep = Boolean.valueOf(false);
private int m_iScaler =20;
private int counter = 0;
/**
* Instance the Thread
* All the parameters i handled by the cDrawer class
* @param paramContext
* @param paramHandler
* @param arg4
*/
public CDrawThread(SurfaceHolder paramContext, Context paramHandler, Handler arg4)
{
mSurfaceHolder = paramContext;
mLinePaint = new Paint();
mLinePaint.setAntiAlias(true);
mLinePaint.setARGB(255, 255, 0, 0);
mLinePaint = new Paint();
mLinePaint.setAntiAlias(true);
mLinePaint.setARGB(255, 255, 0, 255);
mBackPaint = new Paint();
mBackPaint.setAntiAlias(true);
mBackPaint.setARGB(255, 0, 0, 0);
mBuffer = new short[2048];
mBackgroundImage = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
}
/**
* Allow you to change the size of the waveform displayed on the screen
* Or scale of you so will
* @return returns a new scale value
*/
/* public int ChangeSensitivity()
{
m_iScaler = (5 + m_iScaler);
if (m_iScaler > 20)
m_iScaler = 1;
return m_iScaler;
}*/
public Boolean GetDead()
{
return m_bDead;
}
public Boolean GetDead2()
{
return m_bDead2;
}
public Boolean GetSleep()
{
return m_bSleep;
}
public void SetDead2(Boolean paramBoolean)
{
m_bDead2 = paramBoolean;
}
public void SetSleeping(Boolean paramBoolean)
{
m_bSleep = paramBoolean;
}
/**
* Calculate and draws the line
* @param Canvas to draw on, handled by cDrawer class
*/
public void doDraw(Canvas paramCanvas)
{
if (mCanvasHeight == 1)
mCanvasHeight = paramCanvas.getHeight();
paramCanvas.drawPaint(mBackPaint);
/**
* Set some base values as a starting point
* This could be considerd as a part of the calculation process
*/
int height = paramCanvas.getHeight();
int BuffIndex = (mBuffer.length / 2 - paramCanvas.getWidth()) / 2;
int width = paramCanvas.getWidth();
int mBuffIndex = BuffIndex;
int scale = height / m_iScaler;
int StratX = 0;
if (StratX >= width)
{
paramCanvas.save();
return;
}
int cu1 = 0;
/**
* Here is where the real calculations is taken in to action
* In this while loop, we calculate the start and stop points
* for both X and Y
*
* The line is then drawer to the canvas with drawLine method
*/
while (StratX < width -1)
{
int StartBaseY = mBuffer[(mBuffIndex - 1)] / scale;
int StopBaseY = mBuffer[mBuffIndex] / scale;
if (StartBaseY > height / 2)
{
StartBaseY = 1 + height / 2;
int checkSize = height / 2;
if (StopBaseY <= checkSize)
return;
StopBaseY = 2 + height / 2;
}
int StartY = StartBaseY + height / 2;
int StopY = StopBaseY + height / 2;
paramCanvas.drawLine(StratX, StartY, StratX +1, StopY, mLinePaint);
cu1++;
mBuffIndex++;
StratX++;
int checkSize_again = -1 * (height / 2);
if (StopBaseY >= checkSize_again)
continue;
StopBaseY = -2 + -1 * (height / 2);
}
}
public Boolean getRun()
{
return m_bRun;
}
/**
* Updated the Surface and redraws the new audio-data
*/
public void run()
{
while (true)
{
if (!m_bRun.booleanValue())
{
m_bDead = Boolean.valueOf(true);
m_bDead2 = Boolean.valueOf(true);
System.out.println("Goodbye Drawthread");
return;
}
Canvas localCanvas = null;
try
{
localCanvas = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder)
{
if (localCanvas != null)
doDraw(localCanvas);
}
}
finally
{
if (localCanvas != null)
mSurfaceHolder.unlockCanvasAndPost(localCanvas);
}
}
}
public void setBuffer(short[] paramArrayOfShort)
{
synchronized (mBuffer)
{
mBuffer = paramArrayOfShort;
return;
}
}
public void setRun(Boolean paramBoolean)
{
m_bRun = paramBoolean;
}
public void setSurfaceSize(int paramInt1, int paramInt2)
{
synchronized (mSurfaceHolder)
{
mCanvasWidth = paramInt1;
mCanvasHeight = paramInt2;
mBackgroundImage = Bitmap.createScaledBitmap(mBackgroundImage, paramInt1, paramInt2, true);
return;
}
}
}
}
package com.example.soundvisualizer;
导入android.content.Context;
导入android.graphics.Bitmap;
导入android.graphics.Bitmap.Config;
导入android.graphics.Canvas;
导入android.graphics.Paint;
导入android.os.Handler;
导入android.os.Message;
导入android.util.AttributeSet;
导入android.util.Log;
导入android.view.SurfaceHolder;
导入android.view.SurfaceHolder.Callback;
导入android.view.SurfaceView;
导入java.io.PrintStream;
导入java.util.array;
公共类CDrawer扩展了SurfaceView
实现SurfaceHolder.Callback
{
私有上下文;
私有CDrawThread mDrawThread;
私人地勤人员;
私有布尔值isCreated=false;
/**
*这就是你的抽屉
*您实际上不需要关心参数,它们是在xml布局中设置的
*@param应用您当前活动的baseContext
*@param AttributeSet
*/
公共CDrawer(上下文参数上下文、属性集参数属性集)
{
super(paramContext,paramAttributeSet);
System.out.println(“CDrawer()”);
mHolder=getHolder();
mContext=paramContext;
mHolder.addCallback(this);
mDrawThread=new-CDrawThread(mHolder,paramContext,new-Handler())
{
公共无效handleMessage(消息参数消息)
{
}
});
mDrawThread.setName(“+System.currentTimeMillis());
设置聚焦(真);
}
公共布尔GetDead2()
{
返回mDrawThread.GetDead2();
}
/**
*重新启动线程
*@param线死了吗?
*/
公共无效重新启动(布尔参数)
{
如果(已创建){
if(mDrawThread.GetDead2().booleanValue())
{
mDrawThread.SetDead2(Boolean.valueOf(false));
如果((!paramBoolean.booleanValue())| |(!mDrawThread.GetDead().booleanValue()))
mHolder=getHolder();
mHolder.addCallback(this);
System.out.println(“重新启动drawthread”);
mDrawThread=new-CDrawThread(mHolder、mContext、new-Handler())
{
公共无效handleMessage(消息参数消息)
{
}
});
mDrawThread.setName(“+System.currentTimeMillis());
mDrawThread.start();
回来
}
布尔值No1,No2=true;
while(true)
{
while(No2=true)
{
尝试
{
线程。睡眠(10000L);
System.out.println(“刚刚进入重启”);
No2=假;
mDrawThread.SetDead2(Boolean.valueOf(true));
}
捕获(中断异常局部中断异常)
{
localInterruptedException.printStackTrace();
}
回来
}
如果(!mDrawThread.GetDead().booleanValue())
持续
mHolder=getHolder();
mHolder.addCallback(this);
System.out.println(“重新启动drawthread”);
mDrawThread=new-CDrawThread(mHolder、mContext、new-Handler())
{
公共无效handleMessage(消息参数消息)
{
}
});
mDrawThread.setName(“+System.currentTimeMillis());
mDrawThread.start();
回来
}
}
}
公共void SetRun(Boolean参数Boolean)
{
mDrawThread.setRun(参数布尔);
}
公共CDrawThread getThread()
{
返回mdraw线程;
}
/**
*当表面发生变化时调用
*/
public void surfacechange(SurfaceHolder参数SurfaceHolder、int-paramInt1、int-paramInt2、int-paramInt3)
{
mDrawThread.setSurfaceSize(参数2、参数3);
}
/**
*创建曲面
*/
已创建的公共空白表面(表面文件夹参数表面文件夹)
{
System.out.println(“表面处理”);
if(mDrawThread.getRun().booleanValue())
{
系统输出打印项次(“11111”);
isCreated=true;
mDrawThread.start();
}
while(true)
{
System.out.println(“22222”);
重新启动(Boolean.valueOf(false));
回来
}
}
/**
*表面破坏
*/
public void surfaceDestroyed(SurfaceHolder参数SurfaceHolder)
{
int i=1;
while(true)
{
如果(i==0)
回来
尝试
{
mDrawThread.join();
i=0;
}
捕获(中断异常局部中断异常)
{
}
}
}
/**
*抽屉线程,cDrawer类的子类
*我们希望将此过程的大部分内容保留在后台线程中,
*所以UI不会挂起
*@作者Pontus Holmberg(EndLessMind)
*电邮:香港大学_hb@hotmail.com
*/
类CDrawThread扩展线程
{
私人涂料;
私有位图图像;
私人卖空者;
私有整数mcanvashweight=20;
专用int MCANVASWITH=20;
私人油漆;
私有int mPaintCounter=0;
私人地表持有人;
私有布尔m_bDead=Boolean.valueOf(false);
私有布尔m_bDead2=布尔.valueOf(true);
私有布尔m_bRun=布尔.valueOf(true);
私有布尔m_bSleep=Boolean.valueOf(false);
私有整数m_iScaler=20;
专用整数计数器=0;
/**
*实例线程
*cDrawer类处理的所有参数
*@param paramContext
*@param paramHandler
*@param arg4
*/
公共CDrawThread(SurfaceHolder paramContext、Context paramHandler、Handler arg4)
{
mSurfaceHolder=paramContext;
mLinePaint=新油漆();
mLinePaint.setantialas(真);
mLinePaint.setARGB(255,255,0,0);
mLinePaint=新油漆();
mLinePaint.setantialas(真);
mLinePaint.setARGB(255,255,0255);
mBackPaint=新油漆();
mBackPaint.setAntiAlias(真);
private static final int INTERVAL = 16;
public void run()
{
while (true)
{
long start=System.currentTimeMillis(); //<<< record redraw start time
if (!m_bRun.booleanValue())
{
m_bDead = Boolean.valueOf(true);
m_bDead2 = Boolean.valueOf(true);
System.out.println("Goodbye Drawthread");
return;
}
Canvas localCanvas = null;
try
{
localCanvas = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder)
{
if (localCanvas != null)
doDraw(localCanvas);
}
}
finally
{
if (localCanvas != null)
mSurfaceHolder.unlockCanvasAndPost(localCanvas);
}
SystemClock.sleep(INTERVAL - (System.currentTimeMillis() - start)); //<<< sleep
}
}