Class: FMOD::Sound
Overview
Represents the actual data source of audio, usually an audio file or stream.
Defined Under Namespace
Classes: Format, OpenState, TagCollection
3-D Sound collapse
-
#cone_settings ⇒ ConeSettings
The angles that define the sound projection cone including the volume when outside the cone.
-
#custom_rolloff ⇒ Array<Vector>
Must be used in conjunction with Core::Mode::CUSTOM_ROLLOFF_3D flag to be activated.
-
#max_distance ⇒ Float
Maximum volume distance in “units”.
-
#min_distance ⇒ Float
Minimum volume distance in “units”.
MOD/S3M/XM/IT/MIDI collapse
-
#music_channels ⇒ Integer
readonly
The number of channels inside a MOD/S3M/XM/IT/MIDI file.
-
#music_speed ⇒ Float
The relative speed of MOD/S3M/XM/IT/MIDI music.
Instance Attribute Summary collapse
-
#default_frequency ⇒ Float
The sounds’s default frequency, so when it is played it uses this value without having to specify them later for each channel each time the sound is played.
-
#default_priority ⇒ Integer
The sounds’s default priority, so when it is played it uses this value without having to specify them later for each channel each time the sound is played.
-
#format ⇒ Format
readonly
The format information for the sound.
-
#group ⇒ SoundGroup
The sound’s current SoundGroup.
-
#loop_count ⇒ Integer
Sets a sound, by default, to loop a specified number of times before stopping if its mode is set to Core::Mode::LOOP_NORMAL or Core::Mode::LOOP_BIDI.
-
#mode ⇒ Integer
Sets or alters the mode of a sound.
-
#name ⇒ String
readonly
The name of the sound.
-
#parent ⇒ System
readonly
The parent System object that was used to create this object.
-
#parent_sound ⇒ Sound?
readonly
The parent Sound of this sound, or
nil
if this sound is not a subsound. -
#subsound_count ⇒ Integer
readonly
The number of subsounds stored within a sound.
-
#subsounds ⇒ Array<Sound>
readonly
An array of the this sound’s subsounds.
-
#syncpoint_count ⇒ Object
readonly
Retrieves the number of sync points stored within a sound.
-
#tags ⇒ TagCollection
readonly
Object containing the tags within the Sound.
Attributes inherited from Handle
Reading Sound Data collapse
-
#lock(offset, length) ⇒ Object
Returns a pointer to the beginning of the sample data for a sound.
-
#read_data(size) ⇒ String
Reads data from an opened sound to a buffer, using the FMOD codec created internally, and returns it.
-
#seek_data(pcm) ⇒ void
Seeks a sound for use with data reading.
-
#unlock(ptr1, ptr2) ⇒ void
Releases previous sample data lock from #lock.
3-D Sound collapse
-
#min_max_distance(min, max) ⇒ void
Sets the minimum and maximum audible distance.
-
#set_cone(inside_angle, outside_angle, outside_volume) ⇒ void
Sets the angles that define the sound projection cone including the volume when outside the cone.
MOD/S3M/XM/IT/MIDI collapse
-
#music_volume(channel) ⇒ Float
Retrieves the volume of a MOD/S3M/XM/IT/MIDI music channel volume.
-
#set_music_volume(channel, volume) ⇒ void
Sets the volume of a MOD/S3M/XM/IT/MIDI music channel volume.
Instance Method Summary collapse
-
#add_syncpoint(name, offset, unit = TimeUnit::MS) ⇒ Pointer
Adds a sync point at a specific time within the sound.
-
#delete_syncpoint(sync_point) ⇒ void
Deletes a syncpoint within the sound.
-
#each_subsound ⇒ Object
Enumerates each subsound within this Sound.
-
#length(unit = TimeUnit::MS) ⇒ Integer
Retrieves the length of the sound using the specified time unit.
-
#loop_points(start_unit = TimeUnit::MS, end_unit = TimeUnit::MS) ⇒ Array(Integer, Integer)
Retrieves the loop points for a sound.
-
#open_state ⇒ OpenState
Retrieves the state a sound is in after Core::Mode::NON_BLOCKING has been used to open it, or the state of the streaming buffer.
-
#play(group = nil) ⇒ Channel
Plays a sound object on a particular channel and ChannelGroup.
-
#set_loop(loop_start, loop_end, start_unit = TimeUnit::MS, end_unit = TimeUnit::MS) ⇒ void
Sets the loop points within a sound.
-
#subsound(index) ⇒ Sound?
Retrieves a handle to a Sound object that is contained within the parent sound.
-
#syncpoint(index) ⇒ Pointer
Retrieve a handle to a sync point.
-
#syncpoint_info(syncpoint, time_unit = TimeUnit::MS) ⇒ Array(String, Integer)
Retrieves information on an embedded sync point.
Methods inherited from Handle
#initialize, #int_ptr, #release, #to_s
Constructor Details
This class inherits a constructor from FMOD::Handle
Instance Attribute Details
#cone_settings ⇒ ConeSettings
The angles that define the sound projection cone including the volume when outside the cone.
432 433 434 435 436 |
# File 'lib/fmod/sound.rb', line 432 def cone_settings args = ["\0" * SIZEOF_FLOAT, "\0" * SIZEOF_FLOAT, "\0" * SIZEOF_FLOAT] FMOD.invoke(:Sound_Get3DConeSettings, self, *args) ConeSettings.new(*args.map { |arg| arg.unpack1('f') } ) end |
#custom_rolloff ⇒ Array<Vector>
Must be used in conjunction with Core::Mode::CUSTOM_ROLLOFF_3D flag to be activated.
Points must be sorted by distance! Passing an unsorted list to FMOD will result in an error.
473 474 475 476 477 478 479 480 481 482 |
# File 'lib/fmod/sound.rb', line 473 def custom_rolloff count = "\0" * SIZEOF_INT FMOD.invoke(:Sound_Get3DCustomRolloff, self, nil, count) count = count.unpack1('l') return [] if count.zero? size = SIZEOF_FLOAT * 3 FMOD.invoke(:Sound_Get3DCustomRolloff, self, ptr = int_ptr, nil) buffer = Pointer.new(ptr.unpack1('J'), count * size).to_str (0...count).map { |i| Vector.new(*buffer[i * size, size].unpack('fff')) } end |
#default_frequency ⇒ Float
The sounds’s default frequency, so when it is played it uses this value without having to specify them later for each channel each time the sound is played.
567 568 569 570 571 |
# File 'lib/fmod/sound.rb', line 567 def default_frequency value = "\0" * SIZEOF_FLOAT FMOD.invoke(:Sound_GetDefaults, self, value, nil) value.unpack1('f') end |
#default_priority ⇒ Integer
The sounds’s default priority, so when it is played it uses this value without having to specify them later for each channel each time the sound is played.
587 588 589 590 591 |
# File 'lib/fmod/sound.rb', line 587 def default_priority value = "\0" * SIZEOF_INT FMOD.invoke(:Sound_GetDefaults, self, nil, value) value.unpack1('l') end |
#format ⇒ Format (readonly)
Returns the format information for the sound.
273 274 275 276 277 278 |
# File 'lib/fmod/sound.rb', line 273 def format arg = ["\0" * TYPE_INT, "\0" * TYPE_INT, "\0" * TYPE_INT, "\0" * TYPE_INT] FMOD.invoke(:Sound_GetFormat, self, *arg) arg.map! { |a| a.unpack1('l') } Format.new(*arg) end |
#group ⇒ SoundGroup
Returns the sound’s current FMOD::SoundGroup.
170 171 172 173 |
# File 'lib/fmod/sound.rb', line 170 def group FMOD.invoke(:Sound_GetSoundGroup, self, group = int_ptr) SoundGroup.new(group) end |
#loop_count ⇒ Integer
Sets a sound, by default, to loop a specified number of times before stopping if its mode is set to Core::Mode::LOOP_NORMAL or Core::Mode::LOOP_BIDI.
137 |
# File 'lib/fmod/sound.rb', line 137 integer_reader(:loop_count, :Sound_GetLoopCount) |
#max_distance ⇒ Float
Returns Maximum volume distance in “units”. (Default: 10000.0).
513 514 515 516 517 |
# File 'lib/fmod/sound.rb', line 513 def max_distance max = "\0" * SIZEOF_FLOAT FMOD.invoke(:Sound_Get3DMinMaxDistance, self, nil, max) max.unpack1('f') end |
#min_distance ⇒ Float
Returns Minimum volume distance in “units”. (Default: 1.0).
497 498 499 500 501 |
# File 'lib/fmod/sound.rb', line 497 def min_distance min = "\0" * SIZEOF_FLOAT FMOD.invoke(:Sound_Get3DMinMaxDistance, self, min, nil) min.unpack1('f') end |
#mode ⇒ Integer
Sets or alters the mode of a sound.
When calling this function, note that it will only take effect when the sound is played again with #play. Consider this mode the “default mode” for when the sound plays, not a mode that will suddenly change all currently playing instances of this sound.
Supported flags:
129 |
# File 'lib/fmod/sound.rb', line 129 integer_reader(:mode, :Sound_GetMode) |
#music_channels ⇒ Integer (readonly)
Returns the number of channels inside a MOD/S3M/XM/IT/MIDI file.
698 |
# File 'lib/fmod/sound.rb', line 698 integer_reader(:music_channels, :Sound_GetMusicNumChannels) |
#music_speed ⇒ Float
The relative speed of MOD/S3M/XM/IT/MIDI music.
* *Minimum:* 0.01
* *Maximum:* 100.0
* *Default:* 1.0
0.5 is half speed, 2.0 is double speed, etc.
665 |
# File 'lib/fmod/sound.rb', line 665 float_reader(:music_speed, :Sound_GetMusicSpeed) |
#name ⇒ String (readonly)
Returns the name of the sound.
155 156 157 158 |
# File 'lib/fmod/sound.rb', line 155 def name FMOD.invoke(:Sound_GetName, self, buffer = "\0" * 512, 512) buffer.delete("\0") end |
#parent ⇒ System (readonly)
Returns the parent FMOD::System object that was used to create this object.
184 185 186 187 |
# File 'lib/fmod/sound.rb', line 184 def parent FMOD.invoke(:Sound_GetSystemObject, self, system = int_ptr) System.new(system) end |
#parent_sound ⇒ Sound? (readonly)
Returns the parent FMOD::Sound of this sound, or nil
if this sound is not a subsound.
228 229 230 231 232 |
# File 'lib/fmod/sound.rb', line 228 def parent_sound FMOD.invoke(:Sound_GetSubSoundParent, self, sound = "\0" * int_ptr) address = sound.unpack1('J') address.zero? ? nil : Sound.new(address) end |
#subsound_count ⇒ Integer (readonly)
Returns the number of subsounds stored within a sound.
143 |
# File 'lib/fmod/sound.rb', line 143 integer_reader(:subsound_count, :Sound_GetNumSubSounds) |
#subsounds ⇒ Array<Sound> (readonly)
Returns an array of the this sound’s subsounds.
204 205 206 |
# File 'lib/fmod/sound.rb', line 204 def subsounds (0...subsound_count).map { |i| subsound(i) } end |
#syncpoint_count ⇒ Object (readonly)
Retrieves the number of sync points stored within a sound. These points can be user generated or can come from a wav file with embedded markers.
150 |
# File 'lib/fmod/sound.rb', line 150 integer_reader(:syncpoint_count, :Sound_GetNumSyncPoints) |
#tags ⇒ TagCollection (readonly)
Returns object containing the tags within the FMOD::Sound.
163 164 165 |
# File 'lib/fmod/sound.rb', line 163 def TagCollection.send(:new, self) end |
Instance Method Details
#add_syncpoint(name, offset, unit = TimeUnit::MS) ⇒ Pointer
Adds a sync point at a specific time within the sound. These points can be user generated or can come from a wav file with embedded markers.
254 255 256 257 258 |
# File 'lib/fmod/sound.rb', line 254 def add_syncpoint(name, offset, unit = TimeUnit::MS) sync = int_ptr FMOD.invoke(:Sound_AddSyncPoint, self, offset, unit, name, sync) Pointer.new(sync.unpack1('J')) end |
#delete_syncpoint(sync_point) ⇒ void
This method returns an undefined value.
Deletes a syncpoint within the sound. These points can be user generated or can come from a wav file with embedded markers.
265 266 267 268 |
# File 'lib/fmod/sound.rb', line 265 def delete_syncpoint(sync_point) FMOD.type?(sync_point, Pointer) FMOD.invoke(:Sound_DeleteSyncPoint, self, sync_point) end |
#each_subsound {|sound| ... } ⇒ self #each_subsound ⇒ Enumerator
Enumerates each subsound within this FMOD::Sound.
218 219 220 221 222 |
# File 'lib/fmod/sound.rb', line 218 def each_subsound return to_enum(:each_subsound) unless block_given? (0...subsound_count).each { |i| yield subsound(i) } self end |
#length(unit = TimeUnit::MS) ⇒ Integer
Retrieves the length of the sound using the specified time unit.
603 604 605 606 607 |
# File 'lib/fmod/sound.rb', line 603 def length(unit = TimeUnit::MS) value = "\0" * SIZEOF_INT FMOD.invoke(:Sound_GetLength, self, value, unit) value.unpack1('L') end |
#lock(offset, length) {|ptr1, ptr2| ... } ⇒ self #lock(offset, length) ⇒ Array(Pointer, Pointer)
Returns a pointer to the beginning of the sample data for a sound.
With this function you get access to the RAW audio data, for example 8, 16, 24 or 32-bit PCM data, mono or stereo data. You must take this into consideration when processing the data within the pointer.
317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'lib/fmod/sound.rb', line 317 def lock(offset, length) p1, p2, s1, s2 = int_ptr, int_ptr, "\0" * TYPE_INT, "\0" * TYPE_INT FMOD.invoke(:Sound_Lock, self, offset, length, p1, p2, s1, s2) ptr1 = Pointer.new(p1.unpack1('J'), s1.unpack1('L')) ptr2 = Pointer.new(p2.unpack1('J'), s2.unpack1('L')) if block_given? yield ptr1, ptr2 FMOD.invoke(:Sound_Unlock, self, ptr1, ptr2, ptr1.size, ptr2.size) return self end [ptr1, ptr2] end |
#loop_points(start_unit = TimeUnit::MS, end_unit = TimeUnit::MS) ⇒ Array(Integer, Integer)
Retrieves the loop points for a sound.
620 621 622 623 624 625 |
# File 'lib/fmod/sound.rb', line 620 def loop_points(start_unit = TimeUnit::MS, end_unit = TimeUnit::MS) loop_start, loop_end = "\0" * SIZEOF_INT, "\0" * SIZEOF_INT FMOD.invoke(:Sound_GetLoopPoints, self, loop_start, start_unit, loop_end, end_unit) [loop_start.unpack1('L'), loop_end.unpack1('L')] end |
#min_max_distance(min, max) ⇒ void
This method returns an undefined value.
Sets the minimum and maximum audible distance.
When the listener is in-between the minimum distance and the sound source the volume will be at its maximum. As the listener moves from the minimum distance to the maximum distance the sound will attenuate following the rolloff curve set. When outside the maximum distance the sound will no longer attenuate.
Minimum distance is useful to give the impression that the sound is loud or soft in 3D space. An example of this is a small quiet object, such as a bumblebee, which you could set a small minimum distance such as 0.1. This would cause it to attenuate quickly and disappear when only a few meters away from the listener. Another example is a jumbo jet, which you could set to a minimum distance of 100.0 causing the volume to stay at its loudest until the listener was 100 meters away, then it would be hundreds of meters more before it would fade out.
Maximum distance is effectively obsolete unless you need the sound to stop fading out at a certain point. Do not adjust this from the default if you dont need to. Some people have the confusion that maximum distance is the point the sound will fade out to zero, this is not the case.
554 555 556 |
# File 'lib/fmod/sound.rb', line 554 def min_max_distance(min, max) FMOD.invoke(:Sound_Set3DMinMaxDistance, self, min, max) end |
#music_volume(channel) ⇒ Float
Retrieves the volume of a MOD/S3M/XM/IT/MIDI music channel volume.
675 676 677 678 679 |
# File 'lib/fmod/sound.rb', line 675 def music_volume(channel) volume = "\0" * SIZEOF_FLOAT FMOD.invoke(:Sound_GetMusicChannelVolume, self, channel, volume) volume.unpack1('f') end |
#open_state ⇒ OpenState
Retrieves the state a sound is in after Core::Mode::NON_BLOCKING has been used to open it, or the state of the streaming buffer.
707 708 709 710 711 712 |
# File 'lib/fmod/sound.rb', line 707 def open_state args = ["\0" * SIZEOF_INT, "\0" * SIZEOF_INT, "\0" * SIZEOF_INT, "\0" * SIZEOF_INT] FMOD.invoke(:Sound_GetOpenState, self, *args) args = args.join.unpack('lLll') OpenState.send(:new, *args) end |
#play(group = nil) ⇒ Channel
Plays a sound object on a particular channel and ChannelGroup.
When a sound is played, it will use the sound’s default frequency and priority.
A sound defined as Core::Mode::THREE_D will by default play at the position of the listener.
Channels are reference counted. If a channel is stolen by the FMOD priority system, then the handle to the stolen voice becomes invalid, and Channel based commands will not affect the new sound playing in its place. If all channels are currently full playing a sound, FMOD will steal a channel with the lowest priority sound. If more channels are playing than are currently available on the sound-card/sound device or software mixer, then FMOD will “virtualize” the channel. This type of channel is not heard, but it is updated as if it was playing. When its priority becomes high enough or another sound stops that was using a real hardware/software channel, it will start playing from where it should be. This technique saves CPU time (thousands of sounds can be played at once without actually being mixed or taking up resources), and also removes the need for the user to manage voices themselves. An example of virtual channel usage is a dungeon with 100 torches burning, all with a looping crackling sound, but with a sound-card that only supports 32 hardware voices. If the 3D positions and priorities for each torch are set correctly, FMOD will play all 100 sounds without any “out of channels” errors, and swap the real voices in and out according to which torches are closest in 3D space. Priority for virtual channels can be changed in the sound’s defaults, or at runtime with Channel#priority.
766 767 768 |
# File 'lib/fmod/sound.rb', line 766 def play(group = nil) parent.play_sound(self, group, false) end |
#read_data(size) ⇒ String
Reads data from an opened sound to a buffer, using the FMOD codec created internally, and returns it.
This can be used for decoding data offline in small pieces (or big pieces), rather than playing and capturing it, or loading the whole file at once and having to #lock / #unlock the data. If too much data is read, it is possible an EOF error will be thrown, meaning it is out of data. The “read” parameter will reflect this by returning a smaller number of bytes read than was requested. To avoid an error, simply compare the size of the returned buffer against what was requested before calling again.
As a sound already reads the whole file then closes it upon calling FMOD::System#create_sound (unless FMOD::System#create_stream or Core::Mode::CREATE_STREAM is used), this function will not work because the file is no longer open.
Note that opening a stream makes it read a chunk of data and this will advance the read cursor. You need to either use Core::Mode::OPEN_ONLY to stop the stream pre-buffering or call #seek_data to reset the read cursor.
If Core::Mode::OPEN_ONLY flag is used when opening a sound, it will leave the file handle open, and FMOD will not read any data internally, so the read cursor will be at position 0. This will allow the user to read the data from the start.
As noted previously, if a sound is opened as a stream and this function is called to read some data, then you will ‘miss the start’ of the sound.
Channel#position will have the same result. These function will flush the stream buffer and read in a chunk of audio internally. This is why if you want to read from an absolute position you should use Sound::seekData and not the previously mentioned functions.
Remember if you are calling readData and seekData on a stream it is up to you to cope with the side effects that may occur. Information functions such as Channel#position may give misleading results. Calling Channel#position will reset and flush the stream, leading to the time values returning to their correct position.
391 392 393 394 395 396 397 |
# File 'lib/fmod/sound.rb', line 391 def read_data(size) buffer = "\0" * size read = "\0" * SIZEOF_INT FMOD.invoke(:Sound_ReadData, self, buffer, size, read) read = read.unpack1('L') read < size ? buffer.byteslice(0, read) : buffer end |
#seek_data(pcm) ⇒ void
This is not a function to “seek a sound” for normal use. This is for use in conjunction with #read_data.
This method returns an undefined value.
Seeks a sound for use with data reading.
If a stream is opened and this function is called to read some data, then it will advance the internal file pointer, so data will be skipped if you play the stream. Also calling position / time information functions will lead to misleading results.
A stream can be reset before playing by setting the position of the channel (ie using Channel#position), which will make it seek, reset and flush the stream buffer. This will make it sound correct again.
Remember if you are calling #read_data and #seek_data on a stream it is up to you to cope with the side effects that may occur.
419 420 421 |
# File 'lib/fmod/sound.rb', line 419 def seek_data(pcm) FMOD.invoke(:Sound_SeekData, self, pcm) end |
#set_cone(inside_angle, outside_angle, outside_volume) ⇒ void
This method returns an undefined value.
Sets the angles that define the sound projection cone including the volume when outside the cone.
453 454 455 456 457 458 459 460 |
# File 'lib/fmod/sound.rb', line 453 def set_cone(inside_angle, outside_angle, outside_volume) if outside_angle < inside_angle raise Error, 'Outside angle must be greater than inside angle.' end FMOD.invoke(:Sound_Set3DConeSettings, self, inside_angle, outside_angle, outside_volume) self end |
#set_loop(loop_start, loop_end, start_unit = TimeUnit::MS, end_unit = TimeUnit::MS) ⇒ void
This method returns an undefined value.
Sets the loop points within a sound
If a sound was 44100 samples long and you wanted to loop the whole sound, loop_start would be 0, and loop_end would be 44099, not 44100. You wouldn’t use milliseconds in this case because they are not sample accurate.
If loop end is smaller or equal to loop start, it will result in an error.
If loop start or loop end is larger than the length of the sound, it will result in an error
650 651 652 653 |
# File 'lib/fmod/sound.rb', line 650 def set_loop(loop_start, loop_end, start_unit = TimeUnit::MS, end_unit = TimeUnit::MS) FMOD.invoke(:Sound_SetLoopPoints, self, loop_start, start_unit, loop_end, end_unit) end |
#set_music_volume(channel, volume) ⇒ void
This method returns an undefined value.
Sets the volume of a MOD/S3M/XM/IT/MIDI music channel volume.
690 691 692 693 |
# File 'lib/fmod/sound.rb', line 690 def set_music_volume(channel, volume) volume = volume.clamp(0.0, 1.0) FMOD.invoke(:Sound_SetMusicChannelVolume, self, channel, volume) end |
#subsound(index) ⇒ Sound?
Retrieves a handle to a FMOD::Sound object that is contained within the parent sound.
195 196 197 198 199 |
# File 'lib/fmod/sound.rb', line 195 def subsound(index) return nil unless index.between?(0, subsound_count - 1) FMOD.invoke(:Sound_GetSubSound, self, index, sound = int_ptr) Sound.new(sound) end |
#syncpoint(index) ⇒ Pointer
Retrieve a handle to a sync point. These points can be user generated or can come from a wav file with embedded markers.
239 240 241 242 243 |
# File 'lib/fmod/sound.rb', line 239 def syncpoint(index) return nil unless index.between?(0, syncpoint_count - 1) FMOD.invoke(:Sound_GetSyncPoint, self, index, sync = int_ptr) Pointer.new(sync.unpack1('J')) end |
#syncpoint_info(syncpoint, time_unit = TimeUnit::MS) ⇒ Array(String, Integer)
Retrieves information on an embedded sync point. These points can be user generated or can come from a wav file with embedded markers.
723 724 725 726 727 728 |
# File 'lib/fmod/sound.rb', line 723 def syncpoint_info(syncpoint, time_unit = TimeUnit::MS) name, offset = "\0" * 256, "\0" * SIZEOF_INT FMOD.invoke(:Sound_GetSyncPointInfo, self, syncpoint, name, 256, offset, time_unit) [name.delete("\0"), offset.unpack1('L')] end |