Class: SFML::Music

Inherits:
Object
  • Object
show all
Defined in:
lib/sfml/audio/music.rb

Overview

A streamed audio source. Use this for long tracks (background music) so the file isn't loaded into memory all at once.

bgm = SFML::Music.load("assets/track.ogg", looping: true, volume: 60)
bgm.play

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.from_memory(bytes, **opts) ⇒ Object

Stream music from a Ruby String of bytes (an in-memory MP3, OGG, FLAC, …). Useful for embedded audio or downloaded tracks that bypass the disk. The bytes must outlive the Music object — SFML keeps a pointer into them.

Raises:

  • (ArgumentError)


22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/sfml/audio/music.rb', line 22

def self.from_memory(bytes, **opts)
  raise ArgumentError, "expected a String, got #{bytes.class}" unless bytes.is_a?(String)

  buf = FFI::MemoryPointer.new(:uint8, bytes.bytesize)
  buf.write_bytes(bytes)
  ptr = C::Audio.sfMusic_createFromMemory(buf, bytes.bytesize)
  raise LoadError, "sfMusic_createFromMemory returned NULL — unsupported format?" if ptr.null?

  m = _wrap(ptr, opts)
  m.instance_variable_set(:@_memory_pin, buf)   # keep buffer alive
  m
end

.from_stream(io, **opts) ⇒ Object

Stream music straight from a Ruby IO-like object. CSFML reads the audio lazily on its decoding thread — keep the IO open until you stop the Music.

Raises:



38
39
40
41
42
43
44
45
46
47
# File 'lib/sfml/audio/music.rb', line 38

def self.from_stream(io, **opts)
  stream = SFML::InputStream.new(io)
  ptr = C::Audio.sfMusic_createFromStream(stream.to_ptr)
  raise LoadError, "sfMusic_createFromStream returned NULL — unsupported format?" if ptr.null?

  m = _wrap(ptr, opts)
  m.instance_variable_set(:@_stream_pin, stream)
  m.instance_variable_set(:@_io_pin, io)
  m
end

.load(path, **opts) ⇒ Object

Load a music track from disk. opts may include :volume, :pitch, and :looping — these are applied right after load. Raises SFML::LoadError on missing file or unsupported format.

Raises:



11
12
13
14
15
16
# File 'lib/sfml/audio/music.rb', line 11

def self.load(path, **opts)
  ptr = C::Audio.sfMusic_createFromFile(path.to_s)
  raise LoadError, "Could not load music from #{path.inspect}" if ptr.null?

  _wrap(ptr, opts)
end

Instance Method Details

#attenuation ⇒ Object

Falloff sharpness with distance — see Sound#attenuation.



194
# File 'lib/sfml/audio/music.rb', line 194

def attenuation = C::Audio.sfMusic_getAttenuation(@handle)

#attenuation=(value) ⇒ Object

Set the attenuation.



197
198
199
# File 'lib/sfml/audio/music.rb', line 197

def attenuation=(value)
  C::Audio.sfMusic_setAttenuation(@handle, value.to_f)
end

#channel_count ⇒ Object

Number of audio channels (1 = mono, 2 = stereo, ...).



220
221
# File 'lib/sfml/audio/music.rb', line 220

def channel_count = C::Audio.sfMusic_getChannelCount(@handle)
# Sample rate in Hz (e.g. 44_100 for CD-quality).

#cone ⇒ Object

Directional-attenuation cone — see SFML::SoundCone.



130
131
132
# File 'lib/sfml/audio/music.rb', line 130

def cone
  SoundCone.from_native(C::Audio.sfMusic_getCone(@handle))
end

#cone=(value) ⇒ Object

Set the cone. Accepts a SoundCone or a Hash with inner_angle, outer_angle, outer_gain.



136
137
138
139
140
141
142
143
144
145
# File 'lib/sfml/audio/music.rb', line 136

def cone=(value)
  cone =
    case value
    when SoundCone then value
    when Hash      then SoundCone.new(**value)
    else
      raise ArgumentError, "Music#cone= expects SoundCone or Hash; got #{value.class}"
    end
  C::Audio.sfMusic_setCone(@handle, cone.to_native)
end

#direction ⇒ Object

The direction the music's cone points.



116
117
118
119
# File 'lib/sfml/audio/music.rb', line 116

def direction
  v = C::Audio.sfMusic_getDirection(@handle)
  Vector3.new(v[:x], v[:y], v[:z])
end

#direction=(value) ⇒ Object

Set the direction vector — accepts Vector3 or [x, y, z].



122
123
124
125
126
127
# File 'lib/sfml/audio/music.rb', line 122

def direction=(value)
  vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
  packed = C::System::Vector3f.new
  packed[:x] = vec.x.to_f; packed[:y] = vec.y.to_f; packed[:z] = vec.z.to_f
  C::Audio.sfMusic_setDirection(@handle, packed)
end

#directional_attenuation_factor ⇒ Object

Multiplier on the Listener's directional attenuation cone — see Sound#directional_attenuation_factor.



289
290
291
# File 'lib/sfml/audio/music.rb', line 289

def directional_attenuation_factor
  C::Audio.sfMusic_getDirectionalAttenuationFactor(@handle)
end

#directional_attenuation_factor=(v) ⇒ Object

Set the directional-attenuation factor.



294
295
296
# File 'lib/sfml/audio/music.rb', line 294

def directional_attenuation_factor=(v)
  C::Audio.sfMusic_setDirectionalAttenuationFactor(@handle, v.to_f)
end

#doppler_factor ⇒ Object

Per-source Doppler scale. 1.0 realistic, 0 disables.



111
112
# File 'lib/sfml/audio/music.rb', line 111

def doppler_factor    = C::Audio.sfMusic_getDopplerFactor(@handle)
# Set the per-source Doppler scale.

#doppler_factor=(v) ⇒ Object

Set the per-source Doppler scale.



113
# File 'lib/sfml/audio/music.rb', line 113

def doppler_factor=(v) C::Audio.sfMusic_setDopplerFactor(@handle, v.to_f); end

#duration ⇒ Object

Total length of the track as a SFML::Time.



79
# File 'lib/sfml/audio/music.rb', line 79

def duration = Time.from_native(C::Audio.sfMusic_getDuration(@handle))

#effect_processor=(callable) ⇒ Object

See Sound#effect_processor= — same audio-thread DSP callback.



148
149
150
151
# File 'lib/sfml/audio/music.rb', line 148

def effect_processor=(callable)
  @effect_cb = callable.nil? ? nil : Audio._build_effect_processor(callable)
  C::Audio.sfMusic_setEffectProcessor(@handle, @effect_cb, nil)
end

#loop_points ⇒ Object

The portion of the track that loops when looping = true. Returns [offset, length] of SFML::Times; defaults to the whole track. Set with loop_points = [Time, Time].



227
228
229
230
# File 'lib/sfml/audio/music.rb', line 227

def loop_points
  span = C::Audio.sfMusic_getLoopPoints(@handle)
  [Time.from_native(span[:offset]), Time.from_native(span[:length])]
end

#loop_points=(value) ⇒ Object

Set the looping window. Accepts [offset, length] of either SFML::Time or numeric seconds.

Raises:

  • (ArgumentError)


234
235
236
237
238
239
240
241
242
# File 'lib/sfml/audio/music.rb', line 234

def loop_points=(value)
  offset_t, length_t = value
  raise ArgumentError, "expected [offset_time, length_time]" unless offset_t && length_t

  span = C::Audio::TimeSpan.new
  span[:offset][:microseconds] = offset_t.is_a?(Time) ? offset_t.microseconds : Time.seconds(offset_t.to_f).microseconds
  span[:length][:microseconds] = length_t.is_a?(Time) ? length_t.microseconds : Time.seconds(length_t.to_f).microseconds
  C::Audio.sfMusic_setLoopPoints(@handle, span)
end

#looping=(value) ⇒ Object

Toggle looping playback.



161
162
163
164
# File 'lib/sfml/audio/music.rb', line 161

def looping=(value)
  @looping = value ? true : false
  C::Audio.sfMusic_setLooping(@handle, @looping)
end

#looping? ⇒ Boolean

true if the track restarts after reaching the end (or its loop_points length). Cached on the Ruby side; see Sound#looping? for the why.



156
157
158
# File 'lib/sfml/audio/music.rb', line 156

def looping?
  @looping
end

#max_distance ⇒ Object

Distance beyond which the source is fully attenuated.



271
# File 'lib/sfml/audio/music.rb', line 271

def max_distance = C::Audio.sfMusic_getMaxDistance(@handle)

#max_distance=(v) ⇒ Object

Set the max-distance.



274
275
276
# File 'lib/sfml/audio/music.rb', line 274

def max_distance=(v)
  C::Audio.sfMusic_setMaxDistance(@handle, v.to_f)
end

#max_gain ⇒ Object

Upper gain bound — see Sound#max_gain.



263
# File 'lib/sfml/audio/music.rb', line 263

def max_gain = C::Audio.sfMusic_getMaxGain(@handle)

#max_gain=(v) ⇒ Object

Set the max-gain cap.



266
267
268
# File 'lib/sfml/audio/music.rb', line 266

def max_gain=(v)
  C::Audio.sfMusic_setMaxGain(@handle, v.to_f)
end

#min_distance ⇒ Object

Distance below which volume is not attenuated.



202
# File 'lib/sfml/audio/music.rb', line 202

def min_distance = C::Audio.sfMusic_getMinDistance(@handle)

#min_distance=(value) ⇒ Object

Set the min-distance.



205
206
207
# File 'lib/sfml/audio/music.rb', line 205

def min_distance=(value)
  C::Audio.sfMusic_setMinDistance(@handle, value.to_f)
end

#min_gain ⇒ Object

Lower gain bound — see Sound#min_gain.



255
# File 'lib/sfml/audio/music.rb', line 255

def min_gain = C::Audio.sfMusic_getMinGain(@handle)

#min_gain=(v) ⇒ Object

Set the min-gain floor.



258
259
260
# File 'lib/sfml/audio/music.rb', line 258

def min_gain=(v)
  C::Audio.sfMusic_setMinGain(@handle, v.to_f)
end

#pan ⇒ Object

Stereo pan in [-1.0, 1.0] — see Sound#pan.



247
# File 'lib/sfml/audio/music.rb', line 247

def pan = C::Audio.sfMusic_getPan(@handle)

#pan=(v) ⇒ Object

Set the stereo pan.



250
251
252
# File 'lib/sfml/audio/music.rb', line 250

def pan=(v)
  C::Audio.sfMusic_setPan(@handle, v.to_f)
end

#pause ⇒ Object

Pause playback — #play resumes from here.



65
66
# File 'lib/sfml/audio/music.rb', line 65

def pause  = C::Audio.sfMusic_pause(@handle)
# Stop playback and rewind to the start.

#paused? ⇒ Boolean

Convenience for status == :paused.



74
75
# File 'lib/sfml/audio/music.rb', line 74

def paused?  = status == :paused
# Convenience for `status == :stopped`.

#pitch ⇒ Object

Pitch multiplier. 1.0 = normal, 2.0 = octave up, 0.5 = octave down.



175
# File 'lib/sfml/audio/music.rb', line 175

def pitch = C::Audio.sfMusic_getPitch(@handle)

#pitch=(value) ⇒ Object

Set the pitch multiplier.



178
179
180
# File 'lib/sfml/audio/music.rb', line 178

def pitch=(value)
  C::Audio.sfMusic_setPitch(@handle, value.to_f)
end

#play ⇒ Object

Start playback (resumes from pause, restarts when stopped).



63
64
# File 'lib/sfml/audio/music.rb', line 63

def play   = C::Audio.sfMusic_play(@handle)
# Pause playback — `#play` resumes from here.

#playing? ⇒ Boolean

Convenience for status == :playing.



72
73
# File 'lib/sfml/audio/music.rb', line 72

def playing? = status == :playing
# Convenience for `status == :paused`.

#playing_offset ⇒ Object

Current playback head as a SFML::Time. Reads from the underlying OpenAL source — only meaningful while the music is playing or paused (not after #stop).



84
85
86
# File 'lib/sfml/audio/music.rb', line 84

def playing_offset
  Time.from_native(C::Audio.sfMusic_getPlayingOffset(@handle))
end

#playing_offset=(value) ⇒ Object

Seek to value (a SFML::Time, or seconds as a Numeric). Works while the music is playing, paused, or stopped.



90
91
92
93
# File 'lib/sfml/audio/music.rb', line 90

def playing_offset=(value)
  t = value.is_a?(Time) ? value : Time.seconds(value.to_f)
  C::Audio.sfMusic_setPlayingOffset(@handle, t.to_native)
end

#position ⇒ Object

3D positional audio — see SFML::Sound for the why.



183
184
185
# File 'lib/sfml/audio/music.rb', line 183

def position
  Vector3.from_native(C::Audio.sfMusic_getPosition(@handle))
end

#position=(value) ⇒ Object

Set the 3D position — accepts Vector3 or [x, y, z].



188
189
190
191
# File 'lib/sfml/audio/music.rb', line 188

def position=(value)
  vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
  C::Audio.sfMusic_setPosition(@handle, vec.to_native_f)
end

#relative_to_listener=(value) ⇒ Object

Toggle listener-relative positioning.



213
214
215
# File 'lib/sfml/audio/music.rb', line 213

def relative_to_listener=(value)
  C::Audio.sfMusic_setRelativeToListener(@handle, value ? true : false)
end

#relative_to_listener? ⇒ Boolean

true if #position is interpreted relative to the listener.



210
# File 'lib/sfml/audio/music.rb', line 210

def relative_to_listener? = C::Audio.sfMusic_isRelativeToListener(@handle)

#sample_rate ⇒ Object

Sample rate in Hz (e.g. 44_100 for CD-quality).



222
# File 'lib/sfml/audio/music.rb', line 222

def sample_rate   = C::Audio.sfMusic_getSampleRate(@handle)

#spatialization_enabled=(v) ⇒ Object

Toggle 3D spatialisation.



283
284
285
# File 'lib/sfml/audio/music.rb', line 283

def spatialization_enabled=(v)
  C::Audio.sfMusic_setSpatializationEnabled(@handle, v ? true : false)
end

#spatialization_enabled? ⇒ Boolean

true if 3D positional / Doppler / cone math is applied at mix time.



280
# File 'lib/sfml/audio/music.rb', line 280

def spatialization_enabled? = C::Audio.sfMusic_isSpatializationEnabled(@handle)

#status ⇒ Object

Playback state — one of :stopped, :paused, :playing.



70
71
# File 'lib/sfml/audio/music.rb', line 70

def status   = C::Audio::STATUSES[C::Audio.sfMusic_getStatus(@handle)]
# Convenience for `status == :playing`.

#stop ⇒ Object

Stop playback and rewind to the start.



67
# File 'lib/sfml/audio/music.rb', line 67

def stop   = C::Audio.sfMusic_stop(@handle)

#stopped? ⇒ Boolean

Convenience for status == :stopped.



76
# File 'lib/sfml/audio/music.rb', line 76

def stopped? = status == :stopped

#velocity ⇒ Object

3D velocity, Doppler factor, direction, cone — see Sound for the same methods on the simpler buffered source.



97
98
99
100
# File 'lib/sfml/audio/music.rb', line 97

def velocity
  v = C::Audio.sfMusic_getVelocity(@handle)
  Vector3.new(v[:x], v[:y], v[:z])
end

#velocity=(value) ⇒ Object

Set the 3D velocity — accepts Vector3 or [x, y, z].



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

def velocity=(value)
  vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
  packed = C::System::Vector3f.new
  packed[:x] = vec.x.to_f; packed[:y] = vec.y.to_f; packed[:z] = vec.z.to_f
  C::Audio.sfMusic_setVelocity(@handle, packed)
end

#volume ⇒ Object

Playback volume in [0, 100] — 100 = unattenuated.



167
# File 'lib/sfml/audio/music.rb', line 167

def volume = C::Audio.sfMusic_getVolume(@handle)

#volume=(value) ⇒ Object

Set the playback volume in [0, 100].



170
171
172
# File 'lib/sfml/audio/music.rb', line 170

def volume=(value)
  C::Audio.sfMusic_setVolume(@handle, value.to_f)
end