[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

ulaw audio over network

Earle Clubb

5/7/2007 8:43:00 PM

Does anyone know of a good way to stream ulaw audio (read from a file)
over a UDP socket? I have something (mostly) working, but I can't seem
to get the packet timing right. If I use a 10ms sleep, the packets end
up being ~12ms apart. However, if I use a lower value (say 8ms), the
packets are 8ms apart. The code I'm using is included below. Has
anyone done this or something similar?

Thanks,
Earle


Code:
require 'socket'

@audio_socket = UDPSocket.open
@audio_socket.connect("239.1.1.3", 4098)

def send_audio(filename)
data = ""

File.open(filename) do |file|
while file.read(80, data)
@audio_socket.send(data, 0)
sleep 0.01
end
end
end

send_audio(ARGV[0])

--
Posted via http://www.ruby-....

3 Answers

eden li

5/8/2007 7:29:00 AM

0

It looks like this is a pure #sleep issue and has nothing to do with
sending data over a socket. If you setup a simple loop and average
the time sleep actually sleeps, you get the following:

want = 0.008, actual (averaged over 1000 attempts) =
0.00800016689300537
want = 0.01, actual (averaged over 1000 attempts) = 0.0122149839401245
want = 0.012, want (averaged over 1000 attempts) = 0.0120026016235352

Not exactly sure what's so special about 10ms...

Here's what I ran to produce the output above:

def try(n)
dt, dc = [0, 0]
1_000.times do
t = Time.now.to_f
sleep n
dt += Time.now.to_f - t
dc += 1
end
dt / dc
end

[0.008, 0.01, 0.012].each do |n|
puts "want = #{n}, actual (averaged over 1000 attempts) = #{try(n)}"
end

On May 8, 4:42 am, Earle Clubb <ecl...@valcom.com> wrote:
> Does anyone know of a good way to stream ulaw audio (read from a file)
> over a UDP socket? I have something (mostly) working, but I can't seem
> to get the packet timing right. If I use a 10ms sleep, the packets end
> up being ~12ms apart. However, if I use a lower value (say 8ms), the
> packets are 8ms apart. The code I'm using is included below. Has
> anyone done this or something similar?
>
> Thanks,
> Earle
>
> Code:
> require 'socket'
>
> @audio_socket = UDPSocket.open
> @audio_socket.connect("239.1.1.3", 4098)
>
> def send_audio(filename)
> data = ""
>
> File.open(filename) do |file|
> while file.read(80, data)
> @audio_socket.send(data, 0)
> sleep 0.01
> end
> end
> end
>
> send_audio(ARGV[0])
>
> --
> Posted viahttp://www.ruby-....


Brian Candler

5/8/2007 7:57:00 AM

0

On Tue, May 08, 2007 at 04:28:37PM +0900, eden li wrote:
> It looks like this is a pure #sleep issue and has nothing to do with
> sending data over a socket. If you setup a simple loop and average
> the time sleep actually sleeps, you get the following:
>
> want = 0.008, actual (averaged over 1000 attempts) =
> 0.00800016689300537
> want = 0.01, actual (averaged over 1000 attempts) = 0.0122149839401245
> want = 0.012, want (averaged over 1000 attempts) = 0.0120026016235352
>
> Not exactly sure what's so special about 10ms...
>
> Here's what I ran to produce the output above:
>
> def try(n)
> dt, dc = [0, 0]
> 1_000.times do
> t = Time.now.to_f
> sleep n
> dt += Time.now.to_f - t
> dc += 1
> end
> dt / dc
> end
>
> [0.008, 0.01, 0.012].each do |n|
> puts "want = #{n}, actual (averaged over 1000 attempts) = #{try(n)}"
> end

Regardless of how well Ruby's sleep worked, this would still be inaccurate
because of the time needed to execute the other things in the loop.

Try something like this instead:

def run
t = Time.now.to_f
1_000.times do
yield if block_given?
t += 0.01
interval = t - Time.now.to_f
sleep(interval) if interval > 0 # sleep barfs with negative values
end
end

t1 = Time.now
run { x = x }
t2 = Time.now
puts t2 - t1

Your UDP packets will have a small amount of jitter, which the far end's
jitterbuffer will handle (and if this is going over the Internet, you'll get
a lot more jitter from other sources), but will be sent at an average rate
of one every 10ms.

Brian.

Earle Clubb

5/8/2007 1:58:00 PM

0

Brian Candler wrote:
> Regardless of how well Ruby's sleep worked, this would still be
> inaccurate
> because of the time needed to execute the other things in the loop.
>
> Try something like this instead:
>
> def run
> t = Time.now.to_f
> 1_000.times do
> yield if block_given?
> t += 0.01
> interval = t - Time.now.to_f
> sleep(interval) if interval > 0 # sleep barfs with negative values
> end
> end
>
> t1 = Time.now
> run { x = x }
> t2 = Time.now
> puts t2 - t1
>
> Your UDP packets will have a small amount of jitter, which the far end's
> jitterbuffer will handle (and if this is going over the Internet, you'll
> get
> a lot more jitter from other sources), but will be sent at an average
> rate
> of one every 10ms.
>
> Brian.

Brian,

Your solution worked perfectly. The time between packets alternates
between 8ms and 12ms, but averages out to 10ms. Thanks for your help.
Thanks also to you, Eden.

Earle

--
Posted via http://www.ruby-....