Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
Flac.cs
浏览该文件的文档.
1#if IOS
2
3using Foundation;
4using ObjCRuntime;
5using System.Runtime.InteropServices;
6using Un4seen.Bass;
7using Un4seen.Bass.AddOn.Flac;
8
9namespace Engine.Media {
10 public static class Flac {
11 public class FlacStreamingSource : StreamingSource {
12
13 public Stream m_stream;
14
15 private static Dictionary<nint, Stream> streamMap = new();
16
17 private static nint globalStreamId;
18
19 int m_channels;
20
21 int m_sampleRate;
22
23 MemoryStream pcm_stream;
24
25 public override int ChannelsCount => m_channels;
26
27 public override int SamplingFrequency => m_sampleRate;
28
29 public override long Position => pcm_stream.Position;
30
31 public override long BytesCount => pcm_stream.Length;
32
33 public FlacStreamingSource(Stream stream) {
34 m_stream = stream;
35 pcm_stream = new MemoryStream();//解码后的pcm数据
36 BASS_FILEPROCS fileProcs = new BASS_FILEPROCS(CloseProc, LengthProc, ReadProc, SeekProc);
37 ++globalStreamId;
38 m_stream.Position = 0L;
39 streamMap[globalStreamId] = m_stream;
40
41 int streamID = BassFlac.BASS_FLAC_StreamCreateFileUser(BASSStreamSystem.STREAMFILE_BUFFER, BASSFlag.BASS_STREAM_DECODE, fileProcs, globalStreamId);
42 if (streamID == 0) throw new Exception("BASS_FLAC_StreamCreateFileUser failed: " + Bass.BASS_ErrorGetCode());
43 BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(streamID);
44 m_channels = info.chans;
45 m_sampleRate = info.freq;
46 byte[] buffer = new byte[4096];
47 int bytesRead;
48 while ((bytesRead = Bass.BASS_ChannelGetData(streamID, buffer, buffer.Length)) > 0) {
49 pcm_stream.Write(buffer, 0, bytesRead);
50 }
51 pcm_stream.Position = 0L;
52 Bass.BASS_StreamFree(streamID);
53 }
54
55 [MonoPInvokeCallback(typeof(FILELENPROC))]
56 private static long LengthProc(IntPtr user) {
57 var stream = streamMap[user];
58 return stream.Length;
59 }
60
61 [MonoPInvokeCallback(typeof(FILESEEKPROC))]
62 private static bool SeekProc(long offset, IntPtr user) {
63 var stream = streamMap[user];
64 stream.Seek(offset,SeekOrigin.Begin);
65 return true;
66 }
67
68 [MonoPInvokeCallback(typeof(FILEREADPROC))]
69 private static int ReadProc(IntPtr buffer, int length, IntPtr user) {
70 var stream = streamMap[user];
71 byte[] readBuffer = new byte[length];
72 int bytesRead = stream.Read(readBuffer, 0, length);
73 Marshal.Copy(readBuffer, 0, buffer, bytesRead);
74 return bytesRead;
75 }
76
77 [MonoPInvokeCallback(typeof(FILECLOSEPROC))]
78 private static void CloseProc(IntPtr user) {
79 var stream = streamMap[user];
80 stream.Position = 0L;
81 }
82
83 public override void Dispose() {
84 m_stream.Dispose();
85 pcm_stream.Dispose();
86 }
87
88 public override int Read(byte[] buffer, int offset, int count) {
89 ArgumentNullException.ThrowIfNull(buffer);
90 if (offset < 0
91 || count < 0
92 || offset + count > buffer.Length) {
93 throw new InvalidOperationException("Invalid range.");
94 }
95 int num = pcm_stream.Read(buffer, offset, (int)Math.Min(count, BytesCount - Position));
96 return num;
97 }
98
103 public override StreamingSource Duplicate() {
104 MemoryStream memoryStream = new();
105 m_stream.Position = 0L;
106 m_stream.CopyTo(memoryStream);
107 memoryStream.Position = 0L;
108 return new FlacStreamingSource(memoryStream);
109 }
110 }
111
112 public static bool IsFlacStream(Stream stream) {
113 ArgumentNullException.ThrowIfNull(stream);
114 long position = stream.Position;
115 stream.Position = 0;
116 byte[] beginSync = new byte[4];
117 int read = stream.Read(beginSync, 0, beginSync.Length);
118 stream.Position = position;
119 return read < beginSync.Length
120 ? throw new EndOfStreamException("Can not read \"fLaC\" sync.")
121 : beginSync[0] == 0x66 && beginSync[1] == 0x4C && beginSync[2] == 0x61 && beginSync[3] == 0x43;
122 }
123
124 public static StreamingSource Stream(Stream stream) {
125 ArgumentNullException.ThrowIfNull(stream);
126 return new FlacStreamingSource(stream);
127 }
128
129 public static SoundData Load(Stream stream) {
130 using (StreamingSource streamingSource = new FlacStreamingSource(stream)) {
131 if (streamingSource.BytesCount > int.MaxValue) {
132 throw new InvalidOperationException("Sound data too long.");
133 }
134 byte[] array = new byte[(int)streamingSource.BytesCount];
135 streamingSource.Read(array, 0, array.Length);
136 SoundData soundData = new(streamingSource.ChannelsCount, streamingSource.SamplingFrequency, array.Length);
137 Buffer.BlockCopy(array, 0, soundData.Data, 0, array.Length);
138 return soundData;
139 }
140 }
141 }
142}
143
144
145
146#else
147
148using NAudio.Flac;
149
150namespace Engine.Media {
151 public static class Flac {
153 public FlacReader m_reader;
154
156
158
159 public override int ChannelsCount => m_reader.WaveFormat.Channels;
160
161 public override int SamplingFrequency => m_reader.WaveFormat.SampleRate;
162
163 public override long Position {
164 get => m_position;
165 set {
166 m_reader.Position = value;
167 if (m_reader.CanSeek) {
168 long num = value * ChannelsCount * 2;
169 if (num < 0
170 || num > BytesCount) {
171 throw new ArgumentOutOfRangeException();
172 }
173 m_reader.Position = num;
174 m_position = value;
175 return;
176 }
177 throw new NotSupportedException("Underlying stream cannot be seeked.");
178 }
179 }
180
181 public override long BytesCount => m_reader.Length;
182
184 m_stream = new MemoryStream();
185 stream.Position = 0L;
186 stream.CopyTo(m_stream);
187 m_stream.Position = 0L;
188 m_reader = new FlacReader(m_stream);
189 }
190
191 public override void Dispose() {
192 m_reader.Dispose();
193 m_stream.Dispose();
194 }
195
196 public override int Read(byte[] buffer, int offset, int count) {
197 ArgumentNullException.ThrowIfNull(buffer);
198 if (offset < 0
199 || count < 0
200 || offset + count > buffer.Length) {
201 throw new InvalidOperationException("Invalid range.");
202 }
203 int num = m_reader.Read(buffer, offset, (int)Math.Min(count, BytesCount - Position));
204 m_position += num / 2 / ChannelsCount;
205 return num;
206 }
207
212 public override StreamingSource Duplicate() {
213 MemoryStream memoryStream = new();
214 m_stream.Position = 0L;
215 m_stream.CopyTo(memoryStream);
216 memoryStream.Position = 0L;
217 return new FlacStreamingSource(memoryStream);
218 }
219 }
220
221 public static bool IsFlacStream(Stream stream) {
222 ArgumentNullException.ThrowIfNull(stream);
223 long position = stream.Position;
224 stream.Position = 0;
225 ID3v2.SkipTag(stream);
226 byte[] beginSync = new byte[4];
227 int read = stream.Read(beginSync, 0, beginSync.Length);
228 stream.Position = position;
229 return read < beginSync.Length
230 ? throw new EndOfStreamException("Can not read \"fLaC\" sync.")
231 : beginSync[0] == 0x66 && beginSync[1] == 0x4C && beginSync[2] == 0x61 && beginSync[3] == 0x43;
232 }
233
234 public static StreamingSource Stream(Stream stream) {
235 ArgumentNullException.ThrowIfNull(stream);
236 return new FlacStreamingSource(stream);
237 }
238
239 public static SoundData Load(Stream stream) {
240 using (StreamingSource streamingSource = Stream(stream)) {
241 if (streamingSource.BytesCount > int.MaxValue) {
242 throw new InvalidOperationException("Sound data too long.");
243 }
244 byte[] array = new byte[(int)streamingSource.BytesCount];
245 streamingSource.Read(array, 0, array.Length);
246 SoundData soundData = new(streamingSource.ChannelsCount, streamingSource.SamplingFrequency, array.Length);
247 Buffer.BlockCopy(array, 0, soundData.Data, 0, array.Length);
248 return soundData;
249 }
250 }
251 }
252}
253
254#endif
override StreamingSource Duplicate()
复制出一个新的流
override int Read(byte[] buffer, int offset, int count)
static StreamingSource Stream(Stream stream)
static bool IsFlacStream(Stream stream)
static SoundData Load(Stream stream)
int Read(byte[] buffer, int offset, int count)