Class: Vizcore::Audio::InputManager

Inherits:
Object
  • Object
show all
Defined in:
lib/vizcore/audio/input_manager.rb

Overview

High-level coordinator for audio frame capture and ring-buffer storage.

Constant Summary collapse

DEFAULT_SAMPLE_RATE =

Default analysis/input sample rate.

44_100
DEFAULT_FRAME_SIZE =

Default samples read per frame.

1024
DEFAULT_RING_BUFFER_SIZE =

Default ring buffer capacity in samples.

4096

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source: :mic, sample_rate: DEFAULT_SAMPLE_RATE, frame_size: DEFAULT_FRAME_SIZE, ring_buffer_size: DEFAULT_RING_BUFFER_SIZE, file_path: nil, audio_device: nil) ⇒ InputManager

Returns a new instance of InputManager.

Parameters:

  • source (Symbol, String) (defaults to: :mic)

    input source (‘:mic`, `:file`, `:dummy`)

  • sample_rate (Integer) (defaults to: DEFAULT_SAMPLE_RATE)

    sample rate in Hz

  • frame_size (Integer) (defaults to: DEFAULT_FRAME_SIZE)

    frame size used by capture loop

  • ring_buffer_size (Integer) (defaults to: DEFAULT_RING_BUFFER_SIZE)

    stored sample capacity

  • file_path (String, nil) (defaults to: nil)

    source file path for ‘:file`

  • audio_device (String, Integer, nil) (defaults to: nil)

    input device index/name for ‘:mic`



29
30
31
32
33
34
35
36
37
# File 'lib/vizcore/audio/input_manager.rb', line 29

def initialize(source: :mic, sample_rate: DEFAULT_SAMPLE_RATE, frame_size: DEFAULT_FRAME_SIZE, ring_buffer_size: DEFAULT_RING_BUFFER_SIZE, file_path: nil, audio_device: nil)
  @source_name = source.to_sym
  @sample_rate = Integer(sample_rate)
  @frame_size = Integer(frame_size)
  @ring_buffer = RingBuffer.new(ring_buffer_size)
  @audio_device = audio_device
  @input = build_input(file_path)
  @sample_rate = resolve_input_sample_rate(@input, fallback: @sample_rate)
end

Instance Attribute Details

#frame_sizeObject (readonly)

Returns the value of attribute frame_size.



21
22
23
# File 'lib/vizcore/audio/input_manager.rb', line 21

def frame_size
  @frame_size
end

#ring_bufferObject (readonly)

Returns the value of attribute ring_buffer.



21
22
23
# File 'lib/vizcore/audio/input_manager.rb', line 21

def ring_buffer
  @ring_buffer
end

#sample_rateObject (readonly)

Returns the value of attribute sample_rate.



21
22
23
# File 'lib/vizcore/audio/input_manager.rb', line 21

def sample_rate
  @sample_rate
end

#source_nameObject (readonly)

Returns the value of attribute source_name.



21
22
23
# File 'lib/vizcore/audio/input_manager.rb', line 21

def source_name
  @source_name
end

Class Method Details

.available_audio_devicesArray<Hash>

Returns detected audio devices or fallback dummy descriptor.

Returns:

  • (Array<Hash>)

    detected audio devices or fallback dummy descriptor



93
94
95
96
97
98
99
100
# File 'lib/vizcore/audio/input_manager.rb', line 93

def self.available_audio_devices
  devices = PortAudioFFI.input_devices
  return devices unless devices.empty?

  [
    { index: 0, name: "default (dummy fallback)", max_input_channels: 1, default_sample_rate: DEFAULT_SAMPLE_RATE.to_f }
  ]
end

.available_midi_devicesArray<Hash>

Returns detected MIDI devices or virtual fallback descriptor.

Returns:

  • (Array<Hash>)

    detected MIDI devices or virtual fallback descriptor



103
104
105
106
107
108
# File 'lib/vizcore/audio/input_manager.rb', line 103

def self.available_midi_devices
  devices = MidiInput.available_devices
  return devices unless devices.empty?

  [{ id: "virtual-0", name: "virtual-midi (optional dependency: unimidi)" }]
end

Instance Method Details

#capture_frame(read_size = frame_size) ⇒ Array<Float>

Capture one frame from the underlying input and append to ring buffer.

Returns:

  • (Array<Float>)


59
60
61
62
63
64
# File 'lib/vizcore/audio/input_manager.rb', line 59

def capture_frame(read_size = frame_size)
  count = Integer(read_size)
  samples = @input.read(count)
  ring_buffer.write(samples)
  samples
end

#latest_samples(count = frame_size) ⇒ Array<Float>

Returns recent samples from the ring buffer.

Parameters:

  • count (Integer) (defaults to: frame_size)

Returns:

  • (Array<Float>)

    recent samples from the ring buffer



68
69
70
# File 'lib/vizcore/audio/input_manager.rb', line 68

def latest_samples(count = frame_size)
  ring_buffer.latest(count)
end

#realtime_capture_size(frame_rate) ⇒ Integer

Returns approximate real-time sample count to ingest per render tick.

Parameters:

  • frame_rate (Numeric)

Returns:

  • (Integer)

    approximate real-time sample count to ingest per render tick



74
75
76
77
78
79
80
81
# File 'lib/vizcore/audio/input_manager.rb', line 74

def realtime_capture_size(frame_rate)
  rate = Float(frame_rate)
  return frame_size unless rate.positive?

  [(@sample_rate.to_f / rate).round, 1].max
rescue StandardError
  frame_size
end

#running?Boolean

Returns:

  • (Boolean)


52
53
54
# File 'lib/vizcore/audio/input_manager.rb', line 52

def running?
  @input.running?
end

#startVizcore::Audio::InputManager



40
41
42
43
# File 'lib/vizcore/audio/input_manager.rb', line 40

def start
  @input.start
  self
end

#stopVizcore::Audio::InputManager



46
47
48
49
# File 'lib/vizcore/audio/input_manager.rb', line 46

def stop
  @input.stop
  self
end

#sync_transport(playing:, position_seconds:) ⇒ void

This method returns an undefined value.

Parameters:

  • playing (Boolean)
  • position_seconds (Numeric)


86
87
88
89
90
# File 'lib/vizcore/audio/input_manager.rb', line 86

def sync_transport(playing:, position_seconds:)
  return unless @input.respond_to?(:sync_transport)

  @input.sync_transport(playing: playing, position_seconds: position_seconds)
end