Graph S16

ステレオの Sound Data をグラフで表示します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プログラムの説明

  1. サウンドを演奏してデータを確認することは難しいのでグラフにして表示します。
    もらいなき.wav は、ステレオで量子化ビットが 16 でサンプリングレートが 44.1 kHz で作成されています。
    音声データは "data" のチャンクに続いて、16 ビットで L,R,L,R, ... の順に格納されています。
    16 ビットのデータは、無音が 0 で -32768 ~ +32767 で表現されます。
  2. グラフを表示するので Windows(Form) モードでプログラムします。
    フォーム&グラフの表示は Line を描画する を参照して下さい。
    メニューの設定は メニューを設定する を参照して下さい。
    グラフは上側に左音声を、下側に右音声を、上下幅 100 で描画します。
    もらいなき.wav のサンプリングされたデータ件数は 12,594,960 件にもなっています。
    そこで 1000 件程度のグラフになるように、間引いて描画しています。
    従って、ノイズのような短いパルスはグラフに現れないので留意して下さい。
  3. もらいなき.wav を入力して、グラフで表示するコードです。
    //★ WAV FILE ステレオ 16bit のグラフを表示する    前田 稔
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.IO;
    
    public class MyForm : Form
    {
        static string file_name = "C:\\data\\test\\もらいなき.wav";
        static byte[] byt = new byte[20000000];
        static int    m_leng, m_idx, m_siz;
        public MyForm()
        {
            Width = 1200;
            Height = 700;
            Text = "Wave S16 Graph";
            MainMenu menu = new MainMenu();
            MenuItem item = menu.MenuItems.Add("ファイル(&F)");
            item.MenuItems.Add(new MenuItem("音量を下げる(&D)", new EventHandler(this.Level)));
            item.MenuItems.Add(new MenuItem("終了(&X)", new EventHandler(this.FileExit), Shortcut.CtrlQ));
            item = menu.MenuItems.Add("ヘルプ(&H)");
            item.MenuItems.Add(new MenuItem("バージョン情報(&A)...", new EventHandler(this.HelpAbout)));
            this.Menu = menu;
            Paint += new PaintEventHandler(MyHandler);
            m_siz = WavRead();
            if (m_siz==-1)  this.Close();
        }
        private void Level(object sender, EventArgs e)
        {   int i,idx;
            short v;
            for (i=0; i<m_siz; i+=2)
            {   idx = m_idx+i;
                v = (short)(get_short(idx)/2);
                byt[idx] = (byte)(v & 0XFF);
                byt[idx+1] = (byte)(v >> 8);
            }
            Invalidate();
        }
    
        // ファイル-終了メニューのイベントハンドラ
        private void FileExit(object sender, EventArgs e)
        {   this.Close();  }
    
        // ヘルプ-バージョン情報メニューのイベントハンドラ
        private void HelpAbout(object sender, EventArgs e)
        {   MessageBox.Show("Wave Graph S16    by Maeda Minoru");  }
    
        private void MyHandler(object sender, PaintEventArgs e)
        {
            int     i, idx, dt, wk;
            short   v;
            Graphics g = e.Graphics;
            g.DrawLine(new Pen(Color.Black),100,100,1100,100);
            g.DrawLine(new Pen(Color.Black,3),100,200,1100,200);
            g.DrawLine(new Pen(Color.Black), 100, 300, 1100, 300);
            g.DrawLine(new Pen(Color.Black, 3), 100, 400, 1100, 400);
            g.DrawLine(new Pen(Color.Black), 100, 500, 1100, 500);
            if (m_leng==-1) return;
            dt = m_siz/1000;
            if (dt%2==1)    dt++;
            for (i=0; i<1000; i++)
            {
                if (i*dt>=m_siz)    break;
                idx = m_idx + i*dt;
                v = (short)get_short(idx);
                wk = v/327;
                if (wk<0) wk = 0-wk;
                if (v < 0) g.DrawLine(new Pen(Color.Blue), 100+i, 200-wk, 100+i, 200);
                else g.DrawLine(new Pen(Color.Blue), 100+i, 200, 100+i, 200+wk);
                idx+=2;
                v = (short)get_short(idx);
                wk = v/327;
                if (wk<0) wk = 0-wk;
                if (v < 0) g.DrawLine(new Pen(Color.Red), 100+i, 400-wk, 100+i, 400);
                else g.DrawLine(new Pen(Color.Red), 100+i, 400, 100+i, 400+wk);
            }
        }
    
        private int WavRead()
        {   int siz;    //Data Size
    
            if (!File.Exists(file_name)) return -1;
            FileStream reader = File.Open(file_name,FileMode.Open);
            m_leng= reader.Read(byt,0,byt.Length);
            reader.Close();
    
            if (get_str(0)!="RIFF")
            {   MessageBox.Show("Header Error");
                return -1;
            }
            if (get_str(8)!="WAVE")
            {   MessageBox.Show("Header Error");
                return -1;
            }
            if (get_str(12)!="fmt ")
            {   MessageBox.Show("Header Error");
                return -1;
            }
            if (get_short(20) != 1)
            {   MessageBox.Show("Format Error");
                return -1;
            }
            if (get_short(22) != 2)
            {   MessageBox.Show("Format Error");
                return -1;
            }
            m_idx = 12;
            m_idx = m_idx+get_int(m_idx+4)+8;
            if (get_str(m_idx) != "data")
            {   m_idx = m_idx+get_int(m_idx+4)+8;
                if (get_str(m_idx) != "data")
                {   MessageBox.Show("Format Error");
                    return -1;
                }
            }
            siz = get_int(m_idx+4);
            m_idx = m_idx + 8;
            return siz;
        }
    
        //☆ get_str() 関数,  get_short() 関数, get_int() 関数の定義
    }
    
    class Draw
    {
        public static void Main()
        {
            MyForm mf = new MyForm();
            Application.Run(mf);
        }
    }
    
  4. メニューから[音量を下げる]を選択すると Level() 関数で音量を半分にします。
    FileExit() 関数はプログラムを終了する関数です。
    HelpAbout() 関数は Version を確認する関数です。
    MyHandler() 関数でグラフを表示します。
    WavRead() 関数で Wave File を入力します。
    "data" のチャンクに続いて、16 ビットで音声データが格納されています。
    dt が何件置きに描画するかを決める値で、左音声を描画したら idx を +2 して右音声を描画します。
  5. 次の関数は Volume M8 を参照して下さい。
    get_str() 関数で byt[idx] から4文字を取り出します。
    get_short() 関数で byt[idx] から short データを取り出します。
    get_int() 関数で byt[idx] から int データを取り出します。

[Next Chapter ↓] Sound Menu
[Previous Chapter ↑] Graph M8

超初心者のプログラム入門(C# Frame Work)