Class: Rubygame::Sound

Inherits:
Object
  • Object
show all
Defined in:
ext/rubygame/rubygame_sound.c

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.autoload(filename) ⇒ Surface?

Searches each directory in Sound.autoload_dirs for a file with the given filename. If it finds that file, loads it and returns a Sound instance. If it doesn’t find the file, returns nil.

See Rubygame::NamedResource for more information about this functionality.

Returns:



317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'ext/rubygame/rubygame_sound.c', line 317

VALUE rg_sound_autoload( VALUE klass, VALUE namev )
{
  VALUE pathv = rb_funcall( klass, rb_intern("find_file"), 1, namev );

  if( RTEST(pathv) )
  {
    return rg_sound_load( klass, pathv );
  }
  else
  {
    return Qnil;
  }
}

.load(filename) ⇒ Object

Load the given audio file. Supported file formats are WAV, AIFF, RIFF, OGG (Ogg Vorbis), and VOC (SoundBlaster).

filename

Full or relative path to the file. (String, required)

Returns

The new Sound instance. (Sound)

May raise

SDLError, if the sound file could not be loaded.



283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
# File 'ext/rubygame/rubygame_sound.c', line 283

static VALUE rg_sound_load( VALUE klass, VALUE filename )
{
	RG_Sound *sound;

	VALUE s = rg_sound_alloc( cSound );

	Data_Get_Struct( s, RG_Sound, sound );

	char *file = StringValuePtr( filename );

	int result = _rg_sound_load( sound, file );

	if( result == -1 )
	{
		rb_raise(eSDLError, "Could not load Sound file '%s': %s",
		                    file, Mix_GetError());
	}

	return s;
}

.newObject

NOTE: Don’t use this method. Use Sound.load.

This method is not implemented. (In the future, it might be used to create a new Sound with blank audio data.)

Raises NotImplementedError.



345
346
347
348
# File 'ext/rubygame/rubygame_sound.c', line 345

static VALUE rg_sound_new( int argc, VALUE *ARGV, VALUE self )
{
	rb_raise(rb_eNotImpError, "Sound.new is not implemented yet. Use Sound.load to load a sound file.");
}

Instance Method Details

#fade_out(fade_time) ⇒ self

Fade out to silence over the given number of seconds. Once the sound is silent, it is automatically stopped.

Returns

The receiver (self).

NOTE: If the sound is currently paused, the fade will start, but you won’t be able to hear it happening unless you #unpause during the fade. Does nothing if the sound is currently stopped.

Returns:

  • (self)


676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
# File 'ext/rubygame/rubygame_sound.c', line 676

static VALUE rg_sound_fadeout( VALUE self, VALUE fade_time )
{
	RG_Sound *sound;
	Data_Get_Struct(self,  RG_Sound, sound);

	int channel = sound->channel;
	int fade_ms = (int)(1000 * NUM2DBL(fade_time));

	/* Make sure the sound actually belongs to the channel */
	if( _rg_sound_channel_check(sound) )
	{
		Mix_FadeOutChannel( channel, fade_ms );
	}

	return self;
}

#fading?(direction = :either) ⇒ Boolean

True if the Sound is currently fading in or out. See also #play and #fade_out.

direction

Check if it is fading :in, :out, or :either. (Symbol, required)

Returns:

  • (Boolean)


705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
# File 'ext/rubygame/rubygame_sound.c', line 705

static VALUE rg_sound_fadingp( int argc, VALUE *argv, VALUE self )
{
	RG_Sound *sound;
	Data_Get_Struct(self,  RG_Sound, sound);

	VALUE vdirection;
	rb_scan_args(argc, argv, "01", &vdirection);
	
	int direction;
	int channel = sound->channel;

	/* If it's not actually on a channel, return false right away. */
	if( !(_rg_sound_channel_check(sound)) )
	{
		return Qfalse;
	}

	if( RTEST(vdirection) )
	{
		if( make_symbol("in") == vdirection )
		{
			return ( (Mix_FadingChannel(channel) == MIX_FADING_IN)  ? Qtrue : Qfalse );
		}
		
		else if( make_symbol("out") == vdirection )
		{
			return ( (Mix_FadingChannel(channel) == MIX_FADING_OUT) ? Qtrue : Qfalse );
		}
		
		else if( make_symbol("either") == vdirection )
		{
			return ( (Mix_FadingChannel(channel) != MIX_NO_FADING)  ? Qtrue : Qfalse );
		}
	}

	/* default */
	return ( (Mix_FadingChannel(channel) != MIX_NO_FADING)  ? Qtrue : Qfalse );
}

#clone(other) ⇒ Object #dup(other) ⇒ Object

Create a copy of the given Sound instance. Much more memory-efficient than using #load to load the sound file again.

other

An existing Sound instance. (Sound, required)

Returns

The new Sound instance. (Sound)

NOTE: #clone and #dup do slightly different things; #clone will copy the ‘frozen’ state of the object, while #dup will create a fresh, un-frozen object.



368
369
370
371
372
373
374
375
376
377
# File 'ext/rubygame/rubygame_sound.c', line 368

static VALUE rg_sound_initialize_copy( VALUE self, VALUE other )
{
	RG_Sound *soundA, *soundB;
	Data_Get_Struct(self,  RG_Sound, soundA);
	Data_Get_Struct(other, RG_Sound, soundB);

	_rg_sound_copy( soundA, soundB );

	return self;
}

#pauseself

Pause the Sound. Unlike #stop, it can be unpaused later to resume from where it was paused. See also #unpause and #paused?.

Returns

The receiver (self).

NOTE: Does nothing if the sound is not currently playing.

Returns:

  • (self)


515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
# File 'ext/rubygame/rubygame_sound.c', line 515

static VALUE rg_sound_pause( VALUE self )
{
	RG_Sound *sound;
	Data_Get_Struct(self,  RG_Sound, sound);

	int channel = sound->channel;

	/* Make sure the sound actually belongs to the channel */
	if( _rg_sound_channel_check(sound) )
	{
		Mix_Pause( channel );
	}

	return self;
}

#paused?Boolean

True if the Sound is currently paused (not playing or stopped). See also #playing? and #stopped?.

Returns:

  • (Boolean)


569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
# File 'ext/rubygame/rubygame_sound.c', line 569

static VALUE rg_sound_pausedp( VALUE self )
{
	RG_Sound *sound;
	Data_Get_Struct(self,  RG_Sound, sound);

	int channel = sound->channel;

	/* Make sure the sound actually belongs to the channel */
	if( _rg_sound_channel_check(sound) )
	{
		/* Return true if it's "playing" (not stopped), as well as paused. */
		if( Mix_Playing(channel) && Mix_Paused(channel) )
		{
			return Qtrue;
		}
		else
		{
			return Qfalse;
		}
	}
	else
	{
		return Qfalse;
	}
}

#play(options = {}) ⇒ self

Play the Sound, optionally fading in, repeating a certain number of times (or forever), and/or stopping automatically after a certain time.

See also #pause and #stop.

options

Hash of options, listed below. (Hash, required)

:fade_in

Fade in from silence over the given number of seconds. (Numeric)

:repeats

Repeat the sound the given number of times, or forever (or until stopped) if -1. (Integer)

:stop_after

Automatically stop playing after playing for the given number of seconds. (Numeric)

Returns

The receiver (self).

May raise

SDLError, if the sound file could not be played.

NOTE: If the sound is already playing (or paused), it will be stopped and played again from the beginning.

Example:

# Fade in over 2 seconds, play 4 times (1 + 3 repeats),
# but stop playing after 5 seconds.
sound.play( :fade_in => 2, :repeats => 3, :stop_after => 5 );

Returns:

  • (self)


412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
# File 'ext/rubygame/rubygame_sound.c', line 412

static VALUE rg_sound_play( int argc, VALUE *argv, VALUE self )
{
	RG_Sound *sound;
	Data_Get_Struct(self,  RG_Sound, sound);

	VALUE options;
	rb_scan_args(argc, argv, "01", &options);

	int fade_in    =  0;
	int repeats    =  0;
	int stop_after = -1;

	/* If we got some options */
	if( RTEST(options) )
	{
		/* Make sure options is a Hash table */
		if( TYPE(options) != T_HASH )
		{
			rb_raise(rb_eTypeError, "wrong argument type %s (expected Hash)",
			         rb_obj_classname(options));
		}

		VALUE temp;

		temp = rb_hash_aref(options, make_symbol("fade_in"));
		if( RTEST(temp) )
		{
			fade_in = (int)(1000 * NUM2DBL( temp ));
		}

		temp = rb_hash_aref(options, make_symbol("repeats"));
		if( RTEST(temp) )
		{
			repeats = NUM2INT(temp);
		}

		temp = rb_hash_aref(options, make_symbol("stop_after"));
		if( RTEST(temp) )
		{
			stop_after = (int)(1000 * NUM2DBL( temp ));
		}

	}

	int result = _rg_sound_play( sound, fade_in, repeats, stop_after );

	if( result == -1 )
	{
		rb_raise(eSDLError, "Could not play Sound: %s", Mix_GetError());
	}

	return self;
}

#playing?Boolean

True if the Sound is currently playing (not paused or stopped). See also #paused? and #stopped?.

Returns:

  • (Boolean)


475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
# File 'ext/rubygame/rubygame_sound.c', line 475

static VALUE rg_sound_playingp( VALUE self )
{
	RG_Sound *sound;
	Data_Get_Struct(self,  RG_Sound, sound);

	int channel = sound->channel;

	/* Make sure the sound actually belongs to the channel */
	if( _rg_sound_channel_check(sound) )
	{
		/* Return true if it's playing, but not paused. */
		if( Mix_Playing(channel) && !Mix_Paused(channel) )
		{
			return Qtrue;
		}
		else
		{
			return Qfalse;
		}
	}
	else
	{
		return Qfalse;
	}
}

#stopself

Stop the Sound. Unlike #pause, the sound must be played again from the beginning, it cannot be resumed from it was stopped.

Returns

The receiver (self).

NOTE: Does nothing if the sound is not currently playing or paused.

Returns:

  • (self)


609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
# File 'ext/rubygame/rubygame_sound.c', line 609

static VALUE rg_sound_stop( VALUE self )
{
	RG_Sound *sound;
	Data_Get_Struct(self,  RG_Sound, sound);

	int channel = sound->channel;

	/* Make sure the sound actually belongs to the channel */
	if( _rg_sound_channel_check(sound) )
	{
		Mix_HaltChannel( channel );
	}

	return self;
}

#stopped?Boolean

True if the Sound is currently stopped (not playing or paused). See also #playing? and #paused?.

Returns:

  • (Boolean)


634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
# File 'ext/rubygame/rubygame_sound.c', line 634

static VALUE rg_sound_stoppedp( VALUE self )
{
	RG_Sound *sound;
	Data_Get_Struct(self,  RG_Sound, sound);

	int channel = sound->channel;

	/* Make sure the sound actually belongs to the channel */
	if( _rg_sound_channel_check(sound) )
	{
		/* Return true if it's not playing. */
		if( !Mix_Playing(channel) )
		{
			return Qtrue;
		}
		else
		{
			return Qfalse;
		}
	}
	else
	{
		/* If it's not on a channel... it can't be playing! */
		return Qtrue;
	}
}

#unpauseself

Unpause the Sound, if it is currently paused. Resumes from where it was paused. See also #pause and #paused?.

Returns

The receiver (self).

NOTE: Does nothing if the sound is not currently paused.

Returns:

  • (self)


544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
# File 'ext/rubygame/rubygame_sound.c', line 544

static VALUE rg_sound_unpause( VALUE self )
{
	RG_Sound *sound;
	Data_Get_Struct(self,  RG_Sound, sound);

	int channel = sound->channel;

	/* Make sure the sound actually belongs to the channel */
	if( _rg_sound_channel_check(sound) )
	{
		Mix_Resume( channel );
	}

	return self;
}

#volumeObject

Return the volume level of the sound. 0.0 is totally silent, 1.0 is full volume.

NOTE: Ignores fading in or out.



756
757
758
759
760
761
762
# File 'ext/rubygame/rubygame_sound.c', line 756

static VALUE rg_sound_getvolume( VALUE self )
{
	RG_Sound *sound;
	Data_Get_Struct(self,  RG_Sound, sound);

	return rb_float_new(sound->volume);
}

#volume=(new_vol) ⇒ Object

Set the new #volume level of the sound. 0.0 is totally silent, 1.0 is full volume.

Volume cannot be set while the sound is fading in or out. Be sure to check #fading? or rescue from SDLError when using this method.

May raise

SDLError if the sound is fading in or out.



779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
# File 'ext/rubygame/rubygame_sound.c', line 779

static VALUE rg_sound_setvolume( VALUE self, VALUE volume )
{
	RG_Sound *sound;
	Data_Get_Struct(self,  RG_Sound, sound);

	/* Change channel volume if Sound is currently assigned to a channel */
	if( _rg_sound_channel_check(sound) )
	{
		/* But only if it's not fading right now. */
		if( Mix_FadingChannel(sound->channel) == MIX_NO_FADING )
		{
			sound->volume = NUM2DBL(volume);
			Mix_Volume( sound->channel, (int)(MIX_MAX_VOLUME * sound->volume) );
		}
		else
		{
			rb_raise(eSDLError, "cannot set Sound volume while fading");
		}
	}
	else
	{
		/* Save it for later. */
		sound->volume = NUM2DBL(volume);
	}

	return volume;
}