So lets say you want to connect to a website to stream their music through your app, but the problem is they dont give you a direct link only a connectstream from system.net.connectstream. How do you play this with fmod? well after much trial and error and understanding the concept i have found the solution.
Im assuming you already know how to setup FMOD so i wont go through that.
1) you will get your stream and you must know the length. You will have to rely on the content length send over the http stream since you cant get the length of a io.stream when using http.
2) This is the fun part. You will need to take that stream and load it into a byte array. If you want your data in real time and dont want to load the entire buffer(dowload the entire file) you will need to load the data in a thread. Then you will need to trigger for the orginal thread to continue once the initial buffer length of the data has been loaded into the new byte array.
3) once theĀ initialĀ data has been loaded into the byte array just pass that byte data to FMOD createStream function then OPENMEMORY Flag and also create a CREATESOUNDEXINFO and pass those items in and then play your sound. The thread will still be loading the data in the background while the app is playing the sound or music.
There is some extra code in SaveMemTask that gets the pointer to the mem but it is not needed since that approach didnt work too good for me.
Check out the code below.
Sub PlaySong(ByRef songStream As System.IO.Stream, ByVal streamLength As UInt32, ByVal stitle As String)
Dim result As FMOD.RESULT
If channel IsNot Nothing Then channel.stop()
If sound IsNot Nothing Then sound.release()
Dim sinfo As New FMOD.CREATESOUNDEXINFO
sinfo.cbsize = Runtime.InteropServices.Marshal.SizeOf(sinfo)
sinfo.length = streamLength
sinfo.format = FMOD.SOUND_FORMAT.MPEG
Dim streamptr As IntPtr = StreamToByteArray(songStream, streamLength)
result = sys.createStream(rawData, (FMOD.MODE._2D Or FMOD.MODE.HARDWARE Or FMOD.MODE.CREATESTREAM Or FMOD.MODE.OPENMEMORY), sinfo, sound)
result = sys.playSound(FMOD.CHANNELINDEX.FREE, sound, False, channel)
End Sub
Protected Function StreamToByteArray(ByRef songstream As IO.Stream, ByVal streamLength As UInt32) As IntPtr
WaitForThread = True
Me.streamLength = streamLength
AddHandler InitDataRecived, AddressOf InitDataReceivedHandler
trd = New System.Threading.Thread(AddressOf SaveMemTask)
trd.IsBackground = True
Me.songstream = songstream
Me.saveTo = saveTo
trd.Start()
While WaitForThread = True
Threading.Thread.Sleep(100)
End While
Return MyStreamPtr
End Function
'Global Variables Protected rawData() As Byte
Dim streamLength As UInt32
Private Sub SaveMemTask()
ReDim rawData(streamLength)
Dim ran As Boolean = False
Dim sLength As Integer = 1024
Dim buffer(sLength) As Byte
Dim bytesRead As Integer = songstream.Read(Buffer, 0, sLength)
Dim bpos As Integer = 0
While (bytesRead > 0)
For i As Integer = 0 To bytesRead - 1
rawData(i + bpos) = buffer(i)
Next
bpos += bytesRead
If ran = False Then
ran = True
rawDataHandle = GCHandle.Alloc(rawData, GCHandleType.Pinned)
address = rawDataHandle.AddrOfPinnedObject()
RaiseEvent InitDataRecived(address)
Else
End If
bytesRead = songstream.Read(Buffer, 0, sLength)
End While
End Sub
Private Sub InitDataReceivedHandler(ByVal ptr As IntPtr)
MyStreamPtr = ptr
WaitForThread = False
End Sub
Private songstream As IO.Stream
Private saveTo As String
Private WaitForThread As Boolean = True
Private MyStreamPtr As IntPtr
Protected Event InitDataRecived(ByVal ptr As IntPtr)
16 Responses to Item Of the Day. Playing .net io.stream using FMOD