Class: Deftones::Core::AudioBlock
- Inherits:
-
Object
- Object
- Deftones::Core::AudioBlock
- Defined in:
- lib/deftones/core/audio_block.rb
Instance Attribute Summary collapse
-
#channel_data ⇒ Object
readonly
Returns the value of attribute channel_data.
Class Method Summary collapse
- .from_channel_data(channel_data) ⇒ Object
- .from_interleaved(samples, channels:) ⇒ Object
- .from_mono(samples, channels: 1) ⇒ Object
- .from_packed_float32(payload, channels:) ⇒ Object
- .silent(num_frames, channels = 1) ⇒ Object
Instance Method Summary collapse
- #apply_headroom(sample, policy) ⇒ Object private
- #channel(index) ⇒ Object
- #channels ⇒ Object
- #downmixed_channel(policy) ⇒ Object private
- #dup ⇒ Object
- #fit_channels(target_channels, downmix: :average, upmix: :wrap) ⇒ Object
-
#initialize(channel_data) ⇒ AudioBlock
constructor
A new instance of AudioBlock.
- #interleaved ⇒ Object
- #mix!(other, headroom: :sum, gain: 1.0) ⇒ Object
- #mono ⇒ Object
- #num_frames ⇒ Object
- #packed_float32 ⇒ Object
- #packed_float64 ⇒ Object
- #upmixed_channel(index, policy) ⇒ Object private
Constructor Details
#initialize(channel_data) ⇒ AudioBlock
Returns a new instance of AudioBlock.
39 40 41 |
# File 'lib/deftones/core/audio_block.rb', line 39 def initialize(channel_data) @channel_data = channel_data end |
Instance Attribute Details
#channel_data ⇒ Object (readonly)
Returns the value of attribute channel_data.
6 7 8 |
# File 'lib/deftones/core/audio_block.rb', line 6 def channel_data @channel_data end |
Class Method Details
.from_channel_data(channel_data) ⇒ Object
12 13 14 15 |
# File 'lib/deftones/core/audio_block.rb', line 12 def self.from_channel_data(channel_data) normalized = channel_data.map { |channel| channel.map(&:to_f) } new(normalized) end |
.from_interleaved(samples, channels:) ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/deftones/core/audio_block.rb', line 22 def self.from_interleaved(samples, channels:) channel_count = [channels.to_i, 1].max normalized = Array(samples).map(&:to_f) frame_count = (normalized.length.to_f / channel_count).ceil from_channel_data( Array.new(channel_count) do |channel_index| Array.new(frame_count) do |frame_index| normalized[(frame_index * channel_count) + channel_index] || 0.0 end end ) end |
.from_mono(samples, channels: 1) ⇒ Object
17 18 19 20 |
# File 'lib/deftones/core/audio_block.rb', line 17 def self.from_mono(samples, channels: 1) normalized = samples.map(&:to_f) from_channel_data(Array.new([channels.to_i, 1].max) { normalized.dup }) end |
.from_packed_float32(payload, channels:) ⇒ Object
35 36 37 |
# File 'lib/deftones/core/audio_block.rb', line 35 def self.from_packed_float32(payload, channels:) from_interleaved(payload.unpack("e*"), channels: channels) end |
.silent(num_frames, channels = 1) ⇒ Object
8 9 10 |
# File 'lib/deftones/core/audio_block.rb', line 8 def self.silent(num_frames, channels = 1) from_channel_data(Array.new([channels.to_i, 1].max) { Array.new(num_frames.to_i, 0.0) }) end |
Instance Method Details
#apply_headroom(sample, policy) ⇒ Object (private)
131 132 133 134 135 136 137 138 |
# File 'lib/deftones/core/audio_block.rb', line 131 def apply_headroom(sample, policy) case policy when :sum then sample when :clamp then sample.clamp(-1.0, 1.0) else raise ArgumentError, "Unsupported headroom policy: #{policy}" end end |
#channel(index) ⇒ Object
80 81 82 |
# File 'lib/deftones/core/audio_block.rb', line 80 def channel(index) @channel_data[index] || Array.new(num_frames, 0.0) end |
#channels ⇒ Object
43 44 45 |
# File 'lib/deftones/core/audio_block.rb', line 43 def channels @channel_data.length end |
#downmixed_channel(policy) ⇒ Object (private)
109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/deftones/core/audio_block.rb', line 109 def downmixed_channel(policy) case policy when :average then mono when :sum Array.new(num_frames) { |frame_index| @channel_data.sum { |channel| channel[frame_index] } } when :first channel(0).dup else raise ArgumentError, "Unsupported downmix policy: #{policy}" end end |
#dup ⇒ Object
51 52 53 |
# File 'lib/deftones/core/audio_block.rb', line 51 def dup self.class.from_channel_data(@channel_data) end |
#fit_channels(target_channels, downmix: :average, upmix: :wrap) ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/deftones/core/audio_block.rb', line 84 def fit_channels(target_channels, downmix: :average, upmix: :wrap) target = [target_channels.to_i, 1].max return dup if target == channels return self.class.from_channel_data([downmixed_channel(downmix)]) if target == 1 if channels == 1 return self.class.from_channel_data(Array.new(target) { @channel_data.first.dup }) end self.class.from_channel_data(Array.new(target) { |index| upmixed_channel(index, upmix) }) end |
#interleaved ⇒ Object
64 65 66 67 68 69 70 |
# File 'lib/deftones/core/audio_block.rb', line 64 def interleaved Array.new(num_frames * channels) do |index| frame_index = index / channels channel_index = index % channels @channel_data[channel_index][frame_index] end end |
#mix!(other, headroom: :sum, gain: 1.0) ⇒ Object
96 97 98 99 100 101 102 103 104 105 |
# File 'lib/deftones/core/audio_block.rb', line 96 def mix!(other, headroom: :sum, gain: 1.0) incoming = other.fit_channels(channels) channels.times do |channel_index| num_frames.times do |frame_index| mixed = @channel_data[channel_index][frame_index] + (incoming.channel_data[channel_index][frame_index] * gain) @channel_data[channel_index][frame_index] = apply_headroom(mixed, headroom) end end self end |
#mono ⇒ Object
55 56 57 58 59 60 61 62 |
# File 'lib/deftones/core/audio_block.rb', line 55 def mono return [] if @channel_data.empty? return @channel_data.first.dup if channels == 1 Array.new(num_frames) do |frame_index| @channel_data.sum { |channel| channel[frame_index] } / channels.to_f end end |
#num_frames ⇒ Object
47 48 49 |
# File 'lib/deftones/core/audio_block.rb', line 47 def num_frames @channel_data.first&.length || 0 end |
#packed_float32 ⇒ Object
72 73 74 |
# File 'lib/deftones/core/audio_block.rb', line 72 def packed_float32 interleaved.pack("e*") end |
#packed_float64 ⇒ Object
76 77 78 |
# File 'lib/deftones/core/audio_block.rb', line 76 def packed_float64 interleaved.pack("E*") end |
#upmixed_channel(index, policy) ⇒ Object (private)
121 122 123 124 125 126 127 128 129 |
# File 'lib/deftones/core/audio_block.rb', line 121 def upmixed_channel(index, policy) case policy when :wrap then channel(index % channels).dup when :silence then index < channels ? channel(index).dup : Array.new(num_frames, 0.0) when :duplicate then channel([index, channels - 1].min).dup else raise ArgumentError, "Unsupported upmix policy: #{policy}" end end |