Infinite loop or completion event of media.play Event Sound() not firing please help

I am trying to create a piece of code that will step through a string and play a sound event of every character but I am having some issues.

As media.play Event Sound() is by default asynchronous I am using the onComplete (or whatever it’s called) to ensure each character sound has finished before the next one starts. I am using a do while loop to iterate through the string so that it is only moved to the next character once the sound file for the current one has finished.

So it should play the sound file for each letter.

It plays it once and displays D it does not seem to call the function that it should on completion of playing the sound file.

local function playSinglePhoneme(postLetter)

wordToSpeak = “dog”
local len = string.len(wordToSpeak)
local counter = 1
local next = true

function playEquals()
print(“Entered playEquals()”)
media.playEventSound(sayEqualsSID)
counter = counter + 1
end

while counter < len + 1 do
character = string.sub (wordToSpeak, counter,counter)

if next == true then
next = false
print(character)
–increment()
media.playEventSound(speakLetterG[currentPageNo],playEquals)
end

end
end [import]uid: 5872 topic_id: 3760 reply_id: 303760[/import]

You don’t need to use a “do while” loop - and it’s probably the cause of your problem.
Lua is much more simple than that… :slight_smile:

Try this:
[lua]----- Adds a little char-tokenizer to the standard string table
function string.getChars(str)
local ret = {}
local len = string.len(str)

for i=1,len do ret[i] = string.sub(str,i,i) end

return ret
end
----- The main function
function sayWord(word)
local obj = {}
obj.letters = string.getChars(word)
obj.count = 1

function obj.sayLetter() – this is used as an upvalue function for playEventSound
if obj.count <= #obj.letters then
print(obj.letters[obj.count]) – prints current letter
media.playEventSound(“your_sound.caf”,obj.sayLetter)
obj.count = obj.count+1
end
end

obj:sayLetter()
end

sayWord(“GREAT!”) – This starts it all[/lua]

Edit: forgot to print the current letter! :slight_smile: [import]uid: 5750 topic_id: 3760 reply_id: 11456[/import]

Thanks this works great (I didn’t know you could code like this in Lua adding function to existing tables / libraries etc).

I still have an issue as I need a sequence of sounds to play one after another, so in this case after the completion of the sayWord("") but due to the kinda asynchronous nature of lua I can’t get this to work.

I am trying setting a return code of 1

if obj.count <= #obj.letters then
print(obj.letters[obj.count]) – prints current letter
media.playEventSound(IspeakPhonemeG[obj.letters[obj.count]],obj.sayLetter)
obj.count = obj.count+1
else
print(“loop complete”)
return 1
end

or using a global variable and setting that to 1

But I think it’s that the statement that follows the sayWord("") is evaluated as soon as the function returns which is not the point the sequence of eventSound’s have finished (event driven programming etc).

This is the code for a button event that calls for the letters to be spoken
function buttonWord:tap( event )
local g_phonemesFinished = 0
if g_phonicsAudio == 1 then
g_phonemesFinished = sayWord(itemTextG[currentPageNo])
else
g_phonemesFinished = 1
end

if g_ObjectAudio == 1 and g_phonemesFinished == 1 then
media.playEventSound(speakObjectG[currentPageNo]) end
–if g_ObjectAudio == 1 and phonemesFinished == 1 then media.playEventSound(speakObjectG[currentPageNo]) end

if clueSelected > 0 then
–reColourText(buttonClue1, colourClue)
clueSelected = 0
clearPageSetup()
PageSetup()
end

end

Can you help? [import]uid: 5872 topic_id: 3760 reply_id: 11861[/import]

Please explain further your goals. You need to speak a whole phrase, one word after the other ? Or else ?

If you need to speak a phrase I’d create a function that first builds a table of words, and then calls sayWord till the end of the table.

You can’t return a value from sayWord the way you want because the context in which it returns is basically a chain of events.
But you do know when you are issuing the last media.playEventSound inside obj.sayLetter. At that point you can call a different completion function - as an example. [import]uid: 5750 topic_id: 3760 reply_id: 11865[/import]

Both I have it speaking a word from a table of letters (it is fed a txt word from a table etc) but then on completion of that. I want some other sounds to be played. I have this working elsewhere by calling a function using the oncomplete part of the eventsound etc and these function calls are chained together.

I can use the on completion of the last letter as you say but that in effect means making the function non generic I wanted to keep it intact and contained (so it just read a word) and controll the next events out of that function if possible.

THanks for your help. [import]uid: 5872 topic_id: 3760 reply_id: 11868[/import]

Well, if you need nothing but a completion “option” to sayWord, just add it:

[lua]----- The main function
function sayWord(word,oncomplete)
local obj = {}
obj.letters = string.getChars(word)
obj.count = 1
obj.onComplete = oncomplete

function obj.sayLetter() – this is used as an upvalue function for playEventSound
if obj.count <= #obj.letters then
print(obj.letters[obj.count]) – prints current letter
media.playEventSound(“your_sound.caf”,obj.sayLetter)
obj.count = obj.count+1
elseif obj.onComplete then – all letters done, if completion func…
obj.onComplete() – … call it!
end
end

obj:sayLetter()
end

sayWord(“GREAT!”,function () media.playEventSound(“doneIt.caf”) end)[/lua]

The function stays “general” anyway. It’s up to you calling it providing a completion function. You can add it every time you call it or just at the last word… etc. :slight_smile:
[import]uid: 5750 topic_id: 3760 reply_id: 11877[/import]

Oh, and by the way, you can do even more in Lua… you can replace native functions! :slight_smile:

Say you want a custom “print”:

[lua]local lua_print = print – backup original print func

function print(…)
if arg[1] == 0 then lua_print(“I DONT LIKE ZERO!”) return end
lua_print(unpack(arg)) – call original print for rest of the cases
end[/lua]

This is totally valid in Lua. :slight_smile:
[import]uid: 5750 topic_id: 3760 reply_id: 11879[/import]