«   2018/12   »
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Statistics Graph
관리 메뉴

언제나 휴일

[미디 파일] 미디 파일 구조 분석 및 프로그래밍 1 - 청크 목록 본문

프로그래밍 기술/미디 파일 구조 및 미디 분석 프로그램 만들기

[미디 파일] 미디 파일 구조 분석 및 프로그래밍 1 - 청크 목록

언제나 휴일 언제나휴일 2018.04.09 12:30

[미디 파일] 미디 파일 구조 분석 및 프로그래밍 1 - 청크 목록



 안녕하세요. 언제나 휴일, 언휴예요.


 이번에는 미디 파일 구조를 간단히 알아보고 이를 분석하는 간단한 응용 프로그램을 작성해 보기로 할게요.


 먼저 미디(Midi)는 Musical Instrument Digital interface로 전자악기의 디지털 데이터를 주고 받기 위한 표준 규격입니다.


 여기에서는 미디 파일 구조를 점진적으로 분석하고 이를 이용하는 프로그램을 단계적으로 작성해 나가기로 할게요. (작업의 우선 순위로 인해 업데이트 속도가 더딜 수 있습니다.)


 미디 파일은 덩어리(청크, Chunk)들의 집합입니다. 미디 파일은 여러 개의 청크들로 구성하고 있다는 거예요. 


 그리고 청크는 청크 유형(4바이트), 청크 길이(4바이트), 청크 데이터(청크 길이)의 조합이예요.


청크(Chunk) 구조

[그림] Chunk 구조

주의할 점은 파일의 데이터가 Big Endian 바이트 정렬 방식을 따르고 있기 때문에 호스트 정렬 방식으로 조정이 필요합니다.


다음은 C#으로 미디 파일을 로딩하여 어떠한 청크들로 구성하고 있는지를 분석하는 간단한 응용 프로그램 소스 코드입니다.

[StaticFuns.cs] 공통적으로 사용할 함수를 래핑한 정적 클래스

using System;

using System.Net;

using System.Text;

 

namespace 청크분석

{

    public static class StaticFuns

    {

        public static string GetString(int magic)

        {

            byte[] data = BitConverter.GetBytes(magic);

            ASCIIEncoding en = new ASCIIEncoding();

            return en.GetString(data);

        }

        public static int ConvertHostorder(int data)

        {

            return IPAddress.NetworkToHostOrder(data);

        }

    }

}

 


[Chunk.cs]

using System.IO;

using System.Net;

using SF = 청크분석.StaticFuns;

namespace 청크분석

{

    class Chunk

    {

        public int CT//청크 유형

        {

            get;

            private set;

        }

        public int Length//청크 길이

        {

            get;

            private set;

        }

        public byte[] Data//데이터

        {

            get;

            private set;

        }

        public string CTString//청크 유형(문자열)

        {

            get

            {

                return SF.GetString(CT);

            }

        }

        public static Chunk Parse(Stream stream)

        {

            try

            {

                BinaryReader br = new BinaryReader(stream);

                int ctype = br.ReadInt32();

                int length = br.ReadInt32();

                length = SF.ConvertHostorder(length);

                byte[] buffer = br.ReadBytes(length);

                return new Chunk(ctype, length, buffer);

            }

            catch

            {

                return null;

            }

        }

        public Chunk(int ctype, int length, byte[] buffer)

        {

            CT = ctype;

            Length = length;

            Data = buffer;

        }

    }

}


[Program.cs]

using System;

using System.IO;

 

namespace 청크분석

{

    class Program

    {

        static string fname = "example.mid";

        static void Main(string[] args)

        {

            FileStream fs = new FileStream(fname, FileMode.Open);

            while(fs.Position < fs.Length)

            {

                Chunk chunk = Chunk.Parse(fs);

                if(chunk !=null)

                {

                    Console.WriteLine("{0} :{1} bytes",chunk.CTString,chunk.Length);

                }

            }

        }

    }

}



소스 코드에 사용한 표현들

byte[] data = BitConverter.GetBytes(CT); // 입력 인자로 전달한 int 형식 인자를 byte[]로 변환

ASCIIEncoding en = new ASCIIEncoding(); //ASCII 엔코딩 개체 생성

return en.GetString(data); //byte[]의 내용을 문자열로 생성 후 반환


length = IPAddress.NetworkToHostOrder(length); //호스트 정렬 방식으로 변환

미디 파일 구조 분석 실행 화면

[미디 파일 구조 분석 실행 화면]


참고할 파일:

Chunk.cs

Program.cs

StaticFuns.cs

미디 파일.zip



0 Comments
댓글쓰기 폼