Ejemplo n.º 1
0
        //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);
        }
Ejemplo n.º 2
0
        //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++;
            }
        }