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("保存音色数据成功!");
    }

}
unity3D学习之音频播放 、实时变声简化版-audio菜鸟笔记5_第1张图片
项目下载链接: http://download.csdn.net/download/weifut/9966784

你可能感兴趣的:(音频操作)