[안드로이드] TTS (TextToSpeech) 예제

Android (Kotlin) 2020. 10. 11. 17:37

1. TTS Class 소스 (커스텀)

class TTS_Module {
    companion object : TextToSpeech.OnInitListener {
        private const val TTS_DATA_CHECK_CODE = 7200
        private var ctx : Activity? = null
        private var TTS: TextToSpeech? = null
        private var text: String = ""
        private var locale: Locale = Locale.KOREA
        private var level: Float = PITCH.NOMAL.level
        private var speed: Float = SPEED.s1_0X.speed

        fun toSpeech(ctx: Activity, text: String ,
                     locale: Locale? = Locale.KOREA,
                     level: Float = PITCH.NOMAL.level,
                     speed: Float = SPEED.s1_0X.speed){
            this.text = text
            this.ctx = ctx
            if (locale != null) this.locale = locale
            if (level != null) this.level = level
            if (speed != null) this.speed = speed

            if(TTS == null) {
                val intent = Intent()
                intent.action = TextToSpeech.Engine.ACTION_CHECK_TTS_DATA
                ctx.startActivityForResult(intent, TTS_DATA_CHECK_CODE)
            }else{
                speeach()
            }
        }

        private fun speeach(){

            setLanguage(this.locale)
            setPitch(this.level)
            setSpeechRate(this.speed)
			// 블루투스 연결시 패이드인으로 앞에 소리가 살짝 끊김을 해소 하기 위해
            // 무은 MP3 를 재생 후 TTS 작동. (MP3는 0.5~1초 정도가 적당해 보임)
            val resID: Int = ctx!!.resources.getIdentifier(
            	"no_sound", "raw", ctx!!.packageName)
            val player: MediaPlayer = MediaPlayer.create(ctx, resID)
            player.setOnCompletionListener {
                Log.d("B-Rain", "TTS 시작")
                if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
                    TTS!!.speak("", TextToSpeech.QUEUE_FLUSH, null, null)
                    TTS!!.speak(text, TextToSpeech.QUEUE_ADD, null, null)
                } else {
                    TTS!!.speak("", TextToSpeech.QUEUE_FLUSH, null)
                    TTS!!.speak(text, TextToSpeech.QUEUE_ADD, null)
                }
            }
            player.start()
            Log.d("B-Rain", "무음 MP3 시작")
        }

        override fun onInit(status: Int) {
            if (status == TextToSpeech.SUCCESS) {
                if (TTS!!.isLanguageAvailable(Locale.KOREA) >=
                    TextToSpeech.LANG_AVAILABLE) {
                    TTS!!.language = Locale.KOREA

                    speeach()
                }
            }
        }

        /** 음성 언어 */
        fun setLanguage(locale: Locale? = Locale.KOREA) {
            if (TTS != null) TTS!!.language = locale
        }

        /** 음성 속도 */
        fun setSpeechRate(speed: Float = SPEED.s1_0X.speed) {
            if (TTS != null) TTS!!.setSpeechRate(speed)
        }

        /** 음성 톤 */
        fun setPitch(level: Float = PITCH.NOMAL.level) {
            if (TTS != null) TTS!!.setPitch(level)
        }

        fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
            if (requestCode === TTS_DATA_CHECK_CODE) {
                if (resultCode === TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
                    if(TTS == null) {
                        TTS = TextToSpeech(ctx, this)
                    }else{
                        speeach()
                    }

                } else {
                    val installIntent = Intent()
                    installIntent.action = 
                    TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA
                    ctx!!.startActivity(installIntent)
                }
            }
        }

        fun onPause() {
            if (TTS != null) {
                if (TTS!!.isSpeaking) {
                    TTS!!.stop()
                }
            }
        }

        fun onDestroy() {
            if (TTS != null) {
                if(TTS!!.isSpeaking) {
                    TTS!!.stop();
                }
                TTS!!.shutdown();
            }
        }
    }
}

enum class PITCH {
    ROW {
        override fun index() = 1
        override val level: Float
            get() = 0.1F
    },
    NOMAL {
        override fun index() = 2
        override val level: Float
            get() = 1.0F
    },
    HIGH {
        override fun index() = 3
        override val level: Float
            get() = 2.0F
    };

    abstract fun index() : Int
    abstract val level : Float
}

enum class SPEED {
    ZERO {
        override fun index() = 1
        override val speed: Float
            get() = 0.1F
    },
    s1_0X {
        override fun index() = 2
        override val speed: Float
            get() = 1.0F
    },
    s1_5X {
        override fun index() = 3
        override val speed: Float
            get() = 1.5F
    },
    s2_0X {
        override fun index() = 4
        override val speed: Float
        get() = 2.0F
    };

    abstract fun index() : Int
    abstract val speed : Float
}

2. 사용법

 - Base Activity로 만들어서 상속 시켜 사용 하면 적당 할 듯.

class BaseActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        btn_tts.setOnClickListener {
        	// TTS_Module 실행 (SingleTone Clas)
            TTS_Module.toSpeech(
                this,
                "TTS 출력 시킴"
            ,Locale.KOREA      // 옵션
            ,PITCH.NOMAL.level // 옵션
            ,SPEED.s1_0X.speed // 옵션
            )
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
		// TTS 데이터 가 없을 경우 "TTS_Module" 클래스가 처리 할 수 있도록 전달
        TTS_Module.onActivityResult(requestCode, resultCode, data)
    }

    override fun onPause() {
        super.onPause()
        // Pause 일 때 
        TTS_Module.onPause()
    }
    override fun onDestroy() {
        super.onDestroy()
		// Destroy 일 때
        TTS_Module.onDestroy();
    }
}

설정

트랙백

댓글

[Kotlin] DataClass

Android (Kotlin) 2020. 9. 14. 22:29

1. 데이터 클래스 기능

equals() 
hashCode()
toString()
componentN()
copy()

data class Book(
	var name: String, 
    var authorName: String = "dudu", 
    var lastModified: Long = 1234567, 
    var rating: Float = 5f, 
    var downloads: Int = 1000
    )

fun main(args: Array<String>) {
	var book = Book("Android tutorials","Hup..", 1234567, 4.5f, 1000)

    	book = Book("Kotlin")
    	book = Book("Swift",downloads = 500)
    	book = Book("Java","zzz",rating = 5f, downloads = 1000)
    	book = Book("Python","YYY",rating = 5f)
        println(book.toString())
    val newBook = book.copy(name = "iOS dev")
    println("Hashcode is ${newBook.hashCode()}")
    if(!newBook.equals(book))
        println("newBook and book are NOT equal")
        
    println(book.component1()) //Python
    println(book.component2()) //YYY
    println(book.component3()) //1234567
    println(book.component4()) //5f
    println(book.component5()) //1000    
}
// 변수 이름을 사용하면 원하는 값만 선택적으로 입력 가능 하다. 
// toString()함수는 클래스의 값을 출력 한다.
// copy() 는 원하는 값만 변경하여 새로운 val 객채를 만들 수 있다.
// hashCode() 헤시코드를 반환 함.
// equals() " == " 과 같음.
// omponent(n) 생성자에 명시된 순서(n)에 맞는 개체로 접근

2. Destructuring

data class Book(val name: String, val authorName: String = "kaka", val lastModified: Long = 1234567, val rating: Float = 5f, val downloads: Int = 1000)

 val book = Book("Android tutorials","dudu", 1234567, 4.5f, 1000)
 val (n,a,date,rating,downloads) = book
 
 ==> 
 n = "Android tutorials"
 a = "dudu"
 date = 1234566
 rating = 4.5f
 downloads = 1000

equals() 
hashCode()
toString()
componentN()
copy()

설정

트랙백

댓글

[Kotlin] 클래스 정리

Android (Kotlin) 2020. 9. 13. 18:50

Class 기본 사용

class User {

    var loggedIn: Boolean = false
    val cantChangeValue = "Hi"
    
    fun logOn() {
        loggedIn = true
    }
    
    fun logOff() {
        loggedIn = false
    }
}

fun main(args: Array<String>) {

    val user = User()
    println(user.loggedIn) //false
    user.logOn()
    println(user.loggedIn) //true
    user.logOff()
    println(user.loggedIn) //false
    user.cantChangeValue = "Hey" //won't compile. Can't modify a final variable.

}

Class 생성자 "init"

예 1.) =============================

class MultiInit(name: String) {

    init {
        println("First initializer block that prints ${name}")
    }

    init {
        println("Second initializer block that prints ${name.length}")
    }
}

fun main(args: Array<String>) {
    var multiInit = MultiInit("Kotlin")
}

출력>>>>>>>
I/System.out: First initializer block that prints Kotlin
I/System.out: Second initializer block that prints 6


예 2.) ========= With "also"===========

class MultiInit(name: String) {
    val firstProperty = "First property: $name".also(::println)

    init {
        println("First initializer block that prints ${name}")
    }

    val secondProperty = "Second property: ${name.length}".also(::println)

    init {
        println("Second initializer block that prints ${name.length}")
    }
}

fun main(args: Array<String>) {

    var multiInit = MultiInit("Kotlin")
}

출력>>>>>>>
I/System.out: First property: Kotlin
I/System.out: First initializer block that prints Kotlin
I/System.out: Second property: 6
I/System.out: Second initializer block that prints 6

Class 보조 생성자 "constructor"

class Student {
    var name: String
    val age : Int

    constructor(name: String, age: Int)
    {
        this.name = name
        this.age = age
    }

    fun printDetails()
    {
        println("Name is $name and Age is $age")
    }

}

fun main(args: Array<String>) {

    var student = Student("gugu", 17)
    student.printDetails()
}

출력 >>>>>>>>
//Name is gugu and Age is 17

init + constructor

class Student(var name: String, val age: Int) {

    var skill: String

    init {
        skill = "play"
    }

    constructor(name: String, age: Int, skill: String) : this(name, age) {
        this.skill = skill
    }

    fun printDetails() {
        if (skill.equals("play"))
            println("Name is $name and Age is $age")
        else
            println("Name is $name and Age is $age Skill is $skill")
    }
}

I/System.out: Name is no-b-rain and Age is 1
I/System.out: Name is dudu and Age is 20 Skill is dodory

 

생성자의 인수 , 인수의 기본값 설정

예 1.) 
class User(name: String, val isAdmin: Boolean) {

    var username = name     //username = name
    val _isAdmin = isAdmin  //_isAdmin = isAdmin

    init {
        username= username + "https://no-b-rain.tistory.com/"
        println("Author Name is $name. Is Admin? $_isAdmin")
    }
}

fun main(args: Array<String>) {

    var user = User("no-b-rain",false)
    // Error Code : user.isAdmin = true  //won't compile since isAdmin is val
    // Error Code : user._isAdmin = true //won't compile. Same reason.
    user = User("no-Brain",true)
}



예 2.) 
class User(name: String, var website: String = "no-b-rain") {

    init {
        println("Author $name writes at $website")
    }

    init {
        website = website + ".com"
        println("Author $name writes at $website")
    }
}

fun main(args: Array<String>) {

    var user = User("no-b-rain","dudu")
    user = User("no-Brain","dudu")
}

I/System.out: Author no-b-rain writes at dudu
I/System.out: Author no-b-rain writes at dudu.com
I/System.out: Author no-Brain writes at dudu
I/System.out: Author no-Brain writes at dudu.com


커스텀  setter , getter

class Name{
    var post: String = "default"
    set(value) {if(!post.isNotEmpty()) {
        throw IllegalArgumentException(" Enter a valid name")
    }
                field = value
    }
    get() {
        return field.capitalize()
    }

}

fun main(args: Array<String>) {

    var name = Name()
    name.post = "kotlin classes"
    println(name.post)
    name.post = "kotlin data Classes our next Tutorial"
    println(name.post)

}

abstract

abstract class Person(name: String) {

    init {
        println("Abstract Class. init block. Person name is $name")
    }

    abstract fun displayAge()
}

class Teacher(name: String): Person(name) {

    var age : Int

    init {
        age = 24
    }

    override fun displayAge() {
        println("Non-abstract class displayAge function overridden. Age is $age")
    }
}

fun main(args: Array<String>) {

    val person = Teacher("Anupam")
    person.displayAge()

}

//Following is printed in the console.
//Abstract Class. init block. Person name is Anupam
//Non-abstract class. Age is 24

설정

트랙백

댓글

[Kotlin] 제어문 for , forEach , range , repeat , when

Android (Kotlin) 2020. 9. 13. 18:12

for in 

예 1.) ===============================================
for (i in 0..5) {
    print(i)
}

예 2.) ===============================================
val items = listOf(10, 20, 30, 40)

    for (i in items)
        println("value is $i")

//Following is printed to the console.
value is 10
value is 20
value is 30
value is 40

예 3. index 출력 "indices" ============================
val items = listOf(10, 20, 30, 40)

    for (i in items.indices)
        println("value is $i")

//Following is printed to the console:
value is 0
value is 1
value is 2
value is 3

예 4.) index 와 element 출력 "withIndex()" =============
val items = listOf(10, 20, 30, 40)

    for ((i,e) in items.withIndex())
        println("the index is $i and the element is $e")

//Following is printed on the console:
the index is 0 and the element is 10
the index is 1 and the element is 20
the index is 2 and the element is 30
the index is 3 and the element is 40

forEach   [ Range " ..  연산자 " ]

(2..5).forEach{
        println(it)
    }

//or

(2..5).forEach{
      i ->  println(i)
    }

//Following is printed on the console:
2
3
4
5

 

존재 여부 " in  , !in"

var x = 5

    if(x in 1..10)
    {
        print("x exists in range") //this gets printed
    }
    else{
        print("x does not exist in range")
    }

x = 15

    if(x !in 1..10)
    {
        print("x does not exist in range") //this gets printed
    }
    else{
        print("x does exist in range") 
    }
    

 Range ..는 역순으로 사용할 수 없음. -->  10..0 처럼 거꾸로 사용 못함.
 여기에서 downTo키워드를 사용

var x = 5

    if(x in 10 downTo 1)
    {
        print("x exists in range") //this gets printed
    }
    else{
        print("x does not exist in range")
    }

for (i in 5 downTo 0) 
print(i) //543210

마지막 요소를 제외 "until"

for (i in 1 until 4) {
     print(i)
}
//prints 123

단계적으로 범위를 탐색 "step"

for (i in 1..5 step 3) print(i) // prints 14

for (i in 4 downTo 1 step 2) print(i) // prints 42

N번 반복 실행 "repeat"

repeat(3) {
        println("Hello World!")
        println("Kotlin Control Flow")
    }

선택, 분기분 "when"

예 1.)
var num = 10
    when (num) {
        0 -> print("value is 0")
        5 -> print("value is 5")
        else -> {
            print("value is neither 0 nor 5") //this gets printed.
        }
    }
    
예 2.) until
var valueLessThan100 = when(101){
        in 1 until 101 -> true
        else -> {
            false
        }
    }
    
    print(valueLessThan100) //false
    

제어문 for , forEach , range , repeat , when

'Android (Kotlin)' 카테고리의 다른 글

[Kotlin] DataClass  (0) 2020.09.14
[Kotlin] 클래스 정리  (0) 2020.09.13
[Kotlin] let 과 also , Elvis 연산자 와 Null 값 필터링  (0) 2020.09.13
[Kotlin] Array 배열  (0) 2020.09.13
[Kotlin] String 문자열  (0) 2020.09.13

설정

트랙백

댓글

[Kotlin] let 과 also , Elvis 연산자 와 Null 값 필터링

Android (Kotlin) 2020. 9. 13. 17:28

Let function은 아래와 같이 참조가 nullable이 아닌 경우에만 지정된 람다 함수를 실행

newString = " Kotlin from Android"
newString?.let { println("The string value is: $it") }
newString = null
newString?.let { println("The string value is: $it") }

also 사용

var c = "Hello"

        var newString = "chenge string."
        newString?.let { c = it }.also {
            println("Logging the value: $it")
        }
        Log.d("TAG",c)
        
   -->   "chenge string."

Elvis 연산자  : Elvis 연산자를 ?:사용하면 아래와 같이 null 대신 기본값을 설정할 수 있다.

var newString : String?  = "JournalDev.com"
println(newString?.length) //prints 14
newString = null
println(newString?.length?:"-1") //prints -1

Null value filter

var array2: Array<Any?> = arrayOf("1", "2", "3", null)
var newArray = array2.filterNotNull()
println(newArray.size) //prints 

 

'Android (Kotlin)' 카테고리의 다른 글

[Kotlin] DataClass  (0) 2020.09.14
[Kotlin] 클래스 정리  (0) 2020.09.13
[Kotlin] 제어문 for , forEach , range , repeat , when  (0) 2020.09.13
[Kotlin] Array 배열  (0) 2020.09.13
[Kotlin] String 문자열  (0) 2020.09.13

설정

트랙백

댓글

[Kotlin] Array 배열

Android (Kotlin) 2020. 9. 13. 17:07

배열 기본 선언

val abcArray = arrayOf("A","B","C","D","E")
val tmpArray = arrayOf("A",1,1L,1.2,false)

배열 접근

val array1 = arrayOf(1,2,3,4)
val array3 = arrayOf<Long>(1,2,3,4)

array3.get(0)
array3[0]

array1[1] = 6
array1.set(1,6)

println("Size is ${array1.size}") //Size is 4

배열 특정 로직 반복

val array = Array(6) {i-> "Hi "+i}

for(element in array)
println(element)

//prints the following in the console
Hi 0
Hi 1
Hi 2
Hi 3
Hi 4
Hi 5

배열 반전 반환

var array1 = arrayOf(1,2,3,4)
array1 = array1.reversedArray()
    for(element in array1)
    {
        println(element)
    }
//Prints 4,3,2,1

배열 반전 - 변수 자체 반전 변경

var array1 = arrayOf(1,2,3,4)
array1.reverse()
    for(element in array1)
    {
        println(element)
    }
//prints 4,3,2,1

배열 합

var array1 = arrayOf(1,2,3,4)
println(array1.sum()) //prints 10

배열 추가

var array1 = arrayOf(1,2,3,4)
array1 = array1.plus(5)
//or
array1 = array1.plusElement(5)
    for(element in array1)
    {
        println(element)
    }
//prints 1,2,3,4,5

배열 값 체우기( 범위 지정 )

var array1 = arrayOf(1,2,3,4)
array1.fill(0,0,array1.size)
    for(element in array1)
    {
        println(element)
    }
//prints 0,0,0,0,0

배열에 배열 추가

var oldArray = Array(6, {i->i*10})
array1.fill(0,0,array1.size)
array1 = array1.plus(oldArray)

    for(element in array1)
    {
        println(element)
    }

 

설정

트랙백

댓글

[Kotlin] String 문자열

Android (Kotlin) 2020. 9. 13. 16:50

문자열 기본

var str: String  = "Hello"

//or
var str = "Hello"

var newString: String = 'A' //ERROR
var newString: String = 2 //ERROR

문자열 합치기 기본

var str  = "Hello"
str += "Kotlin Strings"

빈문자열

var s = String() //creates an empty string.

문자열 길이

val str = "Hello Kotlin Strings"
println(str.length) //prints 20

특정 위치 문자 반환

val str = "Hello Kotlin Strings"
println(str.get(0)) //print 'H'
println(str.subSequence(0,5)) //prints Hell

 문자열 비교

var str  = "Hello Kotlin Strings"
var s = String()
s = "Hello KOTLIN Strings"
println(s.compareTo(str)) //prints -32
println(s.compareTo(str,true)) //prints 0

문자열 이스케이프 문자

 

  • \n 개행.
  • \r 캐리지 리턴.
  • \t 탭.
  • \b 역행 키이
  • \" 큰 따옴표
  • \' 작은 따옴표
  • \\ 백 슬래시
  • \$ 달러 – 문자열 주입
var len = str.length
var newStr = "Length of str is ${str.length}"
//or
var newStr = "Length of str is $len"

println(Length of str is ${str.length})

Raw 문자열 (여러줄)

var rawString = """Hi How you're Doing
        I'm doing fine\n.
        I owe you $5.50"""
    print(rawString)

//prints the following
Hi How you're Doing
        I'm doing fine\n. /** \n 은 소용 없음. **/
        I owe you $5.50

Raw 문자열 (여러줄) - 줄바꿈

var rawString = """Hi How you're Doing
        |I'm doing fine.
        |I owe you $5.50""".trimMargin("|")
    print(rawString)
//Prints the following to the console.

Hi How you're Doing
I'm doing fine.
I owe you $5.50

String override

class Student(var name: String, var age: Int)
{

    override fun toString(): String {
        return "Student name is $name and age is $age"
    }
}

//The following code is written inside the main function of the Kotlin class.
var student = Student("Banana", 16)
print(student) //prints Student name is Banana and age is 16

비교 연산

  • Reference Equality  === : 두 개체의 포인터가 동일한 지 확인
  • Structural Equality == : 두 객체의 내용이 동일한 지 확인 

 

설정

트랙백

댓글