unity3D学习之音频播放 、实时变声简化版-audio菜鸟笔记5

这是基于soundtouch写的一个实时变声的C#脚本,因为是调试版,所以可能会有BUG


核心代码:

private void OnAudioFilterRead(float[] data, int channels)
    {
        if (isRecording)
        {
            //根据data,一段段处理变声
            soundTouch.PutSamples(data, data.Length);
            float[] tempsample_after = new float[data.Length];
            soundTouch.ReceiveSamples(tempsample_after, data.Length);
            for (int i = 0; i < data.Length; i++)
            {
                data[i] = tempsample_after[i];
            }
        }
    }

关于OnAudioFilterRead的问题,有兴趣的同学可以去看看它的API,我在这里就不多说了


下面直接代码:

using SoundTouch;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;

#if SOUNDTOUCH_INTEGER_SAMPLES
using TSampleType = System.Int16;
using TLongSampleType = System.Int64;
#else
using TSampleType = System.Single;
using TLongSampleType = System.Double;
#endif

public class ClipChangeTest : MonoBehaviour {

    public AudioSource audioSource;
    //滑动条
    public Slider slider1;
    public Slider slider2;
    public Slider slider3;
    //输入框
    public InputField inputField1;
    public InputField inputField2;
    public InputField inputField3;
    public InputField inputField_modelName;

    private float tmpTempo;
    private float tmpPitch;
    private float tmpRate;
    private float temp_ischange1;
    private float temp_ischange2;
    private bool isRecording = false;
    private bool isChange_pitch = false;
    SoundTouch soundTouch = new SoundTouch();

    // Use this for initialization
    void Start ()
    {
        slider1.minValue = -12f;
        slider1.maxValue = 12f;
        slider2.minValue = 0f;
        slider2.maxValue = 6f;
        slider3.minValue = 0f;
        slider3.maxValue = 6f;
        slider1.value = 0f;
        slider2.value = 1f;
        slider3.value = 1f;
    }
	
	// Update is called once per frame
	void Update () {
        if (!isChange_pitch)
        {
            if (slider3.value != temp_ischange2)
            {
                slider2.value = 1f / slider3.value;
                temp_ischange1 = slider2.value;
                temp_ischange2 = slider3.value;
            }
            else if (slider2.value != temp_ischange1)
            {
                slider3.value = 1f / slider2.value;
                temp_ischange1 = slider2.value;
                temp_ischange2 = slider3.value;
            }
            if (inputField1.isFocused)
            {
                slider1.value = float.Parse(inputField1.text);
            }
            else if(inputField2.isFocused)
            {
                slider2.value = float.Parse(inputField2.text);
            }
            else if (inputField3.isFocused)
            {
                slider3.value = float.Parse(inputField3.text);
            }
            else
            {
                inputField1.text = slider1.value.ToString();
                inputField2.text = slider2.value.ToString();
                inputField3.text = slider3.value.ToString();
            }
            tmpPitch = slider1.value;
            tmpTempo = slider2.value;
            tmpRate = slider3.value;
        }
    }

    public void Mic_test()
    {
        if (Microphone.devices.Length == 0)
        {
            Debug.LogWarning("找不到麦克风!");
        }
        Microphone.End(null);
        audioSource.clip = Microphone.Start(null, false, 100, 44100);

        //实时变声调整(初始化)
        isChange_pitch = true;
        soundTouch.SetTempo(tmpTempo);
        soundTouch.SetPitchSemiTones(tmpPitch);//噪音相对大一点
        soundTouch.SetRate(tmpRate);
        soundTouch.SetSampleRate(44100);
        soundTouch.SetChannels(1);
        soundTouch.SetSetting(SettingId.UseQuickseek, 0);
        soundTouch.SetSetting(SettingId.UseAntiAliasFilter, 0);
        soundTouch.SetSetting(SettingId.SequenceDurationMs, 40);
        soundTouch.SetSetting(SettingId.SeekwindowDurationMs, 15);
        soundTouch.SetSetting(SettingId.OverlapDurationMs, 8);

        isRecording = true;
        while (Microphone.GetPosition(null) <= 0) { }
        audioSource.Play();
    }
    
    //保存声音
    public void Save_test()
    {
        soundTouch.Flush();
        float[] saveClip_befor = new float[audioSource.timeSamples];
        audioSource.Stop();
        audioSource.clip.GetData(saveClip_befor, 0);

        //变声处理
        soundTouch.SetTempo(tmpTempo);
        soundTouch.SetPitchSemiTones(tmpPitch);
        soundTouch.SetRate(tmpRate);
        soundTouch.SetSampleRate(44100);
        soundTouch.SetChannels(1);
        soundTouch.SetSetting(SettingId.UseQuickseek, 0);
        soundTouch.SetSetting(SettingId.UseAntiAliasFilter, 0);
        soundTouch.SetSetting(SettingId.SequenceDurationMs, 40);
        soundTouch.SetSetting(SettingId.SeekwindowDurationMs, 15);
        soundTouch.SetSetting(SettingId.OverlapDurationMs, 8);
        soundTouch.PutSamples(saveClip_befor, saveClip_befor.Length);

        //获取变声后的数据并保存
        float[] saveClip_after = new float[saveClip_befor.Length];
        soundTouch.ReceiveSamples(saveClip_after, saveClip_befor.Length);
        soundTouch.Flush();
        audioSource.clip = AudioClip.Create("changedClip", saveClip_befor.Length, 1, 44100,false);
        audioSource.clip.SetData(saveClip_after, 0);
        SavWav.Save("test1", audioSource.clip);
        isChange_pitch = false;
    }

    //实时变声
    private void OnAudioFilterRead(float[] data, int channels)
    {
        if (isRecording)
        {
            //根据data,一段段处理变声
            soundTouch.PutSamples(data, data.Length);
            float[] tempsample_after = new float[data.Length];
            soundTouch.ReceiveSamples(tempsample_after, data.Length);
            for (int i = 0; i < data.Length; i++)
            {
                data[i] = tempsample_after[i];
            }
        }
    }

    //控制录音时是否有声音
    public void ChangeController()
    {
        if (audioSource.volume == 0)
        {
            audioSource.volume = 1;
        }
        else
        {
            audioSource.volume = 0;
        }
        
    }

    //测试所用
    //回放
    public void replay()
    {
        isChange_pitch = false;
        isRecording = true;
        //实时变声调整(初始化)
        soundTouch.SetTempo(tmpTempo);
        soundTouch.SetPitchSemiTones(tmpPitch);//噪音相对大一点
        soundTouch.SetRate(tmpRate);
        soundTouch.SetSampleRate(44100);
        soundTouch.SetChannels(1);
        soundTouch.SetSetting(SettingId.UseQuickseek, 0);
        soundTouch.SetSetting(SettingId.UseAntiAliasFilter, 0);
        soundTouch.SetSetting(SettingId.SequenceDurationMs, 40);
        soundTouch.SetSetting(SettingId.SeekwindowDurationMs, 15);
        soundTouch.SetSetting(SettingId.OverlapDurationMs, 8);
        audioSource.Play();
    }

    //保存不同的音色
    public void Save_changedata()
    {
        if (!File.Exists(Application.dataPath + "/Assets/Resources/speech_model.txt"))
        {
            File.Create(Application.dataPath + "/Assets/Resources/speech_model.txt");
            Debug.LogWarning("创建文件");
        }
        FileStream fileStream = new FileStream(Application.dataPath + "/Assets/Resources/speech_model.txt",FileMode.Append);
        StreamWriter streamWriter = new StreamWriter(fileStream);
        streamWriter.Write(inputField_modelName.text + ": ");
        streamWriter.Write(" pitch:" + tmpPitch);
        streamWriter.Write(" tempo:" + tmpTempo);
        streamWriter.Write(" rate:" + tmpRate);
        streamWriter.WriteLine();
        streamWriter.Close();
        Debug.Log("保存音色数据成功!");
    }

}


  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
蓝牙核心规范(v5.4)11.1-le audio 笔记是蓝牙技术在音频传输领域的重要突破,它为音频设备之间的无线通信提供了更好的解决方案。要了解其诞生的前世今生,需要从蓝牙技术的发展历程和音频传输的需求出发。 蓝牙技术最初是由瑞典的爱立信公司于1994年提出的,主要用于在移动设备之间进行短距离的无线通信。起初,蓝牙技术主要应用于数据传输,例如手机与耳机之间的通信。随着技术的不断进步,人们对音频传输的需求越来越大,这促使了蓝牙技术在音频领域的拓展。 在过去的本中,蓝牙技术在音频传输上还存在一些问题,如传输质量不稳定、延迟较高等。为了解决这些问题,蓝牙核心规范(v5.4)11.1-le audio 笔记于20xx年发布,它是蓝牙技术在音频传输上的一次重要突破。 11.1-le audio 是指针对低功耗设备的音频传输规范。它采用了新的音频编解码算法和协议,能够在保证音质的同时,降低能耗和延迟。这使得蓝牙设备可以更好地支持高品质音频的传输,例如无线耳机、扬声器和音响等。 此外,11.1-le audio 还具备一些其他的优势。它支持多路音频传输,可以同时连接多个音频设备,实现多播功能。同时,它还具备较高的兼容性,可以与之前本的蓝牙技术进行互操作。 总的来说,蓝牙核心规范(v5.4)11.1-le audio 笔记的诞生是蓝牙技术在音频传输领域的一次重要进步。它解决了以往本在音质、能耗和兼容性等方面的不足,并且为音频设备之间的无线通信提供了更好的解决方案。作为蓝牙技术的一个重要分支,它对于无线音频设备的发展和普及具有积极的推动作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值