当前位置:   article > 正文

【Audio】Unity音频模块:加载、转换、剪切、混音、合并_unity audioclip截取一部分

unity audioclip截取一部分

GitHub项目:Epitome.Audio音频模块

WWW类外部加载音乐文件

使用delegate委托:音频加载完成进行回调

namespace Epitome
{
    public delegate void AudioClipLoadFinish(AudioClip clip);

    public static class AudioLoad
    {
        public static IEnumerator Load(string url, AudioClipLoadFinish finish)
        {
            WWW www = new WWW("file://" + url);
            yield return www;
            finish(www.GetAudioClip());
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

使用案列:

public AudioSource accompany;

private void Start()
{
	// 加载音频
	StartCoroutine(AudioLoad.Load("filepath", AudioClipLoadFinish));
}
    
public void AudioClipLoadFinish(AudioClip clip)
{
	accompany.clip = clip;
	accompany.Paly();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

NAudio介绍

NAudio是Mark Heath编写的开源.NET音频库
GitHub:NAudio项目
NAudio是个相对成熟、开源的C#音频开发工具,它包含录音、播放录音、格式转换、混音调整等功能。

基于NAudio音频文件格式转换

namespace Epitome
{
    public static class AudioConverter
    {
        /// <summary>
        /// MP3文件转WAV文件
        /// </summary>
        /// <param name="filePath">MP3文件读取路径</param>
        /// <param name="savePath">WAV文件保存路径</param>
        public static void MP3TurnWAV(string filePath, string savePath)
        {
            using (FileStream stream = File.Open(filePath, FileMode.Open))
            {
                Mp3FileReader reader = new Mp3FileReader(stream);
                WaveFileWriter.CreateWaveFile(savePath, reader);
            }
        }

        public static void MP3TurnWAV(string filePath, string savePath, List<string> fileNames)
        {
            List<string> strs = Project.DirectoryAllFileNames(filePath, new List<string>() { "mp3" });

            if (strs != null)
            {
                string targetFilePath, saveFilePath;
                for (int j = 0; j < strs.Count; j++)
                {
                    targetFilePath = filePath + "/" + strs[j];
                    saveFilePath = savePath + "/" + strs[j].Substring(0, strs[j].Length - 3) + "wav";
                    MP3TurnWAV(targetFilePath, saveFilePath);
                }
#if UNITY_EDITOR
                AssetDatabase.Refresh();
#endif
            }
        }
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

使用案列:
EditorExtension.GetSelectionPath:获取编辑器选择的目标路径,获取该路径下的MP3音频文件
通过拼接音频文件路径,调用MP3TurnWAV生成WAV音频文件

/// <summary>
/// MP3文件转WAV文件
/// </summary>
[MenuItem("Epitome/Audio/MP3TurnWAV")]
[MenuItem("Assets/Epitome/Audio/MP3TurnWAV")]
private static void MP3TurnWAV()
{
    List<string> paths = EditorExtension.GetSelectionPath();
    for (int i = 0; i < paths.Count; i++)
    {
        if (Directory.Exists(paths[i]))
        {
            string rootPath = ProjectPath.GetDataPath.Substring(0, ProjectPath.GetDataPath.Length - 6);

            DirectoryInfo info = new DirectoryInfo(rootPath + paths[i]);

            string savePath = info.FullName + "_WAV";

            Project.CreateDirectory(savePath);

            List<string> strs = Project.DirectoryAllFileNames(info.FullName, new List<string>() { "mp3" });

            AudioConverter.MP3TurnWAV(info.FullName, savePath, strs);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

音频剪切

/// <summary>
/// 剪切空白部分
/// </summary>
public static AudioClip CutBlankSection(AudioClip audioClip, int time, int samplingRate)
{
    float[] samples_one = new float[audioClip.samples];

    audioClip.GetData(samples_one, 0);

    float[] samples_two = new float[time * samplingRate];

    Array.Copy(samples_one, 0, samples_two, 0, time * samplingRate);

    AudioClip newAudioClip = AudioClip.Create(audioClip.name, samplingRate * time, 1, samplingRate, false);
    newAudioClip.SetData(samples_two, 0);

    return newAudioClip;
}

audioLength//秒单位
frequency = 44100;
AudioClip audioClip = AudioClips.CutBlankSection(recording.clip, audioLength, frequency);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

基于NAudio音频剪切

/// <summary>
/// 修剪Wav文件
/// </summary>
/// <param name="filePath">修剪文件路径</param>
/// <param name="savePath">保存文件路径</param>
/// <param name="cutFromStart">开始间隔</param>
/// <param name="cutFromEnd">结束间隔</param>
public static void TrimWavFile(string filePath, string savePath, TimeSpan cutFromStart, TimeSpan cutFromEnd)
{
    using (WaveFileReader reader = new WaveFileReader(filePath))
    {
        using (WaveFileWriter writer = new WaveFileWriter(savePath, reader.WaveFormat))
        {
            int bytesPerMillisecond = reader.WaveFormat.AverageBytesPerSecond / 1000;

            int startPos = (int)cutFromStart.TotalMilliseconds * bytesPerMillisecond;
            startPos = startPos - startPos % reader.WaveFormat.BlockAlign;

            int endBytes = (int)cutFromEnd.TotalMilliseconds * bytesPerMillisecond;
            endBytes = endBytes - endBytes % reader.WaveFormat.BlockAlign;
            int endPos = (int)reader.Length - endBytes;

            TrimWavFile(reader, writer, startPos, endPos);
        }
    }
}

/// <summary>
/// 修剪Wav文件
/// </summary>
private static void TrimWavFile(WaveFileReader reader, WaveFileWriter writer, int startPos, int endPos)
{
    reader.Position = startPos;
    byte[] buffer = new byte[1024];
    while (reader.Position < endPos)
    {
        int bytesRequired = (int)(endPos - reader.Position);
        if (bytesRequired > 0)
        {
            int bytesToRead = Math.Min(bytesRequired, buffer.Length);
            int bytesRead = reader.Read(buffer, 0, bytesToRead);
            if (bytesRead > 0)
            {
                writer.Write(buffer, 0, bytesRead);
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

基于NAudio音频混合(混音)

namespace Epitome
{
    public static class AudioMixer
    {
        /// <summary>
        /// 音频混合(混音)
        /// </summary>
        /// <param name="filePath1">音频文件路径</param>
        /// <param name="filePath2">音频文件路径</param>
        /// <param name="mixedPath">混合音频文件路径</param>
        public static void AudioMixing(string filePath1, string filePath2,string mixedPath)
        {
            using (var reader1 = new AudioFileReader(filePath1))
            using (var reader2 = new AudioFileReader(filePath2))
            {
                var mixer = new MixingSampleProvider(new[] { reader1, reader2 });
                WaveFileWriter.CreateWaveFile16(mixedPath, mixer);
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

使用案列:

// 伴奏混合原声
AudioMixer.AudioMixing(accompanyClipPath, originalPath, finalPath);
  • 1
  • 2

音频合并

/// <summary>
/// 合并音频
/// </summary>
public static AudioClip MergeAudio(int interval, params AudioClip[] clips)
{
    if (clips == null || clips.Length == 0)
        return null;

    int channels = clips[0].channels;
    int frequency = clips[0].frequency;

    using (MemoryStream memoryStream = new MemoryStream())
    {
        for (int i = 0; i < clips.Length; i++)
        {
            if (clips[i] == null)
                continue;

            clips[i].LoadAudioData();

            var buffer = clips[i].GetData();

            memoryStream.Write(buffer, 0, buffer.Length);

            if (clips.Length - 1 == i)
                continue;

            byte[] byteClips = new byte[clips[i].frequency * clips[i].channels * 4 * interval];//合并音频间的间隔
            memoryStream.Write(byteClips, 0, byteClips.Length);
        }

        var bytes = memoryStream.ToArray();

        var result = AudioClip.Create("Merge", bytes.Length / 4 / channels, channels, 44100, false);

        result.SetData(bytes);

        return result;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/127044
推荐阅读
相关标签
  

闽ICP备14008679号