CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 17
  1. #1
    Join Date
    Jan 2008
    Posts
    8

    Voice over UDP problem

    Hi.

    I am trying to record from waveIn and send that data over UDP to another computer and play it there. Recording short sample work's perfectly (I use API calls waveInOpen, waveInPrepareHeader etc), so that is not the problem.

    Then if I play that recorded short sample using API calls (waveOutOpen, waveOutPrepareHeader etc) it works fine. So that is not the problem also.

    The problem comes when I try to send that voice to another computer using UDP.

    My voice is in User Defined Type "WAVEHDR". So, when I send it, I use this:

    Code:
    Dim bData() As Byte
    ReDim bData(Len(waveHeader)) As Byte
    
    CopyMemory ByVal VarPtr(bData(0)), ByVal VarPtr(waveHeader), Len(waveHeader)
    
     Winsock1.SendData bData
    Then, in another computer it get it using this code:

    Code:
    Dim rc As Long
    Dim dData() As Byte
        
    Winsock1.GetData dData, vbArray + vbByte
        
    CopyMemory ByVal VarPtr(wAlamolo), ByVal VarPtr(dData(0)), Len(wAlamolo)
    wAlamolo is defined as WAVEHDR in that computer.

    When I compare values before and after send, both seems to be fine.
    So, it seems that all values are transferred without any problems.

    But, when I then try to play that data from wAlamolo, I can hear strange noise. Totally strange noise.

    What can be wrong? Any ideas?

    All help are welcome
    Last edited by Stargazers; January 22nd, 2008 at 08:33 AM. Reason: More politically :)

  2. #2
    Join Date
    Jul 2006
    Location
    Germany
    Posts
    3,725

    Re: Voice over UDP problem

    Well, as far as I understand the WAVEHDR structure it contains a pointer to the buffer where the actual waveform to play is, but not the waveform itself.
    On your source computer it is somewhere in memory.
    On your target computer it is not. Or at least not in the same place.
    Code:
    typedef struct {
      LPSTR lpData;
      DWORD dwBufferLength;
      DWORD dwBytesRecorded;
      DWORD dwUser;
      DWORD dwFlags;
      DWORD dwLoops;
      struct wavehdr_tag* lpNext;
      DWORD reserved;}
    WAVEHDR;
    You must also transfer the memory at lpData with length of either dwBytesRecorded or dwBufferLength.
    In the target computer you have to store the wave, say, in a byte array and supply the address of the byte(0) to th lpData of your transferred header.
    Otherwise lpDate would point somewhere into memory to a place where other data resides and this data played will really sound strange.

  3. #3
    Join Date
    Jan 2006
    Location
    Fox Lake, IL
    Posts
    15,007

    Re: Voice over UDP problem

    Plus, UDP sends packets and receives s them, but thse order is not kept, like TCP so you couldn't play it back anyways.
    David

    CodeGuru Article: Bound Controls are Evil-VB6
    2013 Samples: MS CODE Samples

    CodeGuru Reviewer
    2006 Dell CSP
    2006, 2007 & 2008 MVP Visual Basic
    If your question has been answered satisfactorily, and it has been helpful, then, please, Rate this Post!

  4. #4
    Join Date
    Jan 2008
    Posts
    8

    Re: Voice over UDP problem

    Quote Originally Posted by WoF
    Well, as far as I understand the WAVEHDR structure it contains a pointer to the buffer where the actual waveform to play is, but not the waveform itself.
    Oh, so that is the problem, then.

    Quote Originally Posted by WoF
    On your source computer it is somewhere in memory.
    On your target computer it is not. Or at least not in the same place.
    But for some reason, if I test it on localhost, it should be there in same place already? But it isn't?

    Quote Originally Posted by WoF
    You must also transfer the memory at lpData with length of either dwBytesRecorded or dwBufferLength.
    Well, should I still transfer the WAVEHDR struct? I mean, can't it be created from empty in other computer, only pointing to it's data what it has taken from network?

    Quote Originally Posted by WoF
    In the target computer you have to store the wave, say, in a byte array and supply the address of the byte(0) to th lpData of your transferred header.
    Well, I have tried to make it work. Can you give little sample?

    Quote Originally Posted by WoF
    Otherwise lpDate would point somewhere into memory to a place where other data resides and this data played will really sound strange.
    Ok, thank you for you help.

    I have tried to do it now using this:

    Code:
        Winsock1.GetData RawAudioData, vbByte
        wAlamolo.dwBufferLength = bytesTotal
        wAlamolo.lpData = VarPtr(RawAudioData(0))
        PlayWave wAlamolo
    So, first I download audio data to RawAudioData (which is byte-array). Then I set dwBufferLength and then I set wAlamolo.lpData to point to my byte-array RawAudioData.

    Finally I play it. But, something is wrong. Same effect. Infernal noise. What can be wrong now?

  5. #5
    Join Date
    Jan 2006
    Location
    Fox Lake, IL
    Posts
    15,007

    Re: Voice over UDP problem

    wrong order?
    David

    CodeGuru Article: Bound Controls are Evil-VB6
    2013 Samples: MS CODE Samples

    CodeGuru Reviewer
    2006 Dell CSP
    2006, 2007 & 2008 MVP Visual Basic
    If your question has been answered satisfactorily, and it has been helpful, then, please, Rate this Post!

  6. #6
    Join Date
    Aug 2001
    Location
    Stockholm, Sweden
    Posts
    1,664

    Re: Voice over UDP problem

    Suggestions:

    1. Don't send the whole WAVEHDR
    - Send WAVEHDR::lpData and WAVEHDR:wBytesRecorded
    (dwBytesRecorded will probably be the same except for last sample)

    2. Include a seqence number (seqno) which is increased for every send (ie counter)

    3. Drop packets which have incorrect seqno (ie seq != prev_seq + 1)

  7. #7
    Join Date
    Jul 2006
    Location
    Germany
    Posts
    3,725

    Re: Voice over UDP problem

    Yeah. Good idea.
    Just transfer the dwBytesRecorded and the apropriate number of bytes from lpData. The dwBufferLength is maybe to large, don't know.
    Then you can construct the WAVEHDR structure at the target computer without having to transfer it. Just you have to know where your transfered waveform lies in memory, and that's about it.
    Edit: reading again your post about your attempts: don't set dwBufferLength, but set dwBytesRecorded to the number of bytes in the waveform array. (Or both)
    Last edited by WoF; January 22nd, 2008 at 06:07 PM.

  8. #8
    Join Date
    Jan 2008
    Posts
    8

    Re: Voice over UDP problem

    Quote Originally Posted by j0nas
    1. Don't send the whole WAVEHDR
    - Send WAVEHDR::lpData and WAVEHDR:wBytesRecorded
    (dwBytesRecorded will probably be the same except for last sample)
    Why I should sen WAVEHDR's lpData? I mean, if that is only the pointer to my computers memory location, then why other computer need that? Shouldn't that be set on the other computer, because memory address propably will be other?


    Quote Originally Posted by j0nas
    2. Include a seqence number (seqno) which is increased for every send (ie counter)

    3. Drop packets which have incorrect seqno (ie seq != prev_seq + 1)
    Can you help a little bit with this? Some kind of short sample how to send and how to take those packets?

    I mean, if I make packet counter and bytes comes in wrong order, then it propably drop all packets?

  9. #9
    Join Date
    Jan 2008
    Posts
    8

    Re: Voice over UDP problem

    Well, now it seems that problem could be CopyMemory function. Let me explain.

    So. I have Computer 1 where I record wave to waveInHDR. Normally I have just tried to copy wavedata from memory and send it and on Computer 1 (well, same, but over UDP) and make a sound. Always crap.

    So I just made a test. As I said, I have waveInHDR what contains right information (I am quite sure about this, because PlayWave waveInHDR works fine). Now I made a function which copy data from waveInHDR to aData() array. So, I just simple try to make a copy of that audio data to another memory place.

    I used this:
    Code:
    CopyMemory ByVal VarPtr(aData(0)), ByVal VarPtr(wHDR.lpData), wHDR.dwBytesRecorded
    aData is public array, wHDR just refers to waveInHDR because I passed it as function argument.

    So, I am trying to copy audio data from waveInHDR to aData array. Then I write this:

    Code:
        wHDR.lpData = VarPtr(aData(0))
    So, I just simply try to tell waveInHDR to use aData (which should be identical to waveInHDR) and then Play waveInHDR (same as wHDR, because wHDR refers to waveInHDR because waveInHDR was passed as function argument).

    But the problem is infernal noise?

    Something is wrong in my memory copying, at least it seems like that. What am I doing wrong?
    Last edited by Stargazers; January 23rd, 2008 at 01:27 AM. Reason: Tag wasn't closed

  10. #10
    Join Date
    Jan 2008
    Posts
    8

    Re: Voice over UDP problem

    I fixed it!

    So, I made function in client:

    Code:
    Private Sub Laheta(wHDR As WAVEHDR)
       ReDim aData(wHDR.dwBytesRecorded) As Byte
        
       CopyMemory aData(0), ByVal wHDR.lpData, wHDR.dwBytesRecorded
       Winsock1.SendData aData
    End Sub
    And in server:

    Code:
    Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
        
        ReDim RawAudioData(bytesTotal) As Byte
        
        Winsock1.GetData RawAudioData, vbByte
        
        Call InitWaveFormat(waveFmt)
        Call InitWaveHDR(wAlamolo, waveFmt, (waveFmt.nAvgBytesPerSec * TIMESLICE))
        wAlamolo.dwBytesRecorded = bytesTotal
        wAlamolo.lpData = VarPtr(RawAudioData(0))
        
        PlayWave wAlamolo
        
    End Sub
    Best of all - It really workd! Also, UDP packets was directly in right order. Even when I tested to send audio data to other computer!

    Thank you all for helping me
    Last edited by Stargazers; January 23rd, 2008 at 02:42 AM. Reason: Typo...

  11. #11
    Join Date
    Jan 2008
    Posts
    8

    Re: Voice over UDP problem

    Here again. Now I have other kind of problem. Hope someone can help me with this.

    Now I can send short samples and receive it. Great, it is good way to go on, but I'd like to send longer audio datas in real time. So, I think I should use two recording buffer (I have done that now) and two playback buffer.

    Now I have this kind of problem: how I can read data from socket to Playback Buffer and when it is full, it should play it and at same time it should fill the Playback Buffer 2?

    I mean, I need "real time" (well, almost... buffer takes little time surely) voice sending and receiving and playing.

    So, any ideas how I can make sure that whole data is read and buffer is full but in same time read to buffer 2 when it is playing buffer 1 out?

    Or should I have more than 2 output buffers?

    Any help would be very nice.

  12. #12
    Join Date
    Jan 2006
    Location
    Fox Lake, IL
    Posts
    15,007

    Re: Voice over UDP problem

    You might want to read this. Glad it worked so far.

    http://en.wikipedia.org/wiki/User_Datagram_Protocol
    David

    CodeGuru Article: Bound Controls are Evil-VB6
    2013 Samples: MS CODE Samples

    CodeGuru Reviewer
    2006 Dell CSP
    2006, 2007 & 2008 MVP Visual Basic
    If your question has been answered satisfactorily, and it has been helpful, then, please, Rate this Post!

  13. #13
    Join Date
    Jan 2008
    Posts
    8

    Re: Voice over UDP problem

    So near but still so far.

    Now I have two data buffers for playback also. In case that someone else is interested how I made it, so there it goes.

    In Winsock DataArrival I made static variable (bCounter) which tells us what buffer we should use. The first or the second. Then we save data from network to that buffer (aData or aData_x, depending on if bCounter is 1 or 2). Then, we point wOutHDR (aka. Wave Output Header) lpData pointing to first element of that aData or aData_x array.
    Then we just play it after setting dwBufferLenght.

    So, for example. First time when data arrivals, it is set to aData. Then we set bCounter = 2, so next time when data arrivals, it is set to aData_x. Now we set bCounter to 1, so next time it will go again in aData and so on, forever and ever...

    In first time, wOutHDR lpData points in aData(0), second time wOutHDR lpData points to aData_x(0)

    So, hope this help any way any other. But if you didn't understood my point, here's the sample.

    Code:
    Private Sub wsIn_DataArrival(ByVal bytesTotal As Long)
        Static bCounter As Byte
        
       ' Use first buffer
       If bCounter = 1 Then    
    
            Call WaitForCallback(wOutHDR.dwFlags, WHDR_DONE)
            ReDim aData(bytesTotal)
            wsIn.GetData aData, vbByte
            wOutHDR.dwBufferLength = bytesTotal
            wOutHDR.lpData = VarPtr(aData(0))
            PlayWave wOutHDR
            bCounter = 2
            
        ' Use second buffer
        Else   
            
            Call WaitForCallback(wOutHDR_x.dwFlags, WHDR_DONE)
            ReDim aData_x(bytesTotal)
            wsIn.GetData aData_x, vbByte
            wOutHDR_x.dwBufferLength = bytesTotal
            wOutHDR_x.lpData = VarPtr(aData_x(0))
            PlayWave wOutHDR_x
            bCounter = 1
    
        End If
     
    End Sub
    But, not too good. There is little gap between playing. Have to learn why there is little gap. Dang.

    Any help would be welcome, again
    Last edited by Stargazers; January 24th, 2008 at 05:42 AM. Reason: Added line Private Sub wsIn_DataArrival and End sub, so now it might be more easy to understand.

  14. #14
    Join Date
    Sep 2000
    Location
    FL
    Posts
    1,452

    Re: Voice over UDP problem

    Stargazers,

    dglienna is trying to tell you something. I suggest you take heed. Ever heard of VoUDP? No? There is a reason. You can't count on the data arriving in the order you sent it. And although it may work fine in a test bed situation, you will end up with problems when transferring data over heavily use network infrastructure like a business network or the Internet. If you keep going down the path you are going now, you will be back in a month asking why the audio is messed up when it worked great in development.

    As for you little gap, you are playing 2 different wave files there will always be a gap when you do this. What you need is a network stream. I am unsure how to do this in VB.

  15. #15
    Join Date
    Jan 2008
    Posts
    8

    Re: Voice over UDP problem

    Well, thank you for answers. Maybe I have to create some checking to be sure that order of bytes is right after and before send.

    But well, should I instead use TCP protocol? What do you think, will there be too much delay?

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured