Andrioid 通过话筒实现吹气功能(1)

文章详细描述了一个Android应用中如何使用AudioRecord进行实时音频录制,每秒获取10次音量并将之转换为分贝值。同时,通过监听特定音量阈值触发雾化动画效果,还介绍了DrawView的使用以及手势擦除功能的集成。
摘要由CSDN通过智能技术生成

public AudioRecordManger(Handler handler,int what) {

mLock = new Object();//同步锁

this.mHandler = handler;//获得句柄

this.mWhat = what;//动作ID

}

实现监听吹气功能,用线程的方式开启话筒录音后,一秒钟10次接收话筒音量,然后将接收的音量转化为float的分贝值,并作为message发送。

public void getNoiseLevel() {

if (isGetVoiceRun) {

Log.e(TAG, “还在录着呢”);

return;

}

//创建录音对象,并初始化对象属性

mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,

SAMPLE_RATE_IN_HZ, AudioFormat.CHANNEL_IN_DEFAULT,

AudioFormat.ENCODING_PCM_16BIT, BUFFER_SIZE);

//判断话筒对象是否为空

if (mAudioRecord == null) {

Log.e(“sound”, “mAudioRecord初始化失败”);

}

isGetVoiceRun = true;//开启录音

//使用新线程

new Thread(new Runnable() {

@Override

public void run() {

mAudioRecord.startRecording();//录音启动

short[] buffer = new short[BUFFER_SIZE];//设置缓存数组

while (isGetVoiceRun) {

int r = mAudioRecord.read(buffer, 0, BUFFER_SIZE);//r是实际读取的数据长度,一般而言r会小于buffersize

long v = 0;

// 将 buffer 内容取出,进行平方和运算

for (int i = 0; i < buffer.length; i++) {

v += buffer[i] * buffer[i];

}

double mean = v / (double) r; // 平方和除以数据总长度,得到音量大小。

double volume = 10 * Math.log10(mean);

// 大概一秒十次,锁

synchronized (mLock) {

try {

mLock.wait(500);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

//声明消息类,句柄发送消息到主窗体函数

Message message = Message.obtain();

message.what = mWhat;

message.obj = volume;

mHandler.sendMessage(message);

}

//话筒对象释放

if (null !=mAudioRecord) {

mAudioRecord.stop();

mAudioRecord.release();

mAudioRecord = null;

}

}

}).start();//启动线程

}

mainactivity中接收message,先声明刚刚创建好的类

private AudioRecordManger audioRecordManger; //调用话筒实现类

private static final int RECORD = 2; //监听话筒

再在onCreate方法中调用实例的方法

audioRecordManger = new AudioRecordManger(handler,RECORD); //实例化话筒实现类

audioRecordManger.getNoiseLevel(); //打开话筒监听声音

我们在xml文件中放置drawview控件用来作为生成雾的画板,并在这上面去擦除雾,这是drawview的类

public class DrawView extends View {

private Canvas mCanvas;// 画布

private Path mPath;// 路径

private Paint mPaint;// 画笔

private float moveX, moveY;//移动坐标

private Bitmap mBitmap;//图片变量

private Bitmap bitmap;//图片变量

private volatile boolean mComplete = false;// 判断遮盖层区域是否消除达到阈值

/**

  • 构造函数

*/

public DrawView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init();//初始化

}

public DrawView(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public DrawView(Context context) {

this(context, null);

}

private void init() {

bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.glasses).copy(Bitmap.Config.ARGB_8888,true);//初始化图片加载

mPaint = new Paint(); //新建画笔

mPaint.setColor(Color.RED); //设置画笔颜色

mPaint.setStyle(Paint.Style.STROKE);//设置画笔样式

mPaint.setStrokeJoin(Paint.Join.ROUND);//设置结合处样子

mPaint.setStrokeCap(Paint.Cap.ROUND);//设置画笔笔触风格

mPaint.setDither(true);// 设置递色

mPaint.setAntiAlias(true);//设置抗锯齿

mPaint.setStrokeWidth(100);//设置空心线宽

mPath = new Path();//创建新路径

}

//画布绘制

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

canvas.drawColor(Color.TRANSPARENT);

if (!mComplete) //如果还未擦除完成

{

mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); //设定目标图模式

canvas.drawBitmap(mBitmap, 0, 0, null);//画图

mCanvas.drawPath(mPath, mPaint); //画布 路径

canvas.drawBitmap(mBitmap, 0, 0, null); //画布图片

}

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int width = MeasureSpec.getSize(widthMeasureSpec);//宽度

int height = MeasureSpec.getSize(heightMeasureSpec);//高度

mBitmap = Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);//图片

bitmap = Bitmap.createScaledBitmap(bitmap,width,height,true);//基于原bitmap,创建一个新的宽、高的bitmap

mCanvas = new Canvas(mBitmap); //画布实例化

mCanvas.drawColor(Color.TRANSPARENT);//设置颜色

mCanvas.drawBitmap(bitmap,0,0,null);//画布重绘bitmap

}

}

接下来是mainactivity开始通过有aduiorecordmanger发送过来的message做处理,如果音量分贝大于50,则产生动画效果形成雾

private void getSoundValues(double values){

//话筒分贝大于50,屏幕起雾

if (values >50){

hideView();//隐藏无关控件

drawView.setVisibility(View.VISIBLE); //显示控件

Animation animation = AnimationUtils.loadAnimation(this, R.anim.in_window);//设置透明度

drawView.setAnimation(animation);

audioRecordManger.isGetVoiceRun = false;//设置话筒停止运行

Log.e(“玻璃显示”,“执行”);

}

}

private Handler handler = new Handler(new Handler.Callback() {

@Override

public boolean handleMessage(Message msg) {

switch (msg.what) {

case RECORD://监测话筒

double soundValues = (double) msg.obj;

getSoundValues(soundValues);//获得话筒声音后,屏幕重绘起雾

break;

default:

break;

}

return false;

}

});

这里的anim中的in_window是在res下建立的动画xml文件,用Alpha的值来表示灰的程度,0是完全没有,1是全灰

<alpha

android:fromAlpha=“0”

android:toAlpha=“1”

android:duration=“3000”/>

这个时候当向手机话筒吹气的时候,就会产生雾气。

这时候加入手势擦除功能。

在drawView中加入写一个内部接口让mainactivity来实现

public interface OnCaYiCaCompleteListener{

void complete();

}

private OnCaYiCaCompleteListener mListener;

public void setOnCaYiCaCompleteListener(OnCaYiCaCompleteListener mListener){

this.mListener = mListener;

}

//变量重置

public void setEndValues(){

moveX = 0;

moveY = 0;

mPath.reset(); //路径重置

mComplete =false; //恢复未擦除状态

}

private Runnable mRunnable = new Runnable() {

@Override

public void run() {

int w = getWidth();

int h = getHeight();

float wipeArea = 0;

float totalArea = w * h;

Bitmap bitmap = mBitmap;

int[] mPixels = new int[w * h];

// 获得Bitmap上所有的像素信息

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

尾声

以薪资待遇为基础,以发展为最终目标,要在高薪资的地方,谋求最好的发展!

下面是有几位Android行业大佬对应上方技术点整理的一些进阶资料。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

Z0-1713707773565)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

[外链图片转存中…(img-VOWNh1k7-1713707773567)]

尾声

以薪资待遇为基础,以发展为最终目标,要在高薪资的地方,谋求最好的发展!

下面是有几位Android行业大佬对应上方技术点整理的一些进阶资料。

[外链图片转存中…(img-AZPVbXP4-1713707773568)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值