Module: PWN::FFI::Volk

Extended by:
Library
Defined in:
lib/pwn/ffi/volk.rb

Overview

Thin VOLK (Vector-Optimized Library of Kernels) binding.

Dispatches to SIMD kernels (SSE/AVX/NEON/…) when the host provides them. Used by PWN::SDR::Decoder::DSP hot paths so MHz-rate I/Q work stays off the Ruby GC heap while orchestration remains pure Ruby.

Nothing here shells out and nothing is compiled at gem-install time — if libvolk is missing, .available? is false and callers fall back.

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.load_errorObject (readonly)

Returns the value of attribute load_error.



28
29
30
# File 'lib/pwn/ffi/volk.rb', line 28

def load_error
  @load_error
end

Class Method Details

.accumulate(opts = {}) ⇒ Object

Supported Method Parameters

sum = PWN::FFI::Volk.accumulate(samples: Array)



82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/pwn/ffi/volk.rb', line 82

public_class_method def self.accumulate(opts = {})
  raise 'ERROR: libvolk not available' unless available?

  samples = opts[:samples]
  n = samples.length
  return 0.0 if n.zero?

  in_ptr = float_ptr(samples)
  out_ptr = PubFFI::MemoryPointer.new(:float, 1)
  accum_fn.call(out_ptr, in_ptr, n)
  out_ptr.read_float
end

.authorsObject

Author(s)

0day Inc. support@0dayinc.com



168
169
170
# File 'lib/pwn/ffi/volk.rb', line 168

public_class_method def self.authors
  "AUTHOR(S):\n  0day Inc. <support@0dayinc.com>\n"
end

.available?Boolean

Supported Method Parameters

PWN::FFI::Volk.available?

Returns:

  • (Boolean)


51
52
53
54
55
# File 'lib/pwn/ffi/volk.rb', line 51

public_class_method def self.available?
  !@load_error && respond_to?(:volk_get_alignment, true)
rescue StandardError
  false
end

.dot_prod(opts = {}) ⇒ Object

Supported Method Parameters

sum = PWN::FFI::Volk.dot_prod(a: Array, b: Array)



151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/pwn/ffi/volk.rb', line 151

public_class_method def self.dot_prod(opts = {})
  raise 'ERROR: libvolk not available' unless available?

  a = opts[:a]
  b = opts[:b]
  n = [a.length, b.length].min
  return 0.0 if n.zero?

  a_ptr = float_ptr(a)
  b_ptr = float_ptr(b)
  out_ptr = PubFFI::MemoryPointer.new(:float, 1)
  dot_fn.call(out_ptr, a_ptr, b_ptr, n)
  out_ptr.read_float
end

.helpObject

Display Usage for this Module



174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/pwn/ffi/volk.rb', line 174

public_class_method def self.help
  puts "USAGE:
    #{self}.available?                           # => true/false
    #{self}.unpack_s16le(data: raw_bytes)        # s16le → Float[-1,1]
    #{self}.accumulate(samples:)                 # Σ samples
    #{self}.magnitude_squared(iq:)               # |z|² per complex pair
    #{self}.sqrt(samples:)
    #{self}.scale(samples:, factor:)
    #{self}.dot_prod(a:, b:)

    #{self}.authors
  "
end

.magnitude_squared(opts = {}) ⇒ Object

Supported Method Parameters

power = PWN::FFI::Volk.magnitude_squared( iq: 'required - Array of interleaved I/Q Floats (even length)' ) Returns Array of |z|^2 per complex sample.



101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/pwn/ffi/volk.rb', line 101

public_class_method def self.magnitude_squared(opts = {})
  raise 'ERROR: libvolk not available' unless available?

  iq = opts[:iq]
  n_c = iq.length / 2
  return [] if n_c.zero?

  in_ptr = float_ptr(iq)
  out_ptr = PubFFI::MemoryPointer.new(:float, n_c)
  mag2_fn.call(out_ptr, in_ptr, n_c)
  out_ptr.read_array_of_float(n_c)
end

.scale(opts = {}) ⇒ Object

Supported Method Parameters

out = PWN::FFI::Volk.scale(samples: Array, factor: Float) Multiplies every sample by factor.



134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/pwn/ffi/volk.rb', line 134

public_class_method def self.scale(opts = {})
  raise 'ERROR: libvolk not available' unless available?

  samples = opts[:samples]
  factor  = opts[:factor].to_f
  n = samples.length
  return [] if n.zero?

  in_ptr = float_ptr(samples)
  out_ptr = PubFFI::MemoryPointer.new(:float, n)
  scale_fn.call(out_ptr, in_ptr, factor, n)
  out_ptr.read_array_of_float(n)
end

.sqrt(opts = {}) ⇒ Object

Supported Method Parameters

out = PWN::FFI::Volk.sqrt(samples: Array)



117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/pwn/ffi/volk.rb', line 117

public_class_method def self.sqrt(opts = {})
  raise 'ERROR: libvolk not available' unless available?

  samples = opts[:samples]
  n = samples.length
  return [] if n.zero?

  in_ptr = float_ptr(samples)
  out_ptr = PubFFI::MemoryPointer.new(:float, n)
  sqrt_fn.call(out_ptr, in_ptr, n)
  out_ptr.read_array_of_float(n)
end

.unpack_s16le(opts = {}) ⇒ Object

Supported Method Parameters

samples = PWN::FFI::Volk.unpack_s16le( data: 'required - raw String of little-endian signed 16-bit PCM' ) Returns Array normalised to -1.0..1.0 (same contract as PWN::SDR::Decoder::DSP.unpack_s16le). VOLK treats scalar as a divisor, so pass 32768.0 to get unit-range floats.



65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/pwn/ffi/volk.rb', line 65

public_class_method def self.unpack_s16le(opts = {})
  raise 'ERROR: libvolk not available' unless available?

  data = opts[:data].to_s
  n = data.bytesize / 2
  return [] if n.zero?

  in_ptr = PubFFI::MemoryPointer.from_string(data)
  # from_string null-terminates — reclaim only the payload region
  out_ptr = PubFFI::MemoryPointer.new(:float, n)
  convert_fn.call(out_ptr, in_ptr, 32_768.0, n)
  out_ptr.read_array_of_float(n)
end