Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
Wav.cs
浏览该文件的文档.
1using System.Runtime.InteropServices;
3
4namespace Engine.Media {
5 public static class Wav {
8
9 public bool m_leaveOpen;
10
11 public int m_channelsCount;
12
14
15 public long m_bytesCount;
16
18
19 public override int ChannelsCount => m_channelsCount;
20
21 public override int SamplingFrequency => m_samplingFrequency;
22
23 public override long BytesCount => m_bytesCount;
24
25 public override long Position {
26 get => m_position;
27 set {
28 if (m_stream.CanSeek) {
29 long num = value * ChannelsCount * 2;
30 if (num < 0
31 || num > BytesCount) {
32 throw new ArgumentOutOfRangeException();
33 }
34 m_stream.Position = Utilities.SizeOf<WavHeader>() + num;
35 m_position = value;
36 return;
37 }
38 throw new NotSupportedException("Underlying stream cannot be seeked.");
39 }
40 }
41
42 public WavStreamingSource(Stream stream, bool leaveOpen = false) {
43 MemoryStream memoryStream = new();
44 stream.Position = 0L;
45 stream.CopyTo(memoryStream);
46 memoryStream.Position = 0L;
47 m_stream = memoryStream;
48 m_leaveOpen = leaveOpen;
49 ReadHeaders(m_stream, out FmtHeader fmtHeader, out DataHeader dataHeader, out long dataStart);
50 m_channelsCount = fmtHeader.ChannelsCount;
51 m_samplingFrequency = fmtHeader.SamplingFrequency;
52 m_bytesCount = dataHeader.DataSize;
53 m_stream.Position = dataStart;
54 }
55
56 public override void Dispose() {
57 if (!m_leaveOpen) {
58 m_stream.Dispose();
59 }
60 m_stream = null;
61 }
62
63 public override int Read(byte[] buffer, int offset, int count) {
64 if (count % (2 * ChannelsCount) != 0) {
65 throw new InvalidOperationException("Cannot read partial samples.");
66 }
67 count = (int)Math.Min(count, m_bytesCount - m_position * 2 * ChannelsCount);
68 int num = m_stream.Read(buffer, offset, count);
69 m_position += num / 2 / ChannelsCount;
70 return num;
71 }
72
73 public override StreamingSource Duplicate() {
74 MemoryStream memoryStream = new();
75 m_stream.Position = 0L;
76 m_stream.CopyTo(memoryStream);
77 memoryStream.Position = 0L;
78 return new WavStreamingSource(memoryStream);
79 }
80 }
81
82 public struct WavInfo {
83 public int ChannelsCount;
84
86
87 public int BytesCount;
88 }
89
90 [StructLayout(LayoutKind.Sequential, Pack = 1)]
91 public struct WavHeader {
92 public int Riff;
93
94 public int FileSize;
95
96 public int Wave;
97 }
98
99 [StructLayout(LayoutKind.Sequential, Pack = 1)]
100 public struct FmtHeader {
101 public int Fmt;
102
103 public int FormatSize;
104
105 public short Type;
106
107 public short ChannelsCount;
108
110
111 public int BytesPerSecond;
112
113 public short BytesPerSample;
114
115 public short BitsPerChannel;
116 }
117
118 [StructLayout(LayoutKind.Sequential, Pack = 1)]
119 public struct DataHeader {
120 public int Data;
121
122 public int DataSize;
123 }
124
125 public static bool IsWavStream(Stream stream) {
126 BinaryReader binaryReader = new(stream);
127 if (stream.Length - stream.Position >= Utilities.SizeOf<WavHeader>()) {
128 int num = binaryReader.ReadInt32();
129 int num2 = binaryReader.ReadInt32();
130 int num3 = binaryReader.ReadInt32();
131 stream.Position -= 12L;
132 if (num == MakeFourCC("RIFF")
133 && num2 != 0
134 && num3 == MakeFourCC("WAVE")) {
135 return true;
136 }
137 }
138 return false;
139 }
140
141 public static WavInfo GetInfo(Stream stream) {
142 ReadHeaders(stream, out FmtHeader fmtHeader, out DataHeader dataHeader, out long _);
143 WavInfo result = default;
144 result.ChannelsCount = fmtHeader.ChannelsCount;
145 result.SamplingFrequency = fmtHeader.SamplingFrequency;
146 result.BytesCount = dataHeader.DataSize;
147 return result;
148 }
149
150 public static StreamingSource Stream(Stream stream) => new WavStreamingSource(stream);
151
152 public static SoundData Load(Stream stream) {
153 ReadHeaders(stream, out FmtHeader fmtHeader, out DataHeader dataHeader, out long dataStart);
154 stream.Position = dataStart;
155 SoundData soundData = new(fmtHeader.ChannelsCount, fmtHeader.SamplingFrequency, dataHeader.DataSize);
156 byte[] array = new byte[dataHeader.DataSize];
157 if (stream.Read(array, 0, array.Length) != array.Length) {
158 throw new InvalidOperationException("Truncated WAV data.");
159 }
160 Buffer.BlockCopy(array, 0, soundData.Data, 0, array.Length);
161 return soundData;
162 }
163
164 public static void Save(SoundData soundData, Stream stream) {
165 ArgumentNullException.ThrowIfNull(soundData);
166 ArgumentNullException.ThrowIfNull(stream);
167 EngineBinaryWriter engineBinaryWriter = new(stream);
168 WavHeader structure = default;
169 structure.Riff = MakeFourCC("RIFF");
170 structure.FileSize = Utilities.SizeOf<WavHeader>()
171 + Utilities.SizeOf<FmtHeader>()
172 + Utilities.SizeOf<DataHeader>()
173 + soundData.Data.Length;
174 structure.Wave = MakeFourCC("WAVE");
175 engineBinaryWriter.WriteStruct(structure);
176 FmtHeader structure2 = default;
177 structure2.Fmt = MakeFourCC("fmt ");
178 structure2.FormatSize = 16;
179 structure2.Type = 1;
180 structure2.ChannelsCount = (short)soundData.ChannelsCount;
181 structure2.SamplingFrequency = soundData.SamplingFrequency;
182 structure2.BytesPerSecond = soundData.ChannelsCount * 2 * soundData.SamplingFrequency;
183 structure2.BytesPerSample = (short)(soundData.ChannelsCount * 2);
184 structure2.BitsPerChannel = 16;
185 engineBinaryWriter.WriteStruct(structure2);
186 DataHeader structure3 = default;
187 structure3.Data = MakeFourCC("data");
188 structure3.DataSize = soundData.Data.Length * 2;
189 engineBinaryWriter.WriteStruct(structure3);
190 byte[] array = new byte[soundData.Data.Length * 2];
191 Buffer.BlockCopy(soundData.Data, 0, array, 0, array.Length);
192 stream.Write(array, 0, array.Length);
193 }
194
195 public static void ReadHeaders(Stream stream, out FmtHeader fmtHeader, out DataHeader dataHeader, out long dataStart) {
196 ArgumentNullException.ThrowIfNull(stream);
197 if (!BitConverter.IsLittleEndian) {
198 throw new InvalidOperationException("Unsupported system endianness.");
199 }
200 if (!IsWavStream(stream)) {
201 throw new InvalidOperationException("Invalid WAV header.");
202 }
203 EngineBinaryReader engineBinaryReader = new(stream);
204 fmtHeader = default;
205 dataHeader = default;
206 dataStart = 0L;
207 stream.Position += 12L;
208 bool flag = false;
209 bool flag2 = false;
210 while (!flag
211 || !flag2) {
212 int num = engineBinaryReader.ReadInt32();
213 if (num == MakeFourCC("fmt ")) {
214 stream.Position -= 4L;
215 fmtHeader = engineBinaryReader.ReadStruct<FmtHeader>();
216 flag = true;
217 }
218 else if (num == MakeFourCC("data")) {
219 stream.Position -= 4L;
220 dataHeader = engineBinaryReader.ReadStruct<DataHeader>();
221 dataStart = stream.Position;
222 flag2 = true;
223 }
224 else {
225 int num2 = engineBinaryReader.ReadInt32();
226 stream.Position += num2;
227 }
228 }
229 if (fmtHeader.Type != 1
230 || fmtHeader.ChannelsCount < 1
231 || fmtHeader.ChannelsCount > 2
232 || fmtHeader.SamplingFrequency < 8000
233 || fmtHeader.SamplingFrequency > 48000
234 || fmtHeader.BitsPerChannel != 16) {
235 throw new InvalidOperationException("Unsupported WAV format.");
236 }
237 }
238
239 public static int MakeFourCC(string text) => (int)(((uint)text[3] << 24) | ((uint)text[2] << 16) | ((uint)text[1] << 8) | text[0]);
240 }
241}
WavStreamingSource(Stream stream, bool leaveOpen=false)
定义 Wav.cs:42
override StreamingSource Duplicate()
定义 Wav.cs:73
override int Read(byte[] buffer, int offset, int count)
定义 Wav.cs:63
static bool IsWavStream(Stream stream)
定义 Wav.cs:125
static void ReadHeaders(Stream stream, out FmtHeader fmtHeader, out DataHeader dataHeader, out long dataStart)
定义 Wav.cs:195
static void Save(SoundData soundData, Stream stream)
定义 Wav.cs:164
static StreamingSource Stream(Stream stream)
定义 Wav.cs:150
static SoundData Load(Stream stream)
定义 Wav.cs:152
static WavInfo GetInfo(Stream stream)
定义 Wav.cs:141
static int MakeFourCC(string text)
定义 Wav.cs:239