fmod 0.9.1 → 0.9.2

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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/HISTORY.txt +23 -1
  3. data/README.md +1 -3
  4. data/Rakefile +2 -1
  5. data/bin/console +1 -0
  6. data/fmod.gemspec +1 -2
  7. data/lib/fmod/channel_control.rb +47 -0
  8. data/lib/fmod/core.rb +1 -0
  9. data/lib/fmod/core/bool_description.rb +9 -4
  10. data/lib/fmod/core/channel_mask.rb +61 -0
  11. data/lib/fmod/core/data_description.rb +44 -0
  12. data/lib/fmod/core/dsp_description.rb +172 -1
  13. data/lib/fmod/core/dsp_index.rb +13 -0
  14. data/lib/fmod/core/dsp_type.rb +154 -0
  15. data/lib/fmod/core/extensions.rb +19 -0
  16. data/lib/fmod/core/file_system.rb +1 -0
  17. data/lib/fmod/core/filter_type.rb +62 -0
  18. data/lib/fmod/core/float_description.rb +38 -0
  19. data/lib/fmod/core/guid.rb +27 -0
  20. data/lib/fmod/core/init_flags.rb +66 -0
  21. data/lib/fmod/core/integer_description.rb +22 -2
  22. data/lib/fmod/core/output_type.rb +81 -2
  23. data/lib/fmod/core/parameter_info.rb +36 -0
  24. data/lib/fmod/core/parameter_type.rb +15 -0
  25. data/lib/fmod/core/reverb.rb +113 -2
  26. data/lib/fmod/core/reverb_index.rb +105 -0
  27. data/lib/fmod/core/sound_ex_info.rb +4 -0
  28. data/lib/fmod/core/sound_group_behavior.rb +14 -0
  29. data/lib/fmod/core/sound_type.rb +1 -0
  30. data/lib/fmod/core/spectrum_data.rb +35 -0
  31. data/lib/fmod/core/structures.rb +10 -4
  32. data/lib/fmod/core/tag.rb +72 -11
  33. data/lib/fmod/core/tag_data_type.rb +30 -0
  34. data/lib/fmod/core/tag_type.rb +55 -0
  35. data/lib/fmod/core/time_unit.rb +3 -0
  36. data/lib/fmod/core/vector.rb +40 -3
  37. data/lib/fmod/core/window_type.rb +46 -0
  38. data/lib/fmod/dsp.rb +427 -98
  39. data/lib/fmod/dsp_connection.rb +3 -0
  40. data/lib/fmod/effects.rb +51 -37
  41. data/lib/fmod/error.rb +3 -0
  42. data/lib/fmod/geometry.rb +7 -0
  43. data/lib/fmod/handle.rb +82 -0
  44. data/lib/fmod/reverb3D.rb +25 -26
  45. data/lib/fmod/sound.rb +21 -1
  46. data/lib/fmod/sound_group.rb +79 -3
  47. data/lib/fmod/system.rb +301 -154
  48. data/lib/fmod/version.rb +4 -1
  49. metadata +6 -3
@@ -1,11 +1,57 @@
1
1
  module FMOD
2
2
  module Core
3
+
4
+ ##
5
+ # List of windowing methods for the {Effects::FFT} unit. Used in spectrum
6
+ # analysis to reduce leakage / transient signals interfering with the
7
+ # analysis.
8
+ #
9
+ # This is a problem with analysis of continuous signals that only have a
10
+ # small portion of the signal sample (the FFT window size).
11
+ #
12
+ # Windowing the signal with a curve or triangle tapers the sides of the FFT
13
+ # window to help alleviate this problem.
14
+ #
15
+ # Cyclic signals such as a sine wave that repeat their cycle in a multiple
16
+ # of the window size do not need windowing. I.e. If the sine wave repeats
17
+ # every 1024, 512, 256 etc samples and the FMOD FFT window is 1024, then the
18
+ # signal would not need windowing.
19
+ #
20
+ # Not windowing is the same as :rectangle, which is the default.
21
+ #
22
+ # If the cycle of the signal (ie the sine wave) is not a multiple of the
23
+ # window size, it will cause frequency abnormalities, so a different
24
+ # windowing method is needed.
3
25
  module WindowType
26
+
27
+ ##
28
+ # Rectangle.
29
+ # w[n] = 1.0
4
30
  RECT = 0
31
+
32
+ ##
33
+ # Triangle.
34
+ # w[n] = TRI(2n/N)
5
35
  TRIANGLE = 1
36
+
37
+ ##
38
+ # Hamming.
39
+ # w[n] = 0.54 - (0.46 * COS(n/N) )
6
40
  HAMMING = 2
41
+
42
+ ##
43
+ # Hanning.
44
+ # w[n] = 0.5 * (1.0 - COS(n/N) )
7
45
  HANNING = 3
46
+
47
+ ##
48
+ # Blackman.
49
+ # w[n] = 0.42 - (0.5 * COS(n/N) ) + (0.08 * COS(2.0 * n/N) )
8
50
  BLACKMAN = 4
51
+
52
+ ##
53
+ # Blackman-Harris.
54
+ # w[n] = 0.35875 - (0.48829 * COS(1.0 * n/N)) + (0.14128 * COS(2.0 * n/N)) - (0.01168 * COS(3.0 * n/N))
9
55
  BLACKMAN_HARRIS = 5
10
56
  end
11
57
  end
@@ -1,17 +1,84 @@
1
1
  module FMOD
2
2
 
3
- # @attr wet_dry_mix [WetDryMix] Allows the user to scale the affect of a DSP
4
- # effect, through control of the "wet" mix, which is the post-processed
5
- # signal and the "dry" which is the pre-processed signal.
6
- #
7
- # The dry signal path is silent by default, because DSP effects transform
8
- # the input and pass the newly processed result to the output. It does not
9
- # add to the input.
3
+
4
+ ##
5
+ # Represents a digital signal processor. This allows for monitoring and
6
+ # applying effects to the sound in real-time.
10
7
  class Dsp < Handle
11
8
 
9
+ ##
10
+ # Describes mix levels that allow the user to scale the affect of a DSP
11
+ # effect, through control of the "wet" mix, which is the post-processed
12
+ # signal and the "dry" which is the pre-processed signal.
13
+ #
14
+ # @attr pre_wet [Float] A floating point value from 0.0 to 1.0, describing a
15
+ # linear scale of the "wet" (pre-processed signal) mix of the effect.
16
+ # Default is 1.0. Scale can be lower than 0.0 (negating) and higher than
17
+ # 1.0 (amplifying).
18
+ # @attr post_wet [Float] A floating point value from 0.0 to 1.0, describing
19
+ # a linear scale of the "'wet' "(post-processed signal) mix of the effect.
20
+ # Default is 1.0. Scale can be lower than 0.0 (negating) and higher than
21
+ # 1.0 (amplifying).
22
+ # @attr dry [Float] A floating point value from 0.0 to 1.0, describing a
23
+ # linear scale of the "dry" (pre-processed signal) mix of the effect.
24
+ # Default is 0.0. Scale can be lower than 0.0 and higher than 1.0
25
+ # (amplifying).
26
+ WetDryMix = Struct.new(:pre_wet, :post_wet, :dry)
27
+
28
+ ##
29
+ # Defines the signal format of a dsp unit so that the signal is processed
30
+ # on the speakers specified, as well as the number of channels in the unit
31
+ # that a read callback will process, and the output signal of the unit.
32
+ #
33
+ # Setting the number of channels on a unit will force a down or up mix to
34
+ # that channel count before processing the DSP read callback. This count is
35
+ # then sent to the outputs of the unit.
36
+ #
37
+ # The speaker mode is informational, when the mask describes what bits are
38
+ # active, and the channel count describes how many channels are in a buffer,
39
+ # speaker mode describes where the channels originated from. For example if
40
+ # the channel count is 2 then this could describe for the DSP if the
41
+ # original signal started from a stereo signal or a 5.1 signal.
42
+ #
43
+ # It could also describe the signal as all monaural, for example if the
44
+ # channel count was 16 and the speaker mode was {SpeakerMode::MONO}.
45
+ #
46
+ # @attr mask [Integer] A series of bits specified by {ChannelMask} to
47
+ # determine which speakers are represented by the channels in the signal.
48
+ # @attr count [Integer] The number of channels to be processed on this unit
49
+ # and sent to the outputs connected to it. Maximum of
50
+ # {FMOD::MAX_CHANNEL_WIDTH}.
51
+ # @attr speaker_mode [Integer] The source speaker mode where the signal came
52
+ # from.
53
+ #
54
+ # @see ChannelMask
55
+ # @see SpeakerMode
12
56
  ChannelFormat = Struct.new(:mask, :count, :speaker_mode)
13
57
 
58
+ ##
59
+ # Contains information about the current DSP unit, including name, version,
60
+ # default channels and width and height of configuration dialog box if it
61
+ # exists.
62
+ #
63
+ # @attr name [String] The name of the unit.
64
+ # @attr version [String] The version number of the DSP unit.
65
+ # @attr channels [Integer] The number of channels the unit was initialized
66
+ # with. 0 means the plugin will process whatever number of channels is
67
+ # currently in the network. >0 would be mostly used if the unit is a unit
68
+ # that only generates sound, or is not flexible enough to take any number
69
+ # of input channels.
70
+ # @attr width [Integer] The width of an optional configuration dialog box
71
+ # that can be displayed with {Dsp.show_dialog}. 0 means the dialog is not
72
+ # present.
73
+ # @attr height [Integer] The height of an optional configuration dialog box
74
+ # that can be displayed with {Dsp.show_dialog}. 0 means the dialog is not
75
+ # present.
14
76
  DspInfo = Struct.new(:name, :version, :channels, :width, :height) do
77
+
78
+ # @!method config?
79
+ # @return [Boolean] a flag indicating if DSP unit has an optional
80
+ # configuration dialog that can be displayed.
81
+ # @note None of the built-in DSP units contain a dialog.
15
82
  def config?
16
83
  width > 0 && height > 0
17
84
  end
@@ -65,6 +132,20 @@ module FMOD
65
132
  raise TypeError, "#{type} is not a Integer or Class."
66
133
  end
67
134
 
135
+ ##
136
+ # Plays a sound object on a particular channel and {ChannelGroup}.
137
+ #
138
+ # When a sound is played, it will use the sound's default frequency and
139
+ # priority.
140
+ #
141
+ # @param group [ChannelGroup] The {ChannelGroup} become a member of. This is
142
+ # more efficient than using {Channel.group}, as it does it during the
143
+ # channel setup, rather than connecting to the master channel group, then
144
+ # later disconnecting and connecting to the new {ChannelGroup} when
145
+ # specified. Specify +nil+ to ignore (use master {ChannelGroup}).
146
+ #
147
+ # @return [Channel] the newly playing channel.
148
+ # @see System.play_dsp
68
149
  def play(group = nil)
69
150
  parent.play_dsp(self, group, false)
70
151
  end
@@ -185,6 +266,17 @@ module FMOD
185
266
  "#{version[0, 4].to_i}.#{version[4, 4].to_i}"
186
267
  end
187
268
 
269
+ # @attribute wet_dry_mix
270
+ # Allows the user to scale the affect of a DSP effect, through control of
271
+ # the "wet" mix, which is the post-processed signal and the "dry" which is
272
+ # the pre-processed signal.
273
+ #
274
+ # The dry signal path is silent by default, because DSP effects transform
275
+ # the input and pass the newly processed result to the output. It does not
276
+ # add to the input.
277
+ #
278
+ # @return [WetDryMix] the current mix.
279
+ # @see WetDryMix
188
280
  def wet_dry_mix
189
281
  args = ["\0" * SIZEOF_FLOAT, "\0" * SIZEOF_FLOAT, "\0" * SIZEOF_FLOAT]
190
282
  FMOD.invoke(:DSP_GetWetDryMix, self, *args)
@@ -226,14 +318,10 @@ module FMOD
226
318
  self
227
319
  end
228
320
 
229
-
230
-
231
-
232
-
233
-
234
-
235
-
236
-
321
+ # @!attribute channel_format
322
+ # @return [ChannelFormat] The signal format of a DSP unit so that the signal
323
+ # is processed on the speakers specified.
324
+ # @see ChannelFormat
237
325
  def channel_format
238
326
  args = ["\0" * SIZEOF_INT, "\0" * SIZEOF_INT, "\0" * SIZEOF_INT]
239
327
  FMOD.invoke(:DSP_GetChannelFormat, self, *args)
@@ -247,16 +335,10 @@ module FMOD
247
335
  format
248
336
  end
249
337
 
250
- def param_info(index)
251
- return nil unless FMOD.valid_range?(index, 0, parameter_count, false)
252
- FMOD.invoke(:DSP_GetParameterInfo, self, index, info = int_ptr)
253
- ParameterInfo.new(info.unpack1('J'))
254
- end
255
-
256
- def to_s
257
- "#{name} v.#{version}"
258
- end
259
-
338
+ ##
339
+ # @return [DspInfo] the information about the current DSP unit, including
340
+ # name, version, default channels and width and height of configuration
341
+ # dialog box if it exists.
260
342
  def info
261
343
  name, vs = "\0" * 32, "\0" * SIZEOF_INT
262
344
  args = ["\0" * SIZEOF_INT, "\0" * SIZEOF_INT, "\0" * SIZEOF_INT]
@@ -267,67 +349,152 @@ module FMOD
267
349
  DspInfo.new(name.delete("\0"), version, *args)
268
350
  end
269
351
 
352
+ ##
353
+ # Calls the DSP unit's reset function, which will clear internal buffers and
354
+ # reset the unit back to an initial state.
355
+ #
356
+ # Calling this function is useful if the DSP unit relies on a history to
357
+ # process itself (ie an echo filter).
358
+ #
359
+ # If you disconnected the unit and reconnected it to a different part of the
360
+ # network with a different sound, you would want to call this to reset the
361
+ # units state (ie clear and reset the echo filter) so that you dont get left
362
+ # over artifacts from the place it used to be connected.
363
+ #
364
+ # @return [void]
270
365
  def reset
271
366
  FMOD.invoke(:DSP_Reset, self)
272
367
  end
273
368
 
369
+ ##
370
+ # @!attribute [r] parent
371
+ # @return [System] the parent {System} object that was used to create this
372
+ # object.
274
373
  def parent
275
374
  FMOD.invoke(:DSP_GetSystemObject, self, system = int_ptr)
276
375
  System.new(system)
277
376
  end
278
377
 
378
+ ##
379
+ # Display or hide a DSP unit configuration dialog box inside the target
380
+ # window.
381
+ #
382
+ # @param hwnd [Pointer] Target HWND in windows to display configuration
383
+ # dialog.
384
+ # @param show [Boolean] +true+ to display the window within the parent
385
+ # window, otherwise +false+ to remove it.
386
+ #
387
+ # @return [void]
279
388
  def show_dialog(hwnd, show = true)
280
389
  FMOD.invoke(:DSP_ShowConfigDialog, self, hwnd, show.to_i)
281
390
  end
282
391
 
392
+ ##
393
+ # Retrieve information about a specified parameter within the DSP unit.
394
+ #
395
+ # @param index [Integer] Parameter index for this unit.
396
+ #
397
+ # @return [ParameterInfo, nil] the information about the specified parameter
398
+ # or +nil+ if the index was out of range.
399
+ def param_info(index)
400
+ return nil unless FMOD.valid_range?(index, 0, parameter_count, false)
401
+ FMOD.invoke(:DSP_GetParameterInfo, self, index, info = int_ptr)
402
+ ParameterInfo.new(info.unpack1('J'))
403
+ end
404
+
405
+ ##
406
+ # Helper function to disconnect either all inputs or all outputs of a DSP
407
+ # unit.
408
+ #
409
+ # @param inputs [Boolean] +true+ to disconnect all inputs to this DSP unit,
410
+ # otherwise +false+ to leave input connections alone.
411
+ # @param outputs [Boolean] +true+ to disconnect all outputs to this DSP
412
+ # unit, otherwise +false+ to leave output connections alone.
413
+ #
414
+ # @return [void]
283
415
  def disconnect(inputs, outputs)
284
416
  FMOD.invoke(:DSP_DisconnectAll, self, inputs.to_i, outputs.to_i)
285
417
  end
286
418
 
419
+ ##
420
+ # Disconnect the DSP unit from the specified input.
421
+ #
422
+ # @param dsp [Dsp] The input unit that this unit is to be disconnected from.
423
+ # @param connection [DspConnection] If there is more than one connection
424
+ # between 2 dDSP units, this can be used to define which of the
425
+ # connections should be disconnected.
426
+ #
427
+ # @note If you have a handle to the connection pointer that binds these 2
428
+ # DSP units, then it will become invalid. The connection is then sent back
429
+ # to a freelist to be re-used again by a later addInput command.
430
+ #
431
+ # @return [void]
287
432
  def disconnect_from(dsp, connection = nil)
288
433
  FMOD.type?(dsp, Dsp) unless dsp.nil?
289
434
  FMOD.type?(connection, DspConnection) unless connection.nil?
290
435
  FMOD.invoke(:DSP_DisconnectFrom, self, dsp, connection)
291
436
  end
292
437
 
293
- def output_format(*args)
294
- if args.size == 3 && args.all? { |arg| arg.is_a?(Integer) }
295
- mask, count, mode = args
296
- elsif args.size == 1 && FMOD.type?(args[0], ChannelFormat)
297
- mask, count, mode = args[0].values
298
- else
299
- mask, count, mode = channel_format.values
300
- end
301
- args = ["\0" * SIZEOF_INT, "\0" * SIZEOF_INT, "\0" * SIZEOF_INT]
302
- FMOD.invoke(:DSP_GetOutputChannelFormat, mask, count, mode, *args)
303
- args.map! { |arg| arg.unpack1('L') }
304
- ChannelFormat.new(*args)
305
- end
306
-
438
+ ##
439
+ # Retrieves a DSP unit which is acting as an input to this unit.
440
+ #
441
+ # @param index [Integer] Index of the input unit to retrieve.
442
+ #
443
+ # @return [Dsp] the input unit.
307
444
  def input(index)
308
445
  input = int_ptr
309
446
  FMOD.invoke(:DSP_GetInput, self, index, input, nil)
310
447
  Dsp.from_handle(input)
311
448
  end
312
449
 
450
+ ##
451
+ # Retrieves a DSP unit which is acting as an output to this unit.
452
+ #
453
+ # @param index [Integer] Index of the output unit to retrieve.
454
+ #
455
+ # @return [Dsp] the output unit.
313
456
  def output(index)
314
457
  output = int_ptr
315
458
  FMOD.invoke(:DSP_GetOutput, self, index, output, nil)
316
459
  Dsp.from_handle(output)
317
460
  end
318
461
 
462
+ ##
463
+ # Retrieves the connection which to a DSP acting as an input to this unit.
464
+ #
465
+ # @param index [Integer] Index of the input unit to retrieve the connection.
466
+ #
467
+ # @return [DspConnection] the input unit connection.
319
468
  def input_connection(index)
320
469
  connection = int_ptr
321
470
  FMOD.invoke(:DSP_GetInput, self, index, nil, connection)
322
471
  DspConnection.new(connection)
323
472
  end
324
473
 
474
+ ##
475
+ # Retrieves the connection which to a DSP acting as an output to this unit.
476
+ #
477
+ # @param index [Integer] Index of the output unit to retrieve the connection.
478
+ #
479
+ # @return [DspConnection] the output unit connection.
325
480
  def output_connection(index)
326
481
  connection = int_ptr
327
482
  FMOD.invoke(:DSP_GetOutput, self, index, nil, connection)
328
483
  DspConnection.new(connection)
329
484
  end
330
485
 
486
+ ##
487
+ # Adds the specified DSP unit as an input of the DSP object.
488
+ #
489
+ # @param dsp [Dsp] The DSP unit to add as an input of the current unit.
490
+ # @param type [Integer] The type of connection between the 2 units. The
491
+ # following are valid values.
492
+ # * {DspConnection::STANDARD}
493
+ # * {DspConnection::SIDECHAIN}
494
+ # * {DspConnection::SEND}
495
+ # * {DspConnection::SEND_SIDECHAIN}
496
+ #
497
+ # @return [DspConnection] the connection between the 2 units.
331
498
  def add_input(dsp, type)
332
499
  FMOD.type?(dsp, Dsp)
333
500
  connection = int_ptr
@@ -335,33 +502,81 @@ module FMOD
335
502
  DspConnection.new(connection)
336
503
  end
337
504
 
505
+ ##
506
+ # Call the DSP process function to retrieve the output signal format for a
507
+ # DSP based on input values.
508
+ #
509
+ # A DSP unit may be an up mixer or down mixer for example. In this case if
510
+ # you specified 6 in for a down-mixer, it may provide you with 2 out for
511
+ # example.
512
+ #
513
+ # Generally the input values will be reproduced for the output values, but
514
+ # some DSP units will want to alter the output format.
515
+ #
516
+ # @overload output_format(format)
517
+ # @param format [ChannelFormat] Structure describing the incoming channel
518
+ # format.
519
+ # @overload output_format(mask, count, speaker_mode)
520
+ # @param mask [Integer] Channel bit-mask representing the speakers enabled
521
+ # for the incoming signal.
522
+ # @param count [Integer] Number of channels for the incoming signal.
523
+ # @param speaker_mode [Integer] Speaker mode for the incoming signal.
524
+ #
525
+ # @return [ChannelFormat] the output signal format.
526
+ def output_format(*args)
527
+ if args.size == 3 && args.all? { |arg| arg.is_a?(Integer) }
528
+ mask, count, mode = args
529
+ elsif args.size == 1 && FMOD.type?(args[0], ChannelFormat)
530
+ mask, count, mode = args[0].values
531
+ else
532
+ mask, count, mode = channel_format.values
533
+ end
534
+ args = ["\0" * SIZEOF_INT, "\0" * SIZEOF_INT, "\0" * SIZEOF_INT]
535
+ FMOD.invoke(:DSP_GetOutputChannelFormat, mask, count, mode, *args)
536
+ args.map! { |arg| arg.unpack1('L') }
537
+ ChannelFormat.new(*args)
538
+ end
539
+
540
+ ##
541
+ # @return [Boolean] a flag indicating if input metering for the DSP it is
542
+ # enabled or not.
338
543
  def input_metering?
339
544
  enabled = "\0" * SIZEOF_INT
340
545
  FMOD.invoke(:DSP_GetMeteringEnabled, self, enabled, nil)
341
546
  enabled.unpack1('l') != 0
342
547
  end
343
548
 
549
+ ##
550
+ # @return [Boolean] a flag indicating if output metering for the DSP it is
551
+ # enabled or not.
344
552
  def output_metering?
345
553
  enabled = "\0" * SIZEOF_INT
346
554
  FMOD.invoke(:DSP_GetMeteringEnabled, self, nil, enabled)
347
555
  enabled.unpack1('l') != 0
348
556
  end
349
557
 
558
+ ##
559
+ # Enable metering for a DSP unit.
560
+ #
561
+ # @param input [Boolean] Enable metering for the input signal
562
+ # (pre-processing). Specify +true+ to turn on input level metering,
563
+ # +false+ to turn it off.
564
+ # @param output [Boolean] Enable metering for the output signal
565
+ # (post-processing). Specify +true+ to turn on output level metering,
566
+ # +false+ to turn it off.
567
+ #
568
+ # @return [void]
350
569
  def enable_metering(input, output)
351
570
  FMOD.invoke(:DSP_SetMeteringEnabled, self, input ? 1 :0, output.to_i)
352
571
  end
353
572
 
354
- def [](index)
355
- return nil unless FMOD.valid_range?(index, 0, parameter_count, false)
356
- case param_info(index).type
357
- when ParameterType::FLOAT then get_float(index)
358
- when ParameterType::INT then get_integer(index)
359
- when ParameterType::BOOL then get_integer(index)
360
- when ParameterType::DATA then get_data(index)
361
- else raise RangeError, 'Unknown data type.'
362
- end
363
- end
364
-
573
+ ##
574
+ # Retrieves the unit's float parameter by index.
575
+ #
576
+ # @param index [Integer] Parameter index for this unit.
577
+ #
578
+ # @return [Float, nil] the parameter specified, or +nil+ if index is out
579
+ # of range.
365
580
  def get_float(index)
366
581
  return nil unless FMOD.valid_range?(index, 0, parameter_count, false)
367
582
  buffer = "\0" * SIZEOF_FLOAT
@@ -369,6 +584,13 @@ module FMOD
369
584
  buffer.unpack1('f')
370
585
  end
371
586
 
587
+ ##
588
+ # Retrieves the unit's integer parameter by index.
589
+ #
590
+ # @param index [Integer] Parameter index for this unit.
591
+ #
592
+ # @return [Integer, nil] the parameter specified, or +nil+ if index is out
593
+ # of range.
372
594
  def get_integer(index)
373
595
  return nil unless FMOD.valid_range?(index, 0, parameter_count, false)
374
596
  buffer = "\0" * SIZEOF_INT
@@ -376,6 +598,13 @@ module FMOD
376
598
  buffer.unpack1('l')
377
599
  end
378
600
 
601
+ ##
602
+ # Retrieves the unit's boolean parameter by index.
603
+ #
604
+ # @param index [Integer] Parameter index for this unit.
605
+ #
606
+ # @return [Boolean, nil] the parameter specified, or +nil+ if index is out
607
+ # of range.
379
608
  def get_bool(index)
380
609
  return nil unless FMOD.valid_range?(index, 0, parameter_count, false)
381
610
  buffer = "\0" * SIZEOF_INT
@@ -383,6 +612,13 @@ module FMOD
383
612
  buffer.unpack1('l') != 0
384
613
  end
385
614
 
615
+ ##
616
+ # Retrieves the unit's data parameter by index.
617
+ #
618
+ # @param index [Integer] Parameter index for this unit.
619
+ #
620
+ # @return [Pointer, nil] the parameter specified, or +nil+ if index is out
621
+ # of range.
386
622
  def get_data(index)
387
623
  return nil unless FMOD.valid_range?(index, 0, parameter_count, false)
388
624
  pointer = int_ptr
@@ -391,35 +627,52 @@ module FMOD
391
627
  Pointer.new(pointer.unpack('J'), size.unpack1('l'))
392
628
  end
393
629
 
394
- def []=(index, value)
395
- return unless FMOD.valid_range?(index, 0, parameter_count, false)
396
- case value
397
- when Float then set_float(index, value)
398
- when Integer then set_integer(index, value)
399
- when TrueClass, FalseClass, NilClass then set_bool(index, value)
400
- when String, Pointer then set_data(index, value)
401
- else raise TypeError, "#{value} is not a valid DSP parameter type."
402
- end
403
- end
404
-
630
+ ##
631
+ # Sets the unit's float parameter by index.
632
+ #
633
+ # @param index [Integer] Parameter index for this unit.
634
+ # @param value [Float] The value to set.
635
+ #
636
+ # @return [self]
405
637
  def set_float(index, value)
406
638
  return unless FMOD.valid_range?(index, 0, parameter_count, false)
407
639
  FMOD.invoke(:DSP_SetParameterFloat, self, index, value)
408
640
  self
409
641
  end
410
642
 
643
+ ##
644
+ # Sets the unit's integer parameter by index.
645
+ #
646
+ # @param index [Integer] Parameter index for this unit.
647
+ # @param value [Integer] The value to set.
648
+ #
649
+ # @return [self]
411
650
  def set_integer(index, value)
412
651
  return unless FMOD.valid_range?(index, 0, parameter_count, false)
413
652
  FMOD.invoke(:DSP_SetParameterInt, self, index, value)
414
653
  self
415
654
  end
416
655
 
656
+ ##
657
+ # Sets the unit's boolean parameter by index.
658
+ #
659
+ # @param index [Integer] Parameter index for this unit.
660
+ # @param value [Boolean] The value to set.
661
+ #
662
+ # @return [self]
417
663
  def set_bool(index, value)
418
664
  return unless FMOD.valid_range?(index, 0, parameter_count, false)
419
665
  FMOD.invoke(:DSP_SetParameterBool, self, index, value.to_i)
420
666
  self
421
667
  end
422
668
 
669
+ ##
670
+ # Sets the unit's data parameter by index.
671
+ #
672
+ # @param index [Integer] Parameter index for this unit.
673
+ # @param value [Pointer, String] The value to set.
674
+ #
675
+ # @return [self]
423
676
  def set_data(index, value)
424
677
  return unless FMOD.valid_range?(index, 0, parameter_count, false)
425
678
  unless FMOD.type?(value, String, false)
@@ -430,11 +683,73 @@ module FMOD
430
683
  self
431
684
  end
432
685
 
686
+ ##
687
+ # Get parameter by index.
688
+ #
689
+ # @param index [Integer] Parameter index for this unit.
690
+ #
691
+ # @return [Object] the value of the parameter at the specified index.
692
+ def [](index)
693
+ return nil unless FMOD.valid_range?(index, 0, parameter_count, false)
694
+ case param_info(index).type
695
+ when ParameterType::FLOAT then get_float(index)
696
+ when ParameterType::INT then get_integer(index)
697
+ when ParameterType::BOOL then get_integer(index)
698
+ when ParameterType::DATA then get_data(index)
699
+ else raise RangeError, 'Unknown data type.'
700
+ end
701
+ end
433
702
 
434
- class << self
703
+ ##
704
+ # Sets parameter by index.
705
+ #
706
+ # @param index [Integer] Parameter index for this unit.
707
+ # @param value [Float, Integer, Boolean, Pointer, String] The value to set.
708
+ #
709
+ # @note The value must be of the correct type for the specified parameter,
710
+ # no implicit conversions will be performed, i.e. passing an integer to a
711
+ # float parameter will fail, as it is not the correct type. It is up to
712
+ # the user to perform any conversions ahead before passing to this method.
713
+ #
714
+ # @return [Object] the value of the parameter at the specified index.
715
+ def []=(index, value)
716
+ return unless FMOD.valid_range?(index, 0, parameter_count, false)
717
+ case value
718
+ when Float then set_float(index, value)
719
+ when Integer then set_integer(index, value)
720
+ when TrueClass, FalseClass, NilClass then set_bool(index, value)
721
+ when String, Pointer then set_data(index, value)
722
+ else raise TypeError, "#{value} is not a valid DSP parameter type."
723
+ end
724
+ end
435
725
 
436
- private
726
+ ##
727
+ # @return [String] the string representation of the DSP unit.
728
+ def to_s
729
+ "#{name} v.#{version}"
730
+ end
731
+
732
+ class << self
437
733
 
734
+ ##
735
+ # Dynamically creates a method for getting and/or setting a named float
736
+ # parameter of a DSP unit.
737
+ #
738
+ # @param index [Integer] The parameter index.
739
+ # @param name [Symbol] The name of the attribute to define.
740
+ # @param options [Hash] The options hash.
741
+ #
742
+ # @option options [Boolean] :readonly (false) Flag indicating if a setter
743
+ # function will be defined or not.
744
+ # @option options [Boolean] :write_only (false) Flag indicating if a
745
+ # getter will be defined or not.
746
+ # @option options [Float] :min (nil) If defined will clamp any given value
747
+ # to the specified minimum value.
748
+ # @option options [Float] :max (nil) If defined will clamp any given value
749
+ # to the specified maximum value.
750
+ #
751
+ # @return [void]
752
+ # @api private
438
753
  def float_param(index, name, **options)
439
754
  define_method(name) { get_float(index) } unless options[:write_only]
440
755
  unless options[:readonly]
@@ -446,6 +761,25 @@ module FMOD
446
761
  end
447
762
  end
448
763
 
764
+ ##
765
+ # Dynamically creates a method for getting and/or setting a named integer
766
+ # parameter of a DSP unit.
767
+ #
768
+ # @param index [Integer] The parameter index.
769
+ # @param name [Symbol] The name of the attribute to define.
770
+ # @param options [Hash] The options hash.
771
+ #
772
+ # @option options [Boolean] :readonly (false) Flag indicating if a setter
773
+ # function will be defined or not.
774
+ # @option options [Boolean] :write_only (false) Flag indicating if a
775
+ # getter will be defined or not.
776
+ # @option options [Integer] :min (nil) If defined will clamp any given
777
+ # value to the specified minimum value.
778
+ # @option options [Integer] :max (nil) If defined will clamp any given
779
+ # value to the specified maximum value.
780
+ #
781
+ # @return [void]
782
+ # @api private
449
783
  def integer_param(index, name, **options)
450
784
  define_method(name) { get_integer(index) } unless options[:write_only]
451
785
  unless options[:readonly]
@@ -457,6 +791,21 @@ module FMOD
457
791
  end
458
792
  end
459
793
 
794
+ ##
795
+ # Dynamically creates a method for getting and/or setting a named boolean
796
+ # parameter of a DSP unit.
797
+ #
798
+ # @param index [Integer] The parameter index.
799
+ # @param name [Symbol] The name of the attribute to define.
800
+ # @param options [Hash] The options hash.
801
+ #
802
+ # @option options [Boolean] :readonly (false) Flag indicating if a setter
803
+ # function will be defined or not.
804
+ # @option options [Boolean] :write_only (false) Flag indicating if a
805
+ # getter will be defined or not.
806
+ #
807
+ # @return [void]
808
+ # @api private
460
809
  def bool_param(index, name, **options)
461
810
  define_method(name) { get_bool(index) } unless options[:write_only]
462
811
  unless options[:readonly]
@@ -464,6 +813,21 @@ module FMOD
464
813
  end
465
814
  end
466
815
 
816
+ ##
817
+ # Dynamically creates a method for getting and/or setting a named data
818
+ # parameter of a DSP unit.
819
+ #
820
+ # @param index [Integer] The parameter index.
821
+ # @param name [Symbol] The name of the attribute to define.
822
+ # @param options [Hash] The options hash.
823
+ #
824
+ # @option options [Boolean] :readonly (false) Flag indicating if a setter
825
+ # function will be defined or not.
826
+ # @option options [Boolean] :write_only (false) Flag indicating if a
827
+ # getter will be defined or not.
828
+ #
829
+ # @return [void]
830
+ # @api private
467
831
  def data_param(index, name, **options)
468
832
  define_method(name) { get_data(index) } unless options[:write_only]
469
833
  unless options[:readonly]
@@ -471,40 +835,5 @@ module FMOD
471
835
  end
472
836
  end
473
837
  end
474
- # def self.float_param(index, name, **options)
475
- # define_method(name) { get_float(index) } unless options[:write_only]
476
- # unless options[:readonly]
477
- # define_method("#{name}=") do |value|
478
- # value = options[:min] if options[:min] && value < options[:min]
479
- # value = options[:max] if options[:max] && value > options[:max]
480
- # set_float(index, value)
481
- # end
482
- # end
483
- # end
484
- #
485
- # def self.integer_param(index, name, **options)
486
- # define_method(name) { get_integer(index) } unless options[:write_only]
487
- # unless options[:readonly]
488
- # define_method("#{name}=") do |value|
489
- # value = options[:min] if options[:min] && value < options[:min]
490
- # value = options[:max] if options[:max] && value > options[:max]
491
- # set_float(index, value)
492
- # end
493
- # end
494
- # end
495
- #
496
- # def self.bool_param(index, name, **options)
497
- # define_method(name) { get_bool(index) } unless options[:write_only]
498
- # unless options[:readonly]
499
- # define_method("#{name}=") { |value| set_bool(index, value) }
500
- # end
501
- # end
502
- #
503
- # def self.data_param(index, name, **options)
504
- # define_method(name) { get_data(index) } unless options[:write_only]
505
- # unless options[:readonly]
506
- # define_method("#{name}=") { |value| set_data(index, value) }
507
- # end
508
- # end
509
838
  end
510
839
  end