Sólo Programadores Banner 468x60
 
 
Este mes en Sólo Programadores
Contenido del CD-ROM
Índice temático
Suscripción
 
   

Programación Multimedia

RECONOCIMIENTO DE VOZ (V)

Durante este mes vamos a continuar con la segunda parte del listado que dejamos pendiente. Correspondía al proyecto DictaPad, el cual soportaba la funcionalidad de efectuar dictado y leer las palabras reconocidas mediante el motor de texto hablado.

Seguimos el listado con el procedimiento Capitalizeword, el cual cambia de minúsculas a mayúsculas y viceversa la primera letra de una palabra seleccionada. Mediante el método FX lograremos capitalizar la primera letra. Para ello, es necesario establecer el valor 3 en su parámetro, tal y como se muestra en el listado:

Private Sub capitalizeword_Click()

  s = RichTextBox1.selstart

  e = RichTextBox1.SelLength  

  Vdict1.Lock

  Vdict1.FX (3)   

  Vdict1.Unlock

  RichTextBox1.selstart = s

  RichTextBox1.SelLength = e

End Sub

Los siguientes procedimientos corresponden al botón de comienzo de dictado de la barra de herramientas. Si se pulsa dicho botón, se establecerá o eliminará el modo escucha para el engine de dictado mediante la función Listen.

Private Sub listening_Click()

  listen (1)

End Sub

Private Sub notlistening_Click()

  listen (0)

End Sub

ReadDocument es la opción de menú que permite al ordenador leer el texto contenido en la caja Richtext. Esto es posible mediante la utilización del engine de texto hablado. Si no hay un engine de este tipo instalado en el ordenador, el procedimiento no tendrá efecto. El objeto que representa al engine de texto hablado es DirectSS1.

Private Sub ReadDocument_Click()

  Dim ReadText As String


  On Error Resume Next  

Si al pulsar la opción de menú el engine está hablando, lo paramos mediante el procedimiento Stopreading_Click. Para comenzar a hablar, seleccionaremos el comienzo del texto y utilizaremos el método Speak del objeto DirectSS1.

If (DirectSS1.Speaking) Then

    Stopreading_Click

Else

    listen (0)

    Toolbar1.Buttons(15).Value = tbrPressed

    Toolbar1.Buttons(15).Image = 13

    gReadStart = RichTextBox1.selstart

    ReadText = Right$(RichTextBox1.Text, Len(RichTextBox1.Text) - RichTextBox1.selstart)

    DirectSS1.Speak ReadText

End If

End Sub

Private Function isTextBreak(c As String, breakchars As String)

For i = 1 To Len(breakchars)

    If c = Mid$(breakchars, i, 1) Then

        isTextBreak = True

        GoTo done

    End If

Next i

isTextBreak = False

done:

End Function

La función Findtextbreak se utiliza en conjunción con la función anterior Istextbreak para reducir el parpadeo (flicker) que se visualiza en la caja de texto Richtext cuando se obtienen cadenas de caracteres. Para ello, es necesario buscar la longitud de cada palabra mediante funciones estándar de Visual Basic Len y Mid$. Estas funciones no son necesarias para el funcionamiento del programa, pero crean un mejor aspecto visual en la representación del texto obtenido.

Private Function FindTextBreak

(direction As Integer, start As Integer, 

breakchars As String)

If (RichTextBox1.Text = "") Then

    FindTextBreak = 1

ElseIf (direction = 0) Then

    For i = start To 1 Step -1

        If (isTextBreak(Mid$

(RichTextBox1.Text, i, 1), breakchars)) 

Then

            FindTextBreak = i

            GoTo done

        End If

        

    Next i

    FindTextBreak = i

    GoTo done

Else

    For i = start To Len(RichTextBox1.Text)

        If (isTextBreak(Mid$

(RichTextBox1.Text, i + 1, 1), breakchars)) 

Then   FindTextBreak = i

            GoTo done

        End If

    Next i

    FindTextBreak = i

End If

done:

End Function

El siguiente procedimiento que vemos a continuación se ejecuta cuando se pulsa con el ratón sobre la caja de texto y normalmente se hace para seleccionar palabras. En la variable breakstring se definen una serie de caracteres que pueden delimitar la longitud de la palabra al ser encontrados:

Private Sub RichTextBox1_Click()

Dim breakstring As String


If (Alwaysselect.Checked) Then

    If RichTextBox1.selstart = 

Len(RichTextBox1.Text) Then GoTo setsel

        

    breakstring = " -_!@#$%^&*(),.[]+=`'""" 

+ vbNewLine + vbCrLf + vbCr + vbLf

    sStart = FindTextBreak(0, RichTextBox1

.selstart, breakstring)

    If (sStart  0) Then

        If (sStart = RichTextBox1.selstart And

 (Not isTextBreak(Mid$(RichTextBox1.Text, 

(sStart), 1), breakstring))) Then

            sStart = sStart - 1

            sEnd = sStart + 1

        Else

            GoTo findit

        End If

        

    Else

findit:

        sEnd = FindTextBreak(1, RichTextBox1

.selstart + RichTextBox1.SelLength, 

breakstring)

    End If

    RichTextBox1.selstart = sStart

    RichTextBox1.SelLength = sEnd - 

sStart

setsel:

    On Error GoTo done

Como se ha hecho anteriormente, para efectuar la selección de la palabra será necesario proteger y desproteger el objeto Vdict1 mediante los métodos Lock y Unlock.

Vdict1.Lock

    Vdict1.TextSelSet RichTextBox1.

selstart, RichTextBox1.SelLength

    Vdict1.Unlock


done:

End If

End Sub

Cuando se selecciona texto es necesario definir la posición de la selección (método TextSelSet). TextSet cambia un texto seleccionado definido por el comienzo y el número de caracteres que tenga. El texto será reemplazado.

Private Sub SetText(newText As String, 

ui As Boolean)

  Vdict1.Lock

  Vdict1.TextSelSet RichTextBox1.

selstart, 0

  Vdict1.TextSet newText, RichTextBox1.

selstart, RichTextBox1.SelLength, 65536

  Vdict1.Unlock

If (ui) Then

  RichTextBox1.SelText = newText

End If

End Sub

La caja de texto que representará los caracteres obtenidos de las palabras del usuario debe incluir varios procedimientos que permitan seleccionar palabras mal reconocidas para poder editarlas posteriormente.

De este modo nosotros gestionaremos este tipo de eventos cuando se levante el dedo sobre el botón del ratón y cuando se presione alguna tecla (MouseUp/Keypress).

Private Sub RichTextBox1_KeyPress

(KeyAscii As Integer)

  Dim s As String

  s = Chr$(KeyAscii)

  SetText s, False

  ShowCorrectionWindow (showcorrection.

Checked)

End Sub


Private Sub RichTextBox1_MouseUp(Button 

As Integer, Shift As Integer, 

x As Single, y As Single)

  Vdict1.Lock

  Vdict1.TextSelSet RichTextBox1.selstart,

 RichTextBox1.SelLength

  Vdict1.Unlock 

  ShowCorrectionWindow (showcorrection.Checked)

End Sub

Cuando se seleccione una palabra debe aparecer una ventana de corrección especializada. Para ello, visualizaremos este formulario mediante ShowCorrectionWindow.

Private Sub showcorrection_Click()

If (showcorrection.Checked) Then

    ShowCorrectionWindow (0)

Else

    ShowCorrectionWindow (1)

End If

End Sub

Para parar la lectura del documento obtenido debemos aplicar al objeto DirectSS1 el método AudioReset. Recordemos que DirectSS1 es el objeto que representa al engine de texto hablado.

Private Sub Stopreading_Click()

  DirectSS1.AudioReset

End Sub

TextChanged es uno de los procedimientos más importantes del programa y se llama de forma automática cada vez que se cambia el texto por el objeto de dictado (no por el usuario). Si cuando obtiene texto obtiene palabras erróneas, intentará sustituirlas por otras que se asemejen bastante.

También será necesario proteger y desproteger el objeto Vdict1 (métodos Lock/ Un Lock) para no incurrir en errores de protección y aplicar los cambios sin problemas.

Private Sub Vdict1_TextChanged

(ByVal reason As Long)

Dim newStart As Long

Dim newend As Long

Dim oldStart As Long

Dim oldEnd As Long

Dim selstart As Long

Dim sellen As Long

Dim theText As String


Vdict1.Lock

On Error GoTo spuriouserror

Mediante el método GetChanges tomamos las diferencias y actualizamos la caja Richtext que visualiza las palabras:

Vdict1.GetChanges newStart, newend, 

oldStart, oldEnd

If (oldStart < oldEnd) Then

    RichTextBox1.selstart = oldStart

    RichTextBox1.SelLength = oldEnd - 

oldStart

    RichTextBox1.SelText = ""

End If


If (newend > newStart) Then

    RichTextBox1.selstart = newStart

    RichTextBox1.SelLength = 0

    Vdict1.TextGet newStart, newend - 

newStart, theText

    RichTextBox1.SelText = theText

End If

    ShowCorrectionWindow 2

    spuriouserror:

Vdict1.Unlock

End Sub

Open_Click es llamado cuando se carga un nuevo archivo de texto en la caja RichText. Podemos seleccionar tres tipos de archivos:

- TXT: archivo de texto
- MSD: archivo de Microsoft Dictation
- RTF: archivo de tipo Richtext
Private Sub open_Click()

  Dim versionstring As String

  Dim fn As String

  Dim fs As Long

  Dim fi As Long

  Dim fb As Long

  Dim fu As Long

  Dim fst As Long


  CommonDialog1.ShowOpen

  If (CommonDialog1.filename  "") Then

    New_Click

    gThisFile = CommonDialog1.filename

El método CreateStream del objeto Vdict1 se utiliza para crear un nuevo documento del tipo MSD. El segundo flag que se utiliza en sus parámetros debe ser 18, ya que es el único valor aceptado por la API hasta el momento.

If (Right(gThisFile, 3) = "msd") Then

        hand = Vdict1.CreateDocFile

(gThisFile, 18)

        stream2 = Vdict1.CreateStream

(hand, "Version", 18)

Vdict1.StreamRead stream2, versionstring, 36

Chequeamos si la versión del archivo se corresponde a un fichero MSD:

If versionstring "46FC730A-D849-11d0-AB8A-08002BE4E3B7" Then dummy = MsgBox("Error. Formato inválido", vbOK, "Formato inválido") En caso de no ser un archivo MSD, utilizaremos el método CreateStream para la carga del archivo. El primer parámetro dónde se almacenará el archivo (handler), el segundo representa el nombre de este handler para diferenciarlo. Por último asignaremos el valor 18 al último parámetro tal y como hemos hecho anteriormente.

Else

            stream = Vdict1.CreateStream

(hand, "Header", 18)

            Vdict1.ReadStreamFont stream,

 fn, fs, fi, fb, fu, fst

            Vdict1.ReleaseStream stream

            Vdict1.SessionDeserialize hand

            RichTextBox1.Font.Name = fn

            If (fs < 0) Then

                fs = -fs

            End If

            RichTextBox1.Font.Size = fs

            RichTextBox1.Font.Italic = fi

            RichTextBox1.Font.Bold = fb

            RichTextBox1.Font.Underline = fu

        End If

Finalmente, vaciamos el handler utilizado y su objeto.

Vdict1.ReleaseStream stream2

        Vdict1.ReleaseStore hand

    Else

        RichTextBox1.filename = 

CommonDialog1.filename

        gThisFile = RichTextBox1.filename

        SetText RichTextBox1.Text, False

    End If

End If


End Sub

Para cambiar las opciones de dictado que permite el engine (cambio de usuario, sensibilidad de reconocimiento, etc.) utilizaremos el método GeneralDlg. En la siguiente imagen se puede apreciar el formulario que se visualizará al activar esta opción:

Private Sub Options_Click()

Vdict1.GeneralDlg Form5.hwnd, "Opciones de Dictado"

End Sub

Es necesario crear un procedimiento para guardar el archivo con el que estamos trabajando actualmente. Para ello, utilizaremos DoSave:

Private Sub DoSave()

Dim hand As Long

Dim fs As Long

Dim fi As Long

Dim fb As Long

Dim fu As Long

Dim fst As Long

Seguidamente crearemos el código para la grabación de los archivos MSD:

If (Right(gThisFile, 3) = "msd") Then

    fs = -RichTextBox1.Font.Size

    fi = RichTextBox1.Font.Italic

    fb = RichTextBox1.Font.Bold

    fu = RichTextBox1.Font.Underline

    fst = False

    

    hand = Vdict1.CreateDocFile(gThisFile,

 18)

    stream = Vdict1.CreateStream(hand, 

"Header", 18)

    Vdict1.SetSize stream, 0

    Vdict1.WriteStreamFont stream, RichTextBox1.

Font.Name, fs, fi, fb, fu, fst

SessionSerialize guarda el estado actual del dictado al handler asignado (hand). La información incluirá todo el texto del buffer, el resultado de los objetos asociados con el texto y los marcadores. Una aplicación puede volver a cargar una sesión utilizando el método SessionDeSerialize.

Vdict1.SessionSerialize hand

    stream2 = Vdict1.CreateStream

(hand, "Version", 18)

    Vdict1.SetSize stream2, 0

    Vdict1.StreamWrite stream2, "46FC730A-D849-11d0-AB8A-08002BE4E3B7"

    Vdict1.ReleaseStream stream

    Vdict1.ReleaseStream stream2

    Vdict1.ReleaseStore hand

Creamos el código para la grabación de archivos RTF:

ElseIf (Right(gThisFile, 3) = "rtf") 

Then

    Open gThisFile For Output As 1

    Print #1, RichTextBox1.TextRTF

    Close 1

Else

Creamos el código para la grabación de archivos TXT:

Open gThisFile For Output As 1

    Print #1, RichTextBox1.Text

    Close 1

End If

End Sub

El procedimiento Listen se utiliza para activar o desactivar la escucha del engine de dictado sobre el usuario. Mediante el método Mode se establece el estado de escucha utilizando alguno de estos flags:

- VSRMODE_DISABLED
  Dictado y command and control desactivados.
- VSRMODE_OFF
  Speech desactivado.
- -VSRMODE_CMDPAUSED
  Speech en pausa (a la escucha para que un comando que lo despierte).
- VSRMODE_CMDONLY
  Command and control activado. Dictado desactivado.
- VSRMODE_DCTONLY
  Dictado activado. Command and control desactivado.
- VSRMODE_CMDANDDCT

Los dos engines activados al mismo tiempo. Esto sólo es posible si el en

Public Sub listen(op As Integer)

  If (op = 1) Then
            Stopreading_Click
            Vdict1.Mode = 32
  On Error GoTo NoActivate
            Vdict1.Activate
  NoActivate:
    Else
           Vdict1.Mode = 2
  On Error GoTo NoDeactivate
            Vdict1.Deactivate
  NoDeactivate:
      
  End If
  ListenUI (op)
  GoTo NoError
  ErrorMessage: 
    MsgBox "ERROR. Debe haber 
un engine instalado."
  End
  NoError:
End Sub

Finalizando el recorrido por los procedimientos más importantes del programa, llegamos al punto en el que nos encontramos con el procedimiento encargado de gestionar la barra de estado que contiene los botones de acceso rápido.

Podemos utilizar una propiedad denominada Key de SelectCase para poder así especificar la acción determinada que necesitamos realizar en cada momento.

Private Sub toolbar1_ButtonClick(ByVal Button As Button)
    Select Case Button.Key
    Case Is = "cut"
        Cut_Click
    Case Is = "cutall"
        SelectAll_Click
        Cut_Click
    Case Is = "copy"
        Copy_Click
    Case Is = "paste"
        Paste_Click
    Case Is = "new"
        New_Click
    Case Is = "save"
        save_Click
    Case Is = "open"
        open_Click
    Case Is = "listen"
        If (listening.Checked) Then
            listen (0)
        Else
            listen (1)
        End If
    Case Is = "showhide"
        showcorrection_Click
    Case Is = "capitalizeword"
        capitalizeword_Click
    Case Is = "addword"
        Addword_Click
    Case Is = "read"
        ReadDocument_Click
    End Select
End Sub

PRÓXIMAMENTE

En el siguiente número de esta serie de reconocimiento de voz veremos un programa sumamente útil de cara al usuario final.

Se trata de un programa que nos avisará, hablando, de los nuevos e-mails que hayamos recibido, diciéndonos el asunto del que trata el mensaje de viva voz.


   
 
  Banner 468x60
  Explorer 4.0, Netscape 4.0. Resolución 800 x 600.
©Tower Communications 1.998.
Diseño: GRUPO ALBERTINA DE COMUNICACION.