/// <summary> /// Stop recording audio and save it to destination WAV-file /// </summary> /// <param name="destination">Output WAV file containing recorderd sound</param> public void StopRecording(string destination) { var mciCommand = "stop capture"; Mci.SendString(mciCommand, null, 0, 0); mciCommand = string.Format("save capture {0}", destination); Mci.SendString(mciCommand, null, 0, 0); mciCommand = "close capture"; Mci.SendString(mciCommand, null, 0, 0); }
/// <summary> /// Pause audio playback /// </summary> public void Pause() { if (_alias == null) { return; } var mciCommand = string.Format("pause {0}", _alias); Mci.SendString(mciCommand, null, 0, 0); _pauseTime = DateTime.Now; _isPaused = true; }
/// <summary> /// Resume playing audio /// </summary> public void Resume() { if (_alias == null || !_isPaused) { return; } var mciCommand = string.Format("resume {0}", _alias); Mci.SendString(mciCommand, null, 0, 0); var pause = DateTime.Now - _pauseTime; _pauseDuration += pause.Duration().Seconds * 1000 + pause.Duration().Milliseconds; _isPaused = false; }
/// <summary> /// Pauses playing audio. /// </summary> public void Pause() { if (_alias is null) { return; } var mciCommand = string.Format("pause {0}", _alias); Mci.SendString(mciCommand, null, 0, 0); // If the playback was paused, the player memorizes how many milliseconds // it was "idle" and then adds this time to the total awaiting time. _pauseTime = DateTime.Now; _isPaused = true; }
/// <summary> /// Stop playing audio and close MCI device /// </summary> public void Stop() { if (_alias == null) { return; } if (_isPaused) { Resume(); } var mciCommand = string.Format("stop {0}", _alias); Mci.SendString(mciCommand, null, 0, 0); mciCommand = string.Format("close {0}", _alias); Mci.SendString(mciCommand, null, 0, 0); _alias = null; }
/// <summary> /// Start recording audio with specific settings /// </summary> /// <param name="samplingRate">Sampling rate</param> /// <param name="channelCount">Number of channels (1=mono, 2=stereo)</param> /// <param name="bitsPerSample">Number of bits per sample (8, 16, 24 or 32)</param> public void StartRecording(int samplingRate = 44100, short channelCount = 1, short bitsPerSample = 16) { var mciCommand = "open new type waveaudio alias capture"; var result = Mci.SendString(mciCommand, null, 0, 0); if (result != 0) { throw new System.InvalidOperationException("Could not open device for recording!"); } mciCommand = string.Format("set capture alignment {0} bitspersample {1} samplespersec {2} " + "channels {3} bytespersec {4} time format samples format tag pcm", channelCount * bitsPerSample / 8, bitsPerSample, samplingRate, channelCount, samplingRate * channelCount * bitsPerSample / 8); Mci.SendString(mciCommand, null, 0, 0); mciCommand = "record capture"; Mci.SendString(mciCommand, null, 0, 0); }
/// <summary> /// Play audio contained in WAV file asynchronously /// </summary> /// <param name="source">WAV file to play</param> /// <param name="startPos">Number of the first sample to play</param> /// <param name="endPos">Number of the last sample to play</param> public async Task PlayAsync(string source, int startPos = 0, int endPos = -1) { if (_isPaused) { Resume(); return; } Stop(); _alias = Guid.NewGuid().ToString(); var mciCommand = string.Format("open \"{0}\" type waveaudio alias {1}", source, _alias); Mci.SendString(mciCommand, null, 0, 0); mciCommand = string.Format("set {0} time format samples", _alias); Mci.SendString(mciCommand, null, 0, 0); var durationBuffer = new StringBuilder(255); mciCommand = string.Format("status {0} length", _alias); Mci.SendString(mciCommand, durationBuffer, 255, 0); var duration = int.Parse(durationBuffer.ToString()); var samplingRateBuffer = new StringBuilder(255); mciCommand = string.Format("status {0} samplespersec", _alias); Mci.SendString(mciCommand, samplingRateBuffer, 255, 0); var samplingRate = int.Parse(samplingRateBuffer.ToString()); mciCommand = string.Format("play {2} from {0} to {1} notify", startPos, endPos, _alias); mciCommand = mciCommand.Replace(" to -1", ""); Mci.SendString(mciCommand, null, 0, 0); // ======= here's how we do asynchrony with old technology from 90's )) ======== var currentAlias = _alias; await Task.Delay((int)(duration * 1000.0 / samplingRate)); // During this time someone could Pause player. // In this case we add pause duration to awaiting time. while (_isPaused || _pauseDuration > 0) { // first, we check if the pause is right now if (_isPaused) { // then just await one second more // (the stupidest wait spin I wrote in years )))) await Task.Delay(1000); } if (_pauseDuration > 0) { await Task.Delay(_pauseDuration); _pauseDuration = 0; } } // During this time someone could stop and run player again, so _alias is already different. // In this case we don't stop player here because it was stopped some time before. if (currentAlias == _alias) { Stop(); } // ============================================================================= }