private static Tuple <int, int> GetSelectedDevices(string apiName, int inDeviceId, int outDeviceId, string inputDeviceName, string outputDeviceName) { var devices = Enumerable.Range(0, PortAudio.Pa_GetDeviceCount()) .ToDictionary(x => x, x => PortAudio.Pa_GetDeviceInfo(x)) .Where(x => PortAudio.Pa_GetHostApiInfo(x.Value.hostApi).name == apiName) .ToDictionary(x => x.Key, x => x.Value); int realInputDeviceId; int realOutputDeviceId; var matchedInputArr = devices.Where(x => x.Key == inDeviceId && x.Value.name == inputDeviceName).ToArray(); if (matchedInputArr.Length == 1) { realInputDeviceId = matchedInputArr[0].Key; } else { realInputDeviceId = devices.Where(x => x.Value.name == inputDeviceName).First().Key; } var matchedOutputArr = devices.Where(x => x.Key == outDeviceId && x.Value.name == outputDeviceName).ToArray(); if (matchedOutputArr.Length == 1) { realOutputDeviceId = matchedOutputArr[0].Key; } else { realOutputDeviceId = devices.Where(x => x.Value.name == outputDeviceName).First().Key; } return(Tuple.Create(realInputDeviceId, realOutputDeviceId)); }
private RealtimeHost() { if (!PortAudio.Pa_IsInitialized) { PortAudio.Pa_Initialize(); } StreamState = StreamState.Closed; }
public static RealtimeHostConfig Deserialize(string serializedString) { try { var dict = serializedString .Split('\n') .Where(x => x.Contains('=')) .Select(x => x.Trim()) .ToDictionary(x => x.Split('=')[0].Trim(), x => x.Split('=')[1].Trim()); var apiName = dict["APIName"]; var inDeviceId = Convert.ToInt32(dict["InputDeviceID"]); var outDeviceId = Convert.ToInt32(dict["OutputDeviceID"]); var inputDeviceName = dict["InputDeviceName"]; var outputDeviceName = dict["OutputDeviceName"]; var numInputs = Convert.ToInt32(dict["NumberOfInputs"]); var numOutputs = Convert.ToInt32(dict["NumberOfOutputs"]); // fuzzy matching of devices as the deviceIds can change // prefers a device that matches on apiName, deviceId and deviceName, but falls back to match only apiName and deviceName if not found var devices = GetSelectedDevices(apiName, inDeviceId, outDeviceId, inputDeviceName, outputDeviceName); var realInputDeviceId = devices.Item1; var realOutputDeviceId = devices.Item2; var inDevice = PortAudio.Pa_GetDeviceInfo(realInputDeviceId); var outDevice = PortAudio.Pa_GetDeviceInfo(realOutputDeviceId); if (inDevice.maxInputChannels < numInputs) { numInputs = inDevice.maxInputChannels; } if (outDevice.maxOutputChannels < numOutputs) { numOutputs = outDevice.maxOutputChannels; } var conf = new RealtimeHostConfig(); conf.InputDeviceID = realInputDeviceId; conf.OutputDeviceID = realOutputDeviceId; conf.NumberOfInputs = numInputs; conf.NumberOfOutputs = numOutputs; conf.Samplerate = Convert.ToInt32(dict["Samplerate"]); conf.BufferSize = Convert.ToUInt32(dict["BufferSize"]); return(conf); } catch { return(null); } }
public void StartStream() { if (StreamState != StreamState.Open) { throw new Exception("Trying to Start a stream that does not have State: Open. State is " + StreamState.ToString()); } var err = PortAudio.Pa_StartStream(Config.Stream); if (err != PortAudio.PaError.paNoError) { throw new Exception(PortAudio.Pa_GetErrorText(err)); } StreamState = StreamState.Started; }
public RealtimeHostConfig() { int defaultInput = PortAudio.Pa_GetDefaultInputDevice(); var inputInfo = PortAudio.Pa_GetDeviceInfo(defaultInput); inputParameters = new PortAudio.PaStreamParameters(); inputParameters.device = defaultInput; inputParameters.sampleFormat = PortAudio.PaSampleFormat.paFloat32 | PortAudio.PaSampleFormat.paNonInterleaved; /* 32 bit floating point output */ inputParameters.suggestedLatency = inputInfo.defaultLowInputLatency; inputParameters.hostApiSpecificStreamInfo = (IntPtr)0; int defaultOutput = PortAudio.Pa_GetDefaultOutputDevice(); var outputInfo = PortAudio.Pa_GetDeviceInfo(defaultInput); outputParameters = new PortAudio.PaStreamParameters(); outputParameters.device = defaultOutput; outputParameters.sampleFormat = PortAudio.PaSampleFormat.paFloat32 | PortAudio.PaSampleFormat.paNonInterleaved; /* 32 bit floating point output */ outputParameters.suggestedLatency = outputInfo.defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = (IntPtr)0; }
public void populateHostAPIs() { int hostCount = PortAudio.Pa_GetHostApiCount(); for (int i = 0; i < hostCount; i++) { hostInfos.Add(PortAudio.Pa_GetHostApiInfo(i)); } int deviceCount = PortAudio.Pa_GetDeviceCount(); for (int i = 0; i < deviceCount; i++) { deviceInfos.Add(PortAudio.Pa_GetDeviceInfo(i)); } foreach (var info in hostInfos) { comboBoxHost.Items.Add(info.name); } }
public void CloseStream() { if (StreamState != StreamState.Stopped) { throw new Exception("Trying to Close a stream that does not have State: Stopped. State is " + StreamState.ToString()); } if (Config == null) { return; } var err = PortAudio.Pa_CloseStream(Config.Stream); if (err != PortAudio.PaError.paNoError) { throw new Exception(PortAudio.Pa_GetErrorText(err)); } StreamState = StreamState.Closed; }
public void OpenStream() { if (Config == null) { throw new Exception("Configuration settings have not been applied. You must first configure the host"); } if (StreamState != StreamState.Closed) { throw new Exception("Trying to Open a stream that does not have State: Closed. State is " + StreamState.ToString()); } callbackDelegate = RealtimeCallback; streamFinishedDelegate = StreamFinished; var err = PortAudio.Pa_OpenStream( out Config.Stream, ref Config.inputParameters, ref Config.outputParameters, Samplerate, BufferSize, (PortAudio.PaStreamFlags.paClipOff | PortAudio.PaStreamFlags.paDitherOff), callbackDelegate, new IntPtr(0) ); if (err != PortAudio.PaError.paNoError) { throw new Exception(PortAudio.Pa_GetErrorText(err)); } err = PortAudio.Pa_SetStreamFinishedCallback(Config.Stream, streamFinishedDelegate); if (err != PortAudio.PaError.paNoError) { throw new Exception(PortAudio.Pa_GetErrorText(err)); } StreamState = StreamState.Open; }
public HostInfo(PortAudio.PaHostApiInfo val) { value = val; }
public DeviceInfo(PortAudio.PaDeviceInfo val) { value = val; }
private void labelASIO_Click(object sender, EventArgs e) { PortAudio.PaAsio_ShowControlPanel(InputDeviceID, this.Handle); }
PortAudio.PaStreamCallbackResult RealtimeCallback(IntPtr inputBuffer, IntPtr outputBuffer, uint framesPerBuffer, ref PortAudio.PaStreamCallbackTimeInfo timeInfo, PortAudio.PaStreamCallbackFlags statusFlags, IntPtr userData) { if(UseDirectProcessing) { var ins = (float**)inputBuffer; var outs = (float**)outputBuffer; ProcessDirect(ins, outs, (int)framesPerBuffer); return PortAudio.PaStreamCallbackResult.paContinue; } float[][] Inputs = new float[NumberOfInputs][]; float[][] Outputs = new float[NumberOfOutputs][]; // create input channels and copy data into them for (int i = 0; i < NumberOfInputs; i++) { float* inChannel = (float*)((float**)inputBuffer)[i]; float[] inArr = new float[framesPerBuffer]; Marshal.Copy((IntPtr)inChannel, inArr, 0, (int)framesPerBuffer); Inputs[i] = inArr; } // create empty output array for (int i = 0; i < NumberOfOutputs; i++) { float[] outArr = new float[framesPerBuffer]; Outputs[i] = outArr; } // Call the process function Process(Inputs, Outputs); // Copy data back from managed array into native array for (int i = 0; i < NumberOfOutputs; i++) { float* outChannel = (float*)((float**)outputBuffer)[i]; float[] outArr = Outputs[i]; Marshal.Copy(outArr, 0, (IntPtr)outChannel, (int)framesPerBuffer); } return PortAudio.PaStreamCallbackResult.paContinue; }
public static RealtimeHostConfig CreateConfig(RealtimeHostConfig config = null) { if (!PortAudio.Pa_IsInitialized) { PortAudio.Pa_Initialize(); } Application.EnableVisualStyles(); var editor = new RealtimeHostConfigEditor(); if (config != null) { var apiName = config.APIName; var devices = GetSelectedDevices(apiName, config.InputDeviceID, config.OutputDeviceID, config.InputDeviceName, config.OutputDeviceName); var realInputDeviceId = devices.Item1; var realOutputDeviceId = devices.Item2; var inDevice = PortAudio.Pa_GetDeviceInfo(realInputDeviceId); var outDevice = PortAudio.Pa_GetDeviceInfo(realOutputDeviceId); var numInputs = (config.NumberOfInputs < inDevice.maxInputChannels) ? config.NumberOfInputs : inDevice.maxInputChannels; var numOutputs = (config.NumberOfOutputs < inDevice.maxOutputChannels) ? config.NumberOfOutputs : outDevice.maxOutputChannels; editor.InputDeviceID = realInputDeviceId; editor.OutputDeviceID = realOutputDeviceId; editor.Samplerate = config.Samplerate; editor.Latency = (int)(config.InputLatencyMs * config.Samplerate); editor.InputChannels = numInputs; editor.OutputChannels = numOutputs; } editor.ShowDialog(); if (editor.OK == false) { return(null); } else { var conf = new RealtimeHostConfig(); conf.InputDeviceID = editor.InputDeviceID; conf.OutputDeviceID = editor.OutputDeviceID; conf.NumberOfInputs = editor.InputChannels; conf.NumberOfOutputs = editor.OutputChannels; conf.Samplerate = editor.Samplerate; conf.InputLatencyMs = editor.Latency / (double)editor.Samplerate; conf.OutputLatencyMs = editor.Latency / (double)editor.Samplerate; var supported = PortAudio.Pa_IsFormatSupported(ref conf.inputParameters, ref conf.outputParameters, conf.Samplerate); if (supported == PortAudio.PaError.paInvalidSampleRate) { throw new InvalidFormatException("The samplerate you have selected is not supported by the device"); } if (supported == PortAudio.PaError.paInvalidChannelCount) { throw new InvalidFormatException("The number of inputs or outputs you have selected is not supported by the device"); } if (supported != PortAudio.PaError.paNoError) { throw new InvalidFormatException("The configuration you have selected is not supported by the device"); } return(conf); } }
private void Dispose(bool isDisposing) { PortAudio.Pa_Terminate(); }