Android练手

您所在的位置:网站首页 免费分贝测试仪app Android练手

Android练手

2023-08-13 15:39| 来源: 网络整理| 查看: 265

基础实现方法以及图片素材来自大黑博客:http://blog.csdn.net/halibobo1998/article/details/51594655,博主基于此做了一些小小的修改和原理的推导~

博主是通信工程学院的学生,不过很不幸对通信一点都不感冒-。-!,从大一开始就走上了编程这条不归路,前几天实验考试被老师质疑是不是通信工程学院的学生咋BPSK都不知道,甚伤我心,为了证明我还是知道一点专业知识的,正好这两天预习光纤通信涉及dB(分贝),不是数据库啊!,所以就写一个Android上的分贝计,当然,在进行开发之前dB的背景知识以及相关公式必须得了解~,我也查了很多资料,下面是小米所介绍的一些背景知识!

度量声音强度,大家最熟悉的单位就是分贝(decibel,缩写为dB)。这是一个无纲量的相对单位,计算公式如下:

L_p=20 \log_{10}\left(\frac{p_{\mathrm{rms}}}{p_{\mathrm{ref}}}\right)\mbox{ dB}

分子是测量值的声压,分母是参考值的声压(20微帕,人类所能听到的最小声压)。因此日常中说道声音强度是多少多少分贝时,都是默认了一个很小的参考值的。

而Android设备传感器可以提供的物理量是场的幅值(amplitude),常用下列公式计算分贝值:

L_\mathrm{dB} = 10 \log_{10} \bigg(\frac{A_1^2}{A_0^2}\bigg) = 20 \log_{10} \bigg(\frac{A_1}{A_0}\bigg). \,

从SDK中读取了某段音频数据的振幅后,取最大振幅或平均振幅(可以用平方和平均,或绝对值的和平均),代入上述公式的A1。

具体实现的原理:通过麦克风进行录音,然后通过对一段时间内的录音源文件的幅度进行分析判断,其中Android的SDK直接给我们提供了getMaxAmplitude()这个方法来获取最大的振幅,因此本项目的问题也就迎刃而解了,下面看具体的代码实现

Android源码: manifest.xml文件 两个执行访问权限别忘记添加: FileUtil.java文件,这里主要是文件的创建、删除、路径查询等方法,使用的是第三方写好的代码,直接贴上来了: public class FileUtil { private static final String TAG = "FileUtil"; public static final String LOCAL = "Test"; public static final String LOCAL_PATH = Environment.getExternalStorageDirectory().getPath() + File.separator; /** * 录音文件目录 */ public static final String REC_PATH = LOCAL_PATH + LOCAL + File.separator; /** * 自动在SD卡创建相关的目录 */ static { File dirRootFile = new File(LOCAL_PATH); if (!dirRootFile.exists()) { dirRootFile.mkdirs(); } File recFile = new File(REC_PATH); if (!recFile.exists()) { recFile.mkdirs(); } } /** * 判断是否存在存储空间 * * * @return */ public static boolean isExitSDCard() { return Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED); } private static boolean hasFile(String fileName) { File f = createFile(fileName); return null != f && f.exists(); } public static File createFile(String fileName) { File myCaptureFile = new File(REC_PATH + fileName); if (myCaptureFile.exists()) { myCaptureFile.delete(); } try { myCaptureFile.createNewFile(); } catch (IOException e) { e.printStackTrace(); } return myCaptureFile; } } Calculator.java文件,用于记录最新的dB值,便于图形的计算绘制。

public class Calculator { public static float dbstart = 0; //初始值记录 public static float dblast = dbstart; //最新值 public static void setDbCount(float dbValue) { dbstart = dblast + (dbValue - dblast) * 0.2f; //最新值赋予以及保留两位小数 dblast = dbstart; } }

View.java文件,分贝计的绘制,参考小黑的绘制方法。

public class View extends ImageView{ private float scaleWidth, scaleHeight; private int newWidth, newHeight; private Matrix mMatrix = new Matrix(); private Bitmap indicatorBitmap; private Paint paint = new Paint(); static final long ANIMATION_INTERVAL = 100; public View(Context context) { super(context); } public View(Context context, AttributeSet attrs) { super(context, attrs); } private void init() { Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.noise_index); int bitmapWidth = myBitmap.getWidth(); int bitmapHeight = myBitmap.getHeight(); newWidth = getWidth(); newHeight = getHeight(); scaleWidth = ((float) newWidth) /(float) bitmapWidth; // 获取缩放比例 scaleHeight = ((float) newHeight) /(float) bitmapHeight; //获取缩放比例 mMatrix.postScale(scaleWidth, scaleHeight); //设置mMatrix的缩放比例 indicatorBitmap = Bitmap.createBitmap(myBitmap, 0, 0, bitmapWidth, bitmapHeight, mMatrix,true); //获取同等和背景宽高的指针图的bitmap paint = new Paint(); paint.setTextSize(55); paint.setAntiAlias(true); paint.setTextAlign(Paint.Align.CENTER); //抗锯齿 paint.setColor(Color.WHITE); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (indicatorBitmap == null) { init(); } float currentAngle = getAngle(Calculator.dbstart); mMatrix.setRotate(currentAngle, newWidth / 2, newHeight * 215 / 460); //片相对位置 canvas.drawBitmap(indicatorBitmap, mMatrix, paint); postInvalidateDelayed(ANIMATION_INTERVAL); canvas.drawText((int)Calculator.dbstart +" DB", newWidth/2,newHeight*36/46, paint); //图片相对位置 } private float getAngle(float db){ return(db-85)*5/3; } }

接下来就是MainActivity.java文件的编写了

public class MainActivity extends AppCompatActivity implements View.OnClickListener { private static final int START_RECORD = 0; private Button mBtnStart, mBtnStop; private File mFileRec; private Thread mThread; private MediaRecorder mMediaRecorder; private MyHandle mHandle; public boolean isRecording = false; private boolean isListener = false; private boolean isThreading = true; private float volume; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mHandle = new MyHandle(); initView(); } private void initView() { mBtnStart = (Button) findViewById(R.id.btn_start); mBtnStop = (Button) findViewById(R.id.btn_stop); mBtnStart.setOnClickListener(this); mBtnStop.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.btn_start: isListener = true; isRecording = true; isThreading = true; Message msg = new Message(); msg.what = START_RECORD; mHandle.sendMessage(msg); break; case R.id.btn_stop: isListener = false; isThreading = false; isRecording = false; mMediaRecorder.reset(); mFileRec.delete(); Calculator.dbstart = 0; break; } } private void beginstart() { isListener = true; mFileRec = FileUtil.createFile("test.amr"); } private void startRecord(File mFileRec) { try { mMediaRecorder = new MediaRecorder(); mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); mMediaRecorder.setOutputFile(mFileRec.getAbsolutePath()); mMediaRecorder.prepare(); mMediaRecorder.start(); isRecording = true; } catch (IOException e) { e.printStackTrace(); } mThread = new Thread(new Runnable() { @Override public void run() { while (isThreading) { try { if (isListener) { volume = mMediaRecorder.getMaxAmplitude(); if (volume > 0 && volume < 1000000) { Calculator.setDbCount(20 * (float) (Math.log10(volume))); } } Log.v("activity", "db = " + Calculator.dbstart); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); isListener = false; } } } }); mThread.start(); } class MyHandle extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case START_RECORD: beginstart(); if (mFileRec != null) { startRecord(mFileRec); } else { Toast.makeText(getApplicationContext(), "创建文件失败", Toast.LENGTH_LONG).show(); } break; } super.handleMessage(msg); } } }

运行后的效果图:

源码:https://github.com/weizainiunai/dBCalculator



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3