zoukankan      html  css  js  c++  java
  • Unity 声音与录音与麦克风实时播放

    Unity AudioSource与MicroPhone以及AudioClip之间的关系。

    下面是一个声音,长度为7秒钟,声音的实际数据本质是由采样点组成的的列表,一秒钟内的采样点数就是采样频率,下面的采样频率是10,正常实际中是44100,根据需求设置;AudioSource播放声音时,设置其TimeSamples的意思就是从声音的第timeSamples个采样点位置开始播放,因此设置声音的播放的偏移位置的方式是设置timeSamples或者设置time。播放时timeSamples并不是一直固定的,跟随时间逐个指向每个对应的采样点的索引值。

    接下来是设置麦克风的,麦克风的原理就是首先定义一个Clip,开始录音之后,就不断的将录音采样点值赋予clip的相对应的采样点,这点和Audiosource的timeSamples相同,区别是两者的操作相反,当前采样点的位置可以用MicroPhone的GetPosition()获得。因此如果想要像KTV那样实时的播放录音,就是让audiosource播放的时候,timeSamples的值刚好等于当前采样点的值,或者延迟不大的一段采样点距离(好吧,我这么干了,可是不知道为什么噪音很严重,有待研究,并且timeSamples的值不能大于当前录音采样点的值,不然没有声音(傻瓜都能想到为什么))。好吧,今日附贴,与公司大佬讨论了一下之后终于明白了,原来噪音出现的原因是我播出来的声音又实时的被录进去了,从而出现类似回音的效果,所以最好戴上耳机录音。

    下面是实时播放的代码。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class MicroPhoneTest : MonoBehaviour
    {
        public AudioSource aud;
    
        bool isHaveMicroPhone;
        string device;
        public Text text;
    
        //Debug Text
        public Text clipLength;//记录音频文件的长度
        public Text devicePosition;//设备音频的位置
        public Text audioTime;//记录音频的时间
        public Text audioSampleTime;//
    
        
        // Start is called before the first frame update
        void Start()
        {
            aud = GetComponent<AudioSource>();
            string[] devices = Microphone.devices;
    
            if (devices.Length > 0)
            {
                isHaveMicroPhone = true;
                device = devices[0];
                text.text = devices[0];
            }
            else
            {
                isHaveMicroPhone = false;
                text.text = "没有获取到麦克风";
            }
        }
    
        //开始录音按钮
        public void OnclickButton()
        {
            if (!isHaveMicroPhone) return;
    
            aud.clip = Microphone.Start(device, true, 10, 10000);
            //aud.Play();
            //aud.timeSamples = Microphone.GetPosition(device);
            //aud.timeSamples = 0;
            Debug.Log("开始录音");
        }
    
        //开始播放按钮
        public void OnPlay()
        {
            aud.Play();
            aud.timeSamples = Microphone.GetPosition(device);//这里设置了之后就会近乎实时同步
    
            int min;
            int max;
            Microphone.GetDeviceCaps(device, out min,out max);
            //aud.timeSamples = 0;
            Debug.Log("开始播放"+min+" "+max);
        }
    
    
    
    
        private void Update()
        {
            //clipLength.text = "     clipLength:" + aud.clip.length;
            //devicePosition.text = " devicePosition:" + Microphone.GetPosition(device);
            //audioTime.text = "      audioTime:" + aud.time;
            //audioSampleTime.text = "audioSampleTime:" + aud.timeSamples;
    
            //Debug.Log("     clipLength:" + aud.clip.length);
            //Debug.Log(" devicePosition:" + Microphone.GetPosition(device));
            //Debug.Log("      audioTime:" + aud.time);
            //Debug.Log("audioSampleTime:" + aud.timeSamples);
    
            //aud.timeSamples = Microphone.GetPosition(device);
        }
    }

    注意,实时录音播放后,可能会出现播放的采样点与录音的采样点的值越来越大的问题,因此可能需要在update函数中每隔一段时间进行处理。

  • 相关阅读:
    APP之百度地图SDK的AK值获取(android)
    横向滚动菜单-选中标题居中显示
    函数按引用传参问题
    js验证提交
    Java servlet ajax
    数据库3种读
    mybatis插件
    mybatis 缓存
    从前端对象中获取的文本变为字符串,并替换其中一些指定的字符
    多个窗口开启后,切换到指定title的窗口
  • 原文地址:https://www.cnblogs.com/xiaoahui/p/11037671.html
Copyright © 2011-2022 走看看