I have an issue using naudio for a project of mine - most likely I just overlooked a tiny error, but I don't catch it, so may I kindly ask for some help.
I am working on a project to receive (and further work with) an audio stream I receive over a network. The stream is encoded with G.711 a-law using 8kHz and 8bit and sent in tiny pieces of 20ms (or 50 packets per second).
The following code receives the stream via UDP (basically whenever a UDP packet is received, it is read from the socket and added to the naudio BufferedWaveProvider:
Private Provider As New NAudio.Wave.BufferedWaveProvider(NAudio.Wave.WaveFormat.CreateALawFormat(8000, 1))
Private Sub FT636VOIP_U_Auslesen(ByVal ar As IAsyncResult)
sample = FT636VOIPUSocket.EndReceive(ar, New Net.IPEndPoint("10.48.11.43", 60001))
Provider.AddSamples(sample, 0, sample.Count)
FT636VOIPUSocket.BeginReceive(New AsyncCallback(AddressOf FT636VOIP_U_Auslesen), FT636VOIPUSocket)
End Sub
Being started in another thread (to avoid blocking the main application), a WaveOutEvent is linked with the BufferedWaveProvider for playback.
Private Sub Audio()
Dim wo As New NAudio.Wave.WaveOutEvent
wo.DesiredLatency = 1000
wo.Init(Provider)
wo.Play()
Do While wo.PlaybackState = NAudio.Wave.PlaybackState.Playing
Threading.Thread.Sleep(500)
Loop
End Sub
Well, the network connection is up and quickly filling the Buffer and the playback starts after the desired latency but only creates a 'choppy sound', though essentially there should only be silence...
Do I have to decode the stream at some stage (though the BufferedWaveProvider is initialized with the correct coded? Or do I miss something else...
You will get best results if you decode the audio as it arrives and put it into the BufferedWaveProvider as 16 bit audio. Also, are you sure that there is no surrounding metadata in the network packets being received? If so that needs to be stripped out or it will result in noise.
The NAudio demo project contains an example of this exact scenario, so you can use that as a reference if you need further help.
Related
I have been trying to use WebRTC Data Channel for a game, however, I am unable to consistently send live player data without hitting the queue size limit (8KB) after 50-70 secs of playing.
Sine the data is required to be real-time, I have no use for data that comes out of order. I have initialized the data channel with the following attributes:
negotiated: true,
id: id,
ordered: true,
maxRetransmits: 0,
maxPacketLifetime: 66
The MDN Docs said that the buffer cannot be altered in any way.
Is there anyway I can consistently send data without exceeding the buffer space? I don't mind purging the buffer space as it only contains data that has been clogged up over time.
NOTE: The data is transmitting until the buffer size exceeds the 8KB space.
EDIT: I forgot to add that this issue is only occurring when the two sides are on different networks. When both are within the same LAN, there is no buffering (since higher bandwidth, I presume). I tried to add multiple Data Channels (8 in parallel). However, this only increased the time before the failure occurred again. All 8 buffers were full. I also tried creating a new channel each time the buffer was close to being full and switched to the new DC while closing the previous one that was full, but I found out the hard way (reading Note in MDN Docs) that the buffer space is not released immediately, rather tries to transmit all data in the buffer taking away precious bandwidth.
Thanks in advance.
The maxRetransmits value is ignored if the maxPacketLifetime value is set; thus, you've configured your channel to resend packets for up to 66ms. For your application, it is probably better to use a pure unreliable channel by setting maxPacketLifetime to 0.
As Sean said, there is no way to flush the queue. What you can do is to drop packets before sending them if the channel is congested:
if(dc.bufferedAmount > 0)
return;
dc.send(data);
Finally, you should realise that buffering may happen in the network as well as at the sender: any router can buffer packets when it is congested, and many routers have very large buffers (this is called BufferBloat). The WebRTC stack should prevent you from buffering too much data in the network, but if WebRTC's behaviour is not aggressive enough for your needs, you will need to add explicit feedback from the sender to the receiver in order to avoid having too many packets in flight.
I don't believe you can flush the outbound buffer, you will probably need to watch the bufferedAmount and adjust what you are sending if it grows.
Maybe handle the retransmissions yourselves and discard old data if needed? WebRTC doesn't surface the SACKs from SCTP. So I think you will need to implement something yourself.
It's an interesting problem. Would love to hear the WebRTC W3C WorkGroup takes on it if exposing more info would make things easier for you.
I have to send file byte-by-byte to serially connected AT89s52 from computer (VB.NET).
Every sended byte have some job to do in microcontroller what require some time.
Here is relevant part of my C code to receiving bytes:
SCON = 0x50;
TMOD = 0x20; // timer 1, mode 2, 8-bit reload
TH1 = 0xFD; // reload value for 9600 baud
TR1 = 1;
TI = 1;
again:
while(RI!=0)
{
P1=SBUF; // show data on led's
RI=0;
receivedBytes++;
}
if (key1==0)
{
goto exitreceive; // break receiving
}
show_lcd_received_bytes(receivedBytes);
// here is one more loop
// with different duration for every byte
goto again;
And here is VB.NET code for sending bytes:
For a As Integer = 1 To 10
For t As Integer = 0 To 255
SerialPort1.Write(Chr(t))
Next t
Next a
Problem is that mC have some job to do after every received byte and VB.NET don't know for that and send bytes too fast so in mC finishes just a part of all bytes (about 10%).
I can incorporate "Sleep(20)" in VB loop ant then thing will work but I have many of wasted time because every byte need different time to process and that would be unacceptable slow communication.
Now, my question is if 8051 can set some busy status on UART which VB can read before sending to decide to send byte or not.
Or how otherwise to setup such communication as described?
I also try to receive bytes with serial interrupt on mC side with same results.
Hardware is surely OK because I can send data to computer well (as expected).
Your problem is architectural. Don't try to do processing on the received data in the interrupt that handles byte Rx. Have your byte Rx interrupt only copy the received byte to a separate Rx data buffer, and have a background task that does the actual processing of the incoming data without blocking the Rx interrupt handler. If you can't keep up due to overall throughput issue, then RTS/CTS flow control is the appropriate mechanism. For example, when your Rx buffer gets 90% full, deassert the flow control signal to pause the transmit side.
As #TJD mentions hardware flow control can be used to stop the PC from sending characters while the microcomputer is processing received bytes. In the past I have implemented hardware flow by using an available port line as an output. The output needs to be connected to an TTL to RS-232 driver(if you are currently using a RS-232 you may have and extra driver available). If you are using a USB virtual serial port or RS-422/485 you will need to implement software flow control. Typically a control-S is sent to tell the PC to stop sending and a control-Q to continue. In order to take full advantage of flow control you most likely will need to also implement a fully interrupt driven FIFO to receive/send characters.
If you would like additional information concerning hardware flow control, check out http://electronics.stackexchange.com.
Blast from the past, I remember using break out boxes to serial line tracers debugging this kind of stuff.
With serial communication, if you have all the pins/wires utililzed then there is flow control via the RTS (Ready To Send) and DTR (Data Terminal Ready) that are used to signal when it is OK to send more data. Do you have control over that in the device you are coding via C? IN VB.NET, there are events used to receive these signals, or they can be queried using properties on the SerialPort object.
A lot of these answers are suggesting hardware flow control, but you also have the option of enhancing your transmission to be more robust by using software flow control. Currently, your communication is strong, but if you start running a higher baud rate or a longer distance or even just have a noisy connection, characters could be received that are incorrect, or characters could be dropped.
You could add a simple two-byte ACK sequence upon completion of whatever action is set to happen. It could look something like this:
Host sends command byte: <0x00>
Device echoes command byte: <0x00>
Device executes whatever action is needed
Device sends ACK/NAK byte (based on result):
This would allow you to see on the host side if communication is breaking down. The echoed character may mismatch what was sent which would alert you to an issue. Additionally, if a character is not received by the host within some timeout, the host can try retransmitting. Finally, the ACK/NAK gives you the option of returning a status, but most importantly it will let the host know that you've completed the operation and that it can send another command.
This can be extended to include a checksum to give the device a way to verify that the command received was valid (A simple logical inverse sent alongside the command byte would be sufficient).
The advantage to this solution is that it does not require extra lines or UART support on either end for hardware flow control.
I'm coding a simple TCP client/server in VB.NET to transfer files of all sizes. I decided to use System.Net.Sockets's command SendFile to transfer the bytes through the socket.
On the receiving side, my code to retrieve the bytes works fairly well, but occasionally the transfer randomly stops.
I figured out that by putting a small sleep delay between retrieving the next block of data makes the transfers 100% stable.
My code to retrieve the data (until there is no data available) is simplified as this:
While newSocket.Available > 0
Threading.Thread.Sleep(100)
newSocket.ReceiveFrom(data, Remote)
End While
I really hate using that sleep delay and figure there must be a proper method/function to retrieve data from SendFile?
Socket.Available returns the total number of bytes that have been received so far that have not yet been read. Therefore, if you read the data faster than its coming in (which is quite possible on a slow network), there will be no more data to read even though the client is still in the middle of sending the data.
If the client makes a new connection to the server for each file it sends, you could simply change it to something like this:
While newSocket.Connected
If newSocket.Available > 0 Then
newSocket.ReceiveFrom(data, Remote)
End If
End While
However, I would suggest using the asynchronous calls, instead, such as BeginReceive. Then, your delegate will be called as soon as there is data to be processed, rather than waiting in a constant loop. See this link for an example:
http://msdn.microsoft.com/en-us/library/dxkwh6zw.aspx
I am consuming real-time data from a network stream using a blocking read as follows:
Do
NetworkStream.Read(Bytes, 0, ReceiveBufferSize)
'Do stuff with data here
Loop
Watching packets come in on the wire in Wireshark, I see that sometimes when a new packet comes in, .NET sees it immediately and unblocks, letting me process it. Other times, multiple packets will come in on the wire before the NetworkStream.Read unblocks and returns the whole lot in one go - I've seen up to 8 packets buffer before the NetworkStream read unblocks.
Is this expected behaviour? Is there a way to grab and process each packet immediately as it is received across the wire? Will an Async receive model make any difference here? Or am I just fundamentally misunderstanding the way that TCP streams work?
I am trying to write an app that exchanges data with other iPhones running the app through the Game Kit framework. The iPhones discover each other and connect fine, but the problems happens when I send the data. I know the iPhones are connected properly because when I serialize an NSString and send it through the connection it comes out on the other end fine. But when I try to archive a larger object (using NSKeyedArchiver) I get the error message "AGPSessionBroadcast failed (801c0001)".
I am assuming this is because the data I am sending is too large (my files are about 500k in size, Apple seems to recommend a max of 95k). I have tried splitting up the data into several transfers, but I can never get it to unarchive properly at the other end. I'm wondering if anyone else has come up against this problem, and how you solved it.
I had the same problem w/ files around 300K. The trouble is the sender needs to know when the receiver has emptied the pipe before sending the next chunk.
I ended up with a simple state engine that ran on both sides. The sender transmits a header with how many total bytes will be sent and the packet size, then waits for acknowledgement from the other side. Once it gets the handshake it proceeds to send fixed size packets each stamped with a sequence number.
The receiver gets each one, reads it and appends it to a buffer, then writes back to the pipe that it got packet with the sequence #. Sender reads the packet #, slices out another buffer's worth, and so on and so forth. Each side keeps track of the state they're in (idle, sending header, receiving header, sending data, receiving data, error, done etc.) The two sides have to keep track of when to read/write the last fragment since it's likely to be smaller than the full buffer size.
This works fine (albeit a bit slow) and it can scale to any size. I started with 5K packet sizes but it ran pretty slow. Pushed it to 10K but it started causing problems so I backed off and held it at 8096. It works fine for both binary and text data.
Bear in mind that the GameKit isn't a general file-transfer API; it's more meant for updates of where the player is, what the current location or other objects are etc. So sending 300k for a game doesn't seem that sensible, though I can understand hijacking the API for general sharing mechanisms.
The problem is that it isn't a TCP connection; it's more a UDP (datagram) connection. In these cases, the data isn't a stream (which gets packeted by TCP) but rather a giant chunk of data. (Technically, UDP can be fragmented into multiple IP packets - but lose one of those, and the entire UDP is lost, as opposed to TCP, which will re-try).
The MTU for most wired networks is ~1.5k; for bluetooth, it's around ~0.5k. So any UDP packet that you sent (a) may get lost, (b) may be split into multiple MTU-sized IP packets, and (c) if one of those packets is lost, then you will automatically lose the entire set.
Your best strategy is to emulate TCP - it sends out packets with a sequence number. The receiving end can then request dupe transmissions of packets which went missing afterwards. If you're using the equivalent of an NSKeyedArchiver, then one suggestion is to iterate through the keys and write those out as individual keys (assuming each keyed value isn't that big on its own). You'll need to have some kind of ACK for each packet that gets sent back, and a total ACK when you're done, so the sender knows it's OK to drop the data from memory.