public void ProcessAudio(float[] AudioData, int SampleRate) { Debug.Assert(AudioData.Length == m_FFTSize); if (SampleRate != m_SampleRate) { SetSampleRate(SampleRate); } m_FFT.Add(AudioData, AudioData.Length); m_FFT.GetFftData(m_FFTResult); // Calculate Band Levels. Band Levels are much more useful // For visualization / system feedback. Raw FFT is mostly useless. ConvertRawSpectrumToBandLevels(); // Fill the buffers full for (int i = 0; i < m_FFTSize; ++i) { float fLChannel = AudioData[i]; m_AudioSamples[i] = fLChannel; // m_RChannelTempBuffer[i] = fRChannel; m_LChannelWeird[i] = Mathf.Lerp(fLChannel, m_LChannelWeird[i], m_WeirdWaveformLerp); m_PeakFFTResult[i] = Mathf.Max(m_PeakFFTResult[i] * m_FFTPeakDecay, m_FFTResult[i]); } m_AudioSamples.CopyTo(m_LChannelLowPass, 0); m_AudioSamples.CopyTo(m_LChannelHighPass, 0); m_LowPassFilter.Frequency = m_LowPassFreq; m_HighPassFilter.Frequency = m_HighPassFreq; m_LowPassFilter.Process(m_LChannelLowPass); m_HighPassFilter.Process(m_LChannelHighPass); // Pipe waveform values in to texture. for (int i = 0; i < m_FFTSize; ++i) { m_WaveFormRow[i].r = m_AudioSamples[i] * 0.5f + 0.5f; m_WaveFormRow[i].g = m_LChannelWeird[i] * 0.5f + 0.5f; m_WaveFormRow[i].b = m_LChannelLowPass[i] * 0.5f + 0.5f; m_WaveFormRow[i].a = m_LChannelHighPass[i] * 0.5f + 0.5f; } // Pipe FFT values in to texture. // Only use the first half of the FFT. Second half is boring. for (int i = 0; i < m_FFTTextureSize; ++i) { // Mirrored index int fMirroredIndex = 128 - Mathf.Abs(i - 128); m_FFTRow[i].r = m_FFTResult[fMirroredIndex] * m_FFTScale; m_FFTRow[i].g = m_FFTResult[fMirroredIndex] * Mathf.Pow((fMirroredIndex / 512.0f), m_FFTPower) * m_FFTPowerScale; m_FFTRow[i].b = m_PeakFFTResult[fMirroredIndex] * Mathf.Pow((fMirroredIndex / 512.0f), m_FFTPower) * m_FFTPowerScale; } for (int i = 0; i < m_FFTTextureSize; ++i) { int band_levels_index = (int)(i * ((float)m_BandLevels.Length / (float)m_FFTTextureSize)); m_FFTRow[i].a = m_BandNormalizedLevels[band_levels_index]; } // Pipe values into the Audio Injector for beat detection, if the component exists. if (m_SystemAudioInjector) { m_SystemAudioInjector.ProcessAudio(m_AudioSamples); } if (m_SystemAudioInjectorAlt) { m_SystemAudioInjectorAlt.ProcessAudio(m_AudioSamples); } if (m_SystemAudioInjectorLowPass) { m_SystemAudioInjectorLowPass.ProcessAudio(m_AudioSamples); } if (m_SystemAudioInjectorHighPass) { m_SystemAudioInjectorHighPass.ProcessAudio(m_AudioSamples); } // // Update Shaders // Shader.SetGlobalTexture("_WaveFormTex", m_WaveFormTexture); Shader.SetGlobalVector("_PeakBandLevels", m_BandPeakLevelsOutput); Shader.SetGlobalTexture("_FFTTex", m_FFTTexture); Shader.SetGlobalVector("_BeatOutput", m_BeatOutput); Shader.SetGlobalVector("_BeatOutputAccum", m_BeatOutputAccum); Shader.SetGlobalVector("_AudioVolume", m_AudioVolume); m_BandPeakLevelsOutput = new Vector4(m_BandPeakLevels[0], m_BandPeakLevels[1], m_BandPeakLevels[2], m_BandPeakLevels[3]); m_WaveFormTexture.SetPixels(0, 0, m_FFTSize, 1, m_WaveFormRow); m_WaveFormTexture.Apply(); m_FFTTexture.SetPixels(0, 0, m_FFTTextureSize, 1, m_FFTRow); m_FFTTexture.Apply(); m_BeatOutput = new Vector4(m_Reaktor.output, m_ReaktorAlt.output, m_ReaktorLowPass.output, m_ReaktorHighPass.output); //Scale the accumulated output to a value more usable in shaders (saves us a multiply) m_BeatOutputAccum = new Vector4(m_Reaktor.outputAccumulated, m_ReaktorAlt.outputAccumulated, m_ReaktorLowPass.outputAccumulated, m_ReaktorHighPass.outputAccumulated) * .02f; // XXX TO DO: Better and more useful conversion from DB to a useful 0:1 range. float val1 = (60.0f + m_Reaktor.outputDb) / 60.0f; val1 = Mathf.Clamp(val1, 0.0f, 1.0f); float val2 = (60.0f + m_ReaktorAlt.outputDb) / 60.0f; val2 = Mathf.Clamp(val2, 0.0f, 1.0f); float val3 = (60.0f + m_ReaktorLowPass.outputDb) / 60.0f; val3 = Mathf.Clamp(val3, 0.0f, 1.0f); float val4 = (60.0f + m_ReaktorHighPass.outputDb) / 60.0f; val4 = Mathf.Clamp(val3, 0.0f, 1.0f); m_AudioVolume = new Vector4(val1, val2, val3, val4); }