Example #1
0
            private void StreamSource(ISource aSource)
            {
                SendResponse("200 OK");

                iSocket.Send(iWavFileHeader);

                const int kAudioChunkBytes = 144 * 1024;
                const int kAudioChunks     = 4;

                CaptureBuffer capture = CreateCaptureBuffer(aSource, kAudioChunks * kAudioChunkBytes);

                int offset = 0;

                NotificationPosition[] notifications = new NotificationPosition[kAudioChunks];
                WaitHandle[]           handles       = new WaitHandle[kAudioChunks];

                for (uint i = 0; i < kAudioChunks; i++)
                {
                    NotificationPosition notification = new NotificationPosition();
                    notification.Offset = offset;
                    notification.Event  = new ManualResetEvent(false);
                    handles[i]          = notification.Event;
                    notifications[i]    = notification;
                    offset += kAudioChunkBytes;
                }

                capture.SetNotificationPositions(notifications);

                // Rotate notifications

                for (uint i = 0; i < kAudioChunks - 1; i++)
                {
                    WaitHandle a = handles[i];
                    handles[i]     = handles[i + 1];
                    handles[i + 1] = a;
                }

                byte[] audio = new byte[kAudioChunkBytes];

                capture.Start(true);

                try
                {
                    while (true)
                    {
                        int x = WaitHandle.WaitAny(handles);
                        ManualResetEvent manual = handles[x] as ManualResetEvent;
                        manual.Reset();
                        capture.Read <byte>(audio, 0, kAudioChunkBytes, notifications[x].Offset, false);
                        iSocket.Send(audio);
                    }
                }
                catch (SocketException)
                {
                }

                capture.Stop();
            }
Example #2
0
        public void Start()
        {
            if (_Running)
            {
                throw new InvalidOperationException();
            }

            if (_CaptureDevice == null)
            {
                _CaptureDevice = new DirectSoundCapture(new Guid(_Guid));
            }

            _WaveFormat.FormatTag             = WaveFormatTag.Pcm; // Change to WaveFormatTag.IeeeFloat for float
            _WaveFormat.BitsPerSample         = 16;                // Set this to 32 for float
            _WaveFormat.BlockAlignment        = (short)(_Channels * (_WaveFormat.BitsPerSample / 8));
            _WaveFormat.Channels              = _Channels;
            _WaveFormat.SamplesPerSecond      = (int)(SampleRateKhz * 1000D);
            _WaveFormat.AverageBytesPerSecond =
                _WaveFormat.SamplesPerSecond *
                _WaveFormat.BlockAlignment;

            _BufferPortionCount = 2;

            _BufferDescription.BufferBytes = _BufferSize * sizeof(short) * _BufferPortionCount * _Channels;
            _BufferDescription.Format      = _WaveFormat;
            _BufferDescription.WaveMapped  = false;

            _CaptureBuffer = new CaptureBuffer(_CaptureDevice, _BufferDescription);

            _BufferPortionSize = _CaptureBuffer.SizeInBytes / _BufferPortionCount;
            _Notifications     = new List <NotificationPosition>();

            for (int i = 0; i < _BufferPortionCount; i++)
            {
                var notification = new NotificationPosition {
                    Offset = _BufferPortionCount - 1 + (_BufferPortionSize * i), Event = new AutoResetEvent(false)
                };
                _Notifications.Add(notification);
            }

            _CaptureBuffer.SetNotificationPositions(_Notifications.ToArray());
            _WaitHandles = new WaitHandle[_Notifications.Count];

            for (int i = 0; i < _Notifications.Count; i++)
            {
                _WaitHandles[i] = _Notifications[i].Event;
            }

            _CaptureThread = new Thread(_DoCapture)
            {
                Name = "DirectSoundCapture", IsBackground = true
            };

            _Running = true;
            _CaptureThread.Start();
        }
Example #3
0
        public AudioCapture()
        {
            try
            {
                directSoundCapture = new DirectSoundCapture();
            }
            catch
            {
                throw new AudioCaptureException("Could not open recording device");
            }
            //var directSoundCaps = directSoundCapture.Capabilities;

            // Default 44.1kHz 16-bit stereo PCM
            waveFormat = new WaveFormat();

            // Set the buffer size.
            // Note that the buffer position will roll over to 0 when the buffer fills up,
            // so set the notification position's offset to one less than the buffer size.
            bufferSize      = waveFormat.ConvertLatencyToByteSize(latency);
            numberOfSamples = bufferSize / waveFormat.BlockAlign;

            // Create audio capture buffer
            captureBufferDesc             = new CaptureBufferDescription();
            captureBufferDesc.Format      = waveFormat;
            captureBufferDesc.BufferBytes = bufferSize;
            captureBuffer = new CaptureBuffer(directSoundCapture, captureBufferDesc);

            // Wait events allow the thread to wait asynchronously for the buffer to fill
            var evt = new AutoResetEvent(false);

            fullEvent = new WaitHandle[] { evt };

            // Notify the thread when the buffer is full
            var nf = new NotificationPosition();

            nf.Offset     = bufferSize - 1;
            nf.WaitHandle = fullEvent[0];
            var nfs = new NotificationPosition[] { nf };

            captureBuffer.SetNotificationPositions(nfs);

            // Start the processing thread
            thread = new Thread(new ThreadStart(Process));
            thread.IsBackground = true; // Allow application to exit
            thread.Start();
        }
Example #4
0
        /// <summary>
        ///   Worker thread.
        /// </summary>
        ///
        private void WorkerThread()
        {
            // Get the selected capture device
            DirectSoundCapture captureDevice = new DirectSoundCapture(device);


            // Set the capture format
            WaveFormat format = new WaveFormat();

            format.Channels              = 1;
            format.SamplesPerSecond      = sampleRate;
            format.FormatTag             = sampleFormat.ToWaveFormat();
            format.BitsPerSample         = (short)Signal.GetSampleSize(sampleFormat);
            format.BlockAlignment        = (short)(format.BitsPerSample / 8);
            format.AverageBytesPerSecond = format.SamplesPerSecond * format.BlockAlignment;

            // Setup the capture buffer
            CaptureBufferDescription captureBufferDescription = new CaptureBufferDescription();

            captureBufferDescription.Format         = format;
            captureBufferDescription.BufferBytes    = 2 * desiredCaptureSize * format.BlockAlignment;
            captureBufferDescription.WaveMapped     = true;
            captureBufferDescription.ControlEffects = false;

            CaptureBuffer captureBuffer = null;

            NotificationPosition[] notifications = new NotificationPosition[2];

            try
            {
                captureBuffer = new CaptureBuffer(captureDevice, captureBufferDescription);

                // Setup the notification positions
                int bufferPortionSize = captureBuffer.SizeInBytes / 2;
                notifications[0]        = new NotificationPosition();
                notifications[0].Offset = bufferPortionSize - 1;
                notifications[0].Event  = new AutoResetEvent(false);
                notifications[1]        = new NotificationPosition();
                notifications[1].Offset = bufferPortionSize - 1 + bufferPortionSize;
                notifications[1].Event  = new AutoResetEvent(false);
                captureBuffer.SetNotificationPositions(notifications);

                // Make a copy of the wait handles
                WaitHandle[] waitHandles = new WaitHandle[notifications.Length];
                for (int i = 0; i < notifications.Length; i++)
                {
                    waitHandles[i] = notifications[i].Event;
                }



                // Start capturing
                captureBuffer.Start(true);


                if (sampleFormat == SampleFormat.Format32BitIeeeFloat)
                {
                    float[] currentSample = new float[desiredCaptureSize];

                    while (!stopEvent.WaitOne(0, true))
                    {
                        int bufferPortionIndex = WaitHandle.WaitAny(waitHandles);
                        captureBuffer.Read(currentSample, 0, currentSample.Length, bufferPortionSize * bufferPortionIndex);
                        OnNewFrame(currentSample);
                    }
                }
                else if (sampleFormat == SampleFormat.Format16Bit)
                {
                    short[] currentSample = new short[desiredCaptureSize];

                    while (!stopEvent.WaitOne(0, true))
                    {
                        int bufferPortionIndex = WaitHandle.WaitAny(waitHandles);
                        captureBuffer.Read(currentSample, 0, currentSample.Length, bufferPortionSize * bufferPortionIndex);
                        OnNewFrame(currentSample);
                    }
                }
            }
            catch (Exception ex)
            {
                if (AudioSourceError != null)
                {
                    AudioSourceError(this, new AudioSourceErrorEventArgs(ex.Message));
                }
                else
                {
                    throw;
                }
            }
            finally
            {
                if (captureBuffer != null)
                {
                    captureBuffer.Stop();
                    captureBuffer.Dispose();
                }

                if (captureDevice != null)
                {
                    captureDevice.Dispose();
                }

                for (int i = 0; i < notifications.Length; i++)
                {
                    if (notifications[i].Event != null)
                    {
                        notifications[i].Event.Close();
                    }
                }
            }
        }
Example #5
0
        /// <summary>
        ///   Worker thread.
        /// </summary>
        /// 
        private void WorkerThread()
        {
            // Get the selected capture device
            DirectSoundCapture captureDevice = new DirectSoundCapture(device);


            // Set the capture format
            WaveFormat format = new WaveFormat();
            format.Channels = 1;
            format.SamplesPerSecond = sampleRate;
            format.FormatTag = sampleFormat.ToWaveFormat();
            format.BitsPerSample = (short)Signal.GetSampleSize(sampleFormat);
            format.BlockAlignment = (short)(format.BitsPerSample / 8);
            format.AverageBytesPerSecond = format.SamplesPerSecond * format.BlockAlignment;

            // Setup the capture buffer
            CaptureBufferDescription captureBufferDescription = new CaptureBufferDescription();
            captureBufferDescription.Format = format;
            captureBufferDescription.BufferBytes = 2 * desiredCaptureSize * format.BlockAlignment;
            captureBufferDescription.WaveMapped = true;
            captureBufferDescription.ControlEffects = false;

            CaptureBuffer captureBuffer = null;
            NotificationPosition[] notifications = new NotificationPosition[2];

            try
            {
                captureBuffer = new CaptureBuffer(captureDevice, captureBufferDescription);

                // Setup the notification positions
                int bufferPortionSize = captureBuffer.SizeInBytes / 2;
                notifications[0] = new NotificationPosition();
                notifications[0].Offset = bufferPortionSize - 1;
                notifications[0].Event = new AutoResetEvent(false);
                notifications[1] = new NotificationPosition();
                notifications[1].Offset = bufferPortionSize - 1 + bufferPortionSize;
                notifications[1].Event = new AutoResetEvent(false);
                captureBuffer.SetNotificationPositions(notifications);

                // Make a copy of the wait handles
                WaitHandle[] waitHandles = new WaitHandle[notifications.Length];
                for (int i = 0; i < notifications.Length; i++)
                    waitHandles[i] = notifications[i].Event;



                // Start capturing
                captureBuffer.Start(true);


                if (sampleFormat == SampleFormat.Format32BitIeeeFloat)
                {
                    float[] currentSample = new float[desiredCaptureSize];

                    while (!stopEvent.WaitOne(0, true))
                    {
                        int bufferPortionIndex = WaitHandle.WaitAny(waitHandles);
                        captureBuffer.Read(currentSample, 0, currentSample.Length, bufferPortionSize * bufferPortionIndex);
                        OnNewFrame(currentSample);
                    }
                }
                else if (sampleFormat == SampleFormat.Format16Bit)
                {
                    short[] currentSample = new short[desiredCaptureSize];

                    while (!stopEvent.WaitOne(0, true))
                    {
                        int bufferPortionIndex = WaitHandle.WaitAny(waitHandles);
                        captureBuffer.Read(currentSample, 0, currentSample.Length, bufferPortionSize * bufferPortionIndex);
                        OnNewFrame(currentSample);
                    }
                }
            }
            catch (Exception ex)
            {
                if (AudioSourceError != null)
                    AudioSourceError(this, new AudioSourceErrorEventArgs(ex.Message));
                else throw;
            }
            finally
            {
                if (captureBuffer != null)
                {
                    captureBuffer.Stop();
                    captureBuffer.Dispose();
                }

                if (captureDevice != null)
                    captureDevice.Dispose();

                for (int i = 0; i < notifications.Length; i++)
                    if (notifications[i].Event != null)
                        notifications[i].Event.Close();
            }
        }
        private void startRecordingOrMonitoring(AudioLibPCMFormat pcmFormat, bool recordingToFile)
        {
            RecordingPCMFormat = pcmFormat;

#if USE_SHARPDX
            WaveFormat waveFormat = new WaveFormat((int)RecordingPCMFormat.SampleRate, 16, (int)RecordingPCMFormat.NumberOfChannels);
#else
            WaveFormat waveFormat = new WaveFormat();
            waveFormat.FormatTag             = WaveFormatTag.Pcm;
            waveFormat.Channels              = (short)RecordingPCMFormat.NumberOfChannels;
            waveFormat.SamplesPerSecond      = (int)RecordingPCMFormat.SampleRate;
            waveFormat.BitsPerSample         = (short)RecordingPCMFormat.BitDepth;
            waveFormat.AverageBytesPerSecond = (int)RecordingPCMFormat.SampleRate * RecordingPCMFormat.BlockAlign;
            waveFormat.BlockAlign            = (short)RecordingPCMFormat.BlockAlign;
#endif

            uint byteRate = RecordingPCMFormat.SampleRate * RecordingPCMFormat.BlockAlign;

            int pcmDataBufferSize = (int)(byteRate * REFRESH_INTERVAL_MS / 1000.0);
            pcmDataBufferSize -= pcmDataBufferSize % RecordingPCMFormat.BlockAlign;

            // here we are probably wasting some heap memory,
            // because the event arg payload buffer (for "data available" event)
            // contains the delta between capture and read circular buffer positions.
            // however, this makes the memory re-alloc (i.e. buffer resize) routine simpler,
            // that is to say here only when start record/monitor,
            // instead of inside the DirectAudio capture thread (based on the actual circular buffer delta).
            m_PcmDataBufferLength = pcmDataBufferSize * NOTIFICATIONS;
            if (m_PcmDataBuffer == null)
            {
                Console.WriteLine("ALLOCATING m_PcmDataBuffer");
                m_PcmDataBuffer = new byte[m_PcmDataBufferLength];
            }
            else if (m_PcmDataBuffer.Length < m_PcmDataBufferLength)
            {
                Console.WriteLine("m_PcmDataBuffer.resize");
                Array.Resize(ref m_PcmDataBuffer, m_PcmDataBufferLength);
            }

            int circularBufferSize = pcmDataBufferSize * NOTIFICATIONS;

            CaptureBufferDescription bufferDescription = new CaptureBufferDescription();
            bufferDescription.BufferBytes = circularBufferSize;
            bufferDescription.Format      = waveFormat;
#if USE_SHARPDX
            bufferDescription.Flags = CaptureBufferCapabilitiesFlags.WaveMapped; //CaptureBufferCapabilitiesFlags.ControlEffects

            if (InputDevice == null)
            {
                Console.WriteLine("/// InputDevice NULL, attempting reset...");

                List <InputDevice> inputDevices = InputDevices;

                Console.WriteLine("/// InputDevices: " + inputDevices.Count);

                SetInputDevice("dummy");
            }

            m_CircularBuffer = new CaptureBuffer(InputDevice.Capture, bufferDescription);
#else
            m_CircularBuffer = new CaptureBuffer(bufferDescription, InputDevice.Capture);
#endif

#if FORCE_SINGLE_NOTIFICATION_EVENT
            m_CircularBufferNotificationEvent = new AutoResetEvent(false);
#else
            m_CircularBufferNotificationEvents = new AutoResetEvent[NOTIFICATIONS];
#endif

#if USE_SHARPDX
            NotificationPosition[] m_BufferPositionNotify = new NotificationPosition[NOTIFICATIONS];
#else
            BufferPositionNotify[] m_BufferPositionNotify = new BufferPositionNotify[NOTIFICATIONS];
#endif


            for (int i = 0; i < NOTIFICATIONS; i++)
            {
#if USE_SHARPDX
                m_BufferPositionNotify[i] = new NotificationPosition();
#endif

                m_BufferPositionNotify[i].Offset = (pcmDataBufferSize * i) + pcmDataBufferSize - 1;

#if FORCE_SINGLE_NOTIFICATION_EVENT
#if USE_SHARPDX
                m_BufferPositionNotify[i].WaitHandle = m_CircularBufferNotificationEvent;
                //m_BufferPositionNotify[i].EventNotifyHandlePointer = m_CircularBufferNotificationEvent.SafeWaitHandle.DangerousGetHandle();
#else
                m_BufferPositionNotify[i].EventNotifyHandle = m_CircularBufferNotificationEvent.SafeWaitHandle.DangerousGetHandle();
#endif
#else
                m_CircularBufferNotificationEvents[i] = new AutoResetEvent(false);

#if USE_SHARPDX
                m_BufferPositionNotify[i].WaitHandle = m_CircularBufferNotificationEvents[i];
                //m_BufferPositionNotify[i].EventNotifyHandlePointer = m_CircularBufferNotificationEvents[i].SafeWaitHandle.DangerousGetHandle();
#else
                m_BufferPositionNotify[i].EventNotifyHandle = m_CircularBufferNotificationEvents[i].SafeWaitHandle.DangerousGetHandle();
#endif
#endif
            }

#if USE_SHARPDX
            m_CircularBuffer.SetNotificationPositions(m_BufferPositionNotify);
#else
            m_Notify = new Notify(m_CircularBuffer);
            m_Notify.SetNotificationPositions(m_BufferPositionNotify, NOTIFICATIONS);
#endif

            m_CircularBufferReadPositon = 0;
            m_RecordingFileWriter       = null;

            m_TotalRecordedBytes = 0;
#if FORCE_SINGLE_NOTIFICATION_EVENT
            m_PreviousTotalRecordedBytes = 0;
#endif

            if (recordingToFile)
            {
                int i = -1;
                do
                {
                    i++;
                    m_RecordedFilePath = RecordingDirectory + Path.DirectorySeparatorChar + i.ToString() + WavFormatConverter.AUDIO_WAV_EXTENSION;
                } while (File.Exists(m_RecordedFilePath));

                Stream stream = File.Create(m_RecordedFilePath);
                try
                {
                    m_RecordedFileRiffHeaderSize = RecordingPCMFormat.RiffHeaderWrite(stream, 0);
                }
                finally
                {
                    stream.Close();
                }
            }

            ThreadStart threadDelegate = delegate()
            {
                try
                {
                    circularBufferRefreshThreadMethod();
                }
                catch (ThreadAbortException ex)
                {
                    //
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    Console.WriteLine(ex.StackTrace);
                }
                finally
                {
                    lock (LOCK_THREAD_INSTANCE)
                    {
                        m_CircularBufferRefreshThread = null;
                    }
                }
                //lock (LOCK_THREAD_INSTANCE)
                //{
                //    m_CircularBufferRefreshThread = null;
                //}
            };

            lock (LOCK_THREAD_INSTANCE)
            {
                m_CircularBufferRefreshThread              = new Thread(threadDelegate);
                m_CircularBufferRefreshThread.Name         = "Recorder Notify Thread";
                m_CircularBufferRefreshThread.Priority     = ThreadPriority.AboveNormal;
                m_CircularBufferRefreshThread.IsBackground = true;


                CurrentState = (recordingToFile ? State.Recording : State.Monitoring);

                m_CircularBuffer.Start(true);

                m_CircularBufferRefreshThread.Start();

#if FORCE_SINGLE_NOTIFICATION_EVENT
                m_CircularBufferTimer.Start();
#endif
            }


            //Console.WriteLine("Recorder notify thread start.");
        }
        /// <summary>
        ///   Worker thread.
        /// </summary>
        ///
        private void WorkerThread()
        {
            needToStop = false;

            // Get the selected capture device
            DirectSoundCapture captureDevice = new DirectSoundCapture(device);

            // Set the capture format
            var        bitsPerSample = Signal.GetSampleSize(sampleFormat);
            WaveFormat format        = WaveFormat.CreateCustomFormat(sampleFormat.ToWaveFormat(), sampleRate, 1,
                                                                     sampleRate * bitsPerSample / 8, bitsPerSample / 8, bitsPerSample);

            // Setup the capture buffer
            CaptureBufferDescription captureBufferDescription = new CaptureBufferDescription();

            captureBufferDescription.Format      = format;
            captureBufferDescription.BufferBytes = 2 * desiredCaptureSize * format.BlockAlign;
            captureBufferDescription.Flags      |= CaptureBufferCapabilitiesFlags.WaveMapped;
            captureBufferDescription.Flags      &= ~CaptureBufferCapabilitiesFlags.ControlEffects;

            CaptureBuffer captureBuffer = null;

            NotificationPosition[] notifications = new NotificationPosition[2];

            try
            {
                captureBuffer = new CaptureBuffer(captureDevice, captureBufferDescription);

                // Setup the notification positions
                int bufferPortionSize = captureBuffer.Capabilities.BufferBytes / 2;
                notifications[0]            = new NotificationPosition();
                notifications[0].Offset     = bufferPortionSize - 1;
                notifications[0].WaitHandle = new AutoResetEvent(false);
                notifications[1]            = new NotificationPosition();
                notifications[1].Offset     = bufferPortionSize - 1 + bufferPortionSize;
                notifications[1].WaitHandle = new AutoResetEvent(false);
                captureBuffer.SetNotificationPositions(notifications);

                // Make a copy of the wait handles
                WaitHandle[] waitHandles = new WaitHandle[notifications.Length];
                for (int i = 0; i < notifications.Length; i++)
                {
                    waitHandles[i] = notifications[i].WaitHandle;
                }

                // Start capturing
                captureBuffer.Start(true);

                if (sampleFormat == SampleFormat.Format32BitIeeeFloat)
                {
                    float[] currentSample = new float[desiredCaptureSize];
                    Signal  signal        = Signal.FromArray(currentSample, sampleRate, sampleFormat);

                    while (!needToStop)
                    {
                        int bufferPortionIndex = WaitHandle.WaitAny(waitHandles);
                        captureBuffer.Read(currentSample, 0, currentSample.Length, bufferPortionSize * bufferPortionIndex, LockFlags.None);
                        OnNewFrame(signal);
                    }
                }
                else if (sampleFormat == SampleFormat.Format16Bit)
                {
                    short[] currentSample = new short[desiredCaptureSize];
                    Signal  signal        = Signal.FromArray(currentSample, sampleRate, sampleFormat);

                    while (!needToStop)
                    {
                        int bufferPortionIndex = WaitHandle.WaitAny(waitHandles);
                        captureBuffer.Read(currentSample, 0, currentSample.Length, bufferPortionSize * bufferPortionIndex, LockFlags.None);
                        OnNewFrame(signal);
                    }
                }
            }
            catch (Exception ex)
            {
                if (AudioSourceError == null)
                {
                    throw;
                }

                AudioSourceError(this, new AudioSourceErrorEventArgs(ex));
            }
            finally
            {
                if (captureBuffer != null)
                {
                    captureBuffer.Stop();
                    captureBuffer.Dispose();
                }

                if (captureDevice != null)
                {
                    captureDevice.Dispose();
                }

#if !NETSTANDARD1_4
                for (int i = 0; i < notifications.Length; i++)
                {
                    if (notifications[i].WaitHandle != null)
                    {
                        notifications[i].WaitHandle.Close();
                    }
                }
#endif
            }
        }