鸟语天空
将AudioClip保存为wav或mp3文件
post by:追风剑情 2024-6-5 18:10

要想将 AudioClip 转成 MP3 文件,需要从Unity资源商店中下载 Save AudioClip to MP3 插件。Lame-For-Unity

11111111.png

如果要打PC包,需要对源码做一点修改,如下:

//LibMp3Lame.cs
internal static class NativeMethods
{
#if UNITY_EDITOR

#if UNITY_EDITOR_OSX
    const string libname = @"__Internal";
#else
    const string libname = @"libmp3lame.dll";
#endif

#elif UNITY_IOS
    const string libname = @"__Internal";
#elif UNITY_ANDROID
    const string libname = @"mp3lame";
#elif UNITY_STANDALONE_WIN //添加Windows平台宏,否则打PC包会报找不到libmp3lame.dll
    const string libname = @"libmp3lame.dll";
#endif
	//省略......
}


工具类

using System;
using System.IO;
using NAudio.Lame;
using NAudio.Wave.WZT;
using UnityEngine;
using UNetwork;

/// <summary>
/// 音频剪辑转换器
/// </summary>
public static class AudioClipConverter
{
    /// <summary>
    /// AudioClip转Wav
    /// </summary>
    /// <param name="clip"></param>
    /// <returns></returns>
    public static byte[] AudioClipToWav(AudioClip clip)
    {
        var samples = new float[clip.samples];
        clip.GetData(samples, 0);

        short numChannels = (short)clip.channels;//通道数量
        int sampleRate = clip.frequency;//采样率
        short audioFormat = 1; //1:PCM
        short bitsPerSample = 16;//每次采样用多少比特存储
        int byteRate = sampleRate * numChannels * bitsPerSample / 8;//字节率
        short blockAlign = (short)(numChannels * bitsPerSample / 8);//块对齐
        int dataSize = samples.Length * 2;

        var memoryStream = new MemoryStream();
        var writer = new BinaryWriter(memoryStream);

        // RIFF chunk
        writer.Write("RIFF".ToCharArray());
        writer.Write(dataSize + 36); // File size
        writer.Write("WAVE".ToCharArray());

        // Format chunk
        writer.Write("fmt ".ToCharArray());
        writer.Write(16); // Size
        writer.Write(audioFormat); // Compression code
        writer.Write(numChannels); //Num channels
        writer.Write(sampleRate); // Sample rate
        writer.Write(byteRate); // Byte rate
        writer.Write(blockAlign); // Block align
        writer.Write(bitsPerSample); // Bits per sample

        // Data chunk
        writer.Write("data".ToCharArray());
        writer.Write(dataSize);

        for (var i = 0; i < samples.Length; i++)
        {
            //将采样值映射到[0, short.MaxValue]范围
            var sample = (int)(samples[i] * short.MaxValue);
            //以小端方式存储
            writer.Write((byte)(sample & 0xff));
            writer.Write((byte)((sample >> 8) & 0xff));
        }

        memoryStream.Position = 0;
        byte[] wavData = memoryStream.ToArray();

        writer.Close();
        memoryStream.Close();

        return wavData;
    }

    /// <summary>
    /// 将AudioClip保存为wav文件
    /// </summary>
    /// <param name="clip">要保存的AudioClip</param>
    /// <param name="path">保存路径</param>
    public static void SaveWav(AudioClip clip, string path)
    {
        byte[] bytes = AudioClipToWav(clip);

        var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);
        fileStream.Write(bytes);
        fileStream.Close();
    }

    /// <summary>
    /// 将AudioClip保存为MP3
    /// </summary>
    /// <param name="clip"></param>
    /// <param name="path"></param>
    public static void SaveMp3(AudioClip clip, string path)
    {
        var samples = new float[clip.samples * clip.channels];
        clip.GetData(samples, 0);

        //将音频数据写入内存流中
        var ms = new MemoryStream();
        for (var i = 0; i < samples.Length; i++)
        {
            //将采样值映射到[0, short.MaxValue]范围
            var sample = (int)(samples[i] * short.MaxValue);
            //以小端方式存储
            ms.WriteByte((byte)(sample & 0xff));
            ms.WriteByte((byte)((sample >> 8) & 0xff));
        }
        ms.Position = 0;

        short bitsPerSample = 16;//每次采样用多少比特存储
        short numChannels = (short)clip.channels;//通道数量
        int sampleRate = clip.frequency;//采样率

        //将内存流中的数据编码为MP3文件
        using (var writer = new LameMP3FileWriter(path, new WaveFormat(sampleRate, bitsPerSample, numChannels), LAMEPreset.ABR_128))
            ms.CopyTo(writer);

        ms.Flush();
        ms.Close();
    }

    public static string SaveFilePathWav
    {
        get
        {
            string path = string.Format("{0}/Audio", LogUtil.GetParentPath(Application.dataPath));
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
            string fileName = DateTime.Now.ToString("yyyyMMdd_HHmmss");
            string filePath = string.Format("{0}/{1}.wav", path, fileName);
            return filePath;
        }
    }

    public static string SaveFilePathMp3
    {
        get
        {
            string path = string.Format("{0}/Audio", LogUtil.GetParentPath(Application.dataPath));
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
            string fileName = DateTime.Now.ToString("yyyyMMdd_HHmmss");
            string filePath = string.Format("{0}/{1}.mp3", path, fileName);
            return filePath;
        }
    }
}
评论:
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容