<span>namespace</span> cSouza.Audio
{
<span>using</span> System;
<span>/// <summary></span>
<span>/// Static methods to convert between different sample formats.</span>
<span>/// </summary></span>
<span>/// <remarks></span>
<span>/// <para></span>
<span>/// Code is mainly based on information available on the original</span>
<span>/// C source code pa_converters.c from Portable Audio I/O Library.</span>
<span>/// </para></span>
<span>/// <para></span>
<span>/// This class try to be as fast as possible without using unsafe code.</span>
<span>/// </para></span>
<span>/// <para></span>
<span>/// Dither isn't currently supported. Currently supported conversions</span>
<span>/// are 'to' and 'from' conversions between the following value types:</span>
<span>/// </para></span>
<span>/// <para></span>
<span>/// Integer 8-bit (byte), </span>
<span>/// Integer 16-bit (Int16), </span>
<span>/// Integer 32-bit (Int32), </span>
<span>/// Single precision 32-bit floating point (float).</span>
<span>/// </para></span>
<span>/// <para></span>
<span>/// Which are the most common PCM formats.</span>
<span>/// </para></span>
<span>/// <example></span>
<span>/// To use it, just call Convert. The compiler will automatically detect</span>
<span>/// which method to call based on your data types. Couldn't be simplier.</span>
<span>/// <code></span>
<span>/// int[] srcPcm16samples = new int[] { 1, 2, 3};</span>
<span>/// float[] destIeeeFloat32samples = new float[3];</span>
<span>/// </span>
<span>/// SampleConverter.Convert(srcPcm16samples, destIeeeFloat32samples);</span>
<span>/// </span>
<span>/// // destIeeeFloat32samples now contains the converted samples.</span>
<span>/// </code></span>
<span>/// </example></span>
<span>/// </remarks></span>
<span>public</span> <span>static</span> <span>class</span> SampleConverter
{
<span>#region</span> Consts: Standard values used <span>in</span> almost all conversions.
<span>private</span> <span>const</span> <span>float</span> const_1_div_128_ = 1.0f / 128.0f; <span>// 8 bit multiplier</span>
<span>private</span> <span>const</span> <span>float</span> const_1_div_32768_ = 1.0f / 32768.0f; <span>// 16 bit multiplier</span>
<span>private</span> <span>const</span> <span>double</span> const_1_div_2147483648_ = 1.0 / 2147483648.0; <span>// 32 bit</span>
<span>#endregion</span>
<span>#region</span> From UInt8 (<span>byte</span>)
<span>#region</span> From UInt8 (<span>byte</span>) to Int16 (<span>short</span>)
<span>/// <summary></span>
<span>/// Converts a array of signed 8-bit int samples</span>
<span>/// into a array of 32-bit float-point samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>byte</span>[][] from, Int16[][] to)
{
<span>for</span> (<span>int</span> j = 0; j < from.Length; j++)
<span>for</span> (<span>int</span> i = 0; i < from[0].Length; i++)
to[i][j] = (Int16)((from[i][j] - 128) << 8);
}
<span>/// <summary></span>
<span>/// Converts a array of signed 8-bit int samples</span>
<span>/// into a array of 32-bit float-point samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>byte</span>[] from, Int16[] to)
{
<span>for</span> (<span>int</span> i = 0; i < from.Length; i++)
to[i] = (Int16)((from[i] - 128) << 8);
}
<span>/// <summary></span>
<span>/// Converts a signed 8-bit int sample</span>
<span>/// into a 32-bit float-point sample.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>byte</span> from, <span>out</span> Int16 to)
{
to = (Int16)((from - 128) << 8);
}
<span>#endregion</span>
<span>#region</span> From UInt8 (<span>byte</span>) to Int32 (<span>int</span>)
<span>/// <summary></span>
<span>/// Converts a matrix of unsigned 8-bit int samples</span>
<span>/// into a matrix of 32-bit float-point samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>byte</span>[][] from, <span>int</span>[][] to)
{
<span>for</span> (<span>int</span> i = 0; i < from.Length; i++)
<span>for</span> (<span>int</span> j = 0; j < from[0].Length; j++)
to[i][j] = ((from[i][j] - 128) << 24);
}
<span>/// <summary></span>
<span>/// Converts a array of unsigned 8-bit int samples</span>
<span>/// into a array of 32-bit float-point samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>byte</span>[] from, <span>int</span>[] to)
{
<span>for</span> (<span>int</span> i = 0; i < from.Length; i++)
to[i] = ((from[i] - 128) << 24);
}
<span>/// <summary></span>
<span>/// Converts a unsigned 8-bit int sample</span>
<span>/// into a 32-bit float-point sample.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>byte</span> from, <span>out</span> <span>int</span> to)
{
to = ((from - 128) << 24);
}
<span>#endregion</span>
<span>#region</span> From UInt8 (<span>byte</span>) to Single (<span>float</span>)
<span>/// <summary></span>
<span>/// Converts a matrix of unsigned 8-bit int samples</span>
<span>/// into a matrix of 32-bit float-point samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>byte</span>[][] from, <span>float</span>[][] to)
{
<span>for</span> (<span>int</span> i = 0; i < from.Length; i++)
<span>for</span> (<span>int</span> j = 0; j < from[0].Length; j++)
to[i][j] = (from[i][j] - 128) * const_1_div_128_;
}
<span>/// <summary></span>
<span>/// Converts a array of unsigned 8-bit int samples</span>
<span>/// into a array of 32-bit float-point samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>byte</span>[] from, <span>float</span>[] to)
{
<span>for</span> (<span>int</span> i = 0; i < from.Length; i++)
to[i] = (from[i] - 128) * const_1_div_128_;
}
<span>/// <summary></span>
<span>/// Converts a unsigned 8-bit int sample</span>
<span>/// into a 32-bit float-point sample.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>byte</span> from, <span>out</span> <span>float</span> to)
{
to = (from - 128) * const_1_div_128_;
}
<span>#endregion</span>
<span>#endregion</span>
<span>#region</span> From Int16 (<span>short</span>)
<span>#region</span> From Int16 (<span>short</span>) to UInt8 (<span>byte</span>)
<span>/// <summary></span>
<span>/// Converts a matrix of signed 16-bit int samples</span>
<span>/// into a matrix of 8-bit unsigned byte samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int16[][] from, <span>byte</span>[][] to)
{
<span>for</span> (<span>int</span> j = 0; j < from.Length; j++)
<span>for</span> (<span>int</span> i = 0; i < from[i].Length; i++)
to[i][j] = (<span>byte</span>)(((from[i][j]) >> 8) + 128);
}
<span>/// <summary></span>
<span>/// Converts a array of signed 16-bit int samples</span>
<span>/// into a array of 8-bit unsigned byte samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int16[] from, <span>byte</span>[] to)
{
<span>for</span> (<span>int</span> i = 0; i < from.Length; i++)
to[i] = (<span>byte</span>)(((from[i]) >> 8) + 128);
}
<span>/// <summary></span>
<span>/// Converts a signed 16-bit int sample</span>
<span>/// into a 8-bit unsigned byte sample.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int16 from, <span>out</span> <span>byte</span> to)
{
to = (<span>byte</span>)(((from) >> 8) + 128);
}
<span>#endregion</span>
<span>#region</span> From Int16 (<span>short</span>) to Int32 (<span>int</span>)
<span>/// <summary></span>
<span>/// Converts a matrix of signed 16-bit int samples</span>
<span>/// into a matrix of 32-bit signed integer samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int16[][] from, Int32[][] to)
{
<span>for</span> (<span>int</span> j = 0; j < from.Length; j++)
<span>for</span> (<span>int</span> i = 0; i < from[i].Length; i++)
to[i][j] = (<span>byte</span>)(((from[i][j]) >> 8) + 128);
}
<span>/// <summary></span>
<span>/// Converts a array of signed 16-bit int samples</span>
<span>/// into a array of 32-bit signed integer samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int16[] from, Int32[] to)
{
<span>for</span> (<span>int</span> i = 0; i < from.Length; i++)
to[i] = (<span>byte</span>)(((from[i]) >> 8) + 128);
}
<span>/// <summary></span>
<span>/// Converts a signed 16-bit int sample</span>
<span>/// into a 32-bit signed integer sample.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int16 from, <span>out</span> Int32 to)
{
to = (<span>byte</span>)(((from) >> 8) + 128);
}
<span>#endregion</span>
<span>#region</span> From Int16 (<span>short</span>) to Single (<span>float</span>)
<span>/// <summary></span>
<span>/// Converts a matrix of signed 16-bit int samples</span>
<span>/// into a matrix of 32-bit float-point samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int16[][] from, <span>float</span>[][] to)
{
<span>for</span> (<span>int</span> j = 0; j < from.Length; j++)
<span>for</span> (<span>int</span> i = 0; i < from[i].Length; i++)
to[i][j] = (<span>float</span>)(from[i][j]*const_1_div_32768_);
}
<span>/// <summary></span>
<span>/// Converts a array of signed 16-bit int samples</span>
<span>/// into a array of 32-bit float-point samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int16[] from, <span>float</span>[] to)
{
<span>for</span> (<span>int</span> i = 0; i < from.Length; i++)
to[i] = (<span>float</span>)(from[i]*const_1_div_32768_);
}
<span>/// <summary></span>
<span>/// Converts a signed 16-bit int sample</span>
<span>/// into a 32-bit float-point sample.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int16 from, <span>out</span> <span>float</span> to)
{
to = (<span>float</span>)(from*const_1_div_32768_);
}
<span>#endregion</span>
<span>#endregion</span>
<span>#region</span> From Int32 (<span>int</span>)
<span>#region</span> From Int32 (<span>int</span>) To UInt8 (<span>byte</span>)
<span>/// <summary></span>
<span>/// Converts a matrix of signed 32-bit int samples</span>
<span>/// into a matrix of 8-bit unsigned byte samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int32[][] from, <span>byte</span>[][] to)
{
<span>for</span> (<span>int</span> j = 0; j < from.Length; j++)
<span>for</span> (<span>int</span> i = 0; i < from[i].Length; i++)
to[i][j] = (<span>byte</span>)(((from[i][j]) >> 24) + 128);
}
<span>/// <summary></span>
<span>/// Converts a array of signed 32-bit int samples</span>
<span>/// into a array of 8-bit unsigned byte samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int32[] from, <span>byte</span>[] to)
{
<span>for</span> (<span>int</span> i = 0; i < from.Length; i++)
to[i] = (<span>byte</span>)(((from[i]) >> 24) + 128);
}
<span>/// <summary></span>
<span>/// Converts a signed 32-bit int sample</span>
<span>/// into a 8-bit unsigned byte sample.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int32 from, <span>out</span> <span>byte</span> to)
{
to = (<span>byte</span>)((from >> 24) + 128);
}
<span>#endregion</span>
<span>#region</span> From Int32 (<span>int</span>) to Int16 (<span>short</span>)
<span>/// <summary></span>
<span>/// Converts a matrix of signed 32-bit int samples</span>
<span>/// into a matrix of 16-bit signed integer samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int32[][] from, Int16[][] to)
{
<span>for</span> (<span>int</span> j = 0; j < from.Length; j++)
<span>for</span> (<span>int</span> i = 0; i < from[i].Length; i++)
to[i][j] = (Int16)(from[i][j] >> 16);
}
<span>/// <summary></span>
<span>/// Converts a array of signed 32-bit int samples</span>
<span>/// into a array of 16-bit signed integer samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int32[] from, Int16[] to)
{
<span>for</span> (<span>int</span> i = 0; i < from.Length; i++)
to[i] = (Int16)(from[i] >> 16);
}
<span>/// <summary></span>
<span>/// Converts a signed 32-bit int sample</span>
<span>/// into a 16-bit signed integer sample.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int32 from, <span>out</span> Int16 to)
{
to = (Int16)(from >> 16);
}
<span>#endregion</span>
<span>#region</span> From Int32 (<span>int</span>) to Single (<span>float</span>)
<span>/// <summary></span>
<span>/// Converts a matrix of signed 32-bit int samples</span>
<span>/// into a matrix of 32-bit float-point samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int32[][] from, <span>float</span>[][] to)
{
<span>for</span> (<span>int</span> j = 0; j < from.Length; j++)
<span>for</span> (<span>int</span> i = 0; i < from[i].Length; i++)
to[i][j] = (<span>float</span>)(from[i][j]*const_1_div_2147483648_);
}
<span>/// <summary></span>
<span>/// Converts a array of signed 32-bit int samples</span>
<span>/// into a array of 32-bit float-point samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int32[] from, <span>float</span>[] to)
{
<span>for</span> (<span>int</span> i = 0; i < from.Length; i++)
to[i] = (<span>float</span>)((<span>double</span>)from[i]*const_1_div_2147483648_);
}
<span>/// <summary></span>
<span>/// Converts a signed 32-bit int sample</span>
<span>/// into a 32-bit float-point sample.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(Int32 from, <span>out</span> <span>float</span> to)
{
to = (<span>float</span>)((<span>double</span>)from*const_1_div_2147483648_);
}
<span>#endregion</span>
<span>#endregion</span>
<span>#region</span> From Single (<span>float</span>)
<span>#region</span> From Single (<span>float</span>) to UInt8 (<span>byte</span>)
<span>/// <summary></span>
<span>/// Converts a matrix of signed 32-bit float samples</span>
<span>/// into a matrix of 8-bit unsigned byte samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>float</span>[][] from, <span>byte</span>[][] to)
{
<span>for</span> (<span>int</span> j = 0; j < from.Length; j++)
<span>for</span> (<span>int</span> i = 0; i < from[i].Length; i++)
to[i][j] = (<span>byte</span>)(128 + ((<span>byte</span>)(to[i][j]*(127.0f))));
}
<span>/// <summary></span>
<span>/// Converts a array of signed 32-bit float samples</span>
<span>/// into a array of 8-bit unsigned byte samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>float</span>[] from, <span>byte</span>[] to)
{
<span>for</span> (<span>int</span> i = 0; i < from.Length; i++)
to[i] = (<span>byte</span>)(128 + ((<span>byte</span>)(to[i]*(127.0f))));
}
<span>/// <summary></span>
<span>/// Converts a signed 32-bit float sample</span>
<span>/// into a 8-bit unsigned byte sample.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>float</span> from, <span>out</span> <span>byte</span> to)
{
to = (<span>byte</span>)(128 + ((<span>byte</span>)(from*(127.0f))));
}
<span>#endregion</span>
<span>#region</span> From Single (<span>float</span>) to Int16 (<span>short</span>)
<span>/// <summary></span>
<span>/// Converts a matrix of signed 32-bit float samples</span>
<span>/// into a matrix of signed 16-bit integer samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>float</span>[][] from, <span>short</span>[][] to)
{
<span>for</span> (<span>int</span> j = 0; j < from.Length; j++)
<span>for</span> (<span>int</span> i = 0; i < from[i].Length; i++)
to[i][j] = (<span>short</span>) (from[i][j] * (32767.0f));
}
<span>/// <summary></span>
<span>/// Converts a array of signed 32-bit float samples</span>
<span>/// into a array of signed 16-bit integer samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>float</span>[] from, <span>short</span>[] to)
{
<span>for</span> (<span>int</span> i = 0; i < from.Length; i++)
to[i] = (<span>short</span>) (from[i] * (32767.0f));
}
<span>/// <summary></span>
<span>/// Converts a signed 32-bit float sample</span>
<span>/// into a signed 16-bit integer sample.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>float</span> from, <span>out</span> <span>short</span> to)
{
to = (<span>short</span>) (from * (32767.0f));
}
<span>#endregion</span>
<span>#region</span> From Single (<span>float</span>) to Int32 (<span>int</span>)
<span>/// <summary></span>
<span>/// Converts a matrix of signed 32-bit float samples</span>
<span>/// into a matrix of signed 32-bit integer samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>float</span>[][] from, Int32[][] to)
{
<span>for</span> (<span>int</span> j = 0; j < from.Length; j++)
<span>for</span> (<span>int</span> i = 0; i < from[i].Length; i++)
to[i][j] = (<span>int</span>)((<span>double</span>)from[i][j] * 0x7FFFFFFF);
}
<span>/// <summary></span>
<span>/// Converts a array of signed 32-bit float samples</span>
<span>/// into a array of signed 32-bit integer samples.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>float</span>[] from, Int32[] to)
{
<span>for</span> (<span>int</span> i = 0; i < from.Length; i++)
to[i] = (<span>int</span>)((<span>double</span>)from[i] * 0x7FFFFFFF);
}
<span>/// <summary></span>
<span>/// Converts a signed 32-bit floating-point sample</span>
<span>/// into a signed 32-bit integer sample.</span>
<span>/// </summary></span>
<span>/// <param name="from">The original sample.</param></span>
<span>/// <param name="to">The resulting sample.</param></span>
<span>public</span> <span>static</span> <span>void</span> Convert(<span>float</span> from, <span>out</span> Int32 to)
{
to = (<span>int</span>)((<span>double</span>)from * 0x7FFFFFFF);
}
<span>#endregion</span>
<span>#endregion</span>
}
}