Me encontraba jugando Minecraft en la nueva snapshot 17w14a y vi que implementaron una nueva funcionalidad la cual es un narrador, es decir una voz lee todo lo que parece en el chat y fue cuando me dije ¿Joder, cómo lo hicieron? generalmente este tipo de cosas utiliza muchos recursos.
Lo primero fue ubicar que biblioteca utilizan, para eso explore la carpeta del juego y encontré algo.
Al parecer es una biblioteca creada por Mojang. Bueno es hora de ver que tiene, al pasar por el descompilador obtuve lo siguiente:
¿Es todo? ¿Dónde esta el resto? Básicamente lo que hacen los de Mojang es invocar otro programa desde java, es decir un wrapper.
¿Pero que programa invocan? viendo las clases encontré que usan un jni para ejecutar una biblioteca en c llamada libfliteWrapper.so
De nuevo descompilando libfliteWrapper.so obtenemos:
Vemos que existe una función llamada "say" como parametro el texto a leer y dentro de la función llama al programa llamado "play" ¿pero que es play?
Pero play solo reproduce sonido ¿cómo es que hace la voz? no encontre forma pero encontré otra forma de generar la voz, usando ffplay.
Esta es la misma voz que escucho en Minecraft.
Es hora de utilizar la biblioteca.
¿Y si creamos una versión en español del narrador de Minecraft?
Lo que tenemos que hacer es crear una nuevo wrapper pero utilizando espeak y usando una voz en español.
Creamos filterWrapper.h
Y en filterWrapper.cc
Compilamos la biblioteca.
Ya tenemos la voz en español.
Codigo GitHub
Lo primero fue ubicar que biblioteca utilizan, para eso explore la carpeta del juego y encontré algo.
.minecraft/libraries/com/mojang/text2speech/1.5/text2speech-1.5.jar
Al parecer es una biblioteca creada por Mojang. Bueno es hora de ver que tiene, al pasar por el descompilador obtuve lo siguiente:
¿Es todo? ¿Dónde esta el resto? Básicamente lo que hacen los de Mojang es invocar otro programa desde java, es decir un wrapper.
¿Pero que programa invocan? viendo las clases encontré que usan un jni para ejecutar una biblioteca en c llamada libfliteWrapper.so
De nuevo descompilando libfliteWrapper.so obtenemos:
man play
Pero play solo reproduce sonido ¿cómo es que hace la voz? no encontre forma pero encontré otra forma de generar la voz, usando ffplay.
ffplay -f lavfi flite=text="Hello world!!!."
Esta es la misma voz que escucho en Minecraft.
Es hora de utilizar la biblioteca.
import com.mojang.text2speech.Narrator; public class App { public static void main(String[] args) { /* Ubicacion de la biblioteca */ System.setProperty("jna.library.path", "./src/natives/resources/"); Narrator narrator = Narrator.getNarrator(); narrator.say("Hola mundo!!!!"); while (true) { try { Thread.sleep(100L); System.exit(0); } catch (InterruptedException arg2) { arg2.printStackTrace(); } } } }
¿Y si creamos una versión en español del narrador de Minecraft?
Lo que tenemos que hacer es crear una nuevo wrapper pero utilizando espeak y usando una voz en español.
Creamos filterWrapper.h
#ifndef FLITE_H #define FLITE_H void init(); void say (char *msg); #endif
Y en filterWrapper.cc
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "fliteWrapper.h" void init(){ } void say (char *msg){ char cmd[1024]; memset(cmd, '\0', 1024); strncat(cmd, "espeak -ves+f5 \"", 16); strncat(cmd, msg, 1000); strncat(cmd, "\"", 1); system(cmd); }
Compilamos la biblioteca.
gcc -fPIC -c fliteWrapper.c gcc -shared -o libfliteWrapper.so fliteWrapper.o
Ya tenemos la voz en español.
Codigo GitHub