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());
        }
Beispiel #3
0
        /// <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);
        }