Class: Hallon::AudioQueue

Inherits:
Object
  • Object
show all
Defined in:
lib/hallon/audio_queue.rb

Overview

Hallon::AudioQueue is a non-blocking (well, not entirely) sized FIFO queue.

You initialize the queue with a max_size, and then push data to it. For every push operation, the AudioQueue will tell you how much of your data it could consume. If the queue becomes full, it won’t accept any more data (and will return 0 on the #push operation) until you pull some data out of it with #pop.

Hallon::AudioQueue is useful for handling Observable::Session#music_delivery_callback.

Examples:

filling the buffer

queue = Hallon::AudioQueue.new(4)
format = { :rate => 44100, :channels => 2 }
queue.push(format, [1, 2]) # => 2
queue.push(format, [3]) # => 1
queue.push(format, [4, 5, 6]) # => 1
queue.push(format, [5, 6]) # => 0
queue.pop(format, 1) # => [1]
queue.push(format, [5, 6]) # => 1
queue.pop(format) # => [2, 3, 4, 5]

changing the format

queue  = Hallon::AudioQueue.new(4)
queue.format # => nil
queue.push(:initial_format, [1, 2, 3, 4]) # => 4
queue.size # => 4
queue.format # => :initial_format
queue.push(:new_format, [1, 2]) # => 2
queue.size # => 2
queue.format # => :new_format

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(max_size) ⇒ AudioQueue

Returns a new instance of AudioQueue.

Parameters:

  • max_size (Integer)

    how many frames


41
42
43
44
45
46
47
48
# File 'lib/hallon/audio_queue.rb', line 41

def initialize(max_size)
  @max_size = max_size
  @frames   = []
  @format   = nil

  @frames.extend(MonitorMixin)
  @condvar  = @frames.new_cond
end

Instance Attribute Details

#formatObject (readonly)

Returns the format previously set by #format=.


104
105
106
# File 'lib/hallon/audio_queue.rb', line 104

def format
  @format
end

#max_sizeObject (readonly)

Returns the value of attribute max_size


38
39
40
# File 'lib/hallon/audio_queue.rb', line 38

def max_size
  @max_size
end

Instance Method Details

#clearObject

Clear all data from the AudioQueue.


99
100
101
# File 'lib/hallon/audio_queue.rb', line 99

def clear
  synchronize { @frames.clear }
end

#empty?Boolean

Returns true if the queue has a #size of 0.

Returns:

  • (Boolean)

    true if the queue has a #size of 0.


94
95
96
# File 'lib/hallon/audio_queue.rb', line 94

def empty?
  size.zero?
end

#new_condMonitorMixin::ConditionVariable

Create a condition variable bound to this AudioQueue. Should be used if you want to wait inside #synchronize.

Returns:

  • (MonitorMixin::ConditionVariable)

See Also:

  • (ruby stdlib)

121
122
123
# File 'lib/hallon/audio_queue.rb', line 121

def new_cond
  @frames.new_cond
end

#pop(format, num_frames = max_size) ⇒ Array?

Note:

If the queue is empty, this operation will block until data is available.

Note:

When data is available, if it’s not in the same format as the format requested the return value will be nil. This is to avoid the format changing during wait.

Returns array of data, but no longer than num_frames.

Parameters:

  • format (Hash)

    requested format

  • num_frames (Integer) (defaults to: max_size)

    max number of frames to pop off the queue

Returns:

  • (Array, nil)

    array of data, but no longer than num_frames


81
82
83
84
85
86
# File 'lib/hallon/audio_queue.rb', line 81

def pop(format, num_frames = max_size)
  synchronize do
    @condvar.wait_while { empty? }
    @frames.shift(num_frames) if format == @format
  end
end

#push(format, frames) ⇒ Integer

Note:

If the format is not the same as the current format, the queue is emptied before appending the new data. In this case, #format will be assigned to the new format as well.

Returns how much of the data that was added to the queue.

Parameters:

  • format (Hash)

    format of the audio frames given

  • frames (#take)

Returns:

  • (Integer)

    how much of the data that was added to the queue


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/hallon/audio_queue.rb', line 57

def push(format, frames)
  synchronize do
    unless format == @format
      @format = format
      clear
    end

    can_accept  = max_size - size
    new_frames = frames.take(can_accept)

    @frames.concat(new_frames)
    @condvar.signal

    new_frames.size
  end
end

#sizeInteger

Returns number of frames in buffer.

Returns:

  • (Integer)

    number of frames in buffer.


89
90
91
# File 'lib/hallon/audio_queue.rb', line 89

def size
  synchronize { @frames.size }
end

#synchronize { ... } ⇒ Object

Note:

this lock is re-entrant, you can nest it in itself

Use this if you wish to perform multiple operations on the AudioQueue atomicly.

Yields:

  • exclusive section around the queue contents

Returns:

  • whatever the given block returns


112
113
114
# File 'lib/hallon/audio_queue.rb', line 112

def synchronize
  @frames.synchronize { return yield }
end