Class: RGame::Core::Audio
- Inherits:
-
Object
- Object
- RGame::Core::Audio
- Defined in:
- lib/rgame/core/audio.rb,
ext/rgame_core/ruby/audio_ext.c
Overview
The sound device: one per game, and the thing samples and songs are made from.
audio = RGame::Core::Audio.new
audio.volume = 0.8
It is not tied to a window. Sound outlives a resized or recreated window
and has nothing to do with a GL context, so nothing here takes an app.
A machine with no sound hardware still gets a working Audio — it opens a
null device and plays silently. That is deliberate: a game should run on a
server, in a container, or on a laptop with the sound card disabled, and
the alternative is a crash at startup for something nobody asked for.
#backend says which one was chosen.
Class Method Summary collapse
Instance Method Summary collapse
- #backend ⇒ Object
- #initialize ⇒ Object constructor
- #inspect ⇒ Object
-
#play_music(id) ⇒ Object
Starts a registered song looping, and does nothing if it is already playing — so a scene that re-emits the same request every time it is entered never restarts the music mid-loop.
-
#play_sound(id) ⇒ Object
Plays a registered sample.
- #register_music(id, song) ⇒ Object
-
#register_sound(id, sample) ⇒ Object
--- play-by-id -----------------------------------------------------.
-
#sample(path) ⇒ Object
Loads a short sound to play over itself.
-
#song(path) ⇒ Object
Loads a long one to stream.
-
#stop_music ⇒ Object
Stops the song this registry started.
- #volume ⇒ Object
- #volume=(volume) ⇒ Object
Constructor Details
#initialize ⇒ Object
63 64 65 66 67 68 69 70 71 72 |
# File 'ext/rgame_core/ruby/audio_ext.c', line 63
static VALUE audio_initialize(VALUE self) {
char error[256] = {0};
rgame_audio *audio = rgame_audio_create(error, sizeof(error));
if (!audio) {
rb_raise(rb_eRuntimeError, "%s", error);
}
RTYPEDDATA_DATA(self) = audio;
return self;
}
|
Class Method Details
.debug_live_sounds ⇒ Object
107 108 109 110 |
# File 'ext/rgame_core/ruby/audio_ext.c', line 107
static VALUE audio_s_debug_live_sounds(VALUE klass) {
(void)klass;
return LONG2NUM(rgame_audio_live_sounds());
}
|
Instance Method Details
#backend ⇒ Object
86 87 88 |
# File 'ext/rgame_core/ruby/audio_ext.c', line 86 static VALUE audio_backend(VALUE self) { return rb_str_new_cstr(rgame_audio_backend(audio_unwrap(self))); } |
#inspect ⇒ Object
90 91 92 93 94 95 96 97 98 |
# File 'ext/rgame_core/ruby/audio_ext.c', line 90
static VALUE audio_inspect(VALUE self) {
rgame_audio *audio;
TypedData_Get_Struct(self, rgame_audio, &audio_data_type, audio);
if (!audio) {
return rb_sprintf("#<%" PRIsVALUE " (uninitialized)>", rb_obj_class(self));
}
return rb_sprintf("#<%" PRIsVALUE " %s>", rb_obj_class(self),
rgame_audio_backend(audio));
}
|
#play_music(id) ⇒ Object
Starts a registered song looping, and does nothing if it is already playing — so a scene that re-emits the same request every time it is entered never restarts the music mid-loop.
61 62 63 64 65 66 67 |
# File 'lib/rgame/core/audio.rb', line 61 def play_music(id) song = songs.fetch(id) return song if song. @playing_song = song song.play(looping: true) end |
#play_sound(id) ⇒ Object
Plays a registered sample. Each call is another voice, layered over the ones already sounding.
54 55 56 |
# File 'lib/rgame/core/audio.rb', line 54 def play_sound(id) samples.fetch(id).play end |
#register_music(id, song) ⇒ Object
47 48 49 50 |
# File 'lib/rgame/core/audio.rb', line 47 def register_music(id, song) songs[id] = song self end |
#register_sound(id, sample) ⇒ Object
--- play-by-id -----------------------------------------------------
The same boundary the renderer's draw-by-id serves: game logic emits
facts — "the ship was hit" — and names the sound, because a scene may
not hold a Sample. Registration only, unlike the renderer: a sound id
is whatever a game wants to call it, and there is no per-frame path to
make resolving one worth caching.
audio.register_sound(:hit, app.assets.sound('example 09/hurt.ogg'))
audio.play_sound(:hit)
42 43 44 45 |
# File 'lib/rgame/core/audio.rb', line 42 def register_sound(id, sample) samples[id] = sample self end |
#sample(path) ⇒ Object
Loads a short sound to play over itself. The same thing as
Sample.new(audio, path), and the form to prefer: it reads in the
direction the objects depend, and it is the form a stand-in device can
implement, which Sample.new is not.
26 |
# File 'lib/rgame/core/audio.rb', line 26 def sample(path) = Sample.new(self, path) |
#song(path) ⇒ Object
Loads a long one to stream. See Song.
29 |
# File 'lib/rgame/core/audio.rb', line 29 def song(path) = Song.new(self, path) |
#stop_music ⇒ Object
Stops the song this registry started.
Deliberately not "stop whatever is playing": the layer being replaced
reached for a process-wide current_song, and there is no such global
here by the decision that one-song-at-a-time is a game's policy rather
than the engine's. A Song a game started by hand is its own to stop.
75 76 77 78 |
# File 'lib/rgame/core/audio.rb', line 75 def stop_music @playing_song&.stop @playing_song = nil end |
#volume ⇒ Object
74 75 76 |
# File 'ext/rgame_core/ruby/audio_ext.c', line 74
static VALUE audio_volume(VALUE self) {
return DBL2NUM((double)rgame_audio_volume(audio_unwrap(self)));
}
|
#volume=(volume) ⇒ Object
78 79 80 81 |
# File 'ext/rgame_core/ruby/audio_ext.c', line 78
static VALUE audio_set_volume(VALUE self, VALUE volume) {
rgame_audio_set_volume(audio_unwrap(self), (float)NUM2DBL(volume));
return volume;
}
|