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立刻导入。接下来才可以被使用

}

}

上一篇下一篇

猜你喜欢

热点阅读