예제 #1
0
        public FFTPlayer(IAudioReader reader)
        {
            _Reader        = reader;
            _RawDataReader = FFTDataReaderFactory.CreateForFormat(reader.Provider.Format);

            int bufferLength = reader.BufferLength;

            Buffer   = new float[bufferLength];
            Buffer2  = new float[bufferLength];
            _Buffer3 = new double[bufferLength];

            UIntPtr allocSize = (UIntPtr)(8 * (uint)bufferLength);

            _Input  = FFTW.Malloc(allocSize);
            _Output = FFTW.Malloc(allocSize);
            _Plan   = FFTW.PlanDft1D(bufferLength, _Input, _Output, -1, 0 /* FFTW_MEASURE */);
            for (int i = 0; i < bufferLength; ++i)
            {
                _Input[i].Imaginary = 0; //Clear only imaginary
            }

            _WindowFunction = new float[bufferLength];
            float sigma  = bufferLength / 2 / WindowRange;
            int   offset = bufferLength / 2;

            for (int i = 0; i < bufferLength; ++i)
            {
                float x = (i - offset);
                _WindowFunction[i] = (float)Math.Exp(-x * x / 2 / sigma / sigma);
            }
        }
예제 #2
0
        public void Calculate()
        {
            float time = _Reader.GetRawBuffer(out var buffer, out var offset);

            _RawDataReader.ReadToBuffer(buffer, offset, _WindowFunction, _Input);
            FFTW.Execute(_Plan);

            var changetime = time - _LastTime;

            _LastTime = time;

            for (int i = 0; i < _WindowFunction.Length; ++i)
            {
                Buffer[i] = (float)Math.Sqrt(_Output[i].Length());
                if (i < 2)
                {
                    Buffer2[i] = 0;
                    continue;
                }

                var x      = (i) / (float)_WindowFunction.Length;
                var freq   = x * _Reader.Provider.Format.SampleRate; //TODO NPE
                var period = 1 / freq;

                var th  = Math.Atan2(_Output[i].Imaginary, _Output[i].Real);
                var tth = th / Math.PI / 2 * period;

                var changeth = th - _Buffer3[i];
                _Buffer3[i] = th;

                if (changetime == 0)
                {
                    Buffer2[i] = 0;
                    continue;
                }

                var expect_changeth = changetime / period * Math.PI * 2;
                var diff            = (expect_changeth - changeth) % (Math.PI * 2);
                diff = diff / (Math.PI * 2);
                if (diff > 0.5)
                {
                    diff = 1 - diff;
                }
                diff *= 15;
                if (diff > 1)
                {
                    diff = 1;
                }
                //Buffer2[i] *= (float)(1 - diff);

                Buffer2[i] = (float)diff;
            }
        }
예제 #3
0
        public unsafe static void Main()
        {
            byte[]     convertedData;
            WaveFormat waveFormat;
            {
                int        size;
                WaveFormat f = new WaveFormat(44100, 16, 2);
                using (Mp3FileReader r = new Mp3FileReader(OpenFile()))
                {
                    using (var conv = new WaveFormatConversionStream(f, r))
                    {
                        int len = (int)conv.Length;
                        size          = len / 4;
                        convertedData = new byte[len];
                        conv.Read(convertedData, 0, len);
                    }
                }
                waveFormat = f;
            }
            const int frameLength = 4;
            int       frameCount  = convertedData.Length / frameLength;

            var bufferLength = 8192;
            var windowRange  = 4.0f;

            float[] windowFunction;
            {
                windowFunction = new float[bufferLength];
                float sigma  = bufferLength / 2 / windowRange;
                int   offset = bufferLength / 2;
                for (int i = 0; i < bufferLength; ++i)
                {
                    float x = (i - offset);
                    windowFunction[i] = 1;// (float)Math.Exp(-x * x / 2 / sigma / sigma);
                }
            }

            FFTW.Complex *inputBuffer, outputBuffer;
            IntPtr        fftwPlanForward, fftwPlanBackward;

            {
                UIntPtr allocSize = (UIntPtr)(8 * (uint)bufferLength);
                inputBuffer      = FFTW.Malloc(allocSize);
                outputBuffer     = FFTW.Malloc(allocSize);
                fftwPlanForward  = FFTW.PlanDft1D(bufferLength, inputBuffer, outputBuffer, -1, 0 /* FFTW_MEASURE */);
                fftwPlanBackward = FFTW.PlanDft1D(bufferLength, outputBuffer, inputBuffer, 1, 0 /* FFTW_MEASURE */);
                for (int i = 0; i < bufferLength; ++i)
                {
                    inputBuffer[i].Imaginary = 0; //Clear only imaginary
                }
            }

            byte[] output = new byte[convertedData.Length];

            void ReadMp3Buffer(int frame)
            {
                fixed(byte *ptrByte = convertedData)
                {
                    short *ptr = (short *)(ptrByte + frameLength * frame);

                    for (int i = 0; i < bufferLength; ++i)
                    {
                        var r = ptr[i * 2] / 32768f * windowFunction[i];
                        if (float.IsNaN(r))
                        {
                        }
                        inputBuffer[i].Real      = r;
                        inputBuffer[i].Imaginary = 0;
                    }
                }
            }

            void WriteOutputBuffer(int frame)
            {
                fixed(byte *ptrByte = output)
                {
                    short *ptr = (short *)(ptrByte + frameLength * frame);

                    for (int i = 0; i < bufferLength; ++i)
                    {
                        if (float.IsNaN((inputBuffer[i].Real)))
                        {
                        }
                        float floatData = inputBuffer[i].Real * windowFunction[i];
                        short data      = (short)(floatData * 32768f / 10);
                        ptr[i * 2]     += data;
                        ptr[i * 2 + 1] += data;
                    }
                }
            }

            //Main loop
            {
                const int step                 = 1000;
                const int reportPercentage     = 5;
                int       nextReportFrame      = 0;
                int       nextReportPercentage = 0;

                float[] compare = new float[bufferLength * 2];
                for (int pos = 0; pos + bufferLength <= frameCount; pos += step)
                {
                    if (pos > nextReportFrame)
                    {
                        System.Diagnostics.Debug.Print("{0}%", nextReportPercentage);
                        nextReportPercentage += reportPercentage;
                        nextReportFrame       = (int)(nextReportPercentage / 100f * frameCount);
                    }

                    ReadMp3Buffer(pos);

                    FFTW.Execute(fftwPlanForward);
                    System.Runtime.InteropServices.Marshal.Copy(new IntPtr(inputBuffer), compare, 0, bufferLength * 2);

                    //Perform transform
                    for (int i = 0; i < bufferLength; ++i)
                    {
                        if (i == 0 && inputBuffer[i].Real != 0)
                        {
                        }
                        if (float.IsNaN(outputBuffer[i].Imaginary + outputBuffer[i].Real))
                        {
                        }
                    }

                    FFTW.Execute(fftwPlanBackward);
                    WriteOutputBuffer(pos);
                }
            }

            var outputFileName = @"E:\test.wav";

            if (File.Exists(outputFileName))
            {
                File.Delete(outputFileName);
            }
            using (var outputStream = File.Create(outputFileName))
            {
                using (var outputProvider = new RawSourceWaveStream(output, 0, output.Length, waveFormat))
                {
                    WaveFileWriter.WriteWavFileToStream(outputStream, outputProvider);
                }
            }
        }