web.config 파일에 아래 부분 추가


<system.web>

<webServices>

<protocols>

<add name="HttpGet"/>

<add name="HttpPost"/>

</protocols>

</webServices>

</system.web>

Posted by 푸르른노을
,

개발자로 일하면서 두번째로 일하게 되었던 직장이 바로 "L&H Korea" 였습니다. 그 당시에는 나름 음성인식/TTS(Text-to-Speech) 관련해서 유명했던 회사였지만, 그 보다는... 아마도 한국 지사의 분식회계로 벨기에 본사까지 파산시킨 사례로 더 유명했을 수도 있습니다. 아직도 그 시절의 기사가 검색되는 군요. ^^;

음성인식 전문기업 L&H 코리아 파산 
; http://www.lawtimes.co.kr/LawNews/News/NewsContents.aspx?kind=AA&serial=4831


기존의 국내 음성인식 회사였던 '범일 정보 통신'을 벨기에의 "L&H" 가 인수해서 운영하던 지사였는데, 나름 외국계 회사라 근무 환경도 그 당시의 다른 IT업체와 비교해서 꽤 좋았던 걸로 기억합니다. 예를 들어, 한 달에 한번씩 맥주집을 통째로 빌려서 전 직원들 모두 서로 간에 가볍게 술한잔 하며 인사를 나눌 수 있는 복지정책도 있었는데... 아... 그 시절 생각하니 (현재 다나와에 계신) 임진배 소장님이 생각나는 군요. ^^

암튼... 제 경우에는 당시에 음성인식의 핵심 내부엔진을 다루는 연구소에서 (한국말은 끝까지 들어봐야 한다는) 일하지는 못했고 '웹 음성 인식 사이트'를 다루는 파트에서 일하게 되었더랬습니다. 당시에는 COM 개체가 생소했고, 회사의 음성인식을 다루는 엔진이 COM 개체로도 제공되긴 했지만 사용하기 어려워서 제가 임의로 좀 더 사용하기 편하게 COM 개체로 만들었고, 그것을 같이 일하던 웹 프로그래머가 HTML 웹 페이지에서 사용할 수 있도록 제공을 해서... 나름 재미있는 아이디어들이 피어나고 있었는데... 왠일인지 사업부 전체가 개편되면서 제가 있던 팀 자체가 해체되는 일이 발생했고, 저는 그 틈을 타서 자연스럽게 (현재 옥션에 계신) 김현승 수석님의 부름을 받아 가온아이(http://www.kaoni.com/)라는 회사에 이직을 하게 되었습니다.
아... 그 시절 생각하니 또 옛 추억에 잠기게 되는 군요. ^^

그나저나 오늘은 왜캐 서론이 길죠? ^^;

정신차리고... 본론으로 돌아와서, 제 기억으로는 그 유명했던 L&H 의 음성인식 엔진이 그 이후 윈도우의 기본 음성인식 엔진으로는 명맥을 이어갔다는 소식이 있었습니다. (현재의 윈도우에 있는 음성인식 엔진이 L&H 의 것인지는 모르겠습니다.)

물론, 윈도우 내에서만 사용할 수 있도록 숨겨져 있지는 않고 C# 으로도 이미 사용법이 잘 공개되어 있습니다.

Speech 101, Part 2 - Using C# to Recognize “Hello World”
; http://blogs.msdn.com/b/rlucero/archive/2012/01/10/speech-101-part-2-using-c-to-recognize-hello-world.aspx

SpeechRecognitionEngine Class
; http://msdn.microsoft.com/en-us/library/system.speech.recognition.speechrecognitionengine.aspx


위의 글에서도 잘 소개되어 있지만, 음성 인식 응용 프로그램을 만드려면 다음과 같은 단계를 밟아주면 됩니다.

  1. System.Speech 어셈블리 참조
  2. SpeechRecognitionEngine 인스턴스 생성
  3. 음성인식이 될 단어들을 적절하게 제시한 "Grammar" 지정
  4. 음성인식 입력 소스 지정
  5. SpeechRecognized 이벤트를 구독
  6. 음성인식 시작


SpeechRecognitionEngine 인스턴스야 그냥 new 하면 되는데요. 이 때, 음성인식에 사용될 '언어'를 지정해 주어야 합니다. 즉, 영어인지 한글인지를 지정해 주어야 하는데, 이를 알기 위해서는 현재의 윈도우에 어떤 언어의 음성인식 엔진이 설치되어 있는지 확인하는 방법이 필요합니다. 바로 이 때, SpeechRecognitionEngine.InstalledRecognizers 메서드를 이용하실 수 있습니다.

foreach (RecognizerInfo ri in SpeechRecognitionEngine.InstalledRecognizers())
{
    Console.WriteLine(ri.Culture);
}

// 영문 윈도우 7 Ultimate 버전에서는 다음과 같이 출력되었고,
en-US
en-GB

// 한글 윈도우 7 에서는 아무런 출력도 없었습니다.


기본값으로는 운영체제의 언어설정을 따라가니, 다음과 같이 빈 생성자로 초기화 해 줄 수도 있습니다.

using (SpeechRecognitionEngine recognizer = new SpeechRecognitionEngine())
{
}


그 다음은 인식될 단어들에 대한 후보를 명시해 주어야 합니다. "Speech 101, Part 2 - Using C# to Recognize “Hello World”" 글에서는 XML 파일을 이용한 방법을 설명하고 있고, "SpeechRecognitionEngine Class" 글에서는 코딩을 이용한 방법이 설명되고 있습니다.

처음에는 "SpeechRecognitionEngine Class" 글을 보고 코드로 직접 입력해 보려고 했는데, 아쉽게도 SetDictationContext 호출 코드에서 예외가 발생했습니다.

DictationGrammar grammar = new DictationGrammar("grammar:dictation");
grammar.Name = "question dictation";
grammar.SetDictationContext("Computer, hibernate yourself", null); <=== 예외: "Grammar is not loaded into this recognizer"
grammar.SetDictationContext("Yes", null);
grammar.Enabled = true;

recognizer.LoadGrammar(grammar);


단서가 많지 않았기 때문에 할 수 없이 XML 파일로 방향을 돌려야 했습니다. 그래서, 다음과 같이 xml 파일을 구성하고,

<grammar version="1.0" sapi:alphabet="x-microsoft-ups" xml:lang="en-us" root="Command" 
         tag-format="semantics-ms/1.0" xmlns="http://www.w3.org/2001/06/grammar"
         xmlns:sapi="http://schemas.microsoft.com/Speech/2002/06/SRGSExtensions">
     <rule id="Command" scope="public">
          <one-of>
               <item>Computer, hibernate yourself</item>
              <item>Yes</item>
              <item>No</item>
          </one-of>
     </rule>
</grammar>


음성인식 엔진에 적용을 시켰습니다.

Grammar grammar = new Grammar("computer.xml");
recognizer.LoadGrammar(grammar);


그 다음으로 할 일이, 음성을 입력받을 Source 를 지정해 주어야 하는데요. WAV 파일로부터도 입력을 받을 수 있고,

recognizer.SetInputToWaveFile("helloworld.wav");


컴퓨터에 연결된 마이크로폰으로부터도 입력 받을 수 있습니다. (여기서는 마이크로부터 입력받을 것입니다.)

recognizer.SetInputToDefaultAudioDevice();


이제 마지막으로, 음성인식이 된 경우 컴퓨터가 인식된 '텍스트'를 구할 수 있도록 이벤트 핸들러를 지정한 후, 음성인식 엔진을 시작시키면 됩니다.

recognizer.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(recognizer_SpeechRecognized);

recognizer.RecognizeAsync(RecognizeMode.Multiple);

while (true)
{
    Console.ReadLine();
}

static void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
    Console.WriteLine("Recognized text: " + e.Result.Text);
}


컴파일 하고 실행한 후, 컴퓨터에 달린 마이크에 "Computer, hibernate yourself" 라고 말하면 콘솔 화면에 "Recognized text: Computer, hibernate yourself"라고 찍힙니다.




음성인식과 쌍을 이루는 TTS 엔진도 마저 간단하게 살펴볼텐데요. 동일하게 System.Speech 어셈블리에서 제공되며 다음과 같이 음성출력을 할 수 있습니다.

SpeechSynthesizer tts = new SpeechSynthesizer();
tts.SetOutputToDefaultAudioDevice();
tts.Speak("Are you sure?");


그렇게 훌륭한 품질의 음성 출력은 아니지만... ^^; 좀 견딜만은 합니다.

자... 그럼, 음성인식과 출력을 곁들여서 다음과 같이 예제 제작을 해보면 어떨까요? 컴퓨터를 최대절전모드로 진입시키는 작업을 음성인식으로 할 수 있습니다. ^^

static RecognitionState current = RecognitionState.None;

static void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
    if (e.Result.Text == "Computer, hibernate yourself" &&
        current == RecognitionState.None)
    {
        current = RecognitionState.Question;

        System.Speech.Synthesis.SpeechSynthesizer tts = new System.Speech.Synthesis.SpeechSynthesizer();
        tts.SetOutputToDefaultAudioDevice();
        tts.Speak("Are you sure?");
        Console.WriteLine("Are you sure?");
        return;
    }

    if (current == RecognitionState.Question)
    {
        current = RecognitionState.None;
        if (e.Result.Text == "Yes")
        {
            Console.WriteLine("hibernating...");
            DoHibernation();
        }
        else
        {
            Console.WriteLine("Canceled.");
        }
    }
}

private static void DoHibernation()
{
    ProcessStartInfo psi = new ProcessStartInfo();
    psi.Arguments = "/h /f";
    psi.FileName = "c:\\windows\\system32\\shutdown.exe";
    Process.Start(psi);
}

public enum RecognitionState
{
    None,
    Question,
}





그런데, 한글 음성인식은 안 되는 걸까요? 이를 위해서는 별도로 "Microsoft Speech Platform - Runtime 11.0" 을 설치해야 하고, 그 버전에 맞는 한글 음성인식 데이터 파일을 설치해 주어야 합니다. (물론, TTS 도 필요하다면.)

그래서, 각각 다음의 경로에서 먼저 파일들을 다운로드 받아서 설치합니다.

Microsoft Speech Platform - Runtime 11.0
; http://go.microsoft.com/fwlink/?LinkID=223568&clcid=0x409

Microsoft Speech Platform - Server SDK
; http://go.microsoft.com/fwlink/?LinkID=223570&clcid=0x409


이어서, 한글에 대한 음성인식과 TTS 데이터 파일을 다운로드/설치하고,

Microsoft Speech Platform - Runtime Languages (Version 11)
; http://www.microsoft.com/download/en/details.aspx?id=27224

한글 음성인식: MSSpeech_SR_ko-KR_TELE.msi
한글 TTS: MSSpeech_TTS_ko-KR_Heami.msi


이제 위에서 만든 예제 프로젝트에 약간의 변화를 가해주어야 합니다. 우선, System.Speech 어셈블리를 참조해제하고, 대신 "Microsoft Speech Platform - Server SDK" 의 설치 폴더로부터 "C:\Program Files\Microsoft SDKs\Speech\v11.0\Assembly\Microsoft.Speech.dll" 파일을 복사해서 참조 추가합니다.

이후, 코드에서 사용된 네임스페이스를 각각 다음과 같이 바꿔주어야 합니다.

System.Speech.Recognition ==> Microsoft.Speech.Recognition
System.Speech.Synthesis ==> Microsoft.Speech.Synthesis


음성인식을 위해 설정한 computer.xml 파일도 바꿔야겠지요.

<grammar version="1.0" sapi:alphabet="x-microsoft-ups" xml:lang="ko-KR" root="Command" 
         tag-format="semantics-ms/1.0" xmlns="http://www.w3.org/2001/06/grammar"
         xmlns:sapi="http://schemas.microsoft.com/Speech/2002/06/SRGSExtensions">
     <rule id="Command" scope="public">
          <one-of>
              <item>컴퓨터, 최대 절전 모드로 들어가</item>
              <item>응</item>
              <item>아니</item>
          </one-of>
     </rule>
</grammar>


마지막으로, SpeechRecognized 이벤트 핸들러 내의 코드를 다음과 같이 바꿔줍니다.

static void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
    if (e.Result.Text == "컴퓨터, 최대 절전 모드로 들어가" &&
        current == RecognitionState.None)
    {
        current = RecognitionState.Question;

        SpeechSynthesizer tts = new SpeechSynthesizer();
        tts.SelectVoice("Microsoft Server Speech Text to Speech Voice (ko-KR, Heami)");
        tts.SetOutputToDefaultAudioDevice();
        tts.Speak("정말?");
        Console.WriteLine("정말?");
        return;
    }

    if (current == RecognitionState.Question)
    {
        current = RecognitionState.None;
        if (e.Result.Text == "응")
        {
            Console.WriteLine("hibernating...");
            DoHibernation();
        }
        else
        {
            Console.WriteLine("Canceled.");
        }
    }
}


전체적으로 소스 코드의 호환성은 System.Speech.dll 과 Microsoft.Speech.dll 에서 지켜지는 편인데, 단지 영문/한글에 대한 부분만 살짝 바꿔주기만 하면 됩니다.




가장 중요한 것! 그래서 한글 음성인식이나 TTS가 어느 정도냐 하는 것인데요. 음... 그냥 '무료'라는 점을 감안하라는 조언만 드리고 싶군요. ^^

* 첨부파일은 2가지 예제 프로젝트를 압축한 것입니다.


Posted by 푸르른노을
,


Obfuscation(난독화)에 관련된 기본 지식은 위키와 서광렬님의 블로그를 참조하자.

.NET Framework에서는 C#, VB.NET등과 같은 Managed .NET code로 쓰여진 코드는 .NET 언어 Compiler에 의해  CIL(Common Intermediate Language, = MSIL)로 만들어지고 JIT(Just-In-Time Compiler)에 의해서 Native Code로 변환되고 CLR(Common Language Runtime)위에서 구동된다. 이러한 이유로 .NET Framework가 설치된 Device에서는 CIL 덕분에 어떤 프로그래밍 언어(단, Managed Code)로 작성된 프로그램이든 실행이 된다. 하지만 소스 보안 측면에서 보면 CIL만 있다면 손쉽게 소스코드를 열어볼 수 있음을 의미한다. (맞겠지...??)

Managed Code로 작성된 프로그램은 .NET Reflector(Reflector를 정복하기 위해서는 남정현님의 블로그[또는 데브피아]를 참조하자. - 최신버전 설명서는 아닌듯!?)를 통해 원본 소스와 거의 비슷하게, 심지어 다른 언어로까지 변환이 된다.

소스 보안을 위해 보통 obfuscator를 사용하곤 하는데 최근 알게된 소프트웨어를 소개할까 한다. GNU GPL 라이선스(무료라는 얘기!)를 가진 Eazfuscator.NET 이다.
Eazfuscator.NET를 사용하면 Reflector를 통해서는 원본 소스를 판단할 수 없게 된다.


사용법을 알아보자.

  1.  Eazfuscator.NET을 설치
  2.  Visual Studio 2008의 Tools Menu에 Add-in 된 것 확인.
  3.  Tool > Eazfuscator.NET Assistant 실행.(그림 1, 2)
  4.  Solution Explorer에서 Obfuscation하길 원하는 Project를(Solution이 아님) 끌어다 녹색바탕에 드래그 앤 드랍.
  5.  Obfuscation이 진행. 그리고 완료.
  6.  Obfuscation이 끝나면VS 2008에서 해당 Project가 변경되었으니 다시 로드할꺼냐고 묻는다. Reload버튼을 눌러주자.
  7.  Release Mode로 두고 Project Build. -끝-


  



그림1. Add-in된 Eazfuscator.NET









 그림 2. Eazfuscator.NET가 실행된 모습






Eazfuscator.NET을 사용한 결과는 아래와 같다.

Before Obfuscation



Posted by 푸르른노을
,