【音乐拼接】WAV格式

预备知识

必备基础知识

用4个字节 表示一个整数
每个字节8位 字节可以用无符号整数(十进制)来表示(0-255) 
假设有如下4个字节
194 021 001 000
分别转换成16进制为
C2 15 01 00
高位在前 于是如下
15C2 0001
再转 如下
000115C2   (这个就是4字节表示的整数对应的16进制)
转成10进制如下
71106

======================================================================================开始 真正内容
wav文件 = 文件头 + 数据体

文件头  44个字节

前12个字节用来说明文件是哪种类型 (如下字节)

082 073 070 070 202 043 000 000 087 065 086 069   ------ a.wav
082 073 070 070 234 046 000 000 087 065 086 069   ------ b.wav
082 073 070 070 120 048 000 000 087 065 086 069   ------ c.wav
082 073 070 070 194 021 001 000 087 065 086 069   ------ d.wav

这12个字节里面第5-8个字节是不一样的,其他一样,这四个字节就表示一个整数,该整数为:从下一个地址开始到文件尾的总字节数。
也就是说,前8个字节加上该整数就等于本wav文件总字节数,不信可以自己算算,百发百中。。。

剩下 32 个字节分为两个部分。
12-35  字节用来说明文件结构
36-43  字节用来说明数据大小
44到最后就是数据体

刚才分析到前12个字节,继续
13-16字节   表示 fmt ,波形格式标志

102 109 116 032   ------ a.wav
102 109 116 032   ------ b.wav
102 109 116 032   ------ c.wav
102 109 116 032   ------ d.wav
可以看到都一样

17-20字节  过滤字节(一般为00000010H)
016 000 000 000   ------ a.wav
016 000 000 000   ------ b.wav
016 000 000 000   ------ c.wav
016 000 000 000   ------ d.wav
可以看到都一样

21-22字节  整数 格式种类(值为1时,表示数据为线性PCM编码)
001 000   ------ a.wav
001 000   ------ b.wav
001 000   ------ c.wav
001 000   ------ d.wav
也是一样

23-24字节  整数 通道数,单声道为1,双声道为2
001 000   ------ a.wav
001 000   ------ b.wav
001 000   ------ c.wav
001 000   ------ d.wav
表示都是单声道,特意用格式工厂转了一个2声道的,变成 002 000 正确

25-28  采样频率
034 086 000 000  ------ a.wav   十进制 22050
034 086 000 000  ------ b.wav   十进制 22050
034 086 000 000  ------ c.wav   十进制 22050
034 086 000 000  ------ d.wav   十进制 22050
4个文件都一样

29-32  每次采样的数据块大小  它跟下面的采样精度有关
034 086 000 000  ------ a.wav   十进制 22050
034 086 000 000  ------ b.wav   十进制 22050
034 086 000 000  ------ c.wav   十进制 22050
068 172 000 000  ------ d.wav   十进制 44100
注意不同的地方

33-34  整数  它 = 通道数 * 采样精度 / 8
001 000  ------ a.wav
001 000  ------ b.wav
001 000  ------ c.wav
002 000  ------ d.wav

35-36 整数   采样精度是多少位
008 000  ------ a.wav    8位
008 000  ------ b.wav    8位
008 000  ------ c.wav    8位
016 000  ------ d.wav    16位

37-40  表示“data”或者“LIST”四个字符,data表示单个音乐,LIST表示合成?或许是这样,因为我的d.wav 是在格式工厂里用 abc合成的
100 097 116 097   ------ a.wav
100 097 116 097   ------ b.wav
100 097 116 097   ------ c.wav
076 073 083 084   ------ d.wav

41-44  整数  数据体长度(字节数)

166 043 000 000   ------ a.wav    十进制11174  已检验正确
197 046 000 000   ------ b.wav    十进制11973  已检验差一个字节  基本正确
083 048 000 000   ------ c.wav    十进制12371  已检验差一个字节  基本正确
026 000 000 000   ------ d.wav    十进制26     严重错误  格式工厂转换问题


程序代码

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Wav
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> ls = new List<string> {
                @"C:\Users\Administrator\Desktop\b.wav",
                @"C:\Users\Administrator\Desktop\c.wav",
                @"C:\Users\Administrator\Desktop\a.wav",
                @"C:\Users\Administrator\Desktop\out.wav"
            };
            Get_wav(ls);
        }
        static void Get_wav(List<string> l)
        {
            List<string> ls = l;
            int n = ls.Count;
            byte[] OUT = File_2_byte(ls[0]);
            for (int i = 0; i < n; i++)
            {
                if (i == n - 2)
                {
                    using (StreamWriter sw = new StreamWriter(ls[i + 1], false, Encoding.GetEncoding(1252)))
                    {
                        sw.Write(Encoding.GetEncoding(1252).GetString(OUT));
                    }
                    return;
                }
                byte[] tmp = File_2_byte(ls[i + 1]);
                OUT = Save_Wav(OUT, tmp);
            }
        }
        static byte[] File_2_byte(string url)
        {
            long l = new FileInfo(url).Length;
            byte[] b = new byte[l];
            new FileStream(url, FileMode.Open).Read(b, 0, (int)l);
            return b;
        }
        static byte[] Save_Wav(byte[] buffer1, byte[] buffer2)
        {
            long len1 = buffer1.Length;
            long len2 = buffer2.Length;

            byte[] Head1 = Get_small_byte(buffer1, 0, 44);
            byte[] Head2 = Get_small_byte(buffer2, 0, 44);
            byte[] Data1 = Get_small_byte(buffer1, 44, len1);
            byte[] Data2 = Get_small_byte(buffer2, 44, len2);
            byte[] DATA = Combine_2_byte(Data1, Data2);

            long L = DATA.Length + 44;
            byte[] HEAD = new byte[44];
            Get_small_byte2(ref HEAD, 0, Head1, 0, 4);   //0-3
            Get_small_byte2(ref HEAD, 4, Get_4_byte(L - 8), 0, 4); //4-7
            Get_small_byte2(ref HEAD, 8, Head1, 8, 36);   //8-35
            Get_small_byte2(ref HEAD, 36, Head1, 36, 40);   //36-39
            Get_small_byte2(ref HEAD, 40, Get_4_byte(DATA.Length), 0, 4);   //40-43

            return Combine_2_byte(HEAD, DATA);
        }
        static byte[] Combine_2_byte(byte[] a , byte[] b)
        {
            long la = a.Length;
            long lb = b.Length;
            long lc = la + lb;
            byte[] c = new byte[lc];
            for(int i =0;i< la; i++)
            {
                c[i] = a[i];
            }
            for (int i = 0; i < lb; i++)
            {
                c[i+la] = b[i];
            }
            return c;
        }
        static byte[] Get_small_byte(byte[] a,long start,long end)//[start,end)
        {
            long la = a.Length;
            long lc = end - start;
            byte[] c = new byte[lc];
            for(long i = start;i< end; i++)
            {
                c[i - start] = a[i];
            }
            return c;
        }
        static void Get_small_byte2(ref byte[] HEAD, long f,byte[] a, long start, long end)
        {
            long la = a.Length;
            for (long i = start; i < end; i++)
            {
                HEAD[i - start + f] = a[i];
            }
        }
        static byte[] Get_4_byte(long a)
        {
            byte[] b = new byte[4];
            b = BitConverter.GetBytes((int)a);
            return b;
        }
    }
}



已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页