Volume M8

モノラル(monaural 8)の WAVE FILE の音量を調整します。

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

プログラムの説明

  1. モノラル(monaural 8)の WAVE FILE(ringin.wav)の音量を半分にします。
    ringin.wav は Windwos System に効果音として格納されているファイルです。
    このファイルは、モノラルで量子化ビットが8でサンプリングレートが 11025 で作成されています。
  2. コンソールモードで作成した Console.cs のソースコードです。
    ringin.wav を入力して、ファイル形式を確認するコードです。
    "data" のチャンクに続いて、8ビットで音声データが格納されています。
    最初の 100 件分の音声データを印字してみます。
    //★ Mono 8bit    前田 稔 ★
    using System;
    using System.IO;
    
    class Sound
    {
        static string file_name = "C:\\data\\test\\ringin.wav";
        static byte[] byt = new byte[20000000];
        static string out_name = "C:\\data\\test\\w.wav";
    
        public static int Main()
        {
            int     leng, siz;
            int     idx, p, v;
            if (!File.Exists(file_name)) return -1; //ファイルの有無をチェック
            FileStream reader = File.Open(file_name,FileMode.Open);
            leng= reader.Read(byt,0,byt.Length);
            reader.Close();
    
            if (get_str(0)!="RIFF")
            {   Console.WriteLine("Header Error=" + get_str(0));
                Console.ReadLine();
                return -1;
            }
            if (get_str(8)!="WAVE")
            {   Console.WriteLine("Header Error=" + get_str(8));
                Console.ReadLine();
                return -1;
            }
            if (get_str(12)!="fmt ")
            {   Console.WriteLine("Header Error=" + get_str(12));
                Console.ReadLine();
                return -1;
            }
            Console.WriteLine("len:" + get_int(16));
            if (get_short(20) != 1)
            {
                Console.WriteLine("Format Error=" + get_short(20));
                Console.ReadLine();
                return -1;
            }
            if (get_short(22) != 1)
            {
                Console.WriteLine("Stereo Error=" + get_short(22));
                Console.ReadLine();
                return -1;
            }
            Console.WriteLine("Mono:8bit Sampling:" + get_int(24));
            idx = 12;
            idx = idx+get_int(idx+4)+8;
            Console.WriteLine("次のチャンク:" + get_str(idx) + " idx:" + idx);
            if (get_str(idx) != "data") return -1;
            siz = get_int(idx+4);
            Console.WriteLine("data size:" + siz);
            idx = idx + 8;
            for (int i=0; i<100; i++)
            {   p = idx+i;
                Console.WriteLine(byt[p]);
            }
    
            Console.ReadLine();
            return 0;
        }
    
        // WAVE 領域からデータを取得
        static string get_str(int idx)
        {
            char[] chary = new char[4];
            chary[0] = (char)byt[idx];
            chary[1] = (char)byt[idx + 1];
            chary[2] = (char)byt[idx + 2];
            chary[3] = (char)byt[idx + 3];
            return new string(chary);
        }
    
        static short get_short(int idx)
        {
            short val;
            val = (short)(byt[idx] + (byt[idx+1] << 8));
            return val;
        }
    
        static int get_int(int idx)
        {
            int val;
            val = byt[idx] + (byt[idx + 1] << 8) + (byt[idx + 2] << 16) + (byt[idx + 3] << 24);
            return val;
        }
    
        // WAVE 領域からデータを設定
        static void set_short(short v, int idx)
        {
            byt[idx] = (byte)(v & 0XFF);
            byt[idx+1] = (byte)(v >> 8);
        }
    
        static void set_int(int v, int idx)
        {
            byt[idx] = (byte)(v & 0XFF);
            byt[idx+1] = (byte)((v>>8) & 0XFF);
            byt[idx+2] = (byte)((v>>16) & 0XFF);
            byt[idx+3] = (byte)((v>>24) & 0XFF);
        }
    }
    
  3. "data" チャンクに続く4byte(int 型)がサンプリングデータの長さで、その後に8ビットで音声データが格納されています。
    最初の 100 件分の音声データを印字してみます。
    123, 48, 101, 141, ...
    64617461 data チャンク
    FD260000 データサイズ(9981)
    7B30658D...8ビットの音声データが続く
  4. get_str() 関数で byt[idx] から4文字を取り出します。
    get_short() 関数で byt[idx] から short データを取り出します。
    get_int() 関数で byt[idx] から int データを取り出します。
    set_short() 関数で short データを設定します。
    set_int() 関数で int データを設定します。
  5. ringin.wav の音量を半分に下げて w.wav の名前で保存します。
    idx から始まる siz 個の音声データを半分にします。
    音声データは 128 が無音で上下に離れるほど音量が大きくなります。
    //★ Mono 8bit    前田 稔 ★
                ・・・
        static string out_name = "C:\\data\\test\\w.wav";
                ・・・
            for (int i=0; i<siz; i++)
            {   p = idx+i;
                v = byt[p];
                if (v<128)  v = 128-(128-v)/2;
                else    v = (v-128)/2+128;
                byt[p] = (byte)v;
            }
            FileStream writer = File.Create(out_name);
            writer.Write(byt,0,leng);
            writer.Close();
            Console.Write("complete");
    
            Console.ReadLine();
            return 0;
        }
    
  6. 元の ringin.wav と w.wav を比べると音量が下がっていることがわかるでしょう。
    ringin.wav は、モノラルで量子化ビットが8ですが、一般に出回っている音楽データはステレオで量子化ビットが16です。
    ステレオの音楽データでは L R L R L R … の順に16ビットで格納されています。
    WAVE FILE の説明は WAV ファイルフォーマット を参照して下さい。

[Next Chapter ↓] Graph M8
[Previous Chapter ↑] もらいなき

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