ruby-sfml 3.0.0.4 → 3.0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +99 -0
- data/lib/sfml/audio/music.rb +14 -0
- data/lib/sfml/audio/sound_buffer.rb +13 -0
- data/lib/sfml/audio/sound_recorder.rb +126 -13
- data/lib/sfml/audio/sound_stream.rb +103 -0
- data/lib/sfml/c/audio.rb +47 -0
- data/lib/sfml/c/graphics.rb +146 -4
- data/lib/sfml/c/network.rb +45 -5
- data/lib/sfml/c/system.rb +12 -0
- data/lib/sfml/c/window.rb +20 -2
- data/lib/sfml/graphics/circle_shape.rb +3 -0
- data/lib/sfml/graphics/color.rb +30 -0
- data/lib/sfml/graphics/convex_shape.rb +3 -0
- data/lib/sfml/graphics/font.rb +19 -0
- data/lib/sfml/graphics/image.rb +12 -0
- data/lib/sfml/graphics/rectangle_shape.rb +5 -0
- data/lib/sfml/graphics/shader.rb +86 -0
- data/lib/sfml/graphics/shape.rb +114 -0
- data/lib/sfml/graphics/shape_inspectable.rb +92 -0
- data/lib/sfml/graphics/texture.rb +46 -10
- data/lib/sfml/graphics/transformable_object.rb +48 -0
- data/lib/sfml/graphics/vertex_array.rb +12 -0
- data/lib/sfml/graphics/vertex_buffer.rb +12 -0
- data/lib/sfml/network/packet.rb +123 -0
- data/lib/sfml/network/tcp_socket.rb +19 -0
- data/lib/sfml/network/udp_socket.rb +23 -0
- data/lib/sfml/system/input_stream.rb +88 -0
- data/lib/sfml/version.rb +1 -1
- data/lib/sfml/window/context.rb +56 -0
- data/lib/sfml/window/keyboard.rb +92 -4
- data/lib/sfml/window/video_mode.rb +22 -0
- data/lib/sfml.rb +6 -0
- metadata +7 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c20f8dbdc29ef33bf370ea4a7fbadf09f9652acc84834dc47f3ca9e325635d5d
|
|
4
|
+
data.tar.gz: f65b6a2c2799e01c45071e5801cb33056cdec961d3c52a1b4ffd209538868f51
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4ef7eabaab2ffe015f2e2325926d4d41f6f941f49392d9d3d72570198d1e5df9873aeec8d4a82a32aeea3dddd2174010b0993ca0c9cfc4070eb6b6630394ec70
|
|
7
|
+
data.tar.gz: 0d8d30d9bae64f2c84ecef83acbaebf7eda423133c362e0d7b397c90a531ad72477bbe64c61d80f10cdfc1e8a316612a2d8ca71f14fd1fe4581b5eee66510218
|
data/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,105 @@ ruby-sfml's own patch level.
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [3.0.0.5] — 2026-05-11
|
|
12
|
+
|
|
13
|
+
Round-trip release: closes every remaining CSFML 3.0 gap that's
|
|
14
|
+
useful from Ruby. The library now covers the surface area you'd
|
|
15
|
+
expect for porting a CSFML application straight across.
|
|
16
|
+
|
|
17
|
+
### Added — graphics
|
|
18
|
+
|
|
19
|
+
- `Color#+`, `Color#-`, `Color#*` (alias `modulate`),
|
|
20
|
+
`Color#to_integer` / `Color.from_integer(value)` — channel-wise
|
|
21
|
+
saturating arithmetic, plus packed 0xRRGGBBAA round-trips.
|
|
22
|
+
- Texture binding + geometric introspection on the three concrete
|
|
23
|
+
shapes via the new `Graphics::ShapeInspectable` mixin:
|
|
24
|
+
`CircleShape`/`RectangleShape`/`ConvexShape` all gain
|
|
25
|
+
`texture` / `texture=` / `set_texture(tex, reset_rect:)`,
|
|
26
|
+
`texture_rect` / `texture_rect=`, `point(i)`, `geometric_center`,
|
|
27
|
+
`local_bounds`, `global_bounds`, `transform`, `inverse_transform`,
|
|
28
|
+
`dup` / `clone`. `RectangleShape` additionally exposes
|
|
29
|
+
`point_count`.
|
|
30
|
+
- `SFML::Shape` — callback-driven abstract shape. Subclass and
|
|
31
|
+
override `#point_count` / `#point(i)` to drive geometry from
|
|
32
|
+
live Ruby data; call `#update` after the source data changes.
|
|
33
|
+
- `SFML::TransformableObject` — standalone transform container
|
|
34
|
+
(CSFML's `sfTransformable*`). Useful as a base for custom
|
|
35
|
+
drawables that combine a transform with their own rendering.
|
|
36
|
+
- `VertexArray#dup` / `#clone` — independent deep copy.
|
|
37
|
+
- `VertexBuffer#bind` / `VertexBuffer.unbind` — bind a VBO as the
|
|
38
|
+
active GL vertex buffer (for mixing raw GL with SFML rendering).
|
|
39
|
+
- Texture sRGB variants via the `srgb:` kwarg on
|
|
40
|
+
`Texture.load`, `Texture.create`, `Texture.from_memory`,
|
|
41
|
+
`Texture.from_image`, and `Texture#resize`.
|
|
42
|
+
- `Shader#set_mat3` / `#set_mat4` / `#set_mat3_array` /
|
|
43
|
+
`#set_mat4_array` and `Shader#set_bvec(name, *components)` —
|
|
44
|
+
matrix and bool-vector uniforms.
|
|
45
|
+
- `Shader.from_stream(vertex:, geometry:, fragment:)`,
|
|
46
|
+
`Font.from_stream(io)`, `Image.from_stream(io)`,
|
|
47
|
+
`Texture.from_stream(io, srgb:, ...)` — load any of these from a
|
|
48
|
+
Ruby IO-like object (File, StringIO, network reader). Backed by
|
|
49
|
+
the new `SFML::InputStream` adapter that wraps a Ruby IO as
|
|
50
|
+
CSFML's `sfInputStream*`.
|
|
51
|
+
|
|
52
|
+
### Added — audio
|
|
53
|
+
|
|
54
|
+
- Full 3D-audio surface on `SoundStream` (mirror of Sound / Music):
|
|
55
|
+
`pan`, `min_gain` / `max_gain`, `max_distance`,
|
|
56
|
+
`spatialization_enabled?`, `direction`, `cone`, `velocity`,
|
|
57
|
+
`doppler_factor`, `directional_attenuation_factor`,
|
|
58
|
+
`effect_processor=` (real-time DSP filter), `channel_map` — and
|
|
59
|
+
the `=` setters.
|
|
60
|
+
- `SoundRecorder#channel_map` — read the channel layout the
|
|
61
|
+
recorder is producing.
|
|
62
|
+
- `SFML::SoundRecorder` — callback-based mic capture. Subclass
|
|
63
|
+
and override `#on_start` / `#on_process_samples(samples,
|
|
64
|
+
channels)` / `#on_stop`. The pre-existing module-level helpers
|
|
65
|
+
(`SoundRecorder.available?` / `.devices` / `.default_device`)
|
|
66
|
+
are preserved as class methods.
|
|
67
|
+
- `Music.from_stream(io, **opts)` and
|
|
68
|
+
`SoundBuffer.from_stream(io)` — stream-backed audio loaders.
|
|
69
|
+
|
|
70
|
+
### Added — network
|
|
71
|
+
|
|
72
|
+
- `SFML::Network::Packet` — wire-compatible with `sf::Packet`. Typed
|
|
73
|
+
read / write for `Bool`, `Int8`–`Int64`, `Uint8`–`Uint64`,
|
|
74
|
+
`Float`, `Double`, `String`; `#data` / `#size` / `#read_position`
|
|
75
|
+
/ `#end_of_packet?` / `#ok?` / `#clear` / `#dup`.
|
|
76
|
+
- `TcpSocket#send_packet` / `#receive_packet` and
|
|
77
|
+
`UdpSocket#send_packet(packet, to:, port:)` /
|
|
78
|
+
`#receive_packet` — structured framing on top of the existing
|
|
79
|
+
raw byte send/receive.
|
|
80
|
+
|
|
81
|
+
### Added — window
|
|
82
|
+
|
|
83
|
+
- `Keyboard::SCAN_CODES` — full layout-independent scancode table
|
|
84
|
+
(146 entries matching `sfScancode`).
|
|
85
|
+
- `Keyboard.scancode_pressed?(:scan_w)` — query the physical key
|
|
86
|
+
regardless of keyboard layout (the standard for WASD-style games).
|
|
87
|
+
- `Keyboard.localize(scancode)` / `.delocalize(key)` /
|
|
88
|
+
`.description(scancode)` — convert between physical scancodes
|
|
89
|
+
and logical keys under the current OS layout, plus the
|
|
90
|
+
human-readable description string.
|
|
91
|
+
- `Keyboard.virtual_keyboard_visible=` — on-screen keyboard toggle
|
|
92
|
+
for touchscreen / mobile builds (no-op on desktop).
|
|
93
|
+
- `VideoMode.fullscreen_modes` — all video modes the display
|
|
94
|
+
supports for true-fullscreen window creation, sorted from most
|
|
95
|
+
to least pixels.
|
|
96
|
+
- `VideoMode#valid?` — does the display actually support this mode
|
|
97
|
+
at fullscreen?
|
|
98
|
+
- `SFML::Context` — headless GL context. Activate it on a thread
|
|
99
|
+
to compile shaders / make raw GL calls without a window. Static
|
|
100
|
+
`Context.active_context_id`, `.extension_available?(name)`,
|
|
101
|
+
`.gl_function(name)`.
|
|
102
|
+
|
|
103
|
+
### Added — system
|
|
104
|
+
|
|
105
|
+
- `SFML::InputStream(io)` — wraps a Ruby IO-like object (anything
|
|
106
|
+
answering `read` / `seek` / `pos` / `size`) as the
|
|
107
|
+
`sfInputStream*` argument CSFML loader functions take. Used
|
|
108
|
+
internally by every `*.from_stream` factory.
|
|
109
|
+
|
|
11
110
|
## [3.0.0.4] — 2026-05-09
|
|
12
111
|
|
|
13
112
|
### Added — graphics
|
data/lib/sfml/audio/music.rb
CHANGED
|
@@ -29,6 +29,20 @@ module SFML
|
|
|
29
29
|
m
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
# Stream music straight from a Ruby IO-like object. CSFML reads
|
|
33
|
+
# the audio lazily on its decoding thread — keep the IO open
|
|
34
|
+
# until you stop the Music.
|
|
35
|
+
def self.from_stream(io, **opts)
|
|
36
|
+
stream = SFML::InputStream.new(io)
|
|
37
|
+
ptr = C::Audio.sfMusic_createFromStream(stream.to_ptr)
|
|
38
|
+
raise Error, "sfMusic_createFromStream returned NULL — unsupported format?" if ptr.null?
|
|
39
|
+
|
|
40
|
+
m = _wrap(ptr, opts)
|
|
41
|
+
m.instance_variable_set(:@_stream_pin, stream)
|
|
42
|
+
m.instance_variable_set(:@_io_pin, io)
|
|
43
|
+
m
|
|
44
|
+
end
|
|
45
|
+
|
|
32
46
|
# Internal — finish initialising a Music from an already-built
|
|
33
47
|
# CSFML pointer.
|
|
34
48
|
def self._wrap(ptr, opts)
|
|
@@ -29,6 +29,19 @@ module SFML
|
|
|
29
29
|
buf
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
# Load fully-decoded audio from any Ruby IO-like object. The
|
|
33
|
+
# whole stream is decoded into RAM — for streaming playback,
|
|
34
|
+
# use `Music.from_stream` instead.
|
|
35
|
+
def self.from_stream(io)
|
|
36
|
+
stream = SFML::InputStream.new(io)
|
|
37
|
+
ptr = C::Audio.sfSoundBuffer_createFromStream(stream.to_ptr)
|
|
38
|
+
raise Error, "sfSoundBuffer_createFromStream returned NULL — unsupported format?" if ptr.null?
|
|
39
|
+
|
|
40
|
+
buf = allocate
|
|
41
|
+
buf.send(:_take_ownership, ptr)
|
|
42
|
+
buf
|
|
43
|
+
end
|
|
44
|
+
|
|
32
45
|
# Default channel-layout map for the common 1- and 2-channel
|
|
33
46
|
# cases — saves callers from spelling out the SoundChannel
|
|
34
47
|
# enum just to build a mono blip or stereo waveform.
|
|
@@ -1,30 +1,143 @@
|
|
|
1
1
|
module SFML
|
|
2
|
-
#
|
|
3
|
-
#
|
|
2
|
+
# Callback-based audio-capture base class. Subclass and override
|
|
3
|
+
# `#on_start` (initialise capture state, return `true` to begin),
|
|
4
|
+
# `#on_process_samples(samples, channels)` (called every audio chunk
|
|
5
|
+
# with an Array<Integer> of interleaved int16 PCM, return `true` to
|
|
6
|
+
# keep recording or `false` to stop), and `#on_stop` (release any
|
|
7
|
+
# resources).
|
|
4
8
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
# The simpler "record to a SoundBuffer" path lives in
|
|
10
|
+
# SFML::SoundBufferRecorder — reach for SoundRecorder only when you
|
|
11
|
+
# need to stream samples somewhere else (file, socket, DSP pipeline).
|
|
12
|
+
#
|
|
13
|
+
# class LevelMeter < SFML::SoundRecorder
|
|
14
|
+
# def on_start
|
|
15
|
+
# @peak = 0
|
|
16
|
+
# true
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# def on_process_samples(samples, _channels)
|
|
20
|
+
# @peak = [@peak, *samples.map(&:abs)].max
|
|
21
|
+
# true
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# def on_stop
|
|
25
|
+
# puts "Peak: #{@peak}"
|
|
26
|
+
# end
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
29
|
+
# meter = LevelMeter.new
|
|
30
|
+
# meter.start(sample_rate: 44_100)
|
|
31
|
+
# sleep 2
|
|
32
|
+
# meter.stop
|
|
33
|
+
#
|
|
34
|
+
# CAVEATS
|
|
35
|
+
# * All three callbacks run on CSFML's audio thread; heavy Ruby work
|
|
36
|
+
# on the audio thread will glitch the capture.
|
|
37
|
+
# * Always keep a reference to the SoundRecorder object — if the Ruby
|
|
38
|
+
# object is GC'd while CSFML is mid-capture, the process crashes.
|
|
39
|
+
class SoundRecorder
|
|
40
|
+
# ---- Static helpers (work without a recorder instance) ------------
|
|
41
|
+
|
|
42
|
+
def self.available?
|
|
13
43
|
C::Audio.sfSoundRecorder_isAvailable
|
|
14
44
|
end
|
|
15
45
|
|
|
16
|
-
def default_device
|
|
46
|
+
def self.default_device
|
|
17
47
|
C::Audio.sfSoundRecorder_getDefaultDevice
|
|
18
48
|
end
|
|
19
49
|
|
|
20
50
|
# All input devices the OS exposes to SFML, as an Array of String
|
|
21
|
-
# names. Pass any of them to
|
|
22
|
-
|
|
51
|
+
# names. Pass any of them to SoundRecorder#device= or
|
|
52
|
+
# SoundBufferRecorder#device= to switch.
|
|
53
|
+
def self.devices
|
|
23
54
|
count_buf = FFI::MemoryPointer.new(:size_t)
|
|
24
55
|
array_ptr = C::Audio.sfSoundRecorder_getAvailableDevices(count_buf)
|
|
25
56
|
n = count_buf.read(:size_t)
|
|
26
57
|
return [] if array_ptr.null? || n.zero?
|
|
27
58
|
array_ptr.read_array_of_pointer(n).map { |p| p.read_string }
|
|
28
59
|
end
|
|
60
|
+
|
|
61
|
+
# ---- Instance API -------------------------------------------------
|
|
62
|
+
|
|
63
|
+
def initialize
|
|
64
|
+
# Strong refs so the GC doesn't disappear callbacks under CSFML.
|
|
65
|
+
@start_cb = FFI::Function.new(:bool, [:pointer]) do |_user|
|
|
66
|
+
on_start ? true : false
|
|
67
|
+
end
|
|
68
|
+
@process_cb = FFI::Function.new(:bool, [:pointer, :size_t, :pointer]) do |samples_ptr, count, _user|
|
|
69
|
+
samples = count.zero? ? [] : samples_ptr.read_array_of_int16(count)
|
|
70
|
+
on_process_samples(samples, channel_count) ? true : false
|
|
71
|
+
end
|
|
72
|
+
@stop_cb = FFI::Function.new(:void, [:pointer]) do |_user|
|
|
73
|
+
on_stop
|
|
74
|
+
nil
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
ptr = C::Audio.sfSoundRecorder_create(@start_cb, @process_cb, @stop_cb, nil)
|
|
78
|
+
raise Error, "sfSoundRecorder_create returned NULL" if ptr.null?
|
|
79
|
+
|
|
80
|
+
@handle = FFI::AutoPointer.new(ptr, C::Audio.method(:sfSoundRecorder_destroy))
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# ---- Subclass hooks ----
|
|
84
|
+
|
|
85
|
+
# Called once before the capture starts. Return `true` to begin
|
|
86
|
+
# the capture or `false` to abort. Default does nothing and
|
|
87
|
+
# accepts the start.
|
|
88
|
+
def on_start
|
|
89
|
+
true
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Called with each chunk of captured audio. `samples` is an
|
|
93
|
+
# Array<Integer> of interleaved int16 PCM (length = frames *
|
|
94
|
+
# channels). Return `true` to keep capturing or `false` to stop.
|
|
95
|
+
# Default raises so subclasses must implement it.
|
|
96
|
+
def on_process_samples(_samples, _channels)
|
|
97
|
+
raise NoMethodError, "#{self.class} must override #on_process_samples"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Called once after the capture is done. Default is a no-op.
|
|
101
|
+
def on_stop; end
|
|
102
|
+
|
|
103
|
+
# ---- Public recorder API ----
|
|
104
|
+
|
|
105
|
+
def start(sample_rate: 44_100)
|
|
106
|
+
C::Audio.sfSoundRecorder_start(@handle, Integer(sample_rate)) ||
|
|
107
|
+
raise(Error, "sfSoundRecorder_start failed (no input device or driver error)")
|
|
108
|
+
self
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def stop
|
|
112
|
+
C::Audio.sfSoundRecorder_stop(@handle)
|
|
113
|
+
self
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def sample_rate = C::Audio.sfSoundRecorder_getSampleRate(@handle)
|
|
117
|
+
def channel_count = C::Audio.sfSoundRecorder_getChannelCount(@handle)
|
|
118
|
+
|
|
119
|
+
def channel_count=(n)
|
|
120
|
+
C::Audio.sfSoundRecorder_setChannelCount(@handle, Integer(n))
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def device = C::Audio.sfSoundRecorder_getDevice(@handle)
|
|
124
|
+
|
|
125
|
+
def device=(name)
|
|
126
|
+
C::Audio.sfSoundRecorder_setDevice(@handle, name.to_s) ||
|
|
127
|
+
raise(Error, "sfSoundRecorder_setDevice failed for #{name.inspect}")
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# The channel layout the recorder is producing, as an Array of
|
|
131
|
+
# `sfSoundChannel` enum values (1 = Mono, 2 = FrontLeft,
|
|
132
|
+
# 3 = FrontRight, etc — see SoundBuffer::DEFAULT_CHANNEL_MAPS).
|
|
133
|
+
def channel_map
|
|
134
|
+
count_buf = FFI::MemoryPointer.new(:size_t)
|
|
135
|
+
ptr = C::Audio.sfSoundRecorder_getChannelMap(@handle, count_buf)
|
|
136
|
+
n = count_buf.read(:size_t)
|
|
137
|
+
return [] if ptr.null? || n.zero?
|
|
138
|
+
ptr.read_array_of_int32(n)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
attr_reader :handle # :nodoc:
|
|
29
142
|
end
|
|
30
143
|
end
|
|
@@ -169,6 +169,109 @@ module SFML
|
|
|
169
169
|
C::Audio.sfSoundStream_setRelativeToListener(@handle, !!value)
|
|
170
170
|
end
|
|
171
171
|
|
|
172
|
+
# ---- 3D-audio surface (mirror of Sound / Music) -------------------
|
|
173
|
+
|
|
174
|
+
def pan = C::Audio.sfSoundStream_getPan(@handle)
|
|
175
|
+
|
|
176
|
+
def pan=(value)
|
|
177
|
+
C::Audio.sfSoundStream_setPan(@handle, value.to_f)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def max_distance = C::Audio.sfSoundStream_getMaxDistance(@handle)
|
|
181
|
+
|
|
182
|
+
def max_distance=(value)
|
|
183
|
+
C::Audio.sfSoundStream_setMaxDistance(@handle, value.to_f)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def min_gain = C::Audio.sfSoundStream_getMinGain(@handle)
|
|
187
|
+
|
|
188
|
+
def min_gain=(value)
|
|
189
|
+
C::Audio.sfSoundStream_setMinGain(@handle, value.to_f)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def max_gain = C::Audio.sfSoundStream_getMaxGain(@handle)
|
|
193
|
+
|
|
194
|
+
def max_gain=(value)
|
|
195
|
+
C::Audio.sfSoundStream_setMaxGain(@handle, value.to_f)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def spatialization_enabled? = C::Audio.sfSoundStream_isSpatializationEnabled(@handle)
|
|
199
|
+
|
|
200
|
+
def spatialization_enabled=(value)
|
|
201
|
+
C::Audio.sfSoundStream_setSpatializationEnabled(@handle, !!value)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def direction
|
|
205
|
+
v = C::Audio.sfSoundStream_getDirection(@handle)
|
|
206
|
+
Vector3.new(v[:x], v[:y], v[:z])
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def direction=(value)
|
|
210
|
+
vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
|
|
211
|
+
packed = C::System::Vector3f.new
|
|
212
|
+
packed[:x] = vec.x.to_f; packed[:y] = vec.y.to_f; packed[:z] = vec.z.to_f
|
|
213
|
+
C::Audio.sfSoundStream_setDirection(@handle, packed)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def cone
|
|
217
|
+
SoundCone.from_native(C::Audio.sfSoundStream_getCone(@handle))
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def cone=(value)
|
|
221
|
+
cone =
|
|
222
|
+
case value
|
|
223
|
+
when SoundCone then value
|
|
224
|
+
when Hash then SoundCone.new(**value)
|
|
225
|
+
else
|
|
226
|
+
raise ArgumentError, "SoundStream#cone= expects SoundCone or Hash; got #{value.class}"
|
|
227
|
+
end
|
|
228
|
+
C::Audio.sfSoundStream_setCone(@handle, cone.to_native)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def velocity
|
|
232
|
+
v = C::Audio.sfSoundStream_getVelocity(@handle)
|
|
233
|
+
Vector3.new(v[:x], v[:y], v[:z])
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def velocity=(value)
|
|
237
|
+
vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
|
|
238
|
+
packed = C::System::Vector3f.new
|
|
239
|
+
packed[:x] = vec.x.to_f; packed[:y] = vec.y.to_f; packed[:z] = vec.z.to_f
|
|
240
|
+
C::Audio.sfSoundStream_setVelocity(@handle, packed)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def doppler_factor = C::Audio.sfSoundStream_getDopplerFactor(@handle)
|
|
244
|
+
|
|
245
|
+
def doppler_factor=(value)
|
|
246
|
+
C::Audio.sfSoundStream_setDopplerFactor(@handle, value.to_f)
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def directional_attenuation_factor
|
|
250
|
+
C::Audio.sfSoundStream_getDirectionalAttenuationFactor(@handle)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def directional_attenuation_factor=(value)
|
|
254
|
+
C::Audio.sfSoundStream_setDirectionalAttenuationFactor(@handle, value.to_f)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# Install a real-time DSP filter (same contract as Sound /
|
|
258
|
+
# Music — see Sound#effect_processor=). Pass `nil` to remove.
|
|
259
|
+
def effect_processor=(callable)
|
|
260
|
+
@effect_cb = callable.nil? ? nil : Audio._build_effect_processor(callable)
|
|
261
|
+
C::Audio.sfSoundStream_setEffectProcessor(@handle, @effect_cb, nil)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# The channel layout the stream is producing, as an Array of
|
|
265
|
+
# `sfSoundChannel` enum values (1 = Mono, 2 = FrontLeft,
|
|
266
|
+
# 3 = FrontRight, etc — see SoundBuffer::DEFAULT_CHANNEL_MAPS).
|
|
267
|
+
def channel_map
|
|
268
|
+
count_buf = FFI::MemoryPointer.new(:size_t)
|
|
269
|
+
ptr = C::Audio.sfSoundStream_getChannelMap(@handle, count_buf)
|
|
270
|
+
n = count_buf.read(:size_t)
|
|
271
|
+
return [] if ptr.null? || n.zero?
|
|
272
|
+
ptr.read_array_of_int32(n)
|
|
273
|
+
end
|
|
274
|
+
|
|
172
275
|
attr_reader :handle # :nodoc:
|
|
173
276
|
|
|
174
277
|
private
|
data/lib/sfml/c/audio.rb
CHANGED
|
@@ -28,6 +28,7 @@ module SFML
|
|
|
28
28
|
attach_function :sfSoundBuffer_getChannelCount,[:sound_buffer_t], :uint32
|
|
29
29
|
attach_function :sfSoundBuffer_copy, [:sound_buffer_t], :sound_buffer_t
|
|
30
30
|
attach_function :sfSoundBuffer_createFromMemory, [:pointer, :size_t], :sound_buffer_t
|
|
31
|
+
attach_function :sfSoundBuffer_createFromStream, [:pointer], :sound_buffer_t
|
|
31
32
|
attach_function :sfSoundBuffer_createFromSamples,
|
|
32
33
|
[:pointer, :uint64, :uint32, :uint32, :pointer, :size_t], :sound_buffer_t
|
|
33
34
|
attach_function :sfSoundBuffer_getSampleCount, [:sound_buffer_t], :uint64
|
|
@@ -94,6 +95,7 @@ module SFML
|
|
|
94
95
|
|
|
95
96
|
attach_function :sfMusic_createFromFile, [:string], :music_t
|
|
96
97
|
attach_function :sfMusic_createFromMemory, [:pointer, :size_t], :music_t
|
|
98
|
+
attach_function :sfMusic_createFromStream, [:pointer], :music_t
|
|
97
99
|
attach_function :sfMusic_destroy, [:music_t], :void
|
|
98
100
|
attach_function :sfMusic_getChannelCount, [:music_t], :uint32
|
|
99
101
|
attach_function :sfMusic_getSampleRate, [:music_t], :uint32
|
|
@@ -187,6 +189,30 @@ module SFML
|
|
|
187
189
|
attach_function :sfSoundStream_setRelativeToListener, [:sound_stream_t, :bool], :void
|
|
188
190
|
attach_function :sfSoundStream_isRelativeToListener, [:sound_stream_t], :bool
|
|
189
191
|
|
|
192
|
+
# 3D-audio surface — symmetric with sfSound / sfMusic.
|
|
193
|
+
attach_function :sfSoundStream_setPan, [:sound_stream_t, :float], :void
|
|
194
|
+
attach_function :sfSoundStream_getPan, [:sound_stream_t], :float
|
|
195
|
+
attach_function :sfSoundStream_setMaxDistance, [:sound_stream_t, :float], :void
|
|
196
|
+
attach_function :sfSoundStream_getMaxDistance, [:sound_stream_t], :float
|
|
197
|
+
attach_function :sfSoundStream_setMinGain, [:sound_stream_t, :float], :void
|
|
198
|
+
attach_function :sfSoundStream_getMinGain, [:sound_stream_t], :float
|
|
199
|
+
attach_function :sfSoundStream_setMaxGain, [:sound_stream_t, :float], :void
|
|
200
|
+
attach_function :sfSoundStream_getMaxGain, [:sound_stream_t], :float
|
|
201
|
+
attach_function :sfSoundStream_setSpatializationEnabled, [:sound_stream_t, :bool], :void
|
|
202
|
+
attach_function :sfSoundStream_isSpatializationEnabled, [:sound_stream_t], :bool
|
|
203
|
+
attach_function :sfSoundStream_setDirection, [:sound_stream_t, System::Vector3f.by_value], :void
|
|
204
|
+
attach_function :sfSoundStream_getDirection, [:sound_stream_t], System::Vector3f.by_value
|
|
205
|
+
attach_function :sfSoundStream_setCone, [:sound_stream_t, SoundSourceCone.by_value], :void
|
|
206
|
+
attach_function :sfSoundStream_getCone, [:sound_stream_t], SoundSourceCone.by_value
|
|
207
|
+
attach_function :sfSoundStream_setVelocity, [:sound_stream_t, System::Vector3f.by_value], :void
|
|
208
|
+
attach_function :sfSoundStream_getVelocity, [:sound_stream_t], System::Vector3f.by_value
|
|
209
|
+
attach_function :sfSoundStream_setDopplerFactor, [:sound_stream_t, :float], :void
|
|
210
|
+
attach_function :sfSoundStream_getDopplerFactor, [:sound_stream_t], :float
|
|
211
|
+
attach_function :sfSoundStream_setDirectionalAttenuationFactor, [:sound_stream_t, :float], :void
|
|
212
|
+
attach_function :sfSoundStream_getDirectionalAttenuationFactor, [:sound_stream_t], :float
|
|
213
|
+
attach_function :sfSoundStream_setEffectProcessor, [:sound_stream_t, :sf_effect_processor, :pointer], :void
|
|
214
|
+
attach_function :sfSoundStream_getChannelMap, [:sound_stream_t, :pointer], :pointer
|
|
215
|
+
|
|
190
216
|
# ---- SoundBufferRecorder ----
|
|
191
217
|
# The simple "record into a SoundBuffer" path. Raw sfSoundRecorder
|
|
192
218
|
# (callback-based) and sfSoundStream (custom audio source via
|
|
@@ -210,6 +236,27 @@ module SFML
|
|
|
210
236
|
attach_function :sfSoundRecorder_getDefaultDevice, [], :string
|
|
211
237
|
attach_function :sfSoundRecorder_getAvailableDevices, [:pointer], :pointer
|
|
212
238
|
|
|
239
|
+
# Callback-based recorder. The three callbacks run on CSFML's
|
|
240
|
+
# audio thread; the Ruby SoundRecorder must hold strong refs to
|
|
241
|
+
# the FFI::Function objects for the lifetime of the recorder.
|
|
242
|
+
typedef :pointer, :sound_recorder_t
|
|
243
|
+
callback :sound_recorder_start, [:pointer], :bool
|
|
244
|
+
callback :sound_recorder_process, [:pointer, :size_t, :pointer], :bool
|
|
245
|
+
callback :sound_recorder_stop, [:pointer], :void
|
|
246
|
+
|
|
247
|
+
attach_function :sfSoundRecorder_create,
|
|
248
|
+
[:sound_recorder_start, :sound_recorder_process, :sound_recorder_stop, :pointer],
|
|
249
|
+
:sound_recorder_t
|
|
250
|
+
attach_function :sfSoundRecorder_destroy, [:sound_recorder_t], :void
|
|
251
|
+
attach_function :sfSoundRecorder_start, [:sound_recorder_t, :uint32], :bool
|
|
252
|
+
attach_function :sfSoundRecorder_stop, [:sound_recorder_t], :void
|
|
253
|
+
attach_function :sfSoundRecorder_getSampleRate, [:sound_recorder_t], :uint32
|
|
254
|
+
attach_function :sfSoundRecorder_setDevice, [:sound_recorder_t, :string], :bool
|
|
255
|
+
attach_function :sfSoundRecorder_getDevice, [:sound_recorder_t], :string
|
|
256
|
+
attach_function :sfSoundRecorder_setChannelCount, [:sound_recorder_t, :uint32], :void
|
|
257
|
+
attach_function :sfSoundRecorder_getChannelCount, [:sound_recorder_t], :uint32
|
|
258
|
+
attach_function :sfSoundRecorder_getChannelMap, [:sound_recorder_t, :pointer], :pointer
|
|
259
|
+
|
|
213
260
|
# ---- Listener (the "ear" — global, no handle) ----
|
|
214
261
|
attach_function :sfListener_setGlobalVolume, [:float], :void
|
|
215
262
|
attach_function :sfListener_getGlobalVolume, [], :float
|