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