티스토리 뷰


이 자료들은 팁스소프트에서 제공하는 [ 알짜배기 ] 프로그램을 이용하면 더 편리하게 볼수 있습니다.
* 알짜배기 프로그램 받기 - http://www.tipssoft.com/bulletin/tb.php/QnA/8406
* 안드로이드 강좌 목록 - http://www.tipssoft.com/bulletin/tb.php/old_bbs/501
이번 자료에서는 음성 인식과 TTS(TextToSpeech) 를 이용하여 사용자의 영문 발음을 테스트 해볼 수 있는
예제를 다루도록 하겠습니다. 이 예제를 쉽게 이해하기 위해서는 액티비티, 음성 인식, TextToSpeech 에
대한 지식이 필요하므로 아래 링크된 자료를 먼저 보시는 것이 좋습니다.
액티비티(Activity)의 이해 : http://www.tipssoft.com/bulletin/tb.php/FAQ/944
액티비티 전환하기 - 명시적 전환<1>: http://www.tipssoft.com/bulletin/tb.php/FAQ/945
음성 인식(Voice Recognition) : http://www.tipssoft.com/bulletin/tb.php/FAQ/961
1. 발음 테스트 예제 구성
이 예제는 여러개의 영어 단어들 중에서 10 개의 단어를 임의로 선택하여 텍스트 뷰에 출력하고, 버튼을
이용하여 음성인식 액티비티를 실행시키도록 구성되어 있습니다. 이렇게 실행된 액티비티는 사용자가
텍스트뷰에 출력했던 단어를 말하므로써 음성인식을 수행하고, 그 결과는 리스트뷰에 출력하게 됩니다.
사용자의 영어 발음은 텍스트뷰에 출력되었던 단어와 리스트뷰에 출력된 음성인식 결과 단어들을
비교하여 일치하는 단어가 존재하는지 여부로 좋고, 나쁨을 판단하게 됩니다. 또한 리스트뷰에 출력된
결과는 사용자의 영문 발음과 유사한 순서대로 정렬된 것이기때문에 일치하는 단어가 상단에 존재할수록
높은 점수를 얻게됩니다.
이제부터 어플리케이션의 동작에 대한 설명을 하도록 하겠습니다. 이 어플리케이션에서 직접 구성하는
액티비티는 2 개인데 하나는 사용자에게 테스트의 시작과 재시작을 유도하는 PronunciationTesterActivity
이고, 다른 하나는 실질적으로 발음 테스트를 수행하는 StartTestActivity 입니다. 먼저 메인 액티비티가
가질 수 있는 상황에 대하여 설명하도록 하겠습니다.
메인 액티비티는 어플리케이션을 실행했을 때 테스트가 바로 실행되지 않고, 사용자가 원할 때 테스트를
할 수 있도록 하단의 왼쪽 그림같은 인터페이스를 제공하기도하고, 테스트가 종료되었을 때 테스트 결과와
함께 재시작 여부를 묻는 하단의 오른쪽 그림같은 인터페이스를 제공하기도 합니다. 이 두 화면에 있는
버튼을 누르면 StartTestActivity 를 실행합니다.
StartTestActivity 는 아래의 그림과 같은 실행 흐름을 가지고 발음 테스트를 수행합니다.
1) 처음 액티비티가 실행되면 랜덤으로 지정된 10 개의 단어 중 첫번째 단어가 텍스트뷰에 출력됩니다.
사용자는 해당 단어를 발음하기위해 버튼을 클릭하여 음성 인식 액티비티를 호출합니다.
2) 실행된 음성 인식 액티비티에 영단어를 말하면, 해당 액티비티는 사용자의 음성을 분석하여 텍스트로
변환합니다.
3) 음성인식 액티비티로부터 반환된 텍스트 결과를 리스트뷰에 출력하고, 텍스트뷰의 단어와 리스트뷰에
출력된 결과가 일치하는지 비교하여 일치하는 단어가 있으면 해당 항목의 라디오버튼을 체크합니다.
또한 일치하는 항목이 있는지 여부에 따라 "Wow Good" 또는 "Oh No" 를 TTS 로 출력합니다.
발음 테스트의 점수는 리스트뷰의 첫번째 항목을 5 점으로 하여 인덱스가 증가할 수록 1 점씩 감소
하는 것으로 하고, 5 개의 항목에 대해서만 점수를 계산합니다.
4) 랜덤하게 뽑은 10 개의 단어를 모두 발음하게되면 발음 테스트가 종료되며, 'Show Score' 버튼을
누르면 해당 액티비티가 종료되면서 메인 액티비티에 테스트의 결과 점수를 넘겨줍니다.
2. 발음 테스트 예제 구현
아래의 코드는 위에서 설명한 실행 순서대로 발음 테스트 예제를 구현한 것입니다. 이 예제에서 사용되는
모든 메소드에 대해서는 설명하지 않고, 예제에서 사용되는 두 액티비티의 실행 순서에 따라 수행되는
주요 메소드에 대해서만 설명하도록 하겠습니다. 예제의 소스 코드를 보고싶으신 분들은 강좌에 첨부된
파일을 참고하시면 됩니다.
2.1 테스트 단어 랜덤하게 선택
발음 테스트를 위해 영어 단어를 가지는 배열로부터 10 개의 단어를 랜덤하게 선택하여 테스트합니다.
단어를 랜덤으로 선택하기 위해서 자바의 Random 클래스를 사용하며, Random 객체를 이용하여
10개의 값을 추출하여 정수형 배열에 중복되지 않도록 저장합니다.
void SelectRandomWord()
{
// 임의의 값을 발생시켜주는 Random 클래스를 생성한다.
Random r = new Random();

for( int i = 0 ; i < 10 ; i++ ) {
// 랜덤한 수를 발생시켜 m_word_index 배열에 저장한다.
m_word_index[i] = r.nextInt( m_word.length );

for( int j = 0 ; j < i ; j++ ) {
// 이전 배열 인덱스에 현재 인덱스 값과 중복되는 값이 있는 경우
if( m_word_index[i] == m_word_index[j] ) {
// 현재 인덱스 값을 다시 저장하기위해 i 값을 감소시킨다.
i--;
break;
}
}
}
}
2.2 음성 인식 액티비티 실행
랜덤하게 선택한 10 개의 단어들을 차례로 텍스트뷰에 출력하고, 사용자가 음성 인식 액티비티에
발음하면 인식한 결과를 리스트뷰에 출력합니다. 그리고 정답과 리스트뷰에 출력된 단어들을 비교하여
일치하는 단어가 있는 경우 해당 항목을 선택한 뒤 "Wow Good" 이라는 음성을 TTS 를 통해 출력하고,
일치하는 단어가 없는 경우 "Oh No" 를 출력합니다.
10 번의 발음 테스트를 모두 수행한 뒤 사용자가 'Show Score' 버튼을 클릭하면 현재 액티비티가
종료되면서 이를 호출한 액티비티에게 발음 테스트의 점수 정보를 반환합니다.
// OnClickListener 인터페이스의 onClick 메소드를 정의한다.
// StartTestActivity 에서 버튼을 클릭하면 호출되는 메소드.
public void onClick(View view) {
//이벤트가 발생한 버튼이 'Speak' 버튼인 경우
if( view.getId() == R.id.id_btn) {
// 10 번의 발음테스트를 마치고, 버튼에 'Show Score'로 텍스트가 변경된 경우
if( m_count == 10 ) {
// StartTestActivity 를 시작하게 한 인텐트를 호출한다.
Intent intent = getIntent();

// 인텐트에 SCORE 라는 이름으로 게임의 스코어를 저장시킨다.
intent.putExtra("SCORE", m_total_score);
// 정상적인 결과 값을 반환하는 경우 RESULT_OK 를 첫번째 인자에 명시하고,
// 두번째 인자에 인텐트를 명시한다.

setResult(RESULT_OK, intent);

// 액티비티를 종료시킨다.
finish();
} else {
// 음성 인식 액티비티를 실행하기위해 정의한 메소드를 호출한다.
startVoiceRecognitionActivity();
}
}
}
// 음성 인식 액티비티를 실행하기 위해 정의한 메소드
private void startVoiceRecognitionActivity() {

// 음성 인식 행위에 대한 액티비티를 실행시킬 수 있는 인텐트 객체를 생성한다.
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
// 음성 인식기에 대한 언어 모델 정보를 실행될 액티비티에 전달한다.
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);

// 음성 인식기에 대한 언어 정보를 실행될 액티비티에 전달한다.
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE , "en-US" );

// 사용자에게 음성 인식 요청시 보여줄 텍스트 정보를 실행될 액티비티에 전달한다.
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, m_word[ m_word_index[m_count]]
+ " 을(를) 발음하세요.");
// 인텐트 정보에 맞는 액티비티를 실행한다.
startActivityForResult(intent, 0);
}
// 실행시킨 액티비티가 종료되었을 때 호출되는 메소드.
// 이 액티비티에서는 음성인식 액티비티가 종료될 때 호출되며 음성인식 액티비티가 반환하는
// 인텐트로 음성인식 결과를 얻을 수 있다.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// 결과 값이 있고, 액티비티를 시작할 때 0으로 설정해둔 결과값인 경우
if (requestCode == 0 && resultCode == RESULT_OK) {
// 리소스 파일에 정의된 id_list 라는 ID 의 리스트뷰를 얻어온다.
ListView list = (ListView) findViewById(R.id.id_list);
// 사용자의 음성을 인식하여 해석한 결과를 String 객체로 반환한다.
ArrayList<String> matches = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
// 리스트뷰에 다섯개의 결과만 출력하기위해 5개 이외의 ArrayList 객체는 제거한다.
for( int i = 5 ; i < matches.size() ; i++ ) matches.remove(i);
// ArrayList 객체와 하나의 항목을 선택할 수 있는 버튼을 가진 어댑터 객체를 생성한다.
m_adapter = new ArrayAdapter<String>( this, android.R.layout.simple_list_item_single_choice
, matches);
// 리스트뷰에 어댑터를 설정한다.
list.setAdapter( m_adapter );
// 리스트뷰의 선택모드를 설정한다.
list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

// 사용자에게 보여준 단어와 음성 인식된 결과가 일치하는지를 체크한다.
int result = CheckAnswer();
// 음성 인식된 결과에 일치되는 단어가 존재하는 경우
if( result != -1 ) {
// TTS 를 이용하여 아래 문장을 음성 변환한다.
m_tts.speak( "Wow Good" , TextToSpeech.QUEUE_FLUSH , null);
// 리스트 뷰의 지정된 인덱스가 체크되도록 설정한다.
list.setItemChecked ( result, true );
// 음성 인식된 결과에 일치되는 단어가 존재하지 않는 경우
} else {
// TTS 를 이용하여 아래 문장을 음성 변환한다.
m_tts.speak( "Oh No, TextToSpeech.QUEUE_FLUSH , null);
// 다음 테스트 단어를 출력하기위해 카운트를 증가한다.
m_count++;
// 리소스 파일에 정의된 id_sec_tv 라는 ID 의 텍스트뷰를 얻어온다.
TextView tv = (TextView) findViewById(R.id.id_sec_tv);
// 현재 출력된 단어가 몇 번째 단어인지 표시한다.
tv.setText(": No. " + (m_count+1) );

// 10 개 단어의 발음 테스트를 마친 경우
if( m_count == 10) {
// 각 컴포넌트의 텍스트를 다음과 같이 변경한다.
m_tv.setText("The End");
m_btn.setText("Show Score");
tv.setText(": Score 를 확인하려면 아래 버튼을 클릭하세요");
// 테스트가 진행 중인 경우
} else {
// 그 다음 단어를 텍스트뷰에 출력한다.
m_tv.setText( m_word[ m_word_index[m_count] ]);
}
}
super.onActivityResult(requestCode, resultCode, data);
}
2.3 PronunciationTesterActivity 실행 결과
StartTestActivity 에서 10 번의 발음 테스트를 수행한 뒤 사용자에의해 액티비티가 종료되면 이
액티비티를 호출한 PronunciationTesterActivity 에 정의된 onActivityResult 메소드에서 액티비티
실행 결과로 반환된 테스트의 점수와 그에 따른 문장을 출력합니다.
// 실행시킨 액티비티가 종료되었을 때 호출되는 메소드.
// 이 액티비티에서는 StartTestActivity 가 종료될 때 호출되며 해당 액티비티가 반환하는 인텐트로
// 발음 테스트 결과 점수를 얻을 수 있다.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// 결과 값이 있고, 액티비티를 시작할 때 0으로 설정해둔 결과값인 경우
if(resultCode == RESULT_OK && requestCode == 0) {

// 발음 테스트의 결과로 반환된 점수를 알려주기위해
// SCORE 라는 이름의 정수 데이터를 가져온다.
int score = data.getIntExtra("SCORE", 0);
// main 리소스 파일에 정의된 id_tv 라는 ID 의 텍스트뷰을 얻어온다.
TextView tv = (TextView) findViewById(R.id.id_tv);
// 발음 테스트의 점수를 표시한다.
tv.setText("Total Score : "+ score);

// main 리소스 파일에 정의된 id_tv 라는 ID 의 텍스트뷰을 얻어온다.
TextView grade_tv = (TextView) findViewById(R.id.id_grade_tv);
// 점수에 따른 문장을 텍스트뷰에 출력한다.
if( score > 40 ) grade_tv.setText("Awesome :-)");
else if( score > 30 ) grade_tv.setText("Pretty Good :-)");
else if( score > 20 ) grade_tv.setText("Good :-)");
else if( score > 10 ) grade_tv.setText("So So:-)");
else grade_tv.setText("Try hard :(");
m_btn.setText("Restart");
}
}


'프로그램 > 안드로이드 강좌' 카테고리의 다른 글

사용자정의 뷰 생성 및 배치1  (0) 2012.08.15
그림그리기의 기초와 구조  (0) 2012.08.15
음성인식  (0) 2012.08.15
사진 촬영 서버전송  (0) 2012.08.15
TTS(TextToSpeech)  (0) 2012.08.15
댓글