Android实现可录音/暂停录音/播放录音的录音软件

本文详细介绍了如何在Android中实现音频录制、暂停/继续、自定义命名保存、pcm转wav、文件列表显示、播放、计时器、文件分享及长按操作等功能。涉及到的关键技术包括AudioRecord、MediaRecorder、MediaPlayer、FileUtil和PopupMenu等,同时讨论了不同音频处理类的优缺点。此外,还强调了权限管理和文件操作的相关细节。

一、功能简介与操作视频

该APP功能完成音频的录制并命名保存与播放功能

1、录制

在音频录制界面点击开始按钮即可进行录制,录制过程中可以点击暂停按钮暂时停止录制,暂停可以继续录制,点击停止按钮结束录制,然后,跳出命名和保存框,点击删除按钮则不保存此次录音文件,在输入框输入文件名并点击保存按钮可以保存此次录音的音频文件

2、查看录音文件列表

在音频录制界面中点击文件列表按钮即可跳转查看录音文件列表,该列表显示了ARecordFiles文件夹中所有的录音文件,长按某个录音文件可以选择删除或者分享给手机上其他应用,点击某个录音文件,跳转到播放该录音文件界面

3、播放

进入播放界面后,点击播放按钮即可进行播放,播放过程中可以点击暂停按钮暂时停止播放,暂停可以继续播放,点击结束按钮结束播放。一次播放结束后,可以再次点击播放按钮重新播放

源码链接

二、文件夹结构

在这里插入图片描述
FileUtil.java找出ARecordFiles文件下所有音频文件然后保存到ArrayList

Pcm2WavUtil.java将原始的.pcm音频文件转成可直接播放的.wav音频文件

PlayerManager.java与音频播放有关

RecorderManager.java与音频录制有关

TimerManager.java与计时器有关

AudioPlay.java实现具体的音频播放功能,与activity_audio_play.xml绑定

FileListAdapter.java继承了BaseAdapter适配器,目的是将文件显示在listview控件中,与activity_filelist绑定

ListActivity.java实现具体的文件显示功能,主要用到了listview控件,与activity_list绑定

MainActivity.java实现具体的音频录制功能,与activity_filelist绑定

ListActivity.java实现具体的文件显示功能,主要用到了listview控件,与activity_main绑定

三、实现

3.1 录制

使用java自带的AudioRecord进行录制

实现录音步骤:

①计算缓冲录音数据的字节数组的大小。AudioRecord 需要一个容器来缓冲来自硬件的音频信息。

bufferSize=AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE,AUDIO_CHANNEL,AUDIO_ENCODING);

②创建AudioRecord对象

myrecord=new AudioRecord(AUDIO_INPUT,AUDIO_SAMPLE_RATE,AUDIO_CHANNEL,AUDIO_ENCODING,bufferSize);

③初始化一个buffer

buffer = new byte[bufferSize];

④开始录音

myrecord.startRecording();
Recordstatus=Status.STATUS_START;

⑤创建一个数据流,一边从AudioRecord中读取声音数据到初始化的buffer,一边将buffer中数据导入数据流,这里创建一个新线程完成该操作,注意使用Environment.getExternalStorageDirectory()获取手机存储的根目录

new Thread(()->{
   
   

            FileOutputStream os=null;

            try {
   
   

                //首先创建文件夹
                File dirFile = new File(Environment.getExternalStorageDirectory(),DirName);
                if(!dirFile.exists()){
   
   
                    dirFile.mkdirs();
                }
                File myfile=new File(dirFile,finalFileName);

                //如果文件存在,先删除文件
                if(myfile.exists()){
   
   
                    myfile.delete();
                }

                //然后创建新文件
                myfile.createNewFile();

                os = new FileOutputStream(myfile);
            }
            catch (FileNotFoundException e) {
   
   
                e.printStackTrace();
            }
            catch (Exception e) {
   
   
                Log.e("TestFile", "Error on write File:" + e);
            }

            if(os!=null){
   
   
                //判断录音的状态
                while(Recordstatus==Status.STATUS_START){
   
   
                    int read = myrecord.read(buffer, 0, bufferSize);

                    // 如果读取音频数据没有出现错误,就将数据写入到文件
                    if (AudioRecord.ERROR_INVALID_OPERATION != read) {
   
   
                        try {
   
   
                            os.write(buffer);
                            os.flush();
                        } catch (IOException e) {
   
   
                            e.printStackTrace();
                        }
                    }

                }
                try {
   
   
                    os.flush();
                    os.close();
                } catch (IOException e) {
   
   
                    e.printStackTrace();
                }
            }
        }

        ).start();

⑥停止录音

		myrecord.stop();
        Recordstatus=Status.STATUS_STOP;

        myrecord.release();
        myrecord=null;
        

        Recordstatus=Status.STATUS_NO_READY;

另外,还可以使用MediaPlayer进行录制。 MediaPlayer比AudioRecord更上层,使用起来更方便、易用,但是AudioRecord偏底层,因此也就更灵活,我可以自由设置位宽采样率通道数录制时所使用的的麦克风这些参数。

录制声音MediaRecorder和AudioRecord 区别

<1>.MediaRecorder录制的音频文件是经过压缩后的,需要设置编码器。并且录制的音频文件可以用系统自带的Music播放器播放。

<2>.而AudioRecord录制的是PCM格式的音频文件,需要用AudioTrack来播放,AudioTrack更接近底层。

<3>.在用MediaRecorder进行录制音视频时,最终还是会创建AudioRecord用来与AudioFlinger进行交互。

<4>.MediaRecorder录制的数据是 amr MP3 格式 ,AudioRecord录制出来的是比较原始的PCM音频格式 ,PCM经过编码压缩可以为 amr MP3 AAC。

<5>.如果想简单地做一个录音机,录制成音频文件,则推荐使用 MediaRecorder,而如果需要对音频做进一步的算法处理、或者采用第三方的编码库进行压缩、以及网络传输等应用,则建议使用 AudioRecord

3.2 暂停/继续录制

实现该功能最重要的是对录音状态的控制

构建状态类,控制录音状态
public enum Status {
   
   
        //未开始
        STATUS_NO_READY,
        //预备
        STATUS_READY,
        //录音
        STATUS_START,
        //暂停
        STATUS_PAUSE,
        //停止
        STATUS_STOP
    }
    //初始状态为未开始
private Status Recordstatus=Status.STATUS_NO_READY;

每次录音开始—录音暂停/停止这一阶段我们称之为一个周期,而每个周期都创建一个临时.pcm文件,保存该周期录制的音频,因此暂停/继续录制功能的实现可看成是将录制分成多个周期,最终得到多个临时小文件,最后将这些小文件合并成为一个大的.pcm文件完成对该功能的实现。这里注意:每个周期的临时文件命名不能冲突,否则会出现覆盖,导致某部分音频的缺失,另外要将各个周期的临时文件名按照创建顺序保存下来,保证最后音频的顺序性。

//合并所有临时文件成为一个文件
    public void mergeAllFiles(){
   
   

        File finalFile =new File(Environment.getExternalStorageDirectory(),DirName+"/"+Afilename);
        FileOutputStream os=null;

        try {
   
   
            //创建最终文件
            finalFile.createNewFile();
            os = new FileOutputStream(finalFile);

            //将每个临时文件的内容读出来并保存到最终文件中,同时删除临时文件
            for (String fileName : AllFiles) {
   
   
                FileInputStream in =null;
                File infile=new File(Environment.getExternalStorageDirectory(),DirName+"/"+fileName);
                in = new FileInputStream(infile);
                byte[] data = new byte[bufferSize];
                while (in.read(data) != -1) {
   
   
                    os.write(data);
                }
                in.close();
                infile.delete();//删除临时文件
            }

            AllFiles.clear();//清除ArrayList
            FileVersion=1;//清除版本号
            os.close();

        }catch (FileNotFoundException e) {
   
   
            e.printStackTrace();
        }
        catch (Exception e) {
   
   
            Log.e("TestFile", "Error on write File:" + e);
        }

    }

3.3 pcm转wav

pcm与wav:

一般通过麦克风采集的录音数据都是PCM格式的,即不包含头部信息,播放器无法知道音频采样率、位宽等参数,导致无法播放,在pcm文件的数据开头加入WAVE HEAD数据即可转成wav文件

wav头文件:

在这里插入图片描述

偏移地址 命名 内容
00-03 ChunkId “RIFF”
4-07 ChunkS
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值