public static void Main(string[] args) { XtMix mix = new XtMix(48000, XtSample.Int16); XtFormat inputFormat = new XtFormat(mix, 2, 0, 0, 0); XtChannels inputChannels = new XtChannels(2, 0, 0, 0); XtFormat outputFormat = new XtFormat(mix, 0, 0, 2, 0); XtChannels outputChannels = new XtChannels(0, 0, 2, 0); using (XtAudio audio = new XtAudio(null, IntPtr.Zero, null, null)) { XtService service = XtAudio.GetServiceBySetup(XtSetup.SystemAudio); using (XtDevice input = service.OpenDefaultDevice(false)) using (XtDevice output = service.OpenDefaultDevice(true)) { if (input != null && input.SupportsFormat(inputFormat) && output != null && output.SupportsFormat(outputFormat)) { using (XtStream stream = service.AggregateStream( new XtDevice[] { input, output }, new XtChannels[] { inputChannels, outputChannels }, new double[] { 30.0, 30.0 }, 2, mix, true, false, output, OnAggregate, XRun, "user-data")) { stream.Start(); Console.WriteLine("Streaming aggregate, press any key to continue..."); Console.ReadLine(); stream.Stop(); } } } } }
internal static extern IntPtr XtPrintChannelsToString(XtChannels channels);
private void OnStart(object sender, EventArgs ea) { try { StreamType type = (StreamType)streamType.SelectedItem; bool input = type == StreamType.Capture || type == StreamType.Duplex || type == StreamType.Latency; bool output = type == StreamType.Render || type == StreamType.Duplex || type == StreamType.Latency; XtDevice inputDevice = ((DeviceView)this.inputDevice.SelectedItem).device; XtDevice outputDevice = ((DeviceView)this.outputDevice.SelectedItem).device; XtDevice secondaryInputDevice = ((DeviceView)this.secondaryInput.SelectedItem).device; XtDevice secondaryOutputDevice = ((DeviceView)this.secondaryOutput.SelectedItem).device; if (input && inputDevice == null) { MessageBox.Show(this, "Select an input device.", "Invalid input device."); return; } if (output && outputDevice == null) { MessageBox.Show(this, "Select an output device.", "Invalid output device."); return; } if (type == StreamType.Duplex && outputDevice != inputDevice) { MessageBox.Show(this, "For duplex operation, input and output device must be the same.", "Invalid duplex device."); return; } if (type == StreamType.Aggregate && (inputDevice == null && secondaryInputDevice == null || outputDevice == null && secondaryOutputDevice == null)) { MessageBox.Show(this, "For aggregate operation, select at least 1 input and 1 output device.", "Invalid aggregate device."); return; } XRunCallback xRunCallback = new XRunCallback(AddMessage); XtFormat inputFormat = GetFormat(false); inputFormat.inputs = (int)channelCount.SelectedItem; if (input && inputChannels.SelectedItems.Count > 0 && inputChannels.SelectedItems.Count != inputFormat.inputs) { MessageBox.Show(this, "Selected either 0 input channels or a number equal to the selected format's channels.", "Invalid input channel mask."); return; } for (int c = 0; c < inputChannels.SelectedItems.Count; c++) { inputFormat.inMask |= (1UL << ((ChannelView)inputChannels.SelectedItems[c]).index); } XtFormat outputFormat = GetFormat(true); if (output && outputChannels.SelectedItems.Count > 0 && outputChannels.SelectedItems.Count != outputFormat.outputs) { MessageBox.Show(this, "Selected either 0 output channels or a number equal to the selected format's channels.", "Invalid output channel mask."); return; } for (int c = 0; c < outputChannels.SelectedItems.Count; c++) { outputFormat.outMask |= (1UL << ((ChannelView)outputChannels.SelectedItems[c]).index); } if (type == StreamType.Capture) { captureFile = new FileStream("xt-audio.raw", FileMode.Create, FileAccess.Write); CaptureCallback callback = new CaptureCallback(OnStreamError, AddMessage, captureFile); inputStream = inputDevice.OpenStream(inputFormat, streamInterleaved.Checked, streamRaw.Checked, bufferSize.Value, callback.OnCallback, xRunCallback.OnCallback, "capture-user-data"); callback.Init(inputStream.GetFormat(), inputStream.GetFrames()); inputStream.Start(); } else if (type == StreamType.Render) { RenderCallback callback = new RenderCallback(OnStreamError, AddMessage); outputStream = outputDevice.OpenStream(outputFormat, streamInterleaved.Checked, streamRaw.Checked, bufferSize.Value, callback.OnCallback, xRunCallback.OnCallback, "render-user-data"); outputStream.Start(); } else if (type == StreamType.Duplex) { XtFormat duplexFormat = inputFormat; duplexFormat.outputs = outputFormat.outputs; duplexFormat.outMask = outputFormat.outMask; FullDuplexCallback callback = new FullDuplexCallback(OnStreamError, AddMessage); outputStream = outputDevice.OpenStream(duplexFormat, streamInterleaved.Checked, streamRaw.Checked, bufferSize.Value, callback.OnCallback, xRunCallback.OnCallback, "duplex-user-data"); outputStream.Start(); } else if (type == StreamType.Aggregate) { List <XtDevice> devices = new List <XtDevice>(); List <double> bufferSizes = new List <double>(); List <XtChannels> channels = new List <XtChannels>(); if (inputDevice != null) { devices.Add(inputDevice); bufferSizes.Add(bufferSize.Value); channels.Add(new XtChannels(inputFormat.inputs, inputFormat.inMask, 0, 0)); } if (outputDevice != null) { devices.Add(outputDevice); bufferSizes.Add(bufferSize.Value); channels.Add(new XtChannels(0, 0, outputFormat.outputs, outputFormat.outMask)); } if (secondaryInputDevice != null) { devices.Add(secondaryInputDevice); bufferSizes.Add(bufferSize.Value); channels.Add(new XtChannels(inputFormat.inputs, inputFormat.inMask, 0, 0)); } if (secondaryOutputDevice != null) { devices.Add(secondaryOutputDevice); bufferSizes.Add(bufferSize.Value); channels.Add(new XtChannels(0, 0, outputFormat.outputs, outputFormat.outMask)); } XtDevice[] devicesArray = devices.ToArray(); double[] bufferSizesArray = bufferSizes.ToArray(); XtChannels[] channelsArray = channels.ToArray(); XtDevice master = outputMaster.Checked ? (outputDevice != null ? outputDevice : secondaryOutputDevice != null ? secondaryOutputDevice : inputDevice != null ? inputDevice : secondaryInputDevice) : (inputDevice != null ? inputDevice : secondaryInputDevice != null ? secondaryInputDevice : outputDevice != null ? outputDevice : secondaryOutputDevice); AggregateCallback streamCallback = new AggregateCallback(OnStreamError, AddMessage); outputStream = ((XtService)service.SelectedItem).AggregateStream(devicesArray, channelsArray, bufferSizesArray, devicesArray.Length, outputFormat.mix, streamInterleaved.Checked, streamRaw.Checked, master, streamCallback.OnCallback, xRunCallback.OnCallback, "aggregate-user-data"); streamCallback.Init(outputStream.GetFrames()); outputStream.Start(); } else if (inputDevice == outputDevice) { XtFormat duplexFormat = inputFormat; duplexFormat.outputs = outputFormat.outputs; duplexFormat.outMask = outputFormat.outMask; LatencyCallback callback = new LatencyCallback(OnStreamError, AddMessage); outputStream = outputDevice.OpenStream(duplexFormat, streamInterleaved.Checked, streamRaw.Checked, bufferSize.Value, callback.OnCallback, xRunCallback.OnCallback, "latency-user-data"); outputStream.Start(); } else { XtDevice[] devices = new XtDevice[] { inputDevice, outputDevice }; double[] bufferSizes = new double[] { bufferSize.Value, bufferSize.Value }; XtChannels[] channels = new XtChannels[] { new XtChannels(inputFormat.inputs, inputFormat.inMask, 0, 0), new XtChannels(0, 0, outputFormat.outputs, outputFormat.outMask) }; XtDevice master = outputMaster.Checked ? outputDevice : inputDevice; LatencyCallback callback = new LatencyCallback(OnStreamError, AddMessage); outputStream = ((XtService)service.SelectedItem).AggregateStream(devices, channels, bufferSizes, devices.Length, outputFormat.mix, streamInterleaved.Checked, streamRaw.Checked, master, callback.OnCallback, xRunCallback.OnCallback, "latency-user-data"); outputStream.Start(); } stop.Enabled = true; panel.Enabled = false; start.Enabled = false; streamRaw.Enabled = false; bufferSize.Enabled = false; streamType.Enabled = false; outputMaster.Enabled = false; secondaryInput.Enabled = false; secondaryOutput.Enabled = false; streamInterleaved.Enabled = false; } catch (XtException e) { Stop(); MessageBox.Show(this, e.ToString(), "Failed to start stream.", MessageBoxButtons.OK, MessageBoxIcon.Error); } }