Skip to content

Proyecto final para la asignatura de Gestión de Proyectos de Software

Notifications You must be signed in to change notification settings

AlfredooP/VoxMate

Repository files navigation

<uses-permission android:name="android.permission.RECORD_AUDIO"/>

<application
    android:allowBackup="true"
    android:label="Asistente de Voz"
    android:theme="@style/Theme.Material3.DayNight.NoActionBar">

    <activity android:name=".MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>

</application>
package com.tunombre.asistente

import android.Manifest import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.result.contract.ActivityResultContracts import androidx.lifecycle.viewmodel.compose.viewModel import com.tunombre.asistente.ui.AssistantScreen

class MainActivity : ComponentActivity() {

private val requestPermission = registerForActivityResult(
    ActivityResultContracts.RequestPermission()
) { }

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    requestPermission.launch(Manifest.permission.RECORD_AUDIO)

    setContent {
        val vm: AssistantViewModel = viewModel()
        AssistantScreen(vm)
    }
}

}

package com.tunombre.asistente.voice

import android.content.Context import android.content.Intent import android.os.Bundle import android.speech.RecognitionListener import android.speech.RecognizerIntent import android.speech.SpeechRecognizer

class VoiceToTextManager( private val context: Context, private val onTextReady: (String) -> Unit, private val onError: (String) -> Unit ) {

private var recognizer: SpeechRecognizer? = null

fun start() {
    recognizer = SpeechRecognizer.createSpeechRecognizer(context)

    val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
        putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
        putExtra(RecognizerIntent.EXTRA_LANGUAGE, "es-MX")
        putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true)
    }

    recognizer?.setRecognitionListener(object : RecognitionListener {

        override fun onResults(results: Bundle?) {
            val text = results
                ?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)
                ?.getOrNull(0)
            onTextReady(text ?: "")
        }

        override fun onPartialResults(partialResults: Bundle?) {
            val text = partialResults
                ?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)
                ?.getOrNull(0)
            if (!text.isNullOrBlank()) onTextReady(text)
        }

        override fun onError(error: Int) {
            onError("Error de voz: $error")
        }

        override fun onReadyForSpeech(params: Bundle?) {}
        override fun onBeginningOfSpeech() {}
        override fun onRmsChanged(rmsdB: Float) {}
        override fun onBufferReceived(buffer: ByteArray?) {}
        override fun onEndOfSpeech() {}
        override fun onEvent(eventType: Int, params: Bundle?) {}
    })

    recognizer?.startListening(intent)
}

fun stop() {
    recognizer?.stopListening()
    recognizer?.destroy()
    recognizer = null
}

} package com.tunombre.asistente.voice

import android.content.Context import android.speech.tts.TextToSpeech

class VoiceSpeaker(context: Context) {

private val tts = TextToSpeech(context) {}

fun speak(text: String) {
    tts.speak(text, TextToSpeech.QUEUE_FLUSH, null, null)
}

fun shutdown() {
    tts.shutdown()
}

}

package com.tunombre.asistente

import android.app.Application import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.MutableLiveData import com.tunombre.asistente.voice.VoiceToTextManager import com.tunombre.asistente.voice.VoiceSpeaker import java.time.LocalTime

class AssistantViewModel(application: Application) : AndroidViewModel(application) {

val heardText = MutableLiveData("")
val responseText = MutableLiveData("")

private val speaker = VoiceSpeaker(application)

private val listener = VoiceToTextManager(
    application,
    onTextReady = { process(it) },
    onError = { responseText.postValue(it) }
)

fun startListening() = listener.start()
fun stopListening() = listener.stop()

private fun process(text: String) {
    heardText.postValue(text)

    val response =
        when {
            text.contains("hora", ignoreCase = true) ->
                "Son las ${LocalTime.now().withNano(0)}"

            text.contains("hola", ignoreCase = true) ->
                "Hola, ¿en qué puedo ayudarte?"

            text.contains("cómo estás", ignoreCase = true) ->
                "Estoy funcionando perfectamente."

            text.contains("tu nombre", ignoreCase = true) ->
                "Soy tu asistente de voz personal."

            else ->
                "No entendí eso, pero puedo seguir aprendiendo."
        }

    responseText.postValue(response)
    speaker.speak(response)
}

override fun onCleared() {
    super.onCleared()
    speaker.shutdown()
}

} package com.tunombre.asistente.ui

import androidx.compose.foundation.layout.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.tunombre.asistente.AssistantViewModel

@Composable fun AssistantScreen(vm: AssistantViewModel) {

val heard by vm.heardText.observeAsState("")
val response by vm.responseText.observeAsState("")

Column(
    modifier = Modifier
        .fillMaxSize()
        .padding(20.dp)
) {

    Text("Te escuché:", style = MaterialTheme.typography.titleMedium)
    Text(heard, style = MaterialTheme.typography.bodyLarge)
    Spacer(Modifier.height(30.dp))

    Text("Asistente:", style = MaterialTheme.typography.titleMedium)
    Text(response, style = MaterialTheme.typography.bodyLarge)
    Spacer(Modifier.height(40.dp))

    Button(
        onClick = { vm.startListening() },
        modifier = Modifier.fillMaxWidth()
    ) {
        Text("Hablar")
    }

    Spacer(Modifier.height(10.dp))

    Button(
        onClick = { vm.stopListening() },
        modifier = Modifier.fillMaxWidth()
    ) {
        Text("Detener")
    }
}

}

About

Proyecto final para la asignatura de Gestión de Proyectos de Software

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages