登录 立即注册
安币:

安卓巴士 - 安卓开发 - Android开发 - 安卓 - 移动互联网门户

用ClipDrawable实现音频录制麦克风讲话效果

[复制链接]
来自: MrlLee 分类: Android精品源码 上传时间: 2016-6-20 11:03:02
立即下载
收藏

项目介绍:

由于最近项目开发需要用到自定义SeekBar,于是又对android下的各种类型drawable进行了一个全面系统的认识,只能感慨drawable的功能还是很强大的。通过自定义SeekBar有感而发,尝试用ClipDrawable实现音频录制过程的一个麦克风录制效果:
在实现开发之前先让我们一起认识两种类型的Drawable:
LayerDrawableLayerDrawable可以包含一个drawable数组,而且系统会根据drawable数组的前后顺序来绘制所有的drawable,索引最大的drawable也就相应的会被绘制在最上面。使用过PhotoShop的朋友应该会比较容易理解,LayerDrawable和PhotoShop中图层的概念很相似,这里drawable数组中的每一个drawable就相当于PhotoShop中的一个图层,上一个图层会遮住之后所有图层与之重叠的部分。
定义LayerDrawable对象的XML文件的根元素为,该元素可以包含对个元素也就是一个drawable对象。
ClipDrawable
ClipDrawable,顾名思义这就是一个可以进行裁切的drawable,在XML文件中定义ClipDrawable对象使用的根元素是元素,该元素包含以下几个重要的属性:
  • android:drawable:指定将要被截取的Drawable对象。
  • android:clipOrientation:指定Drawable对象的截取方向可以是水平和竖直方向。
  • android:gravity:表示Drawable对象的对齐方式,例如:left 可以理解为左边部分为保留部分,右边部分为剪切部分,则我们可以看到的就是截取的左边部分。
注意,使用ClipDrawable对象时可以调用setLevel(int level)方法来控制截取区域的大小,而level的取值区间在0~10000之间,则level为0时,表示图片截取部分为空,当了level为10000时,截取整张图片。
了解完毕,下面我们就要用这两种Drawable结合使用开发我们今天的麦克风说话效果:
首先,准备两张位图
2.png 1.png

然后,在XML中新建一个拥有两个Drawable的LayerDrawable文件layer-microphone.xml,在顶层显示的是可以裁切的ClipDrawable,设置剪切方向为竖直方向,设置对其方式为bottom,底部的则是不通的Drawable作为背景。
[XML] 查看源文件 复制代码


    
    
        
    

然后,再自定义一个PopupWindow用于音频录制过程显示麦克风动画效
窗口布局如下layout_microphone.xml:
[XML] 查看源文件 复制代码



    

        

        
    

从代码中可以看出,我把ImageVie的资源设为layer-microphone.xml,我们获取ImageView的Drawable对象并设置Level值就能实现想要的效果:
[JavaScript] 查看源文件 复制代码
imageView.getDrawable().setLevel(5400);

3.png
从这里我们已经可以看到裁切效果。最后一步,我们只要能够实时获取音频录制过程中的分贝值的变化,再将分贝值变化转换到相应的Level值,就能实现音频录制说话效果啦,
[Java] 查看源文件 复制代码
package com.mariostudio.audiorecoder;

import java.io.File;
import java.io.IOException;

import android.media.MediaRecorder;
import android.os.Handler;
import android.util.Log;

/**
 * Created by MarioStudio on 2016/5/12.
 */

public class AudioRecoderUtils {

    private String filePath;
    private MediaRecorder mMediaRecorder;
    private final String TAG = "MediaRecord";
    public static final int MAX_LENGTH = 1000 * 60 * 10;// 最大录音时长1000*60*10;

    private OnAudioStatusUpdateListener audioStatusUpdateListener;

    public AudioRecoderUtils(){
        this.filePath = "/dev/null";
    }

    public AudioRecoderUtils(File file) {
        this.filePath = file.getAbsolutePath();
    }

    private long startTime;
    private long endTime;

    /**
     * 开始录音 使用amr格式
     *      录音文件
     * @return
     */
    public void startRecord() {
        // 开始录音
        /* ①Initial:实例化MediaRecorder对象 */
        if (mMediaRecorder == null)
            mMediaRecorder = new MediaRecorder();
        try {
            /* ②setAudioSource/setVedioSource */
            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
            /* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
            mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
            /*
             * ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
             * ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
             */
            mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            /* ③准备 */
            mMediaRecorder.setOutputFile(filePath);
            mMediaRecorder.setMaxDuration(MAX_LENGTH);
            mMediaRecorder.prepare();
            /* ④开始 */
            mMediaRecorder.start();
            // AudioRecord audioRecord.
            /* 获取开始时间* */
            startTime = System.currentTimeMillis();
            updateMicStatus();
            Log.i("ACTION_START", "startTime" + startTime);
        } catch (IllegalStateException e) {
            Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
        } catch (IOException e) {
            Log.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
        }
    }

    /**
     * 停止录音
     */
    public long stopRecord() {
        if (mMediaRecorder == null)
            return 0L;
        endTime = System.currentTimeMillis();
        Log.i("ACTION_END", "endTime" + endTime);
        mMediaRecorder.stop();
        mMediaRecorder.reset();
        mMediaRecorder.release();
        mMediaRecorder = null;
        Log.i("ACTION_LENGTH", "Time" + (endTime - startTime));
        return endTime - startTime;
    }

    private final Handler mHandler = new Handler();
    private Runnable mUpdateMicStatusTimer = new Runnable() {
        public void run() {
            updateMicStatus();
        }
    };

    /**
     * 更新话筒状态
     */
    private int BASE = 1;
    private int SPACE = 100;// 间隔取样时间

    public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener audioStatusUpdateListener) {
        this.audioStatusUpdateListener = audioStatusUpdateListener;
    }

    private void updateMicStatus() {
        if (mMediaRecorder != null) {
            double ratio = (double)mMediaRecorder.getMaxAmplitude() / BASE;
            double db = 0;// 分贝
            if (ratio > 1) {
                db = 20 * Math.log10(ratio);
                if(null != audioStatusUpdateListener) {
                    audioStatusUpdateListener.onUpdate(db);
                }
            }
            mHandler.postDelayed(mUpdateMicStatusTimer, SPACE);
        }[mw_shl_code=java,true]public void setLevel(int level) {
    imageView.getDrawable().setLevel(3000 + 6000 * level / 100);
}

    }

    public interface OnAudioStatusUpdateListener {
        public void onUpdate(double db);
    }
}[/mw_shl_code]
进行到这一步,已经基本完成了这个效果,最后只需要在自定义PopupWindow的时候提供方法setLevel(int level)就可以轻松实现PopupWindow实时刷新分贝值啦!!
至于为什么设置level的时候要3000 + 6000 level / 100*以及计时效果,就都留给聪明的你去探索咯!!
还是那句老话,如果文中有表述不当或阐述错误的地方,还望正在看文章的您可以帮忙指出,有疑惑呢,也可以在评论中提问,期待您的意见和建议,欢迎关注交流。







相关源码推荐:

我来说两句
所有评论(21)
嘘丶~低调 2016-6-20 15:26:22
淡定,淡定,淡定……
回复
dielianxian 2016-6-21 09:13:47
楼主用心了,内容非常精彩。
回复
嘘丶~低调 2016-6-21 11:04:36
楼主用心了,内容非常精彩。
回复
vatty 2016-6-21 11:25:25
很给力,安卓巴士有你更精彩!
回复
权爸爸啊! 2016-6-21 11:46:09
感谢分享,安卓巴士有你更精彩:)
回复
fan0424 2016-6-22 16:13:08
我只是路过打酱油的。
回复
fan0424 2016-6-23 10:13:37
感谢分享,安卓巴士有你更精彩:)
回复
123下一页
上传代码
查看数:1914 收藏数:13 下载数:31 点赞数:1
状态:已购或VIP 售价:10(原价:10)金钱 下载权限:初级码农 
代码贡献英雄榜
用户名 下载数
联系我们
首页/微信公众账号投稿

帖子代码编辑/版权问题

QQ:435399051,769657487

如何获得代码达人称号

如何成为签约作者

联系我们
关闭
合作电话:
15618560077
Email:
805941275@qq.com
商务市场合作/投稿
问题反馈及帮助
联系我们

广告投放| 广东互联网违法和不良信息举报中心|中国互联网举报中心|下载客户端|申请友链|手机版|站点统计|安卓巴士 ( 粤ICP备15117877号 )

快速回复 返回顶部 返回列表