LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How do I transfer a sound file via TCP?

The red dot indicates data coercion. It's converting the 1D array to a waveform. You can do this yourself by simply doing the same thing you were doing with the Build Waveform function and feeding the waveform to the Sound Output Write VI. You can use dummy values for dt and start time.

You cannot use the same task ID since the music is playing on another computer! You have to call the Sound Output Configure VI in your client VI in order to create a task ID for the sound card that's in the client computer. As I indicated, the dt will indicate the sampling rate, and that's what you need for Sound Output Configure. Unfortunately, the sound functions require that you create a new task ID each time you reconfigure. This means that your client has to keep track of the task ID and close the current task ID and create a new one if it receives this "new song coming through, here's the sampling rate for it" command. Otherwise, you'll be creating and orphaning task IDs with each new song.

I think you may be beginning to see why music streaming isn't so trivial. Smiley Wink
0 Kudos
Message 11 of 35
(1,802 Views)
So I've made progress.  Using your suggestion and send over just the y data, using the output configure, output write, and output clear.vi's I've been able to produce sound on both sides (server and client) but, it's choppy on both ends.  It plays for maybe a half second, stops, another half second, stops, another, stops...this happens for both the server and client.  Why is this?  I can understand why on the client side since I do not have a sampling rate set up for the sound config vi but why the server side?
 
Also, with the sampling rate, where does this get hooked up to?  sound output configure requires a cluster with the sample rate within the cluster along with number of channels and bits per sample.  Instead of just the dt should I send over the entire cluster or how do I hook up just the dt?
0 Kudos
Message 12 of 35
(1,799 Views)
Why don't you upload your new VIs, and I can take a look at them. Sending over the whole cluster will work, and is probably the best way to do it since it has those other pieces of information.

Note: If you can say that you're going to play songs that are all the same sampling rate, then you can simplify this considerably, by calling the Sound Output Configure just once, outside the loop in your client.
0 Kudos
Message 13 of 35
(1,796 Views)
Let me know what you think.  I'm gonna try something real quick that might work..not sure.  I appreciate the help.
0 Kudos
Message 14 of 35
(1,793 Views)
I took a quick look at this for you. Basically, to get rid of the choppiness you have to remove the playing of the sound in the server loop. That's slowing down the loop and the transmission of the data. If you want the music playing on the server as well (not sure why) you will need a separate, independent loop to play the sound. You can probably use a queue to share the data between the two loops.

What you've got is a decent start, though it's a fair bit off from being functional. You would need to modify the client VI to do the sound configuration as I had mentioned in my previous response. How you do it depends on whether you intend to be able to play songs of different rates, or you're just going to have all songs be the same sampling rate. The latter will obviously be easier. In fact, what you've got right now for the client does this, without needing to send over the configuration from the server to the client.

Also, you need to deal with handling the server starting up before a client is listening. Normally, the server is always running and client connect and disconnect as desired. As you have it, if the server starts up and there's no client listening the server still goes ahead and read the sound file, but the TCP/IP functions won't do anything because of the error coming from the TCP Open Connection.

All in all a pretty decent start.
0 Kudos
Message 15 of 35
(1,783 Views)

This is kind of a test to show latency using TCP.  I'd have one both playing the sound file and instead of saying ("TCP has an average 3ms latency...") you could hear the difference.

So to eliminate the choppiness I need to remove the playing vi from the server?  Can do.  I'll have one loop to play it and the other loop to just read the data and send it over.  What do you mean by "use a queue to share the data"?

My current set up does configure the sound like you had suggested but I thought it was still wrong since I was getting choppiness.  I'll put those blocks back in and make the change you suggested and try again.  And you're saying to have the server wait until a connection from the client has been established?  Sounds good.  Thanks again.



Message Edited by MSAT on 03-17-2008 07:30 AM
0 Kudos
Message 16 of 35
(1,768 Views)
You don't want to be calling the Play Waveform in the loop that's transmitting data because you want that loop to be as tight as possible. Iif you want to be playing the sound at the server while you're transmitting you need a second, independent loop. Well, you don't really want both loops to be reading the sound file. You just want one loop to do it. Thus, you need to get the data over to the other loop. You can't use a wire since that will establish a data dependency, and cause the loop that's the sink to wait until the source loop is done before it runs. A queue is a way to shuttle data across loops and VIs. A global variable is another. With a queue you basically just place the same data you get from the read file VI. You can check the LabVIEW documentation and the examples for how to use queues.

As for the server/client waiting for connections: The answer depends on what kind of operational model you are trying to achieve. A "regular" music server like the ones you have on the internet are basically always broadcasting, and clients connect and disconnect at whim. If this is the model you're trying to achieve, then what you have won't work since it depends on one or the other starting first. In your setup you require the client to start up first.

You can take a look at the "Multiple Connections" example that ships with LabVIEW as a potential alternate model that allows multiple connections. To find it, open the Example Finder (Help -> Find Examples) and search for "TCP/IP". Whether or not this is how you should set it up really depends on your fundamental operational goal.
0 Kudos
Message 17 of 35
(1,760 Views)
I tried a different set up using TCP to send over the data but now I can't even get the sound to play on the other side.  The error I get the second the connection is made is "Not enough memory to complete the operation."  The data isn't even getting sent over correctly.  What have I done wrong here?
 
Attached are my new VI's that I've put together using TCP.  Let me know what errors you see and what I should do to change it.
Download All
0 Kudos
Message 18 of 35
(1,699 Views)
Change your constants of 8 and 100 to both be 4. Where did you come up with 8 and 100? You need to read an I32 to get the number of bytes that follow, and an I32 is 4 bytes long.
0 Kudos
Message 19 of 35
(1,696 Views)
Both randomly chosen but what difference does changing those number make?  I thought they just had to be large enough to accept the data type being sent over.  If those values are bigger than that--does it matter?
0 Kudos
Message 20 of 35
(1,691 Views)