예제 #1
0
        // Wave
        public static GameObject CreateWave(WaveType waveType, Sprite sprite, Font font)
        {
            // UI hierarchy
            Vector2 size = Vector2.one;

            size.x *= wWidth;
            size.y *= wHeight;
            var root    = CreateUIElementRoot(waveType.ToString() + " Wave", size);
            var graphic = CreateUIObject("Graphic", root);

            // Stretch settings
            FitToParent(graphic, Vector2.zero);

            // Graphic
            var image = graphic.AddComponent <Image>();

            image.material = new Material(Shader.Find("UI/Unlit/Wave"));
            image.sprite   = sprite;
            image.color    = Color.white;

            // Wave
            var wave = root.AddComponent <MidiWave>();

            wave.graphic  = image;
            wave.waveType = waveType;

            return(root);
        }
예제 #2
0
 // Update is called once per frame
 void Update()
 {
     if (IsListening)
     {
         midiNote = VoiceInput.Instance.midi;
         if (GetWaveType() != WaveType.None)
         {
             if (currentWave != GetWaveType())
             {
                 if (debug_log)
                 {
                     Debug.Log("CAMBIO DE WAVE!!!!!! ");
                     Debug.Log("WAVE ANTERIOR = " + currentWave.ToString());
                 }
                 currentWave = GetWaveType();
                 WaveChanged();
                 if (debug_log)
                 {
                     Debug.Log("WAVE NUEVA = " + currentWave.ToString());
                 }
             }
         }
         else
         {
             if (OnWaveStoppedCallback != null)
             {
                 OnWaveStoppedCallback();
             }
         }
     }
 }
예제 #3
0
        /// <summary>
        /// Generates a new wave-form as an audio stream (list of PCMSample objects).
        /// </summary>
        /// <param name="audioFormat">The format used to sample the waveform.</param>
        /// <param name="wavePattern">The type of wave to generate.</param>
        /// <param name="amplitudePerc">A percentage of the audio format's MaxAmplitude (0 to 100%).</param>
        /// <param name="durationSec">How long (in seconds) the sound will be generated for.</param>
        /// <param name="frequencyHz">The frequency at which the sound should be played.</param>
        /// <returns>A new list of PCMSample objects that represent the sound.</returns>
        /// <see cref="PCMSample"/>
        /// <see cref="AudioFormat"/>
        public static List <PCMSample> CreateNewWave(AudioFormat audioFormat, WaveType wavePattern,
                                                     double amplitudePerc, double durationSec, double frequencyHz)
        {
            // Cap the amplitude at 100%.
            amplitudePerc = Math.Min(100.0, Math.Abs(amplitudePerc));
            // Samples required to complete one wave period at the given frequency.
            double samplesPerWaveCycle = (double)(audioFormat.SampleRate / frequencyHz);
            // Total amount of samples for the wave duration in its entirety.
            double totalSamples = durationSec * (double)audioFormat.SampleRate;
            // Additional amount of samples to append onto the stream until the final wave/period completes.
            //   This is aimed at keeping sudden adjacent tones from causing hard key clicks when transitioning.
            double extraSamples = samplesPerWaveCycle - (totalSamples % samplesPerWaveCycle);
            double waveAttenuationSamplesCount = (samplesPerWaveCycle * WaveGenerator.ATTENUATION_CYCLES);
            // Short-handing some variables from the audio format as needed...
            int sampleRate = audioFormat.SampleRate;
            // Get the peak amplitude permitted based on the amplitudePerc parameter.
            double peakAmplitude = audioFormat.GetPeakAmplitude(amplitudePerc);
            // Initialize the new stream object.
            var newWaveStream = new List <PCMSample>();
            // Create the wave stream based on the requested wave type.
            var prng = new Random(); //PRNG as needed for noise and dither
            Func <int, double> sampleCalculation = wavePattern switch {
                // f(x) = amplitude * SIN(2pi * x * frequency / sampleRate)
                WaveType.SINE => (currSample =>
                                  peakAmplitude * Math.Sin((2 * Math.PI * currSample * frequencyHz) / sampleRate)
                                  ),
                // f(x) = abs(amplitude), when 0 <= x < period/2 ;; f(x) = neg(amplitude), when period/2 <= x < period
                // My implementation factors amplitude out of: f(x) = (({2*[amp/samplesPerPeriod]*x + amp} % [amp*2]) - (amp)
                WaveType.SAWTOOTH => (currSample =>
                                      ((peakAmplitude * ((2 * currSample / samplesPerWaveCycle) + 1)) % (peakAmplitude * 2)) - peakAmplitude
                                      ),
                // f(x) = x, when 0 <= x < pi ;; f(x) = x-2pi, when pi <= x =< 2pi
                WaveType.SQUARE => (currSample =>
                                    (currSample % samplesPerWaveCycle) < (samplesPerWaveCycle / 2) ? peakAmplitude : 0 - peakAmplitude
                                    ),
                // f(x) = [2*amp / pi] * [ arcsin( sin( {2pi * freq}/sampleRate ) * x ) ]
                // Definitely had to look this one up...
                WaveType.TRIANGLE => (currSample =>
                                      ((2 * peakAmplitude) / Math.PI)
                                      * Math.Asin(Math.Sin(((2 * Math.PI * frequencyHz) / sampleRate) * currSample))
                                      ),
                // f(x) = random(x); f(x) constrained to [-MinPeak, MaxPeak]
                WaveType.WHITE_NOISE => (currSample =>
                                         (prng.NextDouble() * (audioFormat.MaxSampleValue - audioFormat.MinSampleValue)) + audioFormat.MinSampleValue
                                         ),
                // If no other enum matched, throw exception
                _ => throw new Exception("CreateNewWave: Invalid wave pattern selection: " + wavePattern.ToString())
            };

            for (int currentSample = 0; currentSample < totalSamples + extraSamples; currentSample++)
            {
                double sampleValue = sampleCalculation(currentSample);
                if (currentSample < waveAttenuationSamplesCount)
                {
                    // For the first few wave cycles, attenuate the max amplitude by a
                    //   ratio to gradually introduce the signal.
                    //   Again, this is aimed to help prevent clicking in the resulting sample
                    sampleValue *= (double)((double)currentSample / waveAttenuationSamplesCount);
                }
                else if (currentSample > ((totalSamples + extraSamples) - waveAttenuationSamplesCount))
                {
                    // Likewise, attenuate the end of the signal for the sample.
                    sampleValue *= (double)((double)((totalSamples + extraSamples) - currentSample) / waveAttenuationSamplesCount);
                }
                newWaveStream.Add(new PCMSample(audioFormat, (int)sampleValue));
            }
            // Finally, return the new stream.
            return(newWaveStream);
        }
    }