class FMOD::Sound

Represents the actual data source of audio, usually an audio file or stream.

Constants

Format

Contains format information about the sound. @attr type [Integer] The type of sound.

@see SoundType

@attr format [Integer] The format of the sound.

@see SoundFormat

@attr channels [Integer] The number of channels for the sound. @attr bits [Integer] The number of bits per sample for the sound.

Public Instance Methods

add_syncpoint(name, offset, unit = TimeUnit::MS) click to toggle source

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. @param name [String] A name character string to be stored with the sync

point.

@param offset [Integer] Offset to add the callback sync-point for a sound. @param unit [Integer] Offset type to describe the offset provided.

@see TimeUnit

@return [Pointer] The sync point handle.

# 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
cone_settings() click to toggle source

@!attribute cone_settings The angles that define the sound projection cone including the volume when outside the cone. @return [ConeSettings] the sound projection cone.

# 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
cone_settings=(settings) click to toggle source
# File lib/fmod/sound.rb, line 438
def cone_settings=(settings)
  FMOD.type?(settings, ConeSettings)
  set_cone(*settings.values)
  settings
end
custom_rolloff() click to toggle source

@!attribute custom_rolloff

A custom rolloff curve to define how audio will attenuate over distance.

Must be used in conjunction with {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. @return [Array<Vector>] the rolloff curve.

# 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
custom_rolloff=(rolloff) click to toggle source
# File lib/fmod/sound.rb, line 484
def custom_rolloff=(rolloff)
  FMOD.type?(rolloff, Array)
  vectors = rolloff.map { |vector| vector.to_str }.join
  FMOD.invoke(:Sound_Set3DCustomRolloff, self, vectors, rolloff.size)
  rolloff
end
default_frequency() click to toggle source

@!attribute default_frequency 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. @return [Float] the default playback frequency, in hz. (ie 44100hz).

# 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_frequency=(frequency) click to toggle source
# File lib/fmod/sound.rb, line 573
def default_frequency=(frequency)
  FMOD.invoke(:Sound_SetDefaults, self, frequency, default_priority)
end
default_priority() click to toggle source

@!attribute default_priority 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. @return [Integer] the default priority when played on a channel.

* *Minimum:* 0 (most important)
* *Maximum:* 256 (least important)
* Default:* 128
# 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
default_priority=(priority) click to toggle source
# File lib/fmod/sound.rb, line 593
def default_priority=(priority)
  priority = priority.clamp(0, 256)
  FMOD.invoke(:Sound_SetDefaults, self, default_frequency, priority)
end
delete_syncpoint(sync_point) click to toggle source

Deletes a syncpoint within the sound. These points can be user generated or can come from a wav file with embedded markers. @param sync_point [Pointer] A sync point handle. @return [void]

# 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() { |subsound(i)| ... } click to toggle source

Enumerates each subsound within this {Sound}. @overload each_subsound

When block is given, yields each subsound before returning self.
@yield [sound] Yields a sound to the block.
@yieldparam sound [Sound] The current sound being enumerated.
@return [self]

@overload each_subsound

When no block is given, returns an enumerator for the subsounds.
@return [Enumerator]
# 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
format() click to toggle source

@!attribute [r] format @return [Format] the format information for the sound.

# 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() click to toggle source

@!attribute group @return [SoundGroup] the sound's current {SoundGroup}.

# File lib/fmod/sound.rb, line 170
def group
  FMOD.invoke(:Sound_GetSoundGroup, self, group = int_ptr)
  SoundGroup.new(group)
end
group=(group) click to toggle source
# File lib/fmod/sound.rb, line 175
def group=(group)
  FMOD.type?(group, SoundGroup)
  FMOD.invoke(:Sound_SetSoundGroup, self, group)
end
length(unit = TimeUnit::MS) click to toggle source

Retrieves the length of the sound using the specified time unit. @param unit [Integer] Time unit retrieve into the length parameter.

@see TimeUnit

@return [Integer] the length in the requested units.

# 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| ... } click to toggle source

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.

@overload lock(offset, length)

If called with a block, yields the pointers to the first and second
sections of locked data before unlocking and returning +self+.
@yield [ptr1, ptr2] Yields two pointers to the block.
@yieldparam ptr1 [Pointer] Pointer to the first part of the locked data,
  and its size set to the number of locked bytes.
@yieldparam ptr2 [Pointer] The second pointer will point to the second
  part of the locked data. This will be {FMOD::NULL} if the data locked
  hasn't wrapped at the end of the buffer, and its size will be 0.
@return [self]

@overload lock(offset, length)

If called without a block, returns the pointers in an array, and
{#unlock} must be called.
@return [Array(Pointer, Pointer)] An array containing two pointers.

  The first pointer will point to the first part of the locked data, and
  its size set to the number of locked bytes.

  The second pointer will point to the second part of the locked data.
  This will be {FMOD::NULL} if the data locked hasn't wrapped at the end
  of the buffer, and its size will be 0.

@param offset [Integer] Offset in bytes to the position to lock in the

sample buffer.

@param length [Integer] Number of bytes you want to lock in the sample

buffer.

@see unlock

# 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) click to toggle source

Retrieves the loop points for a sound. @param start_unit [Integer] The time format used for the returned loop

start point.
@see TimeUnit

@param end_unit [Integer] The time format used for the returned loop end

point.
@see TimeUnit

@return [Array(Integer, Integer)] the loop points in an array where the

first element is the start loop point, and second element is the end
loop point in the requested time units.
# 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
max_distance() click to toggle source

@!attribute max_distance @return [Float] Maximum volume distance in “units”. (Default: 10000.0) @see min_distance @see in_max_distance

# 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
max_distance=(distance) click to toggle source
# File lib/fmod/sound.rb, line 519
def max_distance=(distance)
  min_max_distance(min_distance, distance)
end
min_distance() click to toggle source

@!attribute min_distance @return [Float] Minimum volume distance in “units”. (Default: 1.0) @see max_distance @see min_max_distance

# 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
min_distance=(distance) click to toggle source
# File lib/fmod/sound.rb, line 503
def min_distance=(distance)
  min_max_distance(distance, max_distance)
end
min_max_distance(min, max) click to toggle source

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.

@param min [Float] Minimum volume distance in “units”.

* *Default:* 1.0

@param max [Float] Maximum volume distance in “units”.

* *Default:* 10000.0

@see min_distance @see max_distance @return [void]

# File lib/fmod/sound.rb, line 554
def min_max_distance(min, max)
  FMOD.invoke(:Sound_Set3DMinMaxDistance, self, min, max)
end
music_volume(channel) click to toggle source

Retrieves the volume of a MOD/S3M/XM/IT/MIDI music channel volume. @param channel [Integer] MOD/S3M/XM/IT/MIDI music sub-channel to retrieve

the volume for.

@return [Float] the volume of the channel from 0.0 to 1.0.

* *Default:* 1.0

@see set_music_volume

# 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
name() click to toggle source

@!attribute [r] name @return [String] the name of the sound.

# File lib/fmod/sound.rb, line 155
def name
  FMOD.invoke(:Sound_GetName, self, buffer = "\0" * 512, 512)
  buffer.delete("\0")
end
open_state() click to toggle source

Retrieves the state a sound is in after {Mode::NON_BLOCKING} has been used to open it, or the state of the streaming buffer.

@return [OpenState] the current state of the sound.

# 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
parent() click to toggle source

@!attribute [r] parent @return [System] the parent {System} object that was used to create this

object.
# File lib/fmod/sound.rb, line 184
def parent
  FMOD.invoke(:Sound_GetSystemObject, self, system = int_ptr)
  System.new(system)
end
parent_sound() click to toggle source

@!attribute [r] parent_sound @return [Sound, nil] the parent {Sound} of this sound, or nil if this

sound is not a subsound.
# 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
play(group = nil) click to toggle source

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 {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}.

@param group [ChannelGroup] The {ChannelGroup} become a member of. This is

more efficient than later setting with {Channel.group}, as it does it
during the channel setup, rather than connecting to the master channel
group, then later disconnecting and connecting to the new {ChannelGroup}
when specified. Specify +nil+ to ignore (use master {ChannelGroup}).

@return [Channel] the newly playing channel.

# File lib/fmod/sound.rb, line 766
def play(group = nil)
  parent.play_sound(self, group, false)
end
read_data(size) click to toggle source

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 {System.create_sound} (unless {System.create_stream} or {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 {Mode::OPEN_ONLY} to stop the stream pre-buffering or call {#seek_data} to reset the read cursor.

If {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.

@param size [Integer] The number of bytes to read into the buffer. @return [String] A binary string containing the buffer data. The data will

be the size specified unless it has reached the end of the data, in
which case it will be less, and trimmed to length.

@see seek_data

# 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) click to toggle source

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.

@note This is not a function to “seek a sound” for normal use. This is for

use in conjunction with {#read_data}.

@param pcm [Integer] Offset to seek to in PCM samples. @return [void] @see read_data

# 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) click to toggle source

Sets the angles that define the sound projection cone including the volume when outside the cone. @param inside_angle [Float] Inside cone angle, in degrees. This is the

angle within which the sound is at its normal volume.

@param outside_angle [Float] Outside cone angle, in degrees. This is the

angle outside of which the sound is at its outside volume.

@param outside_volume [Float] Cone outside volume. @return [void]

# 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) click to toggle source

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

@param loop_start [Integer] The loop start point. This point in time is

played, so it is inclusive.

@param loop_end [Integer] The loop end point. This point in time is

played, so it is inclusive

@param start_unit [Integer] The time format used for the loop start point.

@see TimeUnit

@param end_unit [Integer] The time format used for the loop end point.

@see TimeUnit

@return [void]

# 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) click to toggle source

Sets the volume of a MOD/S3M/XM/IT/MIDI music channel volume. @param channel [Integer] MOD/S3M/XM/IT/MIDI music sub-channel to set a

linear volume for.

@param volume [Float] Volume of the channel.

* *Minimum:* 0.0
* *Maximum:* 1.0
* *Default:* 1.0

@return [void]

# 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) click to toggle source

Retrieves a handle to a {Sound} object that is contained within the parent sound. @param index [Integer] Index of the subsound to retrieve within this

sound.

@return [Sound, nil] the subsound, or nil

# 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
subsounds() click to toggle source

@!attribute [r] subsounds @return [Array<Sound>] an array of the this sound's subsounds.

# File lib/fmod/sound.rb, line 204
def subsounds
  (0...subsound_count).map { |i| subsound(i) }
end
syncpoint(index) click to toggle source

Retrieve a handle to a sync point. These points can be user generated or can come from a wav file with embedded markers. @param index [Integer] Index of the sync point to retrieve. @return [Pointer] the sync point handle.

# 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) click to toggle source

Retrieves information on an embedded sync point. These points can be user generated or can come from a wav file with embedded markers. @param syncpoint [Pointer] A handle to a sync-point. @param time_unit [Integer] A {TimeUnit} parameter to determine a desired

format for the offset parameter.

@return [Array(String, Integer)] array containing the name of the

sync-point and the offset in the requested time unit.

@see TimeUnit

# 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
tags() click to toggle source

@!attribute [r] tags @return [TagCollection] object containing the tags within the {Sound}.

# File lib/fmod/sound.rb, line 163
def tags
  TagCollection.send(:new, self)
end
unknown() click to toggle source

@!attribute mode 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:

  • {Mode::LOOP_OFF}

  • {Mode::LOOP_NORMAL}

  • {Mode::LOOP_BIDI}

  • {Mode::TWO_D}

  • {Mode::THREE_D}

  • {Mode::HEAD_RELATIVE_3D}

  • {Mode::WORLD_RELATIVE_3D}

  • {Mode::INVERSE_ROLLOFF_3D}

  • {Mode::LINEAR_ROLLOFF_3D}

  • {Mode::LINEAR_SQUARE_ROLLOFF_3D}

  • {Mode::CUSTOM_ROLLOFF_3D}

  • {Mode::IGNORE_GEOMETRY_3D}

@return [Integer]

# File lib/fmod/sound.rb, line 129
integer_reader(:mode, :Sound_GetMode)
unlock(ptr1, ptr2) click to toggle source

Releases previous sample data lock from {#lock}.

@note This function should not be called if a block was passed to {#lock}.

@param ptr1 [Pointer] Pointer to the first locked portion of sample data,

from {#lock}.

@param ptr2 [Pointer] Pointer to the second locked portion of sample data,

from {#lock}.

@see lock @return [void]

# File lib/fmod/sound.rb, line 341
def unlock(ptr1, ptr2)
  FMOD.invoke(:Sound_Unlock, self, ptr1, ptr2, ptr1.size, ptr2.size)
end