Xander Lamkins Xander Lamkins - 3 months ago 22
Vb.net Question

Playing a Wav too fast messes up

I'm recreating an old 16 bit game. I'm creating the chat normally displayed at the bottom. Each sentence transitions in character-by-character.

Every time a character is added, I wanted to have it make that little bleep noise. I've got a wav file that contains a short 'blip' that sounds just right, problem is, when I have it do the blip every time, it usually messes up.

Either it:


  • Skips the character-by-character process and just shows the full word and blips once

  • Lags and does a couple of bips correctly and then does what the thing listed above



Here is where it gets complicated. I'm using Lua and VB.net for this. The engine, I've written in VB.net while the actual game mechanics and story line are controlled by Lua.

Here is the basic snippit of Lua:

RegisterEvent("ready", function()
_G.Chat={}
_G.Chat["busy"]=false
_G.Chat.Say=(function(from,msg,done)
if _G.Chat["busy"] then return end
_G.Chat["busy"]=true
local x,y=getRelativePositionOpposite(1024,192)
--Draw
local chatPanel=engine:AddSprite("chat.png",0,0,1024,192,x,y,1024,192,5)
local fromText=engine:AddString(from..":",x+25,y+25,"#FFFFFF",16,0,0)
local msgText=nil
local mx=string.len(msg)
--Chat Cleanup
setupCleanup=(function()
local g=true
RegisterEvent("keyup", function(key)
if not g then return end
if key=="Space" then
engine:RemoveSprite(chatPanel)
engine:RemoveString(fromText)
engine:RemoveString(msgText)
_G.Chat["busy"]=false
done()
g=false
end
end)
end)
doText=(function(i)
if msgText then
engine:RemoveString(msgText)
end
msgText=engine:AddString(string.sub(msg,1,i),x,y+75,"#FFFFFF",14,1,0)
engine:PlaySound("chatblip.wav")
if i>=mx then setupCleanup() return end
pause(.75,(function() doText(i+1) end))
end)
doText(1)
end)
end)


Here is the pause function, just for reference (in Lua):

_G.pause=(function(t,f)
if t and f then
local tt=engine.timer.ElapsedMilliseconds/1000+t
local lcc=true
engine.event_tick:add(function(nt)
if nt>=tt and lcc then
f()
lcc=false
end
end)
end
end)


Here is the snippit that is actually playing the noise in VB.net:

Public Sub PlaySound(ByVal fileFullPath As String)
My.Computer.Audio.Play(My.Computer.FileSystem.CurrentDirectory & "\bin\sounds\" & fileFullPath, AudioPlayMode.Background)
End Sub


Thanks if you can help! If you need any clarifications, I'm more than willing to help!

Answer

I used reflector and the internal implementation of Audio.Play uses the SoundPlayer:

Public Sub Play(ByVal location As String, ByVal playMode As AudioPlayMode)
    Me.ValidateAudioPlayModeEnum(playMode, "playMode")
    Dim sound As New SoundPlayer(Me.ValidateFilename(location))
    Me.Play(sound, playMode)
End Sub

Reading the sound file for each character is going to be quite intensive on IO.

To overcome the perf. bottleneck can you try adding a reference to the Microsoft.VisualBasic.dll assembly and use:

Microsoft.VisualBasic.Interaction.Beep()

Or just Beep() if your using .Net Framework 2.0 and/OR greater.

I didn't drill down very far in reflector but it might also be worth checking if the SoundPlayer uses the PlaySound API and if it doesn't give that method a go as well:

    <DllImport("coredll.dll")> _
Public Shared Function PlaySound(szSound As String, hModule As IntPtr, flags As Integer) As Integer
End Function