Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Audio streaming over UDP

Hi.

Have anyone any ideas how I can record to Microphone and send that audio data over UDP and play it in other computer?

It should send it in real time, so recording to .wav and then sending it won't be what I need (multiuser chatting). So, I have thought that I create one server which listen UDP connections and clients connect to that server.

So, client should send data from it's microphone directly to the server and server should send it to other client(s). Then the other client(s) should play it.

So, the problem is, how I can play .wav STREAM and how I can send .wav stream from microphone to server using UDP?

I think that waveInOpen API calls (etc) can do that, but is there any good tutorials, as short and as simple as possible?

It should be written in Visual Basic 6, NOT for .NET.
«1

Comments

  • BitByBit_ThorBitByBit_Thor Member Posts: 2,444
    UDP is not the right protocol for this. You need TCP.

    Probably the easiest way to do this is to use the WinSock control.

    Best Regards,
    Richard

    The way I see it... Well, it's all pretty blurry
  • aleksirasanenaleksirasanen Member Posts: 21
    : UDP is not the right protocol for this. You need TCP.
    :
    : Probably the easiest way to do this is to use the WinSock control.
    :
    : Best Regards,
    : Richard
    :
    : The way I see it... Well, it's all pretty blurry

    Umm, can you explain a little bit? Why I should use TCP, not UDP, when streaming audio?

    I mean, if there is even one packet lost in TCP protocol, then it waits and waits and waits until it get it. In real time talking it's not necessary, because people can't hear if there is lost one millisecond in the middle of the speaking? So, isn't UDP right thing to that?

    By the way, Winsock control handles UDP also, and it's not even hard to use :)

    Hardes part is how I can record from waveIn and send that audio data directly to UDP :/

    Thanks for your reply, anyway.
  • BitByBit_ThorBitByBit_Thor Member Posts: 2,444
    : Umm, can you explain a little bit? Why I should use TCP, not UDP,
    : when streaming audio?
    :
    : I mean, if there is even one packet lost in TCP protocol, then it
    : waits and waits and waits until it get it. In real time talking it's
    : not necessary, because people can't hear if there is lost one
    : millisecond in the middle of the speaking? So, isn't UDP right thing
    : to that?
    :

    It was just my first thought. You're probably right though - I figured TCP was better for getting the ordening right and guarantee delivery.
    But if you're live-streaming audio, UDP makes sure there is no delay when a packet is stuck in traffic (or worse: dies in a traffic accident).
    Anyway, the WinSock control supports both protocols in an easy way.

    : By the way, Winsock control handles UDP also, and it's not even hard
    : to use :)
    :
    : Hardes part is how I can record from waveIn and send that audio data
    : directly to UDP :/
    :
    : Thanks for your reply, anyway.

    That is indeed the hardest part. If you need help with any specific part let me know (I've never used wave recording before though).
    Best Regards,
    Richard

    The way I see it... Well, it's all pretty blurry
  • aleksirasanenaleksirasanen Member Posts: 21
    : That is indeed the hardest part. If you need help with any specific
    : part let me know (I've never used wave recording before though).
    : Best Regards,
    : Richard

    Now I can save audio from line in to buffer, and also play it back.
    But when I try to send it over UDP and in other machine take it (well, actually, same machine in testing but you got the point...) and play, the wave data seems to be corrupted?

    I mean, I can hear only crappy wave audio data, not what I was recorded. So, before sendind it is ok.

    Any ideas what might cause this?
  • BitByBit_ThorBitByBit_Thor Member Posts: 2,444
    : : That is indeed the hardest part. If you need help with any specific
    : : part let me know (I've never used wave recording before though).
    : : Best Regards,
    : : Richard
    :
    : Now I can save audio from line in to buffer, and also play it back.
    : But when I try to send it over UDP and in other machine take it
    : (well, actually, same machine in testing but you got the point...)
    : and play, the wave data seems to be corrupted?
    :
    : I mean, I can hear only crappy wave audio data, not what I was
    : recorded. So, before sendind it is ok.
    :
    : Any ideas what might cause this?

    I have some idea's, but I am not sure if they're crazy/impossible or not.

    Test it out with a test buffer: fill it with some known and recognisable data. Such as: 32 bytes with value 0, 32 bytes with value 1, 32 bytes with value 2, etc... all the way up to 255. This'll get you a 8kB block.
    Then send it. At the receiving side, print it to a file or something... make sure you get a visual picture of the incoming data. Is all the data in place (where it should be?). Are there gaps?

    Best Regards,
    Richard

    The way I see it... Well, it's all pretty blurry
  • aleksirasanenaleksirasanen Member Posts: 21
    : I have some idea's, but I am not sure if they're crazy/impossible or
    : not.

    Any ideas are welcome :)



    : Test it out with a test buffer: fill it with some known and
    : recognisable data. Such as: 32 bytes with value 0, 32 bytes with
    : value 1, 32 bytes with value 2, etc... all the way up to 255.
    : This'll get you a 8kB block.
    : Then send it. At the receiving side, print it to a file or
    : something... make sure you get a visual picture of the incoming
    : data. Is all the data in place (where it should be?). Are there gaps?


    Well. I have tried to it, in some way. I'm not sure is that what you meant, but I set my type values manually.

    Eg. I set this values manually (no matter what those values are, just for test).

    wWaveHeader.dwBufferLength = 100
    wWaveHeader.dwBytesRecorded = 1000
    wWaveHeader.dwFlags = 10
    wWaveHeader.dwLoops = 7
    wWaveHeader.dwUser = 82
    wWaveHeader.hData = 232323
    wWaveHeader.lpData = 33
    wWaveHeader.Reserved = 1
    wWaveHeader.wavehdr_tag = 1

    Then I use messagebox to show those values, just for test:

    MsgBox "dwBufferLength: " & wWaveHeader.dwBufferLength & vbCrLf & _
    "dwBytesRecorded: " & wWaveHeader.dwBytesRecorded & vbCrLf & _
    "dwFlags: " & wWaveHeader.dwFlags & vbCrLf & _
    "dwLoops: " & wWaveHeader.dwLoops & vbCrLf & _
    "dwUser: " & wWaveHeader.dwUser & vbCrLf & _
    "hData: " & wWaveHeader.hData & vbCrLf & _
    "lpData: " & wWaveHeader.lpData & vbCrLf & _
    "Reserved: " & wWaveHeader.Reserved & vbCrLf & _
    "wavehdr_tag: " & wWaveHeader.wavehdr_tag

    Then I sent that wWaveHeader using this:

    Dim aBytes() As Byte
    ReDim aBytes(Len(wWaveHeader)) As Byte

    CopyMemory ByVal VarPtr(aBytes(0)), ByVal VarPtr(wWaveHeader), _
    Len(wWaveHeader)

    Winsock1.SendData aBytes


    And in the client I received it using this:

    Dim aBytes() As Byte
    Winsock1.GetData aBytes, vbArray + vbByte

    CopyMemory ByVal VarPtr(wWaveHeader), ByVal VarPtr(aBytes(0)), _
    Len(wWaveHeader)


    And when I use MessageBox (same as above) and look values, they are identical. Nothing has changed.

    So, it seems that it is "ok". But, now I am thinking, does that sender really send the data, not just handle and pointter to that handle? CopyMemory with ByVal should do it, but how I can be sure? :/

  • BitByBit_ThorBitByBit_Thor Member Posts: 2,444
    : : I have some idea's, but I am not sure if they're crazy/impossible or
    : : not.
    :
    : Any ideas are welcome :)
    :
    :
    :
    : : Test it out with a test buffer: fill it with some known and
    : : recognisable data. Such as: 32 bytes with value 0, 32 bytes with
    : : value 1, 32 bytes with value 2, etc... all the way up to 255.
    : : This'll get you a 8kB block.
    : : Then send it. At the receiving side, print it to a file or
    : : something... make sure you get a visual picture of the incoming
    : : data. Is all the data in place (where it should be?). Are there gaps?
    :
    :
    : Well. I have tried to it, in some way. I'm not sure is that what you
    : meant, but I set my type values manually.
    :
    : Eg. I set this values manually (no matter what those values are,
    : just for test).
    :
    : wWaveHeader.dwBufferLength = 100
    : wWaveHeader.dwBytesRecorded = 1000
    : wWaveHeader.dwFlags = 10
    : wWaveHeader.dwLoops = 7
    : wWaveHeader.dwUser = 82
    : wWaveHeader.hData = 232323
    : wWaveHeader.lpData = 33
    : wWaveHeader.Reserved = 1
    : wWaveHeader.wavehdr_tag = 1
    :
    : Then I use messagebox to show those values, just for test:
    :
    : MsgBox "dwBufferLength: " & wWaveHeader.dwBufferLength & vbCrLf
    : & _
    : "dwBytesRecorded: " & wWaveHeader.dwBytesRecorded & vbCrLf &
    : _
    : "dwFlags: " & wWaveHeader.dwFlags & vbCrLf & _
    : "dwLoops: " & wWaveHeader.dwLoops & vbCrLf & _
    : "dwUser: " & wWaveHeader.dwUser & vbCrLf & _
    : "hData: " & wWaveHeader.hData & vbCrLf & _
    : "lpData: " & wWaveHeader.lpData & vbCrLf & _
    : "Reserved: " & wWaveHeader.Reserved & vbCrLf & _
    : "wavehdr_tag: " & wWaveHeader.wavehdr_tag
    :
    : Then I sent that wWaveHeader using this:
    :
    : Dim aBytes() As Byte
    : ReDim aBytes(Len(wWaveHeader)) As Byte
    :
    : CopyMemory ByVal VarPtr(aBytes(0)), ByVal VarPtr(wWaveHeader), _
    : Len(wWaveHeader)
    :
    : Winsock1.SendData aBytes
    :
    :
    : And in the client I received it using this:
    :
    : Dim aBytes() As Byte
    : Winsock1.GetData aBytes, vbArray + vbByte
    :
    : CopyMemory ByVal VarPtr(wWaveHeader), ByVal VarPtr(aBytes(0)), _
    : Len(wWaveHeader)
    :
    :
    : And when I use MessageBox (same as above) and look values, they are
    : identical. Nothing has changed.
    :
    : So, it seems that it is "ok". But, now I am thinking, does that
    : sender really send the data, not just handle and pointter to that
    : handle? CopyMemory with ByVal should do it, but how I can be sure? :/
    :
    :

    I think I know what the problem is. What you need to do is send over only a part of the wave header, and the raw wave data. Then you need to use that data to create a new waveheader. Make sure lpData is pointing to the received raw wave data.

    Best Regards,
    Richard

    The way I see it... Well, it's all pretty blurry
  • aleksirasanenaleksirasanen Member Posts: 21
    : I think I know what the problem is. What you need to do is send over
    : only a part of the wave header, and the raw wave data. Then you need
    : to use that data to create a new waveheader. Make sure lpData is
    : pointing to the received raw wave data.

    Thank you for your answer. Now it works. I read data from memory using CopyMemory API call and then I send only that data over network.

    Then, in other machine, I just read it to byte-array and created manually wave header and put my wave header's lpData to point in that byte array. So, now the sound recording and sending over network and then listening works.

    But, problem is now double buffering.

    Any idea about that? I am trying to send longer audio data, so I have two buffers. Recording works fine, it just first record to buffer 1 and send it when it is full, meanwhile it records to buffer 2 and when it is full, it send that to network and start again recording to buffer 1 etc.

    Problem is to get that data to two waveOut buffers. Any ideas?
  • BitByBit_ThorBitByBit_Thor Member Posts: 2,444
    : : I think I know what the problem is. What you need to do is send over
    : : only a part of the wave header, and the raw wave data. Then you need
    : : to use that data to create a new waveheader. Make sure lpData is
    : : pointing to the received raw wave data.
    :
    : Thank you for your answer. Now it works. I read data from memory
    : using CopyMemory API call and then I send only that data over
    : network.
    :
    : Then, in other machine, I just read it to byte-array and created
    : manually wave header and put my wave header's lpData to point in
    : that byte array. So, now the sound recording and sending over
    : network and then listening works.
    :
    : But, problem is now double buffering.
    :
    : Any idea about that? I am trying to send longer audio data, so I
    : have two buffers. Recording works fine, it just first record to
    : buffer 1 and send it when it is full, meanwhile it records to buffer
    : 2 and when it is full, it send that to network and start again
    : recording to buffer 1 etc.
    :
    : Problem is to get that data to two waveOut buffers. Any ideas?

    I'm not fully sure I understand your question. But I assume the question is: How to play the sound on the receiving side, using two buffers?

    I don't know how the wave API's work, but probably you're going to have to create two wave headers, one for each buffer, and play each of them after the other.
    Best Regards,
    Richard

    The way I see it... Well, it's all pretty blurry
  • aleksirasanenaleksirasanen Member Posts: 21
    m not fully sure I understand your question. But I assume the
    : question is: How to play the sound on the receiving side, using two
    : buffers?

    Yes, that was what I meant. But, that problem is now fixed.

    If you're interested, then I can paste answer here also (I wrote it already on codeguru.com forums).

    But, now I have problem with gap. Any ideas how to remove gap between data blocks?
«1
Sign In or Register to comment.