//Converts hsv to rgb private RGBcolor HSVToRGB(HSVcolor color) { RGBcolor output; output.r = 0; output.g = 0; output.b = 0; if (color.s < 1) { color.s = 1; } output = HueToRGB(color.h); output.r = Lerp(output.r, 1, 1 - color.s); output.g = Lerp(output.g, 1, 1 - color.s); output.b = Lerp(output.b, 1, 1 - color.s); output.r *= color.v; output.g *= color.v; output.b *= color.v; return(output); }
//Callback for when data is available from the sound card private void WaveInDataAvailable(object sender, WaveInEventArgs e) { //Calculate the length of the fft buffer fftBufferLength = e.Buffer.Length / (waveIn.WaveFormat.BitsPerSample * waveIn.WaveFormat.Channels); dataLength = fftBufferLength / 2; double[] data = new double[e.Buffer.Length / 32]; for (int i = 0; i < data.Length; i += 1) { data[i] = BitConverter.ToSingle(e.Buffer, (i) * 4); } data.CopyTo(allData, 0); leftSample = new double[fftBufferLength + 2]; rightSample = new double[fftBufferLength + 2]; fftInputLeft = new double[fftBufferLength + 2]; fftInputRight = new double[fftBufferLength + 2]; int sampleSize = waveIn.WaveFormat.BitsPerSample / 2; //Read the buffer and copy the data to left and right channel arrays for (int i = 0; i < fftBufferLength; i += 2) { leftSample[i] = BitConverter.ToSingle(e.Buffer, i * 4); rightSample[i] = BitConverter.ToSingle(e.Buffer, (i + 1) * 4); } //Copy the data to a seperate array to prevent the data to be overwritten and preform Fourier transform leftSample.CopyTo(fftInputLeft, 0); rightSample.CopyTo(fftInputRight, 0); Fourier.ForwardReal(fftInputLeft, fftBufferLength); Fourier.ForwardReal(fftInputRight, fftBufferLength); for (int i = 0; i < fftInputLeft.Length; i++) { fftInputLeft[i] = Math.Abs(fftInputLeft[i]); fftInputRight[i] = Math.Abs(fftInputRight[i]); } fftOutputLeft = new double[fftBufferLength / 2]; fftOutputRight = new double[fftBufferLength / 2]; Array.Copy(fftInputLeft, 0, fftOutputLeft, 0, 300); Array.Copy(fftInputRight, 0, fftOutputRight, 0, 300); //Check which LED visualisation mode is selected and preform the selected calculations if (LED_Mode == "Average") { //Bands in Hz int[] ranges = { 0, 300, 1200, (int)(dataLength * dataToHzMultiplier) }; double[] outputDataLeft = new double[ranges.Length - 1]; double[] outputDataRight = new double[ranges.Length - 1]; //Calculate the averages of the frequency bands for (int i = 0; i < ranges.Length - 1; i++) { for (int n = (int)(ranges[i] / dataToHzMultiplier); n < (int)(ranges[i + 1] / dataToHzMultiplier); n++) { outputDataLeft[i] += fftOutputLeft[n]; outputDataRight[i] += fftOutputRight[n]; } outputDataLeft[i] /= (ranges[i + 1] / dataToHzMultiplier) - (ranges[i] / dataToHzMultiplier); outputDataRight[i] /= (ranges[i + 1] / dataToHzMultiplier) - (ranges[i] / dataToHzMultiplier); } //Call the function that sends the data to a microcontroller SendData(new double[] { outputDataLeft[2], outputDataLeft[1], outputDataLeft[0], outputDataRight[2], outputDataRight[1], outputDataRight[0] }); } else if (LED_Mode == "Peak") { //Bands in Hz int[] ranges = { 0, 300, 1200, (int)(dataLength * dataToHzMultiplier) }; double[] outputDataLeft = new double[ranges.Length - 1]; double[] outputDataRight = new double[ranges.Length - 1]; //Get the peak value of every frequency band for (int i = 0; i < ranges.Length - 1; i++) { outputDataLeft[i] = 0; outputDataRight[i] = 0; for (int n = (int)(ranges[i] / dataToHzMultiplier); n < (int)(ranges[i + 1] / dataToHzMultiplier); n++) { if (outputDataLeft[i] < fftOutputLeft[n]) { outputDataLeft[i] = fftOutputLeft[n]; } if (outputDataRight[i] < fftOutputRight[n]) { outputDataRight[i] = fftOutputRight[n]; } } } //Ensure the values are between 0 and 1 for (int i = 0; i < outputDataLeft.Length; i++) { outputDataLeft[i] /= outputDataLeft[i] + 1; outputDataRight[i] /= outputDataRight[i] + 1; } //Call the function that sends the data to a microcontroller SendData(new double[] { outputDataLeft[2], outputDataLeft[1], outputDataLeft[0], outputDataRight[2], outputDataRight[1], outputDataRight[0] }); } else if (LED_Mode == "Average hue") { //Convert the fft output to RGB based on the hsv color space RGBcolor outputLeft = new RGBcolor(); RGBcolor outputRight = new RGBcolor(); for (int i = 0; i < dataLength; i++) { outputLeft.r += colors[i].r * fftOutputLeft[i]; outputLeft.g += colors[i].g * fftOutputLeft[i]; outputLeft.b += colors[i].b * fftOutputLeft[i]; outputRight.r += colors[i].r * fftOutputRight[i]; outputRight.g += colors[i].g * fftOutputRight[i]; outputRight.b += colors[i].b * fftOutputRight[i]; } outputLeft.r /= dataLength; outputLeft.g /= dataLength; outputLeft.b /= dataLength; outputRight.r /= dataLength; outputRight.g /= dataLength; outputRight.b /= dataLength; //Proccess the colors a bit float x = 400; outputLeft.r *= x; outputLeft.g *= x; outputLeft.b *= x; outputRight.r *= x; outputRight.g *= x; outputRight.b *= x; outputLeft.r = Math.Pow(outputLeft.r, magnitude); outputLeft.g = Math.Pow(outputLeft.g, magnitude); outputLeft.b = Math.Pow(outputLeft.b, magnitude); outputRight.r = Math.Pow(outputRight.r, magnitude); outputRight.g = Math.Pow(outputRight.g, magnitude); outputRight.b = Math.Pow(outputRight.b, magnitude); outputLeft.r /= x; outputLeft.g /= x; outputLeft.b /= x; outputRight.r /= x; outputRight.g /= x; outputRight.b /= x; //I'm trying to figure out a way to have the brightness adapt to the volume so there would be more detail. Now That I think about it it does sound like HDR haha... /*double maxLeft = Math.Max(outputLeft.r,Math.Max(outputLeft.g, outputLeft.b)); * outputLeft.r /= maxLeft; * outputLeft.g /= maxLeft; * outputLeft.b /= maxLeft; * double maxRight = Math.Max(outputRight.r, Math.Max(outputRight.g, outputRight.b)); * outputRight.r /= maxRight; * outputRight.g /= maxRight; * outputRight.b /= maxRight;*/ //Ensure the RGB chanels are between 0 and 1 outputLeft.r /= outputLeft.r + 1; outputLeft.g /= outputLeft.g + 1; outputLeft.b /= outputLeft.b + 1; outputRight.r /= outputRight.r + 1; outputRight.g /= outputRight.g + 1; outputRight.b /= outputRight.b + 1; //Call the function that sends the data to a microcontroller SendData(new double[] { outputLeft.r, outputLeft.g, outputLeft.b, outputRight.r, outputRight.g, outputRight.b }); } else if (LED_Mode == "Average frequency hue") { //Calculate average frequency and amplitude RGBcolor outputLeft = new RGBcolor(); RGBcolor outputRight = new RGBcolor(); double totalAmplitudeLeft = 0; double totalAmplitudeRight = 0; double averagefrequencyLeft = 0; double averagefrequencyRight = 0; double averageAmplitudeLeft = 0; double averageAmplitudeRight = 0; for (int i = 0; i < dataLength; i++) { totalAmplitudeLeft += fftOutputLeft[i]; totalAmplitudeRight += fftOutputRight[i]; averagefrequencyLeft += fftOutputLeft[i] * i; averagefrequencyRight += fftOutputRight[i] * i; } averagefrequencyLeft /= totalAmplitudeLeft; averagefrequencyRight /= totalAmplitudeRight; averageAmplitudeLeft = totalAmplitudeLeft / dataLength; averageAmplitudeRight = totalAmplitudeRight / dataLength; if (!Double.IsNaN(averagefrequencyLeft)) { outputLeft = colors[(int)averagefrequencyLeft]; outputLeft.r *= averageAmplitudeLeft; outputLeft.g *= averageAmplitudeLeft; outputLeft.b *= averageAmplitudeLeft; } else { outputLeft = new RGBcolor(); } if (!Double.IsNaN(averagefrequencyRight)) { outputRight = colors[(int)averagefrequencyRight]; outputRight.r *= averageAmplitudeRight; outputRight.g *= averageAmplitudeRight; outputRight.b *= averageAmplitudeRight; } else { outputRight = new RGBcolor(); } int x = 20; outputLeft.r *= x; outputLeft.g *= x; outputLeft.b *= x; outputRight.r *= x; outputRight.g *= x; outputRight.b *= x; //Call the function that sends the data to a microcontroller SendData(new double[] { outputLeft.r, outputLeft.g, outputLeft.b, outputRight.r, outputRight.g, outputRight.b }); } else if (LED_Mode == "Saturation enhancement - 1") { RGBcolor outputLeft = new RGBcolor(); RGBcolor outputRight = new RGBcolor(); for (int i = 0; i < dataLength; i++) { outputLeft.r += colors[i].r * fftOutputLeft[i]; outputLeft.g += colors[i].g * fftOutputLeft[i]; outputLeft.b += colors[i].b * fftOutputLeft[i]; outputRight.r += colors[i].r * fftOutputRight[i]; outputRight.g += colors[i].g * fftOutputRight[i]; outputRight.b += colors[i].b * fftOutputRight[i]; } outputLeft.r /= dataLength; outputLeft.g /= dataLength; outputLeft.b /= dataLength; outputRight.r /= dataLength; outputRight.g /= dataLength; outputRight.b /= dataLength; float x = 10; outputLeft.r *= x; outputLeft.g *= x; outputLeft.b *= x; outputRight.r *= x; outputRight.g *= x; outputRight.b *= x; HSVcolor hsvLeft = RGBtoHSV(outputLeft); hsvLeft.s *= saturationMultiplier; outputLeft = HSVToRGB(hsvLeft); HSVcolor hsvRight = RGBtoHSV(outputRight); hsvRight.s *= saturationMultiplier; outputRight = HSVToRGB(hsvRight); //Call the function that sends the data to a microcontroller SendData(new double[] { outputLeft.r, outputLeft.g, outputLeft.b, outputRight.r, outputRight.g, outputRight.b }); } else if (LED_Mode == "Saturation enhancement - 2") { //Calculate average frequency and amplitude RGBcolor outputLeft = new RGBcolor(); RGBcolor outputRight = new RGBcolor(); double totalAmplitudeLeft = 0; double totalAmplitudeRight = 0; double averagefrequencyLeft = 0; double averagefrequencyRight = 0; double averageAmplitudeLeft = 0; double averageAmplitudeRight = 0; for (int i = 0; i < dataLength; i++) { totalAmplitudeLeft += fftOutputLeft[i]; totalAmplitudeRight += fftOutputRight[i]; averagefrequencyLeft += fftOutputLeft[i] * i; averagefrequencyRight += fftOutputRight[i] * i; } averagefrequencyLeft /= totalAmplitudeLeft; averagefrequencyRight /= totalAmplitudeRight; averageAmplitudeLeft = totalAmplitudeLeft / dataLength; averageAmplitudeRight = totalAmplitudeRight / dataLength; if (!Double.IsNaN(averagefrequencyLeft)) { outputLeft = colors[(int)averagefrequencyLeft]; outputLeft.r *= averageAmplitudeLeft; outputLeft.g *= averageAmplitudeLeft; outputLeft.b *= averageAmplitudeLeft; } else { outputLeft = new RGBcolor(); } if (!Double.IsNaN(averagefrequencyRight)) { outputRight = colors[(int)averagefrequencyRight]; outputRight.r *= averageAmplitudeRight; outputRight.g *= averageAmplitudeRight; outputRight.b *= averageAmplitudeRight; } else { outputRight = new RGBcolor(); } int x = 10; outputLeft.r *= x; outputLeft.g *= x; outputLeft.b *= x; outputRight.r *= x; outputRight.g *= x; outputRight.b *= x; HSVcolor hsvLeft = RGBtoHSV(outputLeft); hsvLeft.s *= saturationMultiplier; outputLeft = HSVToRGB(hsvLeft); HSVcolor hsvRight = RGBtoHSV(outputRight); hsvRight.s *= saturationMultiplier; outputRight = HSVToRGB(hsvRight); //Call the function that sends the data to a microcontroller SendData(new double[] { outputLeft.r, outputLeft.g, outputLeft.b, outputRight.r, outputRight.g, outputRight.b }); } else if (LED_Mode == "DEBUG") { RGBcolor outputLeft = new RGBcolor(); RGBcolor outputRight = new RGBcolor(); HSVcolor color = new HSVcolor(); color.h = counter / 100.0f; color.s = 0.5f; color.v = 1; outputLeft = HSVToRGB(color); outputRight = HSVToRGB(color); HSVcolor hsvLeft = RGBtoHSV(outputLeft); hsvLeft.s = 1; outputLeft = HSVToRGB(hsvLeft); //HSVcolor hsvRight = RGBtoHSV(outputRight); //hsvRight.s = 1; //outputRight = HSVToRGB(hsvRight); //Call the function that sends the data to a microcontroller SendData(new double[] { outputLeft.r, outputLeft.g, outputLeft.b, outputRight.r, outputRight.g, outputRight.b }); counter %= 100; counter++; } }