Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
WaveFormatAdpcm.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 //
4 // Copyright (c) 2010-2013 SharpDX - Alexandre Mutel
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to deal
8 // in the Software without restriction, including without limitation the rights
9 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 // copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 // THE SOFTWARE.
23 
24 using System;
25 using System.Runtime.InteropServices;
26 
27 using SiliconStudio.Core;
28 
29 namespace SiliconStudio.Paradox.Audio.Wave
30 {
31  /// <summary>
32  /// WaveFormatAdpcm
33  /// http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.xaudio2.adpcmwaveformat%28v=vs.85%29.aspx
34  /// Additional documentation: http://icculus.org/SDL_sound/downloads/external_documentation/wavecomp.htm
35  /// </summary>
36  internal class WaveFormatAdpcm : WaveFormat
37  {
38  /// <summary>
39  /// Parameterless constructor for marshalling
40  /// </summary>
41  internal WaveFormatAdpcm()
42  {
43  }
44 
45  /// <summary>
46  /// Creates a new WaveFormatAdpcm for MicrosoftADPCM
47  /// </summary>
48  /// <param name="rate">The rate.</param>
49  /// <param name="channels">The channels.</param>
50  /// <param name="blockAlign">The block align. If 0, then 256 for [0, 11KHz], 512 for ]11KHz, 22Khz], 1024 for ]22Khz, +inf]</param>
51  public WaveFormatAdpcm(int rate, int channels, int blockAlign = 0)
52  : base(rate, 4, channels)
53  {
54  waveFormatTag = WaveFormatEncoding.Adpcm;
55  this.blockAlign = (short)blockAlign;
56 
57  if (blockAlign == 0)
58  {
59  if (rate <= 11025)
60  {
61  blockAlign = 256;
62  }
63  else if (rate <= 22050)
64  {
65  blockAlign = 512;
66  }
67  else
68  {
69  blockAlign = 1024;
70  }
71  }
72 
73  SamplesPerBlock = (ushort)(blockAlign * 2 / channels - 12);
74  averageBytesPerSecond = (SampleRate * blockAlign) / SamplesPerBlock;
75 
76  // Default Microsoft ADPCM coefficients
77  Coefficients1 = new short[] { 256, 512, 0, 192, 240, 460, 392 };
78  Coefficients2 = new short[] { 0, -256, 0, 64, 0, -208, -232 };
79  extraSize = 32;
80  }
81 
82  /// <summary>
83  /// Gets or sets the samples per block.
84  /// </summary>
85  /// <value>
86  /// The samples per block.
87  /// </value>
88  public ushort SamplesPerBlock { get; private set; }
89 
90  /// <summary>
91  /// Gets or sets the coefficients.
92  /// </summary>
93  /// <value>
94  /// The coefficients.
95  /// </value>
96  public short[] Coefficients1 { get; set; }
97 
98  /// <summary>
99  /// Gets or sets the coefficients.
100  /// </summary>
101  /// <value>
102  /// The coefficients.
103  /// </value>
104  public short[] Coefficients2 { get; set; }
105 
106  protected unsafe override IntPtr MarshalToPtr()
107  {
108  var result = Marshal.AllocHGlobal(Utilities.SizeOf<WaveFormat.__Native>() + sizeof(int) + sizeof(int) * Coefficients1.Length);
109  __MarshalTo(ref *(__Native*)result);
110  return result;
111  }
112 
113  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 2)]
114  internal new struct __Native
115  {
116  public WaveFormat.__Native waveFormat;
117  public ushort samplesPerBlock;
118  public ushort numberOfCoefficients;
119  public short coefficients;
120 
121  // Method to free native struct
122  internal void __MarshalFree()
123  {
124  waveFormat.__MarshalFree();
125  }
126  }
127  // Method to marshal from native to managed struct
128  internal unsafe void __MarshalFrom(ref __Native @ref)
129  {
130  __MarshalFrom(ref @ref.waveFormat);
131  SamplesPerBlock = @ref.samplesPerBlock;
132  Coefficients1 = new short[@ref.numberOfCoefficients];
133  Coefficients2 = new short[@ref.numberOfCoefficients];
134  if (@ref.numberOfCoefficients > 7)
135  throw new InvalidOperationException("Unable to read Adpcm format. Too may coefficients (max 7)");
136  fixed (short* pCoefs = &@ref.coefficients)
137  for (int i = 0; i < @ref.numberOfCoefficients; i++)
138  {
139  Coefficients1[i] = pCoefs[i * 2];
140  Coefficients2[i] = pCoefs[i * 2 + 1];
141  }
142  extraSize = (short)(sizeof(int) + sizeof(int) * @ref.numberOfCoefficients);
143  }
144  // Method to marshal from managed struct tot native
145  private unsafe void __MarshalTo(ref __Native @ref)
146  {
147  if (Coefficients1.Length > 7)
148  throw new InvalidOperationException("Unable to encode Adpcm format. Too may coefficients (max 7)");
149 
150  extraSize = (short)(sizeof(int) + sizeof(int) * Coefficients1.Length);
151  __MarshalTo(ref @ref.waveFormat);
152  @ref.samplesPerBlock = SamplesPerBlock;
153  @ref.numberOfCoefficients = (ushort)Coefficients1.Length;
154  fixed (short* pCoefs = &@ref.coefficients)
155  for (int i = 0; i < @ref.numberOfCoefficients; i++)
156  {
157  pCoefs[i * 2] = Coefficients1[i];
158  pCoefs[i * 2 + 1] = Coefficients2[i];
159  }
160  }
161  }
162 }