Blame platform-demos/ko/guitar-tuner.cpp.page

Packit 1470ea
Packit 1470ea
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" type="topic" id="guitar-tuner.cpp" xml:lang="ko">
Packit 1470ea
Packit 1470ea
  <info>
Packit 1470ea
    <link type="guide" xref="cpp#examples"/>
Packit 1470ea
Packit 1470ea
    <desc>GTKmm과 Gstreamermm을 활용하여 간단한 그놈용 기타 조율 프로그램을 만들어보겠습니다. 인터페이스 디자이너 활용 방법을 보여드립니다.</desc>
Packit 1470ea
Packit 1470ea
    <revision pkgversion="0.1" version="0.1" date="2011-03-17" status="review"/>
Packit 1470ea
    <credit type="author">
Packit 1470ea
      <name>그놈 문서 프로젝트</name>
Packit 1470ea
      <email its:translate="no">gnome-doc-list@gnome.org</email>
Packit 1470ea
    </credit>
Packit 1470ea
    <credit type="author">
Packit 1470ea
      <name>Johannes Schmid</name>
Packit 1470ea
      <email its:translate="no">jhs@gnome.org</email>
Packit 1470ea
    </credit>
Packit 1470ea
    <credit type="editor">
Packit 1470ea
      <name>Marta Maria Casetti</name>
Packit 1470ea
      <email its:translate="no">mmcasetti@gmail.com</email>
Packit 1470ea
      <years>2013</years>
Packit 1470ea
    </credit>
Packit 1470ea
  
Packit 1470ea
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
Packit 1470ea
      <mal:name>조성호</mal:name>
Packit 1470ea
      <mal:email>shcho@gnome.org</mal:email>
Packit 1470ea
      <mal:years>2017</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  </info>
Packit 1470ea
Packit 1470ea
<title>기타 조율기</title>
Packit 1470ea
Packit 1470ea
<synopsis>
Packit 1470ea
  

이 지침서에서, 기타 조율에 사용할 수 있는 음색을 재생하는 프로그램을 만들겠습니다. 다음 내용을 배워나갑니다:

Packit 1470ea
  <list>
Packit 1470ea
    <item>

안주타에서 기본 프로젝트 설정

</item>
Packit 1470ea
    <item>

안주타 사용자 인터페이스 디자이너에서 간단한 GUI 만들기

</item>
Packit 1470ea
    <item>

지스트리머를 사용하여 소리 재생하기

</item>
Packit 1470ea
  </list>
Packit 1470ea
  

이 지침을 따라갈 수 있으려면 다음이 필요합니다:

Packit 1470ea
  <list>
Packit 1470ea
    <item>

<link xref="getting-ready">안주타 IDE</link> 설치 사본

</item>
Packit 1470ea
    <item>

C++ 프로그래밍 언어 기본 지식

</item>
Packit 1470ea
  </list>
Packit 1470ea
</synopsis>
Packit 1470ea
Packit 1470ea
<media type="image" mime="image/png" src="media/guitar-tuner.png"/>
Packit 1470ea
Packit 1470ea
<section id="anjuta">
Packit 1470ea
  <title>안주타에서 프로젝트 만들기</title>
Packit 1470ea
  

코딩을 시작하기 전에 안주타에서 새 프로젝트를 설정해야합니다. 이 프로그램은 빌드에 필요한 모든 파일을 만들고 그 다음 코드를 실행합니다. 또한 이 모든 상태를 유지 관리하는데 쓸만합니다.

Packit 1470ea
  <steps>
Packit 1470ea
    <item>
Packit 1470ea
    

안주타를 시작하고 <guiseq><gui>파일</gui><gui>새로 만들기</gui><gui>프로젝트</gui></guiseq> 를 눌러 프로젝트 마법사를 여십시오.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
    

<gui>C++</gui> 탭에서 <gui>GTKmm (단순)</gui>을 선택한 후 <gui>다음</gui> 을 누르고 다음 페이지 몇 군데에서 자세한 내용을 채워나가십시오. 프로젝트 이름과 디렉터리 이름은 <file>guitar-tuner</file>로 설정하십시오.

Packit 1470ea
   	</item>
Packit 1470ea
    <item>
Packit 1470ea
    

<gui>외부 패키지 설정</gui>을 선택했는지 확인하십시오. 다음 페이지 목록에서 gstreamermm-0.10을 선택하고 프로젝트에 GStreamermm 라이브러리를 넣으십시오.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
    

<gui>마침</gui>을 누르면 프로젝트를 만들어줍니다. <gui>프로젝트</gui>나 <gui>파일</gui>탭에서 <file>src/main.cc</file> 파일을 여십시오. 다음 줄로 시작하는 일부 코드가 나타납니다:

Packit 1470ea
    
Packit 1470ea
#include <gtkmm.h>
Packit 1470ea
#include <iostream>
Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="build">
Packit 1470ea
  <title>첫 코드 작성</title>
Packit 1470ea
  

이 부분은 GTKmm을 구성한 매우 간단한 C++ 코드입니다. 더 자세한 내용은 아래를 보십시오. 기본을 이해하고 있다면 이 부분을 건너 뛰십시오:

Packit 1470ea
  <list>
Packit 1470ea
  <item>
Packit 1470ea
    

상단의 #include 세 줄은 config(쓸만한 autoconf 빌드 정의), gtkmm(사용자 인터페이스), iostream(STL) 라이브러리입니다. 이 라이브러리의 함수는 코드 나머지 부분에서 활용합니다.

Packit 1470ea
   </item>
Packit 1470ea
   <item>
Packit 1470ea
    

main 함수는 GtkBuilder 파일(위 몇 줄을 정의한 <file>src/guitar-tuner.ui</file>)을 열어 새 창을 만들고 창 안에 구성 요소를 표시합니다. GtkBuilder 파일에는 사용자 인터페이스 설명과 구성 요소 모드가 들어있습니다. GtkBuilder 사용자 인터페이스를 만들 때 안주타 편집기를 사용할 수 있습니다.

Packit 1470ea
   </item>
Packit 1470ea
   <item>
Packit 1470ea
    

그 다음 프로그램을 설정하고 실행할 몇가지 함수를 호출합니다. kit.run 함수는 사용자 인터페이스를 실행하고 이벤트(마우스 단추 누름, 키보드 키 누름)를 기다리는 GTKmm 메인 루프를 시작합니다.

Packit 1470ea
   </item>
Packit 1470ea
  </list>
Packit 1470ea
Packit 1470ea
  

이 코드를 사용할 준비가 됐으니 <guiseq><gui>빌드</gui><gui>프로젝트 빌드</gui></guiseq>(또는 <keyseq><key>Shift</key><key>F7</key></keyseq> 키 누름)를 눌러 코드를 컴파일할 수 있습니다.

Packit 1470ea
  

디버깅 빌드 설정이 나타나는 다음 창에서 <gui>실행</gui> 을 누르십시오. 처음 빌드할 때 한번만 하면 됩니다.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="ui">
Packit 1470ea
  <title>사용자 인터페이스 만들기</title>
Packit 1470ea
  

사용자 인터페이스(UI) 설명은 GtkBuilder 파일에 있습니다. 사용자 인터페이스를 편집하려면 <file>src/guitar_tuner.ui</file> 파일을 여십시오. 이 과정에서 바로 인터페이스 디자이너로 넘어갑니다. 설계 창은 가운데에 있고 위젯과 위젯 속성은 왼편에, 사용할 수 있는 위젯은 오른편에 있습니다.

Packit 1470ea
  

GTK+의 모든 UI 배치는 상자와 표로 구성합니다. 가로 방향 <gui>GtkButtonBox</gui>를 여기서 사용하여 각 기타 줄에 해당하는 여섯 개의 <gui>GtkButtons</gui> 단추를 넣어보겠습니다.

Packit 1470ea
Packit 1470ea
<media type="image" mime="image/png" src="media/guitar-tuner-glade.png"/>
Packit 1470ea
Packit 1470ea
  <steps>
Packit 1470ea
   <item>
Packit 1470ea
   

우측 <gui>팔레트</gui>의 <gui>컨테이너</gui> 섹션에서 <gui>GtkButtonBox</gui> 를 선택하여 창에 가져다 높으십시오. <gui>속성</gui> 창에서 구성 요소 수를 6(기타 줄 6개)으로 설정하고, 방향은 세로(vertical)로 설정하십시오.

Packit 1470ea
   </item>
Packit 1470ea
   <item>
Packit 1470ea
    

이제 팔레트에서 <gui>GtkButton</gui> 를 선택하고 상자의 처음 부분에 가져다 놓으십시오.

Packit 1470ea
   </item>
Packit 1470ea
   <item>
Packit 1470ea
    

단추를 선택한 상태에서 <gui>위젯</gui> 탭의 <gui>레이블</gui> 속성을 <gui>E</gui>로 바꾸십시오. 기타의 낮은 E 줄을 의미합니다. 또한 <gui>이름</gui> 속성을 <gui>button_E</gui> 값으로 바꾸십시오. 나중에 코드에서 위젯을 참조할 이름입니다.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
    

위 단계를 다음 5현을 대해 A, D, G, B, e 레이블로 추가하는 단추에도 반복하시고 button_A와 같은 식으로 이름을 부여하십시오.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
    

UI 디자인을 저장(<guiseq><gui>파일</gui><gui>저장</gui></guiseq> 누름)하고 파일을 닫으십시오.

Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="gst">
Packit 1470ea
  <title>지스트리머 파이프라인</title>
Packit 1470ea
  

지스트리머는 그놈 멀티미디어 프레임워크입니다. 동영상 오디오 웹캠 스트림 같은걸 재생, 녹음/녹화, 처리할 때 지스트리머를 사용할 수 있습니다. 여기서는 단일 주파수 음색을 만들 때 사용하겠습니다. GStreamermm은 여기서 우리가 사용할 지스트리머 C++ 바인딩입니다.

Packit 1470ea
  

개념적으로 지스트리머 동작은 다음과 같습니다. (우선) source에서 sink(출력)으로 내보낼 수많은 처리 요소가 들어간 파이프라인을 만듭니다. source는 그림 파일, 동영상, 음악 파일일 수 있으며, 출력 대상은 위젯 또는 사운드 카드가 될 수 있습니다.

Packit 1470ea
  

source와 sink 사이에서 다양한 필터와 변환 프로그램을 적용하여 효과를 처리하거나, 형식을 변환하는 등을 할 수 있습니다. 각 파이프라인 구성 요소에는 동작을 바꿀 수 있는 속성이 있습니다.

Packit 1470ea
  <media type="image" mime="image/png" src="media/guitar-tuner-pipeline.png">
Packit 1470ea
    

지스트리머 파이프라인 예제입니다.

Packit 1470ea
  </media>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="usinggst">
Packit 1470ea
  <title>GStreamermm 사용</title>
Packit 1470ea
  

GStreamermm을 사용하려면 초기화해야합니다. <file>main.cc</file>의 Gtk::Main kit(argc, argv); 다음에 코드 몇 줄을 추가하겠습니다:

Packit 1470ea
  	Gst::init (argc, argv);
Packit 1470ea
  

여기에 있는 동안 <file>gstreamermm.h</file> 파일을 <file>main.cc</file> 파일에 제대로 넣었는지도 확인하십시오.

Packit 1470ea
Packit 1470ea
  

여기 단순 예제에서는 audiotestsrc 라는 음 재생기 소스를 사용하고 기본 시스템 사운드 장치 autoaudiosink로 출력을 내보내겠습니다. 우리는 여기서 음 재생기 주파수를 설정해야합니다. audiotestsrcfreq 속성을 사용하면 됩니다.

Packit 1470ea
Packit 1470ea
  

파이프라인 처리를 단순하게 할 목적으로 Sound 보조 클래스를 정의하겠습니다. 여러분은 다른 파일에 정의하고 싶겠지만 이 예제의 단순함을 유지할 목적으로 <file>main.cc</file>에서 진행하겠습니다:

Packit 1470ea
  
Packit 1470ea
class Sound
Packit 1470ea
{
Packit 1470ea
	public:
Packit 1470ea
		Sound();
Packit 1470ea
Packit 1470ea
		void start_playing(double frequency);
Packit 1470ea
		bool stop_playing();
Packit 1470ea
Packit 1470ea
	private:
Packit 1470ea
		Glib::RefPtr<Gst::Pipeline> m_pipeline;
Packit 1470ea
		Glib::RefPtr<Gst::Element> m_source;
Packit 1470ea
		Glib::RefPtr<Gst::Element> m_sink;
Packit 1470ea
};
Packit 1470ea
Packit 1470ea
Sound::Sound()
Packit 1470ea
{
Packit 1470ea
	m_pipeline = Gst::Pipeline::create("note");
Packit 1470ea
	m_source = Gst::ElementFactory::create_element("audiotestsrc",
Packit 1470ea
	                                               "source");
Packit 1470ea
	m_sink = Gst::ElementFactory::create_element("autoaudiosink",
Packit 1470ea
	                                             "output");
Packit 1470ea
	m_pipeline->add(m_source);
Packit 1470ea
	m_pipeline->add(m_sink);
Packit 1470ea
	m_source->link(m_sink);
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
void Sound::start_playing (double frequency)
Packit 1470ea
{
Packit 1470ea
	m_source->set_property("freq", frequency);
Packit 1470ea
	m_pipeline->set_state(Gst::STATE_PLAYING);
Packit 1470ea
Packit 1470ea
	/* stop it after 200ms */
Packit 1470ea
	Glib::signal_timeout().connect(sigc::mem_fun(*this, &Sound::stop_playing),
Packit 1470ea
	                               200);
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
bool Sound::stop_playing()
Packit 1470ea
{
Packit 1470ea
	m_pipeline->set_state(Gst::STATE_NULL);
Packit 1470ea
	return false;
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
Packit 1470ea
  

이 코드는 다음 목적으로 작성합니다:

Packit 1470ea
  <steps>
Packit 1470ea
    <item>
Packit 1470ea
    

생성자에서 source 지스트리머 구성요소와 sink 지스트리머 구성요소(Gst::Element), 파이프라인 지스트리머 구성요소(앞서 말한 구성 요소의 컨테이너로 활용)를 만듭니다. 파이프라인 이름은 "note"라고 지어둡니다. source는 "source"로 이름 붙이고 audiotestsrc로 설정합니다. sink는 "output"으로 이름 붙이고 autoaudiosink sink로 설정합니다(사운드 카드 출력이 기본). 구성 요소를 파이프라인에 추가하고 서로 연결한 다음에는 파이프라인 실행 준비가 끝납니다.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
    

start_playing은 각 주파수를 재생할 source 구성 요소를 설정하고 파이프라인을 시작하여 소리를 실제로 재생하게 합니다. 소리를 영원히 짜증나게 재생하고 싶지는 않기에 stop_playing을 200ms 후에 호출하여 파이프라인 동작을 멈추도록 제한 시간을 설정합니다.

Packit 1470ea
    </item>
Packit 1470ea
    <item>
Packit 1470ea
    

제한 시간에 도달했을 때 호출하는 stop_playing 함수에서는, 파이프라인을 멈추어 더 이상 소리가 나지 않게 합니다. GStreamermm에서 Glib::RefPtr 객체로 참조 카운팅을 하기 때문에 Sound 클래스를 해체하면 메모리를 자동으로 해제합니다.

Packit 1470ea
    </item>
Packit 1470ea
  </steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="signals">
Packit 1470ea
  <title>시그널에 연결하기</title>
Packit 1470ea
  

사용자가 단추를 눌렀을 때 제대로 된 음을 재생하려고 합니다. 무슨 얘기냐면 사용자가 단추를 누르면 나오는 시그널을 실행할 함수에 연결해야 한다는 뜻입니다. 또한 재생할 음에 대한 정보를 호출 함수에 넘겨주려고 합니다. GTKmm에서는 sigc 라이브러리에서 정보를 바인딩해서 쉽게 처리할 수 있습니다.

Packit 1470ea
Packit 1470ea
  

관심있어 하는 부분을 이제는 보조 클래스에서 처리하므로, 사용자가 단추를 눌렀을 때 호출하는 함수가 약간 간단할 수 있습니다:

Packit 1470ea
  
Packit 1470ea
static void
Packit 1470ea
on_button_clicked(double frequency, Sound* sound)
Packit 1470ea
{
Packit 1470ea
	sound->start_playing (frequency);
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
  

이 코드에서는 올바른 주파수 음을 재생하려 앞서 정의한 보조 클래스를 호출하기만 합니다. 더 멋진 코드에서는 함수를 활용하지 않고 클래스에 직접 연결할 수 있겠지만, 그냥 이대로를 연습용으로 두겠습니다.

Packit 1470ea
Packit 1470ea
  

시그널을 설정하는 코드는 main() 함수의 builder->get_widget("main_window", main_win); 코드 줄 바로 다음에 추가하십시오:

Packit 1470ea
  
Packit 1470ea
Sound sound;
Packit 1470ea
Gtk::Button* button;
Packit 1470ea
Packit 1470ea
builder->get_widget("button_E", button);
Packit 1470ea
button->signal_clicked().connect (sigc::bind<double, Sound*>(sigc::ptr_fun(&on_button_clicked),
Packit 1470ea
                                              329.63, &sound));
Packit 1470ea
Packit 1470ea
	<steps>
Packit 1470ea
	<item>
Packit 1470ea
	

우선 당장 쓰려는 보조 클래스의 인스턴스를 만들고 연결하고자 하는 단추의 변수를 선언하겠습니다.

Packit 1470ea
	</item>
Packit 1470ea
	<item>
Packit 1470ea
	

그 다음 사용자 인터페이스 파일에서 만든 사용자 인터페이스에서 단추 객체를 가져오겠습니다. 기억하시겠지만 button_E가 첫번째 단추에 지어준 이름이죠.

Packit 1470ea
	</item>
Packit 1470ea
	<item>
Packit 1470ea
	

마지막으로 clicked 시그널을 연결하겠습니다. 그다지 간단하지 않은 과정인데 자료형에 안전한 방식으로 끝낼 일이며 실제로 주파수 정보와 보조 클래스를 시그널 핸들러로 전달하고 싶어하기 때문입니다. sigc::ptr_fun(&on_button_clicked) 메서드는 위에서 우리가 정의한 on_button_clicked 메서드의 slot을 만듭니다. sigc::bind로 슬롯에 추가 인자를 전달할 수 있는데, 이 경우 우리는 주파수(double 형식) 값과 보조 클래스를 전달합니다.

Packit 1470ea
	</item>
Packit 1470ea
  </steps>
Packit 1470ea
  

이제 E 단추를 설정했고, 다른 단추에도 해당 주파수 값으로 연결해야합니다. A에는 440, D에는 587.33, G에는 783.99, B에는 987.77, 높은 E에는 1318.5 이런 식이죠. 그냥 핸들러에 다른 주파수 값을 전달하는 동일한 방식으로 처리할 수 있습니다.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="run">
Packit 1470ea
  <title>프로그램 빌드 및 실행</title>
Packit 1470ea
  

모든 코드가 동작할 준비가 끝났습니다. <guiseq><gui>빌드</gui><gui>프로젝트 빌드</gui></guiseq>를 눌러 모두 다시 빌드하시고, <guiseq><gui>실행</gui><gui>실행</gui></guiseq>을 눌러 프로그램을 시작하십시오.

Packit 1470ea
  

아직 끝내지 않았다면 나타난 대화상자에서 <file>Debug/src/guitar-tuner</file> 프로그램을 선택하십시오. 마지막으로 <gui>Run</gui>를 눌러 만든 프로그램을 즐기시죠!

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="impl">
Packit 1470ea
 <title>참조 구현체</title>
Packit 1470ea
 

지침서를 따라하는 실행하는 과정에 문제가 있다면, <link href="guitar-tuner/guitar-tuner.cc">참조 코드</link>와 여러분의 코드를 비교해보십시오.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="further">
Packit 1470ea
  <title>더 읽을거리</title>
Packit 1470ea
  

위에 보여드린 예제 대부분에 대해서는, GTKmm의 완벽한 힘을 활용하여 더 핵심적인 개념을 다루는 <link href="http://library.gnome.org/devel/gtkmm-tutorial/stable/">GTKmm book</link>에서 더 자세한 내용을 다룹니다. <link href="http://library.gnome.org/devel/gstreamermm/">GStreamermm 참고 문서</link>에도 관심이 있으실지도 모르겠습니다.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="next">
Packit 1470ea
  <title>다음 단계</title>
Packit 1470ea
  

여기 간단한 시험 프로그램에 여러분이 추가로 넣을 수 있는 몇가지 아이디어가 있습니다:

Packit 1470ea
  <list>
Packit 1470ea
   <item>
Packit 1470ea
   

프로그램에 음 재생 자동 주기 기능 넣기.

Packit 1470ea
   </item>
Packit 1470ea
   <item>
Packit 1470ea
   

프로그램에 실제 기타 현을 퉁겼을 때의 음을 녹음하여 재생하기.

Packit 1470ea
   

이 동작을 구현하려면 음악 파일을 불러와서 재생할 수 있도록 지스트리머 파이프라인을 좀 더 복잡하게 설정해야합니다. 녹음 음원의 파일 형식에 따른<link href="http://gstreamer.freedesktop.org/documentation/plugins.html">decoder와 demuxer</link> 지스트리머 구성 요소를 선택해야 할 수도 있습니다. 예를 들자면 MP3는 Ogg Vorbis 파일과는 다른 구성 요소를 활용합니다.

Packit 1470ea
   

좀 더 복잡한 식으로 구성 요소를 연결해야 할 수도 있습니다. <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-intro-basics-pads.html">pads</link>와 같이 우리가 지침서에서 다룰 수 없는 <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-intro-basics.html">지스트리머 개념</link>이 들어갈 수도 있습니다. 쓸만한 <cmd>gst-inspect</cmd> 명령을 찾아볼 수도 있습니다.

Packit 1470ea
   </item>
Packit 1470ea
   <item>
Packit 1470ea
   

사용자 연주 음을 자동으로 분석.

Packit 1470ea
   

마이크를 연결하고 <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-autoaudiosrc.html">input source</link>로 음을 녹음할 수 있습니다. 아마도 <link href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-plugin-spectrum.html">스펙트럼 분석</link> 같은 것으로 어떤 음을 재생했는지 알 수 있겠죠?

Packit 1470ea
   </item>
Packit 1470ea
  </list>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
</page>