フラクタル - peace098beat/windows_applicaciton GitHub Wiki

using NAudio.Dsp;
using NAudio.Wave;
using System;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace Tutorial14
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog openfiledlg = new OpenFileDialog();
            if (openfiledlg.ShowDialog() != DialogResult.OK) return;
            string fileName = openfiledlg.FileName;
            //TODO: 関数化


            AudioFileReader reader = new AudioFileReader(fileName);
            int FS = reader.WaveFormat.SampleRate;

            float[] samples = new float[reader.Length / reader.BlockAlign * reader.WaveFormat.Channels];
            reader.Read(samples, 0, samples.Length); // Wavのデータを配列(samples)にコピー

            int fftLength = 512;
            int m = (int)Math.Log(fftLength, 2.0);
            int fftPos = 0;


            Console.WriteLine("FFT START" + Environment.NewLine);


            Complex[] buffer = new Complex[fftLength];
            float[,] result = new float[samples.Length / fftLength, fftLength / 2];


            for (int i = 0; i < samples.Length; i++)
            {

                // FastFourierTransform.FFTに突っ込むためのComplex配列
                buffer[fftPos].X = (float)(samples[i] * FastFourierTransform.HammingWindow(fftPos, fftLength));
                buffer[fftPos].Y = 0.0f;

                // フレームシフト
                fftPos++;

                if (fftLength <= fftPos)
                {
                    fftPos = 0;

                    FastFourierTransform.FFT(true, m, buffer);

                    for (int k = 0; k < fftLength / 2; k++)
                    {
                        double diagonal = Math.Sqrt(buffer[k].X * buffer[k].X + buffer[k].Y * buffer[k].Y);
                        double intensityDB = 10.0 * Math.Log10(diagonal);

                        const double minDB = -120.0;
                        double percent = (intensityDB < minDB) ? 0.0 : 1 - (intensityDB / minDB);

                        result[i / fftLength, k] = (float)percent;
                    }
                }
            }

            Console.WriteLine("FFT End" + Environment.NewLine);

            this.contourMap1.plot(result);

            /**********************************************************************************************/
            // 波形の表示
            /**********************************************************************************************/
            Series waveChart = new Series();
            //グラフのタイプを指定(今回は線)
            waveChart.ChartType = SeriesChartType.Line;
            //グラフのデータを追加(試しにsin関数)
            for (int i = 0; i < samples.Length / chart1.Width; i++)
                waveChart.Points.AddXY(i * chart1.Width * (1 / (double)FS), samples[i * chart1.Width]);
            //作ったSeriesをchartコントロールに追加する
            chart1.Series.Add(waveChart);


            /**********************************************************************************************/
            // フラクタルの表示
            /**********************************************************************************************/

            int FractalWindow = 1024;
            int[] taus = new int[] { 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 };
            int Ntaus = taus.Length;
            int tau = taus[0];
            int tauMax = taus[Ntaus - 1];

            float[] fractalNumbers = new float[samples.Length];

            int pos = 0;
            float fractal_n = 0;

            for (int i = 0; i < samples.Length; i++)
            {

                if (i > FractalWindow + tauMax)
                {
                    fractal_n = 0;

                    for (int j = 0; j < FractalWindow; j++)
                    {
                        fractal_n += (float)Math.Pow(samples[i-j] - samples[i - j - tauMax], 2) / FractalWindow;
                    }
                    fractalNumbers[i] = fractal_n;
                    fractal_n = 0;

                }
                else
                {
                    fractalNumbers[i] = 0;
                }
            }

            // 波形の表示
            Series fractalChart = new Series();
            //グラフのタイプを指定(今回は線)
            fractalChart.ChartType = SeriesChartType.Line;
            //グラフのデータを追加(試しにsin関数)
            for (int i = 0; i < samples.Length / chart2.Width; i++)
                fractalChart.Points.AddXY(i * chart2.Width * (1 / (double)FS), fractalNumbers[i * chart2.Width]);
            //作ったSeriesをchartコントロールに追加する
            chart2.Series.Add(fractalChart);


        }
    }
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Tutorial14
{
    public partial class ContourMap : UserControl
    {

        // スペクトログラムのBitmapばっふぁ 
        Bitmap bitmap_buffer = null;


        public ContourMap()
        {
            InitializeComponent();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            this.pictureBox1.Paint += pictureBox1_Paint;
        }

        /// <summary>
        /// プロットデータをセット
        /// </summary>
        public void plot(float[,] listBuffer)
        {

            int height = this.pictureBox1.Height;
            int width = this.pictureBox1.Width;

            int NumFrame = listBuffer.GetLength(0);
            int NumBin = listBuffer.GetLength(1);

            Console.WriteLine($"NumFrame:{NumFrame}, NumBin:{NumBin} ");

            bitmap_buffer = new Bitmap(width, height);

            Color[] cmap = Contour.Create();

            for (int k = 0; k < height; k++)
            {
                for (int j = 0; j < width; j++)
                {
                    ////色を決める
                    int index = (int)(NumBin * (float)k / height);
                    int frame = (int)(NumFrame * (float)j / width);

                    if (index > NumBin - 1) throw new Exception();
                    if (frame > NumFrame - 1) throw new Exception();


                    float value = listBuffer[frame, index];

                    if (value > 1.0) value = 1.0F;
                    else if (value < 0.0) value = 0.0F;


                    int cindex = (int)(255.0F * value);

                    if (cindex > 255) throw new Exception();


                    Color c = cmap[cindex];

                    ////1つのピクセルの色を変える
                    //bitmap_buffer.SetPixel(j, height - k - 1, c);
                    bitmap_buffer.SetPixel(j, (height-1)-k, c);
                }
            }

            //補間方法を指定して画像を縮小して描画する

            this.Refresh();

            Console.WriteLine("plot end");
        }
       

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {

            if (bitmap_buffer == null) return;


            // Graphicsオブジェクトを作成する
            var g = e.Graphics;

            //補間方法として最近傍補間を指定する
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
            ////補間方法として高品質双三次補間を指定する
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

            //画像を縮小して描画する
            g.DrawImage(bitmap_buffer, 0, 0, pictureBox1.Width, pictureBox1.Height);

        }

        protected override void OnResize(EventArgs e)
        {
            this.Refresh();
            base.OnResize(e);
        }


    }

    public class Contour
    {

        public static Color[] Create()
        {
            Color[] colors = new Color[256];

            for (int i = 0; i < 256; i++)
            {
                float[] rgb = Contour.ColorScaleBCGYR(i/(float)255);
                colors[i] = Color.FromArgb((int)(255 * rgb[0]), (int)(255 * rgb[1]), (int)(255 * rgb[2]));
            }

            return colors;
        }

        public static float[] ColorScaleBCGYR(double in_value)
        {
            // 0.0~1.0 の範囲の値をサーモグラフィみたいな色にする
            // 0.0                    1.0
            // 青    水    緑    黄    赤
            // 最小値以下 = 青
            // 最大値以上 = 赤
            float[] ret;
            int a = 255;    // alpha値
            int r, g, b;    // RGB値
            double value = in_value;
            double tmp_val = Math.Cos(4 * Math.PI * value);
            int col_val = (int)((-tmp_val / 2 + 0.5) * 255);
            if (value >= (4.0 / 4.0)) { r = 255; g = 0; b = 0; }   // 赤
            else if (value >= (3.0 / 4.0)) { r = 255; g = col_val; b = 0; }   // 黄~赤
            else if (value >= (2.0 / 4.0)) { r = col_val; g = 255; b = 0; }   // 緑~黄
            else if (value >= (1.0 / 4.0)) { r = 0; g = 255; b = col_val; }   // 水~緑
            else if (value >= (0.0 / 4.0)) { r = 0; g = col_val; b = 255; }   // 青~水
            else { r = 0; g = 0; b = 255; }   // 青
            ret = new float[3] { (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f };
            return ret;
        }
    }

}
⚠️ **GitHub.com Fallback** ⚠️