SaveWav

作者: 萧非子 | 来源:发表于2017-11-27 18:11 被阅读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立刻导入。接下来才可以被使用

    }
    

    }

    相关文章

      网友评论

          本文标题:SaveWav

          本文链接:https://www.haomeiwen.com/subject/ndwdbxtx.html