diff --git a/Vocaluxe/Lib/Sound/CPortAudioCommon.cs b/Vocaluxe/Lib/Sound/CPortAudioHandle.cs
similarity index 61%
rename from Vocaluxe/Lib/Sound/CPortAudioCommon.cs
rename to Vocaluxe/Lib/Sound/CPortAudioHandle.cs
index a3233047..0406055e 100644
--- a/Vocaluxe/Lib/Sound/CPortAudioCommon.cs
+++ b/Vocaluxe/Lib/Sound/CPortAudioHandle.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Diagnostics;
using PortAudioSharp;
using Vocaluxe.Base;
@@ -8,40 +9,53 @@ namespace Vocaluxe.Lib.Sound
///
/// PortAudio can be used for record and playback
/// So do some common stuff here and make sure those 2 do not interfere
+ /// Basic lifetime: On Init() get a new handle, close/dispose it in your close/dispose
///
/// DO NEVER use following Pa_* functions other than the ones from this class:
/// Initialize, Terminate, OpenStream, CloseStream
///
- static class CPortAudioCommon
+ class CPortAudioHandle : IDisposable
{
private static int _RefCount;
private static readonly object _Mutex = new object();
+ private bool _Disposed;
+ private readonly List _Streams = new List();
+
///
- /// Safe method to init PortAudio (adds a reference)
- /// MUST call CloseDriver when done
+ /// Initializes PortAudio library (if required)
///
- /// True on success, falso if not initialized (log written)
- public static bool InitDriver()
+ public CPortAudioHandle()
{
lock (_Mutex)
{
if (_RefCount == 0)
{
if (CheckError("Initialize", PortAudio.Pa_Initialize()))
- return false;
+ throw new Exception();
}
_RefCount++;
}
- return true;
}
- ///
- /// Safe method to close PortAudio
- /// MUST be called _exactly_ once after successfull InitDriver call
- ///
- public static void CloseDriver()
+ ~CPortAudioHandle()
{
+ _Dispose(false);
+ }
+
+ private void _Dispose(bool disposing)
+ {
+ if (_Disposed)
+ return;
+ if (!disposing)
+ CLog.LogDebug("Did not close CPortAudioHandle");
+ //Make sure we do not leek any streams as we may keep PA open
+ if (_Streams.Count > 0)
+ {
+ CLog.LogDebug("Did not close " + _Streams.Count + "PortAudio-Stream(s)");
+ while (_Streams.Count > 0)
+ CloseStream(_Streams[0]);
+ }
lock (_Mutex)
{
Debug.Assert(_RefCount > 0);
@@ -49,15 +63,37 @@ namespace Vocaluxe.Lib.Sound
if (_RefCount == 0)
PortAudio.Pa_Terminate();
}
+ _Disposed = true;
}
- public static PortAudio.PaError OpenStream(out IntPtr stream, ref PortAudio.PaStreamParameters? inputParameters, ref PortAudio.PaStreamParameters? outputParameters,
- double sampleRate, uint framesPerBuffer, PortAudio.PaStreamFlags streamFlags,
- PortAudio.PaStreamCallbackDelegate streamCallback, IntPtr userData)
+ public void Dispose()
{
+ _Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Close the PortAudio handle once you are done
+ ///
+ public void Close()
+ {
+ Dispose();
+ }
+
+ public PortAudio.PaError OpenStream(out IntPtr stream, ref PortAudio.PaStreamParameters? inputParameters, ref PortAudio.PaStreamParameters? outputParameters,
+ double sampleRate, uint framesPerBuffer, PortAudio.PaStreamFlags streamFlags,
+ PortAudio.PaStreamCallbackDelegate streamCallback, IntPtr userData)
+ {
+ if (_Disposed)
+ throw new ObjectDisposedException("PortAudioHandle already disposed");
+
lock (_Mutex)
{
- return PortAudio.Pa_OpenStream(out stream, ref inputParameters, ref outputParameters, sampleRate, framesPerBuffer, streamFlags, streamCallback, userData);
+ PortAudio.PaError res = PortAudio.Pa_OpenStream(out stream, ref inputParameters, ref outputParameters, sampleRate, framesPerBuffer, streamFlags, streamCallback,
+ userData);
+ if (res == PortAudio.PaError.paNoError)
+ _Streams.Add(stream);
+ return res;
}
}
@@ -72,9 +108,9 @@ namespace Vocaluxe.Lib.Sound
///
///
/// True on success
- public static bool OpenInputStream(out IntPtr stream, ref PortAudio.PaStreamParameters? inputParameters,
- double sampleRate, uint framesPerBuffer, PortAudio.PaStreamFlags streamFlags,
- PortAudio.PaStreamCallbackDelegate streamCallback, IntPtr userData)
+ public bool OpenInputStream(out IntPtr stream, ref PortAudio.PaStreamParameters? inputParameters,
+ double sampleRate, uint framesPerBuffer, PortAudio.PaStreamFlags streamFlags,
+ PortAudio.PaStreamCallbackDelegate streamCallback, IntPtr userData)
{
PortAudio.PaStreamParameters? outputParameters = null;
return
@@ -93,9 +129,9 @@ namespace Vocaluxe.Lib.Sound
///
///
/// True on success
- public static bool OpenOutputStream(out IntPtr stream, ref PortAudio.PaStreamParameters? outputParameters,
- double sampleRate, uint framesPerBuffer, PortAudio.PaStreamFlags streamFlags,
- PortAudio.PaStreamCallbackDelegate streamCallback, IntPtr userData)
+ public bool OpenOutputStream(out IntPtr stream, ref PortAudio.PaStreamParameters? outputParameters,
+ double sampleRate, uint framesPerBuffer, PortAudio.PaStreamFlags streamFlags,
+ PortAudio.PaStreamCallbackDelegate streamCallback, IntPtr userData)
{
PortAudio.PaStreamParameters? inputParameters = null;
return
@@ -103,11 +139,15 @@ namespace Vocaluxe.Lib.Sound
OpenStream(out stream, ref inputParameters, ref outputParameters, sampleRate, framesPerBuffer, streamFlags, streamCallback, userData));
}
- public static void CloseStream(IntPtr stream)
+ public void CloseStream(IntPtr stream)
{
+ if (_Disposed)
+ throw new ObjectDisposedException("PortAudioHandle already disposed");
+
lock (_Mutex)
{
PortAudio.Pa_CloseStream(stream);
+ _Streams.Remove(stream);
}
}
@@ -118,8 +158,11 @@ namespace Vocaluxe.Lib.Sound
/// Action identifier (E.g. openStream)
/// Result returned by Pa_* call
/// True on error
- public static bool CheckError(String action, PortAudio.PaError errorCode)
+ public bool CheckError(String action, PortAudio.PaError errorCode)
{
+ if (_Disposed)
+ throw new ObjectDisposedException("PortAudioHandle already disposed");
+
if (errorCode != PortAudio.PaError.paNoError)
{
CLog.LogError(action + " error: " + PortAudio.Pa_GetErrorText(errorCode));
@@ -140,11 +183,10 @@ namespace Vocaluxe.Lib.Sound
/// Selects the most appropriate host api
///
/// The most appropriate host api
- public static int GetHostApi()
+ public int GetHostApi()
{
- //Caller has to hold a reference anyway so no locking needed
- if (_RefCount < 1)
- return -1;
+ if (_Disposed)
+ throw new ObjectDisposedException("PortAudioHandle already disposed");
int selectedHostApi = PortAudio.Pa_GetDefaultHostApi();
int apiCount = PortAudio.Pa_GetHostApiCount();
diff --git a/Vocaluxe/Lib/Sound/Playback/PortAudio/CPortAudioStream.cs b/Vocaluxe/Lib/Sound/Playback/PortAudio/CPortAudioStream.cs
index 62a2f9f4..cd2328e2 100644
--- a/Vocaluxe/Lib/Sound/Playback/PortAudio/CPortAudioStream.cs
+++ b/Vocaluxe/Lib/Sound/Playback/PortAudio/CPortAudioStream.cs
@@ -15,6 +15,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
public readonly int ID;
private readonly Closeproc _Closeproc;
+ private CPortAudioHandle _PaHandle;
private readonly CSyncTimer _SyncTimer;
private int _ByteCount = 4;
@@ -187,12 +188,12 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
{
Paused = false;
_AfterFadeAction = EStreamAction.Nothing;
- CPortAudioCommon.CheckError("StartStream", PortAudioSharp.PortAudio.Pa_StartStream(_Stream));
+ _PaHandle.CheckError("StartStream", PortAudioSharp.PortAudio.Pa_StartStream(_Stream));
}
public void Stop()
{
- CPortAudioCommon.CheckError("StopStream (playback)", PortAudioSharp.PortAudio.Pa_StopStream(_Stream));
+ _PaHandle.CheckError("StopStream (playback)", PortAudioSharp.PortAudio.Pa_StopStream(_Stream));
Skip(0f);
}
@@ -210,14 +211,11 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
if (!File.Exists(fileName))
return false;
- bool driverInitialized = false;
try
{
- if (!CPortAudioCommon.InitDriver())
- return false;
- driverInitialized = true;
+ _PaHandle = new CPortAudioHandle();
- int hostApi = CPortAudioCommon.GetHostApi();
+ int hostApi = _PaHandle.GetHostApi();
_ApiInfo = PortAudioSharp.PortAudio.Pa_GetHostApiInfo(hostApi);
_OutputDeviceInfo = PortAudioSharp.PortAudio.Pa_GetDeviceInfo(_ApiInfo.defaultOutputDevice);
if (_OutputDeviceInfo.defaultLowOutputLatency < 0.1)
@@ -227,8 +225,11 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
}
catch (Exception)
{
- if (driverInitialized)
- CPortAudioCommon.CloseDriver();
+ if (_PaHandle != null)
+ {
+ _PaHandle.Close();
+ _PaHandle = null;
+ }
CLog.LogError("Error Init PortAudio Playback");
return false;
}
@@ -240,7 +241,8 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
SFormatInfo format = _Decoder.GetFormatInfo();
if (format.SamplesPerSecond == 0)
{
- CPortAudioCommon.CloseDriver();
+ _PaHandle.Close();
+ _PaHandle = null;
_Decoder.Close();
_Decoder = null;
CLog.LogError("Error Init PortAudio Playback (samples=0)");
@@ -262,7 +264,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
hostApiSpecificStreamInfo = IntPtr.Zero
};
- if (!CPortAudioCommon.OpenOutputStream(
+ if (!_PaHandle.OpenOutputStream(
out _Stream,
ref outputParams,
format.SamplesPerSecond,
@@ -271,7 +273,8 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
_PaStreamCallback,
IntPtr.Zero) || _Stream == IntPtr.Zero)
{
- CPortAudioCommon.CloseDriver();
+ _PaHandle.Close();
+ _PaHandle = null;
_Decoder.Close();
_Decoder = null;
return false;
@@ -410,9 +413,11 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
private void _DoFree()
{
- CPortAudioCommon.CloseStream(_Stream);
- CPortAudioCommon.CloseDriver();
+ _PaHandle.CloseStream(_Stream);
+ _PaHandle.Close();
+ _PaHandle = null;
_Decoder.Close();
+ _Decoder = null;
_Closeproc(ID);
}
diff --git a/Vocaluxe/Lib/Sound/Record/CRecordBase.cs b/Vocaluxe/Lib/Sound/Record/CRecordBase.cs
new file mode 100644
index 00000000..78630c90
--- /dev/null
+++ b/Vocaluxe/Lib/Sound/Record/CRecordBase.cs
@@ -0,0 +1,148 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using Vocaluxe.Base;
+
+namespace Vocaluxe.Lib.Sound.Record
+{
+ ///
+ /// Base class to implement common functionality for Record classes
+ ///
+ abstract class CRecordBase
+ {
+ private bool _Initialized;
+ protected List _Devices;
+ protected CBuffer[] _Buffer;
+
+ ///
+ /// Init recording
+ /// Child class should overwrite this to list devices
+ ///
+ /// true if success
+ public virtual bool Init()
+ {
+ if (_Initialized)
+ return false;
+
+ _Devices = new List();
+ _Buffer = new CBuffer[CSettings.MaxNumPlayer];
+ for (int i = 0; i < _Buffer.Length; i++)
+ _Buffer[i] = new CBuffer();
+
+ _Initialized = true;
+
+ return true;
+ }
+
+ ///
+ /// Stop all voice capturing streams and terminates recording freeing resources
+ ///
+ public virtual void Close()
+ {
+ if (!_Initialized)
+ return;
+
+ _Devices = null;
+ if (_Buffer != null)
+ {
+ foreach (CBuffer buffer in _Buffer)
+ buffer.Dispose();
+ _Buffer = null;
+ }
+
+ _Initialized = false;
+ }
+
+ ///
+ /// Procedure to be called by descendent classes with data that got recorded
+ ///
+ /// Device from which the data was recorded
+ /// Recorded samples, assume Int16 and interleaved for multi-channels
+ protected void _HandleData(CRecordDevice device, byte[] data)
+ {
+ byte[] leftBuffer;
+ byte[] rightBuffer;
+
+ if (device.Channels == 2)
+ {
+ leftBuffer = new byte[data.Length / 2];
+ rightBuffer = new byte[data.Length / 2];
+ //[]: Sample, L: Left channel R: Right channel
+ //[LR][LR][LR][LR][LR][LR]
+ //The data is interleaved and needs to be demultiplexed
+ for (int i = 0; i < data.Length / 4; i++)
+ {
+ leftBuffer[i * 2] = data[i * 4];
+ leftBuffer[i * 2 + 1] = data[i * 4 + 1];
+ rightBuffer[i * 2] = data[i * 4 + 2];
+ rightBuffer[i * 2 + 1] = data[i * 4 + 3];
+ }
+ }
+ else
+ leftBuffer = rightBuffer = data;
+
+ if (device.PlayerChannel1 > 0)
+ _Buffer[device.PlayerChannel1 - 1].ProcessNewBuffer(leftBuffer);
+
+ if (device.PlayerChannel2 > 0)
+ _Buffer[device.PlayerChannel2 - 1].ProcessNewBuffer(rightBuffer);
+ }
+
+ ///
+ /// Detect Pitch and Volume of the newest voice buffer
+ ///
+ ///
+ public void AnalyzeBuffer(int player)
+ {
+ if (!_Initialized)
+ return;
+
+ _Buffer[player].AnalyzeBuffer();
+ }
+
+ public int GetToneAbs(int player)
+ {
+ if (!_Initialized)
+ return 0;
+
+ return _Buffer[player].ToneAbs;
+ }
+
+ public int GetTone(int player)
+ {
+ return _Initialized ? _Buffer[player].Tone : 0;
+ }
+
+ public void SetTone(int player, int tone)
+ {
+ if (!_Initialized)
+ return;
+
+ _Buffer[player].Tone = tone;
+ }
+
+ public float GetMaxVolume(int player)
+ {
+ return _Initialized ? _Buffer[player].MaxVolume : 0f;
+ }
+
+ public bool ToneValid(int player)
+ {
+ return _Initialized && _Buffer[player].ToneValid;
+ }
+
+ public int NumHalfTones()
+ {
+ return CBuffer.NumHalfTones;
+ }
+
+ public float[] ToneWeigth(int player)
+ {
+ return _Initialized ? _Buffer[player].ToneWeigth : null;
+ }
+
+ public ReadOnlyCollection RecordDevices()
+ {
+ return (_Initialized && _Devices.Count > 0) ? _Devices.AsReadOnly() : null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Vocaluxe/Lib/Sound/Record/DirectSound/CDirectSoundRecord.cs b/Vocaluxe/Lib/Sound/Record/DirectSound/CDirectSoundRecord.cs
index e0a37e8e..61b54b23 100644
--- a/Vocaluxe/Lib/Sound/Record/DirectSound/CDirectSoundRecord.cs
+++ b/Vocaluxe/Lib/Sound/Record/DirectSound/CDirectSoundRecord.cs
@@ -23,39 +23,28 @@ using Vocaluxe.Base;
namespace Vocaluxe.Lib.Sound.Record.DirectSound
{
- class CDirectSoundRecord : IRecord
+ class CDirectSoundRecord : CRecordBase, IRecord
{
private bool _Initialized;
- private List _Devices;
+
private List _Sources;
- private readonly CBuffer[] _Buffer;
-
- public CDirectSoundRecord()
+ public override bool Init()
{
- _Buffer = new CBuffer[CSettings.MaxNumPlayer];
- for (int i = 0; i < _Buffer.Length; i++)
- _Buffer[i] = new CBuffer();
+ if (!base.Init())
+ return false;
- Init();
- }
-
- public bool Init()
- {
- DeviceCollection devices = DirectSoundCapture.GetDevices();
- _Devices = new List();
_Sources = new List();
- int id = 0;
+ DeviceCollection devices = DirectSoundCapture.GetDevices();
+
foreach (DeviceInformation dev in devices)
{
using (var ds = new DirectSoundCapture(dev.DriverGuid))
{
- var device = new CRecordDevice(id, dev.DriverGuid.ToString(), dev.Description, ds.Capabilities.Channels);
+ var device = new CRecordDevice(_Devices.Count, dev.DriverGuid.ToString(), dev.Description, ds.Capabilities.Channels);
_Devices.Add(device);
-
- id++;
}
}
@@ -64,14 +53,11 @@ namespace Vocaluxe.Lib.Sound.Record.DirectSound
return true;
}
- public void Close()
+ public override void Close()
{
- if (_Initialized)
- {
- Stop();
- _Initialized = false;
- }
- //System.IO.File.WriteAllBytes("test0.raw", _Buffer[0].Buffer);
+ Stop();
+ _Initialized = false;
+ base.Close();
}
public bool Start()
@@ -112,81 +98,6 @@ namespace Vocaluxe.Lib.Sound.Record.DirectSound
return true;
}
- public void AnalyzeBuffer(int player)
- {
- if (!_Initialized)
- return;
-
- _Buffer[player].AnalyzeBuffer();
- }
-
- public int GetToneAbs(int player)
- {
- if (!_Initialized)
- return 0;
-
- return _Buffer[player].ToneAbs;
- }
-
- public int GetTone(int player)
- {
- if (!_Initialized)
- return 0;
-
- return _Buffer[player].Tone;
- }
-
- public void SetTone(int player, int tone)
- {
- if (!_Initialized)
- return;
-
- _Buffer[player].Tone = tone;
- }
-
- public float GetMaxVolume(int player)
- {
- if (!_Initialized)
- return 0f;
-
- return _Buffer[player].MaxVolume;
- }
-
- public bool ToneValid(int player)
- {
- if (!_Initialized)
- return false;
-
- return _Buffer[player].ToneValid;
- }
-
- public ReadOnlyCollection RecordDevices()
- {
- if (!_Initialized)
- return null;
-
- if (_Devices.Count == 0)
- return null;
-
- return _Devices.AsReadOnly();
- }
-
- public int NumHalfTones()
- {
- if (!_Initialized)
- return 0;
-
- return CBuffer.NumHalfTones;
- }
-
- public float[] ToneWeigth(int player)
- {
- if (!_Initialized)
- return null;
-
- return _Buffer[player].ToneWeigth;
- }
-
private void _OnDataReady(object sender, CSampleDataEventArgs e)
{
if (!_Initialized)
@@ -194,32 +105,7 @@ namespace Vocaluxe.Lib.Sound.Record.DirectSound
CRecordDevice dev = _Devices.FirstOrDefault(device => device.Driver == e.Guid);
if (dev == null)
return;
- byte[] leftBuffer;
- byte[] rightBuffer;
-
- if (dev.Channels == 2)
- {
- leftBuffer = new byte[e.Data.Length / 2];
- rightBuffer = new byte[e.Data.Length / 2];
- //[]: Sample, L: Left channel R: Right channel
- //[LR][LR][LR][LR][LR][LR]
- //The data is interleaved and needs to be demultiplexed
- for (int i = 0; i < e.Data.Length / 4; i++)
- {
- leftBuffer[i * 2] = e.Data[i * 4];
- leftBuffer[i * 2 + 1] = e.Data[i * 4 + 1];
- rightBuffer[i * 2] = e.Data[i * 4 + 2];
- rightBuffer[i * 2 + 1] = e.Data[i * 4 + 3];
- }
- }
- else
- leftBuffer = rightBuffer = e.Data;
-
- if (dev.PlayerChannel1 > 0)
- _Buffer[dev.PlayerChannel1 - 1].ProcessNewBuffer(leftBuffer);
-
- if (dev.PlayerChannel2 > 0)
- _Buffer[dev.PlayerChannel2 - 1].ProcessNewBuffer(rightBuffer);
+ _HandleData(dev, e.Data);
}
}
}
\ No newline at end of file
diff --git a/Vocaluxe/Lib/Sound/Record/PortAudio/CPortAudioRecord.cs b/Vocaluxe/Lib/Sound/Record/PortAudio/CPortAudioRecord.cs
index 5515b8b9..76b952da 100644
--- a/Vocaluxe/Lib/Sound/Record/PortAudio/CPortAudioRecord.cs
+++ b/Vocaluxe/Lib/Sound/Record/PortAudio/CPortAudioRecord.cs
@@ -16,47 +16,33 @@
#endregion
using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
using System.Threading;
using Vocaluxe.Base;
namespace Vocaluxe.Lib.Sound.Record.PortAudio
{
- class CPortAudioRecord : IRecord
+ class CPortAudioRecord : CRecordBase, IRecord
{
private bool _Initialized;
- private readonly List _Devices = new List();
-
+ private CPortAudioHandle _PaHandle;
private PortAudioSharp.PortAudio.PaStreamCallbackDelegate _MyRecProc;
private IntPtr[] _RecHandle;
- private readonly CBuffer[] _Buffer;
-
- public CPortAudioRecord()
- {
- _Buffer = new CBuffer[CSettings.MaxNumPlayer];
- for (int i = 0; i < _Buffer.Length; i++)
- _Buffer[i] = new CBuffer();
- }
-
///
/// Init PortAudio and list record devices
///
/// true if success
- public bool Init()
+ public override bool Init()
{
- if (_Initialized)
+ if (!base.Init())
return false;
try
{
- if (!CPortAudioCommon.InitDriver())
- return false;
+ _PaHandle = new CPortAudioHandle();
- _Devices.Clear();
- int hostAPI = CPortAudioCommon.GetHostApi();
+ int hostAPI = _PaHandle.GetHostApi();
int numDevices = PortAudioSharp.PortAudio.Pa_GetDeviceCount();
for (int i = 0; i < numDevices; i++)
{
@@ -69,9 +55,6 @@ namespace Vocaluxe.Lib.Sound.Record.PortAudio
}
}
- foreach (CBuffer buffer in _Buffer)
- buffer.Reset();
-
_RecHandle = new IntPtr[_Devices.Count];
_MyRecProc = _MyPaStreamCallback;
_Initialized = true;
@@ -80,6 +63,7 @@ namespace Vocaluxe.Lib.Sound.Record.PortAudio
{
_Initialized = false;
CLog.LogError("Error initializing PortAudio: " + e.Message);
+ Close();
return false;
}
@@ -95,9 +79,6 @@ namespace Vocaluxe.Lib.Sound.Record.PortAudio
if (!_Initialized)
return false;
- if (_RecHandle == null || _RecHandle.Length == 0)
- return false;
-
Stop();
foreach (IntPtr handle in _RecHandle)
@@ -128,7 +109,7 @@ namespace Vocaluxe.Lib.Sound.Record.PortAudio
suggestedLatency = PortAudioSharp.PortAudio.Pa_GetDeviceInfo(_Devices[dev].ID).defaultLowInputLatency,
hostApiSpecificStreamInfo = IntPtr.Zero
};
- if (!CPortAudioCommon.OpenInputStream(
+ if (!_PaHandle.OpenInputStream(
out _RecHandle[dev],
ref inputParams,
44100,
@@ -138,7 +119,7 @@ namespace Vocaluxe.Lib.Sound.Record.PortAudio
new IntPtr(dev)))
return false;
- if (CPortAudioCommon.CheckError("Start Stream (rec)", PortAudioSharp.PortAudio.Pa_StartStream(_RecHandle[dev])))
+ if (_PaHandle.CheckError("Start Stream (rec)", PortAudioSharp.PortAudio.Pa_StartStream(_RecHandle[dev])))
return false;
}
}
@@ -162,97 +143,25 @@ namespace Vocaluxe.Lib.Sound.Record.PortAudio
///
/// Stop all voice capturing streams and terminate PortAudio
///
- public void Close()
+ public override void Close()
{
- if (!_Initialized)
- return;
-
- foreach (IntPtr handle in _RecHandle)
- CPortAudioCommon.CloseStream(handle);
- CPortAudioCommon.CloseDriver();
+ if (_RecHandle != null)
+ {
+ foreach (IntPtr handle in _RecHandle)
+ {
+ if (handle != IntPtr.Zero)
+ _PaHandle.CloseStream(handle);
+ }
+ }
+ if (_PaHandle != null)
+ {
+ _PaHandle.Close();
+ _PaHandle = null;
+ }
_Initialized = false;
- //System.IO.File.WriteAllBytes("test0.raw", _Buffer[0].Buffer);
- }
-
- ///
- /// Detect Pitch and Volume of the newest voice buffer
- ///
- ///
- public void AnalyzeBuffer(int player)
- {
- if (!_Initialized)
- return;
-
- _Buffer[player].AnalyzeBuffer();
- }
-
- public int GetToneAbs(int player)
- {
- if (!_Initialized)
- return 0;
-
- return _Buffer[player].ToneAbs;
- }
-
- public int GetTone(int player)
- {
- if (!_Initialized)
- return 0;
-
- return _Buffer[player].Tone;
- }
-
- public void SetTone(int player, int tone)
- {
- if (!_Initialized)
- return;
-
- _Buffer[player].Tone = tone;
- }
-
- public float GetMaxVolume(int player)
- {
- if (!_Initialized)
- return 0f;
-
- return _Buffer[player].MaxVolume;
- }
-
- public bool ToneValid(int player)
- {
- if (!_Initialized)
- return false;
-
- return _Buffer[player].ToneValid;
- }
-
- public int NumHalfTones()
- {
- if (!_Initialized)
- return 0;
-
- return CBuffer.NumHalfTones;
- }
-
- public float[] ToneWeigth(int player)
- {
- if (!_Initialized)
- return null;
-
- return _Buffer[player].ToneWeigth;
- }
-
- public ReadOnlyCollection RecordDevices()
- {
- if (!_Initialized)
- return null;
-
- if (_Devices.Count == 0)
- return null;
-
- return _Devices.AsReadOnly();
+ base.Close();
}
private PortAudioSharp.PortAudio.PaStreamCallbackResult _MyPaStreamCallback(
@@ -275,34 +184,10 @@ namespace Vocaluxe.Lib.Sound.Record.PortAudio
numBytes = frameCount * 2;
byte[] recbuffer = new byte[numBytes];
- byte[] leftBuffer;
- byte[] rightBuffer;
// copy from managed to unmanaged memory
Marshal.Copy(input, recbuffer, 0, (int)numBytes);
- if (dev.Channels == 2)
- {
- leftBuffer = new byte[numBytes / 2];
- rightBuffer = new byte[numBytes / 2];
- //[]: Sample, L: Left channel R: Right channel
- //[LR][LR][LR][LR][LR][LR]
- //The data is interleaved and needs to be demultiplexed
- for (int i = 0; i < frameCount; i++)
- {
- leftBuffer[i * 2] = recbuffer[i * 4];
- leftBuffer[i * 2 + 1] = recbuffer[i * 4 + 1];
- rightBuffer[i * 2] = recbuffer[i * 4 + 2];
- rightBuffer[i * 2 + 1] = recbuffer[i * 4 + 3];
- }
- }
- else
- leftBuffer = rightBuffer = recbuffer;
-
- if (dev.PlayerChannel1 > 0)
- _Buffer[dev.PlayerChannel1 - 1].ProcessNewBuffer(leftBuffer);
-
- if (dev.PlayerChannel2 > 0)
- _Buffer[dev.PlayerChannel2 - 1].ProcessNewBuffer(rightBuffer);
+ _HandleData(dev, recbuffer);
}
}
catch (Exception e)
diff --git a/Vocaluxe/Vocaluxe.csproj b/Vocaluxe/Vocaluxe.csproj
index 0dc33afe..fcf7e6f6 100644
--- a/Vocaluxe/Vocaluxe.csproj
+++ b/Vocaluxe/Vocaluxe.csproj
@@ -222,7 +222,7 @@
-
+
@@ -264,6 +264,7 @@
+