|
-
January 22nd, 2008, 08:32 AM
#1
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 :)
-
January 22nd, 2008, 08:51 AM
#2
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.
-
January 22nd, 2008, 10:33 AM
#3
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.
-
January 22nd, 2008, 04:02 PM
#4
Re: Voice over UDP problem
 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.
 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?
 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?
 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?
 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?
-
January 22nd, 2008, 04:34 PM
#5
Re: Voice over UDP problem
-
January 22nd, 2008, 04:57 PM
#6
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)
-
January 22nd, 2008, 06:04 PM
#7
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.
-
January 23rd, 2008, 12:27 AM
#8
Re: Voice over UDP problem
 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?
 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?
-
January 23rd, 2008, 01:27 AM
#9
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
-
January 23rd, 2008, 02:40 AM
#10
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...
-
January 23rd, 2008, 04:43 PM
#11
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.
-
January 23rd, 2008, 04:49 PM
#12
Re: Voice over UDP problem
You might want to read this. Glad it worked so far.
http://en.wikipedia.org/wiki/User_Datagram_Protocol
-
January 24th, 2008, 05:40 AM
#13
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.
-
January 24th, 2008, 07:34 AM
#14
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.
-
January 24th, 2008, 08:20 AM
#15
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?
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|