SaveWav
2017-11-27 本文已影响23人
萧非子
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
using System.Collections;
//保存Wave文件在本地
public class SaveWav
{
public static string filePath;
public static void Save(string fileName,AudioClip clip)
{
if (!fileName.ToLower().EndsWith(".wav"))//文件小写。
{
fileName += ".wav";
}
//保存的文件为系统临时文件
filePath = Path.Combine(Application.persistentDataPath,fileName);
Debug.Log(filePath);
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
//1.创建空头,44个空字节
FileStream fs = CreateEmpty(filePath);
//2.写语音数据
ConvertAndWrite(fs,clip);
//3.重写真正的文件头
WriteHeader(fs,clip);
}
//创建头
static FileStream CreateEmpty(string filepath)
{
var fileStream = new FileStream(filepath,FileMode.Create);
byte emptyByte = new byte();
for (int i = 0; i < 44; i++)//文件头,wav头有44个字节
{
fileStream.WriteByte(emptyByte);
}
return fileStream;
}
//写语音数据,转换float-int
static void ConvertAndWrite(FileStream fileStream, AudioClip clip)
{
var samples = new float[clip.samples];//采样值,多少个采样值
clip.GetData(samples,0);//从头0开始
Int16[] intData = new Int16[samples.Length];
Byte[] bytesData = new Byte[samples.Length*2];//一个int=2个byte;
int rescaleFactor = 32767;//int最大值
for (int i = 0; i < samples.Length; i++)//float转int ,转 byte
{
intData[i] = (short)(samples[i] * rescaleFactor);
Byte[] byteArray = new Byte[2];
byteArray = BitConverter.GetBytes(intData[i]);
byteArray.CopyTo(bytesData,i*2);
}
fileStream.Write(bytesData, 0, bytesData.Length);
}
//写头文件
static void WriteHeader(FileStream fileStream, AudioClip clip)
{
var hz = clip.frequency;
var channels = clip.channels;
var samples = clip.samples;
fileStream.Seek(0,SeekOrigin.Begin);
Byte[] riff = Encoding.UTF8.GetBytes("RIFF");//资源交换文件标志(RIFF)
fileStream.Write(riff,0,4);
Byte[] chunkSize = BitConverter.GetBytes(fileStream.Length-8);//从下个地址开始到文件尾的总字节数
fileStream.Write(chunkSize,0,4);
Byte[] wave = Encoding.UTF8.GetBytes("WAVE");//WAV文件标志(WAVE)
fileStream.Write(wave, 0, 4);
Byte[] fmt = Encoding.UTF8.GetBytes("fmt ");//波形格式标志(fmt ),最后一位空格。
fileStream.Write(fmt, 0, 4);
Byte[] subChunk1 = BitConverter.GetBytes(16);//过滤字节(一般为00000010H)
fileStream.Write(subChunk1, 0, 4);
Byte[] audioFormat = BitConverter.GetBytes(1);//格式种类(值为1时,表示数据为线性PCM编码)
fileStream.Write(audioFormat, 0, 2);
Byte[] numChannels = BitConverter.GetBytes(channels);//通道数,单声道为1,双声道为2
fileStream.Write(numChannels, 0, 2);
Byte[] sampleRate = BitConverter.GetBytes(hz);//采样频率
fileStream.Write(sampleRate, 0, 4);
Byte[] bytRate = BitConverter.GetBytes(hz*channels*2);//波形数据传输速率(每秒平均字节数)
fileStream.Write(bytRate, 0, 4);
UInt16 blockAlign = (ushort)(channels*2);//DATA数据块长度,字节。
fileStream.Write(BitConverter.GetBytes(blockAlign), 0, 2);
UInt16 bps = 16;//PCM位宽
Byte[] bitsPerSample = BitConverter.GetBytes(bps);
fileStream.Write(bitsPerSample, 0, 2);
Byte[] dataString = Encoding.UTF8.GetBytes("data");//"fact",该部分一下是可选部分,即可能有,可能没有,一般到WAV文件由某些软件转换而成时,包含这部分。
fileStream.Write(dataString, 0, 4);
Byte[] subChunk2 = BitConverter.GetBytes(samples*channels*2);//size,数值为4
fileStream.Write(subChunk2, 0, 4);
//UnityEditor.AssetDatabase.Refresh();//刷新,使刚创建的mp3立刻导入。接下来才可以被使用
}
}