Italian eseguire un beep per 10 volte

tmtube73

Active Member
Licensed User
qualcuno sa dirmi cosa non va nel mio codice sento il suono solo 1 volta anzichè 10 come mi aspettavo, grazie.

B4X:
Sub EseguiSuono
    Dim i As Int
    Dim b As Beeper
    Dim p As Phone

    p.SetVolume(p.VOLUME_RING, p.GetMaxVolume(p.VOLUME_RING), False)
   
   
    For i = 1 To 10
        b.Initialize(100, 100) '300 milliseconds, 500 hz
        b.Beep
    Next
End Sub
 

udg

Expert
Licensed User
Longtime User
Per come hai scritto il codice, il beeper viene inizializzato 10 volte (senza mai rilasciare le risorse e quindi creando i presupposti di un memory leak) per produrre un suono a 100Hz di durata 100ms, ma il loop fa sì che il successivo venga avviato mentre il precedente ancora non iniziava nemmeno. Alla fine senti solo l'ultimo.

Prova con un timer. Prima inizializzi (una sola volta) il beeper, poi setti un timer in modo opportuno affinchè il suono abbia tempo di essere eseguito ed anche seguito da una breve pausa. Tramite un contatore, quando arrivi a 10 (o al numero max di ripetizioni), disabiliti il timer e rilasci il beeper (b.release se non sbaglio).

Un altro modo sarebbe tramite sub richiamata da un wait for. Anche questa sarebbe da sperimentare per comprendere bene come funziona questo tipo di meccanismo.
 

Star-Dust

Expert
Licensed User
Longtime User
B4X:
Sub EseguiSuono
    Dim i As Int
    Dim b As Beeper
    Dim p As Phone

    p.SetVolume(p.VOLUME_RING, p.GetMaxVolume(p.VOLUME_RING), False)

    b.Initialize(300, 500) '300 milliseconds, 500 hz
    For i = 1 To 10
        b.Beep
        Sleep(450)
    Next
    b.Release
End Sub
 

udg

Expert
Licensed User
Longtime User
E come ti ha appena mostrato @Star-Dust sleep è ancora un'altra possibilità. Attenzione che all'esecuzione di sleep, il flusso torna alla sub che ha lancianciato Eseguisuono (o comunque alla UI), per poi ritornare in essa ogni 450ms, avviare un beep etc; dopo l'ultimo beep Eseguisuono viene completata con il rilascio delle risorse del beeper (e si torna definitivamente al flusso principale.
 

sirjo66

Well-Known Member
Licensed User
Longtime User
Attenzione che all'esecuzione di sleep, il flusso torna alla sub che ha lanciato Eseguisuono (o comunque alla UI), per poi ritornare in essa ogni 450ms

Sì, esatto, infatti l'uso di Sleep deve essere ben ponderato e valutato, a me sta dando un sacco di problemi proprio per questo motivo, che ritorna alla sub di livello superiore e lì il casino è totale.

Se si usa ancora il DoEvents controllando con DateTime.Now che siano passati i 450 ms è proprio brutto ???
 

udg

Expert
Licensed User
Longtime User
Se si usa ancora il DoEvents controllando con DateTime.Now che siano passati i 450 ms è proprio brutto ???
A quel punto, proverei con il timer..
Invece di controllare un orario in un loop (cosa che Android comunque non gradisce perchè blocca la UI), aspetti che la tua beep-routine venga richiamata dal timer. Facile, semplice e pulito.
 

Star-Dust

Expert
Licensed User
Longtime User
Per risolvere i problemi dello Sleep che ritorna al livello superiore
B4X:
Sub Principale
    Wait For (EseguiSuono)  Complete (Result As Boolean)
End Sub

Sub EseguiSuono As ResumableSub
    Dim i As Int, b As Beeper, p As Phone

    p.SetVolume(p.VOLUME_RING, p.GetMaxVolume(p.VOLUME_RING), False)
    b.Initialize(300, 500) '300 milliseconds, 500 hz
    For i = 1 To 10
        b.Beep
        Sleep(450)
    Next
    b.Release
    Return True
End Sub

Chiaramente l'uso di sleep dipende dall'intera struttura dell'Algoritmo. DoEvent lo userei con parsimonia perchè in effetti qualche volta genera Crash. C'è uno Sleep in Java che ferma il dispositivo per un Tot (ms), che può essere richiamato da Java, però l'effetto che "congela" il dispositivo in quel lasso di tempo stabilito.

Il timer che è stato suggerito, è una buona alternativa.

Per far sentire i 10 beep bisogna intervallare dai 100ms ai 200ms di silenzio altrimenti sembrerebbe un suono unico ecco perchè ho messo uno Sleep(450) e non di 300ms.
 
Last edited:

Sagenut

Expert
Licensed User
Longtime User
Se, da qualunque punto del progetto, si deve richiamare una Sub che contiene uno Sleep e si ha necessità di attendere il suo completamento và per forza implementato subito anche un WAIT FOR che attenda il completamento della SUB.
 

udg

Expert
Licensed User
Longtime User
Personalmente utilizzo molto il waitfor, mi piace. Però capisco anche chi non si sente a suo agio e preferisce altre strade.
Direi che, in generale, siamo fortunati ad avere un ventaglio di scelte
 

tmtube73

Active Member
Licensed User
Ciao, grazie a tutti per gli esempi, ho provato il codice postato da Star-Dust oggi alle 10.12 ma eseguendolo mi da il seguente errore:

Errore di sintassi
Routine EseguiSuono non utilizzata (warning #12)

qualcuno da il motivo?

io eseguo la routine Principale su click di un Button1 qui sotto riporto codice

B4X:
Sub Button1_Click
    Principale
End Sub

Sub Principale
    Wait For EseguiSuono Complete (Result As Boolean)
End Sub

Sub EseguiSuono As ResumableSub
    Dim i As Int, b As Beeper, p As Phone

    p.SetVolume(p.VOLUME_RING, p.GetMaxVolume(p.VOLUME_RING), False)
    b.Initialize(300, 500) '300 milliseconds, 500 hz
    For i = 1 To 10
        b.Beep
        Sleep(450)
    Next
    b.Release
    Return True
End Sub
 

Star-Dust

Expert
Licensed User
Longtime User
Vanno messe le parentesi.
I post che lo spiega è questo:
 
Top