public float frequencyModulationRangeOut; //The Frequency Modulation Oscillator’s current value (range 0 to 1) void Awake() { amplitudeModulationOscillator = new SineHP(); frequencyModulationOscillator = new SineHP(); // Grab the sample rate from the system _FS = AudioSettings.outputSampleRate; // Calculate how long each sample lasts _sampleDuration = 1.0 / _FS; }
void OnAudioFilterRead(float[] data, int channels) { /* * This is "the current time of the audio system", as given * by Unity. It is updated every time the OnAudioFilterRead() function * is called. It's usually every 1024 samples. * * A note on the sample rate: * We don't actually see real numbers for the sample rate, we instead * read it from the system in the Start() function. */ //currentDspTime = AudioSettings.dspTime; // goes through data chunk for (int i = 0; i < data.Length; i += channels) { /* * Sample duration is just 1/fs. Because dspTime isn't updated every * sample, we "update" it ourselves so our envelope sounds smooth. */ // currentDspTime += _sampleDuration; // envelope = ComputeAmplitude(currentDspTime) * volume; // lets you modulate the frequency double currentFreq = frequency; // Applies Frequency Modulation if (useFrequencyModulation) { phaseIncrementFM = (frequencyModulationOscillatorFrequency) * 2.0 * Mathf.PI / _FS; phaseFM += phaseIncrementFM; if (phaseFM > (Mathf.PI * 2)) { phaseFM = phaseFM % (Mathf.PI * 2); } double freqOffset = (frequencyModulationOscillatorIntensity * frequency * 0.75) / 100.0; currentFreq += mapValueD(SineHP.Sin((float)phaseFM), -1.0, 1.0, -freqOffset, freqOffset); frequencyModulationRangeOut = (float)SineHP.Sin((float)phaseFM) * 0.5f + 0.5f; } else { frequencyModulationRangeOut = 0.0f; } /* * The phase variable below increments by the calculated amount for * every audio sample. We can then use this value to calculate what * each waveform's value should be. * * 2pi * f * phase = ------- * fs * * When phase is greater than 2pi, we just reset * it so we don't have an ever-increasing variable that will cause * an overflow error. */ phaseIncrement = (currentFreq * octave) * 2.0 * Mathf.PI / _FS; phase += phaseIncrement; if (phase > (Mathf.PI * 2)) { phase = phase % (Mathf.PI * 2); } nextOutput = 0; sinOutput = 0; sawOutput = 0; sqrOutput = 0; noiseOutput = 0; // Adds sinusoidal wave to the next output sample sinOutput = (float)(sinWeight * Mathf.Sin((float)phase)); sinOutput = (float)(sinWeight * SineHP.Sin((float)phase)); // nextOutput += (float)(sinWeight * Mathf.Sin((float)phase)); // Adds sawtooth wave to the next output sample sawOutput = (float)sawWeight - (float)(sawWeight / Mathf.PI * phase); // nextOutput += (float)(sawWeight * ((phase) / (2 * Mathf.PI))); // Adds square wave to the next output sample if (phase > Mathf.PI) { sqrOutput = (float)(sqrWeight); //nextOutput += (float) (sqrWeight ) ; } else { sqrOutput = (-(float)(sqrWeight)); //nextOutput += (-(float) ( sqrWeight) ) ; } // Adds noise wave to the next output sample noiseOutput = PinkNoise.Noise(); /* Mixa tutti gli output * http://www.vttoth.com/CMS/index.php/technical-notes/68 * Let's say we have two signals, A and B. If A is quiet, we want to hear B on the output in unaltered form. If B * is quiet, we want to hear A on the output (i.e., A and B are treated symmetrically.) If both A and B have a non-zero amplitude, * the mixed signal must have an amplitude between the greater of A and B, and the maximum permissible amplitude. * If we take A and B to have values between 0 and 1, there is actually a simple equation that satisfies all of the * above conditions: Z= A + B − AB. * Simple, isn't it! Moreover, it can be easily adapted for more than two signals. * Consider what happens if we mix another signal, C, to Z: T= Z + C − Z C = A + B + C − AB − AC − BC + ABC. * * */ nextOutput = sinOutput + sawOutput + sqrOutput - (sinOutput * sawOutput) - (sinOutput * sqrOutput) - (sawOutput * sqrOutput) + (sinOutput * sawOutput * sqrOutput); nextOutput += noiseOutput * (float)noiseWeight; //da cambiare /* * Here we apply a single-pole low-pass filter. Even if the filter * is completely open (lowPass = 1) we still compute this step so we * don't have to have any conditional logic. */ nextOutput = (float)((nextOutput * lowPass) + (previousOutput * (1 - lowPass))); nextOutput = nextOutput * 0.5f * volume; // Applies Amplitude Modulation if (useAmplitudeModulation) { phaseIncrementAM = (amplitudeModulationOscillatorFrequency) * 2.0 * Mathf.PI / _FS; phaseAM += phaseIncrementAM; if (phaseAM > (Mathf.PI * 2)) { phaseAM = phaseAM % (Mathf.PI * 2); } nextOutput *= (float)mapValueD(SineHP.Sin((float)phaseAM), -1.0, 1.0, 0.0, 1.0); amplitudeModulationRangeOut = (float)SineHP.Sin((float)phaseAM) * 0.5f + 0.5f; } else { amplitudeModulationRangeOut = 0.0f; } // Write the output to the audio filter data[i] += nextOutput; // This is for the next low-pass calculation previousOutput = nextOutput; // Copy the sound from one channel into the next channel for stereo if (channels == 2) { data[i + 1] = data[i]; } } }