From 748f572201afae4fd78d158b93ef2b3646e5e500 Mon Sep 17 00:00:00 2001 From: groogy Date: Wed, 24 Nov 2010 21:08:40 +0000 Subject: [PATCH] Finished SoundBuffer. Also adding files for SoundStream and Sound, not completed yet! git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1706 4e206d99-4929-0410-ac5d-dfc041789085 --- bindings/ruby/sfml-audio/audio/Sound.cpp | 56 ++++ bindings/ruby/sfml-audio/audio/Sound.hpp | 31 ++ .../ruby/sfml-audio/audio/SoundBuffer.cpp | 276 ++++++++++++++++++ .../ruby/sfml-audio/audio/SoundBuffer.hpp | 31 ++ .../ruby/sfml-audio/audio/SoundStream.cpp | 141 +++++++++ .../ruby/sfml-audio/audio/SoundStream.hpp | 31 ++ 6 files changed, 566 insertions(+) create mode 100644 bindings/ruby/sfml-audio/audio/Sound.cpp create mode 100644 bindings/ruby/sfml-audio/audio/Sound.hpp create mode 100644 bindings/ruby/sfml-audio/audio/SoundBuffer.cpp create mode 100644 bindings/ruby/sfml-audio/audio/SoundBuffer.hpp create mode 100644 bindings/ruby/sfml-audio/audio/SoundStream.cpp create mode 100644 bindings/ruby/sfml-audio/audio/SoundStream.hpp diff --git a/bindings/ruby/sfml-audio/audio/Sound.cpp b/bindings/ruby/sfml-audio/audio/Sound.cpp new file mode 100644 index 000000000..bebd5d583 --- /dev/null +++ b/bindings/ruby/sfml-audio/audio/Sound.cpp @@ -0,0 +1,56 @@ +/* rbSFML - Copyright (c) 2010 Henrik Valter Vogelius Hansson - groogy@groogy.se + * This software is provided 'as-is', without any express or + * implied warranty. In no event will the authors be held + * liable for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute + * it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; + * you must not claim that you wrote the original software. + * If you use this software in a product, an acknowledgment + * in the product documentation would be appreciated but + * is not required. + * + * 2. Altered source versions must be plainly marked as such, + * and must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any + * source distribution. + */ + +#include "Sound.hpp" +#include "Vector3.hpp" +#include "main.hpp" +#include + +VALUE globalSoundClass; + +/* External classes */ +extern VALUE globalVector3Class; +extern VALUE globalSoundSourceClass; + +static VALUE Sound_New( int argc, VALUE *args, VALUE self ) +{ + sf::Sound *object = new sf::Sound(); +} + +void Init_Sound( void ) +{ +/* SFML namespace which contains the classes of this module. */ + VALUE sfml = rb_define_module( "SFML" ); +/* Base class defining a sound's properties. + * + * SFML::SoundSource is not meant to be used directly, it only serves as a common base for all audio objects that can + * live in the audio environment. + * + * It defines several properties for the sound: pitch, volume, position, attenuation, etc. All of them can be changed + * at any time with no impact on performances. + */ + globalSoundClass = rb_define_class_under( sfml, "Sound", globalSoundSourceClass ); + + // Instance methods + + // Aliases +} diff --git a/bindings/ruby/sfml-audio/audio/Sound.hpp b/bindings/ruby/sfml-audio/audio/Sound.hpp new file mode 100644 index 000000000..1e33a1772 --- /dev/null +++ b/bindings/ruby/sfml-audio/audio/Sound.hpp @@ -0,0 +1,31 @@ +/* rbSFML - Copyright (c) 2010 Henrik Valter Vogelius Hansson - groogy@groogy.se + * This software is provided 'as-is', without any express or + * implied warranty. In no event will the authors be held + * liable for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute + * it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; + * you must not claim that you wrote the original software. + * If you use this software in a product, an acknowledgment + * in the product documentation would be appreciated but + * is not required. + * + * 2. Altered source versions must be plainly marked as such, + * and must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any + * source distribution. + */ + +#ifndef SFML_RUBYEXT_SOUND_HEADER_ +#define SFML_RUBYEXT_SOUND_HEADER_ + +#include "ruby.h" + +// Ruby initiation function +void Init_Sound( void ); + +#endif // SFML_RUBYEXT_SOUND_HEADER_ diff --git a/bindings/ruby/sfml-audio/audio/SoundBuffer.cpp b/bindings/ruby/sfml-audio/audio/SoundBuffer.cpp new file mode 100644 index 000000000..a6c7898cb --- /dev/null +++ b/bindings/ruby/sfml-audio/audio/SoundBuffer.cpp @@ -0,0 +1,276 @@ +/* rbSFML - Copyright (c) 2010 Henrik Valter Vogelius Hansson - groogy@groogy.se + * This software is provided 'as-is', without any express or + * implied warranty. In no event will the authors be held + * liable for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute + * it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; + * you must not claim that you wrote the original software. + * If you use this software in a product, an acknowledgment + * in the product documentation would be appreciated but + * is not required. + * + * 2. Altered source versions must be plainly marked as such, + * and must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any + * source distribution. + */ + +#include "SoundBuffer.hpp" +#include "main.hpp" +#include + +VALUE globalSoundBufferClass; + +/* Free a heap allocated object + * Not accessible trough ruby directly! + */ +static void SoundBuffer_Free( sf::SoundBuffer *anObject ) +{ + delete anObject; +} + +/* call-seq: + * sound_buffer.loadFromFile( filename ) -> true or false + * + * Load the sound buffer from a file. + * + * Here is a complete list of all the supported audio formats: ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, + * ircam, w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + */ +static VALUE SoundBuffer_LoadFromFile( VALUE self, VALUE aFileName ) +{ + sf::SoundBuffer *object = NULL; + Data_Get_Struct( self, sf::SoundBuffer, object ); + if( object->LoadFromFile( rb_string_value_cstr( &aFileName ) ) == true ) + { + return Qtrue; + } + else + { + return Qfalse; + } +} + +/* call-seq: + * sound_buffer.loadFromSamples( samples, samplesCount, channelsCount, sampleRate ) -> true or false + * + * Load the sound buffer from an array of audio samples. + * + * The assumed format of the audio samples is 16 bits signed integer. + */ +static VALUE SoundBuffer_LoadFromSamples( VALUE self, VALUE someSamples, VALUE aSamplesCount, VALUE aChannelsCount, VALUE aSampleRate ) +{ + const unsigned int rawSamplesCount = FIX2UINT( aSamplesCount ); + const unsigned int rawChannelsCount = FIX2UINT( aChannelsCount ); + const unsigned int rawSampleRate = FIX2UINT( aSampleRate ); + VALIDATE_CLASS( someSamples, rb_cArray, "samples" ); + sf::Int16 * const tempData = new sf::Int16[rawSamplesCount]; + VALUE samples = rb_funcall( someSamples, rb_intern("flatten"), 0 ); + for(unsigned long index = 0; index < rawSamplesCount; index++) + { + sf::Int16 val = NUM2INT( rb_ary_entry( samples, index ) ); + tempData[index] = val; + } + + sf::SoundBuffer *object = NULL; + Data_Get_Struct( self, sf::SoundBuffer, object ); + bool result = object->LoadFromSamples( tempData, rawSamplesCount, rawChannelsCount, rawSampleRate ); + delete[] tempData; + + if( result == true ) + { + return Qtrue; + } + else + { + return Qfalse; + } +} + +/* call-seq: + * sound_buffer.saveToFile( filename ) -> true or false + * + * Save the sound buffer to an audio file. + * + * Here is a complete list of all the supported audio formats: ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, + * w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + */ +static VALUE SoundBuffer_SaveToFile( VALUE self, VALUE aFileName ) +{ + sf::SoundBuffer *object = NULL; + Data_Get_Struct( self, sf::SoundBuffer, object ); + if( object->SaveToFile( rb_string_value_cstr( &aFileName ) ) == true ) + { + return Qtrue; + } + else + { + return Qfalse; + } +} + +/* call-seq: + * image.getSamples() -> array of samples + * + * Get the array of audio samples stored in the buffer. + * + * The format of the returned samples is 16 bits signed integer. The total number of samples in this array is given + * by the getSamplesCount() function. + */ +static VALUE SoundBuffer_GetSamples( VALUE self ) +{ + sf::SoundBuffer *object = NULL; + Data_Get_Struct( self, sf::SoundBuffer, object ); + + const unsigned int samplesCount = object->GetSamplesCount(); + const sf::Int16 *const samplesPtr = object->GetSamples(); + VALUE samples = rb_ary_new2( samplesCount ); + for(unsigned long index = 0; index < samplesCount; index++) + { + rb_ary_store( samples, index, INT2FIX( samplesPtr[index] ) ); + } + + return samples; +} + +static VALUE SoundBuffer_GetSamplesCount( VALUE self ) +{ + sf::SoundBuffer *object = NULL; + Data_Get_Struct( self, sf::SoundBuffer, object ); + return INT2FIX( object->GetSamplesCount() ); +} + +static VALUE SoundBuffer_GetSampleRate( VALUE self ) +{ + sf::SoundBuffer *object = NULL; + Data_Get_Struct( self, sf::SoundBuffer, object ); + return INT2FIX( object->GetSampleRate() ); +} + +static VALUE SoundBuffer_GetChannelsCount( VALUE self ) +{ + sf::SoundBuffer *object = NULL; + Data_Get_Struct( self, sf::SoundBuffer, object ); + return INT2FIX( object->GetChannelsCount() ); +} + +static VALUE SoundBuffer_GetDuration( VALUE self ) +{ + sf::SoundBuffer *object = NULL; + Data_Get_Struct( self, sf::SoundBuffer, object ); + return rb_float_new( object->GetDuration() ); +} + +/* call-seq: + * SoundBuffer.new() -> sound_buffer + * + * Creates an sound buffer instance for us. + */ +static VALUE SoundBuffer_New( int argc, VALUE *args, VALUE aKlass ) +{ + sf::SoundBuffer *object = new sf::SoundBuffer(); + VALUE rbData = Data_Wrap_Struct( aKlass, 0, SoundBuffer_Free, object ); + rb_obj_call_init( rbData, argc, args ); + return rbData; +} + +void Init_SoundBuffer( void ) +{ +/* SFML namespace which contains the classes of this module. */ + VALUE sfml = rb_define_module( "SFML" ); +/* Storage for audio samples defining a sound. + * + * A sound buffer holds the data of a sound, which is an array of audio samples. + * + * A sample is a 16 bits signed integer that defines the amplitude of the sound at a given time. The sound is then + * restituted by playing these samples at a high rate (for example, 44100 samples per second is the standard rate used + * for playing CDs). In short, audio samples are like image pixels, and a SFML::SoundBuffer is similar to a SFML::Image. + * + * A sound buffer can be loaded from a file (see loadFromFile() for the complete list of supported formats), from + * memory or directly from an array of samples. It can also be saved back to a file. + * + * Sound buffers alone are not very useful: they hold the audio data but cannot be played. To do so, you need to use + * the SFML::Sound class, which provides functions to play/pause/stop the sound as well as changing the way it is + * outputted (volume, pitch, 3D position, ...). This separation allows more flexibility and better performances: + * indeed a SFML::SoundBuffer is a heavy resource, and any operation on it is slow (often too slow for real-time + * applications). On the other side, a SFML::Sound is a lightweight object, which can use the audio data of a sound + * buffer and change the way it is played without actually modifying that data. Note that it is also possible to bind + * several SFML::Sound instances to the same SFML::SoundBuffer. + * + * It is important to note that the SFML::Sound instance doesn't copy the buffer that it uses, it only keeps a reference + * to it. Thus, a SFML::SoundBuffer must not be destructed while it is used by a SFML::Sound (i.e. never write a function + * that uses a local SFML::SoundBuffer instance for loading a sound). + * + * Usage example: + * + * # Declare a new sound buffer + * buffer = SFML::SoundBuffer.new + * + * # Load it from a file + * if buffer.loadFromFile( "sound.wav" ) == false + * # error... + * end + * + * # Create a sound source and bind it to the buffer + * sound1 = SFML::Sound.new + * sound1.setBuffer( buffer ) + * + * # Play the sound + * sound1.play() + * + * # Create another sound source bound to the same buffer + * sound2 = SFML::Sound.new + * sound2.setBuffer( buffer ) + * + * # Play it with a higher pitch -- the first sound remains unchanged + * sound2.setPitch( 2 ) + * sound2.play() + */ + globalSoundBufferClass = rb_define_class_under( sfml, "SoundBuffer", rb_cObject ); + + // Class methods + rb_define_singleton_method( globalSoundBufferClass, "new", SoundBuffer_New, -1 ); + + // Instance methods + rb_define_method( globalSoundBufferClass, "loadFromFile", SoundBuffer_LoadFromFile, 1 ); + rb_define_method( globalSoundBufferClass, "loadFromSamples", SoundBuffer_LoadFromSamples, 4 ); + rb_define_method( globalSoundBufferClass, "saveToFile", SoundBuffer_SaveToFile, 1 ); + rb_define_method( globalSoundBufferClass, "getSamples", SoundBuffer_GetSamples, 0 ); + rb_define_method( globalSoundBufferClass, "getSamplesCount", SoundBuffer_GetSamplesCount, 0 ); + rb_define_method( globalSoundBufferClass, "getSampleRate", SoundBuffer_GetSampleRate, 0 ); + rb_define_method( globalSoundBufferClass, "getChannelsCount", SoundBuffer_GetChannelsCount, 0 ); + rb_define_method( globalSoundBufferClass, "getDuration", SoundBuffer_GetDuration, 0 ); + + // Instance Aliases + rb_define_alias( globalSoundBufferClass, "load_from_file", "loadFromFile" ); + rb_define_alias( globalSoundBufferClass, "loadFile", "loadFromFile" ); + rb_define_alias( globalSoundBufferClass, "load_file", "loadFromFile" ); + rb_define_alias( globalSoundBufferClass, "load_from_samples", "loadFromSamples" ); + rb_define_alias( globalSoundBufferClass, "loadSamples", "loadFromSamples" ); + rb_define_alias( globalSoundBufferClass, "load_samples", "loadFromSamples" ); + rb_define_alias( globalSoundBufferClass, "save_to_file", "saveToFile" ); + rb_define_alias( globalSoundBufferClass, "save", "saveToFile" ); + + rb_define_alias( globalSoundBufferClass, "get_samples", "getSamples" ); + rb_define_alias( globalSoundBufferClass, "samples", "getSamples" ); + + rb_define_alias( globalSoundBufferClass, "get_samples_count", "getSamplesCount" ); + rb_define_alias( globalSoundBufferClass, "samples_count", "getSamplesCount" ); + rb_define_alias( globalSoundBufferClass, "samplesCount", "getSamplesCount" ); + + rb_define_alias( globalSoundBufferClass, "get_sample_rate", "getSampleRate" ); + rb_define_alias( globalSoundBufferClass, "sample_rate", "getSampleRate" ); + rb_define_alias( globalSoundBufferClass, "sampleRate", "getSampleRate" ); + + rb_define_alias( globalSoundBufferClass, "get_channels_count", "getChannelsCount" ); + rb_define_alias( globalSoundBufferClass, "channels_count", "getChannelsCount" ); + rb_define_alias( globalSoundBufferClass, "channelsCount", "getChannelsCount" ); + + rb_define_alias( globalSoundBufferClass, "get_duration", "getDuration" ); + rb_define_alias( globalSoundBufferClass, "duration", "getDuration" ); +} diff --git a/bindings/ruby/sfml-audio/audio/SoundBuffer.hpp b/bindings/ruby/sfml-audio/audio/SoundBuffer.hpp new file mode 100644 index 000000000..329d8673b --- /dev/null +++ b/bindings/ruby/sfml-audio/audio/SoundBuffer.hpp @@ -0,0 +1,31 @@ +/* rbSFML - Copyright (c) 2010 Henrik Valter Vogelius Hansson - groogy@groogy.se + * This software is provided 'as-is', without any express or + * implied warranty. In no event will the authors be held + * liable for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute + * it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; + * you must not claim that you wrote the original software. + * If you use this software in a product, an acknowledgment + * in the product documentation would be appreciated but + * is not required. + * + * 2. Altered source versions must be plainly marked as such, + * and must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any + * source distribution. + */ + +#ifndef SFML_RUBYEXT_SOUND_BUFFER_HEADER_ +#define SFML_RUBYEXT_SOUND_BUFFER_HEADER_ + +#include "ruby.h" + +// Ruby initiation function +void Init_SoundBuffer( void ); + +#endif // SFML_RUBYEXT_SOUND_BUFFER_HEADER_ diff --git a/bindings/ruby/sfml-audio/audio/SoundStream.cpp b/bindings/ruby/sfml-audio/audio/SoundStream.cpp new file mode 100644 index 000000000..4c2538380 --- /dev/null +++ b/bindings/ruby/sfml-audio/audio/SoundStream.cpp @@ -0,0 +1,141 @@ +/* rbSFML - Copyright (c) 2010 Henrik Valter Vogelius Hansson - groogy@groogy.se + * This software is provided 'as-is', without any express or + * implied warranty. In no event will the authors be held + * liable for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute + * it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; + * you must not claim that you wrote the original software. + * If you use this software in a product, an acknowledgment + * in the product documentation would be appreciated but + * is not required. + * + * 2. Altered source versions must be plainly marked as such, + * and must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any + * source distribution. + */ + +#include "SoundStream.hpp" +#include "main.hpp" +#include + +VALUE globalSoundStreamClass; + +static VALUE SoundStream_GetAttenuation( VALUE self ) +{ + sf::SoundStream *object = NULL; + Data_Get_Struct( self, sf::SoundStream, object ); + return rb_float_new( object->GetAttenuation() ); +} + +static VALUE SoundStream_GetChannelsCount( VALUE self ) +{ + sf::SoundStream *object = NULL; + Data_Get_Struct( self, sf::SoundStream, object ); + return INT2FIX( object->GetChannelsCount() ); +} + +static VALUE SoundStream_GetLoop( VALUE self ) +{ + sf::SoundStream *object = NULL; + Data_Get_Struct( self, sf::SoundStream, object ); + return ( object->GetLoop() == true ? Qtrue : Qfalse ); +} + +static VALUE SoundStream_GetMinDistance( VALUE self ) +{ + sf::SoundStream *object = NULL; + Data_Get_Struct( self, sf::SoundStream, object ); + return rb_float_new( object->GetMinDistance() ); +} + +static VALUE SoundStream_GetPitch( VALUE self ) +{ + sf::SoundStream *object = NULL; + Data_Get_Struct( self, sf::SoundStream, object ); + return rb_float_new( object->GetPitch() ); +} + + +static void DefineStatusEnum( void ) +{ + rb_define_const( globalSoundStreamClass, "Stopped", INT2FIX( sf::SoundStream::Stopped ) ); + rb_define_const( globalSoundStreamClass, "Paused", INT2FIX( sf::SoundStream::Paused ) ); + rb_define_const( globalSoundStreamClass, "Playing", INT2FIX( sf::SoundStream::Playing ) ); +} + +void Init_SoundStream( void ) +{ +/* SFML namespace which contains the classes of this module. */ + VALUE sfml = rb_define_module( "SFML" ); +/* Abstract base class for streamed audio sources. + * + * Unlike audio buffers (see SFML::SoundBuffer), audio streams are never completely loaded in memory. + * + * Instead, the audio data is acquired continuously while the stream is playing. This behaviour allows to play a sound + * with no loading delay, and keeps the memory consumption very low. + * + * Sound sources that need to be streamed are usually big files (compressed audio musics that would eat hundreds of MB + * in memory) or files that would take a lot of time to be received (sounds played over the network). + * + * SFML::SoundStream is a base class that doesn't care about the stream source, which is left to the derived class. + * SFML provides a built-in specialization for big files (see SFML::Music). No network stream source is provided, but you + * can write your own by combining this class with the network module. + * + * A derived class has to override two virtual functions: + * + * - onGetData fills a new chunk of audio data to be played + * - onSeek changes the current playing position in the source + * + * It is important to note that each SoundStream is played in its own separate thread, so that the streaming loop + * doesn't block the rest of the program. In particular, the onGetData and onSeek virtual functions may sometimes be + * called from this separate thread. It is important to keep this in mind, because you may have to take care of + * synchronization issues if you share data between threads. + * + * Usage example: + * + * class CustomStream < SFML::SoundStream + * def open( location ) + * # Open the source and get audio settings + * ... + * channelsCount = ... + * sampleRate = ... + * + * # Initialize the stream -- important! + * initialize( channelsCount, sampleRate ) + * end + * + * def onGetData( data ) + * # Fill the chunk with audio data from the stream source + * data.Samples = ...; + * data.NbSamples = ...; + * + * # Return true to continue playing + * return true; + * end + * + * def onSeek( timeOffset ) + * # Change the current position in the stream source + * ... + * end + * end + * + * # Usage + * CustomStream stream; + * stream.open( "path/to/stream" ) + * stream.play + */ + globalSoundStreamClass = rb_define_class_under( sfml, "SoundStream", rb_cObject ); + DefineStatusEnum(); + + // Class methods + + // Instance methods + + // Aliases +} diff --git a/bindings/ruby/sfml-audio/audio/SoundStream.hpp b/bindings/ruby/sfml-audio/audio/SoundStream.hpp new file mode 100644 index 000000000..382905f27 --- /dev/null +++ b/bindings/ruby/sfml-audio/audio/SoundStream.hpp @@ -0,0 +1,31 @@ +/* rbSFML - Copyright (c) 2010 Henrik Valter Vogelius Hansson - groogy@groogy.se + * This software is provided 'as-is', without any express or + * implied warranty. In no event will the authors be held + * liable for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute + * it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; + * you must not claim that you wrote the original software. + * If you use this software in a product, an acknowledgment + * in the product documentation would be appreciated but + * is not required. + * + * 2. Altered source versions must be plainly marked as such, + * and must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any + * source distribution. + */ + +#ifndef SFML_RUBYEXT_SOUND_STREAM_HEADER_ +#define SFML_RUBYEXT_SOUND_STREAM_HEADER_ + +#include "ruby.h" + +// Ruby initiation function +void Init_SoundStream( void ); + +#endif // SFML_RUBYEXT_SOUND_STREAM_HEADER_