Ulaw audio over network

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-forum.com/.

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-forum.com/.

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.

···

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

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-forum.com/.