<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Simon Steed&#039;s Blog About Stuff! &#187; balance</title>
	<atom:link href="http://blog.xploiter.com/tag/balance/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.xploiter.com</link>
	<description>i.e. anything interesting...</description>
	<lastBuildDate>Wed, 01 Sep 2010 11:15:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4369</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Muting audio channels using Mixer Control API</title>
		<link>http://blog.xploiter.com/c-and-aspnet/muting-audio-channels-mixer-control-api/</link>
		<comments>http://blog.xploiter.com/c-and-aspnet/muting-audio-channels-mixer-control-api/#comments</comments>
		<pubDate>Fri, 01 May 2009 07:24:16 +0000</pubDate>
		<dc:creator>Simon Steed</dc:creator>
				<category><![CDATA[C# and ASP.Net]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[balance]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[framework 3.5]]></category>
		<category><![CDATA[mixerSetControlDetails]]></category>
		<category><![CDATA[pinvoke]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[sndvol.exe]]></category>

		<guid isPermaLink="false">http://blog.xploiter.com/?p=230</guid>
		<description><![CDATA[I recently had a problem on a job where no matter what we did, we could not control the left/right balance programmatically on two specific PC&#8217;s. We tried using various methods: Windows Media player API DirectSound APi WinMM.dll Praying None of them worked although you could control the balance using the Windows sound vol (sndvol.exe)]]></description>
			<content:encoded><![CDATA[<p>I recently had a problem on a job where no matter what we did, we could not control the left/right balance programmatically on two specific PC&#8217;s.</p>
<p>We tried using various methods:</p>
<ol>
<li>Windows Media player API</li>
<li>DirectSound APi</li>
<li>WinMM.dll</li>
<li>Praying</li>
</ol>
<p>None of them worked although you could control the balance using the Windows sound vol (sndvol.exe) program from the taskbar.</p>
<p>We decided to try and use the same method so out came Depends.exe and we loaded the sndvol.exe to see what libraries and methods it was loading. We discovered a likely method called mixerSetControlDetails() and promptly started to google it to discover how it worked.</p>
<p>The following example is the result. After a lot of searching for c# code samples, I found a chinese site that had a code listing that I could modify to possibly fix our problem. </p>
<p>Well to cut a long story very short (not much time today), I got it working and implemented into the project. The code is below so feel free to use as you wish. </p>
<p><span style="color: #99cc00;">SoundControl.cs</span><br />
<code><br />
using System;<br />
using System.Collections.Generic;<br />
using System.Linq;<br />
using System.Text;<br />
using System.Runtime.InteropServices;</p>
<p>class SoundControl<br />
{<br />
#region declarations</p>
<p>const int MAXPNAMELEN = 32;<br />
const int MIXER_SHORT_NAME_CHARS = 16;<br />
const int MIXER_LONG_NAME_CHARS = 64;</p>
<p>[Flags]<br />
enum MIXERLINE_LINEF : uint<br />
{<br />
ACTIVE = 0x00000001,<br />
DISCONNECTED = 0x00008000,<br />
SOURCE = 0x80000000<br />
}<br />
[Flags]<br />
enum MIXER : uint<br />
{<br />
GETLINEINFOF_DESTINATION = 0x00000000,<br />
GETLINEINFOF_SOURCE = 0x00000001,<br />
GETLINEINFOF_LINEID = 0x00000002,<br />
GETLINEINFOF_COMPONENTTYPE = 0x00000003,<br />
GETLINEINFOF_TARGETTYPE = 0x00000004,<br />
GETLINEINFOF_QUERYMASK = 0x0000000F,</p>
<p>GETLINECONTROLSF_ALL = 0x00000000,<br />
GETLINECONTROLSF_ONEBYID = 0x00000001,<br />
GETLINECONTROLSF_ONEBYTYPE = 0x00000002,<br />
GETLINECONTROLSF_QUERYMASK = 0x0000000F,</p>
<p>GETCONTROLDETAILSF_VALUE = 0x00000000,<br />
GETCONTROLDETAILSF_LISTTEXT = 0x00000001,<br />
GETCONTROLDETAILSF_QUERYMASK = 0x0000000F,</p>
<p>OBJECTF_MIXER = 0x00000000,<br />
OBJECTF_WAVEOUT = 0x10000000,<br />
OBJECTF_WAVEIN = 0x20000000,<br />
OBJECTF_MIDIOUT = 0x30000000,<br />
OBJECTF_MIDIIN = 0x40000000,<br />
OBJECTF_AUX = 0x50000000,<br />
OBJECTF_HANDLE = 0x80000000,<br />
OBJECTF_HMIXER = OBJECTF_HANDLE | OBJECTF_MIXER,<br />
OBJECTF_HWAVEOUT = OBJECTF_HANDLE | OBJECTF_WAVEOUT,<br />
OBJECTF_HWAVEIN = OBJECTF_HANDLE | OBJECTF_WAVEIN,<br />
OBJECTF_HMIDIOUT = OBJECTF_HANDLE | OBJECTF_MIDIOUT,<br />
OBJECTF_HMIDIIN = OBJECTF_HANDLE | OBJECTF_MIDIIN<br />
}<br />
[Flags]<br />
enum MIXERCONTROL_CT : uint<br />
{<br />
CLASS_MASK = 0xF0000000,<br />
CLASS_CUSTOM = 0x00000000,<br />
CLASS_METER = 0x10000000,<br />
CLASS_SWITCH = 0x20000000,<br />
CLASS_NUMBER = 0x30000000,<br />
CLASS_SLIDER = 0x40000000,<br />
CLASS_FADER = 0x50000000,<br />
CLASS_TIME = 0x60000000,<br />
CLASS_LIST = 0x70000000,</p>
<p>SUBCLASS_MASK = 0x0F000000,</p>
<p>SC_SWITCH_BOOLEAN = 0x00000000,<br />
SC_SWITCH_BUTTON = 0x01000000,</p>
<p>SC_METER_POLLED = 0x00000000,</p>
<p>SC_TIME_MICROSECS = 0x00000000,<br />
SC_TIME_MILLISECS = 0x01000000,</p>
<p>SC_LIST_SINGLE = 0x00000000,<br />
SC_LIST_MULTIPLE = 0x01000000,</p>
<p>UNITS_MASK = 0x00FF0000,<br />
UNITS_CUSTOM = 0x00000000,<br />
UNITS_BOOLEAN = 0x00010000,<br />
UNITS_SIGNED = 0x00020000,<br />
UNITS_UNSIGNED = 0x00030000,<br />
UNITS_DECIBELS = 0x00040000, /* in 10ths */<br />
UNITS_PERCENT = 0x00050000, /* in 10ths */<br />
}<br />
[Flags]<br />
enum MIXERCONTROL_CONTROLTYPE : uint<br />
{<br />
CUSTOM = MIXERCONTROL_CT.CLASS_CUSTOM | MIXERCONTROL_CT.UNITS_CUSTOM,<br />
BOOLEANMETER = MIXERCONTROL_CT.CLASS_METER | MIXERCONTROL_CT.SC_METER_POLLED | MIXERCONTROL_CT.UNITS_BOOLEAN,<br />
SIGNEDMETER = MIXERCONTROL_CT.CLASS_METER | MIXERCONTROL_CT.SC_METER_POLLED | MIXERCONTROL_CT.UNITS_SIGNED,<br />
PEAKMETER = SIGNEDMETER + 1,<br />
UNSIGNEDMETER = MIXERCONTROL_CT.CLASS_METER | MIXERCONTROL_CT.SC_METER_POLLED | MIXERCONTROL_CT.UNITS_UNSIGNED,<br />
BOOLEAN = MIXERCONTROL_CT.CLASS_SWITCH | MIXERCONTROL_CT.SC_SWITCH_BOOLEAN | MIXERCONTROL_CT.UNITS_BOOLEAN,<br />
ONOFF = BOOLEAN + 1,<br />
MUTE = BOOLEAN + 2,<br />
MONO = BOOLEAN + 3,<br />
LOUDNESS = BOOLEAN + 4,<br />
STEREOENH = BOOLEAN + 5,<br />
BASS_BOOST = BOOLEAN + 0x00002277,<br />
BUTTON = MIXERCONTROL_CT.CLASS_SWITCH | MIXERCONTROL_CT.SC_SWITCH_BUTTON | MIXERCONTROL_CT.UNITS_BOOLEAN,<br />
DECIBELS = MIXERCONTROL_CT.CLASS_NUMBER | MIXERCONTROL_CT.UNITS_DECIBELS,<br />
SIGNED = MIXERCONTROL_CT.CLASS_NUMBER | MIXERCONTROL_CT.UNITS_SIGNED,<br />
UNSIGNED = MIXERCONTROL_CT.CLASS_NUMBER | MIXERCONTROL_CT.UNITS_UNSIGNED,<br />
PERCENT = MIXERCONTROL_CT.CLASS_NUMBER | MIXERCONTROL_CT.UNITS_PERCENT,<br />
SLIDER = MIXERCONTROL_CT.CLASS_SLIDER | MIXERCONTROL_CT.UNITS_SIGNED,<br />
PAN = SLIDER + 1,<br />
QSOUNDPAN = SLIDER + 2,<br />
FADER = MIXERCONTROL_CT.CLASS_FADER | MIXERCONTROL_CT.UNITS_UNSIGNED,<br />
VOLUME = FADER + 1,<br />
BASS = FADER + 2,<br />
TREBLE = FADER + 3,<br />
EQUALIZER = FADER + 4,<br />
SINGLESELECT = MIXERCONTROL_CT.CLASS_LIST | MIXERCONTROL_CT.SC_LIST_SINGLE | MIXERCONTROL_CT.UNITS_BOOLEAN,<br />
MUX = SINGLESELECT + 1,<br />
MULTIPLESELECT = MIXERCONTROL_CT.CLASS_LIST | MIXERCONTROL_CT.SC_LIST_MULTIPLE | MIXERCONTROL_CT.UNITS_BOOLEAN,<br />
MIXER = MULTIPLESELECT + 1,<br />
MICROTIME = MIXERCONTROL_CT.CLASS_TIME | MIXERCONTROL_CT.SC_TIME_MICROSECS | MIXERCONTROL_CT.UNITS_UNSIGNED,<br />
MILLITIME = MIXERCONTROL_CT.CLASS_TIME | MIXERCONTROL_CT.SC_TIME_MILLISECS | MIXERCONTROL_CT.UNITS_UNSIGNED<br />
}</p>
<p>[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]<br />
struct MIXERLINE<br />
{<br />
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]<br />
public struct TargetInfo<br />
{<br />
public uint dwType;<br />
public uint dwDeviceID;<br />
public ushort wMid;<br />
public ushort wPid;<br />
public uint vDriverVersion;<br />
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAXPNAMELEN)]<br />
public string szPname;<br />
}</p>
<p>public uint cbStruct;<br />
public uint dwDestination;<br />
public uint dwSource;<br />
public uint dwLineID;<br />
public MIXERLINE_LINEF fdwLine;<br />
public uint dwUser;<br />
public uint dwComponentType;<br />
public uint cChannels;<br />
public uint cConnection;<br />
public uint cControls;<br />
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MIXER_SHORT_NAME_CHARS)]<br />
public string szShortName;<br />
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MIXER_LONG_NAME_CHARS)]<br />
public string szName;<br />
public TargetInfo Target;<br />
}<br />
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]<br />
struct MIXERCONTROL<br />
{<br />
[StructLayout(LayoutKind.Explicit)]<br />
public struct BoundsInfo<br />
{<br />
[FieldOffset(0)]<br />
public int lMinimum;<br />
[FieldOffset(4)]<br />
public int lMaximum;<br />
[FieldOffset(0)]<br />
public uint dwMinimum;<br />
[FieldOffset(4)]<br />
public uint dwMaximum;<br />
[FieldOffset(8), MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]<br />
public uint[] dwReserved;<br />
}<br />
[StructLayout(LayoutKind.Explicit)]<br />
public struct MetricsInfo<br />
{<br />
[FieldOffset(0)]<br />
public uint cSteps;<br />
[FieldOffset(0)]<br />
public uint cbCustomData;<br />
[FieldOffset(4), MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]<br />
public uint[] dwReserved;<br />
}</p>
<p>public uint cbStruct;<br />
public uint dwControlID;<br />
public MIXERCONTROL_CONTROLTYPE dwControlType;<br />
public uint fdwControl;<br />
public uint cMultipleItems;<br />
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MIXER_SHORT_NAME_CHARS)]<br />
public string szShortName;<br />
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MIXER_LONG_NAME_CHARS)]<br />
public string szName;<br />
public BoundsInfo Bounds;<br />
public MetricsInfo Metrics;<br />
}<br />
[StructLayout(LayoutKind.Explicit)]<br />
struct MIXERLINECONTROLS<br />
{<br />
[FieldOffset(0)]<br />
public uint cbStruct;<br />
[FieldOffset(4)]<br />
public uint dwLineID;<br />
[FieldOffset(8)]<br />
public uint dwControlID;<br />
[FieldOffset(8)] // not a typo!  overlaps previous field<br />
public uint dwControlType;<br />
[FieldOffset(12)]<br />
public uint cControls;<br />
[FieldOffset(16)]<br />
public uint cbmxctrl;<br />
[FieldOffset(20)]<br />
public IntPtr pamxctrl;<br />
}<br />
[StructLayout(LayoutKind.Explicit)]<br />
struct MIXERCONTROLDETAILS<br />
{<br />
[FieldOffset(0)]<br />
public uint cbStruct;<br />
[FieldOffset(4)]<br />
public uint dwControlID;<br />
[FieldOffset(8)]<br />
public uint cChannels;<br />
[FieldOffset(12)]<br />
public IntPtr hwndOwner;<br />
[FieldOffset(12)] // not a typo!<br />
public uint cMultipleItems;<br />
[FieldOffset(16)]<br />
public uint cbDetails;<br />
[FieldOffset(20)]<br />
public IntPtr paDetails;<br />
}<br />
[StructLayout(LayoutKind.Sequential)]<br />
struct VOLUME<br />
{<br />
public int left;<br />
public int right;<br />
}<br />
struct MixerInfo<br />
{<br />
public uint volumeCtl;<br />
public uint muteCtl;<br />
public int minVolume;<br />
public int maxVolume;<br />
}</p>
<p>[DllImport("WinMM.dll", CharSet = CharSet.Auto)]<br />
static extern uint mixerGetLineInfo(IntPtr hmxobj, ref MIXERLINE pmxl, MIXER flags);</p>
<p>[DllImport("WinMM.dll", CharSet = CharSet.Auto)]<br />
static extern uint mixerGetLineControls(IntPtr hmxobj, ref MIXERLINECONTROLS pmxlc, MIXER flags);</p>
<p>[DllImport("WinMM.dll", CharSet = CharSet.Auto)]<br />
static extern uint mixerGetControlDetails(IntPtr hmxobj, ref MIXERCONTROLDETAILS pmxcd, MIXER flags);</p>
<p>[DllImport("WinMM.dll", CharSet = CharSet.Auto)]<br />
static extern uint mixerSetControlDetails(IntPtr hmxobj, ref MIXERCONTROLDETAILS pmxcd, MIXER flags);</p>
<p>#endregion declarations</p>
<p>#region private methods</p>
<p>static MixerInfo GetMixerControls()<br />
{<br />
MIXERLINE mxl = new MIXERLINE();<br />
MIXERLINECONTROLS mlc = new MIXERLINECONTROLS();<br />
mxl.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERLINE));<br />
mlc.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERLINECONTROLS));</p>
<p>mixerGetLineInfo(IntPtr.Zero, ref mxl, MIXER.OBJECTF_MIXER | MIXER.GETLINEINFOF_DESTINATION);</p>
<p>mlc.dwLineID = mxl.dwLineID;<br />
mlc.cControls = mxl.cControls;<br />
mlc.cbmxctrl = (uint)Marshal.SizeOf(typeof(MIXERCONTROL));<br />
mlc.pamxctrl = Marshal.AllocHGlobal((int)(mlc.cbmxctrl * mlc.cControls));</p>
<p>mixerGetLineControls(IntPtr.Zero, ref mlc, MIXER.OBJECTF_MIXER | MIXER.GETLINECONTROLSF_ALL);</p>
<p>MixerInfo rtn = new MixerInfo();</p>
<p>for (int i = 0; i &lt; mlc.cControls; i++)<br />
{<br />
MIXERCONTROL mxc = (MIXERCONTROL)Marshal.PtrToStructure((IntPtr)((int)mlc.pamxctrl + (int)mlc.cbmxctrl * i), typeof(MIXERCONTROL));<br />
switch (mxc.dwControlType)<br />
{<br />
case MIXERCONTROL_CONTROLTYPE.VOLUME:<br />
rtn.volumeCtl = mxc.dwControlID;<br />
rtn.minVolume = mxc.Bounds.lMinimum;<br />
rtn.maxVolume = mxc.Bounds.lMaximum;<br />
break;<br />
case MIXERCONTROL_CONTROLTYPE.MUTE:<br />
rtn.muteCtl = mxc.dwControlID;<br />
break;<br />
}<br />
}</p>
<p>Marshal.FreeHGlobal(mlc.pamxctrl);</p>
<p>return rtn;<br />
}<br />
static VOLUME GetVolume(MixerInfo mi)<br />
{<br />
MIXERCONTROLDETAILS mcd = new MIXERCONTROLDETAILS();<br />
mcd.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERCONTROLDETAILS));<br />
mcd.dwControlID = mi.volumeCtl;<br />
mcd.cMultipleItems = 0;<br />
mcd.cChannels = 2;<br />
mcd.cbDetails = (uint)Marshal.SizeOf(typeof(VOLUME));<br />
mcd.paDetails = Marshal.AllocHGlobal((int)mcd.cbDetails);</p>
<p>mixerGetControlDetails(IntPtr.Zero, ref mcd, MIXER.GETCONTROLDETAILSF_VALUE | MIXER.OBJECTF_MIXER);</p>
<p>VOLUME rtn = (VOLUME)Marshal.PtrToStructure(mcd.paDetails, typeof(VOLUME));</p>
<p>Marshal.FreeHGlobal(mcd.paDetails);</p>
<p>return rtn;<br />
}<br />
static bool IsMuted(MixerInfo mi)<br />
{<br />
MIXERCONTROLDETAILS mcd = new MIXERCONTROLDETAILS();<br />
mcd.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERCONTROLDETAILS));<br />
mcd.dwControlID = mi.muteCtl;<br />
mcd.cMultipleItems = 0;<br />
mcd.cChannels = 1;<br />
mcd.cbDetails = 4;<br />
mcd.paDetails = Marshal.AllocHGlobal((int)mcd.cbDetails);</p>
<p>mixerGetControlDetails(IntPtr.Zero, ref mcd, MIXER.GETCONTROLDETAILSF_VALUE | MIXER.OBJECTF_MIXER);</p>
<p>int rtn = Marshal.ReadInt32(mcd.paDetails);</p>
<p>Marshal.FreeHGlobal(mcd.paDetails);</p>
<p>return rtn != 0;<br />
}</p>
<p>static void MuteIt(MixerInfo mi, bool left, bool right)<br />
{<br />
VOLUME volume = GetVolume(mi);<br />
if (!left &amp;&amp; !right) // mute off<br />
{<br />
volume.left = 65530;<br />
volume.right = 65530;<br />
}<br />
else if (left) //mute left channel<br />
{<br />
volume.left = 0;<br />
volume.right = 65530;<br />
}<br />
else if (right) // mute right channel<br />
{<br />
volume.left = 65530;<br />
volume.right = 0;<br />
}</p>
<p>SetVolume(mi, volume);<br />
}</p>
<p>static void SetVolume(MixerInfo mi, VOLUME volume)<br />
{<br />
MIXERCONTROLDETAILS mcd = new MIXERCONTROLDETAILS();<br />
mcd.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERCONTROLDETAILS));<br />
mcd.dwControlID = mi.volumeCtl;<br />
mcd.cMultipleItems = 0;<br />
mcd.cChannels = 2;<br />
mcd.cbDetails = (uint)Marshal.SizeOf(typeof(VOLUME));<br />
mcd.paDetails = Marshal.AllocHGlobal((int)mcd.cbDetails);</p>
<p>Marshal.StructureToPtr(volume, mcd.paDetails, false);</p>
<p>mixerSetControlDetails(IntPtr.Zero, ref mcd, MIXER.GETCONTROLDETAILSF_VALUE | MIXER.OBJECTF_MIXER);</p>
<p>Marshal.FreeHGlobal(mcd.paDetails);<br />
}</p>
<p>#endregion private methods</p>
<p>#region public methods</p>
<p>/// &lt;summary&gt;<br />
/// Mutes the left hand channel and transfers audio fully to the right<br />
/// &lt;/summary&gt;<br />
public void MuteLeftChannel()<br />
{<br />
MixerInfo mi = GetMixerControls();<br />
MuteIt(mi, false, true);<br />
}</p>
<p>/// &lt;summary&gt;<br />
/// Mutes the right hand channel and transfers audio fully to the left<br />
/// &lt;/summary&gt;<br />
public void MuteRightChannel()<br />
{<br />
MixerInfo mi = GetMixerControls();<br />
MuteIt(mi, true, false);<br />
}</p>
<p>public void MuteOff()<br />
{<br />
MixerInfo mi = GetMixerControls();<br />
MuteIt(mi, false, false);<br />
}</p>
<p>#endregion public methods<br />
}</p>
<p>You call it as follows:</p>
<p>private void CreateSoundControl()<br />
{<br />
if (sndMute != null) return;<br />
sndMute = new SoundControl();<br />
}</p>
<p>private void btnRight_Click(object sender, EventArgs e)<br />
{<br />
CreateSoundControl();<br />
sndMute.MuteRightChannel();<br />
}</p>
<p>private void btnLeft_Click(object sender, EventArgs e)<br />
{<br />
CreateSoundControl();<br />
sndMute.MuteLeftChannel();<br />
}</p>
<p>private void btnCenter_Click(object sender, EventArgs e)<br />
{<br />
CreateSoundControl();<br />
sndMute.MuteOff();</p>
<p>}<br />
</code></p>
<p><a title="Download the source files here" href="http://blog.xploiter.com/wp-content/uploads/2009/04/mutesoundexample.zip">Download the source files here</a></p>
<p>Enjoy &#8211; remember if your machine blows up or crashes, do not blame me <img src='http://blog.xploiter.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.xploiter.com/c-and-aspnet/muting-audio-channels-mixer-control-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
