private void GenerateToneWaveFile(string path, DtmfTone tone, int sampleRate, double duration, ISampleProvider noise = null) { var tone1 = new SignalGenerator(sampleRate, 1) { Gain = 0.5, Frequency = tone.LowTone, Type = SignalGeneratorType.Sin } .Take(TimeSpan.FromMilliseconds(duration)); var tone2 = new SignalGenerator(sampleRate, 1) { Gain = 0.5, Frequency = tone.HighTone, Type = SignalGeneratorType.Sin } .Take(TimeSpan.FromMilliseconds(duration)); var list = new List <ISampleProvider>(new[] { tone1, tone2 }); if (noise != null) { list.Add(noise.Take(TimeSpan.FromMilliseconds(duration))); } var mix = new MixingSampleProvider(list); WaveFileWriter.CreateWaveFile16(path, mix); }
/* Applies volume and pan parameters to outgoing samples*/ private ISampleProvider ProcessInput(ISampleProvider input, int bankIndex, int padIndex) { VolumeSampleProvider VSP = new VolumeSampleProvider(input); VSP.Volume = samplerModel.song.banks[bankIndex].pads[padIndex].volume; PanningSampleProvider PSP = new PanningSampleProvider(VSP.ToWaveProvider16().ToSampleProvider()); // <- this throws ArgumentException PSP.Pan = samplerModel.song.banks[bankIndex].pads[padIndex].pan; //ISampleProvider result = PSP.Skip(new TimeSpan(0, 0, (int) samplerModel.song.banks[bankIndex].pads[padIndex].startPoint)); ISampleProvider result = PSP.Skip(samplerModel.song.banks[bankIndex].pads[padIndex].startPoint); //int duration = (int)(samplerModel.song.banks[bankIndex].pads[padIndex].endPoint - samplerModel.song.banks[bankIndex].pads[padIndex].startPoint); TimeSpan duration = (samplerModel.song.banks[bankIndex].pads[padIndex].endPoint - samplerModel.song.banks[bankIndex].pads[padIndex].startPoint); //result = result.Take(new TimeSpan(0,0,duration)); result = result.Take(duration); return(result.ToWaveProvider16().ToSampleProvider()); }
/// <summary> /// Uses the Windows TTS library to get the bytes of a PCM Wave file from a text messages. /// </summary> /// <param name="message"></param> /// <param name="voiceName"></param> /// <returns>The way files bytes, or an empty array if something went wrong.</returns> public byte[] GenerateRadioMessageWavBytes(string message, string voiceName = null) { if (string.IsNullOrEmpty(message)) { message = ""; // Make sure message is not null } // No voice name provided, use the default voice instead if (voiceName == null) { if (DefaultVoice == null) // Default voice not set/doesn't exist { return(new byte[0]); } voiceName = DefaultVoice; } try { Reader.SelectVoice(voiceName); } catch (Exception) { return(new byte[0]); } // Text-to-speech MemoryStream ttsStream = new MemoryStream(); // create a new memory stream Reader.SetOutputToWaveStream(ttsStream); // set the stream as output for the TTS reader Reader.Volume = 35; Reader.Speak(message); // read the text into the stream ttsStream.Seek(0, SeekOrigin.Begin); // rewind the stream to position 0 WaveFileReader waveTTS = new WaveFileReader(ttsStream); // read the stream into a WaveFileReader object // Mix voice with radio static WaveFileReader waveStatic = new WaveFileReader($"{HQTools.PATH_MEDIA}RadioMessageGenerator/Loop.wav"); // load the static sound loop ISampleProvider providerSpeech = new TTSAMRadioFilter(waveTTS.ToSampleProvider(), FXIntensity * 250); // get the sample provider for the TTS, apply a radio filter ISampleProvider providerStatic = waveStatic.ToSampleProvider(); // get the sample provider for the static TimeSpan ttsDuration = waveTTS.TotalTime; // get the tts wave duration if (ttsDuration < TimeSpan.FromSeconds(MIN_SPEECH_DURATION)) { ttsDuration = TimeSpan.FromSeconds(MIN_SPEECH_DURATION); // check min value } if (ttsDuration > TimeSpan.FromSeconds(MAX_SPEECH_DURATION)) { ttsDuration = TimeSpan.FromSeconds(MAX_SPEECH_DURATION); // check max value } ISampleProvider[] sources = new[] { providerSpeech.Take(ttsDuration), providerStatic.Take(ttsDuration) }; // use both providers as source with a duration of ttsDuration MixingSampleProvider mixingSampleProvider = new MixingSampleProvider(sources); // mix both channels IWaveProvider radioMix = mixingSampleProvider.ToWaveProvider16(); // convert the mix output to a PCM 16bit sample provider // Concatenate radio in/out sounds WaveFileReader waveRadioIn = new WaveFileReader($"{HQTools.PATH_MEDIA}RadioMessageGenerator/In.wav"); // load the radio in FX WaveFileReader waveRadioOut = new WaveFileReader($"{HQTools.PATH_MEDIA}RadioMessageGenerator/Out.wav"); // load the radio out FX IWaveProvider[] radioFXParts = new IWaveProvider[] { waveRadioIn, radioMix, waveRadioOut }; // create an array with all 3 parts byte[] buffer = new byte[1024]; // create a buffer to store wav data to concatenate MemoryStream finalWavStr = new MemoryStream(); // create a stream for the final concatenated wav WaveFileWriter waveFileWriter = null; // create a writer to fill the stream foreach (IWaveProvider wav in radioFXParts) // iterate all three parts { if (waveFileWriter == null) // no writer, first part of the array { waveFileWriter = new WaveFileWriter(finalWavStr, wav.WaveFormat); // create a writer of the proper format } else if (!wav.WaveFormat.Equals(waveFileWriter.WaveFormat)) // else, check the other parts are of the same format { continue; // file is not of the proper format } int read; // bytes read while ((read = wav.Read(buffer, 0, buffer.Length)) > 0) // read data from the wave { waveFileWriter.Write(buffer, 0, read); } // fill the buffer with it } // Copy the stream to a byte array waveFileWriter.Flush(); finalWavStr.Seek(0, SeekOrigin.Begin); byte[] waveBytes = new byte[finalWavStr.Length]; finalWavStr.Read(waveBytes, 0, waveBytes.Length); // Close/dispose of everything ttsStream.Close(); ttsStream.Dispose(); waveTTS.Close(); waveTTS.Dispose(); waveStatic.Close(); waveStatic.Dispose(); waveRadioIn.Close(); waveRadioIn.Dispose(); waveRadioOut.Close(); waveRadioOut.Dispose(); waveFileWriter.Close(); waveFileWriter.Dispose(); finalWavStr.Close(); finalWavStr.Dispose(); // Return the bytes return(waveBytes); }
private byte[] DoRadioMix(ISampleProvider voiceProvider, TimeSpan duration) { // Media files are stored in the Release build directory, so if we're running a Debug build, we have to look for them here. string debugPathToRelease = ""; #if DEBUG debugPathToRelease = "..\\Release\\"; #endif // Mix voice with radio static WaveFileReader waveStatic = new WaveFileReader(debugPathToRelease + "Media/Loop.wav"); // load the static sound loop ISampleProvider providerStatic = waveStatic.ToSampleProvider(); // get the sample provider for the static if (duration < TimeSpan.FromSeconds(MIN_SPEECH_DURATION)) { duration = TimeSpan.FromSeconds(MIN_SPEECH_DURATION); // check min value } if (duration > TimeSpan.FromSeconds(MAX_SPEECH_DURATION)) { duration = TimeSpan.FromSeconds(MAX_SPEECH_DURATION); // check max value } ISampleProvider[] sources = new[] { voiceProvider.Take(duration), providerStatic.Take(duration) }; // use both providers as source with a duration of ttsDuration MixingSampleProvider mixingSampleProvider = new MixingSampleProvider(sources); // mix both channels IWaveProvider radioMix = mixingSampleProvider.ToWaveProvider16(); // convert the mix output to a PCM 16bit sample provider // Concatenate radio in/out sounds WaveFileReader waveRadioIn = new WaveFileReader(debugPathToRelease + "Media/In.wav"); // load the radio in FX WaveFileReader waveRadioOut = new WaveFileReader(debugPathToRelease + "Media/Out.wav"); // load the radio out FX IWaveProvider[] radioFXParts = new IWaveProvider[] { waveRadioIn, radioMix, waveRadioOut }; // create an array with all 3 parts byte[] buffer = new byte[1024]; // create a buffer to store wav data to concatenate MemoryStream finalWavStr = new MemoryStream(); // create a stream for the final concatenated wav WaveFileWriter waveFileWriter = null; // create a writer to fill the stream foreach (IWaveProvider wav in radioFXParts) // iterate all three parts { if (waveFileWriter == null) // no writer, first part of the array { waveFileWriter = new WaveFileWriter(finalWavStr, wav.WaveFormat); // create a writer of the proper format } else if (!wav.WaveFormat.Equals(waveFileWriter.WaveFormat)) // else, check the other parts are of the same format { continue; // file is not of the proper format } int read; // bytes read while ((read = wav.Read(buffer, 0, buffer.Length)) > 0) // read data from the wave { waveFileWriter.Write(buffer, 0, read); } // fill the buffer with it } // Copy the stream to a byte array waveFileWriter.Flush(); finalWavStr.Seek(0, SeekOrigin.Begin); byte[] waveBytes = new byte[finalWavStr.Length]; finalWavStr.Read(waveBytes, 0, waveBytes.Length); // Close/dispose of everything waveStatic.Close(); waveStatic.Dispose(); waveRadioIn.Close(); waveRadioIn.Dispose(); waveRadioOut.Close(); waveRadioOut.Dispose(); waveFileWriter.Close(); waveFileWriter.Dispose(); finalWavStr.Close(); finalWavStr.Dispose(); // Return the bytes return(waveBytes); }