public static bool ExportSample(SampleGeneratingArgs sampleGeneratingArgs, string name, string exportFolder, Dictionary <SampleGeneratingArgs, SampleSoundGenerator> loadedSamples = null, SampleExportFormat format = SampleExportFormat.Default) { // Export as midi file with single note if (format == SampleExportFormat.MidiChords) { MidiExporter.SaveToFile(Path.Combine(exportFolder, name + ".mid"), new[] { sampleGeneratingArgs }); return(true); } if (sampleGeneratingArgs.CanCopyPaste && format == SampleExportFormat.Default) { var dest = Path.Combine(exportFolder, name + sampleGeneratingArgs.GetExtension()); return(CopySample(sampleGeneratingArgs.Path, dest)); } SampleSoundGenerator sampleSoundGenerator; if (loadedSamples != null) { if (SampleImporter.ValidateSampleArgs(sampleGeneratingArgs, loadedSamples)) { sampleSoundGenerator = loadedSamples[sampleGeneratingArgs]; } else { return(false); } } else { try { sampleSoundGenerator = SampleImporter.ImportSample(sampleGeneratingArgs); } catch (Exception ex) { Console.WriteLine($@"{ex.Message} while importing sample {sampleGeneratingArgs}."); return(false); } } var sourceWaveEncoding = sampleSoundGenerator.Wave.WaveFormat.Encoding; // Either if it is the blank sample or the source file is literally what the user wants to be exported if (sampleSoundGenerator.BlankSample && sampleGeneratingArgs.GetExtension() == ".wav" || sampleGeneratingArgs.CanCopyPaste && IsCopyCompatible(sampleGeneratingArgs, sourceWaveEncoding, format)) { var dest = Path.Combine(exportFolder, name + sampleGeneratingArgs.GetExtension()); return(CopySample(sampleGeneratingArgs.Path, dest)); } var sampleProvider = sampleSoundGenerator.GetSampleProvider(); if ((format == SampleExportFormat.WavePcm || format == SampleExportFormat.OggVorbis) && sourceWaveEncoding == WaveFormatEncoding.IeeeFloat) { // When the source is IEEE float and the export format is PCM or Vorbis, then clipping is possible, so we add a limiter sampleProvider = new SoftLimiter(sampleProvider); } switch (format) { case SampleExportFormat.WaveIeeeFloat: CreateWaveFile(Path.Combine(exportFolder, name + ".wav"), sampleProvider.ToWaveProvider()); break; case SampleExportFormat.WavePcm: CreateWaveFile(Path.Combine(exportFolder, name + ".wav"), sampleProvider.ToWaveProvider16()); break; case SampleExportFormat.OggVorbis: var resampled = new WdlResamplingSampleProvider(sampleProvider, VorbisFileWriter.GetSupportedSampleRate(sampleProvider.WaveFormat.SampleRate)); VorbisFileWriter.CreateVorbisFile(Path.Combine(exportFolder, name + ".ogg"), resampled.ToWaveProvider()); break; default: switch (sourceWaveEncoding) { case WaveFormatEncoding.IeeeFloat: CreateWaveFile(Path.Combine(exportFolder, name + ".wav"), sampleProvider.ToWaveProvider()); break; case WaveFormatEncoding.Pcm: CreateWaveFile(Path.Combine(exportFolder, name + ".wav"), sampleProvider.ToWaveProvider16()); break; default: CreateWaveFile(Path.Combine(exportFolder, name + ".wav"), sampleProvider.ToWaveProvider()); break; } break; } return(true); }
private void PlayThread() { ResamplerDmoStream resamplerDmoStream = null; IWaveProvider playbackProvider = sourceProvider; Exception exception = null; WdlResamplingSampleProvider resamplerWdlStream = null; try { if (dmoResamplerNeeded) { if (!windowsN) { resamplerDmoStream = new ResamplerDmoStream(sourceProvider, outputFormat); playbackProvider = resamplerDmoStream; } else { resamplerWdlStream = new WdlResamplingSampleProvider(sourceProvider.ToSampleProvider(), outputFormat.SampleRate); playbackProvider = resamplerWdlStream.ToWaveProvider(); } } // fill a whole buffer bufferFrameCount = audioClient.BufferSize; bytesPerFrame = outputFormat.Channels * outputFormat.BitsPerSample / 8; readBuffer = new byte[bufferFrameCount * bytesPerFrame]; FillBuffer(playbackProvider, bufferFrameCount); // Create WaitHandle for sync var waitHandles = new WaitHandle[] { frameEventWaitHandle }; audioClient.Start(); while (playbackState != PlaybackState.Stopped) { // If using Event Sync, Wait for notification from AudioClient or Sleep half latency int indexHandle = 0; if (isUsingEventSync) { indexHandle = WaitHandle.WaitAny(waitHandles, 3 * latencyMilliseconds, false); } else { Thread.Sleep(latencyMilliseconds / 2); } // If still playing and notification is ok if (playbackState == PlaybackState.Playing && indexHandle != WaitHandle.WaitTimeout) { // See how much buffer space is available. int numFramesPadding; if (isUsingEventSync) { // In exclusive mode, always ask the max = bufferFrameCount = audioClient.BufferSize numFramesPadding = (shareMode == AudioClientShareMode.Shared) ? audioClient.CurrentPadding : 0; } else { numFramesPadding = audioClient.CurrentPadding; } int numFramesAvailable = bufferFrameCount - numFramesPadding; if (numFramesAvailable > 10) // see https://naudio.codeplex.com/workitem/16363 { FillBuffer(playbackProvider, numFramesAvailable); } } } Thread.Sleep(latencyMilliseconds / 2); audioClient.Stop(); if (playbackState == PlaybackState.Stopped) { audioClient.Reset(); } } catch (Exception e) { exception = e; } finally { if (resamplerDmoStream != null) { resamplerDmoStream.Dispose(); } RaisePlaybackStopped(exception); } }