要想将 AudioClip 转成 MP3 文件,需要从Unity资源商店中下载 Save AudioClip to MP3 插件。Lame-For-Unity
如果要打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;
}
}
}