Пример #1
0
        static int GetBufferSize(XtStream stream, int frames)
        {
            XtFormat format     = stream.GetFormat();
            int      sampleSize = XtAudio.GetSampleAttributes(format.mix.sample).size;

            return(frames * format.inputs * sampleSize);
        }
Пример #2
0
        internal void OnCallback(XtStream stream, object input, object output, int frames,
                                 double time, ulong position, bool timeValid, ulong error, object user)
        {
            if (error != 0)
            {
                onError(() => "Stream callback error: " + XtPrint.ErrorToString(error));
                return;
            }

            XtFormat format      = stream.GetFormat();
            bool     interleaved = stream.IsInterleaved();

            OnCallback(format, interleaved, stream.IsRaw(), input, output, frames);
            processed += frames;
            if (processed < format.mix.rate * 3)
            {
                return;
            }

            processed = 0;
            XtLatency latency      = stream.GetLatency();
            string    formatString = "Stream {1}:{0}\tinput latency:{2}{0}\toutput latency:{3}{0}\t" +
                                     "buffer frames:{4}{0}\tcurrent frames:{5}{0}\ttime:{6}{0}\tposition:{7}{0}\ttimeValid:{8}{0}\tuser:{9}.";

            OnMessage(() => string.Format(formatString, Environment.NewLine, name, latency.input,
                                          latency.output, stream.GetFrames(), frames, time, position, timeValid, user));
        }
Пример #3
0
        static void OnAggregate(XtStream stream, object input, object output, int frames, double time,
                                ulong position, bool timeValid, ulong error, object user)
        {
            XtFormat     format = stream.GetFormat();
            XtAttributes attrs  = XtAudio.GetSampleAttributes(format.mix.sample);

            if (frames > 0)
            {
                Buffer.BlockCopy((Array)input, 0, (Array)output, 0, frames * format.inputs * attrs.size);
            }
        }
Пример #4
0
 internal XtSafeBuffer(XtStream stream, bool interleaved)
 {
     _stream      = stream;
     _interleaved = interleaved;
     _format      = stream.GetFormat();
     _inputs      = _format.channels.inputs;
     _outputs     = _format.channels.outputs;
     _attrs       = XtAudio.GetSampleAttributes(_format.mix.sample);
     _input       = CreateBuffer(_inputs);
     _output      = CreateBuffer(_outputs);
 }
Пример #5
0
        static unsafe void RenderNonInterleavedRaw(XtStream stream, object input, object output,
                                                   int frames, double time, ulong position, bool timeValid, ulong error, object user)
        {
            XtFormat format = stream.GetFormat();

            for (int f = 0; f < frames; f++)
            {
                float sine = NextSine(format.mix.rate);
                for (int c = 0; c < format.outputs; c++)
                {
                    ((float **)(IntPtr)output)[c][f] = sine;
                }
            }
        }
Пример #6
0
        static void RenderInterleaved(XtStream stream, object input, object output,
                                      int frames, double time, ulong position, bool timeValid, ulong error, object user)
        {
            XtFormat format = stream.GetFormat();

            for (int f = 0; f < frames; f++)
            {
                float sine = NextSine(format.mix.rate);
                for (int c = 0; c < format.outputs; c++)
                {
                    ((float[])output)[f * format.outputs + c] = sine;
                }
            }
        }
Пример #7
0
 static void CaptureNonInterleaved(XtStream stream, object input, object output,
                                   int frames, double time, ulong position, bool timeValid, ulong error, object user)
 {
     if (frames > 0)
     {
         Context  ctx        = (Context)user;
         XtFormat format     = stream.GetFormat();
         int      channels   = format.inputs;
         int      sampleSize = XtAudio.GetSampleAttributes(format.mix.sample).size;
         for (int f = 0; f < frames; f++)
         {
             for (int c = 0; c < channels; c++)
             {
                 // Don't do this.
                 ctx.recording.Write(((byte[][])input)[c], f * sampleSize, sampleSize);
             }
         }
     }
 }
Пример #8
0
 static unsafe void CaptureNonInterleavedRaw(XtStream stream, object input, object output,
                                             int frames, double time, ulong position, bool timeValid, ulong error, object user)
 {
     if (frames > 0)
     {
         Context  ctx        = (Context)user;
         XtFormat format     = stream.GetFormat();
         int      channels   = format.inputs;
         int      sampleSize = XtAudio.GetSampleAttributes(format.mix.sample).size;
         for (int f = 0; f < frames; f++)
         {
             for (int c = 0; c < channels; c++)
             {
                 IntPtr source = new IntPtr(&(((byte **)(IntPtr)input)[c][f * sampleSize]));
                 Marshal.Copy(source, ctx.intermediate, 0, sampleSize);
                 // Don't do this.
                 ctx.recording.Write(ctx.intermediate, 0, sampleSize);
             }
         }
     }
 }
Пример #9
0
        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);
            }
        }
Пример #10
0
        object Start()
        {
            StreamType type                  = (StreamType)_streamType.SelectedItem;
            bool       input                 = type == StreamType.Capture || type == StreamType.Duplex;
            bool       output                = type == StreamType.Render || type == StreamType.Duplex;
            var        inputInfo             = _input._device.SelectedItem as DeviceInfo;
            var        outputInfo            = _output._device.SelectedItem as DeviceInfo;
            XtDevice   inputDevice           = inputInfo?.Device;
            XtDevice   outputDevice          = outputInfo?.Device;
            XtDevice   secondaryInputDevice  = (_secondaryInput.SelectedItem as DeviceInfo).Device;
            XtDevice   secondaryOutputDevice = (_secondaryOutput.SelectedItem as DeviceInfo).Device;

            bool   anyInput         = inputDevice != null || secondaryInputDevice != null;
            bool   anyOutput        = outputDevice != null || secondaryOutputDevice != null;
            string duplexMessage    = "For duplex operation, input and output device must be the same.";
            string aggregateMessage = "For aggregate operation, select at least 1 input and 1 output device.";

            if (input && inputDevice == null)
            {
                return(MessageBox.Show(this, "Select an input device.", "Invalid input device."));
            }
            if (output && outputDevice == null)
            {
                return(MessageBox.Show(this, "Select an output device.", "Invalid output device."));
            }
            if (type == StreamType.Duplex && inputInfo.Id != outputInfo.Id)
            {
                return(MessageBox.Show(this, duplexMessage, "Invalid duplex device."));
            }
            if (type == StreamType.Aggregate && (!anyInput || !anyOutput))
            {
                return(MessageBox.Show(this, aggregateMessage, "Invalid aggregate device."));
            }

            var      state         = _logXRuns.CheckState;
            XtSystem system        = (XtSystem)_system.SelectedItem;
            OnXRun   onXRunWrapper = new OnXRun(AddMessage);
            bool     doLogXRuns    = state == CheckState.Checked || (state == CheckState.Indeterminate && system != XtSystem.JACK);
            XtOnXRun onXRun        = doLogXRuns ? onXRunWrapper.Callback : (XtOnXRun)null;

            XtFormat inputFormat    = GetFormat(false).Value;
            var      inputSelection = _input._channels.SelectedItems;

            inputFormat.channels.inputs = (int)_channelCount.SelectedItem;
            string inputChannelMessage = "Selected either 0 input channels or a number equal to the selected format's channels.";

            if (input && inputSelection.Count > 0 && inputSelection.Count != inputFormat.channels.inputs)
            {
                return(MessageBox.Show(this, inputChannelMessage, "Invalid input channel mask."));
            }
            for (int c = 0; c < inputSelection.Count; c++)
            {
                inputFormat.channels.inMask |= (1UL << ((ChannelInfo)inputSelection[c]).Index);
            }

            XtFormat outputFormat    = GetFormat(true).Value;
            var      outputSelection = _output._channels.SelectedItems;

            outputFormat.channels.outputs = (int)_channelCount.SelectedItem;
            string outputChannelMessage = "Selected either 0 output channels or a number equal to the selected format's channels.";

            if (output && outputSelection.Count > 0 && outputSelection.Count != outputFormat.channels.outputs)
            {
                return(MessageBox.Show(this, outputChannelMessage, "Invalid output channel mask."));
            }
            for (int c = 0; c < outputSelection.Count; c++)
            {
                outputFormat.channels.outMask |= (1UL << ((ChannelInfo)outputSelection[c]).Index);
            }

            int  buffer      = _bufferSize.Value;
            bool native      = _streamNative.Checked;
            bool interleaved = _streamInterleaved.Checked;

            var @params = new OnBufferParams(interleaved, native, AddMessage);

            if (type == StreamType.Capture)
            {
                @params.Name = "Capture";
                _captureFile = new FileStream("xt-audio.raw", FileMode.Create, FileAccess.Write);
                OnCapture callback     = new OnCapture(@params, _captureFile);
                var       streamParams = new XtStreamParams(interleaved, callback.Callback, onXRun, OnRunning);
                var       deviceParams = new XtDeviceStreamParams(in streamParams, in inputFormat, buffer);
                _stream = inputDevice.OpenStream(in deviceParams, "capture-user-data");
                callback.Init(_stream.GetFormat(), _stream.GetFrames());
                _safeBuffer = XtSafeBuffer.Register(_stream, interleaved);
                _stream.Start();
            }
            else if (type == StreamType.Render)
            {
                @params.Name = "Render";
                OnRender callback     = new OnRender(@params);
                var      streamParams = new XtStreamParams(interleaved, callback.Callback, onXRun, OnRunning);
                var      deviceParams = new XtDeviceStreamParams(in streamParams, in outputFormat, buffer);
                _stream     = outputDevice.OpenStream(in deviceParams, "render-user-data");
                _safeBuffer = XtSafeBuffer.Register(_stream, interleaved);
                _stream.Start();
            }
            else if (type == StreamType.Duplex)
            {
                @params.Name = "Duplex";
                XtFormat duplexFormat = inputFormat;
                duplexFormat.channels.outputs = outputFormat.channels.outputs;
                duplexFormat.channels.outMask = outputFormat.channels.outMask;
                OnFullDuplex callback     = new OnFullDuplex(@params);
                var          streamParams = new XtStreamParams(interleaved, callback.Callback, onXRun, OnRunning);
                var          deviceParams = new XtDeviceStreamParams(in streamParams, in duplexFormat, buffer);
                _stream     = outputDevice.OpenStream(in deviceParams, "duplex-user-data");
                _safeBuffer = XtSafeBuffer.Register(_stream, interleaved);
                _stream.Start();
            }
            else if (type == StreamType.Aggregate)
            {
                @params.Name = "Aggregate";
                var      devices = new List <XtAggregateDeviceParams>();
                XtDevice master  = _outputMaster.Checked ? (outputDevice ?? secondaryOutputDevice) : (inputDevice ?? secondaryInputDevice);
                if (inputDevice != null)
                {
                    devices.Add(new XtAggregateDeviceParams(inputDevice, inputFormat.channels, buffer));
                }
                if (outputDevice != null)
                {
                    devices.Add(new XtAggregateDeviceParams(outputDevice, outputFormat.channels, buffer));
                }
                if (secondaryInputDevice != null)
                {
                    devices.Add(new XtAggregateDeviceParams(secondaryInputDevice, inputFormat.channels, buffer));
                }
                if (secondaryOutputDevice != null)
                {
                    devices.Add(new XtAggregateDeviceParams(secondaryOutputDevice, outputFormat.channels, buffer));
                }
                OnAggregate streamCallback  = new OnAggregate(@params);
                var         streamParams    = new XtStreamParams(interleaved, streamCallback.Callback, onXRun, OnRunning);
                var         aggregateParams = new XtAggregateStreamParams(in streamParams, devices.ToArray(), devices.Count, outputFormat.mix, master);
                _stream = _platform.GetService(system).AggregateStream(in aggregateParams, "aggregate-user-data");
                streamCallback.Init(_stream.GetFrames());
                _safeBuffer = XtSafeBuffer.Register(_stream, interleaved);
                _stream.Start();
            }
            return(null);
        }