29 using System.Globalization;
31 using System.Runtime.InteropServices;
33 using SiliconStudio.Core;
35 namespace SiliconStudio.
Paradox.Audio.Wave
40 internal class WaveFormat
43 protected WaveFormatEncoding waveFormatTag;
45 protected short channels;
47 protected int sampleRate;
49 protected int averageBytesPerSecond;
51 protected short blockAlign;
53 protected short bitsPerSample;
55 protected short extraSize;
57 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 2)]
58 internal struct __Native
60 public __PcmNative pcmWaveFormat;
62 public short extraSize;
64 internal void __MarshalFree()
69 internal void __MarshalFree(ref __Native @ref)
75 internal void __MarshalFrom(ref __Native @ref)
77 waveFormatTag = @ref.pcmWaveFormat.waveFormatTag;
78 channels = @ref.pcmWaveFormat.channels;
79 sampleRate = @ref.pcmWaveFormat.sampleRate;
80 averageBytesPerSecond = @ref.pcmWaveFormat.averageBytesPerSecond;
81 blockAlign = @ref.pcmWaveFormat.blockAlign;
82 bitsPerSample = @ref.pcmWaveFormat.bitsPerSample;
83 extraSize = @ref.extraSize;
86 internal void __MarshalTo(ref __Native @ref)
88 @ref.pcmWaveFormat.waveFormatTag = waveFormatTag;
89 @ref.pcmWaveFormat.channels = channels;
90 @ref.pcmWaveFormat.sampleRate = sampleRate;
91 @ref.pcmWaveFormat.averageBytesPerSecond = averageBytesPerSecond;
92 @ref.pcmWaveFormat.blockAlign = blockAlign;
93 @ref.pcmWaveFormat.bitsPerSample = bitsPerSample;
94 @ref.extraSize = extraSize;
97 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 2)]
98 internal struct __PcmNative
101 public WaveFormatEncoding waveFormatTag;
103 public short channels;
105 public int sampleRate;
107 public int averageBytesPerSecond;
109 public short blockAlign;
111 public short bitsPerSample;
114 internal unsafe
void __MarshalFree()
119 internal unsafe
void __MarshalFree(ref __PcmNative @ref)
121 @ref.__MarshalFree();
125 internal void __MarshalFrom(ref __PcmNative @ref)
127 waveFormatTag = @ref.waveFormatTag;
128 channels = @ref.channels;
129 sampleRate = @ref.sampleRate;
130 averageBytesPerSecond = @ref.averageBytesPerSecond;
131 blockAlign = @ref.blockAlign;
132 bitsPerSample = @ref.bitsPerSample;
136 internal void __MarshalTo(ref __PcmNative @ref)
138 @ref.waveFormatTag = waveFormatTag;
139 @ref.channels = channels;
140 @ref.sampleRate = sampleRate;
141 @ref.averageBytesPerSecond = averageBytesPerSecond;
142 @ref.blockAlign = blockAlign;
143 @ref.bitsPerSample = bitsPerSample;
162 public WaveFormat(
int sampleRate,
int channels)
163 : this(sampleRate, 16, channels)
172 public int ConvertLatencyToByteSize(
int milliseconds)
174 int bytes = (int)((AverageBytesPerSecond / 1000.0) * milliseconds);
175 if ((bytes % BlockAlign) != 0)
178 bytes = bytes + BlockAlign - (bytes % BlockAlign);
193 public static WaveFormat CreateCustomFormat(WaveFormatEncoding tag,
int sampleRate,
int channels,
int averageBytesPerSecond,
int blockAlign,
int bitsPerSample)
195 var waveFormat =
new WaveFormat
198 channels = (short)channels,
199 sampleRate = sampleRate,
200 averageBytesPerSecond = averageBytesPerSecond,
201 blockAlign = (
short)blockAlign,
202 bitsPerSample = (short)bitsPerSample,
211 public WaveFormat(
int rate,
int bits,
int channels)
215 throw new ArgumentOutOfRangeException(
"channels",
"Channels must be 1 or greater");
218 waveFormatTag = bits < 32 ? WaveFormatEncoding.Pcm : WaveFormatEncoding.IeeeFloat;
219 this.channels = (short)channels;
221 bitsPerSample = (short)bits;
224 blockAlign = (short)(channels * (bits / 8));
225 averageBytesPerSecond = sampleRate * blockAlign;
233 public static WaveFormat CreateIeeeFloatWaveFormat(
int sampleRate,
int channels)
235 var wf =
new WaveFormat
237 waveFormatTag = WaveFormatEncoding.IeeeFloat,
238 channels = (short)channels,
240 sampleRate = sampleRate,
241 blockAlign = (
short)(4 * channels)
243 wf.averageBytesPerSecond = sampleRate * wf.blockAlign;
253 public unsafe
static WaveFormat MarshalFrom(byte[] rawdata)
255 fixed (
void* pRawData = rawdata)
256 return MarshalFrom((IntPtr)pRawData);
264 public unsafe static WaveFormat MarshalFrom(IntPtr pointer)
266 if (pointer == IntPtr.Zero)
return null;
268 var pcmWaveFormat = *(__PcmNative*)pointer;
269 var encoding = pcmWaveFormat.waveFormatTag;
273 if (pcmWaveFormat.channels <= 2 && (encoding == WaveFormatEncoding.Pcm || encoding == WaveFormatEncoding.IeeeFloat))
275 var waveFormat =
new WaveFormat();
276 waveFormat.__MarshalFrom(ref pcmWaveFormat);
280 if (encoding == WaveFormatEncoding.Extensible)
282 var waveFormat =
new WaveFormatExtensible();
283 waveFormat.__MarshalFrom(ref *(WaveFormatExtensible.__Native*)pointer);
287 if (encoding == WaveFormatEncoding.Adpcm)
289 var waveFormat =
new WaveFormatAdpcm();
290 waveFormat.__MarshalFrom(ref *(WaveFormatAdpcm.__Native*)pointer);
294 throw new InvalidOperationException(
string.Format(
"Unsupported WaveFormat [{0}]", encoding));
297 protected unsafe
virtual IntPtr MarshalToPtr()
299 var result = Marshal.AllocHGlobal(Utilities.SizeOf<__Native>());
300 __MarshalTo(ref *(__Native*)result);
309 public static IntPtr MarshalToPtr(WaveFormat
format)
311 if (format == null)
return IntPtr.Zero;
312 return format.MarshalToPtr();
319 public WaveFormat(BinaryReader br)
321 int formatChunkLength = br.ReadInt32();
322 if (formatChunkLength < 16)
323 throw new ArgumentException(
"Invalid WaveFormat Structure");
324 waveFormatTag = (WaveFormatEncoding)br.ReadUInt16();
325 channels = br.ReadInt16();
326 sampleRate = br.ReadInt32();
327 averageBytesPerSecond = br.ReadInt32();
328 blockAlign = br.ReadInt16();
329 bitsPerSample = br.ReadInt16();
331 if (formatChunkLength > 16)
334 extraSize = br.ReadInt16();
335 if (extraSize > formatChunkLength - 18)
340 extraSize = (short)(formatChunkLength - 18);
353 public override string ToString()
355 switch (waveFormatTag)
357 case WaveFormatEncoding.Pcm:
358 case WaveFormatEncoding.Extensible:
360 return string.Format(CultureInfo.InvariantCulture,
"{0} bit PCM: {1}kHz {2} channels",
361 bitsPerSample, sampleRate / 1000, channels);
363 return waveFormatTag.ToString();
372 public override bool Equals(
object obj)
374 if (!(obj is WaveFormat))
377 WaveFormat other = (WaveFormat)obj;
378 return waveFormatTag == other.waveFormatTag &&
379 channels == other.channels &&
380 sampleRate == other.sampleRate &&
381 averageBytesPerSecond == other.averageBytesPerSecond &&
382 blockAlign == other.blockAlign &&
383 bitsPerSample == other.bitsPerSample;
390 public override int GetHashCode()
392 return (
int)waveFormatTag ^
395 averageBytesPerSecond ^
407 return waveFormatTag;
425 public int SampleRate
436 public int AverageBytesPerSecond
440 return averageBytesPerSecond;
447 public int BlockAlign
459 public int BitsPerSample
463 return bitsPerSample;
System.Text.Encoding Encoding
_In_ size_t _In_ size_t _In_ DXGI_FORMAT format