用c# 随机数/函数 编写简单的.wav文件
.wav 文件主要由两部分组成:头文件 和 数据文件
这里用了sin函数产生有规律的波型值,模拟声波, byte【】 test。
直接在头文件后部加入模拟声波test的值,随后可用音乐播放器直接读文件。
下面是头文件,所有 readonly 标志的是不能改的部分,是wav的必要格式。
没写 readonly 的,有部分是可选参数,偷懒没用枚举器…可以在构造器内改数值。
因为头部文件必须要输入数据总长,所以构造此结构体要求录入byte数组,读取长度。
注意!作者没有测试有附加信息条件下能否运行!
命名空间:
using System;
using System.IO;
using System.Runtime.InteropServices;
头文件结构体:
[Serializable]
public struct Wav
{
//资源交换文件标志
public readonly char ResourceSign1;
public readonly char ResourceSign2;
public readonly char ResourceSign3;
public readonly char ResourceSign4;
//下一个至文件尾长度
public int AllLongFromNext;
//WAV格式
public readonly char WAVSign1;
public readonly char WAVSign2;
public readonly char WAVSign3;
public readonly char WAVSign4;
//波形格式
public readonly char FMTSign1;
public readonly char FMTSign2;
public readonly char FMTSign3;
public readonly char FMTSign4;
//过滤字节 0x0000 0010 无附加信息 0x0000 0012 有附加信息
public int Filter;
//格式种类 1 表示数据为线性PCM编码
public short Format;
//通道数 1 单声道 2 立体声
public short Channel;
//采样频率 常选: 11025 22050
public int Sampling;
//波形数据传输速率(平均每秒字节) 通道数×每秒样本数×每样本的数据位数/8(1*22050*16/8)
//常选: 22050 44100
public int Velocity;//32
//数据块的调整数 字节 通道数×每样本的数据位值/8
public short BuffTimes;
//PCM位宽(采样大小) 每个声道 样本大小一样
//常选: 16 8
public readonly short PCMWidth;
/*
//附加信息
public readonly short AddInformation = 0;
//不定长度字符 fact可选部分
public char[] FactName = {'','','',''};
public int FactLength = {get{return 1;}}
public bytes[] FactDate;
*/
//数据标志
public readonly char waveDataSign1;
public readonly char waveDataSign2;
public readonly char waveDataSign3;
public readonly char waveDataSign4;
//Date 数据块总长
public int waveDataLength;
public Wav(byte[] waveData)
{
waveDataLength = waveData.Length;
AllLongFromNext = 36 + waveDataLength;
ResourceSign1 = 'R';
ResourceSign2 = 'I';
ResourceSign3 = 'F';
ResourceSign4 = 'F';
WAVSign1 = 'W';
WAVSign2 = 'A';
WAVSign3 = 'V';
WAVSign4 = 'E';
FMTSign1 = 'f';
FMTSign2 = 'm';
FMTSign3 = 't';
FMTSign4 = ' ';
waveDataSign1 = 'd';
waveDataSign2 = 'a';
waveDataSign3 = 't';
waveDataSign4 = 'a';
Filter = 16;
Format = 1;
Channel = 1;
Sampling = 11025;
Velocity = 22050;
BuffTimes = 2;
PCMWidth = 8;
}
}
其余代码:
static void Main(string[] args)
{
byte[] test = new byte[80000];
//填充方法一:结果为噪音
//Random random = new Random();
//random.NextBytes(test);
//填充方法二:sin(i/w),参数w在【3,15】之间会有声音
for(int i =0,j = 0;i < 80000; i++,j++)
{
j %= 1000;
test[i] = (byte)(j / 10 * Math.Sin(i / 4f + j));
test[i] += (byte)(j / 30 * Math.Sin(i / 3f - j));
}
//定义头部文件
Wav wav = new Wav(test);
//将结构体内容复制到 byte【】
int size = 0;
size = Marshal.SizeOf(wav);
IntPtr intPtr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(wav, intPtr, false);
byte[] head = new byte[size];
Marshal.Copy(intPtr, head, 0, size);
Marshal.FreeHGlobal(intPtr);
//写出文件
using (Stream file = new FileStream("test.wav", FileMode.Create))
{
file.Write(head, 0, head.Length);
file.Write(test, 0, test.Length);
}
//命令行提示完成
Console.WriteLine("完成");
Console.ReadLine();
}
第一次发文章,小激动