Welcome, Guest
Username: Password: Remember me
Qui si parla italiano
  • Page:
  • 1

TOPIC:

Eseguire un file audio 04 Feb 2022 17:19 #21446

  • claudiocarletta
  • claudiocarletta's Avatar
  • Topic Author


  • Posts: 94
  • Salve a tutti,
    ho la necessità di allertare gli utenti con un messaggio sonoro (file audio) al verificarsi di un evento sul database MySQL. L'applicazione potrebbe essere iconizzata o addirittura non presidiata (l'utente potrebbe essere occupato nell'ufficio adiacente)
    C'è un modo per "eseguire" un file audio in background?
    Pensavo di utilizzare
    SELF:RegisterTimer(30, false)
    per eseguire ogni 30 secondi il
    METHOD Timer()
    per controllare il database e nell'eventualità ci fosse bisogno dell'intervento dell'operatore eseguire il file audio per richiamare l'attenzione dell'operatore.
    Vi ricordo che adopero X# nel dialetto VO

    Grazie a tutti
    Claudio

    Please Log in or Create an account to join the conversation.

    Last edit: by claudiocarletta.

    Eseguire un file audio 04 Feb 2022 17:43 #21449

    • softdevo@tiscali.it's Avatar


  • Posts: 177
  • Puoi usare la classe System.Speech.Synthesis.SpeechSynthesizer che ti permette di far parlare il tuo PC facendogli "leggere" una qualsiasi stringa con la velocità ed il volume che vuoi.
    Ho estratto da una mia applicazione quello che serve,spero di aver messo tutto, contattami se ho dimenticato qualcosa.

    Danilo

    FUNCTION Parla(cTesto AS STRING) AS VOID
    LOCAL _Lettura AS Lettura
    _Lettura := Lettura{}
    _Lettura:ImpostaVoce()
    _Lettura:Voce(cTesto,TRUE)
    _Lettura:ChiudiParlato()
    RETURN

    CLASS Lettura
    EXPORT oVoce AS System.Speech.Synthesis.SpeechSynthesizer
    EXPORT Nome_SV AS STRING
    EXPORT nVolume AS INT
    EXPORT nRate AS INT
    EXPORT Nome AS STRING
    EXPORT Attivo AS STRING
    METHOD ImpostaVoce() AS VOID
    LOCAL oXMLFile AS XML_File
    LOCAL cVolume,cRate AS STRING
    /*
    Microsoft Elsa Desktop - Italian (Italy)
    Microsoft Zira Desktop - English (United States)
    ScanSoft Silvia_Dri40_16kHz
    */
    SELF:Nome_SV := "Microsoft Elsa Desktop" //"ScanSoft Silvia_Dri40_16kHz"
    SELF:nVolume := 100
    SELF:nRate := -3

    IF File(WorkDir()+"parla.xml")
    oXMLFile := XML_File{WorkDir()+"parla.xml"}
    IF oXMLFile:ExistSection("SET")
    SELF:Nome_SV := iif(!Empty(oXMLFile:GetEntry("SET","NOME")),oXMLFile:GetEntry("SET","NOME"),"ScanSoft Silvia_Dri40_16kHz")
    cVolume := iif(!Empty(oXMLFile:GetEntry("SET","VOLUME")),oXMLFile:GetEntry("SET","VOLUME"),"30")
    SELF:nVolume := Val(cVolume)
    cRate := iif(!Empty(oXMLFile:GetEntry("SET","RATE")),oXMLFile:GetEntry("SET","RATE"),"-3")
    SELF:nRate := Val(cRate)
    IF SELF:nRate > 10
    SELF:nRate := 10
    ENDIF
    IF SELF:nRate < -10
    SELF:nRate := -10
    ENDIF
    ENDIF
    ENDIF

    IF !Empty(SELF:Nome_SV) //Contiene il nome della Dll
    SELF:oVoce := System.Speech.Synthesis.SpeechSynthesizer{}
    SELF:oVoce:SelectVoice(SELF:Nome_SV) //Self:Nome_SV
    SELF:oVoce:SelectVoiceByHints(System.Speech.Synthesis.VoiceGender.Female , System.Speech.Synthesis.VoiceAge.Adult)
    SELF:oVoce:Rate := SELF:nRate
    SELF:oVoce:Volume := SELF:nVolume //contiene il valore della variabile Self:nVolume: 0=nessun volume 30=medio basso
    // Voce("benvenuti nel programma di gestione del parlato",TRUE)
    ELSE
    SELF:oVoce := NULL_OBJECT
    ENDIF

    RETURN
    METHOD ScriviImpostaVoce() AS VOID
    LOCAL oXMLFile AS XML_File
    LOCAL oStream AS System.IO.StreamWriter
    LOCAL cTesto AS STRING
    LOCAL cSpazi AS STRING

    IF File(WorkDir()+"parla.xml")
    oXMLFile := XML_File{WorkDir()+"parla.xml"}
    oXMLFile:WriteEntry( "SET", "NOME",SELF:Nome_SV)
    oXMLFile:WriteEntry( "SET", "VOLUME",NTrim(SELF:nVolume))
    oXMLFile:WriteEntry( "SET", "RATE",NTrim(SELF:nRate))
    //oXMLFile:WriteEntry( "SET", "LINGUA",SELF:Lingua)
    oXMLFile:WriteEntry( "SET", "ATTIVO",SELF:Attivo)
    oXMLFile:Close()
    ELSE
    cSpazi := Space(2)
    cTesto := "<?xml version='1.0' encoding='utf-8' ?>"+CRLF
    cTesto += "<Configurazione>"+CRLF
    cTesto += cSpazi+"<SET>"+CRLF
    cSpazi := Space(4)
    cTesto += cSpazi+"<NOME>"+SELF:Nome_SV+"</NOME>"+CRLF
    cTesto += cSpazi+"<VOLUME>"+NTrim(SELF:nVolume)+"</VOLUME>"+CRLF
    cTesto += cSpazi+"<RATE>"+NTrim(SELF:nRate)+"</RATE>"+CRLF
    cTesto += cSpazi+"<ATTIVO>"+SELF:Attivo+"</ATTIVO>"+CRLF
    cSpazi := Space(2)
    cTesto += cSpazi+"</SET>"+CRLF
    cTesto += "</Configurazione>"+CRLF

    oStream := System.IO.StreamWriter{WorkDir()+"parla.xml"}
    oStream:Write(cTesto)
    oStream:Close()
    ENDIF

    RETURN

    METHOD ChiudiParlato() AS VOID
    //5) Per chiudere, quando esci dal programma:
    IF IsInstanceOf(SELF:oVoce,"SpeechSynthesizer")
    SELF:oVoce:Dispose()
    ENDIF
    RETURN

    METHOD Voce(cTesto AS STRING,lFlag := FALSE AS LOGIC) AS VOID

    IF IsInstanceOf(SELF:oVoce,"SpeechSynthesizer")
    IF lFlag
    SELF:oVoce:Speak(cTesto) //il programma si blocca fino alla fine della lettura del testo
    ELSE
    SELF:oVoce:SpeakAsync(cTesto) //Il programma continua l'esecuzione mentre parla
    ENDIF
    ENDIF

    RETURN
    METHOD Stop() AS VOID

    IF IsInstanceOf(SELF:oVoce,"SpeechSynthesizer")
    SELF:oVoce:Speak("") //il programma si blocca fino alla fine della lettura del testo
    ENDIF

    RETURN

    METHOD Avviso(cTesto AS STRING) AS VOID //Oppure la tua Mostra
    SELF:Voce(cTesto) //Viele letto il testo
    System.Windows.Forms.MessageBox.Show(cTesto,"Avviso",System.Windows.Forms.MessageBoxButtons.OK,System.Windows.Forms.MessageBoxIcon.Information)
    RETURN

    END CLASS

    #USING System.IO
    #USING System.Data
    #USING System.Windows.Forms

    CLASS XML_File
    PROTECT cFileXML AS STRING
    PROTECT oDataTable AS DataTable //La tabella corrente (il nodo e le variabili)

    PROTECT oDataSet AS DataSet //Contiene la struttura delfile XML
    //Tante tabelle quanti sono i nodi, tante colonne
    // quanto sono le variabili del nodo e tante
    //righe quanti sono i nodi ripetuti.

    PROTECT nNodi AS INT //Contiene il numero di tabelle lette dall'XML
    //Ogni nodo è una tabella

    PROTECT cSezione AS STRING // La tabella/il nodo corrente
    PROTECT cVariabile AS STRING
    PROTECT cValore AS STRING

    PROTECT aSezioni AS ARRAY //Contiene il nome delle tabelle e la posizione
    //nel DataSet

    PROTECT aColonne AS ARRAY //Contiene le colonne della tabella

    CONSTRUCTOR(cFile := "" AS STRING)

    IF ! Empty(cFile)
    IF File.Exists(cFile)
    SELF:cFileXML := cFile
    SELF:oDataSet := DataSet{}
    SELF:oDataSet:ReadXml(SELF:cFileXML)

    SELF:LeggiSezioni()
    SELF:GetSection(SELF:aSezioni[1,1])
    ELSE
    MessageBox.Show("Attenzione, il file "+cFile+" non esiste." ,"Avviso",MessageBoxButtons.OK,MessageBoxIcon.Information)
    ENDIF
    ENDIF
    RETURN

    METHOD CreateFile(cFile AS STRING) AS VOID

    SELF:oDataSet := DataSet{}
    SELF:oDataSet:ReadXml(cFile)

    SELF:LeggiSezioni()
    SELF:GetSection(SELF:aSezioni[1,1])

    RETURN

    METHOD CreateSection(cNomeSezione AS STRING,cNomeVariabile := "" AS STRING,cValore := "" AS STRING) AS VOID
    LOCAL oTable AS DataTable
    LOCAL oColonna AS System.Data.DataColumn
    LOCAL oDataRow AS DataRow

    IF ! Empty(cNomeSezione) .and. ! Empty(cNomeVariabile)
    oTable := DataTable{}
    oTable:TableName := Upper(cNomeSezione)
    oColonna := DataColumn{}
    oColonna:DataType := System.Type.GetType("System.String")
    oColonna:ColumnName := Upper(cNomeVariabile)
    oTable:Columns:Add(oColonna)
    oDataRow := oTable:NewRow()
    oDataRow[cNomeVariabile] := cValore
    oTable:Rows:Add(oDataRow)
    SELF:oDataSet:Tables:Add(oTable)
    SELF:LeggiSezioni()
    ENDIF
    RETURN
    METHOD DeleteSection(uNomeNodo AS USUAL) AS LOGIC
    LOCAL lOK := FALSE AS LOGIC
    LOCAL nPos AS INT
    LOCAL cNomeTabella AS STRING

    IF ValType(uNomeNodo) == "C"
    nPos := (INT) AScan(SELF:aSezioni,{|x| Upper(x[1]) == Upper(uNomeNodo)})
    ELSEIF ValType(uNomeNodo) == "N"
    nPos := (INT) AScan(SELF:aSezioni,{|x| x[2] == uNomeNodo})
    ENDIF
    IF nPos > 0
    cNomeTabella := SELF:aSezioni[nPos,1]
    SELF:oDataSet:Tables:Remove(cNomeTabella)
    SELF:LeggiSezioni()
    lOK := TRUE
    ENDIF

    RETURN lOK

    METHOD CreateElement(cElemento AS STRING,cValore AS STRING,nPos := 0 AS INT) AS VOID
    LOCAL nCol AS INT

    SELF:oDataTable:Columns:Add(cElemento)
    nCol := SELF:oDataTable:Columns:Count -1
    SELF:oDataTable:Rows[nPos]:Item[nCol] := cValore
    SELF:LeggiColonne(SELF:oDataTable)
    RETURN
    METHOD DeleteColumn(cSezione AS STRING, uElemento AS STRING) AS VOID
    LOCAL nPos AS INT

    SELF:GetSection(cSezione)
    nPos := (INT) AScan(SELF:aColonne,{|x| Upper(x[1]) == Upper(uElemento)})
    IF nPos > 0
    SELF:oDataTable:Columns:RemoveAt(nPos-1)
    SELF:LeggiColonne(SELF:oDataTable)
    SELF:SaveXML(SELF:cFileXML)
    ENDIF

    RETURN

    METHOD DeleteElement(uElemento AS USUAL) AS VOID
    LOCAL nPos AS INT

    IF ValType(uElemento) == "C"
    nPos := (INT) AScan(SELF:aColonne,{|x| Upper(x[1]) == Upper(uElemento)})
    ELSEIF ValType(uElemento) == "N"
    nPos := (INT) AScan(SELF:aColonne,{|x| x[2] == uElemento})
    ENDIF
    IF nPos > 0
    SELF:oDataTable:Columns:RemoveAt(nPos-1)
    SELF:LeggiColonne(SELF:oDataTable)
    ENDIF
    RETURN

    METHOD DeleteValue(cNomeSezione AS STRING,cColonna AS STRING, cValore AS STRING) AS VOID
    LOCAL oDataView AS DataView
    LOCAL n AS INT

    SELF:GetSection(cNomeSezione)
    oDataView := DataView{SELF:oDataTable}

    oDataView:Sort := cColonna
    n := oDataView:Find(cValore)
    IF n <> -1
    oDataView:Delete(n)
    ENDIF
    SELF:SaveXML(SELF:cFileXML)
    RETURN

    METHOD ExistSection(cNomeSezione AS STRING) AS LOGIC
    RETURN ((INT) AScan(SELF:aSezioni,{|x| Upper(x[1]) == Upper(cNomeSezione)})) > 0

    METHOD GetNodi() AS INT
    RETURN SELF:nNodi
    METHOD GetEntry(cNomeSezione AS STRING,cNomeVariabile AS STRING) AS STRING
    LOCAL cValore AS STRING
    LOCAL nPos AS INT
    LOCAL oTable AS DataTable

    TRY
    cValore := ""
    IF ! Empty(cNomeSezione) .and. ! Empty(cNomeVariabile)
    IF (SELF:oDataTable:TableName == cNomeSezione)
    cValore := Convert.ToString(SELF:oDataTable:Rows[0]:Item[cNomeVariabile])
    ELSE
    nPos := (INT) AScan(SELF:aSezioni,{|x| Upper(x[1]) == Upper(cNomeSezione)})
    IF nPos > 0
    oTable := SELF:oDataSet:Tables[nPos-1]
    IF SELF:oDataSet:Tables[nPos-1]:Columns:Contains(cNomeVariabile)
    cValore := Convert.ToString(oTable:Rows[0]:Item[cNomeVariabile])
    ELSE
    cValore := ""
    ENDIF
    ENDIF
    ENDIF
    ENDIF
    CATCH
    cValore := ""
    END TRY

    RETURN cValore

    METHOD GetSection(uNomeNodo AS USUAL) AS DataTable
    LOCAL nPos AS INT

    SELF:oDataTable := DataTable{}
    IF ValType(uNomeNodo) == "C"
    nPos := (INT) AScan(SELF:aSezioni,{|x| Upper(x[1]) == Upper(uNomeNodo)})
    ELSEIF ValType(uNomeNodo) == "N"
    nPos := (INT) AScan(SELF:aSezioni,{|x| x[2] == uNomeNodo})
    ENDIF
    IF nPos > 0
    SELF:oDataTable := SELF:oDataSet:Tables[nPos-1]
    SELF:LeggiColonne(SELF:oDataTable)
    ENDIF
    RETURN SELF:oDataTable

    METHOD GetArraySection(uNomeNodo AS USUAL) AS ARRAY
    LOCAL nCount,xx AS INT
    LOCAL aMat AS ARRAY

    SELF:GetSection(uNomeNodo)
    nCount := SELF:oDataTable:Columns:Count
    aMat := {}
    FOR xx := 0 UPTO nCount - 1
    AAdd(aMat,{SELF:oDataTable:Columns[xx]:ColumnName,Convert.ToString(SELF:oDataTable:Rows[0]:Item[xx])})
    NEXT
    RETURN aMat

    METHOD GetArraySectionColumnName(uNomeNodo AS USUAL,uNomeColonna AS USUAL) AS ARRAY
    LOCAL nCount,xx,nPos AS INT
    LOCAL aMat AS ARRAY

    SELF:GetSection(uNomeNodo)
    nCount := SELF:oDataTable:Rows:Count
    IF ValType(uNomeColonna) == "C"
    nPos := (INT) AScan(SELF:aColonne,{|x| Upper(x[1]) == Upper(uNomeColonna)})
    ELSEIF ValType(uNomeColonna) == "N"
    nPos := (INT) AScan(SELF:aColonne,{|x| x[2] == uNomeColonna})
    ENDIF

    aMat := {}
    IF nPos > 0
    FOR xx := 0 UPTO nCount - 1
    AAdd(aMat,{SELF:oDataTable:Columns[nPos-1]:ColumnName,Convert.ToString(SELF:oDataTable:Rows[xx]:Item[nPos-1])})
    NEXT
    ENDIF
    RETURN aMat

    METHOD GetSections() AS ARRAY
    RETURN AClone(SELF:aSezioni)

    METHOD GetXML() AS STRING
    RETURN SELF:oDataSet:GetXML()

    METHOD InsRow(cNomeSezione AS STRING,cNomeVariabile AS STRING,cValore AS STRING) AS VOID
    LOCAL oRow AS DataRow
    LOCAL oDT AS DataTable

    oDT := SELF:GetSection(cNomeSezione)
    oRow := oDT:NewRow()
    oRow[cNomeVariabile] := cValore
    oDT:Rows:Add(oRow)
    SELF:oDataTable:AcceptChanges()
    SELF:oDataSet:AcceptChanges()
    SELF:oDataTable := oDT
    SELF:SaveXML()
    oRow := NULL_OBJECT

    RETURN

    PRIVATE METHOD LeggiSezioni() AS VOID
    LOCAL xx AS INT
    LOCAL cNomeTabella AS STRING

    SELF:nNodi := SELF:oDataSet:Tables:Count
    SELF:aSezioni := {}
    FOR xx := 0 UPTO SELF:nNodi-1
    cNomeTabella := SELF:oDataSet:Tables[xx]:TableName
    AAdd(SELF:aSezioni,{cNomeTabella,xx})
    NEXT
    SELF:oDataTable := SELF:oDataSet:Tables[0]
    SELF:LeggiColonne(SELF:oDataTable)
    RETURN

    PRIVATE METHOD LeggiColonne(oTable AS DataTable) AS VOID
    LOCAL nCol,xx AS INT
    nCol := oTable:Columns:Count
    SELF:aColonne := {}
    FOR xx := 0 UPTO nCol-1
    AAdd(SELF:aColonne,{oTable:Columns[xx]:ColumnName,xx })
    NEXT
    RETURN

    METHOD SaveXML(cFile := "" AS STRING) AS VOID
    IF ! Empty(cFile)
    SELF:oDataSet:WriteXml(cFile)
    ELSE
    SELF:oDataSet:WriteXml(SELF:cFileXML)
    ENDIF
    RETURN

    METHOD WriteEntry(cNomeSezione AS STRING,cNomeVariabile AS STRING,cValore AS STRING) AS VOID
    LOCAL nPos AS INT

    IF ! Empty(cNomeSezione) .and. ! Empty(cNomeVariabile)
    IF SELF:ExistSection(cNomeSezione)
    SELF:GetSection(cNomeSezione)
    IF (SELF:oDataTable:TableName == cNomeSezione)
    nPos := (INT) AScan(SELF:aColonne,{|x| Upper(x[1]) == Upper(cNomeVariabile)})
    IF nPos > 0
    SELF:oDataTable:Rows[0]:Item[nPos-1] := cValore
    ELSE
    SELF:CreateElement(Upper(cNomeVariabile),cValore)
    ENDIF
    ENDIF
    SELF:SaveXML()
    ELSE
    SELF:CreateSection(Upper(cNomeSezione),Upper(cNomeVariabile),cValore)
    SELF:SaveXML()
    ENDIF
    ENDIF

    RETURN

    METHOD Close() AS VOID
    SELF:oDataSet:Clear()
    SELF:oDataSet := NULL_OBJECT
    SELF:oDataTable:Clear()
    SELF:oDataTable := NULL_OBJECT
    SELF:aSezioni := {}
    SELF:aColonne := {}
    RETURN

    END CLASS

    Please Log in or Create an account to join the conversation.

    Eseguire un file audio 04 Feb 2022 17:48 #21450

    • Chris
    • Chris's Avatar


  • Posts: 3981
  • Claudio,

    There's also the SoundPlayer class which can play sounds, but it has limited functionality and can only play .wav files:
    LOCAL oPlayer AS System.Media.SoundPlayer
    oPlayer := System.Media.SoundPlayer{"C:\wav\Ring10.wav"}
    oPlayer:Play()
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Eseguire un file audio 04 Feb 2022 17:48 #21451

    • FFF
    • FFF's Avatar


  • Posts: 1419
  • Claudio,
    Ho fatto una prova veloce dell'applicazione Vo StdMDI in XIDE, usando il metodo Timer nella shell, nessun problema. La variante più semplice potrebbe essere:
    METODO Timer() AS USUAL
    IF yourDBCheck_Alert()
    Tone(440,5)
    Tone(660,5)
    Tone(880,5)
    Tone(1000,5)
    ENDIF
    RETURN TRUE
    Regards
    Karl (X# 2.15.0.3; Xide 2.15; W8.1/64 German)

    Please Log in or Create an account to join the conversation.

    Eseguire un file audio 04 Feb 2022 17:57 #21452

    • FFF
    • FFF's Avatar


  • Posts: 1419
  • Oppure, per essere un po' più fantasiosi, usate questo mio vecchio metodo di test come punto di partenza per farlo parlare:

    USING System.Speech.Synthesis
    USING System.Speech.AudioFormat
    USING System.IO
    FUNCTION EncodeNewNumbers(d AS STRING, val AS STRING ) AS LOGIC
    LOCAL oSAFI AS SpeechAudioFormatInfo
    oSAFI:=SpeechAudioFormatInfo{32000, AudioBitsPerSample.Sixteen, AudioChannel.Mono}

    LOCAL Synth AS SpeechSynthesizer
    Synth := SpeechSynthesizer{}

    LOCAL cEinleitung AS STRING

    cEinleitung:="Am" + d + " Dezember wurden folgende Nummern gezogen:"
    Synth:Speak(cEinleitung + val)

    /*
    FOREACH v AS System.Speech.Synthesis.InstalledVoice IN Synth:GetInstalledVoices()
    ? v:VoiceInfo:Name
    NEXT
    */

    // Var 1 -> WAV File schreiben
    //Synth:SetOutputToWaveFile( cPath, oSAFI)

    RETURN TRUE
    Regards
    Karl (X# 2.15.0.3; Xide 2.15; W8.1/64 German)

    Please Log in or Create an account to join the conversation.

    • Page:
    • 1
    Moderators: wriedmann