<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
	<channel>
		<title>류종택의 프로그래밍 강의실</title>
		<link>http://ryulib.tistory.com/</link>
		<description></description>
		<language>ko</language>
		<pubDate>Fri, 17 Feb 2012 07:30:36 +0900</pubDate>
		<generator>Tistory 1.1 (http://www.tistory.com/)</generator>
		<managingEditor>류종택</managingEditor>
		<image>
		<title>류종택의 프로그래밍 강의실</title>
		<url><![CDATA[http://cfile24.uf.tistory.com/image/201B9A184D036F6826DF06]]></url>
		<link>http://ryulib.tistory.com/</link>
		<description></description>
		</image>
		<item>
			<title>Tron 게임</title>
			<link>http://ryulib.tistory.com/187</link>
			<description>&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://cfile6.uf.tistory.com/original/123E6D464F3D822C03AF82&quot; rel=&quot;lightbox&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://cfile6.uf.tistory.com/image/123E6D464F3D822C03AF82&quot; alt=&quot;&quot; filemime=&quot;image/jpeg&quot; filename=&quot;tron_game3.jpg&quot; height=&quot;240&quot; width=&quot;275&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;br /&gt;초등학교 때였던가? &amp;nbsp;이게 영화가 있는 것도 모르고, 게임에 빠져들었던 적이 있었는데, PC에서 실행할 수 있는 프로그램이 있어서 올려봅니다.&lt;br /&gt;
&lt;br /&gt;&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://ryulib.tistory.com/attachment/cfile2.uf@1363653D4F3D826A09EB3F.zip&quot;&gt;&lt;img src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/blog/image/extension/zip.gif&quot; alt=&quot;&quot; style=&quot;vertical-align: middle;&quot; /&gt; Tron.zip&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;br /&gt;기억이 참 새롭네요 ^^*&lt;br /&gt;&lt;div class=&quot;entry-ccl&quot; style=&quot;clear: both; text-align: right; margin-bottom: 10px&quot;&gt;
	&lt;img id=&quot;ccl-icon-187-0&quot; class=&quot;entry-ccl-by&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png&quot; alt=&quot;저작자 표시&quot;/&gt;
	&lt;img id=&quot;ccl-icon-187-1&quot; class=&quot;entry-ccl-nc&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black02.png&quot; alt=&quot;비영리&quot;/&gt;
	&lt;img id=&quot;ccl-icon-187-2&quot; class=&quot;entry-ccl-nd&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black03.png&quot; alt=&quot;변경 금지&quot;/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
		&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;
			&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align:center; padding-top:10px;&quot;&gt;
&lt;iframe src=&quot;http://www.facebook.com/plugins/like.php?href=ryulib.tistory.com/187&amp;amp;layout=standard&amp;amp;show_faces=true&amp;amp;width=310&amp;amp;action=like&amp;amp;font=tahoma&amp;amp;colorscheme=light&amp;amp;height=65&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; style=&quot;border:none; overflow:hidden; width:310px; height:65px;&quot; allowTransparency=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
</description>
			<category>etc</category>
			<author>류종택</author>
			<guid>http://ryulib.tistory.com/187</guid>
			<comments>http://ryulib.tistory.com/187#entry187comment</comments>
			<pubDate>Fri, 17 Feb 2012 07:26:24 +0900</pubDate>
		</item>
		<item>
			<title>퍼포먼스를 위한 발악</title>
			<link>http://ryulib.tistory.com/186</link>
			<description>오래 전부터 습관이 된 탓에 and 조건을 분별할 때에는 항상 확률이 낮은 것부터 나열하도록 신경을 쓰고 있었습니다. &amp;nbsp;그러다가, 요즘 PC에서 그런 것이 과연 얼마나 퍼포먼스 향상에 도움이 될 까 궁굼해 졌습니다. &amp;nbsp;바로 테스트에 들어 갔습니다.&lt;br /&gt;
&lt;br /&gt;
[소스 1]&lt;br /&gt;

&lt;pre name=&quot;code&quot; class=&quot;brush: delphi;  highlight: []; toolbar: false;&quot;&gt;procedure TForm1.Button1Click(Sender: TObject);
var
  Tick : Cardinal;
  Loop, a, b : integer;
begin
  Tick := GetTickCount;

  for Loop := 1 to 100000000 do begin
      a := Random(2);
      b := Random(100);
//      if (a = 1) and (b = 1) then Tag := Tag + 1;
      if (b = 1) and (a = 1) then Tag := Tag + 1;
  end;

  Caption := IntToStr(GetTickCount - Tick);
end;
&lt;/pre&gt;11: 라인과 12: 라인이 오늘의 주인공입니다. &amp;nbsp;결과적으로 똑같은 두 문장의 속도 차이는 아래와 같습니다.&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc; &quot;&gt;
&lt;li&gt;11: 라인 평균 1200 ms 정도&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;12:&amp;nbsp;라인 평균 730 ms 정도&lt;/li&gt;
&lt;/ul&gt;
and 문장에서는 앞에서 false가 판별되었을 경우 다음 조건을 검사하지 않기 때문에 확률이 낮은 것을 먼저 분별하면 성능에 도움이 됩니다. &amp;nbsp;or 에서는 반대로 확률이 높은 것부터 나열하는 것이 조금이나마 이득이 됩니다.&lt;br /&gt;
&lt;br /&gt;
근래에는 PC의 성능이 워낙에 좋아졌기 때문에 일반적인 경우 퍼포먼스에 대한 고민을 많이 할 필요가 없었졌습니다. &amp;nbsp;하지만, 스마트폰, 게임 및 증권 시스템 트레이딩과 같이 반복 계산이 많은 프로젝트 등에서는 이런 작은 차이들이 엄청난 결과를 만들어 내기도 합니다.&lt;br /&gt;
&lt;br /&gt;그렇긴 해도 반복 횟수를 감안하면 상당한 뻘짓이네요 ^^;&amp;nbsp;&lt;div class=&quot;entry-ccl&quot; style=&quot;clear: both; text-align: right; margin-bottom: 10px&quot;&gt;
	&lt;img id=&quot;ccl-icon-186-0&quot; class=&quot;entry-ccl-by&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png&quot; alt=&quot;저작자 표시&quot;/&gt;
	&lt;img id=&quot;ccl-icon-186-1&quot; class=&quot;entry-ccl-nc&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black02.png&quot; alt=&quot;비영리&quot;/&gt;
	&lt;img id=&quot;ccl-icon-186-2&quot; class=&quot;entry-ccl-nd&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black03.png&quot; alt=&quot;변경 금지&quot;/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
		&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;
			&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align:center; padding-top:10px;&quot;&gt;
&lt;iframe src=&quot;http://www.facebook.com/plugins/like.php?href=ryulib.tistory.com/186&amp;amp;layout=standard&amp;amp;show_faces=true&amp;amp;width=310&amp;amp;action=like&amp;amp;font=tahoma&amp;amp;colorscheme=light&amp;amp;height=65&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; style=&quot;border:none; overflow:hidden; width:310px; height:65px;&quot; allowTransparency=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
</description>
			<category>etc</category>
			<author>류종택</author>
			<guid>http://ryulib.tistory.com/186</guid>
			<comments>http://ryulib.tistory.com/186#entry186comment</comments>
			<pubDate>Sat, 11 Feb 2012 23:52:25 +0900</pubDate>
		</item>
		<item>
			<title>State Pattern을 이용한 미디어 서버 구축 과정</title>
			<link>http://ryulib.tistory.com/184</link>
			<description>소스가 복잡한 편이라 예제로서는 부적합 할 수 있으나, 현재 작업 중인 과정을 잠시 설명하려고 합니다. &amp;nbsp;중단했던 미디어 서버 개발이 모두 완료되면 다시 정리해서 올리도록 하겠습니다.&lt;br /&gt;
&lt;br /&gt;
우선 어제 새벽에 그린 상태도는 &amp;nbsp;[그림 1]과 같습니다. &amp;nbsp;기존의 UML 툴이 제공하는&amp;nbsp;상태변화의 선행처리와 후행처리 표시가 복잡해 보여서, 네모 박스로 표시했습니다. &amp;nbsp;문제는 상태가 완전히 변한 후에 처리되느냐, 전에 처리되느냐를 알 수가 없다는 것 입니다. &amp;nbsp;나중에 좀 더 고민하여 표기법을 정리해보려고 합니다.&lt;br /&gt;
&lt;br /&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://cfile1.uf.tistory.com/original/180210444F2760D629AC8A&quot; rel=&quot;lightbox&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://cfile1.uf.tistory.com/image/180210444F2760D629AC8A&quot; alt=&quot;&quot; filemime=&quot;&quot; filename=&quot;cfile1.uf@180210444F2760D629AC8A.png&quot; height=&quot;417&quot; width=&quot;600&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
[그림 1] 미디어 서버의 클라이언트 모듈의 일부에 대한 상태도&lt;/div&gt;
&lt;br /&gt;
&lt;p&gt;&lt;/p&gt;
[그림 1]은 TCP 소켓을 이용해서 미디어 서버로부터 데이터를 스트림으로 받는 TFFTCPStream라는 클래스의 상태도입니다. &amp;nbsp;
TFFTCPStream는 아래와 같은 조건에서 개발 중 입니다.&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc; &quot;&gt;
&lt;li&gt;TFFTCPStream&amp;nbsp;은 서버에 있는 동영상 파일의 정보 및 데이터를 수신 받아서 버퍼에 저장한다. &amp;nbsp;이 버퍼는 미디어 플레이어 클래스에서 사용되어 재생된다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;안드로이드 플랫폼에서 사용 될 것이다. &amp;nbsp;다만, 디버깅 효율을 높이기 위해서 델파이로 원도우용 클라이언트를 작성하여 테스트를 진행 할 것이다.&lt;/li&gt;
&lt;li&gt;스마트 폰의 특성 상 접속이 자주 끊어질 수 있다. &amp;nbsp;따라서, 접속이 끊어지면 기존의 세션을 복구해야 한다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;재생 위치의 빠른 이동을 위해서 서버에서는 인덱싱 정보를 캐싱하고 있다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;기타 등등&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
[소스 1] 패킷의 종류&lt;br /&gt;

&lt;pre name=&quot;code&quot; class=&quot;brush: delphi;  highlight: []; toolbar: false;&quot;&gt;type
  TPacketType = (
    // 공통
    ptNone, ptPing,

    // Server Received
    ptOptions, ptOpen, ptReopen, ptAsk, ptClose, ptLogin, ptLogout,

    // Client Received
    ptPackage, ptOkOpen, ptErOpen, ptOkReopen, ptErReopen,
    ptOkLogin, ptErLogin, ptOkLogout, ptErLogout
  );
  PPacketType = ^TPacketType;
&lt;/pre&gt;

[소스 1]은 통신 할 때 사용하는 패킷의 종류들 입니다. &amp;nbsp;대부분 이름을 보면 금새 무엇을 하는 넘인지 알 수 있을 것이라 생각합니다. &amp;nbsp;ptReopen은 접속이 끊어졌다가 다시 연결되었을 때, 기존의 세션을 복구하기 위한 패킷입니다. &amp;nbsp;ptAsk는 인덱스 위치에 해당하는 미디어 데이터를 요청합니다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[소스 2]&amp;nbsp;
주요 클래스의 인터페이스&lt;br /&gt;

&lt;pre name=&quot;code&quot; class=&quot;brush: delphi;  highlight: []; toolbar: false;&quot;&gt;type
  TFFTCPStream = class (TComponent)
  private
  public
    function OpenFile(AHost:string; APort:integer; AFileName:string):boolean;
    procedure CloseFile;
  published
    property IsOpened : boolean read FIsOpened;
    property OnFileOpened : TFileOpenedEvent read FOnFileOpened write FOnFileOpened;
    property OnFileOpenError : TNotifyEvent read FOnFileOpenError write FOnFileOpenError;
    property OnFileClosed : TNotifyEvent read FOnFileClosed write FOnFileClosed;
  end;

  TState = class
  private
    FFFTCPStream:TFFTCPStream;
  public
    constructor Create(AFFTCPStream:TFFTCPStream); reintroduce; virtual;

    procedure ActionIn(AOldState:TObject); virtual;
    procedure ActionOut(ANewState:TObject); virtual;

    function OpenFile(AHost:string; APort:integer; AFileName:string):boolean; virtual;
    procedure CloseFile; virtual;

    procedure on_Timer; virtual;
    procedure on_Disconnected; virtual;

    procedure pt_Package(AData:pointer; ASize:integer); virtual;
    procedure pt_OkOpen(AData:pointer; ASize:integer); virtual;
    procedure pt_ErOpen(AData:pointer; ASize:integer); virtual;
    procedure pt_OkReopen(AData:pointer; ASize:integer); virtual;
    procedure pt_ErReopen(AData:pointer; ASize:integer); virtual;
  end;&lt;/pre&gt;

TSate는 각 상태에 대한 클래스의 추상화된 부모 클래스입니다.&lt;br /&gt;
&lt;br /&gt;
20: 상태가 변화되서 자신이 선택되었을 경우 실행됩니다. &amp;nbsp;자신이 선택되었을 때 선행처리를 합니다.&lt;br /&gt;
21: 상태가 변화되서 다른 상태가 선택되었을 경우 실행됩니다. &amp;nbsp;다른 상태로 전이될 때 후행처리를 합니다.&lt;br /&gt;
&lt;br /&gt;
23-33: [그림 1]의 상태도에서 화살표에 그려진 프로세스들을 모두 표기한 것 입니다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[소스 3] 디버깅을 위한 코드&lt;br /&gt;

&lt;pre name=&quot;code&quot; class=&quot;brush: delphi;  highlight: []; toolbar: false;&quot;&gt;{ TState }

procedure TState.CloseFile;
begin
  {$IFDEF DEBUG}
    OutputDebugString(PChar(Format(&#039;%s.CloseFile: &#039;, [Self.ClassName])));
  {$ENDIF}
end;

{ TStateConnected }

procedure TStateConnected.CloseFile;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  FFFTCPStream.close_File;
  FFFTCPStream.SetState(FFFTCPStream.FStateClosed);
end;
&lt;/pre&gt;

부모 클래스인 TState에는 모든 메소드마다 디버깅 정보를 출력하도록 되어 있습니다. &amp;nbsp;이를 통해서 실제 동작 할 때 어떤 순서로 동작하는 지, 그리고 [그림 1]의 상태도의 조건대로 프로세스가 진행된느 지를 쉽게 확인 할 수가 있습니다. &amp;nbsp;자식 클래스에서는&amp;nbsp;inherited 를 실행하여 자신이 동작 할 때마다 디버그 정보를 [그림 2]와 같이 출력하도록 합니다.&lt;br /&gt;
&lt;br /&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://cfile25.uf.tistory.com/original/13409A364F27662B0B84E2&quot; rel=&quot;lightbox&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://cfile25.uf.tistory.com/image/13409A364F27662B0B84E2&quot; alt=&quot;&quot; filemime=&quot;&quot; filename=&quot;cfile25.uf@13409A364F27662B0B84E2.png&quot; height=&quot;452&quot; width=&quot;600&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
[그림 2] 디버깅 정보 확인&lt;/div&gt;
&lt;br /&gt;
&lt;p&gt;&lt;/p&gt;
&lt;br /&gt;
[소스 4]&amp;nbsp;FFTCPStream.pas의 전체 소스&lt;br /&gt;

&lt;pre name=&quot;code&quot; class=&quot;brush: delphi;  highlight: []; toolbar: false;&quot;&gt;unit FFTCPStream;

interface

uses
  FFServerUtils, RyuMpeg, RyuSocketClient, ThreadRepeater,
  Windows, Classes, SysUtils, SyncObjs;

const
  _TimerInterval = 1 * 1000;  // 1초 마다

type
  TFileOpenedEvent = procedure (Sender:TObject; AMediaInfo:TMediaInfo) of object;

  TFFTCPStream = class (TComponent)
  private
    FFileName : string;
    FOldTick : Cardinal;
    FCS : TCriticalSection;
    procedure close_File;
    procedure fire_OnFileOpened(AMediaInfo:TMediaInfo);
    procedure fire_OnFileOpenError;
    procedure fire_OnFileClosed;
  private
    FSocket : TRyuSocketClient;
    procedure on_Disconnected(Sender:TObject);
    procedure on_Received(Sender:TObject; AData:pointer; ASize:integer);
  private
    procedure send_Text(APacketType:TPacketType; AText:AnsiString);
    procedure send_Open;
    procedure send_Reopen;
    procedure send_Close;
    procedure send_Ask(AIndex:integer);
  private
    FTimer : TThreadRepeater;
    procedure on_Timer(Sender:TObject);
  private
    FState : TObject;
    FStateClosed, FStateConnected, FStateOpened, FStateDisconnected, FStateReconnected : TObject;
    procedure SetState(AState:TObject);
  private
    FOnFileClosed: TNotifyEvent;
    FOnFileOpenError: TNotifyEvent;
    FOnFileOpened: TFileOpenedEvent;
    FIsOpened: boolean;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    function OpenFile(AHost:string; APort:integer; AFileName:string):boolean;
    procedure CloseFile;
  published
    property IsOpened : boolean read FIsOpened;
    property OnFileOpened : TFileOpenedEvent read FOnFileOpened write FOnFileOpened;
    property OnFileOpenError : TNotifyEvent read FOnFileOpenError write FOnFileOpenError;
    property OnFileClosed : TNotifyEvent read FOnFileClosed write FOnFileClosed;
  end;

implementation

type
  TState = class
  private
    FFFTCPStream:TFFTCPStream;
  public
    constructor Create(AFFTCPStream:TFFTCPStream); reintroduce; virtual;

    procedure ActionIn(AOldState:TObject); virtual;
    procedure ActionOut(ANewState:TObject); virtual;

    function OpenFile(AHost:string; APort:integer; AFileName:string):boolean; virtual;
    procedure CloseFile; virtual;

    procedure on_Timer; virtual;
    procedure on_Disconnected; virtual;

    procedure pt_Package(AData:pointer; ASize:integer); virtual;
    procedure pt_OkOpen(AData:pointer; ASize:integer); virtual;
    procedure pt_ErOpen(AData:pointer; ASize:integer); virtual;
    procedure pt_OkReopen(AData:pointer; ASize:integer); virtual;
    procedure pt_ErReopen(AData:pointer; ASize:integer); virtual;
  end;

  TStateClosed = class (TState)
  private
  public
    function OpenFile(AHost:string; APort:integer; AFileName:string):boolean; override;
  end;

  TStateConnected = class (TState)
  private
  public
    function OpenFile(AHost:string; APort:integer; AFileName:string):boolean; override;
    procedure CloseFile; override;

    procedure on_Timer; override;
    procedure on_Disconnected; override;

    procedure pt_OkOpen(AData:pointer; ASize:integer); override;
    procedure pt_ErOpen(AData:pointer; ASize:integer); override;
  end;

  TStateOpened = class (TState)
  private
  public
    function OpenFile(AHost:string; APort:integer; AFileName:string):boolean; override;
    procedure CloseFile; override;

    procedure on_Timer; override;
    procedure on_Disconnected; override;

    procedure pt_Package(AData:pointer; ASize:integer); override;
  end;

  TStateDisconnected = class (TState)
  private
  public
    function OpenFile(AHost:string; APort:integer; AFileName:string):boolean; override;
    procedure CloseFile; override;

    procedure on_Timer; override;
  end;

  TStateReconnected = class (TState)
  private
  public
    function OpenFile(AHost:string; APort:integer; AFileName:string):boolean; override;
    procedure CloseFile; override;

    procedure on_Timer; override;

    procedure pt_OkReopen(AData:pointer; ASize:integer); override;
    procedure pt_ErReopen(AData:pointer; ASize:integer); override;
  end;

{ TFFTCPStream }

procedure TFFTCPStream.CloseFile;
begin
  TState(FState).CloseFile;
end;

procedure TFFTCPStream.close_File;
begin
  SetState(FStateClosed);

  FTimer.Stop;
  send_Close;

  FIsOpened := false;
  fire_OnFileClosed;
end;

constructor TFFTCPStream.Create(AOwner: TComponent);
begin
  inherited;

  FFileName := &#039;&#039;;
  FIsOpened := false;

  FSocket := TRyuSocketClient.Create(Self);
  FSocket.OnDisconnected := on_Disconnected;
  FSocket.OnReceived := on_Received;

  FCS := TCriticalSection.Create;

  FStateClosed  := TStateClosed.Create(Self);
  FStateConnected  := TStateConnected.Create(Self);
  FStateOpened  := TStateOpened.Create(Self);
  FStateDisconnected  := TStateDisconnected.Create(Self);
  FStateReconnected := TStateReconnected.Create(Self);

  FState := FStateClosed;

  FTimer := TThreadRepeater.Create(Self);
end;

destructor TFFTCPStream.Destroy;
begin
  CloseFile;

  FreeAndNil(FSocket);
  FreeAndNil(FStateClosed);
  FreeAndNil(FStateConnected);
  FreeAndNil(FStateOpened);
  FreeAndNil(FStateDisconnected);
  FreeAndNil(FStateReconnected);
  FreeAndNil(FTimer);
  FreeAndNil(FCS);

  inherited;
end;

procedure TFFTCPStream.fire_OnFileClosed;
begin
  if Assigned(FOnFileClosed) then FOnFileClosed(Self);
end;

procedure TFFTCPStream.fire_OnFileOpened(AMediaInfo:TMediaInfo);
begin
  // TODO : Player.Open(AMediaInfo);
  if Assigned(FOnFileOpened) then FOnFileOpened(Self, AMediaInfo);
end;

procedure TFFTCPStream.fire_OnFileOpenError;
begin
  if Assigned(FOnFileOpenError) then FOnFileOpenError(Self);
end;

procedure TFFTCPStream.on_Disconnected(Sender: TObject);
begin
  TState(FState).on_Disconnected;
end;

procedure TFFTCPStream.on_Received(Sender: TObject; AData: pointer;
  ASize: integer);
var
  pPacketType : ^TPacketType absolute AData;
begin
  case pPacketType^ of
    ptPackage:  TState(FState).pt_Package(AData, ASize);
    ptOkOpen:   TState(FState).pt_OkOpen(AData, ASize);
    ptErOpen:   TState(FState).pt_ErOpen(AData, ASize);
    ptOkReopen: TState(FState).pt_OkReopen(AData, ASize);
    ptErReopen: TState(FState).pt_ErReopen(AData, ASize);
  end;
end;

procedure TFFTCPStream.on_Timer(Sender: TObject);
var
  Tick : Cardinal;
  Temp : integer;
begin
  Tick := GetTickCount;

  FCS.Enter;
  try
    if Tick &amp;gt; FOldTick then Temp := Tick - FOldTick
    else Temp := 0;

    if Temp &amp;gt;= _TimerInterval then begin
      FOldTick := Tick;
      TState(FState).on_Timer;
    end;
  finally
    FCS.Leave;
  end;

  Sleep(1);
end;

function TFFTCPStream.OpenFile(AHost: string; APort: integer;
  AFileName: string): boolean;
begin
  FIsOpened := false;
  FFileName := AFileName;

  Result := TState(FState).OpenFile(AHost, APort, AFileName);
  if Result then FTimer.Execute(on_Timer);
end;

procedure TFFTCPStream.send_Ask(AIndex: integer);
var
  Packet : TPacketAsk;
begin
  Packet.PacketType := ptAsk;
  Packet.Index := AIndex;

  FSocket.Send(@Packet, SizeOf(Packet));
end;

procedure TFFTCPStream.send_Close;
var
  PacketType : TPacketType;
begin
  PacketType := ptClose;
  FSocket.Send(@PacketType, SizeOf(PacketType));
end;

procedure TFFTCPStream.send_Open;
begin
  send_Text(ptOpen, FFileName);
end;

procedure TFFTCPStream.send_Reopen;
begin
  send_Text(ptReopen, FFileName);
end;

procedure TFFTCPStream.send_Text(APacketType: TPacketType; AText: AnsiString);
var
  pPacket : ^TPacket;
  iPacketSize : integer;
begin
  iPacketSize := SizeOf(TPacketType) + Length(AText) + 1;

  GetMem(pPacket, iPacketSize);
  try
    FillChar(pPacket^, iPacketSize, 0);

    pPacket^.PacketType := APacketType;

    if Length(AText) &amp;gt; 0 then Move(AText[1], pPacket^.DataStart, Length(AText));

    FSocket.SendNow(pPacket, iPacketSize);
  finally
    FreeMem(pPacket);
  end;
end;

procedure TFFTCPStream.SetState(AState: TObject);
var
  OldState, NewState : TObject;
begin
  FCS.Enter;
  try
    FOldTick := GetTickCount;

    OldState := FState;
    NewState := AState;

    TState(OldState).ActionOut(NewState);
    FState := NewState;
    TState(NewState).ActionIn(OldState);
  finally
    FCS.Leave;
  end;
end;

{ TState }

procedure TState.ActionIn(AOldState: TObject);
begin
  {$IFDEF DEBUG}
    OutputDebugString(PChar(Format(&#039;%s.ActionIn: OldState = %s&#039;, [Self.ClassName, AOldState.ClassName])));
  {$ENDIF}
end;

procedure TState.ActionOut(ANewState: TObject);
begin
  {$IFDEF DEBUG}
    OutputDebugString(PChar(Format(&#039;%s.ActionOut: NewState = %s&#039;, [Self.ClassName, ANewState.ClassName])));
  {$ENDIF}
end;

procedure TState.CloseFile;
begin
  {$IFDEF DEBUG}
    OutputDebugString(PChar(Format(&#039;%s.CloseFile: &#039;, [Self.ClassName])));
  {$ENDIF}
end;

constructor TState.Create(AFFTCPStream: TFFTCPStream);
begin
  inherited Create;

  FFFTCPStream := AFFTCPStream;
end;

procedure TState.on_Disconnected;
begin
  {$IFDEF DEBUG}
    OutputDebugString(PChar(Format(&#039;%s.on_Disconnected: &#039;, [Self.ClassName])));
  {$ENDIF}
end;

procedure TState.on_Timer;
begin
  {$IFDEF DEBUG}
    OutputDebugString(PChar(Format(&#039;%s.on_Timer: &#039;, [Self.ClassName])));
  {$ENDIF}
end;

function TState.OpenFile(AHost: string; APort: integer;
  AFileName: string): boolean;
begin
  {$IFDEF DEBUG}
    OutputDebugString(PChar(Format(&#039;%s.OpenFile: %s, %d, %s&#039;, [Self.ClassName, AHost, APort, AFileName])));
  {$ENDIF}

  Result := false;
end;

procedure TState.pt_ErOpen(AData: pointer; ASize: integer);
begin
  {$IFDEF DEBUG}
    OutputDebugString(PChar(Format(&#039;%s.pt_ErOpen: &#039;, [Self.ClassName])));
  {$ENDIF}
end;

procedure TState.pt_ErReopen(AData: pointer; ASize: integer);
begin
  {$IFDEF DEBUG}
    OutputDebugString(PChar(Format(&#039;%s.pt_ErReopen: &#039;, [Self.ClassName])));
  {$ENDIF}
end;

procedure TState.pt_OkOpen(AData: pointer; ASize: integer);
begin
  {$IFDEF DEBUG}
    OutputDebugString(PChar(Format(&#039;%s.pt_OkOpen: &#039;, [Self.ClassName])));
  {$ENDIF}
end;

procedure TState.pt_OkReopen(AData: pointer; ASize: integer);
begin
  {$IFDEF DEBUG}
    OutputDebugString(PChar(Format(&#039;%s.pt_OkReopen: &#039;, [Self.ClassName])));
  {$ENDIF}
end;

procedure TState.pt_Package(AData: pointer; ASize: integer);
begin
  {$IFDEF DEBUG}
    OutputDebugString(PChar(Format(&#039;%s.pt_Package: &#039;, [Self.ClassName])));
  {$ENDIF}
end;

{ TStateClosed }

function TStateClosed.OpenFile(AHost: string; APort: integer;
  AFileName: string): boolean;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  FFFTCPStream.FSocket.Host := AHost;
  FFFTCPStream.FSocket.Port := APort;
  FFFTCPStream.FSocket.Connect;

  Result := FFFTCPStream.FSocket.Connected;

  if Result then begin
    FFFTCPStream.SetState(FFFTCPStream.FStateConnected);
    FFFTCPStream.send_Open;
  end;
end;

{ TStateConnected }

procedure TStateConnected.CloseFile;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  FFFTCPStream.close_File;
  FFFTCPStream.SetState(FFFTCPStream.FStateClosed);
end;

procedure TStateConnected.on_Disconnected;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  FFFTCPStream.SetState(FFFTCPStream.FStateDisconnected);
end;

procedure TStateConnected.on_Timer;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  FFFTCPStream.send_Open;
end;

function TStateConnected.OpenFile(AHost: string; APort: integer;
  AFileName: string): boolean;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  raise Exception.Create(ClassName + &#039;.OpenFile: &#039;);
end;

procedure TStateConnected.pt_ErOpen(AData: pointer; ASize: integer);
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  FFFTCPStream.fire_OnFileOpenError;
  FFFTCPStream.SetState(FFFTCPStream.FStateClosed);
end;

procedure TStateConnected.pt_OkOpen(AData: pointer; ASize: integer);
var
  pPacket : ^TPacketOkOpen absolute AData;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  FFFTCPStream.FIsOpened := true;

  // TODO : Buffer.Clear;

  FFFTCPStream.SetState(FFFTCPStream.FStateOpened);
  FFFTCPStream.send_Ask(0);
  FFFTCPStream.fire_OnFileOpened(pPacket^.MediaInfo);
end;

{ TStateOpened }

procedure TStateOpened.CloseFile;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  FFFTCPStream.close_File;
  FFFTCPStream.SetState(FFFTCPStream.FStateClosed);
end;

procedure TStateOpened.on_Disconnected;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  FFFTCPStream.SetState(FFFTCPStream.FStateDisconnected);
end;

procedure TStateOpened.on_Timer;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  // TODO : FFFTCPStream.send_Ask(Buffer.NextIndex);
end;

function TStateOpened.OpenFile(AHost: string; APort: integer;
  AFileName: string): boolean;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  raise Exception.Create(ClassName + &#039;.OpenFile: &#039;);
end;

procedure TStateOpened.pt_Package(AData: pointer; ASize: integer);
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  // TODO : Buffer.Add();
end;

{ TStateDisconnected }

procedure TStateDisconnected.CloseFile;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  FFFTCPStream.close_File;
  FFFTCPStream.SetState(FFFTCPStream.FStateClosed);
end;

procedure TStateDisconnected.on_Timer;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  FFFTCPStream.FSocket.Connect;

  if FFFTCPStream.FSocket.Connected then begin
    if FFFTCPStream.FIsOpened then begin
      FFFTCPStream.SetState(FFFTCPStream.FStateReconnected);
      FFFTCPStream.send_Reopen;
    end else begin
      FFFTCPStream.SetState(FFFTCPStream.FStateConnected);
      FFFTCPStream.send_Open;
    end;
  end;
end;

function TStateDisconnected.OpenFile(AHost: string; APort: integer;
  AFileName: string): boolean;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  raise Exception.Create(ClassName + &#039;.OpenFile: &#039;);
end;

{ TStateReconnected }

procedure TStateReconnected.CloseFile;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  FFFTCPStream.close_File;
  FFFTCPStream.SetState(FFFTCPStream.FStateClosed);
end;

procedure TStateReconnected.on_Timer;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  FFFTCPStream.send_Reopen;
end;

function TStateReconnected.OpenFile(AHost: string; APort: integer;
  AFileName: string): boolean;
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  raise Exception.Create(ClassName + &#039;.OpenFile: &#039;);
end;

procedure TStateReconnected.pt_ErReopen(AData: pointer; ASize: integer);
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  FFFTCPStream.close_File;
end;

procedure TStateReconnected.pt_OkReopen(AData: pointer; ASize: integer);
begin
  {$IFDEF DEBUG}
    inherited;
  {$ENDIF}

  FFFTCPStream.SetState(FFFTCPStream.FStateOpened);
end;

end.&lt;/pre&gt;

&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&lt;div class=&quot;entry-ccl&quot; style=&quot;clear: both; text-align: right; margin-bottom: 10px&quot;&gt;
	&lt;img id=&quot;ccl-icon-184-0&quot; class=&quot;entry-ccl-by&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png&quot; alt=&quot;저작자 표시&quot;/&gt;
	&lt;img id=&quot;ccl-icon-184-1&quot; class=&quot;entry-ccl-nc&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black02.png&quot; alt=&quot;비영리&quot;/&gt;
	&lt;img id=&quot;ccl-icon-184-2&quot; class=&quot;entry-ccl-nd&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black03.png&quot; alt=&quot;변경 금지&quot;/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
		&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;
			&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align:center; padding-top:10px;&quot;&gt;
&lt;iframe src=&quot;http://www.facebook.com/plugins/like.php?href=ryulib.tistory.com/184&amp;amp;layout=standard&amp;amp;show_faces=true&amp;amp;width=310&amp;amp;action=like&amp;amp;font=tahoma&amp;amp;colorscheme=light&amp;amp;height=65&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; style=&quot;border:none; overflow:hidden; width:310px; height:65px;&quot; allowTransparency=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
</description>
			<category>디자인패턴</category>
			<author>류종택</author>
			<guid>http://ryulib.tistory.com/184</guid>
			<comments>http://ryulib.tistory.com/184#entry184comment</comments>
			<pubDate>Tue, 31 Jan 2012 12:56:37 +0900</pubDate>
		</item>
		<item>
			<title>SoundTouch 버그 수정</title>
			<link>http://ryulib.tistory.com/179</link>
			<description>VoiceZip(&lt;a href=&quot;http://ryulib.tistory.com/178&quot;&gt;http://ryulib.tistory.com/178&lt;/a&gt;)에 사용된 오픈 소스 중에&amp;nbsp;SoundTouch의 버그 수정 내용과 파일을 아래와 같이 첨부합니다. &amp;nbsp;(SoundTouch는 음성의 속도, 피치 등을 조절 할 수 있는 오픈 소스 라이브러리 입니다)&lt;br /&gt;
&lt;br /&gt;&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://ryulib.tistory.com/attachment/cfile6.uf@121CFF354F15EBBE2CFCE9.zip&quot;&gt;&lt;img src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/blog/image/extension/zip.gif&quot; alt=&quot;&quot; style=&quot;vertical-align: middle;&quot; /&gt; soundtouch-1.6.0.zip&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;br /&gt;출처:&amp;nbsp;
&lt;a href=&quot;http://www.surina.net/soundtouch/&quot;&gt;http://www.surina.net/soundtouch/&lt;/a&gt;&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;*&amp;nbsp;SoundTouchDLL.h 버그 수정&lt;br /&gt;
&lt;div&gt;SOUNDTOUCHDLL_API void soundtouch_putSamples(HANDLE h,&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; const &lt;font color=&quot;#e31600&quot;&gt;SAMPLETYPE&lt;/font&gt; *samples, &amp;nbsp; &amp;nbsp; &amp;nbsp; ///&amp;lt; Pointer to sample buffer.&lt;/div&gt;
&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; unsigned int numSamples &amp;nbsp; &amp;nbsp; ///&amp;lt; Number of samples in buffer. Notice&lt;/div&gt;
&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ///&amp;lt; that in case of stereo-sound a single sample&lt;/div&gt;
&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ///&amp;lt; contains data for both channels.&lt;/div&gt;
&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; );&lt;/div&gt;
&lt;br /&gt;&lt;br /&gt;
* 버그는 아니고, 16비트 샘플을 위해서 수정 한 부분,&amp;nbsp;STTypes.h&lt;br /&gt;
&lt;div&gt;// 16비트 샘플을 사용한다.&lt;/div&gt;
&lt;div&gt;#define SOUNDTOUCH_INTEGER_SAMPLES 1&lt;/div&gt;
&lt;br /&gt;&lt;div class=&quot;entry-ccl&quot; style=&quot;clear: both; text-align: right; margin-bottom: 10px&quot;&gt;
	&lt;img id=&quot;ccl-icon-179-0&quot; class=&quot;entry-ccl-by&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png&quot; alt=&quot;저작자 표시&quot;/&gt;
	&lt;img id=&quot;ccl-icon-179-1&quot; class=&quot;entry-ccl-nc&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black02.png&quot; alt=&quot;비영리&quot;/&gt;
	&lt;img id=&quot;ccl-icon-179-2&quot; class=&quot;entry-ccl-nd&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black03.png&quot; alt=&quot;변경 금지&quot;/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
		&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;
			&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align:center; padding-top:10px;&quot;&gt;
&lt;iframe src=&quot;http://www.facebook.com/plugins/like.php?href=ryulib.tistory.com/179&amp;amp;layout=standard&amp;amp;show_faces=true&amp;amp;width=310&amp;amp;action=like&amp;amp;font=tahoma&amp;amp;colorscheme=light&amp;amp;height=65&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; style=&quot;border:none; overflow:hidden; width:310px; height:65px;&quot; allowTransparency=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
</description>
			<category>etc</category>
			<author>류종택</author>
			<guid>http://ryulib.tistory.com/179</guid>
			<comments>http://ryulib.tistory.com/179#entry179comment</comments>
			<pubDate>Wed, 18 Jan 2012 06:47:54 +0900</pubDate>
		</item>
		<item>
			<title>음성 채팅용 라이브러리 VoiceZip</title>
			<link>http://ryulib.tistory.com/178</link>
			<description>VoiceZip은 음성 채팅을 위한 라이브러리 입니다. &amp;nbsp;주요 특징은 아래와 같습니다.&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc; &quot;&gt;
&lt;li&gt;간단한 인터페이스&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;부드러운 음성 지연 방지 (&lt;a href=&quot;http://www.acoustics.hut.fi/publications/files/theses/lemmetty_mst/chap5.html&quot; target=&quot;_blank&quot; title=&quot;[http://www.acoustics.hut.fi/publications/files/theses/lemmetty_mst/chap5.html]로 이동합니다.&quot;&gt;PSOLA&lt;/a&gt; 알고리즘 적용)&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Speex 코덱 사용&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
여러 유닛과 클래스가 제공되지만, 중요 클래스는 [소스 1]의 두 개 입니다.&lt;br /&gt;
&lt;br /&gt;
[소스 1]&lt;br /&gt;

&lt;pre name=&quot;code&quot; class=&quot;brush: delphi;  highlight: []; toolbar: false;&quot;&gt;  TVoiceDataEvent = procedure (Sender:TObject; AData:pointer; ASize,AVolume:integer) of object;

  TVoiceRecorder = class (TComponent)
  private
  public
    procedure Start(AMicDeviceID: Integer = -1);
    procedure Stop;
  published
    property WaveVolume: integer read FWaveVolume;
    property Volume: Single read GetVolume write SetVolume;
    property OnNewData : TVoiceDataEvent read FOnNewData write FOnNewData;
  end;
  
  TVoicePlayer = class (TComponent)
  private
  public
    procedure Start;
    procedure Stop;

    procedure DataIn(AData:pointer; ASize:integer); overload;
    procedure DataIn(AStream:TStream); overload;
  published
    property SaveToBuffer : Boolean read FSaveToBuffer write FSaveToBuffer;
    property Mute: Boolean read FMute write FMute;
    property WaveVolume: integer read FWaveVolume;
    property Volume: Single read GetVolume write SetVolume;
    property Tempo : integer read GetTempo write SetTempo;
    property Duration : int64 read GetDuration;
    property DurationLimit : int64 read GetDurationLimit write SetDurationLimit;
  end;
&lt;/pre&gt;3-12: TVoiceRecorder는 음성 압축을 위한 클래스 입니다. &amp;nbsp;Start 메소드를 실행하면 녹음 장치로부터 음원을 캡쳐해서 압축한 뒤에 주기(20ms)적으로 OnNewData 이벤트를 발생시킵니다.&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc; &quot;&gt;&lt;li&gt;WaveVolume: 녹음된 원본의 볼륨 정보입니다.&lt;br /&gt;
&lt;/li&gt;&lt;li&gt;Volume: 녹음&amp;nbsp;볼륨을 조절합니다. &amp;nbsp;1.0은 원음. &amp;nbsp;2.0은 2배 증폭.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;14-30:&amp;nbsp;TVoicePlayer는 압축된 데이터를 해제하고 재생 장치로 출력하는 클래스입니다. &amp;nbsp;Start 메소드를 먼저 실행해야 합니다. &amp;nbsp;이후,&amp;nbsp;
TVoiceRecorder에서 압축된 데이터를 DataIn 메소드로 입력하면, 압축이 해제되면서 재생됩니다.&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc; &quot;&gt;&lt;li&gt;SaveToBuffer: true가 되면 버퍼에 저장만 할 뿐 재생하지 않습니다. &amp;nbsp;테스트 등의 목적으로 음성을 지연시키거나 버퍼링을 하기 위한 메소드 입니다.&lt;br /&gt;
&lt;/li&gt;&lt;li&gt;Mute: 음 소거&lt;br /&gt;
&lt;/li&gt;&lt;li&gt;WaveVolume: 전달받은 원본의 볼륨 정보입니다.&lt;br /&gt;
&lt;/li&gt;&lt;li&gt;Volume: 재생 볼륨을 조절합니다.&amp;nbsp;&amp;nbsp;1.0은 원음. &amp;nbsp;2.0은 2배 증폭.&lt;br /&gt;
&lt;/li&gt;&lt;li&gt;Tempo: 재생 속도를 빠르게 합니다. &amp;nbsp;음성의 피치는 그대로 유지하여 자연스러운 소리가 나도록 합니다.&lt;br /&gt;
&lt;/li&gt;&lt;li&gt;Duration: 현재 버퍼에 있는 데이터의 양을 시간으로 표기한 것 입니다. &amp;nbsp;지연의 정도를 측정 할 수 있습니다. &amp;nbsp;(ms 단위)&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&lt;/li&gt;&lt;li&gt;DurationLimit: 버퍼에 지연 될 수 있는 최대의 시간을 조절합니다. &amp;nbsp;이 보다 지연된 데이터는 재생 속도를 변경하여 부드럽게 제거됩니다.&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
아래 첨부에는 간단한 예제가 들어 있습니다. &amp;nbsp;컴파일은 되지 않고, 실행 해 볼 수는 있습니다.&lt;br /&gt;
&lt;br /&gt;&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://ryulib.tistory.com/attachment/cfile29.uf@182A1D4F4F15E90623EB10.zip&quot;&gt;&lt;img src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/blog/image/extension/zip.gif&quot; alt=&quot;&quot; style=&quot;vertical-align: middle;&quot; /&gt; UDP Sample.zip&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;br /&gt;&lt;span style=&quot;text-align: center; &quot;&gt;각각의 프로그램을 실행하고 주소를 설정한 후&amp;nbsp;&lt;/span&gt;
&lt;span style=&quot;text-align: center; &quot;&gt;Sender.exe의 전송 버턴을 누르면 음성이 전달됩니다. &amp;nbsp;같은 장비에서 테스트할 때에는 피드백에 의한 하울링을 유의하시기 바랍니다.&lt;br /&gt;
&lt;br /&gt;&lt;div style=&quot;text-align: -webkit-auto;&quot;&gt;
Receiver.exe의 btStop을 클릭하시면, 재생이 중지되고 버퍼에 음성 데이터를 쌓게 됩니다. &amp;nbsp;고의적으로 음성 지연을 일으키게 되며, 다시 btPlay를 하면 지정 된&amp;nbsp;DurationLimit까지 지연을 자연스럽게 제거해 나갑니다. &amp;nbsp;데모에는 1초로 지정되어 있으며, 실제 음성 채팅에서는 250(0.25초) 미만으로 설정하시면 됩니다.&amp;nbsp;&lt;/div&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://cfile22.uf.tistory.com/original/197BE44B4F15E955243275&quot; rel=&quot;lightbox&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://cfile22.uf.tistory.com/image/197BE44B4F15E955243275&quot; alt=&quot;&quot; filemime=&quot;image/jpeg&quot; filename=&quot;K-20120118-63341-1.png&quot; height=&quot;120&quot; width=&quot;280&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;text-align: center;&quot;&gt;
[그림 1] Receiver.exe의 화면&lt;/div&gt;
&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://cfile25.uf.tistory.com/original/207BE44B4F15E9552560F5&quot; rel=&quot;lightbox&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://cfile25.uf.tistory.com/image/207BE44B4F15E9552560F5&quot; alt=&quot;&quot; filemime=&quot;image/jpeg&quot; filename=&quot;K-20120118-63355-1.png&quot; height=&quot;120&quot; width=&quot;280&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;[그림 2]&amp;nbsp;Sender.exe의 화면&lt;/div&gt;
&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;entry-ccl&quot; style=&quot;clear: both; text-align: right; margin-bottom: 10px&quot;&gt;
	&lt;img id=&quot;ccl-icon-178-0&quot; class=&quot;entry-ccl-by&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png&quot; alt=&quot;저작자 표시&quot;/&gt;
	&lt;img id=&quot;ccl-icon-178-1&quot; class=&quot;entry-ccl-nc&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black02.png&quot; alt=&quot;비영리&quot;/&gt;
	&lt;img id=&quot;ccl-icon-178-2&quot; class=&quot;entry-ccl-nd&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black03.png&quot; alt=&quot;변경 금지&quot;/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
		&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;
			&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align:center; padding-top:10px;&quot;&gt;
&lt;iframe src=&quot;http://www.facebook.com/plugins/like.php?href=ryulib.tistory.com/178&amp;amp;layout=standard&amp;amp;show_faces=true&amp;amp;width=310&amp;amp;action=like&amp;amp;font=tahoma&amp;amp;colorscheme=light&amp;amp;height=65&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; style=&quot;border:none; overflow:hidden; width:310px; height:65px;&quot; allowTransparency=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
</description>
			<category>VoiceZip</category>
			<author>류종택</author>
			<guid>http://ryulib.tistory.com/178</guid>
			<comments>http://ryulib.tistory.com/178#entry178comment</comments>
			<pubDate>Wed, 18 Jan 2012 06:38:22 +0900</pubDate>
		</item>
		<item>
			<title>ThreadPool</title>
			<link>http://ryulib.tistory.com/177</link>
			<description>쓰레드 클래스를 생성하지 않고 함수 호출만으로 쓰레드를 사용하기 위한 유닛입니다. &amp;nbsp;&quot;RyuLib for Delphi&quot; 소스는 아래의 링크에서 받으시기 바랍니다.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://ryulib.tistory.com/notice/11&quot;&gt;http://ryulib.tistory.com/notice/11&lt;/a&gt;&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
사용법은 [소스 1]과 같습니다.&lt;br /&gt;
&lt;br /&gt;
[소스 1]&lt;br /&gt;

&lt;pre name=&quot;code&quot; class=&quot;brush: delphi;  highlight: []; toolbar: false;&quot;&gt;function InternalThreadFunction(lpThreadParameter: Pointer): Integer; stdcall;
begin
  Result := 0;

  // TOO : 
end;

procedure TfmMain.btCalcClick(Sender: TObject);
begin
  QueueWorkItem(InternalThreadFunction, nil);
end;
&lt;/pre&gt;


10: 새로운 함수를 쓰레드 풀에 넣어서 실행 시킬 수 있을 때 함수가 실행됩니다. &amp;nbsp;쓰레드 생성 등에 대한 오버 헤드가 없습니다.&lt;br /&gt;
&lt;br /&gt;
1-6: 함수의 형태는 1-6: 라인과 같아야 합니다.&lt;br /&gt;
&lt;br /&gt;
1:&amp;nbsp;lpThreadParameter 인자는 쓰레드와 호출 객체가 서로 공유 할 데이터나 객체를 전달 받기 위한 것입니다. &amp;nbsp;필요없으면 사용하지 않아도 됩니다.&lt;br /&gt;
&lt;br /&gt;
ThreadPool 유닛에는 [소스 2]와 같은 형태의 함수가 제공됩니다. &amp;nbsp;각각 필요한 작업에 따라 선택하시면 됩니다.&lt;br /&gt;
&lt;br /&gt;
[소스 2]&lt;br /&gt;

&lt;pre name=&quot;code&quot; class=&quot;brush: delphi;  highlight: []; toolbar: false;&quot;&gt;function QueueWorkItem(Func:TThreadStartRoutine; Context:Pointer):boolean;
function QueueIOWorkItem(Func:TThreadStartRoutine; Context:Pointer):boolean;
function QueueUIWorkItem(Func:TThreadStartRoutine; Context:Pointer):boolean;
&lt;/pre&gt;

&lt;br /&gt;
&lt;br /&gt;
[소스 3]은 1부터 n까지 더하는 프로그램을 멀티 쓰레드로 작성해 본 것 입니다. &amp;nbsp;속도를 줄이기 위해서 중간에 Sleep(1)로 쉬도록 했습니다. &amp;nbsp;[그림 1]은 실행 결과 화면이며, 1000 --&amp;gt; 100 --&amp;gt; 10 순으로 계산을 했지만, 멀티 쓰레드이다 보니 먼저 계산 된 것부터 표시되고 있습니다. &amp;nbsp;가장 처음 입력한 수는 좀 큰 수였는데, 한 참 동안 계산이 안끝나서 중간에 캡쳐된 것을 올립니다.&lt;br /&gt;
&lt;br /&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://cfile5.uf.tistory.com/original/12534C3E4F15E17D25D997&quot; rel=&quot;lightbox&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://cfile5.uf.tistory.com/image/12534C3E4F15E17D25D997&quot; alt=&quot;&quot; filemime=&quot;image/jpeg&quot; filename=&quot;result.png&quot; height=&quot;328&quot; width=&quot;480&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
[그림 1] 실행 결과&lt;/div&gt;
&lt;br /&gt;
&lt;p&gt;&lt;/p&gt;
&lt;br /&gt;
[소스 3]&lt;br /&gt;

&lt;pre name=&quot;code&quot; class=&quot;brush: delphi;  highlight: []; toolbar: false;&quot;&gt;unit _fmMain;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Samples.Spin;

type
  TfmMain = class(TForm)
    btCalc: TButton;
    ListBox1: TListBox;
    SpinEdit1: TSpinEdit;
    procedure btCalcClick(Sender: TObject);
  private
    procedure do_WM_User(var Msg:TMessage); message WM_User;
  public
  end;

var
  fmMain: TfmMain;

implementation

uses
  ThreadPool;

{$R *.dfm}

type
  TContext = class
    n : integer;
    Handle : THandle;
  end;

function InternalThreadFunction(lpThreadParameter: Pointer): Integer; stdcall;
var
  Loop, Sum : integer;
  Context : TContext absolute lpThreadParameter;
begin
  Result := 0;

  Sum := 0;
  for Loop := 1 to Context.n do begin
    Sum := Sum + Loop;
    Sleep(1);
  end;

  PostMessage(Context.Handle, WM_User, Sum, Context.n);
end;

procedure TfmMain.btCalcClick(Sender: TObject);
var
  Context : TContext;
begin
  Context := TContext.Create;
  try
    Context.n := SpinEdit1.Value;
    Context.Handle := Self.Handle;
    QueueWorkItem(InternalThreadFunction, Context);
  finally
    Context.Free;
  end;
end;

procedure TfmMain.do_WM_User(var Msg: TMessage);
begin
  ListBox1.Items.Add(Format(&#039;Sum = %d, n = %d&#039;, [Msg.WParam, Msg.LParam]));
end;

end.
&lt;/pre&gt;

&amp;nbsp;&lt;div class=&quot;entry-ccl&quot; style=&quot;clear: both; text-align: right; margin-bottom: 10px&quot;&gt;
	&lt;img id=&quot;ccl-icon-177-0&quot; class=&quot;entry-ccl-by&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png&quot; alt=&quot;저작자 표시&quot;/&gt;
	&lt;img id=&quot;ccl-icon-177-1&quot; class=&quot;entry-ccl-nc&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black02.png&quot; alt=&quot;비영리&quot;/&gt;
	&lt;img id=&quot;ccl-icon-177-2&quot; class=&quot;entry-ccl-nd&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black03.png&quot; alt=&quot;변경 금지&quot;/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
		&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;
			&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align:center; padding-top:10px;&quot;&gt;
&lt;iframe src=&quot;http://www.facebook.com/plugins/like.php?href=ryulib.tistory.com/177&amp;amp;layout=standard&amp;amp;show_faces=true&amp;amp;width=310&amp;amp;action=like&amp;amp;font=tahoma&amp;amp;colorscheme=light&amp;amp;height=65&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; style=&quot;border:none; overflow:hidden; width:310px; height:65px;&quot; allowTransparency=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
</description>
			<category>RyuLib for Delphi</category>
			<author>류종택</author>
			<guid>http://ryulib.tistory.com/177</guid>
			<comments>http://ryulib.tistory.com/177#entry177comment</comments>
			<pubDate>Wed, 18 Jan 2012 06:05:31 +0900</pubDate>
		</item>
		<item>
			<title>WowCast 2.0 beta - 무료 증권방송 솔루션</title>
			<link>http://ryulib.tistory.com/176</link>
			<description>&lt;p style=&quot;margin:0&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://ryulib.tistory.com/attachment/cfile4.uf@121015354F198F093048DD.zip&quot;&gt;&lt;img src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/blog/image/extension/zip.gif&quot; alt=&quot;&quot; style=&quot;vertical-align: middle;&quot; /&gt; 20120121_-_2.0_beta.zip&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;br /&gt;
무료로 사용할 수 있는 증권방송 솔루션 WowCast 입니다. &amp;nbsp;현재는 베타 테스트 버전이며 중요 특징은 아래와 같습니다. &amp;nbsp;기존의 버전보다 압축률을 개선하였으며, 정식 버전은 기능을 보강하여 3월 이전에 발표 할 예정입니다. &amp;nbsp;정식 버전 발표 시에는 디자인도 신경 쓰겠습니다 ^^;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc; &quot;&gt;
&lt;li&gt;사용자 수 제한은 없습니다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;로그인 시 아이디와 암호를 아무것이나 입력해도 됩니다. &amp;nbsp;같은 아이디를 입력하면 기존 접속자는 접속이 끊어집니다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;네트워크 속도가 느린 사용자를 지원하기 위해서 Receiver는 캐싱을 이용합니다. &amp;nbsp;한 번 보낸 프레임(화면조각)은 최대한 다시 받지 않도록 합니다. &amp;nbsp;이때문에, Server는 CPU와 메모리를 많이 사용합니다. &amp;nbsp; &amp;nbsp;Server가 실행 될 PC에서는 최소 1GB 이상의 사용 가능한 메모리가 있어야 합니다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;서버의 캐싱 계산을 끄면, 서버가 CPU를 덜 사용하게 됩니다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;최상의 품질을 위해서 서버는 모든 Receiver 접속 마다 따로 화면을 압축합니다.&amp;nbsp;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;음성 지연은 1초로 설정되어 있습니다. &amp;nbsp;음성지연을 부드럽게 줄이기 위해서 &lt;a href=&quot;http://en.wikipedia.org/wiki/PSOLA&quot; target=&quot;_blank&quot; title=&quot;[http://en.wikipedia.org/wiki/PSOLA]로 이동합니다.&quot;&gt;PSOLA&lt;/a&gt;&amp;nbsp;알고리즘을 사용합니다. &amp;nbsp;추후 사용자 마다 최적화된 음성 버퍼 시간을 자동으로 계산 하여 적용하도록 할 예정입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;Server.exe 실행&lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc; &quot;&gt;
&lt;li&gt;Server.exe는 아무런 외부 dll이 필요 없습니다. &amp;nbsp;즉, Server.exe 만을 복사해서 실행하시면 됩니다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;포트는 3690, 3691을 사용합니다.&lt;/li&gt;
&lt;li&gt;Server를 실행하면 [그림 1]과 같이 트래이 아이콘으로 등록됩니다. &amp;nbsp;아이콘 위에서 마우스 오른쪽 버턴을 클릭하시면 메뉴가 나타납니다. &amp;nbsp;현재는 &quot;프로그램 종료&quot; 만 실행됩니다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;CPU 사용률이 부담스러울 때는 같은 폴더에 Server.ini 파일을 만드시고, [Options] 세션에 &#039;UseCache=0&#039;을 추가해주시면 됩니다. &amp;nbsp;캐시를 사용하지 않게 됩니다.&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://cfile29.uf.tistory.com/original/132C0D3F4F151FF30B0EDA&quot; rel=&quot;lightbox&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://cfile29.uf.tistory.com/image/132C0D3F4F151FF30B0EDA&quot; alt=&quot;&quot; filemime=&quot;image/jpeg&quot; filename=&quot;tray.png&quot; height=&quot;164&quot; width=&quot;218&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;text-align: center; &quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
[그림 1] 서버 실행 이후&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Sender.exe 실행&lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc; &quot;&gt;
&lt;li&gt;ijl15Dec.dll,&amp;nbsp;SoundTouch.dll 를 제외한 나머지 dll이 필요합니다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;실행하면 [그림 2]와 같이 로그인 창이 나타납니다. &amp;nbsp;서버가 실행된 주소와 사용자 아이디 암호를 입력하시고, 로그인하시면 됩니다. &amp;nbsp;아이디와 암호는 아무거나 입력하셔도 됩니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://cfile3.uf.tistory.com/original/12645E444F15027B28204D&quot; rel=&quot;lightbox&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://cfile3.uf.tistory.com/image/12645E444F15027B28204D&quot; alt=&quot;&quot; filemime=&quot;image/jpeg&quot; filename=&quot;K-20120117-140431-0.png&quot; height=&quot;205&quot; width=&quot;346&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
[그림 2] 로그인 화면&lt;/div&gt;
&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc; &quot;&gt;
&lt;li&gt;로그인이 완료되면 [그림 3]과 같은 창이 나타납니다. &amp;nbsp;이때부터 PC의 첫 번째 모니터의 화면이 서버로 전송됩니다. &amp;nbsp;듀얼 모니터가 아닌 경우에는 [그림 3] 창이 함께 전송되기 때문에 불편합니다. &amp;nbsp;현재는 듀얼 모니터를 기준으로 솔루션이 작성되어 있습니다. &amp;nbsp;이 부분은 정식 버전 때 보강하도록 하겠습니다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&quot;화이트&amp;nbsp;보드&quot; 버턴을 클릭하시면, 화면에 판서를 할 수 있는 상태가 됩니다. &amp;nbsp;우측 상단에 나타나는 버턴을 이용해서 판서하거나 판서를 지울 수가 있습니다. &amp;nbsp;화이트 보드 기능은 정식 버전 때 보강하도록 하겠습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://cfile9.uf.tistory.com/original/13645E444F15027B2990AC&quot; rel=&quot;lightbox&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://cfile9.uf.tistory.com/image/13645E444F15027B2990AC&quot; alt=&quot;&quot; filemime=&quot;image/jpeg&quot; filename=&quot;K-20120117-140405-6.png&quot; height=&quot;608&quot; width=&quot;501&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
[그림 3] 강사용 프로그램의 화면&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Receiver.exe 실행&lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc; &quot;&gt;
&lt;li&gt;ijl15Enc.dll 이외의 모든 dll이 필요합니다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;실행하시면 [그림 2]와 같이 로그인 창이 나타납니다. &amp;nbsp;이후 사용법은 동일합니다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;로그인이 완료되면, [그림 4]와 같이 수강생용 프로그램이 나타납니다.&lt;br /&gt;
프로그램의 화면 크기에 맞춰서 전송된 화면을 작게 만들어 주기 때문에 CPU를 많이 사용 할 수 있습니다. &amp;nbsp;화면을 더블 클릭하시면 원본 크기로 보여주며, CPU 사용률도 낮아집니다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;화면이 원본 크기 일 때는 마우스 드래그를 이용하여 화면을 이동 할 수 있습니다.&lt;/li&gt;
&lt;li&gt;화면 아래 숫자 버턴을 클릭하시면 화면 배열이 달라집니다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;화면 아래 스크롤 바를 움직이면 출력되는 음성의 볼륨을 조절 하실 수 있습니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://cfile5.uf.tistory.com/original/11645E444F15027B2A8D9E&quot; rel=&quot;lightbox&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://cfile5.uf.tistory.com/image/11645E444F15027B2A8D9E&quot; alt=&quot;&quot; filemime=&quot;&quot; filename=&quot;cfile5.uf@11645E444F15027B2A8D9E.png&quot; height=&quot;454&quot; width=&quot;600&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
[그림 4] 수강생의 실행 화면&lt;/div&gt;
&lt;br /&gt;&lt;div class=&quot;entry-ccl&quot; style=&quot;clear: both; text-align: right; margin-bottom: 10px&quot;&gt;
	&lt;img id=&quot;ccl-icon-176-0&quot; class=&quot;entry-ccl-by&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png&quot; alt=&quot;저작자 표시&quot;/&gt;
	&lt;img id=&quot;ccl-icon-176-1&quot; class=&quot;entry-ccl-nc&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black02.png&quot; alt=&quot;비영리&quot;/&gt;
	&lt;img id=&quot;ccl-icon-176-2&quot; class=&quot;entry-ccl-nd&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black03.png&quot; alt=&quot;변경 금지&quot;/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
		&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;
			&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align:center; padding-top:10px;&quot;&gt;
&lt;iframe src=&quot;http://www.facebook.com/plugins/like.php?href=ryulib.tistory.com/176&amp;amp;layout=standard&amp;amp;show_faces=true&amp;amp;width=310&amp;amp;action=like&amp;amp;font=tahoma&amp;amp;colorscheme=light&amp;amp;height=65&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; style=&quot;border:none; overflow:hidden; width:310px; height:65px;&quot; allowTransparency=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
</description>
			<category>프로그램 배포</category>
			<category>강의</category>
			<category>온라인</category>
			<category>증권방송</category>
			<author>류종택</author>
			<guid>http://ryulib.tistory.com/176</guid>
			<comments>http://ryulib.tistory.com/176#entry176comment</comments>
			<pubDate>Tue, 17 Jan 2012 14:09:36 +0900</pubDate>
		</item>
		<item>
			<title>MinGW에서 libfaac 설치</title>
			<link>http://ryulib.tistory.com/173</link>
			<description>&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://ryulib.tistory.com/attachment/cfile3.uf@166B414A4F10326225FB9F.patch&quot;&gt;&lt;img src=&quot;http://i1.daumcdn.net/cfs.tistory/v/110706133414/blog/image/extension/unknown.gif&quot; alt=&quot;&quot; style=&quot;vertical-align: middle;&quot; /&gt; faac-1.26.patch&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://ryulib.tistory.com/attachment/cfile8.uf@1608B04A4F1032630CB272.gz&quot;&gt;&lt;img src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/blog/image/extension/gz.gif&quot; alt=&quot;&quot; style=&quot;vertical-align: middle;&quot; /&gt; faac-1.26.tar.gz&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://ryulib.tistory.com/attachment/cfile5.uf@130BE34A4F103264091CFC.patch&quot;&gt;&lt;img src=&quot;http://i1.daumcdn.net/cfs.tistory/v/110706133414/blog/image/extension/unknown.gif&quot; alt=&quot;&quot; style=&quot;vertical-align: middle;&quot; /&gt; faad2-2.6.1.patch&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://ryulib.tistory.com/attachment/cfile23.uf@1577DB4A4F1032671A1761.gz&quot;&gt;&lt;img src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/blog/image/extension/gz.gif&quot; alt=&quot;&quot; style=&quot;vertical-align: middle;&quot; /&gt; faad2-2.6.1.tar.gz&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;br /&gt;
&lt;div&gt;
$ patch -p0 &amp;lt; faac-1.26.patch&lt;/div&gt;
&lt;div&gt;
$ cd faac&lt;/div&gt;
&lt;div&gt;
$ ./bootstrap&lt;/div&gt;
&lt;div&gt;
$ ./configure --prefix=/mingw --enable-shared --disable-static&lt;/div&gt;
&lt;div&gt;
$ make LDFLAGS=&quot;-no-undefined&quot;&lt;/div&gt;
&lt;div&gt;
$ make install&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;div&gt;
$ patch -p0 &amp;lt; faad2-2.6.1.patch&lt;/div&gt;
&lt;div&gt;
$ cd faad2&lt;/div&gt;
&lt;div&gt;
$ ./bootstrap&lt;/div&gt;
&lt;div&gt;
$ ./configure --prefix=/mingw --enable-shared --disable-static&lt;/div&gt;
&lt;div&gt;
$ make LDFLAGS=&quot;-no-undefined&quot;&lt;/div&gt;
&lt;div&gt;
$ make install&lt;br /&gt;
&lt;br /&gt;ffmpeg에서 빌드 옵션에 넣으니 문제가 발생.&lt;br /&gt;
아래 주소 참고!&lt;br /&gt;
&lt;a href=&quot;http://ffmpeg.org/pipermail/ffmpeg-devel/2008-August/042579.html&quot;&gt;&lt;br /&gt;
http://ffmpeg.org/pipermail/ffmpeg-devel/2008-August/042579.html&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;faac.h에&amp;nbsp;WIN32가 정의 되지 않은 것이 문제.&lt;br /&gt;
&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;entry-ccl&quot; style=&quot;clear: both; text-align: right; margin-bottom: 10px&quot;&gt;
	&lt;img id=&quot;ccl-icon-173-0&quot; class=&quot;entry-ccl-by&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png&quot; alt=&quot;저작자 표시&quot;/&gt;
	&lt;img id=&quot;ccl-icon-173-1&quot; class=&quot;entry-ccl-nc&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black02.png&quot; alt=&quot;비영리&quot;/&gt;
	&lt;img id=&quot;ccl-icon-173-2&quot; class=&quot;entry-ccl-nd&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black03.png&quot; alt=&quot;변경 금지&quot;/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
		&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;
			&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align:center; padding-top:10px;&quot;&gt;
&lt;iframe src=&quot;http://www.facebook.com/plugins/like.php?href=ryulib.tistory.com/173&amp;amp;layout=standard&amp;amp;show_faces=true&amp;amp;width=310&amp;amp;action=like&amp;amp;font=tahoma&amp;amp;colorscheme=light&amp;amp;height=65&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; style=&quot;border:none; overflow:hidden; width:310px; height:65px;&quot; allowTransparency=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
</description>
			<category>MinGW</category>
			<author>류종택</author>
			<guid>http://ryulib.tistory.com/173</guid>
			<comments>http://ryulib.tistory.com/173#entry173comment</comments>
			<pubDate>Fri, 13 Jan 2012 22:32:38 +0900</pubDate>
		</item>
		<item>
			<title>DeskTop Share - PC 화면 공유 (서버 추가)</title>
			<link>http://ryulib.tistory.com/171</link>
			<description>&lt;p style=&quot;margin:0&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin:0&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://ryulib.tistory.com/attachment/cfile23.uf@192190354F0EF68E24D3C4.zip&quot;&gt;&lt;img src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/blog/image/extension/zip.gif&quot; alt=&quot;&quot; style=&quot;vertical-align: middle;&quot; /&gt; DeskTop Share.zip&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;br /&gt;
DeskCam 라이브러리로 만든 PC 화면 공유 데모 입니다. &amp;nbsp;한 사람의 PC 화면을 다수의 다른 사용자에게 전송하는 데모입니다. &amp;nbsp;온라인 강의나 증권 방송 등에 사용되는 형태입니다. &amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;위의 첨부 파일의 압축을 해제하시면 아래와 같이 두 종류의 실행 파일이 나옵니다.&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc; &quot;&gt;
&lt;li&gt;Sender.exe&lt;br /&gt;
&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;자신의 화면을 다른 사용자에게 전송합니다.&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;최소한의 트래픽으로 다수의 사용자에게 전송하기 위해 계산을 많이 합니다. &amp;nbsp;CPU를 다른 데모보다 많이 사용합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;초당 전송 프레임 수 또는 Bandwidth를 제한 할 수 있으나, 데모는 아무런 제한을 두지 않았습니다. &amp;nbsp;따라서, 성능이 낮은 PC에서는 버거울 수 있습니다. &amp;nbsp;네트워크 트래픽도 문제가 될 수 있습니다. &amp;nbsp;실제 상황에서는 자신의 네트워크 상황에 맞춰서&amp;nbsp;Bandwidth를 제한하여야 합니다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;화면에 애니메이션 효과 등을 사용하지 않아야 효율적인 화면 전송이 됩니다. &amp;nbsp;화려할 수록 화면 전송 속도는 떨어집니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Receiver.exe&amp;nbsp;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Sender.exe가 실행 중이라면 해당 PC의 화면이 표시됩니다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Caption에는 화면이 한 번 바뀔 때마다 전송 받은 데이터 양을 표시합니다. &amp;nbsp;앞의 수치는 한 화면 당 받은 데이터의 크기이며, 두 번 째 수치는 캐시를 이용해서 절약된 데이터의 크기입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Server.exe&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;중계 용 서버입니다. &amp;nbsp;다른 실행 파일과 다른 PC에서 실행된다면, 각 실행 파일의 ini 파일을 열어서 서버의 주소와 포트를 지정해 주어야 합니다.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;서버는 모든 Receiver 마다 별도의 인코더를 둬서 최적화된 화면을 전송합니다. &amp;nbsp;이 때문에 CPU를 많이 사용하게 됩니다. &amp;nbsp;Server.ini에서는 캐시 계산을 하지않도록 해서 CPU 사용률을 최소화 할 수 있습니다.&amp;nbsp;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;어느 수준까지 메모리를 계속 사용하게 됩니다. &amp;nbsp;접속자 수에 따라 다르지만, 400MB 이상 사용하게 되므로, 충분한 메모리를 확보하셔야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
기존의 버전보다 현저히 낮은 트래픽에서도 안정적으로 화면이 전달되도록 하였습니다. &amp;nbsp;또한, 각자의 네트워크 트래픽 상황에 따라 프레임수가 달라지도록 되어 있습니다. &amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
예전 버전과 가장 크게 다른 점은, 서버에서 모든&amp;nbsp;Receiver.exe에게 개별로 화면을 압축해서 보낸다는 점 입니다. &amp;nbsp;그러면서도 서버에 부하가 가지 않도록 구성되어 있습니다. &amp;nbsp;즉, 서버에 컨넥션 마다 인코더를 두고 있는 셈입니다. &amp;nbsp;하지만, 압축하는 자원을 최대한 공유하도록 설계되어 크게 부하가 걸리지 않도록 설계하였습니다.&lt;br /&gt;&lt;div class=&quot;entry-ccl&quot; style=&quot;clear: both; text-align: right; margin-bottom: 10px&quot;&gt;
	&lt;img id=&quot;ccl-icon-171-0&quot; class=&quot;entry-ccl-by&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png&quot; alt=&quot;저작자 표시&quot;/&gt;
	&lt;img id=&quot;ccl-icon-171-1&quot; class=&quot;entry-ccl-nc&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black02.png&quot; alt=&quot;비영리&quot;/&gt;
	&lt;img id=&quot;ccl-icon-171-2&quot; class=&quot;entry-ccl-nd&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black03.png&quot; alt=&quot;변경 금지&quot;/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
		&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;
			&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align:center; padding-top:10px;&quot;&gt;
&lt;iframe src=&quot;http://www.facebook.com/plugins/like.php?href=ryulib.tistory.com/171&amp;amp;layout=standard&amp;amp;show_faces=true&amp;amp;width=310&amp;amp;action=like&amp;amp;font=tahoma&amp;amp;colorscheme=light&amp;amp;height=65&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; style=&quot;border:none; overflow:hidden; width:310px; height:65px;&quot; allowTransparency=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
</description>
			<category>DeskCam</category>
			<author>류종택</author>
			<guid>http://ryulib.tistory.com/171</guid>
			<comments>http://ryulib.tistory.com/171#entry171comment</comments>
			<pubDate>Fri, 06 Jan 2012 00:08:07 +0900</pubDate>
		</item>
		<item>
			<title>비리 의혹에 대한 처리 결과</title>
			<link>http://ryulib.tistory.com/170</link>
			<description>비리 의혹을 제기하는 원문 :&amp;nbsp;
&lt;a href=&quot;http://ryulib.tistory.com/165&quot;&gt;http://ryulib.tistory.com/165&lt;/a&gt;&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
결과적으로 의혹으로 끝났습니다. &amp;nbsp;관심 주신 분들에게 죄송합니다. &amp;nbsp;하지만, 참으로 아쉽네요. &amp;nbsp;답변의 내용을 보면서 개인적으로 정리하자면 다음과 같습니다. &amp;nbsp;(원문을 공개해도 되는 지 몰라서)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
서울시 감사는 비리 의혹을 제시한 담당자와 해당 공사에서만 조사를 마친 듯 합니다. &amp;nbsp;&lt;/b&gt;&lt;br /&gt;
연관된 다른 청과 회사나 인원들에 대한 조사는 전혀 없었던 듯 합니다. &amp;nbsp;전화로 확인하였으나, 제가 거기에 있는 분들을 다 아는 것도 아니라서 추측으로만 적습니다. &amp;nbsp;결국 의혹을 가진 담당자의 이야기를 요약하여 조사를 마친 것이 되겠지요.&lt;div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;개발 가이드라인이 통보되었다.&lt;/b&gt;&lt;br /&gt;
&quot;카메라 두 대로 경매용 PC와 경매 참가자들을 녹화한다&quot; &amp;nbsp;수준의 가이드라인을 전문적인 프로젝트 가이드 라인이라고 봐야 하는지 참으로 답답합니다. &amp;nbsp;최소한이라고 생각할 수 있는, 해상도 및 프레임 수 등의 스팩도 빠져 있었고, 음성 녹음에 대한 요구사항도 한 참 후에 발생한 문제였습니다. &amp;nbsp;프로젝트 진행의 부실에 대한 조사가 있었기나 한 것인지 의심스럽습니다. &amp;nbsp;프로젝트를 시작 할 만한 요구사항 명세서라던가, RFP와 같은 문서는 어디에도 없었습니다.&lt;br /&gt;
&amp;nbsp;&lt;br /&gt;
&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;업체 대표가 작성해 준 문건을 공문으로 발생했다라는 의혹&lt;/b&gt;&lt;br /&gt;
아래가 원문 중에 내용입니다.&lt;br /&gt;
&lt;b&gt;&quot;특정 업체 대표의 글을 그대로 공문으로 발생한 것이 아니고 검증 결과에 나온 얘기를 정리하여 보완 지시하였고, 마지막 보완지시 공문내용은 상당부분 S청과 전산담당자가 실토한 내용을 정리하여 통보한 사항임&quot;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
일단 감사팀은 S청과와는 아무런 접촉이 없었음을 확인하였습니다. &amp;nbsp;담당자도 &quot;몰 실토했다는 거죠?&quot;라는 군요. &amp;nbsp;그리고, 청문회가 있을 때 제가 직접 &quot;이 공문은 저 업체 대표님이 작성해 준거라면서요?&quot;라고 직접 물었던 적이 있었습니다. &amp;nbsp;분위기가 썰렁해졌고 반박을 하지 못하더군요, 하지만 아쉽게도 답변을 회피 할 뿐 정확한 답변을 듣지 못했었습니다. &amp;nbsp;단순히 심증만 가는 상황이 되어 버린 것 입니다. &amp;nbsp;그리고, 해당 공문 내용은 일반인이 쓸 수 있는 내용이 아닌 전문적인 내용입니다. &amp;nbsp;더구나 한 쪽 이야기만 듣고 작성한 글이고, 이에 대한 반발로 인해서 겨우 청문회를 가졌던 것이고요. &amp;nbsp;정말 아쉬운 것은 업체 대표가 작성한 글을 공문으로 발송했다라는 말은 이 사건의 핵심 관련자인 S청과 직원들 뿐이라고 하는 군요.&lt;/div&gt;
&lt;div&gt;
&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
결국 &quot;A가 B를 때렸어요!&quot;라고 신고했는데, A에게 너 저 녀석 때렸어? 라고 묻고 나서, &quot;A는 B를 안때렸다&quot;라고 결론을 받은 것과 같은 기분입니다.&lt;br /&gt;
&lt;br /&gt;
서울시의 감사 활동에 조금은 기대를 했었는데, 의혹을 풀려는 의지가 있었던 것인 지 상당히 궁굼합니다. &amp;nbsp;같은 결과가 나왔더라도, 관련자 모두를 조사하고 프로젝트 과정의 문제점을 전문가와 함께 연구하려는 시도조차 없었던 것으로 보입니다.&lt;br /&gt;
&lt;br /&gt;
참고로, 이미 저는 저에게 주어진 요구사항을 마무리하고 나온지 몇 개월이 지났고, 개발비도 받았고, 이런 의혹을 제기해서 얻어지는 이익은 전혀 없습니다.&lt;/div&gt;&lt;div class=&quot;entry-ccl&quot; style=&quot;clear: both; text-align: right; margin-bottom: 10px&quot;&gt;
	&lt;img id=&quot;ccl-icon-170-0&quot; class=&quot;entry-ccl-by&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black01.png&quot; alt=&quot;저작자 표시&quot;/&gt;
	&lt;img id=&quot;ccl-icon-170-1&quot; class=&quot;entry-ccl-nc&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black02.png&quot; alt=&quot;비영리&quot;/&gt;
	&lt;img id=&quot;ccl-icon-170-2&quot; class=&quot;entry-ccl-nd&quot; src=&quot;http://i1.daumcdn.net/cfs.tistory/v/0/static/admin/editor/ccl_black03.png&quot; alt=&quot;변경 금지&quot;/&gt;
	&lt;!--
	&lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
		&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
		&lt;/Work&gt;
		&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;
			&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;
		&lt;/License&gt;
	&lt;/rdf:RDF&gt;
	--&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align:center; padding-top:10px;&quot;&gt;
&lt;iframe src=&quot;http://www.facebook.com/plugins/like.php?href=ryulib.tistory.com/170&amp;amp;layout=standard&amp;amp;show_faces=true&amp;amp;width=310&amp;amp;action=like&amp;amp;font=tahoma&amp;amp;colorscheme=light&amp;amp;height=65&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; style=&quot;border:none; overflow:hidden; width:310px; height:65px;&quot; allowTransparency=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
</description>
			<category>etc</category>
			<author>류종택</author>
			<guid>http://ryulib.tistory.com/170</guid>
			<comments>http://ryulib.tistory.com/170#entry170comment</comments>
			<pubDate>Mon, 26 Dec 2011 15:59:57 +0900</pubDate>
		</item>
	</channel>
</rss>

