Class: Deftones::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/deftones/context.rb

Direct Known Subclasses

OfflineContext

Defined Under Namespace

Classes: PortAudioOutputStream

Constant Summary collapse

DEFAULT_SAMPLE_RATE =
44_100
DEFAULT_BUFFER_SIZE =
256
DEFAULT_CHANNELS =
2

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sample_rate: DEFAULT_SAMPLE_RATE, buffer_size: DEFAULT_BUFFER_SIZE, channels: DEFAULT_CHANNELS, realtime_backend: nil, autostart: true, latency_hint: "interactive", look_ahead: nil, transport: nil, draw: nil, on_stream_error: nil, stream_error_mode: :abort, output_device_id: nil, output_device_label: nil) ⇒ Context

Returns a new instance of Context.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/deftones/context.rb', line 13

def initialize(sample_rate: DEFAULT_SAMPLE_RATE, buffer_size: DEFAULT_BUFFER_SIZE, channels: DEFAULT_CHANNELS,
               realtime_backend: nil, autostart: true, latency_hint: "interactive", look_ahead: nil,
               transport: nil, draw: nil, on_stream_error: nil, stream_error_mode: :abort,
               output_device_id: nil, output_device_label: nil)
  @sample_rate = sample_rate
  @buffer_size = buffer_size
  @channels = channels
  @transport = transport || Event::Transport.new(clock: self)
  @draw = draw || Draw.new
  @realtime_backend = realtime_backend
  @autostart = autostart
  @latency_hint = latency_hint
  @look_ahead = look_ahead || (buffer_size.to_f / sample_rate)
  @output_device_id = output_device_id
  @output_device_label = output_device_label
  @on_stream_error = on_stream_error
  @stream_error_mode = normalize_stream_error_mode(stream_error_mode)
  @output = Core::Gain.new(context: self, gain: 1.0)
  @running = false
  @closed = false
  @started_at = monotonic_time
  @stream = nil
  @rendered_frames = 0
  @scheduler_position = 0.0
  @stream_error = nil
  @stream_status_flags = []
end

Instance Attribute Details

#buffer_sizeObject (readonly)

Returns the value of attribute buffer_size.



9
10
11
# File 'lib/deftones/context.rb', line 9

def buffer_size
  @buffer_size
end

#channelsObject (readonly)

Returns the value of attribute channels.



9
10
11
# File 'lib/deftones/context.rb', line 9

def channels
  @channels
end

#drawObject (readonly)

Returns the value of attribute draw.



9
10
11
# File 'lib/deftones/context.rb', line 9

def draw
  @draw
end

#latency_hintObject (readonly) Also known as: latencyHint

Returns the value of attribute latency_hint.



9
10
11
# File 'lib/deftones/context.rb', line 9

def latency_hint
  @latency_hint
end

#look_aheadObject (readonly) Also known as: lookAhead

Returns the value of attribute look_ahead.



9
10
11
# File 'lib/deftones/context.rb', line 9

def look_ahead
  @look_ahead
end

#on_stream_errorObject Also known as: onStreamError

Returns the value of attribute on_stream_error.



11
12
13
# File 'lib/deftones/context.rb', line 11

def on_stream_error
  @on_stream_error
end

#output_device_idObject (readonly) Also known as: outputDeviceId

Returns the value of attribute output_device_id.



9
10
11
# File 'lib/deftones/context.rb', line 9

def output_device_id
  @output_device_id
end

#output_device_labelObject (readonly) Also known as: outputDeviceLabel

Returns the value of attribute output_device_label.



9
10
11
# File 'lib/deftones/context.rb', line 9

def output_device_label
  @output_device_label
end

#sample_rateObject (readonly)

Returns the value of attribute sample_rate.



9
10
11
# File 'lib/deftones/context.rb', line 9

def sample_rate
  @sample_rate
end

#stream_errorObject (readonly)

Returns the value of attribute stream_error.



9
10
11
# File 'lib/deftones/context.rb', line 9

def stream_error
  @stream_error
end

#stream_status_flagsObject (readonly) Also known as: streamStatusFlags

Returns the value of attribute stream_status_flags.



9
10
11
# File 'lib/deftones/context.rb', line 9

def stream_status_flags
  @stream_status_flags
end

#transportObject (readonly)

Returns the value of attribute transport.



9
10
11
# File 'lib/deftones/context.rb', line 9

def transport
  @transport
end

Instance Method Details

#block_timeObject Also known as: blockTime



114
115
116
# File 'lib/deftones/context.rb', line 114

def block_time
  buffer_size.to_f / sample_rate
end

#build_realtime_backendObject (private)



167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/deftones/context.rb', line 167

def build_realtime_backend
  case @realtime_backend
  when nil
    return unless Deftones.portaudio_available?

    PortAudioOutputStream.new(context: self)
  when Class
    @realtime_backend.new(context: self)
  else
    @realtime_backend
  end
end

#closeObject



65
66
67
68
69
# File 'lib/deftones/context.rb', line 65

def close
  stop
  @closed = true
  self
end

#current_timeObject



91
92
93
94
95
96
# File 'lib/deftones/context.rb', line 91

def current_time
  return @stream.time if @stream&.respond_to?(:time)
  return 0.0 unless @running

  monotonic_time - @started_at
end

#handle_stream_error(error) ⇒ Object (private)



197
198
199
200
201
# File 'lib/deftones/context.rb', line 197

def handle_stream_error(error)
  @stream_error ||= error
  @on_stream_error&.call(error)
  @stream_error_mode == :continue ? :continue : :abort
end

#monotonic_timeObject (private)



218
219
220
# File 'lib/deftones/context.rb', line 218

def monotonic_time
  Process.clock_gettime(Process::CLOCK_MONOTONIC)
end

#normalize_stream_error_mode(value) ⇒ Object (private)

Raises:

  • (ArgumentError)


211
212
213
214
215
216
# File 'lib/deftones/context.rb', line 211

def normalize_stream_error_mode(value)
  normalized = value.to_sym
  return normalized if %i[abort continue].include?(normalized)

  raise ArgumentError, "Unsupported stream error mode: #{value}"
end

#outputObject



86
87
88
89
# File 'lib/deftones/context.rb', line 86

def output
  start if @autostart && !running?
  @output
end

#pull_realtime_samples(frames) ⇒ Object (private)



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/deftones/context.rb', line 180

def pull_realtime_samples(frames)
  start_frame = @rendered_frames
  next_frame = start_frame + frames
  window_start = start_frame.to_f / sample_rate
  window_end = next_frame.to_f / sample_rate
  scheduler_end = window_end + look_ahead
  scheduler_start = [@scheduler_position, window_start].max
  @transport.prepare_render_window(scheduler_start, scheduler_end)
  Deftones.transport.prepare_render_window(scheduler_start, scheduler_end) unless Deftones.transport.equal?(@transport)
  chunk = render_block_frames(frames, start_frame).fit_channels(@channels)
  @rendered_frames = next_frame
  @scheduler_position = scheduler_end
  @draw.advance_to(scheduler_end)
  Deftones.draw.advance_to(scheduler_end) unless Deftones.draw.equal?(@draw)
  chunk.interleaved
end

#raw_contextObject Also known as: rawContext



106
107
108
# File 'lib/deftones/context.rb', line 106

def raw_context
  self
end

#realtime?Boolean

Returns:

  • (Boolean)


82
83
84
# File 'lib/deftones/context.rb', line 82

def realtime?
  !@stream.nil?
end

#record_stream_status_flags(status_flags) ⇒ Object (private)



203
204
205
206
207
208
209
# File 'lib/deftones/context.rb', line 203

def record_stream_status_flags(status_flags)
  return self if status_flags.nil?
  return self if status_flags.respond_to?(:zero?) && status_flags.zero?

  @stream_status_flags << status_flags
  self
end

#render_block_frames(num_frames, start_frame = 0) ⇒ Object



102
103
104
# File 'lib/deftones/context.rb', line 102

def render_block_frames(num_frames, start_frame = 0)
  @output.send(:render_block, num_frames, start_frame, {})
end

#render_frames(num_frames, start_frame = 0) ⇒ Object



98
99
100
# File 'lib/deftones/context.rb', line 98

def render_frames(num_frames, start_frame = 0)
  render_block_frames(num_frames, start_frame).mono
end

#reset!Object



118
119
120
121
122
123
124
125
126
127
# File 'lib/deftones/context.rb', line 118

def reset!
  stop
  @transport = Event::Transport.new(clock: self)
  @draw = Draw.new
  @stream_error = nil
  @stream_status_flags.clear
  @rendered_frames = 0
  @scheduler_position = 0.0
  self
end

#resume(use_realtime: true) ⇒ Object



53
54
55
# File 'lib/deftones/context.rb', line 53

def resume(use_realtime: true)
  start(use_realtime: use_realtime)
end

#running?Boolean

Returns:

  • (Boolean)


71
72
73
# File 'lib/deftones/context.rb', line 71

def running?
  @running
end

#sample_timeObject Also known as: sampleTime



110
111
112
# File 'lib/deftones/context.rb', line 110

def sample_time
  1.0 / sample_rate
end

#start(use_realtime: true) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
# File 'lib/deftones/context.rb', line 41

def start(use_realtime: true)
  @closed = false
  @started_at = monotonic_time
  @rendered_frames = 0
  @scheduler_position = 0.0
  @stream_error = nil
  @stream_status_flags.clear
  @running = true
  start_realtime_stream if use_realtime
  self
end

#start_realtime_streamObject (private)



153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/deftones/context.rb', line 153

def start_realtime_stream
  return if @stream

  backend = build_realtime_backend
  return unless backend

  backend.start
  @stream = backend
rescue StandardError => error
  backend&.close if backend.respond_to?(:close)
  @stream_error = error
  @stream = nil
end

#stateObject



75
76
77
78
79
80
# File 'lib/deftones/context.rb', line 75

def state
  return "closed" if @closed
  return "running" if running?

  "suspended"
end

#stopObject



57
58
59
60
61
62
63
# File 'lib/deftones/context.rb', line 57

def stop
  @stream&.stop
  @stream&.close if @stream.respond_to?(:close)
  @stream = nil
  @running = false
  self
end

#stream_error_modeObject Also known as: streamErrorMode



139
140
141
# File 'lib/deftones/context.rb', line 139

def stream_error_mode
  @stream_error_mode
end

#stream_error_mode=(value) ⇒ Object Also known as: streamErrorMode=



143
144
145
# File 'lib/deftones/context.rb', line 143

def stream_error_mode=(value)
  @stream_error_mode = normalize_stream_error_mode(value)
end