示例#1
0
        //These methods run on the main thread, they drain audio from the mic and send it across to the other thread for proper processing
        //
        // Update            - Either discard mic samples (if no one is subscribed to mic data) or call DrainMicSamples
        // DrainMicSamples   - Read as many samples as possible from the mic (using a set of pow2 sized buffers to get as
        //                     much as possible), passes samples to ConsumeMicSamples
        // ConsumeMicSamples - Take some number of samples from produced by DrainMicSamples and buffer them up, call SendFrame
        //                     every time some samples are added to the buffer
        // SendFrame         - Read as many frames as possible from the buffer and send them to the other thread. Also poke the other thread
        //                     to tell it that it has work to do

        public void Update()
        {
            if (!_started)
            {
                _readHead = Microphone.GetPosition(_micName);
                _started  = _readHead > 0;

                if (!_started)
                {
                    return;
                }
            }

            if (_preprocessing.RequiresInput)
            {
                //Read samples from clip into mic sample buffer
                DrainMicSamples();
            }
            else
            {
                //We're not interested in the audio from the mic, so skip the read head to the current mic position and drop all the audio
                _readHead = Microphone.GetPosition(_micName);
                _rawMicSamples.Reset();
                _rawMicFrames.Reset();
                _preprocessing.Reset();

                if (_microphoneDiagnosticOutput != null)
                {
                    _microphoneDiagnosticOutput.Dispose();
                    _microphoneDiagnosticOutput = null;
                }
            }
        }
示例#2
0
        protected void SendSamplesToSubscribers([NotNull] float[] buffer)
        {
            //Write processed audio to file (for diagnostic purposes)
            //ncrunch: no coverage start (Justification: don't want to have to write to disk in a test)
            if (DebugSettings.Instance.EnableRecordingDiagnostics && DebugSettings.Instance.RecordPreprocessorOutput)
            {
                if (_diagnosticOutputRecorder == null)
                {
                    var filename = string.Format("Dissonance_Diagnostics/PreprocessorOutputAudio_{0}", DateTime.UtcNow.ToFileTime());
                    _diagnosticOutputRecorder = new AudioFileWriter(filename, OutputFormat);
                }

                _diagnosticOutputRecorder.WriteSamples(new ArraySegment <float>(buffer));
            }
            //ncrunch: no coverage end

            //Send the audio to subscribers
            using (var unlocker = _micSubscriptions.Lock())
            {
                var subs = unlocker.Value;
                for (var i = 0; i < subs.Count; i++)
                {
                    try
                    {
                        subs[i].ReceiveMicrophoneData(new ArraySegment <float>(buffer), OutputFormat);
                    }
                    catch (Exception ex)
                    {
                        Log.Error("Microphone subscriber '{0}' threw: {1}", subs[i].GetType().Name, ex);
                    }
                }
            }
        }
示例#3
0
        private void StopCapture()
        {
            if (!_subscribed)
            {
                throw Log.CreatePossibleBugException("Cannot unsubscribe encoder from mic: not subscribed", "8E0EAC83-BF44-4BE3-B132-BFE02AD1FADB");
            }
            Log.Debug("Unsubscribing encoder from microphone");

            _mic.Unsubscribe(this);
            _subscribed    = false;
            _resetRequired = true;

            //Disposing the output writers is racy, because the audio thread is trying to write to them at the same time.
            //That's fine, because the writer have an internal SpinLock ensuring that doing this is safe
            if (_microphoneDiagnosticOutput != null)
            {
                _microphoneDiagnosticOutput.Dispose();
                _microphoneDiagnosticOutput = null;
            }

            if (_preEncodeDiagnosticOutput != null)
            {
                _preEncodeDiagnosticOutput.Dispose();
                _preEncodeDiagnosticOutput = null;
            }
        }
示例#4
0
        public virtual void Dispose()
        {
            _runThread = false;
            _threadEvent.Set();
            if (_thread.IsStarted)
            {
                _thread.Join();
            }

            //ncrunch: no coverage start
            if (_diagnosticOutputRecorder != null)
            {
                _diagnosticOutputRecorder.Dispose();
                _diagnosticOutputRecorder = null;
            }
            //ncrunch: no coverage end

            using (var subscriptions = _micSubscriptions.Lock())
                while (subscriptions.Value.Count > 0)
                {
                    Unsubscribe(subscriptions.Value[0]);
                }

            using (var subscriptions = _vadSubscriptions.Lock())
                while (subscriptions.Value.Count > 0)
                {
                    Unsubscribe(subscriptions.Value[0]);
                }

            Log.Debug("Disposed pipeline");
        }
示例#5
0
        public virtual void StopCapture()
        {
            Log.AssertAndThrowPossibleBug(_clip != null, "CDDAE69D-44DC-487F-9B69-4703B779400E", "Attempted to stop microphone capture, but it is already stopped");

            //Stop diagnostic output
            if (_microphoneDiagnosticOutput != null)
            {
                _microphoneDiagnosticOutput.Dispose();
                _microphoneDiagnosticOutput = null;
            }

            //Stop capture
            Microphone.End(_micName);
            _format   = null;
            _clip     = null;
            _readHead = 0;
            _started  = false;
            _micName  = null;

            //Clean the buffers
            _rawMicSamples.Reset();
            _rawMicFrames.Reset();

            //Stop watching for device changes
            AudioSettings.OnAudioConfigurationChanged -= OnAudioDeviceChanged;
            _audioDeviceChanged = false;
        }
        //These methods run on the main thread, they drain audio from the mic and send it across to subscribers
        //
        // UpdateSubscribers - Either discard mic samples (if no one is subscribed to mic data) or call DrainMicSamples
        // DrainMicSamples   - Read as many samples as possible from the mic (using a set of pow2 sized buffers to get as
        //                     much as possible), passes samples to ConsumeSamples
        // ConsumeMicSamples - Take some number of samples from produced by DrainMicSamples and buffer them up, call SendFrame
        //                     every time some samples are added to the buffer
        // SendFrame         - Read as many frames as possible from the buffer and send them to the subscribers

        public bool UpdateSubscribers()
        {
            //Don't deliver any audio at all until microphone has initialised (i.e. delivered at least one sample)
            if (!_started)
            {
                _readHead = Microphone.GetPosition(_micName);
                _started  = _readHead > 0;

                if (!_started)
                {
                    return(false);
                }
            }

            // If the clip capacity is zero then something has gone horribly wrong! This can happen if the microphone hardware fails...
            // ...but we don't get an audio device reset event for some reason. Force the mic to reinitialize (hope it fixes the problem).
            if (_clip.samples == 0)
            {
                Log.Error("Unknown microphone capture error (zero length clip) - restarting mic");
                return(true);
            }

            // If the audio device changes then we really don't know what state we're in any more (e.g. the mic could have just been unplugged).
            // Force the mic to reinitialize (setting us back to a known state).
            if (_audioDeviceChanged)
            {
                Log.Debug("Audio device changed - restarting mic");
                return(true);
            }

            // If the microphone simply isn't recording at this point something has gone wrong, for example an external script has called Microphone.End
            // or something else has taken exclusive control of the mic. Force a reset and hope that fixes the issue.
            if (!Microphone.IsRecording(_micName))
            {
                Log.Warn("Microphone stopped recording for an unknown reason (possibly due to an external script calling `Microphone.End`");
                return(true);
            }

            if (_subscribers.Count > 0)
            {
                //There are subscribers - drain data from mic and pass it on to the subscribers
                DrainMicSamples();
            }
            else
            {
                //No subscribers - discard the data in the mic input buffer
                _readHead = Microphone.GetPosition(_micName);
                _rawMicSamples.Reset();
                _rawMicFrames.Reset();

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

            return(false);
        }
示例#7
0
 public void Prepare(SessionContext context)
 {
     if (DebugSettings.Instance.EnablePlaybackDiagnostics && DebugSettings.Instance.RecordDecodedAudio)
     {
         var filename = string.Format("Dissonance_Diagnostics/Decoded_{0}_{1}_{2}", context.PlayerName, context.Id, DateTime.UtcNow.ToFileTime());
         _diagnosticOutput = new AudioFileWriter(filename, _waveFormat);
     }
 }
示例#8
0
        public void Reset()
        {
            _buffer.Reset();
            _decoder.Reset();

            if (_diagnosticOutput != null)
            {
                _diagnosticOutput.Dispose();
                _diagnosticOutput = null;
            }
        }
示例#9
0
        public FolderWriter(string FolderName, int FrameRate, IAudioProvider AudioProvider)
        {
            _folderPath   = FolderName;
            SupportsAudio = AudioProvider != null;

            Directory.CreateDirectory(FolderName);

            File.WriteAllText(Path.Combine(FolderName, "FrameRate.txt"), FrameRate.ToString());

            if (SupportsAudio)
            {
                _audioWriter = new AudioFileWriter(Path.Combine(FolderName, "audio.wav"), AudioProvider.WaveFormat);
            }
        }
示例#10
0
        public void Reset()
        {
            _buffer.Reset();
            _decoder.Reset();

            using (var l = _options.Lock())
                l.Value = new PlaybackOptions(false, 1, ChannelPriority.Default);

            using (var l = _channels.Lock())
                l.Value.Clear();

            if (_diagnosticOutput != null)
            {
                _diagnosticOutput.Dispose();
                _diagnosticOutput = null;
            }
        }
示例#11
0
        public void Dispose()
        {
            if (!_disposed)
            {
                _preprocessing.Dispose();
                Microphone.End(_micName);

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

                Log.Debug("Stopping audio capture thread");
            }
            _disposed = true;
        }
示例#12
0
        /// <summary>
        /// Read as many frames as possible from the mic sample buffer and pass them to the encoding thread
        /// </summary>
        private void SendFrame()
        {
            //Drain as many frames as possible
            while (_rawMicSamples.Count > _rawMicFrames.FrameSize)
            {
                //Try to get a frame
                var segment   = new ArraySegment <float>(_frame);
                var available = _rawMicFrames.Read(segment);
                if (!available)
                {
                    break;
                }

                //Create diagnostic writer (if necessary)
                if (DebugSettings.Instance.EnableRecordingDiagnostics && DebugSettings.Instance.RecordMicrophoneRawAudio)
                {
                    if (_microphoneDiagnosticOutput == null)
                    {
                        var filename = string.Format("Dissonance_Diagnostics/MicrophoneRawAudio_{0}", DateTime.UtcNow.ToFileTime());
                        _microphoneDiagnosticOutput = new AudioFileWriter(filename, _format);
                    }
                }
                else if (_microphoneDiagnosticOutput != null)
                {
                    _microphoneDiagnosticOutput.Dispose();
                    _microphoneDiagnosticOutput = null;
                }

                //Write out the diagnostic info
                if (_microphoneDiagnosticOutput != null)
                {
                    _microphoneDiagnosticOutput.WriteSamples(segment);
                    _microphoneDiagnosticOutput.Flush();
                }

                //Send frame to subscribers
                for (var i = 0; i < _subscribers.Count; i++)
                {
                    _subscribers[i].ReceiveMicrophoneData(segment, _format);
                }
            }
        }
示例#13
0
        /// <summary>
        /// Creates a new instance of <see cref="FFMpegMuxedWriter"/>.
        /// </summary>
        /// <param name="FilePath">Path for the output file.</param>
        /// <param name="FrameRate">Video Frame Rate.</param>
        public FFMpegMuxedWriter(string FilePath, int FrameRate, int VideoQuality, FFMpegVideoArgsProvider VideoArgsProvider, int AudioQuality, FFMpegAudioArgsProvider AudioArgsProvider, IAudioProvider AudioProvider)
        {
            if (AudioProvider == null)
            {
                throw new ArgumentNullException(nameof(AudioProvider), $"{nameof(AudioProvider)} can't be null. Use {nameof(FFMpegVideoWriter)} instead.");
            }

            if (!Directory.Exists(BaseDir))
            {
                Directory.CreateDirectory(BaseDir);
            }

            var fileName = Path.GetFileName(FilePath);

            tempVideoPath = Path.Combine(BaseDir, fileName);
            tempAudioPath = Path.Combine(BaseDir, Path.ChangeExtension(fileName, ".wav"));

            _audioWriter = new AudioFileWriter(tempAudioPath, AudioProvider.WaveFormat);

            _videoWriter = new FFMpegVideoWriter(tempVideoPath, FrameRate, VideoQuality, VideoArgsProvider);

            _ffmpegArgs = $"-i {tempVideoPath} -vcodec copy -i {tempAudioPath} {AudioArgsProvider(AudioQuality)} \"{FilePath}\"";
        }
示例#14
0
        private void StartCapture()
        {
            if (_subscribed)
            {
                throw Log.CreatePossibleBugException("Cannot subscribe encoder to mic: already subscribed", "B1F845C2-3A9F-48F0-B9D2-4E5457CFDCB8");
            }
            Log.Debug("Subscribing encoder to microphone");

            if (DebugSettings.Instance.EnableRecordingDiagnostics && DebugSettings.Instance.RecordEncoderPipelineInputAudio)
            {
                var filename = string.Format("Dissonance_Diagnostics/EncoderPipelineInput_{0}", DateTime.UtcNow.ToFileTime());
                _microphoneDiagnosticOutput = new AudioFileWriter(filename, _inputFormat);
            }

            if (DebugSettings.Instance.EnableRecordingDiagnostics && DebugSettings.Instance.RecordEncoderPipelineOutputAudio)
            {
                var filename = string.Format("Dissonance_Diagnostics/EncoderPipelineOutput_{0}", DateTime.UtcNow.ToFileTime());
                _preEncodeDiagnosticOutput = new AudioFileWriter(filename, _output.WaveFormat);
            }

            _mic.Subscribe(this);
            _subscribed = true;
        }
示例#15
0
        /// <summary>
        /// Read as many frames as possible from the mic sample buffer and pass them to the encoding thread
        /// </summary>
        private void SendFrame()
        {
            while (_rawMicSamples.Count > _preprocessing.InputFrameSize)
            {
                //Get an empty buffer from the pool of buffers (sent back from the audio processing thread)
                var frameBuffer = _preprocessing.GetFrameBuffer();

                //Read a complete frame
                _rawMicFrames.Read(new ArraySegment <float>(frameBuffer));

                //Create diagnostic writer (if necessary)
                if (DebugSettings.Instance.EnableRecordingDiagnostics && DebugSettings.Instance.RecordMicrophoneRawAudio)
                {
                    if (_microphoneDiagnosticOutput == null)
                    {
                        var filename = string.Format("Dissonance_Diagnostics/MicrophoneRawAudio_{0}", DateTime.UtcNow.ToFileTime());
                        _microphoneDiagnosticOutput = new AudioFileWriter(filename, _rawMicSamples.WaveFormat);
                    }
                }
                else if (_microphoneDiagnosticOutput != null)
                {
                    _microphoneDiagnosticOutput.Dispose();
                    _microphoneDiagnosticOutput = null;
                }

                //Write out the diagnostic info
                if (_microphoneDiagnosticOutput != null)
                {
                    _microphoneDiagnosticOutput.WriteSamples(new ArraySegment <float>(frameBuffer));
                    _microphoneDiagnosticOutput.Flush();
                }

                //Send the full buffer to the audio thread for processing (no copying, just pass the entire buffer across by ref)
                _preprocessing.Send(frameBuffer);
            }
        }
示例#16
0
        internal static bool Filter(SpeechSession session, float[] data, int channels, float[] temp, [CanBeNull] AudioFileWriter diagnosticOutput, out float arv, out int samplesRead, bool multiply)
        {
            //Read out data from source (exactly as much as we need for one channel)
            var samplesRequired = data.Length / channels;
            var complete        = session.Read(new ArraySegment <float>(temp, 0, samplesRequired));

            if (diagnosticOutput != null)
            {
                diagnosticOutput.WriteSamples(new ArraySegment <float>(temp, 0, samplesRequired));
            }

            float accumulator = 0;

            //Step through samples, stretching them (i.e. play mono input in all output channels)
            var sampleIndex = 0;

            for (var i = 0; i < data.Length; i += channels)
            {
                //Get a single sample from the source data
                var sample = temp[sampleIndex++];

                //Accumulate the sum of the audio signal
                accumulator += Mathf.Abs(sample);

                //Copy data into all channels
                for (var c = 0; c < channels; c++)
                {
                    if (multiply)
                    {
                        data[i + c] *= sample;
                    }
                    else
                    {
                        data[i + c] = sample;
                    }
                }
            }

            arv         = accumulator / data.Length;
            samplesRead = samplesRequired;

            return(complete);
        }
示例#17
0
        public void OnAudioFilterRead(float[] data, int channels)
        {
            //If there is no session, clear filter and early exit
            var maybeSession = Session;

            if (!maybeSession.HasValue)
            {
                Array.Clear(data, 0, data.Length);
                return;
            }

            _sessionLock.EnterUpgradeableReadLock();
            try
            {
                //Check if there is no session again, this time protected by a lock
                maybeSession = Session;
                if (!maybeSession.HasValue)
                {
                    Array.Clear(data, 0, data.Length);
                    return;
                }

                //Detect if the session has changed since the last call to this method, if so reset
                if (!maybeSession.Value.Context.Equals(_lastPlayedSessionContext))
                {
                    _lastPlayedSessionContext = maybeSession.Value.Context;
                    ApplyReset();
                }

                //Calculate the difference between where we should be and where we are (in samples)
                var session = maybeSession.Value;
                _desync.Update(IdealPlaybackPosition, PlaybackPosition);

                //If necessary skip samples to bring us back in sync
                int deltaDesync, deltaSamples;
                var complete = Skip(session, _desync.DesyncMilliseconds, out deltaSamples, out deltaDesync);
                Interlocked.Add(ref _totalSamplesRead, deltaSamples);
                _desync.Skip(deltaDesync);

                //If the session wasn't completed by the skip, keep playing
                if (!complete)
                {
                    int   samples;
                    float arv;
                    complete = Filter(session, data, channels, _temp, _diagnosticOutput, out arv, out samples, MultiplyBySource);
                    _arv     = arv;
                    Interlocked.Add(ref _totalSamplesRead, samples);
                }

                //Clean up now that this session is complete
                if (complete)
                {
                    Log.Debug("Finished playback of speech session. id={0}", session.Context.Id);

                    //Clear the session
                    _sessionLock.EnterWriteLock();
                    try
                    {
                        Session = null;
                    }
                    finally
                    {
                        _sessionLock.ExitWriteLock();
                    }

                    //Reset the state
                    ApplyReset();

                    //Discard the diagnostic recorder if necessary
                    if (_diagnosticOutput != null)
                    {
                        _diagnosticOutput.Dispose();
                        _diagnosticOutput = null;
                    }
                }
            }
            finally
            {
                _sessionLock.ExitUpgradeableReadLock();
            }
        }
示例#18
0
        private void Record()
        {
            try
            {
                _stopWrite.Reset();

                if (!String.IsNullOrEmpty(Micobject.recorder.trigger))
                {
                    string[] tid = Micobject.recorder.trigger.Split(',');
                    switch (tid[0])
                    {
                        case "1":
                            VolumeLevel vl = MainForm.InstanceReference.GetVolumeLevel(Convert.ToInt32(tid[1]));
                            if (vl != null && !vl.Recording)
                                vl.RecordSwitch(true);
                            break;
                        case "2":
                            CameraWindow c = MainForm.InstanceReference.GetCameraWindow(Convert.ToInt32(tid[1]));
                            if (c != null && !c.Recording)
                                c.RecordSwitch(true);
                            break;
                    }
                }
                var cw = CameraControl;
                //
                if (cw != null)
                {
                    if (cw.AbortedAudio)
                    {
                        MainForm.LogErrorToFile(Micobject.name +
                                                ": paired recording aborted as the camera is already recording");
                        ForcedRecording = false;
                        return;
                    }
                }
                try
                {
                    if (cw != null)
                    {
                        cw.ForcedRecording = ForcedRecording;
                        cw.StartSaving();
                        _stopWrite.WaitOne();
                    }
                    else
                    {
                        #region mp3writer

                        DateTime date = DateTime.Now;

                        string filename = String.Format("{0}-{1}-{2}_{3}-{4}-{5}",
                            date.Year, Helper.ZeroPad(date.Month), Helper.ZeroPad(date.Day),
                            Helper.ZeroPad(date.Hour), Helper.ZeroPad(date.Minute),
                            Helper.ZeroPad(date.Second));

                        AudioFileName = Micobject.id + "_" + filename;
                        string folder = Dir.Entry + "audio\\" + Micobject.directory + "\\";
                        if (!Directory.Exists(folder))
                            Directory.CreateDirectory(folder);
                        filename = folder + AudioFileName;

                        _writer = new AudioFileWriter();
                        try
                        {
                            Program.FFMPEGMutex.WaitOne();
                            _writer.Open(filename + ".mp3", AudioCodec.MP3,
                                AudioSource.RecordingFormat.BitsPerSample*AudioSource.RecordingFormat.SampleRate*
                                AudioSource.RecordingFormat.Channels, AudioSource.RecordingFormat.SampleRate,
                                AudioSource.RecordingFormat.Channels);
                        }
                        finally
                        {
                            try
                            {
                                Program.FFMPEGMutex.ReleaseMutex();
                            }
                            catch (ObjectDisposedException)
                            {
                                //can happen on shutdown
                            }
                        }

                        double maxlevel = 0;
                        bool first = true;
                        DateTime recordingStart = Helper.Now;

                        try
                        {
                            while (!_stopWrite.WaitOne(5))
                            {
                                Helper.FrameAction fa;
                                while (Buffer.TryDequeue(out fa))
                                {
                                    if (first)
                                    {
                                        recordingStart = fa.TimeStamp;
                                        first = false;
                                    }

                                    if (fa.FrameType == Enums.FrameType.Audio)
                                    {
                                        unsafe
                                        {
                                            fixed (byte* p = fa.Content)
                                            {
                                                _writer.WriteAudio(p, fa.DataLength);
                                            }
                                        }
                                        float d = Levels.Max();
                                        _soundData.Append(String.Format(CultureInfo.InvariantCulture,
                                            "{0:0.000}", d));
                                        _soundData.Append(",");
                                        if (d > maxlevel)
                                            maxlevel = d;
                                    }
                                    fa.Nullify();

                                }
                            }

                            FilesFile ff = _filelist.FirstOrDefault(p => p.Filename.EndsWith(AudioFileName + ".mp3"));
                            bool newfile = false;
                            if (ff == null)
                            {
                                ff = new FilesFile();
                                newfile = true;
                            }

                            string[] fnpath = (filename + ".mp3").Split('\\');
                            string fn = fnpath[fnpath.Length - 1];
                            var fi = new FileInfo(filename + ".mp3");
                            var dSeconds = Convert.ToInt32((Helper.Now - recordingStart).TotalSeconds);

                            ff.CreatedDateTicks = DateTime.Now.Ticks;
                            ff.Filename = fnpath[fnpath.Length - 1];
                            ff.MaxAlarm = maxlevel;
                            ff.SizeBytes = fi.Length;
                            ff.DurationSeconds = dSeconds;
                            ff.IsTimelapse = false;
                            ff.IsMergeFile = false;
                            ff.AlertData = Helper.GetMotionDataPoints(_soundData);
                            _soundData.Clear();
                            ff.TriggerLevel = Micobject.detector.minsensitivity;
                            ff.TriggerLevelMax = Micobject.detector.maxsensitivity;

                            if (newfile)
                            {
                                lock (_lockobject)
                                {
                                    _filelist.Insert(0, ff);
                                }

                                MainForm.MasterFileAdd(new FilePreview(fn, dSeconds, Micobject.name, DateTime.Now.Ticks,
                                    1, Micobject.id, ff.MaxAlarm, false, false));
                                MainForm.NeedsMediaRefresh = Helper.Now;

                            }

                        }
                        catch (Exception ex)
                        {
                            if (ErrorHandler != null)
                                ErrorHandler(ex.Message);
                        }

                        if (_writer != null && _writer.IsOpen)
                        {
                            try
                            {
                                Program.FFMPEGMutex.WaitOne();
                                _writer.Dispose();
                            }
                            catch (Exception ex)
                            {
                                if (ErrorHandler != null)
                                    ErrorHandler(ex.Message);
                            }
                            finally
                            {
                                try
                                {
                                    Program.FFMPEGMutex.ReleaseMutex();
                                }
                                catch (ObjectDisposedException)
                                {
                                    //can happen on shutdown
                                }
                            }
                        }

                        _writer = null;

                        #endregion
                    }

                    UpdateFloorplans(false);
                }
                catch (Exception ex)
                {
                    if (ErrorHandler != null)
                        ErrorHandler(ex.Message);
                }

                if (!String.IsNullOrEmpty(Micobject.recorder.trigger))
                {
                    string[] tid = Micobject.recorder.trigger.Split(',');
                    switch (tid[0])
                    {
                        case "1":
                            VolumeLevel vl = MainForm.InstanceReference.GetVolumeLevel(Convert.ToInt32(tid[1]));
                            if (vl != null)
                                vl.RecordSwitch(false);
                            break;
                        case "2":
                            CameraWindow c = MainForm.InstanceReference.GetCameraWindow(Convert.ToInt32(tid[1]));
                            if (c != null)
                                c.RecordSwitch(false);
                            break;
                    }
                }

                if (cw == null)
                {
                    Micobject.newrecordingcount++;
                    if (Notification != null)
                        Notification(this, new NotificationType("NewRecording", Micobject.name, ""));
                }
            }
            catch (Exception ex)
            {
                MainForm.LogExceptionToFile(ex);
            }
        }
示例#19
0
文件: VolumeLevel.cs 项目: vmail/main
        private void Record()
        {
            _stopWrite = false;
            DateTime recordingStart = DateTime.MinValue;

            if (!String.IsNullOrEmpty(Micobject.recorder.trigger) && TopLevelControl != null)
            {
                string[] tid = Micobject.recorder.trigger.Split(',');
                switch (tid[0])
                {
                    case "1":
                        VolumeLevel vl = ((MainForm)TopLevelControl).GetVolumeLevel(Convert.ToInt32(tid[1]));
                        if (vl != null)
                            vl.RecordSwitch(true);
                        break;
                    case "2":
                        CameraWindow cw = ((MainForm)TopLevelControl).GetCameraWindow(Convert.ToInt32(tid[1]));
                        if (cw != null)
                            cw.RecordSwitch(true);
                        break;
                }
            }

            try
            {
                WriterBuffer = new QueueWithEvents<AudioAction>();
                WriterBuffer.Changed += WriterBufferChanged;

                _pairedRecording = false;
                if (CameraControl!=null && CameraControl.Camobject.settings.active)
                {
                    _pairedRecording = true;
                    CameraControl.StartSaving();
                    CameraControl.ForcedRecording = ForcedRecording;
                    while (!_stopWrite)
                    {
                        _newRecordingFrame.WaitOne(200);
                    }
                }
                else
                {
                    #region mp3writer

                    DateTime date = DateTime.Now;

                    string filename = String.Format("{0}-{1}-{2}_{3}-{4}-{5}",
                                                    date.Year, Helper.ZeroPad(date.Month), Helper.ZeroPad(date.Day),
                                                    Helper.ZeroPad(date.Hour), Helper.ZeroPad(date.Minute),
                                                    Helper.ZeroPad(date.Second));

                    AudioFileName = Micobject.id + "_" + filename;
                    filename = MainForm.Conf.MediaDirectory + "audio\\" + Micobject.directory + "\\";
                    filename += AudioFileName;

                    Program.WriterMutex.WaitOne();
                    try
                    {
                        _writer = new AudioFileWriter();
                        _writer.Open(filename + ".mp3", AudioCodec.MP3, AudioSource.RecordingFormat.BitsPerSample * AudioSource.RecordingFormat.SampleRate * AudioSource.RecordingFormat.Channels, AudioSource.RecordingFormat.SampleRate, AudioSource.RecordingFormat.Channels);
                    }
                    catch (Exception ex)
                    {
                        Log.Error("",ex);//MainForm.LogExceptionToFile(ex);
                    }
                    finally
                    {
                        Program.WriterMutex.ReleaseMutex();
                    }

                    double maxlevel = 0;
                    foreach (AudioAction aa in AudioBuffer.OrderBy(p=>p.TimeStamp))
                    {
                        if (recordingStart == DateTime.MinValue)
                        {
                            recordingStart = aa.TimeStamp;
                        }

                        unsafe
                        {
                            fixed (byte* p = aa.Decoded)
                            {
                                _writer.WriteAudio(p, aa.Decoded.Length);
                            }
                        }

                        _soundData.Append(String.Format(CultureInfo.InvariantCulture,
                                                        "{0:0.000}", aa.SoundLevel));
                        _soundData.Append(",");
                        if (aa.SoundLevel > maxlevel)
                            maxlevel = aa.SoundLevel;
                    }

                    AudioBuffer.Clear();

                    if (recordingStart == DateTime.MinValue)
                        recordingStart = DateTime.Now;

                    try
                    {
                        while (!_stopWrite)
                        {
                            while (WriterBuffer.Count > 0)
                            {
                                AudioAction b;
                                lock (_obj)
                                {
                                    b = WriterBuffer.Dequeue();
                                }
                                unsafe
                                {
                                    fixed (byte* p = b.Decoded)
                                    {
                                        _writer.WriteAudio(p, b.Decoded.Length);
                                    }
                                }
                                float d = Levels.Max();
                                _soundData.Append(String.Format(CultureInfo.InvariantCulture,
                                                               "{0:0.000}", d));
                                _soundData.Append(",");
                                if (d > maxlevel)
                                    maxlevel = d;

                            }
                            _newRecordingFrame.WaitOne(200);
                        }

                        FilesFile ff = FileList.FirstOrDefault(p => p.Filename.EndsWith(AudioFileName + ".mp3"));
                        bool newfile = false;
                        if (ff == null)
                        {
                            ff = new FilesFile();
                            newfile = true;
                        }

                        string[] fnpath = (filename + ".mp3").Split('\\');
                        string fn = fnpath[fnpath.Length - 1];
                        var fi = new FileInfo(filename + ".mp3");
                        var dSeconds = Convert.ToInt32((DateTime.Now - recordingStart).TotalSeconds);

                        ff.CreatedDateTicks = DateTime.Now.Ticks;
                        ff.Filename = fnpath[fnpath.Length - 1];
                        ff.MaxAlarm = maxlevel;
                        ff.SizeBytes = fi.Length;
                        ff.DurationSeconds = dSeconds;
                        ff.IsTimelapse = false;
                        ff.AlertData = Helper.GetMotionDataPoints(_soundData);
                        _soundData.Clear();
                        ff.TriggerLevel = Micobject.detector.sensitivity;

                        if (newfile)
                        {
                            FileList.Insert(0, ff);
                            if (MainForm.MasterFileList.Count(p => p.Filename.EndsWith(fn)) == 0)
                            {
                                MainForm.MasterFileList.Add(new FilePreview(fn, dSeconds, Micobject.name, DateTime.Now.Ticks, 1,Micobject.id, ff.MaxAlarm));
                            }
                        }

                    }
                    catch (Exception ex)
                    {
                        Log.Error("",ex);//MainForm.LogExceptionToFile(ex);
                    }

                    Program.WriterMutex.WaitOne();
                    try
                    {
                        _writer.Close();
                        _writer.Dispose();
                    }
                    catch (Exception ex)
                    {
                        Log.Error("",ex);//MainForm.LogExceptionToFile(ex);
                    }
                    finally
                    {
                        Program.WriterMutex.ReleaseMutex();
                    }

                    _writer = null;
                    #endregion
                }
                _stopWrite = false;
                WriterBuffer = null;
                _recordingTime = 0;
                UpdateFloorplans(false);
            }
            catch (Exception ex)
            {
                Log.Error("",ex);//MainForm.LogExceptionToFile(ex);
            }

            if (!String.IsNullOrEmpty(Micobject.recorder.trigger) && TopLevelControl != null)
            {
                string[] tid = Micobject.recorder.trigger.Split(',');
                switch (tid[0])
                {
                    case "1":
                        VolumeLevel vl = ((MainForm)TopLevelControl).GetVolumeLevel(Convert.ToInt32(tid[1]));
                        if (vl != null)
                            vl.RecordSwitch(false);
                        break;
                    case "2":
                        CameraWindow cw = ((MainForm)TopLevelControl).GetCameraWindow(Convert.ToInt32(tid[1]));
                        if (cw != null)
                            cw.RecordSwitch(false);
                        break;
                }
            }

            if (!_pairedRecording)
            {
                Micobject.newrecordingcount++;
                if (Notification != null)
                    Notification(this, new NotificationType("NewRecording", Micobject.name, ""));
            }
        }
        internal static bool Filter(SpeechSession session, [NotNull] float[] output, int channels, [NotNull] float[] temp, [CanBeNull] AudioFileWriter diagnosticOutput, out float arv)
        {
            //Read out data from source (exactly as much as we need for one channel)
            var samplesRequired = output.Length / channels;
            var complete        = session.Read(new ArraySegment <float>(temp, 0, samplesRequired));

            //Write the audio we're about to play to the diagnostics writer (on disk)
            if (diagnosticOutput != null)
            {
                diagnosticOutput.WriteSamples(new ArraySegment <float>(temp, 0, samplesRequired));
            }

            //Step through samples, stretching them (i.e. play mono input in all output channels)
            float accumulator = 0;
            var   sampleIndex = 0;

            for (var i = 0; i < output.Length; i += channels)
            {
                //Get a single sample from the source data
                var sample = temp[sampleIndex++];

                //Accumulate the sum of the audio signal
                accumulator += Mathf.Abs(sample);

                //Copy data into all channels
                for (var c = 0; c < channels; c++)
                {
                    output[i + c] *= sample;
                }
            }

            arv = accumulator / output.Length;

            return(complete);
        }
        public void OnAudioFilterRead([NotNull] float[] data, int channels)
        {
            //If there is no session, clear filter and early exit
            var maybeSession = Session;

            if (!maybeSession.HasValue)
            {
                Array.Clear(data, 0, data.Length);
                return;
            }

            _sessionLock.EnterUpgradeableReadLock();
            try
            {
                //Check if there is no session again, this time protected by a lock
                maybeSession = Session;
                if (!maybeSession.HasValue)
                {
                    Array.Clear(data, 0, data.Length);
                    return;
                }

                //Detect if the session has changed since the last call to this method, if so reset
                var session = maybeSession.Value;
                if (!session.Context.Equals(_lastPlayedSessionContext))
                {
                    _lastPlayedSessionContext = maybeSession.Value.Context;
                    ApplyReset();
                }

                // Read data from pipeline
                float arv;
                var   complete = Filter(session, data, channels, _temp, _diagnosticOutput, out arv);
                _arv = arv;

                //Clean up now that this session is complete
                if (complete)
                {
                    Log.Debug("Finished playback of speech session. id={0}. player={1}", session.Context.Id, session.Context.PlayerName);

                    //Clear the session
                    _sessionLock.EnterWriteLock();
                    try
                    {
                        Session = null;
                    }
                    finally
                    {
                        _sessionLock.ExitWriteLock();
                    }

                    //Reset the state
                    ApplyReset();

                    //Discard the diagnostic recorder if necessary
                    if (_diagnosticOutput != null)
                    {
                        _diagnosticOutput.Dispose();
                        _diagnosticOutput = null;
                    }
                }
            }
            finally
            {
                _sessionLock.ExitUpgradeableReadLock();
            }
        }