首页 > 其他分享 >Android录制副麦克风的声音

Android录制副麦克风的声音

时间:2022-10-26 14:34:11浏览次数:85  
标签:麦克风 mBuffer 录制 mAudioTrack mBufferCount new Android public bsright

总结就是立体录音,声道分离

public class AudioRecoderUtils {
    String TAG = "AudioRecoder";
    private boolean isRecording = false;
    private boolean isPlay = false;

    byte[] mBuffer = new byte[10485760];
    Handler mHandler = new Handler(Looper.myLooper()) {
    };
    static int mBufferCount = 0;
    AudioRecord audioRecord;
    AudioTrack mAudioTrack;
    //16K采集率
    int frequency = 16000;
    //录音通道--立体音录音
    int channel = AudioFormat.CHANNEL_IN_STEREO;
    //16Bit
    int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
    AudioManager mAudioManager;

    public AudioRecoderUtils() {

    }

    public boolean getPlay(){
        return isPlay;
    }

    //停止录音
    public void StopRecord() {
        isRecording = false;
        if(audioRecord != null){
            audioRecord.release();
        }
    }

    private AudioManager.OnAudioFocusChangeListener mAudioFocusChange = new AudioManager.OnAudioFocusChangeListener() {
        @Override
        public void onAudioFocusChange(int focusChange) {
            switch (focusChange) {
                case AudioManager.AUDIOFOCUS_LOSS:
                    break;
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                    break;
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                    break;
                case AudioManager.AUDIOFOCUS_GAIN:
                    //start();
                    break;
            }
        }
    };

    //申请音频焦点
    private void beforePlay(Context context) {
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        mAudioManager.requestAudioFocus(mAudioFocusChange, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
    }

    //退出释放
    public void releaseAudioManager(){
        if (audioRecord != null) {
            audioRecord.release();
        }
        if (mAudioTrack != null) {
            mAudioTrack.release();
        }
        if(mAudioManager != null){
            mAudioManager.abandonAudioFocus(mAudioFocusChange);
        }
    }

    //开始录音
    public void StartRecord(Context context) {
        new Thread(new Runnable() {
            @SuppressLint("MissingPermission")
            public void run() {
                mBufferCount = 0;
                isPlay = false;
                beforePlay(context);
                int bufferSize = AudioRecord.getMinBufferSize(frequency, channel, audioEncoding);
                if (audioRecord != null) {
                    audioRecord.release();
                }
                long count = 0;
                long start = System.currentTimeMillis();
                audioRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_PERFORMANCE, frequency,channel, audioEncoding, bufferSize);
                isRecording = true;
                audioRecord.startRecording();
                while (isRecording) {
                    int n = audioRecord.read(mBuffer, mBufferCount, 12000);
                    if (n > 0) {
                        mBufferCount += n;
                        long cc = Math.round(((double) (System.currentTimeMillis() - start)) / 1000.0d);
                        if (cc != count) {
                            count = cc;
                        }
                    } else if (n < 0) {

                    }
                }
            }
        }).start();
        new Thread(new Runnable() {
            public void run() {
                savePCM(mBuffer, mBufferCount, "stereo.pcm");
            }
        }).start();
    }
    /**
     //播放音频 --- 在这里把主副MIC录制的数据单独提取出来,因为是用的CHANNEL_IN_STEREO,
     //注意,因为把数据区分出来了所以在new AudioTrack的时候要用CHANNEL_IN_MONO单通道播放
     //如果要播放录制的原音可以就要用CHANNEL_IN_STEREO,直接用
     //mAudioTrack.write(mBuffer, 0, mBufferCount);
     //  mAudioTrack.play();
     */
    public void SaveRecord(Context context){

            new Thread(new Runnable() {
                public void run() {
                    byte[] bsleft = new byte[(mBufferCount / 2)];
                    int i = 0;
                    while (i < mBufferCount - 1 && (i / 2) + 1 < mBufferCount / 2) {
                        bsleft[i / 2] = mBuffer[i];
                        bsleft[(i / 2) + 1] = mBuffer[i + 1];
                        i += 4;
                    }
                    savePCM(bsleft, bsleft.length, "left.pcm");
                    byte[] bsright = new byte[(mBufferCount / 2)];
                    int j = 2;
                    while (j < mBufferCount - 1 && (j / 2) + 1 < mBufferCount / 2) {
                        bsright[(j / 2) - 1] = mBuffer[j];
                        bsright[j / 2] = mBuffer[j + 1];
                        bsright[(j / 2) + 1] = 0;
                        j += 4;
                    }
                    savePCM(bsright, bsright.length, "right.pcm");

                }

            }).start();
        Toast.makeText(context,"成功",Toast.LENGTH_LONG).show();

    }
    public void PlayRecord(boolean isLeft) {
        if (mAudioTrack != null) {
            mAudioTrack.release();
        }
        isPlay = true;
        mAudioTrack = new AudioTrack(3, 16000, 4, 2, mBuffer.length, 0);
        if (isLeft) {
            new Thread(new Runnable() {
                public void run() {
                    byte[] bsleft = new byte[(mBufferCount / 2)];
                    int i = 0;
                    while (i < mBufferCount - 1 && (i / 2) + 1 < mBufferCount / 2) {
                        bsleft[i / 2] = mBuffer[i];
                        bsleft[(i / 2) + 1] = mBuffer[i + 1];
                        i += 4;
                    }
                    savePCM(bsleft, bsleft.length, "left.pcm");
                    if (mAudioTrack != null) {
                        try {
                            mAudioTrack.write(bsleft, 0, bsleft.length);
                            mAudioTrack.play();
                        } catch (Exception e) {
                            isPlay = false;
                        }
                    } else {
                        isPlay = false;
                    }
                }
            }).start();
        } else {
            new Thread(new Runnable() {
                public void run() {
                    byte[] bsright = new byte[(mBufferCount / 2)];
                    int j = 2;
                    while (j < mBufferCount - 1 && (j / 2) + 1 < mBufferCount / 2) {
                        bsright[(j / 2) - 1] = mBuffer[j];
                        bsright[j / 2] = mBuffer[j + 1];
                        bsright[(j / 2) + 1] = 0;
                        j += 4;
                    }
                    savePCM(bsright, bsright.length, "right.pcm");
                    if (mAudioTrack != null) {
                        try {
                            mAudioTrack.write(bsright, 0, bsright.length);
                            mAudioTrack.play();
                        } catch (Exception e) {
                        }
                    } else {
                    }
                }
            }).start();
        }

    }

    //把录制的音频以PCM的格式写入存储里面
    public String savePCM(byte[] data, int count, String name) {
        Log.d(TAG, "开始写入 count = " + count);
        String str = null;
        if (count <= 0) {
            return str;
        }
        try {

            File fout = new File(getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS) + "/" + name);
            OutputStream out = new FileOutputStream(fout);
            out.write(data, 0, count);
            out.close();
            Log.d(TAG, "写入成功");
            return fout.getAbsolutePath();
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "写入失败");
            return str;
        }
    }

}

GitHub地址 下载前给star

标签:麦克风,mBuffer,录制,mAudioTrack,mBufferCount,new,Android,public,bsright
From: https://www.cnblogs.com/Frank-dev-blog/p/16828261.html

相关文章

  • Android使用AccessibilityService
    介绍AccessibilityService设计初衷在于帮助残障用户使用android设备和应用,在后台运行,可以监听用户界面的一些状态转换,例如页面切换、焦点改变、通知、Toast等,并在触发Acc......
  • android实现第一次打开应用的介绍页面
    效果图    添加依赖implementation'com.github.AppIntro:AppIntro:6.2.0'dependencyResolutionManagement{repositoriesMode.set(RepositoriesMo......
  • Android Studio报错:Error:Execution failed for task':app:mergeDebugResources'
    Build失败,原因是我添加的图片不符合AndroidStudio的审核要求,添加两行代码,禁用审核在app目录下的build.gradle中的android{...}增加配置android{.......aaptOptions.crun......
  • Android 渠道包生成
    目前看到了两家打包实现:美团腾讯VasDolly前言其实本文大部分资料都来自github和google,如何有兴趣的读者,可以直接阅读官方文档~什么是GradleAndroid构建系统编译应......
  • Android Studio Gradle 输出信息乱码
    AndroidStudioGradle输出信息出现乱码如下:>Task:app:compileDebugJavaWithJavacע:ijЩ�����ļ�ʹ�û......
  • Android Kotlin 导入 Protobuf
    projectbuild.gradleplugins{id"com.google.protobuf"version"0.9.1"applyfalse}modulebuild.gradleandroid{sourceSets{main{......
  • Android Gradle 导入 Kotlin gRPC
    projectbuild.gradleplugins{id"com.google.protobuf"version"0.9.1"applyfalse}modulebuild.gradleandroid{sourceSets{main{......
  • 直播带货源码,如何用Android Studio实现登录跳转
    直播带货源码,如何用AndroidStudio实现登录跳转一、基本要求实现一个简单的用户登录界面,功能如下: 1、默认不存储用户信息,默认隐藏密码。 2、能通过勾选框记住密码......
  • Android发送通知支持安卓11
    上代码privatefinalstaticStringNOTIFICATION_CHANNEL_ID="1001";privatefinalstaticStringNOTIFICATION_CHANNEL_NAME="Service";privateNotificationMana......
  • Android实现GPS定位,不用SDK
    权限<uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION"/><uses-permissionandroid:name="android.permission.ACCESS_COARSE_LOCATI......