private IWaveSource GetSoundSource(Stream stream) { var magic = new byte[8]; stream.Read(magic, 0, 8); stream.Position = 0; if (VisualC.CompareMemory(magic, _mp3Magic, 3) == 0 || VisualC.CompareMemory(magic, _mp3Magic2, 2) == 0) { return(new DmoMp3Decoder(stream)); } if (VisualC.CompareMemory(magic, _oggMagic, 4) == 0) { stream.Position = 0x1C; stream.Read(magic, 0, 8); stream.Position = 0; if (VisualC.CompareMemory(magic, _opusMagic, 8) == 0) { throw new NotSupportedException("Ogg Opus is not currently supported."); } var decoder = new VorbisDecoder(stream); var converter = new SampleToPcm16(decoder); return(converter); } if (VisualC.CompareMemory(magic, _flacMagic, 4) == 0) { return(new FlacFile(stream, FlacPreScanMode.Sync)); } if (VisualC.CompareMemory(magic, _riffMagic, 4) == 0) { stream.Position = 8; stream.Read(magic, 0, 7); if (VisualC.CompareMemory(magic, _waveMagic, 7) == 0) { return(new MediaFoundationDecoder(stream)); } stream.Position = 0; } if (VisualC.CompareMemory(magic, _m4aMagic, 7) == 0) { return(new MediaFoundationDecoder(stream)); } throw new FormatException("The stream is an unsupported format."); }
//*********************************************************************************************************************************************************************************************************** #region Control recorder (start, stop, pause, resume) /// <summary> /// Start a new record /// </summary> public void StartRecord() { try { if (RecordState == RecordStates.RECORDING) { return; } if (TrackInfo == null) { _logHandle.Report(new LogEventWarning("Record not started, because no track info exists.")); return; } CreateFilePath(); if (RecorderRecSettings.FileExistMode == RecorderFileExistModes.SKIP && (System.IO.File.Exists(FileStrWAV) || System.IO.File.Exists(FileStrMP3))) { _logHandle.Report(new LogEventWarning("Record (\"" + TrackInfo?.TrackName + "\") not started, because FileExistMode == SKIP and file already exists.")); return; } if (!Directory.Exists(RecorderRecSettings.BasePath)) { _logHandle.Report(new LogEventWarning("Record (\"" + TrackInfo?.TrackName + "\") not started, because RecordPath is invalid.")); return; } if (WasapiOut.IsSupportedOnCurrentPlatform) { _silenceOut = new WasapiOut(); } else { _silenceOut = new DirectSoundOut(); } _silenceOut.Initialize(new SilenceGenerator()); _silenceOut.Play(); //Play silence because otherwise silent parts aren't recorded _capture = new WasapiLoopbackCapture(); MMDeviceEnumerator devEnumerator = new MMDeviceEnumerator(); MMDeviceCollection mMDevices = devEnumerator.EnumAudioEndpoints(DataFlow.All, DeviceState.All); MMDevice dev; if (RecorderRecSettings.RecorderDeviceName.ToLower().Contains("default")) { dev = devEnumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia); } else { dev = mMDevices.Where(d => d.DeviceState == DeviceState.Active && d.FriendlyName == RecorderRecSettings.RecorderDeviceName)?.First(); } if (dev == null) { _logHandle.Report(new LogEventError("Record (\"" + TrackInfo?.TrackName + "\") not started, because device \"" + RecorderRecSettings.RecorderDeviceName + "\" wasn't found." + (RecorderRecSettings.RecorderDeviceName.Contains("CABLE Input") ? " Make sure that \"VB Cable\" is installed correctly." : ""))); return; } _capture.Device = dev; _capture.Initialize(); // Important!!! First set the capture device, then call Initialize(); otherwise audio is captured from the previous device SoundInSource soundInSource = new SoundInSource(_capture); SampleToPcm16 soundInSourcePCM = new SampleToPcm16(soundInSource.ToSampleSource()); //Used to convert _capture to Pcm16 format Directory.CreateDirectory(Path.GetDirectoryName(FileStrWAV)); _wavWriterFormat = new WaveFormat(_capture.WaveFormat.SampleRate, soundInSourcePCM.WaveFormat.BitsPerSample, _capture.WaveFormat.Channels, AudioEncoding.Pcm, _capture.WaveFormat.ExtraSize); //WAV file must be 16-bit PCM file for normalizing with normalize.exe _wavWriter = new WaveWriter(FileStrWAV, _wavWriterFormat); _wavWriterPositionBytes = 0; soundInSource.DataAvailable += (s, capData) => { if (RecordState == RecordStates.RECORDING) //Only record when RecordState is RECORDING { byte[] buffer = new byte[soundInSourcePCM.WaveFormat.BytesPerSecond / 2]; int read; while ((read = soundInSourcePCM.Read(buffer, 0, buffer.Length)) > 0) //keep reading as long as we still get some data { _wavWriter.Write(buffer, 0, read); //write the read data to a file _wavWriterPositionBytes += read; } } }; _capture.Start(); RecordState = RecordStates.RECORDING; _logHandle.Report(new LogEventInfo("Record (\"" + TrackInfo?.TrackName + "\") started.")); WasRecordPaused = false; } catch (Exception ex) { _logHandle.Report(new LogEventError("Error while starting record: " + ex.Message)); } }