diff --git a/CMakeLists.txt b/CMakeLists.txt index 2af2f32..cd1e91f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,7 @@ message(STATUS "Found ASSIMP in ${ASSIMP_INCLUDE_DIR}") # message(STATUS "Found GLEW in ${GLEW_INCLUDE_DIR}") if(WIN32) - set(LIBS glfw3 opengl32 assimp freetype) + set(LIBS glfw3 opengl32 assimp freetype irrKlang) elseif(UNIX AND NOT APPLE) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall") find_package(OpenGL REQUIRED) @@ -162,9 +162,8 @@ set(6.pbr set(7.in_practice 1.debugging - # due to trickier build setups (other libs rarely used everywhere else) these examples won't compile through CMake, but source code is available. 2.text_rendering - # 3.2d_game + 3.2d_game ) diff --git a/dlls/ikpMP3.dll b/dlls/ikpMP3.dll new file mode 100644 index 0000000..b913400 Binary files /dev/null and b/dlls/ikpMP3.dll differ diff --git a/dlls/irrKlang.dll b/dlls/irrKlang.dll new file mode 100644 index 0000000..3d6fdc5 Binary files /dev/null and b/dlls/irrKlang.dll differ diff --git a/includes/irrKlang/ik_ESoundEngineOptions.h b/includes/irrKlang/ik_ESoundEngineOptions.h new file mode 100644 index 0000000..df65607 --- /dev/null +++ b/includes/irrKlang/ik_ESoundEngineOptions.h @@ -0,0 +1,78 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __E_IRRKLANG_SOUND_ENGINE_OPTIONS_H_INCLUDED__ +#define __E_IRRKLANG_SOUND_ENGINE_OPTIONS_H_INCLUDED__ + +namespace irrklang +{ + //! An enumeration for all options for starting up the sound engine + /** When using createIrrKlangDevice, use a combination of this these + as 'options' parameter to start up the engine. By default, irrKlang + uses ESEO_DEFAULT_OPTIONS, which is set to the combination + ESEO_MULTI_THREADED | ESEO_LOAD_PLUGINS | ESEO_USE_3D_BUFFERS | ESEO_PRINT_DEBUG_INFO_TO_DEBUGGER | ESEO_PRINT_DEBUG_INFO_TO_STDOUT. */ + enum E_SOUND_ENGINE_OPTIONS + { + //! If specified (default), it will make irrKlang run in a separate thread. + /** Using this flag, irrKlang will update + all streams, sounds, 3d positions and whatever automaticly. You also don't need to call ISoundEngine::update() + if irrKlang is running multithreaded. However, if you want to run irrKlang in the same thread + as your application (for easier debugging for example), don't set this. But you need to call ISoundEngine::update() + as often as you can (at least about 2-3 times per second) to make irrKlang update everything correctly then. */ + ESEO_MULTI_THREADED = 0x01, + + //! If the window of the application doesn't have the focus, irrKlang will be silent if this has been set. + /** This will only work when irrKlang is using the DirectSound output driver. */ + ESEO_MUTE_IF_NOT_FOCUSED = 0x02, + + //! Automaticly loads external plugins when starting up. + /** Plugins usually are .dll, .so or .dylib + files named for example ikpMP3.dll (= short for irrKlangPluginMP3) which are executed + after the startup of the sound engine and modify it for example to make it possible + to play back mp3 files. Plugins are being loaded from the current working directory + as well as from the position where the .exe using the irrKlang library resides. + It is also possible to load the plugins after the engine has started up using + ISoundEngine::loadPlugins(). */ + ESEO_LOAD_PLUGINS = 0x04, + + //! Uses 3D sound buffers instead of emulating them when playing 3d sounds (default). + /** If this flag is not specified, all buffers will by created + in 2D only and 3D positioning will be emulated in software, making the engine run + faster if hardware 3d audio is slow on the system. */ + ESEO_USE_3D_BUFFERS = 0x08, + + //! Prints debug messages to the debugger window. + /** irrKlang will print debug info and status messages to any windows debugger supporting + OutputDebugString() (like VisualStudio). + This is useful if your application does not capture any console output (see ESEO_PRINT_DEBUG_INFO_TO_STDOUT). */ + ESEO_PRINT_DEBUG_INFO_TO_DEBUGGER = 0x10, + + //! Prints debug messages to stdout (the ConsoleWindow). + /** irrKlang will print debug info and status messages stdout, the console window in Windows. */ + ESEO_PRINT_DEBUG_INFO_TO_STDOUT = 0x20, + + //! Uses linear rolloff for 3D sound. + /** If specified, instead of the default logarithmic one, irrKlang will + use a linear rolloff model which influences the attenuation + of the sounds over distance. The volume is interpolated linearly between the MinDistance + and MaxDistance, making it possible to adjust sounds more easily although this is not + physically correct. + Note that this option may not work when used together with the ESEO_USE_3D_BUFFERS + option when using Direct3D for example, irrKlang will then turn off ESEO_USE_3D_BUFFERS + automaticly to be able to use this option and write out a warning. */ + ESEO_LINEAR_ROLLOFF = 0x40, + + //! Default parameters when starting up the engine. + ESEO_DEFAULT_OPTIONS = ESEO_MULTI_THREADED | ESEO_LOAD_PLUGINS | ESEO_USE_3D_BUFFERS | ESEO_PRINT_DEBUG_INFO_TO_DEBUGGER | ESEO_PRINT_DEBUG_INFO_TO_STDOUT, + + //! Never used, it only forces the compiler to compile these enumeration values to 32 bit. + /** Don't use this. */ + ESEO_FORCE_32_BIT = 0x7fffffff + }; + +} // end namespace irrklang + + +#endif + diff --git a/includes/irrKlang/ik_ESoundOutputDrivers.h b/includes/irrKlang/ik_ESoundOutputDrivers.h new file mode 100644 index 0000000..bc3e0ea --- /dev/null +++ b/includes/irrKlang/ik_ESoundOutputDrivers.h @@ -0,0 +1,59 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __E_IRRKLANG_SOUND_OUTPUT_DRIVERS_H_INCLUDED__ +#define __E_IRRKLANG_SOUND_OUTPUT_DRIVERS_H_INCLUDED__ + +namespace irrklang +{ + //! An enumeration for all types of supported sound drivers + /** Values of this enumeration can be used as parameter when calling createIrrKlangDevice(). */ + enum E_SOUND_OUTPUT_DRIVER + { + //! Autodetects the best sound driver for the system + ESOD_AUTO_DETECT = 0, + + //! DirectSound8 sound output driver, windows only. + /** In contrast to ESOD_DIRECT_SOUND, this supports sophisticated sound effects + but may not be available on old windows versions. It behaves very similar + to ESOD_DIRECT_SOUND but also supports DX8 sound effects.*/ + ESOD_DIRECT_SOUND_8, + + //! DirectSound sound output driver, windows only. + /** This uses DirectSound 3 or above, if available. If DX8 sound effects + are needed, use ESOD_DIRECT_SOUND_8 instead. The + ESOD_DIRECT_SOUND driver may be available on more and older windows + versions than ESOD_DIRECT_SOUND_8.*/ + ESOD_DIRECT_SOUND, + + //! WinMM sound output driver, windows only. + /** Supports the ISoundMixedOutputReceiver interface using setMixedDataOutputReceiver. */ + ESOD_WIN_MM, + + //! ALSA sound output driver, linux only. + /** When using ESOD_ALSA in createIrrKlangDevice(), it is possible to set the third parameter, + 'deviceID' to the name of specific ALSA pcm device, to the irrKlang force to use this one. + Set it to 'default', or 'plug:hw' or whatever you need it to be. + Supports the ISoundMixedOutputReceiver interface using setMixedDataOutputReceiver. */ + ESOD_ALSA, + + //! Core Audio sound output driver, mac os only. + /** Supports the ISoundMixedOutputReceiver interface using setMixedDataOutputReceiver. */ + ESOD_CORE_AUDIO, + + //! Null driver, creating no sound output + ESOD_NULL, + + //! Amount of built-in sound output drivers + ESOD_COUNT, + + //! This enumeration literal is never used, it only forces the compiler to + //! compile these enumeration values to 32 bit. + ESOD_FORCE_32_BIT = 0x7fffffff + }; + +} // end namespace irrklang + +#endif + diff --git a/includes/irrKlang/ik_EStreamModes.h b/includes/irrKlang/ik_EStreamModes.h new file mode 100644 index 0000000..62d4a0f --- /dev/null +++ b/includes/irrKlang/ik_EStreamModes.h @@ -0,0 +1,31 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __E_IRRKLANG_STREAM_MODES_H_INCLUDED__ +#define __E_IRRKLANG_STREAM_MODES_H_INCLUDED__ + +namespace irrklang +{ + //! An enumeration for all types of supported stream modes + enum E_STREAM_MODE + { + //! Autodetects the best stream mode for a specified audio data. + ESM_AUTO_DETECT = 0, + + //! Streams the audio data when needed. + ESM_STREAMING, + + //! Loads the whole audio data into the memory. + ESM_NO_STREAMING, + + //! This enumeration literal is never used, it only forces the compiler to + //! compile these enumeration values to 32 bit. + ESM_FORCE_32_BIT = 0x7fffffff + }; + +} // end namespace irrklang + + +#endif + diff --git a/includes/irrKlang/ik_IAudioRecorder.h b/includes/irrKlang/ik_IAudioRecorder.h new file mode 100644 index 0000000..49b4085 --- /dev/null +++ b/includes/irrKlang/ik_IAudioRecorder.h @@ -0,0 +1,110 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __I_IRRKLANG_AUDIO_RECORDER_H_INCLUDED__ +#define __I_IRRKLANG_AUDIO_RECORDER_H_INCLUDED__ + +#include "ik_IRefCounted.h" +#include "ik_ISoundSource.h" + + +namespace irrklang +{ + class ICapturedAudioDataReceiver; + + //! Interface to an audio recorder. Create it using the createIrrKlangAudioRecorder() function. + /** It creates sound sources into an ISoundEngine which then can be played there. + See @ref recordingAudio for an example on how to use this. */ + class IAudioRecorder : public virtual IRefCounted + { + public: + + //! Starts recording audio. + /** Clears all possibly previously recorded buffered audio data and starts to record. + When finished recording audio data, call stopRecordingAudio(). + All recorded audio data gets stored into an internal audio buffer, which + can then be accessed for example using addSoundSourceFromRecordedAudio() or + getRecordedAudioData(). For recording audio data not into an internal audio + buffer, use startRecordingCustomHandledAudio(). + \param sampleRate: Sample rate of the recorded audio. + \param sampleFormat: Sample format of the recorded audio. + \param channelCount: Amount of audio channels. + \return Returns true if successfully started recording and false if not.*/ + virtual bool startRecordingBufferedAudio(ik_s32 sampleRate=22000, + ESampleFormat sampleFormat=ESF_S16, + ik_s32 channelCount=1) = 0; + + //! Starts recording audio. + /** Clears all possibly previously recorded buffered audio data and starts to record + audio data, which is delivered to a custom user callback interface. + When finished recording audio data, call stopRecordingAudio(). If instead of + recording the data to the receiver interface recording into a managed buffer + is wished, use startRecordingBufferedAudio() instead. + \param receiver: Interface to be implemented by the user, gets called once for each + captured audio data chunk. + \param sampleRate: Sample rate of the recorded audio. + \param sampleFormat: Sample format of the recorded audio. + \param channelCount: Amount of audio channels. + \return Returns true if successfully started recording and false if not. */ + virtual bool startRecordingCustomHandledAudio(ICapturedAudioDataReceiver* receiver, + ik_s32 sampleRate=22000, + ESampleFormat sampleFormat=ESF_S16, + ik_s32 channelCount=1) = 0; + + //! Stops recording audio. + virtual void stopRecordingAudio() = 0; + + //! Creates a sound source for the recorded audio data. + /** The returned sound source pointer then can be used to play back the recorded audio data + using ISoundEngine::play2D(). This method only will succeed if the audio was recorded using + startRecordingBufferedAudio() and audio recording is currently stopped. + \param soundName Name of the virtual sound file (e.g. "someRecordedAudio"). You can also use this + name when calling play3D() or play2D(). */ + virtual ISoundSource* addSoundSourceFromRecordedAudio(const char* soundName) = 0; + + //! Clears recorded audio data buffer, freeing memory. + /** This method will only succeed if audio recording is currently stopped. */ + virtual void clearRecordedAudioDataBuffer() = 0; + + //! Returns if the recorder is currently recording audio. + virtual bool isRecording() = 0; + + //! Returns the audio format of the recorded audio data. + /** Also contains informations about the length of the recorded audio stream. */ + virtual SAudioStreamFormat getAudioFormat() = 0; + + //! Returns a pointer to the recorded audio data. + /** This method will only succeed if audio recording is currently stopped and + something was recorded previously using startRecordingBufferedAudio(). + The lenght of the buffer can be retrieved using + getAudioFormat().getSampleDataSize(). Note that the pointer is only valid + as long as not clearRecordedAudioDataBuffer() is called or another sample is + recorded.*/ + virtual void* getRecordedAudioData() = 0; + + //! returns the name of the sound driver, like 'ALSA' for the alsa device. + /** Possible returned strings are "NULL", "ALSA", "CoreAudio", "winMM", + "DirectSound" and "DirectSound8". */ + virtual const char* getDriverName() = 0; + }; + + + //! Interface to be implemented by the user if access to the recorded audio data is needed. + /** Is used as parameter in IAudioRecorder::startRecordingCustomHandledAudio. */ + class ICapturedAudioDataReceiver : public IRefCounted + { + public: + + //! Gets called once for each captured audio data chunk. + /** See IAudioRecorder::startRecordingCustomHandledAudio for details. + \param audioData: Pointer to a part of the recorded audio data + \param lengthInBytes: Amount of bytes in the audioData buffer.*/ + virtual void OnReceiveAudioDataStreamChunk(unsigned char* audioData, unsigned long lengthInBytes) = 0; + }; + + +} // end namespace irrklang + + +#endif diff --git a/includes/irrKlang/ik_IAudioStream.h b/includes/irrKlang/ik_IAudioStream.h new file mode 100644 index 0000000..97bfbd4 --- /dev/null +++ b/includes/irrKlang/ik_IAudioStream.h @@ -0,0 +1,49 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __I_IRRKLANG_AUDIO_STREAM_H_INCLUDED__ +#define __I_IRRKLANG_AUDIO_STREAM_H_INCLUDED__ + +#include "ik_IRefCounted.h" +#include "ik_SAudioStreamFormat.h" + +namespace irrklang +{ + + +//! Reads and decodes audio data into an usable audio stream for the ISoundEngine +class IAudioStream : public IRefCounted +{ +public: + + //! destructor + virtual ~IAudioStream() {}; + + //! returns format of the audio stream + virtual SAudioStreamFormat getFormat() = 0; + + //! sets the position of the audio stream. + /** For example to let the stream be read from the beginning of the file again, + setPosition(0) would be called. This is usually done be the sound engine to + loop a stream after if has reached the end. Return true if sucessful and 0 if not. + \param pos: Position in frames.*/ + virtual bool setPosition(ik_s32 pos) = 0; + + //! returns true if the audio stream is seekable + /* Some file formats like (MODs) don't support seeking */ + virtual bool getIsSeekingSupported() { return true; } + + //! tells the audio stream to read frameCountToRead audio frames into the specified buffer + /** \param target: Target data buffer to the method will write the read frames into. The + specified buffer will be at least getFormat().getFrameSize()*frameCountToRead bytes big. + \param frameCountToRead: amount of frames to be read. + \returns Returns amount of frames really read. Should be frameCountToRead in most cases. */ + virtual ik_s32 readFrames(void* target, ik_s32 frameCountToRead) = 0; +}; + + +} // end namespace irrklang + +#endif + diff --git a/includes/irrKlang/ik_IAudioStreamLoader.h b/includes/irrKlang/ik_IAudioStreamLoader.h new file mode 100644 index 0000000..dd90ae2 --- /dev/null +++ b/includes/irrKlang/ik_IAudioStreamLoader.h @@ -0,0 +1,40 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __I_IRRKLANG_AUDIO_STREAM_LOADER_H_INCLUDED__ +#define __I_IRRKLANG_AUDIO_STREAM_LOADER_H_INCLUDED__ + +#include "ik_IRefCounted.h" +#include "ik_IFileReader.h" + +namespace irrklang +{ + +class IAudioStream; + +//! Class which is able to create an audio file stream from a file. +class IAudioStreamLoader : public IRefCounted +{ +public: + + //! destructor + virtual ~IAudioStreamLoader() {}; + + //! Returns true if the file maybe is able to be loaded by this class. + /** This decision should be based only on the file extension (e.g. ".wav"). The given + filename string is guaranteed to be lower case. */ + virtual bool isALoadableFileExtension(const ik_c8* fileName) = 0; + + //! Creates an audio file input stream from a file + /** \return Pointer to the created audio stream. Returns 0 if loading failed. + If you no longer need the stream, you should call IAudioFileStream::drop(). + See IRefCounted::drop() for more information. */ + virtual IAudioStream* createAudioStream(IFileReader* file) = 0; +}; + + +} // end namespace irrklang + +#endif + diff --git a/includes/irrKlang/ik_IFileFactory.h b/includes/irrKlang/ik_IFileFactory.h new file mode 100644 index 0000000..4160acb --- /dev/null +++ b/includes/irrKlang/ik_IFileFactory.h @@ -0,0 +1,41 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __I_IRRKLANG_FILE_FACTORY_H_INCLUDED__ +#define __I_IRRKLANG_FILE_FACTORY_H_INCLUDED__ + +#include "ik_IRefCounted.h" + +namespace irrklang +{ + class IFileReader; + + //! Interface to overwrite file access in irrKlang. + /** Derive your own class from IFileFactory, overwrite the createFileReader() + method and return your own implemented IFileReader to overwrite file access of irrKlang. + Use ISoundEngine::addFileFactory() to let irrKlang know about your class. + Example code can be found in the tutorial 04.OverrideFileAccess. + */ + class IFileFactory : public virtual IRefCounted + { + public: + + virtual ~IFileFactory() {}; + + //! Opens a file for read access. + /** Derive your own class from IFileFactory, overwrite this + method and return your own implemented IFileReader to overwrite file access of irrKlang. + Use ISoundEngine::addFileFactory() to let irrKlang know about your class. + Example code can be found in the tutorial 04.OverrideFileAccess. + \param filename Name of file to open. + \return Returns a pointer to the created file interface. + The returned pointer should be dropped when no longer needed. + See IRefCounted::drop() for more information. Returns 0 if file cannot be opened. */ + virtual IFileReader* createFileReader(const ik_c8* filename) = 0; + }; + +} // end namespace irrklang + +#endif + diff --git a/includes/irrKlang/ik_IFileReader.h b/includes/irrKlang/ik_IFileReader.h new file mode 100644 index 0000000..818fe1a --- /dev/null +++ b/includes/irrKlang/ik_IFileReader.h @@ -0,0 +1,50 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __I_IRRKLANG_READ_FILE_H_INCLUDED__ +#define __I_IRRKLANG_READ_FILE_H_INCLUDED__ + +#include "ik_IRefCounted.h" + +namespace irrklang +{ + + //! Interface providing read acess to a file. + class IFileReader : public virtual IRefCounted + { + public: + + virtual ~IFileReader() {}; + + //! Reads an amount of bytes from the file. + //! \param buffer: Pointer to buffer where to read bytes will be written to. + //! \param sizeToRead: Amount of bytes to read from the file. + //! \return Returns how much bytes were read. + virtual ik_s32 read(void* buffer, ik_u32 sizeToRead) = 0; + + //! Changes position in file, returns true if successful. + //! \param finalPos: Destination position in the file. + //! \param relativeMovement: If set to true, the position in the file is + //! changed relative to current position. Otherwise the position is changed + //! from beginning of file. + //! \return Returns true if successful, otherwise false. + virtual bool seek(ik_s32 finalPos, bool relativeMovement = false) = 0; + + //! Returns size of file. + //! \return Returns the size of the file in bytes. + virtual ik_s32 getSize() = 0; + + //! Returns the current position in the file. + //! \return Returns the current position in the file in bytes. + virtual ik_s32 getPos() = 0; + + //! Returns name of file. + //! \return Returns the file name as zero terminated character string. + virtual const ik_c8* getFileName() = 0; + }; + +} // end namespace irrklang + +#endif + diff --git a/includes/irrKlang/ik_IRefCounted.h b/includes/irrKlang/ik_IRefCounted.h new file mode 100644 index 0000000..f86e8b9 --- /dev/null +++ b/includes/irrKlang/ik_IRefCounted.h @@ -0,0 +1,119 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __I_IRRKLANG_IREFERENCE_COUNTED_H_INCLUDED__ +#define __I_IRRKLANG_IREFERENCE_COUNTED_H_INCLUDED__ + +#include "ik_irrKlangTypes.h" + +namespace irrklang +{ + //! Base class of most objects of the irrKlang. + /** This class provides reference counting through the methods grab() and drop(). + It also is able to store a debug string for every instance of an object. + Most objects of irrKlang are derived from IRefCounted, and so they are reference counted. + + When you receive an object in irrKlang (for example an ISound using play2D() or + play3D()), and you no longer need the object, you have + to call drop(). This will destroy the object, if grab() was not called + in another part of you program, because this part still needs the object. + Note, that you only don't need to call drop() for all objects you receive, it + will be explicitely noted in the documentation. + + A simple example: + + If you want to play a sound, you may want to call the method + ISoundEngine::play2D. You call + ISound* mysound = engine->play2D("foobar.mp3", false, false true); + If you no longer need the sound interface, call mysound->drop(). The + sound may still play on after this because the engine still has a reference + to that sound, but you can be sure that it's memory will be released as soon + the sound is no longer used. + + If you want to add a sound source, you may want to call a method + ISoundEngine::addSoundSourceFromFile. You do this like + ISoundSource* mysource = engine->addSoundSourceFromFile("example.jpg"); + You will not have to drop the pointer to the source, because + sound sources are managed by the engine (it will live as long as the sound engine) and + the documentation says so. + */ + class IRefCounted + { + public: + + //! Constructor. + IRefCounted() + : ReferenceCounter(1) + { + } + + //! Destructor. + virtual ~IRefCounted() + { + } + + //! Grabs the object. Increments the reference counter by one. + //! Someone who calls grab() to an object, should later also call + //! drop() to it. If an object never gets as much drop() as grab() + //! calls, it will never be destroyed. + //! The IRefCounted class provides a basic reference counting mechanism + //! with its methods grab() and drop(). Most objects of irrklang + //! are derived from IRefCounted, and so they are reference counted. + //! + //! When you receive an object in irrKlang (for example an ISound using play2D() or + //! play3D()), and you no longer need the object, you have + //! to call drop(). This will destroy the object, if grab() was not called + //! in another part of you program, because this part still needs the object. + //! Note, that you only don't need to call drop() for all objects you receive, it + //! will be explicitely noted in the documentation. + //! + //! A simple example: + //! + //! If you want to play a sound, you may want to call the method + //! ISoundEngine::play2D. You call + //! ISound* mysound = engine->play2D("foobar.mp3", false, false true); + //! If you no longer need the sound interface, call mysound->drop(). The + //! sound may still play on after this because the engine still has a reference + //! to that sound, but you can be sure that it's memory will be released as soon + //! the sound is no longer used. + void grab() { ++ReferenceCounter; } + + //! When you receive an object in irrKlang (for example an ISound using play2D() or + //! play3D()), and you no longer need the object, you have + //! to call drop(). This will destroy the object, if grab() was not called + //! in another part of you program, because this part still needs the object. + //! Note, that you only don't need to call drop() for all objects you receive, it + //! will be explicitely noted in the documentation. + //! + //! A simple example: + //! + //! If you want to play a sound, you may want to call the method + //! ISoundEngine::play2D. You call + //! ISound* mysound = engine->play2D("foobar.mp3", false, false true); + //! If you no longer need the sound interface, call mysound->drop(). The + //! sound may still play on after this because the engine still has a reference + //! to that sound, but you can be sure that it's memory will be released as soon + //! the sound is no longer used. + bool drop() + { + --ReferenceCounter; + + if (!ReferenceCounter) + { + delete this; + return true; + } + + return false; + } + + private: + + ik_s32 ReferenceCounter; + }; + +} // end namespace irr + +#endif + diff --git a/includes/irrKlang/ik_ISound.h b/includes/irrKlang/ik_ISound.h new file mode 100644 index 0000000..3f267b9 --- /dev/null +++ b/includes/irrKlang/ik_ISound.h @@ -0,0 +1,194 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __I_IRRKLANG_SOUND_H_INCLUDED__ +#define __I_IRRKLANG_SOUND_H_INCLUDED__ + +#include "ik_IVirtualRefCounted.h" +#include "ik_ISoundEffectControl.h" +#include "ik_vec3d.h" + + +namespace irrklang +{ + class ISoundSource; + class ISoundStopEventReceiver; + + //! Represents a sound which is currently played. + /** The sound can be stopped, its volume or pan changed, effects added/removed + and similar using this interface. + Creating sounds is done using ISoundEngine::play2D() or ISoundEngine::play3D(). + More informations about the source of a sound can be obtained from the ISoundSource + interface. */ + class ISound : public IVirtualRefCounted + { + public: + + //! returns source of the sound which stores the filename and other informations about that sound + /** \return Returns the sound source poitner of this sound. May return 0 if the sound source + has been removed.*/ + virtual ISoundSource* getSoundSource() = 0; + + //! returns if the sound is paused + virtual void setIsPaused( bool paused = true) = 0; + + //! returns if the sound is paused + virtual bool getIsPaused() = 0; + + //! Will stop the sound and free its resources. + /** If you just want to pause the sound, use setIsPaused(). + After calling stop(), isFinished() will usually return true. + Be sure to also call ->drop() once you are done.*/ + virtual void stop() = 0; + + //! returns volume of the sound, a value between 0 (mute) and 1 (full volume). + /** (this volume gets multiplied with the master volume of the sound engine + and other parameters like distance to listener when played as 3d sound) */ + virtual ik_f32 getVolume() = 0; + + //! sets the volume of the sound, a value between 0 (mute) and 1 (full volume). + /** This volume gets multiplied with the master volume of the sound engine + and other parameters like distance to listener when played as 3d sound. */ + virtual void setVolume(ik_f32 volume) = 0; + + //! sets the pan of the sound. Takes a value between -1 and 1, 0 is center. + virtual void setPan(ik_f32 pan) = 0; + + //! returns the pan of the sound. Takes a value between -1 and 1, 0 is center. + virtual ik_f32 getPan() = 0; + + //! returns if the sound has been started to play looped + virtual bool isLooped() = 0; + + //! changes the loop mode of the sound. + /** If the sound is playing looped and it is changed to not-looped, then it + will stop playing after the loop has finished. + If it is not looped and changed to looped, the sound will start repeating to be + played when it reaches its end. + Invoking this method will not have an effect when the sound already has stopped. */ + virtual void setIsLooped(bool looped) = 0; + + //! returns if the sound has finished playing. + /** Don't mix this up with isPaused(). isFinished() returns if the sound has been + finished playing. If it has, is maybe already have been removed from the playing list of the + sound engine and calls to any other of the methods of ISound will not have any result. + If you call stop() to a playing sound will result that this function will return true + when invoked. */ + virtual bool isFinished() = 0; + + //! Sets the minimal distance if this is a 3D sound. + /** Changes the distance at which the 3D sound stops getting louder. This works + like this: As a listener approaches a 3D sound source, the sound gets louder. + Past a certain point, it is not reasonable for the volume to continue to increase. + Either the maximum (zero) has been reached, or the nature of the sound source + imposes a logical limit. This is the minimum distance for the sound source. + Similarly, the maximum distance for a sound source is the distance beyond + which the sound does not get any quieter. + The default minimum distance is 1, the default max distance is a huge number like 1000000000.0f. */ + virtual void setMinDistance(ik_f32 min) = 0; + + //! Returns the minimal distance if this is a 3D sound. + /** See setMinDistance() for details. */ + virtual ik_f32 getMinDistance() = 0; + + //! Sets the maximal distance if this is a 3D sound. + /** Changing this value is usually not necessary. Use setMinDistance() instead. + Don't change this value if you don't know what you are doing: This value causes the sound + to stop attenuating after it reaches the max distance. Most people think that this sets the + volume of the sound to 0 after this distance, but this is not true. Only change the + minimal distance (using for example setMinDistance()) to influence this. + The maximum distance for a sound source is the distance beyond which the sound does not get any quieter. + The default minimum distance is 1, the default max distance is a huge number like 1000000000.0f. */ + virtual void setMaxDistance(ik_f32 max) = 0; + + //! Returns the maximal distance if this is a 3D sound. + /** See setMaxDistance() for details. */ + virtual ik_f32 getMaxDistance() = 0; + + //! sets the position of the sound in 3d space + virtual void setPosition(vec3df position) = 0; + + //! returns the position of the sound in 3d space + virtual vec3df getPosition() = 0; + + //! sets the position of the sound in 3d space, needed for Doppler effects. + /** To use doppler effects use ISound::setVelocity to set a sounds velocity, + ISoundEngine::setListenerPosition() to set the listeners velocity and + ISoundEngine::setDopplerEffectParameters() to adjust two parameters influencing + the doppler effects intensity. */ + virtual void setVelocity(vec3df vel) = 0; + + //! returns the velocity of the sound in 3d space, needed for Doppler effects. + /** To use doppler effects use ISound::setVelocity to set a sounds velocity, + ISoundEngine::setListenerPosition() to set the listeners velocity and + ISoundEngine::setDopplerEffectParameters() to adjust two parameters influencing + the doppler effects intensity. */ + virtual vec3df getVelocity() = 0; + + //! returns the current play position of the sound in milliseconds. + /** \return Returns -1 if not implemented or possible for this sound for example + because it already has been stopped and freed internally or similar. */ + virtual ik_u32 getPlayPosition() = 0; + + //! sets the current play position of the sound in milliseconds. + /** \param pos Position in milliseconds. Must be between 0 and the value returned + by getPlayPosition(). + \return Returns true successful. False is returned for example if the sound already finished + playing and is stopped or the audio source is not seekable, for example if it + is an internet stream or a a file format not supporting seeking (a .MOD file for example). + A file can be tested if it can bee seeking using ISoundSource::getIsSeekingSupported(). */ + virtual bool setPlayPosition(ik_u32 pos) = 0; + + //! Sets the playback speed (frequency) of the sound. + /** Plays the sound at a higher or lower speed, increasing or decreasing its + frequency which makes it sound lower or higher. + Note that this feature is not available on all sound output drivers (it is on the + DirectSound drivers at least), and it does not work together with the + 'enableSoundEffects' parameter of ISoundEngine::play2D and ISoundEngine::play3D when + using DirectSound. + \param speed Factor of the speed increase or decrease. 2 is twice as fast, + 0.5 is only half as fast. The default is 1.0. + \return Returns true if sucessful, false if not. The current sound driver might not + support changing the playBack speed, or the sound was started with the + 'enableSoundEffects' parameter. */ + virtual bool setPlaybackSpeed(ik_f32 speed = 1.0f) = 0; + + //! Returns the playback speed set by setPlaybackSpeed(). Default: 1.0f. + /** See setPlaybackSpeed() for details */ + virtual ik_f32 getPlaybackSpeed() = 0; + + //! returns the play length of the sound in milliseconds. + /** Returns -1 if not known for this sound for example because its decoder + does not support length reporting or it is a file stream of unknown size. + Note: You can also use ISoundSource::getPlayLength() to get the length of + a sound without actually needing to play it. */ + virtual ik_u32 getPlayLength() = 0; + + //! Returns the sound effect control interface for this sound. + /** Sound effects such as Chorus, Distorsions, Echo, Reverb and similar can + be controlled using this. The interface pointer is only valid as long as the ISound pointer is valid. + If the ISound pointer gets dropped (IVirtualRefCounted::drop()), the ISoundEffects + may not be used any more. + \return Returns a pointer to the sound effects interface if available. The sound + has to be started via ISoundEngine::play2D() or ISoundEngine::play3D(), + with the flag enableSoundEffects=true, otherwise 0 will be returned. Note that + if the output driver does not support sound effects, 0 will be returned as well.*/ + virtual ISoundEffectControl* getSoundEffectControl() = 0; + + //! Sets the sound stop event receiver, an interface which gets called if a sound has finished playing. + /** This event is guaranteed to be called when the sound or sound stream is finished, + either because the sound reached its playback end, its sound source was removed, + ISoundEngine::stopAllSounds() has been called or the whole engine was deleted. + There is an example on how to use events in irrklang at @ref events . + \param receiver Interface to a user implementation of the sound receiver. This interface + should be as long valid as the sound exists or another stop event receiver is set. + Set this to null to set no sound stop event receiver. + \param userData: A iser data pointer, can be null. */ + virtual void setSoundStopEventReceiver(ISoundStopEventReceiver* reciever, void* userData=0) = 0; + }; + +} // end namespace irrklang + + +#endif diff --git a/includes/irrKlang/ik_ISoundDeviceList.h b/includes/irrKlang/ik_ISoundDeviceList.h new file mode 100644 index 0000000..bda2090 --- /dev/null +++ b/includes/irrKlang/ik_ISoundDeviceList.h @@ -0,0 +1,41 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __I_IRRKLANG_SOUND_DEVICE_LIST_H_INCLUDED__ +#define __I_IRRKLANG_SOUND_DEVICE_LIST_H_INCLUDED__ + +#include "ik_IRefCounted.h" + +namespace irrklang +{ + +//! A list of sound devices for a sound driver. Use irrklang::createSoundDeviceList() to create this list. +/** The function createIrrKlangDevice() has a parameter 'deviceID' which takes the value returned by +ISoundDeviceList::getDeviceID() and uses that device then. +The list of devices in ISoundDeviceList usually also includes the default device which is the first +entry and has an empty deviceID string ("") and the description "default device". +There is some example code on how to use the ISoundDeviceList in @ref enumeratingDevices.*/ +class ISoundDeviceList : public IRefCounted +{ +public: + + //! Returns amount of enumerated devices in the list. + virtual ik_s32 getDeviceCount() = 0; + + //! Returns the ID of the device. Use this string to identify this device in createIrrKlangDevice(). + /** \param index Index of the device, a value between 0 and ISoundDeviceList::getDeviceCount()-1. + \return Returns a pointer to a string identifying the device. The string will only as long valid + as long as the ISoundDeviceList exists. */ + virtual const char* getDeviceID(ik_s32 index) = 0; + + //! Returns description of the device. + /** \param index Index of the device, a value between 0 and ISoundDeviceList::getDeviceCount()-1. */ + virtual const char* getDeviceDescription(ik_s32 index) = 0; +}; + + +} // end namespace irrklang + +#endif + diff --git a/includes/irrKlang/ik_ISoundEffectControl.h b/includes/irrKlang/ik_ISoundEffectControl.h new file mode 100644 index 0000000..86ade35 --- /dev/null +++ b/includes/irrKlang/ik_ISoundEffectControl.h @@ -0,0 +1,243 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __I_IRRKLANG_SOUND_EFFECT_CONTROL_H_INCLUDED__ +#define __I_IRRKLANG_SOUND_EFFECT_CONTROL_H_INCLUDED__ + +#include "ik_IVirtualRefCounted.h" +#include "ik_vec3d.h" + + +namespace irrklang +{ + //! Interface to control the active sound effects (echo, reverb,...) of an ISound object, a playing sound. + /** Sound effects such as chorus, distorsions, echo, reverb and similar can + be controlled using this. An instance of this interface can be obtained via + ISound::getSoundEffectControl(). The sound containing this interface has to be started via + ISoundEngine::play2D() or ISoundEngine::play3D() with the flag enableSoundEffects=true, + otherwise no acccess to this interface will be available. + For the DirectSound driver, these are effects available since DirectSound8. For most + effects, sounds should have a sample rate of 44 khz and should be at least + 150 milli seconds long for optimal quality when using the DirectSound driver. + Note that the interface pointer is only valid as long as + the ISound pointer is valid. If the ISound pointer gets dropped (IVirtualRefCounted::drop()), + the ISoundEffects may not be used any more. */ + class ISoundEffectControl + { + public: + + //! Disables all active sound effects + virtual void disableAllEffects() = 0; + + //! Enables the chorus sound effect or adjusts its values. + /** Chorus is a voice-doubling effect created by echoing the + original sound with a slight delay and slightly modulating the delay of the echo. + If this sound effect is already enabled, calling this only modifies the parameters of the active effect. + \param fWetDryMix Ratio of wet (processed) signal to dry (unprocessed) signal. Minimal Value:0, Maximal Value:100.0f; + \param fDepth Percentage by which the delay time is modulated by the low-frequency oscillator, in hundredths of a percentage point. Minimal Value:0, Maximal Value:100.0f; + \param fFeedback Percentage of output signal to feed back into the effect's input. Minimal Value:-99, Maximal Value:99.0f; + \param fFrequency Frequency of the LFO. Minimal Value:0, Maximal Value:10.0f; + \param sinusWaveForm True for sinus wave form, false for triangle. + \param fDelay Number of milliseconds the input is delayed before it is played back. Minimal Value:0, Maximal Value:20.0f; + \param lPhase Phase differential between left and right LFOs. Possible values: + -180, -90, 0, 90, 180 + \return Returns true if successful. */ + virtual bool enableChorusSoundEffect(ik_f32 fWetDryMix = 50, + ik_f32 fDepth = 10, + ik_f32 fFeedback = 25, + ik_f32 fFrequency = 1.1, + bool sinusWaveForm = true, + ik_f32 fDelay = 16, + ik_s32 lPhase = 90) = 0; + + //! removes the sound effect from the sound + virtual void disableChorusSoundEffect() = 0; + + //! returns if the sound effect is active on the sound + virtual bool isChorusSoundEffectEnabled() = 0; + + //! Enables the Compressor sound effect or adjusts its values. + /** Compressor is a reduction in the fluctuation of a signal above a certain amplitude. + If this sound effect is already enabled, calling this only modifies the parameters of the active effect. + \param fGain Output gain of signal after Compressor. Minimal Value:-60, Maximal Value:60.0f; + \param fAttack Time before Compressor reaches its full value. Minimal Value:0.01, Maximal Value:500.0f; + \param fRelease Speed at which Compressor is stopped after input drops below fThreshold. Minimal Value:50, Maximal Value:3000.0f; + \param fThreshold Point at which Compressor begins, in decibels. Minimal Value:-60, Maximal Value:0.0f; + \param fRatio Compressor ratio. Minimal Value:1, Maximal Value:100.0f; + \param fPredelay Time after lThreshold is reached before attack phase is started, in milliseconds. Minimal Value:0, Maximal Value:4.0f; + \return Returns true if successful. */ + virtual bool enableCompressorSoundEffect( ik_f32 fGain = 0, + ik_f32 fAttack = 10, + ik_f32 fRelease = 200, + ik_f32 fThreshold = -20, + ik_f32 fRatio = 3, + ik_f32 fPredelay = 4) = 0; + + //! removes the sound effect from the sound + virtual void disableCompressorSoundEffect() = 0; + + //! returns if the sound effect is active on the sound + virtual bool isCompressorSoundEffectEnabled() = 0; + + //! Enables the Distortion sound effect or adjusts its values. + /** Distortion is achieved by adding harmonics to the signal in such a way that, + If this sound effect is already enabled, calling this only modifies the parameters of the active effect. + as the level increases, the top of the waveform becomes squared off or clipped. + \param fGain Amount of signal change after distortion. Minimal Value:-60, Maximal Value:0; + \param fEdge Percentage of distortion intensity. Minimal Value:0, Maximal Value:100; + \param fPostEQCenterFrequency Center frequency of harmonic content addition. Minimal Value:100, Maximal Value:8000; + \param fPostEQBandwidth Width of frequency band that determines range of harmonic content addition. Minimal Value:100, Maximal Value:8000; + \param fPreLowpassCutoff Filter cutoff for high-frequency harmonics attenuation. Minimal Value:100, Maximal Value:8000; + \return Returns true if successful. */ + virtual bool enableDistortionSoundEffect(ik_f32 fGain = -18, + ik_f32 fEdge = 15, + ik_f32 fPostEQCenterFrequency = 2400, + ik_f32 fPostEQBandwidth = 2400, + ik_f32 fPreLowpassCutoff = 8000) = 0; + + //! removes the sound effect from the sound + virtual void disableDistortionSoundEffect() = 0; + + //! returns if the sound effect is active on the sound + virtual bool isDistortionSoundEffectEnabled() = 0; + + //! Enables the Echo sound effect or adjusts its values. + /** An echo effect causes an entire sound to be repeated after a fixed delay. + If this sound effect is already enabled, calling this only modifies the parameters of the active effect. + \param fWetDryMix Ratio of wet (processed) signal to dry (unprocessed) signal. Minimal Value:0, Maximal Value:100.0f; + \param fFeedback Percentage of output fed back into input. Minimal Value:0, Maximal Value:100.0f; + \param fLeftDelay Delay for left channel, in milliseconds. Minimal Value:1, Maximal Value:2000.0f; + \param fRightDelay Delay for right channel, in milliseconds. Minimal Value:1, Maximal Value:2000.0f; + \param lPanDelay Value that specifies whether to swap left and right delays with each successive echo. Minimal Value:0, Maximal Value:1; + \return Returns true if successful. */ + virtual bool enableEchoSoundEffect(ik_f32 fWetDryMix = 50, + ik_f32 fFeedback = 50, + ik_f32 fLeftDelay = 500, + ik_f32 fRightDelay = 500, + ik_s32 lPanDelay = 0) = 0; + + //! removes the sound effect from the sound + virtual void disableEchoSoundEffect() = 0; + + //! returns if the sound effect is active on the sound + virtual bool isEchoSoundEffectEnabled() = 0; + + //! Enables the Flanger sound effect or adjusts its values. + /** Flange is an echo effect in which the delay between the original + signal and its echo is very short and varies over time. The result is + sometimes referred to as a sweeping sound. The term flange originated + with the practice of grabbing the flanges of a tape reel to change the speed. + If this sound effect is already enabled, calling this only modifies the parameters of the active effect. + \param fWetDryMix Ratio of wet (processed) signal to dry (unprocessed) signal. Minimal Value:0, Maximal Value:100.0f; + \param fDepth Percentage by which the delay time is modulated by the low-frequency oscillator, in hundredths of a percentage point. Minimal Value:0, Maximal Value:100.0f; + \param fFeedback Percentage of output signal to feed back into the effect's input. Minimal Value:-99, Maximal Value:99.0f; + \param fFrequency Frequency of the LFO. Minimal Value:0, Maximal Value:10.0f; + \param triangleWaveForm True for triangle wave form, false for square. + \param fDelay Number of milliseconds the input is delayed before it is played back. Minimal Value:0, Maximal Value:20.0f; + \param lPhase Phase differential between left and right LFOs. Possible values: + -180, -90, 0, 90, 180 + \return Returns true if successful. */ + virtual bool enableFlangerSoundEffect(ik_f32 fWetDryMix = 50, + ik_f32 fDepth = 100, + ik_f32 fFeedback = -50, + ik_f32 fFrequency = 0.25f, + bool triangleWaveForm = true, + ik_f32 fDelay = 2, + ik_s32 lPhase = 0) = 0; + + //! removes the sound effect from the sound + virtual void disableFlangerSoundEffect() = 0; + + //! returns if the sound effect is active on the sound + virtual bool isFlangerSoundEffectEnabled() = 0; + + //! Enables the Gargle sound effect or adjusts its values. + /** The gargle effect modulates the amplitude of the signal. + If this sound effect is already enabled, calling this only modifies the parameters of the active effect. + \param rateHz Rate of modulation, in Hertz. Minimal Value:1, Maximal Value:1000 + \param sinusWaveForm True for sinus wave form, false for triangle. + \return Returns true if successful. */ + virtual bool enableGargleSoundEffect(ik_s32 rateHz = 20, bool sinusWaveForm = true) = 0; + + //! removes the sound effect from the sound + virtual void disableGargleSoundEffect() = 0; + + //! returns if the sound effect is active on the sound + virtual bool isGargleSoundEffectEnabled() = 0; + + //! Enables the Interactive 3D Level 2 reverb sound effect or adjusts its values. + /** An implementation of the listener properties in the I3DL2 specification. Source properties are not supported. + If this sound effect is already enabled, calling this only modifies the parameters of the active effect. + \param lRoom Attenuation of the room effect, in millibels (mB). Interval: [-10000, 0] Default: -1000 mB + \param lRoomHF Attenuation of the room high-frequency effect. Interval: [-10000, 0] default: 0 mB + \param flRoomRolloffFactor Rolloff factor for the reflected signals. Interval: [0.0, 10.0] default: 0.0 + \param flDecayTime Decay time, in seconds. Interval: [0.1, 20.0] default: 1.49s + \param flDecayHFRatio Ratio of the decay time at high frequencies to the decay time at low frequencies. Interval: [0.1, 2.0] default: 0.83 + \param lReflections Attenuation of early reflections relative to lRoom. Interval: [-10000, 1000] default: -2602 mB + \param flReflectionsDelay Delay time of the first reflection relative to the direct path in seconds. Interval: [0.0, 0.3] default: 0.007 s + \param lReverb Attenuation of late reverberation relative to lRoom, in mB. Interval: [-10000, 2000] default: 200 mB + \param flReverbDelay Time limit between the early reflections and the late reverberation relative to the time of the first reflection. Interval: [0.0, 0.1] default: 0.011 s + \param flDiffusion Echo density in the late reverberation decay in percent. Interval: [0.0, 100.0] default: 100.0 % + \param flDensity Modal density in the late reverberation decay, in percent. Interval: [0.0, 100.0] default: 100.0 % + \param flHFReference Reference high frequency, in hertz. Interval: [20.0, 20000.0] default: 5000.0 Hz + \return Returns true if successful. */ + virtual bool enableI3DL2ReverbSoundEffect(ik_s32 lRoom = -1000, + ik_s32 lRoomHF = -100, + ik_f32 flRoomRolloffFactor = 0, + ik_f32 flDecayTime = 1.49f, + ik_f32 flDecayHFRatio = 0.83f, + ik_s32 lReflections = -2602, + ik_f32 flReflectionsDelay = 0.007f, + ik_s32 lReverb = 200, + ik_f32 flReverbDelay = 0.011f, + ik_f32 flDiffusion = 100.0f, + ik_f32 flDensity = 100.0f, + ik_f32 flHFReference = 5000.0f ) = 0; + + //! removes the sound effect from the sound + virtual void disableI3DL2ReverbSoundEffect() = 0; + + //! returns if the sound effect is active on the sound + virtual bool isI3DL2ReverbSoundEffectEnabled() = 0; + + //! Enables the ParamEq sound effect or adjusts its values. + /** Parametric equalizer amplifies or attenuates signals of a given frequency. + If this sound effect is already enabled, calling this only modifies the parameters of the active effect. + \param fCenter Center frequency, in hertz, The default value is 8000. Minimal Value:80, Maximal Value:16000.0f + \param fBandwidth Bandwidth, in semitones, The default value is 12. Minimal Value:1.0f, Maximal Value:36.0f + \param fGain Gain, default value is 0. Minimal Value:-15.0f, Maximal Value:15.0f + \return Returns true if successful. */ + virtual bool enableParamEqSoundEffect(ik_f32 fCenter = 8000, + ik_f32 fBandwidth = 12, + ik_f32 fGain = 0) = 0; + + //! removes the sound effect from the sound + virtual void disableParamEqSoundEffect() = 0; + + //! returns if the sound effect is active on the sound + virtual bool isParamEqSoundEffectEnabled() = 0; + + //! Enables the Waves Reverb sound effect or adjusts its values. + /** \param fInGain Input gain of signal, in decibels (dB). Min/Max: [-96.0,0.0] Default: 0.0 dB. + If this sound effect is already enabled, calling this only modifies the parameters of the active effect. + \param fReverbMix Reverb mix, in dB. Min/Max: [-96.0,0.0] Default: 0.0 dB + \param fReverbTime Reverb time, in milliseconds. Min/Max: [0.001,3000.0] Default: 1000.0 ms + \param fHighFreqRTRatio High-frequency reverb time ratio. Min/Max: [0.001,0.999] Default: 0.001 + \return Returns true if successful. */ + virtual bool enableWavesReverbSoundEffect(ik_f32 fInGain = 0, + ik_f32 fReverbMix = 0, + ik_f32 fReverbTime = 1000, + ik_f32 fHighFreqRTRatio = 0.001f) = 0; + + //! removes the sound effect from the sound + virtual void disableWavesReverbSoundEffect() = 0; + + //! returns if the sound effect is active on the sound + virtual bool isWavesReverbSoundEffectEnabled() = 0; + }; + +} // end namespace irrklang + + +#endif diff --git a/includes/irrKlang/ik_ISoundEngine.h b/includes/irrKlang/ik_ISoundEngine.h new file mode 100644 index 0000000..fdb25e8 --- /dev/null +++ b/includes/irrKlang/ik_ISoundEngine.h @@ -0,0 +1,436 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __I_IRRKLANG_SOUND_ENGINE_H_INCLUDED__ +#define __I_IRRKLANG_SOUND_ENGINE_H_INCLUDED__ + +#include "ik_IRefCounted.h" +#include "ik_vec3d.h" +#include "ik_ISoundSource.h" +#include "ik_ISound.h" +#include "ik_EStreamModes.h" +#include "ik_IFileFactory.h" +#include "ik_ISoundMixedOutputReceiver.h" + + +namespace irrklang +{ + class IAudioStreamLoader; + struct SInternalAudioInterface; + + //! Interface to the sound engine, for playing 3d and 2d sound and music. + /** This is the main interface of irrKlang. You usually would create this using + the createIrrKlangDevice() function. + */ + class ISoundEngine : public virtual irrklang::IRefCounted + { + public: + + //! returns the name of the sound driver, like 'ALSA' for the alsa device + /** Possible returned strings are "NULL", "ALSA", "CoreAudio", "winMM", + "DirectSound" and "DirectSound8". */ + virtual const char* getDriverName() = 0; + + //! loads a sound source (if not loaded already) from a file and plays it. + /** \param sourceFileName Filename of sound, like "sounds/test.wav" or "foobar.ogg". + \param playLooped plays the sound in loop mode. If set to 'false', the sound is played once, then stopped and deleted from the internal playing list. Calls to + ISound have no effect after such a non looped sound has been stopped automaticly. + \param startPaused starts the sound paused. This implies that track=true. Use this if you want to modify some of the playing + parameters before the sound actually plays. Usually you would set this parameter to true, then use the ISound interface to + modify some of the sound parameters and then call ISound::setPaused(false); + Note: You need to call ISound::drop() when setting this parameter to true and you don't need the ISound + object anymore. See 'return' for details. + \param track Makes it possible to track the sound. Causes the method to return an ISound interface. See 'return' for details. + \param streamMode Specifies if the file should be streamed or loaded completely into memory for playing. + ESM_AUTO_DETECT sets this to autodetection. Note: if the sound has been loaded or played before into the + engine, this parameter has no effect. + \param enableSoundEffects Makes it possible to use sound effects such as chorus, distorsions, echo, + reverb and similar for this sound. Sound effects can then be controlled via ISound::getSoundEffectControl(). + Only enable if necessary. + \return Only returns a pointer to an ISound if the parameters 'track', 'startPaused' or + 'enableSoundEffects' have been set to true. Note: if this method returns an ISound as result, + you HAVE to call ISound::drop() after you don't need the ISound interface anymore. Otherwise this + will cause memory waste. This method also may return 0 altough 'track', 'startPaused' or + 'enableSoundEffects' have been set to true, if the sound could not be played.*/ + virtual ISound* play2D(const char* soundFileName, + bool playLooped = false, + bool startPaused = false, + bool track = false, + E_STREAM_MODE streamMode = ESM_AUTO_DETECT, + bool enableSoundEffects = false) = 0; + + //! Plays a sound source as 2D sound with its default settings stored in ISoundSource. + /** An ISoundSource object will be created internally when playing a sound the first time, + or can be added with getSoundSource(). + \param source The sound source, specifiying sound file source and default settings for this file. + Use the other ISoundEngine::play2D() overloads if you want to specify a filename string instead of this. + \param playLooped plays the sound in loop mode. If set to 'false', the sound is played once, then stopped and deleted from the internal playing list. Calls to + ISound have no effect after such a non looped sound has been stopped automaticly. + \param startPaused starts the sound paused. This implies that track=true. Use this if you want to modify some of the playing + parameters before the sound actually plays. Usually you would set this parameter to true, then use the ISound interface to + modify some of the sound parameters and then call ISound::setPaused(false); + Note: You need to call ISound::drop() when setting this parameter to true and you don't need the ISound + object anymore. See 'return' for details. + \param track Makes it possible to track the sound. Causes the method to return an ISound interface. See 'return' for details. + \param enableSoundEffects Makes it possible to use sound effects such as chorus, distorsions, echo, + reverb and similar for this sound. Sound effects can then be controlled via ISound::getSoundEffectControl(). + Only enable if necessary. + \return Only returns a pointer to an ISound if the parameters 'track', 'startPaused' or + 'enableSoundEffects' have been set to true. Note: if this method returns an ISound as result, + you HAVE to call ISound::drop() after you don't need the ISound interface anymore. Otherwise this + will cause memory waste. This method also may return 0 altough 'track', 'startPaused' or + 'enableSoundEffects' have been set to true, if the sound could not be played.*/ + virtual ISound* play2D(ISoundSource* source, + bool playLooped = false, + bool startPaused = false, + bool track = false, + bool enableSoundEffects = false) = 0; + + //! Loads a sound source (if not loaded already) from a file and plays it as 3D sound. + /** There is some example code on how to work with 3D sound at @ref sound3d. + \param sourceFileName Filename of sound, like "sounds/test.wav" or "foobar.ogg". + \param pos Position of the 3D sound. + \param playLooped plays the sound in loop mode. If set to 'false', the sound is played once, then stopped and deleted from the internal playing list. Calls to + ISound have no effect after such a non looped sound has been stopped automaticly. + \param startPaused starts the sound paused. This implies that track=true. Use this if you want to modify some of the playing + parameters before the sound actually plays. Usually you would set this parameter to true, then use the ISound interface to + modify some of the sound parameters and then call ISound::setPaused(false); + Note: You need to call ISound::drop() when setting this parameter to true and you don't need the ISound + object anymore. See 'return' for details. + \param track Makes it possible to track the sound. Causes the method to return an ISound interface. See 'return' for details. + \param streamMode Specifies if the file should be streamed or loaded completely into memory for playing. + ESM_AUTO_DETECT sets this to autodetection. Note: if the sound has been loaded or played before into the + engine, this parameter has no effect. + \param enableSoundEffects Makes it possible to use sound effects such as chorus, distorsions, echo, + reverb and similar for this sound. Sound effects can then be controlled via ISound::getSoundEffectControl(). + Only enable if necessary. + \return Only returns a pointer to an ISound if the parameters 'track', 'startPaused' or + 'enableSoundEffects' have been set to true. Note: if this method returns an ISound as result, + you HAVE to call ISound::drop() after you don't need the ISound interface anymore. Otherwise this + will cause memory waste. This method also may return 0 altough 'track', 'startPaused' or + 'enableSoundEffects' have been set to true, if the sound could not be played.*/ + virtual ISound* play3D(const char* soundFileName, vec3df pos, + bool playLooped = false, + bool startPaused = false, + bool track = false, + E_STREAM_MODE streamMode = ESM_AUTO_DETECT, + bool enableSoundEffects = false) = 0; + + //! Plays a sound source as 3D sound with its default settings stored in ISoundSource. + /** An ISoundSource object will be created internally when playing a sound the first time, + or can be added with getSoundSource(). There is some example code on how to work with 3D sound @ref sound3d. + \param source The sound source, specifiying sound file source and default settings for this file. + Use the other ISoundEngine::play2D() overloads if you want to specify a filename string instead of this. + \param pos Position of the 3D sound. + \param playLooped plays the sound in loop mode. If set to 'false', the sound is played once, then stopped and deleted from the internal playing list. Calls to + ISound have no effect after such a non looped sound has been stopped automaticly. + \param startPaused starts the sound paused. This implies that track=true. Use this if you want to modify some of the playing + parameters before the sound actually plays. Usually you would set this parameter to true, then use the ISound interface to + modify some of the sound parameters and then call ISound::setPaused(false); + Note: You need to call ISound::drop() when setting this parameter to true and you don't need the ISound + object anymore. See 'return' for details. + \param track Makes it possible to track the sound. Causes the method to return an ISound interface. See 'return' for details. + \param enableSoundEffects Makes it possible to use sound effects such as chorus, distorsions, echo, + reverb and similar for this sound. Sound effects can then be controlled via ISound::getSoundEffectControl(). + Only enable if necessary. + \return Only returns a pointer to an ISound if the parameters 'track', 'startPaused' or + 'enableSoundEffects' have been set to true. Note: if this method returns an ISound as result, + you HAVE to call ISound::drop() after you don't need the ISound interface anymore. Otherwise this + will cause memory waste. This method also may return 0 altough 'track', 'startPaused' or + 'enableSoundEffects' have been set to true, if the sound could not be played.*/ + virtual ISound* play3D(ISoundSource* source, vec3df pos, + bool playLooped = false, + bool startPaused = false, + bool track = false, + bool enableSoundEffects = false) = 0; + + //! Stops all currently playing sounds. + virtual void stopAllSounds() = 0; + + //! Pauses or unpauses all currently playing sounds. + virtual void setAllSoundsPaused( bool bPaused = true ) = 0; + + //! Gets a sound source by sound name. Adds the sound source as file into the sound engine if not loaded already. + /** Please note: For performance reasons most ISoundEngine implementations will + not try to load the sound when calling this method, but only when play() is called + with this sound source as parameter. + \param addIfNotFound if 'true' adds the sound source to the list and returns the interface to it + if it cannot be found in the sound source list. If 'false', returns 0 if the sound + source is not in the list and does not modify the list. Default value: true. + \return Returns the sound source or 0 if not available. + Note: Don't call drop() to this pointer, it will be managed by irrKlang and + exist as long as you don't delete irrKlang or call removeSoundSource(). However, + you are free to call grab() if you want and drop() it then later of course. */ + virtual ISoundSource* getSoundSource(const ik_c8* soundName, bool addIfNotFound=true) = 0; + + //! Returns a sound source by index. + /** \param idx: Index of the loaded sound source, must by smaller than getSoundSourceCount(). + \return Returns the sound source or 0 if not available. + Note: Don't call drop() to this pointer, it will be managed by irrKlang and + exist as long as you don't delete irrKlang or call removeSoundSource(). However, + you are free to call grab() if you want and drop() it then later of course. */ + virtual ISoundSource* getSoundSource(ik_s32 index) = 0; + + //! Returns amount of loaded sound sources. + virtual ik_s32 getSoundSourceCount() = 0; + + //! Adds sound source into the sound engine as file. + /** \param fileName Name of the sound file (e.g. "sounds/something.mp3"). You can also use this + name when calling play3D() or play2D(). + \param mode Streaming mode for this sound source + \param preload If this flag is set to false (which is default) the sound engine will + not try to load the sound file when calling this method, but only when play() is called + with this sound source as parameter. Otherwise the sound will be preloaded. + \return Returns the pointer to the added sound source or 0 if not sucessful because for + example a sound already existed with that name. If not successful, the reason will be printed + into the log. Note: Don't call drop() to this pointer, it will be managed by irrKlang and + exist as long as you don't delete irrKlang or call removeSoundSource(). However, + you are free to call grab() if you want and drop() it then later of course. */ + virtual ISoundSource* addSoundSourceFromFile(const ik_c8* fileName, E_STREAM_MODE mode=ESM_AUTO_DETECT, + bool preload=false) = 0; + + //! Adds a sound source into the sound engine as memory source. + /** Note: This method only accepts a file (.wav, .ogg, etc) which is totally loaded into memory. + If you want to add a sound source from decoded plain PCM data in memory, use addSoundSourceFromPCMData() instead. + \param memory Pointer to the memory to be treated as loaded sound file. + \param sizeInBytes Size of the memory chunk, in bytes. + \param soundName Name of the virtual sound file (e.g. "sounds/something.mp3"). You can also use this + name when calling play3D() or play2D(). Hint: If you include the extension of the original file + like .ogg, .mp3 or .wav at the end of the filename, irrKlang will be able to decide better what + file format it is and might be able to start playback faster. + \param copyMemory If set to true which is default, the memory block is copied + and stored in the engine, after calling addSoundSourceFromMemory() the memory pointer can be deleted + savely. If set to false, the memory is not copied and the user takes the responsibility that + the memory block pointed to remains there as long as the sound engine or at least this sound + source exists. + \return Returns the pointer to the added sound source or 0 if not sucessful because for example a sound already + existed with that name. If not successful, the reason will be printed into the log. + Note: Don't call drop() to this pointer, it will be managed by irrKlang and exist as long as you don't + delete irrKlang or call removeSoundSource(). However, you are free to call grab() if you + want and drop() it then later of course. */ + virtual ISoundSource* addSoundSourceFromMemory(void* memory, ik_s32 sizeInBytes, const ik_c8* soundName, + bool copyMemory=true) = 0; + + + //! Adds a sound source into the sound engine from plain PCM data in memory. + /** \param memory Pointer to the memory to be treated as loaded sound file. + \param sizeInBytes Size of the memory chunk, in bytes. + \param soundName Name of the virtual sound file (e.g. "sounds/something.mp3"). You can also use this + name when calling play3D() or play2D(). + \param copyMemory If set to true which is default, the memory block is copied + and stored in the engine, after calling addSoundSourceFromPCMData() the memory pointer can be deleted + savely. If set to true, the memory is not copied and the user takes the responsibility that + the memory block pointed to remains there as long as the sound engine or at least this sound + source exists. + \return Returns the pointer to the added sound source or 0 if not sucessful because for + example a sound already existed with that name. If not successful, the reason will be printed + into the log. */ + virtual ISoundSource* addSoundSourceFromPCMData(void* memory, ik_s32 sizeInBytes, + const ik_c8* soundName, SAudioStreamFormat format, + bool copyMemory=true) = 0; + + //! Adds a sound source as alias for an existing sound source, but with a different name or optional different default settings. + /** This is useful if you want to play multiple sounds but each sound isn't necessarily one single file. + Also useful if you want to or play the same sound using different names, volumes or min and max 3D distances. + \param baseSource The sound source where this sound source should be based on. This sound + source will use the baseSource as base to access the file and similar, but it will have its + own name and its own default settings. + \param soundName Name of the new sound source to be added. + \return Returns the pointer to the added sound source or 0 if not sucessful because for + example a sound already existed with that name. If not successful, the reason will be printed + into the log.*/ + virtual ISoundSource* addSoundSourceAlias(ISoundSource* baseSource, const ik_c8* soundName) = 0; + + //! Removes a sound source from the engine, freeing the memory it occupies. + /** This will also cause all currently playing sounds of this source to be stopped. + Also note that if the source has been removed successfully, the value returned + by getSoundSourceCount() will have been decreased by one. + Removing sound sources is only necessary if you know you won't use a lot of non-streamed + sounds again. Sound sources of streamed sounds do not cost a lot of memory.*/ + virtual void removeSoundSource(ISoundSource* source) = 0; + + //! Removes a sound source from the engine, freeing the memory it occupies. + /** This will also cause all currently playing sounds of this source to be stopped. + Also note that if the source has been removed successfully, the value returned + by getSoundSourceCount() will have been decreased by one. + Removing sound sources is only necessary if you know you won't use a lot of non-streamed + sounds again. Sound sources of streamed sounds do not cost a lot of memory. */ + virtual void removeSoundSource(const ik_c8* name) = 0; + + //! Removes all sound sources from the engine + /** This will also cause all sounds to be stopped. + Removing sound sources is only necessary if you know you won't use a lot of non-streamed + sounds again. Sound sources of streamed sounds do not cost a lot of memory. */ + virtual void removeAllSoundSources() = 0; + + //! Sets master sound volume. This value is multiplied with all sounds played. + /** \param volume 0 (silent) to 1.0f (full volume) */ + virtual void setSoundVolume(ik_f32 volume) = 0; + + //! Returns master sound volume. + /* A value between 0.0 and 1.0. Default is 1.0. Can be changed using setSoundVolume(). */ + virtual ik_f32 getSoundVolume() = 0; + + //! Sets the current listener 3d position. + /** When playing sounds in 3D, updating the position of the listener every frame should be + done using this function. + \param pos Position of the camera or listener. + \param lookdir Direction vector where the camera or listener is looking into. If you have a + camera position and a target 3d point where it is looking at, this would be cam->getTarget() - cam->getAbsolutePosition(). + \param velPerSecond The velocity per second describes the speed of the listener and + is only needed for doppler effects. + \param upvector Vector pointing 'up', so the engine can decide where is left and right. + This vector is usually (0,1,0).*/ + virtual void setListenerPosition(const vec3df& pos, + const vec3df& lookdir, + const vec3df& velPerSecond = vec3df(0,0,0), + const vec3df& upVector = vec3df(0,1,0)) = 0; + + //! Updates the audio engine. This should be called several times per frame if irrKlang was started in single thread mode. + /** This updates the 3d positions of the sounds as well as their volumes, effects, + streams and other stuff. Call this several times per frame (the more the better) if you + specified irrKlang to run single threaded. Otherwise it is not necessary to use this method. + This method is being called by the scene manager automaticly if you are using one, so + you might want to ignore this. */ + virtual void update() = 0; + + //! Returns if a sound with the specified name is currently playing. + virtual bool isCurrentlyPlaying(const char* soundName) = 0; + + //! Returns if a sound with the specified source is currently playing. + virtual bool isCurrentlyPlaying(ISoundSource* source) = 0; + + //! Stops all sounds of a specific sound source + virtual void stopAllSoundsOfSoundSource(ISoundSource* source) = 0; + + //! Registers a new audio stream loader in the sound engine. + /** Use this to enhance the audio engine to support other or new file formats. + To do this, implement your own IAudioStreamLoader interface and register it + with this method */ + virtual void registerAudioStreamLoader(IAudioStreamLoader* loader) = 0; + + //! Returns if irrKlang is running in the same thread as the application or is using multithreading. + /** This basicly returns the flag set by the user when creating the sound engine.*/ + virtual bool isMultiThreaded() const = 0; + + //! Adds a file factory to the sound engine, making it possible to override file access of the sound engine. + /** Derive your own class from IFileFactory, overwrite the createFileReader() + method and return your own implemented IFileReader to overwrite file access of irrKlang. */ + virtual void addFileFactory(IFileFactory* fileFactory) = 0; + + //! Sets the default minimal distance for 3D sounds. + /** This value influences how loud a sound is heard based on its distance. + See ISound::setMinDistance() for details about what the min distance is. + It is also possible to influence this default value for every sound file + using ISoundSource::setDefaultMinDistance(). + This method only influences the initial distance value of sounds. For changing the + distance after the sound has been started to play, use ISound::setMinDistance() and ISound::setMaxDistance(). + \param minDistance Default minimal distance for 3d sounds. The default value is 1.0f.*/ + virtual void setDefault3DSoundMinDistance(ik_f32 minDistance) = 0; + + //! Returns the default minimal distance for 3D sounds. + /** This value influences how loud a sound is heard based on its distance. + You can change it using setDefault3DSoundMinDistance(). + See ISound::setMinDistance() for details about what the min distance is. + It is also possible to influence this default value for every sound file + using ISoundSource::setDefaultMinDistance(). + \return Default minimal distance for 3d sounds. The default value is 1.0f. */ + virtual ik_f32 getDefault3DSoundMinDistance() = 0; + + //! Sets the default maximal distance for 3D sounds. + /** Changing this value is usually not necessary. Use setDefault3DSoundMinDistance() instead. + Don't change this value if you don't know what you are doing: This value causes the sound + to stop attenuating after it reaches the max distance. Most people think that this sets the + volume of the sound to 0 after this distance, but this is not true. Only change the + minimal distance (using for example setDefault3DSoundMinDistance()) to influence this. + See ISound::setMaxDistance() for details about what the max distance is. + It is also possible to influence this default value for every sound file + using ISoundSource::setDefaultMaxDistance(). + This method only influences the initial distance value of sounds. For changing the + distance after the sound has been started to play, use ISound::setMinDistance() and ISound::setMaxDistance(). + \param maxDistance Default maximal distance for 3d sounds. The default value is 1000000000.0f. */ + virtual void setDefault3DSoundMaxDistance(ik_f32 maxDistance) = 0; + + //! Returns the default maximal distance for 3D sounds. + /** This value influences how loud a sound is heard based on its distance. + You can change it using setDefault3DSoundmaxDistance(), but + changing this value is usually not necessary. This value causes the sound + to stop attenuating after it reaches the max distance. Most people think that this sets the + volume of the sound to 0 after this distance, but this is not true. Only change the + minimal distance (using for example setDefault3DSoundMinDistance()) to influence this. + See ISound::setMaxDistance() for details about what the max distance is. + It is also possible to influence this default value for every sound file + using ISoundSource::setDefaultMaxDistance(). + \return Default maximal distance for 3d sounds. The default value is 1000000000.0f. */ + virtual ik_f32 getDefault3DSoundMaxDistance() = 0; + + //! Sets a rolloff factor which influences the amount of attenuation that is applied to 3D sounds. + /** The rolloff factor can range from 0.0 to 10.0, where 0 is no rolloff. 1.0 is the default + rolloff factor set, the value which we also experience in the real world. A value of 2 would mean + twice the real-world rolloff. */ + virtual void setRolloffFactor(ik_f32 rolloff) = 0; + + //! Sets parameters affecting the doppler effect. + /** \param dopplerFactor is a value between 0 and 10 which multiplies the doppler + effect. Default value is 1.0, which is the real world doppler effect, and 10.0f + would be ten times the real world doppler effect. + \param distanceFactor is the number of meters in a vector unit. The default value + is 1.0. Doppler effects are calculated in meters per second, with this parameter, + this can be changed, all velocities and positions are influenced by this. If + the measurement should be in foot instead of meters, set this value to 0.3048f + for example.*/ + virtual void setDopplerEffectParameters(ik_f32 dopplerFactor=1.0f, ik_f32 distanceFactor=1.0f) = 0; + + //! Loads irrKlang plugins from a custom path. + /** Plugins usually are .dll, .so or .dylib + files named for example ikpMP3.dll (= short for irrKlangPluginMP3) which + make it possible to play back mp3 files. Plugins are being + loaded from the current working directory at startup of the sound engine + if the parameter ESEO_LOAD_PLUGINS is set (which it is by default), but + using this method, it is possible to load plugins from a custom path in addition. + \param path Path to the plugin directory, like "C:\games\somegamegame\irrklangplugins". + \return returns true if sucessful or fals if not, for example because the path could + not be found. */ + virtual bool loadPlugins(const ik_c8* path) = 0; + + //! Returns a pointer to internal sound engine pointers, like the DirectSound interface. + /** Use this with caution. This is only exposed to make it possible for other libraries + such as Video playback packages to extend or use the sound driver irrklang uses. */ + virtual const SInternalAudioInterface& getInternalAudioInterface() = 0; + + //! Sets the OutputMixedDataReceiver, so you can receive the pure mixed output audio data while it is being played. + /** This can be used to store the sound output as .wav file or for creating a Oscillograph or similar. + This works only with software based audio drivers, that is ESOD_WIN_MM, ESOD_ALSA, and ESOD_CORE_AUDIO. + Returns true if sucessful and fals if the current audio driver doesn't support this feature. Set this to null + again once you don't need it anymore. */ + virtual bool setMixedDataOutputReceiver(ISoundMixedOutputReceiver* receiver) = 0; + }; + + + //! structure for returning pointers to the internal audio interface. + /** Use ISoundEngine::getInternalAudioInterface() to get this. */ + struct SInternalAudioInterface + { + //! IDirectSound interface, this is not null when using the ESOD_DIRECT_SOUND audio driver + void* pIDirectSound; + + //! IDirectSound8 interface, this is not null when using the ESOD_DIRECT_SOUND8 audio driver + void* pIDirectSound8; + + //! HWaveout interface, this is not null when using the ESOD_WIN_MM audio driver + void* pWinMM_HWaveOut; + + //! ALSA PCM Handle interface, this is not null when using the ESOD_ALSA audio driver + void* pALSA_SND_PCM; + + //! AudioDeviceID handle, this is not null when using the ESOD_CORE_AUDIO audio driver + ik_u32 pCoreAudioDeciceID; + }; + + + +} // end namespace irrklang + + +#endif diff --git a/includes/irrKlang/ik_ISoundMixedOutputReceiver.h b/includes/irrKlang/ik_ISoundMixedOutputReceiver.h new file mode 100644 index 0000000..8f6d58e --- /dev/null +++ b/includes/irrKlang/ik_ISoundMixedOutputReceiver.h @@ -0,0 +1,46 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __I_IRRKLANG_SOUND_MIXED_OUTPUT_RECEIVER_H_INCLUDED__ +#define __I_IRRKLANG_SOUND_MIXED_OUTPUT_RECEIVER_H_INCLUDED__ + +#include "ik_IRefCounted.h" +#include "ik_SAudioStreamFormat.h" + + +namespace irrklang +{ + + +//! Interface to be implemented by the user, which recieves the mixed output when it it played by the sound engine. +/** This can be used to store the sound output as .wav file or for creating a Oscillograph or similar. + Simply implement your own class derived from ISoundMixedOutputReceiver and use ISoundEngine::setMixedDataOutputReceiver + to let the audio driver know about it. */ +class ISoundMixedOutputReceiver +{ +public: + + //! destructor + virtual ~ISoundMixedOutputReceiver() {}; + + //! Called when a chunk of sound has been mixed and is about to be played. + /** Note: This is called from the playing thread of the sound library, so you need to + make everything you are doing in this method thread safe. Additionally, it would + be a good idea to do nothing complicated in your implementation and return as fast as possible, + otherwise sound output may be stuttering. + \param data representing the sound frames which just have been mixed. Sound data always + consists of two interleaved sound channels at 16bit per frame. + \param byteCount Amount of bytes of the data + \param playbackrate The playback rate at samples per second (usually something like 44000). + This value will not change and always be the same for an instance of an ISoundEngine. */ + virtual void OnAudioDataReady(const void* data, int byteCount, int playbackrate) = 0; + +}; + + +} // end namespace irrklang + + +#endif + diff --git a/includes/irrKlang/ik_ISoundSource.h b/includes/irrKlang/ik_ISoundSource.h new file mode 100644 index 0000000..087d295 --- /dev/null +++ b/includes/irrKlang/ik_ISoundSource.h @@ -0,0 +1,167 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __I_IRRKLANG_IRR_SOUND_SOURCE_H_INCLUDED__ +#define __I_IRRKLANG_IRR_SOUND_SOURCE_H_INCLUDED__ + +#include "ik_IVirtualRefCounted.h" +#include "ik_vec3d.h" +#include "ik_EStreamModes.h" +#include "ik_SAudioStreamFormat.h" + + +namespace irrklang +{ + + //! A sound source describes an input file (.ogg, .mp3, .wav or similar) and its default settings. + /** It provides some informations about the sound source like the play lenght and + can have default settings for volume, distances for 3d etc. There is some example code on how + to use Sound sources at @ref soundSources.*/ + class ISoundSource : public IVirtualRefCounted + { + public: + + //! Returns the name of the sound source (usually, this is the file name) + virtual const ik_c8* getName() = 0; + + //! Sets the stream mode which should be used for a sound played from this source. + /** Note that if this is set to ESM_NO_STREAMING, the engine still might decide + to stream the sound if it is too big. The threashold for this can be + adjusted using ISoundSource::setForcedStreamingThreshold(). */ + virtual void setStreamMode(E_STREAM_MODE mode) = 0; + + //! Returns the detected or set type of the sound with wich the sound will be played. + /** Note: If the returned type is ESM_AUTO_DETECT, this mode will change after the + sound has been played the first time. */ + virtual E_STREAM_MODE getStreamMode() = 0; + + //! Returns the play length of the sound in milliseconds. + /** Returns -1 if not known for this sound for example because its decoder + does not support lenght reporting or it is a file stream of unknown size. + Note: If the sound never has been played before, the sound engine will have to open + the file and try to get the play lenght from there, so this call could take a bit depending + on the type of file. */ + virtual ik_u32 getPlayLength() = 0; + + //! Returns informations about the sound source: channel count (mono/stereo), frame count, sample rate, etc. + /** \return Returns the structure filled with 0 or negative values if not known for this sound for example because + because the file could not be opened or similar. + Note: If the sound never has been played before, the sound engine will have to open + the file and try to get the play lenght from there, so this call could take a bit depending + on the type of file. */ + virtual SAudioStreamFormat getAudioFormat() = 0; + + //! Returns if sounds played from this source will support seeking via ISound::setPlayPosition(). + /* If a sound is seekable depends on the file type and the audio format. For example MOD files + cannot be seeked currently. + \return Returns true of the sound source supports setPlayPosition() and false if not. + Note: If the sound never has been played before, the sound engine will have to open + the file and try to get the information from there, so this call could take a bit depending + on the type of file. */ + virtual bool getIsSeekingSupported() = 0; + + //! Sets the default volume for a sound played from this source. + /** The default value of this is 1.0f. + Note that the default volume is being multiplied with the master volume + of ISoundEngine, change this via ISoundEngine::setSoundVolume(). + //! \param volume 0 (silent) to 1.0f (full volume). Default value is 1.0f. */ + virtual void setDefaultVolume(ik_f32 volume=1.0f) = 0; + + //! Returns the default volume for a sound played from this source. + /** You can influence this default volume value using setDefaultVolume(). + Note that the default volume is being multiplied with the master volume + of ISoundEngine, change this via ISoundEngine::setSoundVolume(). + //! \return 0 (silent) to 1.0f (full volume). Default value is 1.0f. */ + virtual ik_f32 getDefaultVolume() = 0; + + //! sets the default minimal distance for 3D sounds played from this source. + /** This value influences how loud a sound is heard based on its distance. + See ISound::setMinDistance() for details about what the min distance is. + This method only influences the initial distance value of sounds. For changing the + distance while the sound is playing, use ISound::setMinDistance() and ISound::setMaxDistance(). + \param minDistance: Default minimal distance for 3D sounds from this source. Set it to a negative + value to let sounds of this source use the engine level default min distance, which + can be set via ISoundEngine::setDefault3DSoundMinDistance(). Default value is -1, causing + the default min distance of the sound engine to take effect. */ + virtual void setDefaultMinDistance(ik_f32 minDistance) = 0; + + //! Returns the default minimal distance for 3D sounds played from this source. + /** This value influences how loud a sound is heard based on its distance. + See ISound::setMinDistance() for details about what the minimal distance is. + \return Default minimal distance for 3d sounds from this source. If setDefaultMinDistance() + was set to a negative value, it will return the default value set in the engine, + using ISoundEngine::setDefault3DSoundMinDistance(). Default value is -1, causing + the default min distance of the sound engine to take effect. */ + virtual ik_f32 getDefaultMinDistance() = 0; + + //! Sets the default maximal distance for 3D sounds played from this source. + /** Changing this value is usually not necessary. Use setDefaultMinDistance() instead. + Don't change this value if you don't know what you are doing: This value causes the sound + to stop attenuating after it reaches the max distance. Most people think that this sets the + volume of the sound to 0 after this distance, but this is not true. Only change the + minimal distance (using for example setDefaultMinDistance()) to influence this. + See ISound::setMaxDistance() for details about what the max distance is. + This method only influences the initial distance value of sounds. For changing the + distance while the sound is played, use ISound::setMinDistance() + and ISound::setMaxDistance(). + \param maxDistance Default maximal distance for 3D sounds from this source. Set it to a negative + value to let sounds of this source use the engine level default max distance, which + can be set via ISoundEngine::setDefault3DSoundMaxDistance(). Default value is -1, causing + the default max distance of the sound engine to take effect. */ + virtual void setDefaultMaxDistance(ik_f32 maxDistance) = 0; + + //! returns the default maxmial distance for 3D sounds played from this source. + /** This value influences how loud a sound is heard based on its distance. + Changing this value is usually not necessary. Use setDefaultMinDistance() instead. + Don't change this value if you don't know what you are doing: This value causes the sound + to stop attenuating after it reaches the max distance. Most people think that this sets the + volume of the sound to 0 after this distance, but this is not true. Only change the + minimal distance (using for example setDefaultMinDistance()) to influence this. + See ISound::setMaxDistance() for details about what the max distance is. + \return Default maximal distance for 3D sounds from this source. If setDefaultMaxDistance() + was set to a negative value, it will return the default value set in the engine, + using ISoundEngine::setDefault3DSoundMaxDistance(). Default value is -1, causing + the default max distance of the sound engine to take effect. */ + virtual ik_f32 getDefaultMaxDistance() = 0; + + //! Forces the sound to be reloaded at next replay. + /** Sounds which are not played as streams are buffered to make it possible to + replay them without much overhead. If the sound file is altered after the sound + has been played the first time, the engine won't play the changed file then. + Calling this method makes the engine reload the file before the file is played + the next time.*/ + virtual void forceReloadAtNextUse() = 0; + + //! Sets the threshold size where irrKlang decides to force streaming a file independent of the user specified setting. + /** When specifying ESM_NO_STREAMING for playing back a sound file, irrKlang will + ignore this setting if the file is bigger than this threshold and stream the file + anyway. Please note that if an audio format loader is not able to return the + size of a sound source and returns -1 as length, this will be ignored as well + and streaming has to be forced. + \param threshold: New threshold. The value is specified in uncompressed bytes and its default value is + about one Megabyte. Set to 0 or a negative value to disable stream forcing. */ + virtual void setForcedStreamingThreshold(ik_s32 thresholdBytes) = 0; + + //! Returns the threshold size where irrKlang decides to force streaming a file independent of the user specified setting. + /** The value is specified in uncompressed bytes and its default value is + about one Megabyte. See setForcedStreamingThreshold() for details. */ + virtual ik_s32 getForcedStreamingThreshold() = 0; + + //! Returns a pointer to the loaded and decoded sample data. + /** \return Returns a pointer to the sample data. The data is provided in decoded PCM data. The + exact format can be retrieved using getAudioFormat(). Use getAudioFormat().getSampleDataSize() + for getting the amount of bytes. The returned pointer will only be valid as long as the sound + source exists. + This function will only return a pointer to the data if the + audio file is not streamed, namely ESM_NO_STREAMING. Otherwise this function will return 0. + Note: If the sound never has been played before, the sound engine will have to open + the file and decode audio data from there, so this call could take a bit depending + on the type of the file.*/ + virtual void* getSampleData() = 0; + }; + +} // end namespace irrklang + + +#endif diff --git a/includes/irrKlang/ik_ISoundStopEventReceiver.h b/includes/irrKlang/ik_ISoundStopEventReceiver.h new file mode 100644 index 0000000..511a8b0 --- /dev/null +++ b/includes/irrKlang/ik_ISoundStopEventReceiver.h @@ -0,0 +1,72 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __I_IRRKLANG_SOUND_STOP_EVENT_RECEIVER_H_INCLUDED__ +#define __I_IRRKLANG_SOUND_STOP_EVENT_RECEIVER_H_INCLUDED__ + +#include "ik_IRefCounted.h" +#include "ik_SAudioStreamFormat.h" + + +namespace irrklang +{ + + +//! An enumeration listing all reasons for a fired sound stop event +enum E_STOP_EVENT_CAUSE +{ + //! The sound stop event was fired because the sound finished playing + ESEC_SOUND_FINISHED_PLAYING = 0, + + //! The sound stop event was fired because the sound was stopped by the user, calling ISound::stop(). + ESEC_SOUND_STOPPED_BY_USER, + + //! The sound stop event was fired because the source of the sound was removed, for example + //! because irrKlang was shut down or the user called ISoundEngine::removeSoundSource(). + ESEC_SOUND_STOPPED_BY_SOURCE_REMOVAL, + + //! This enumeration literal is never used, it only forces the compiler to + //! compile these enumeration values to 32 bit. + ESEC_FORCE_32_BIT = 0x7fffffff +}; + + +//! Interface to be implemented by the user, which recieves sound stop events. +/** The interface has only one method to be implemented by the user: OnSoundStopped(). +Implement this interface and set it via ISound::setSoundStopEventReceiver(). +The sound stop event is guaranteed to be called when a sound or sound stream is finished, +either because the sound reached its playback end, its sound source was removed, +ISoundEngine::stopAllSounds() has been called or the whole engine was deleted. */ +class ISoundStopEventReceiver +{ +public: + + //! destructor + virtual ~ISoundStopEventReceiver() {}; + + //! Called when a sound has stopped playing. + /** This is the only method to be implemented by the user. + The sound stop event is guaranteed to be called when a sound or sound stream is finished, + either because the sound reached its playback end, its sound source was removed, + ISoundEngine::stopAllSounds() has been called or the whole engine was deleted. + Please note: Sound events will occur in a different thread when the engine runs in + multi threaded mode (default). In single threaded mode, the event will happen while + the user thread is calling ISoundEngine::update(). + \param sound: Sound which has been stopped. + \param reason: The reason why the sound stop event was fired. Usually, this will be ESEC_SOUND_FINISHED_PLAYING. + When the sound was aborded by calling ISound::stop() or ISoundEngine::stopAllSounds();, this would be + ESEC_SOUND_STOPPED_BY_USER. If irrKlang was deleted or the sound source was removed, the value is + ESEC_SOUND_STOPPED_BY_SOURCE_REMOVAL. + \param userData: userData pointer set by the user when registering the interface + via ISound::setSoundStopEventReceiver(). */ + virtual void OnSoundStopped(ISound* sound, E_STOP_EVENT_CAUSE reason, void* userData) = 0; + +}; + + +} // end namespace irrklang + + +#endif + diff --git a/includes/irrKlang/ik_IVirtualRefCounted.h b/includes/irrKlang/ik_IVirtualRefCounted.h new file mode 100644 index 0000000..86b589f --- /dev/null +++ b/includes/irrKlang/ik_IVirtualRefCounted.h @@ -0,0 +1,48 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __I_IRRKLANG_VIRTUAL_UNKNOWN_H_INCLUDED__ +#define __I_IRRKLANG_VIRTUAL_UNKNOWN_H_INCLUDED__ + +#include "ik_irrKlangTypes.h" + + +namespace irrklang +{ + + //! Reference counting base class for objects in the Irrlicht Engine similar to IRefCounted. + /** See IRefCounted for the basics of this class. + The difference to IRefCounted is that the class has to implement reference counting + for itself. + */ + class IVirtualRefCounted + { + public: + + //! Destructor. + virtual ~IVirtualRefCounted() + { + } + + //! Grabs the object. Increments the reference counter by one. + /** To be implemented by the derived class. If you don't want to + implement this, use the class IRefCounted instead. See IRefCounted::grab() for details + of this method. */ + virtual void grab() = 0; + + //! Drops the object. Decrements the reference counter by one. + /** To be implemented by the derived class. If you don't want to + implement this, use the class IRefCounted instead. See IRefCounted::grab() for details + of this method. */ + virtual bool drop() = 0; + }; + + + +} // end namespace irrklang + + + +#endif + diff --git a/includes/irrKlang/ik_SAudioStreamFormat.h b/includes/irrKlang/ik_SAudioStreamFormat.h new file mode 100644 index 0000000..cc6d343 --- /dev/null +++ b/includes/irrKlang/ik_SAudioStreamFormat.h @@ -0,0 +1,71 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __S_IRRKLANG_AUDIO_STREAM_FORMAT_H_INCLUDED__ +#define __S_IRRKLANG_AUDIO_STREAM_FORMAT_H_INCLUDED__ + +#include "ik_IRefCounted.h" + + +namespace irrklang +{ + + //! audio sample data format enumeration for supported formats + enum ESampleFormat + { + //! one unsigned byte (0;255) + ESF_U8, + + //! 16 bit, signed (-32k;32k) + ESF_S16 + }; + + + //! structure describing an audio stream format with helper functions + struct SAudioStreamFormat + { + //! channels, 1 for mono, 2 for stereo + ik_s32 ChannelCount; + + //! amount of frames in the sample data or stream. + /** If the stream has an unknown lenght, this is -1 */ + ik_s32 FrameCount; + + //! samples per second + ik_s32 SampleRate; + + //! format of the sample data + ESampleFormat SampleFormat; + + //! returns the size of a sample of the data described by the stream data in bytes + inline ik_s32 getSampleSize() const + { + return (SampleFormat == ESF_U8) ? 1 : 2; + } + + //! returns the frame size of the stream data in bytes + inline ik_s32 getFrameSize() const + { + return ChannelCount * getSampleSize(); + } + + //! returns the size of the sample data in bytes + /* Returns an invalid negative value when the stream has an unknown lenght */ + inline ik_s32 getSampleDataSize() const + { + return getFrameSize() * FrameCount; + } + + //! returns amount of bytes per second + inline ik_s32 getBytesPerSecond() const + { + return getFrameSize() * SampleRate; + } + }; + + +} // end namespace irrklang + +#endif + diff --git a/includes/irrKlang/ik_irrKlangTypes.h b/includes/irrKlang/ik_irrKlangTypes.h new file mode 100644 index 0000000..e2b1560 --- /dev/null +++ b/includes/irrKlang/ik_irrKlangTypes.h @@ -0,0 +1,96 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __IRRKLANG_TYPES_H_INCLUDED__ +#define __IRRKLANG_TYPES_H_INCLUDED__ + + +namespace irrklang +{ + + //! 8 bit unsigned variable. + /** This is a typedef for unsigned char, it ensures portability of the engine. */ + typedef unsigned char ik_u8; + + //! 8 bit signed variable. + /** This is a typedef for signed char, it ensures portability of the engine. */ + typedef signed char ik_s8; + + //! 8 bit character variable. + /** This is a typedef for char, it ensures portability of the engine. */ + typedef char ik_c8; + + + + //! 16 bit unsigned variable. + /** This is a typedef for unsigned short, it ensures portability of the engine. */ + typedef unsigned short ik_u16; + + //! 16 bit signed variable. + /** This is a typedef for signed short, it ensures portability of the engine. */ + typedef signed short ik_s16; + + + + //! 32 bit unsigned variable. + /** This is a typedef for unsigned int, it ensures portability of the engine. */ + typedef unsigned int ik_u32; + + //! 32 bit signed variable. + /** This is a typedef for signed int, it ensures portability of the engine. */ + typedef signed int ik_s32; + + + + //! 32 bit floating point variable. + /** This is a typedef for float, it ensures portability of the engine. */ + typedef float ik_f32; + + //! 64 bit floating point variable. + /** This is a typedef for double, it ensures portability of the engine. */ + typedef double ik_f64; + + + + // some constants + + const ik_f32 IK_ROUNDING_ERROR_32 = 0.000001f; + const ik_f64 IK_PI64 = 3.1415926535897932384626433832795028841971693993751; + const ik_f32 IK_PI32 = 3.14159265359f; + const ik_f32 IK_RADTODEG = 180.0f / IK_PI32; + const ik_f32 IK_DEGTORAD = IK_PI32 / 180.0f; + const ik_f64 IK_RADTODEG64 = 180.0 / IK_PI64; + const ik_f64 IK_DEGTORAD64 = IK_PI64 / 180.0; + + //! returns if a float equals the other one, taking floating + //! point rounding errors into account + inline bool equalsfloat(const ik_f32 a, const ik_f32 b, const ik_f32 tolerance = IK_ROUNDING_ERROR_32) + { + return (a + tolerance > b) && (a - tolerance < b); + } + +} // end irrklang namespace + +// ensure wchar_t type is existing for unicode support +#include + +// define the wchar_t type if not already built in. +#ifdef _MSC_VER // microsoft compiler + #ifndef _WCHAR_T_DEFINED + //! A 16 bit wide character type. + /** + Defines the wchar_t-type. + In VS6, its not possible to tell + the standard compiler to treat wchar_t as a built-in type, and + sometimes we just don't want to include the huge stdlib.h or wchar.h, + so we'll use this. + */ + typedef unsigned short wchar_t; + #define _WCHAR_T_DEFINED + #endif // wchar is not defined +#endif // microsoft compiler + + +#endif // __IRR_TYPES_H_INCLUDED__ + diff --git a/includes/irrKlang/ik_vec3d.h b/includes/irrKlang/ik_vec3d.h new file mode 100644 index 0000000..ce56669 --- /dev/null +++ b/includes/irrKlang/ik_vec3d.h @@ -0,0 +1,261 @@ +// Copyright (C) 2002-2018 Nikolaus Gebhardt +// This file is part of the "irrKlang" library. +// For conditions of distribution and use, see copyright notice in irrKlang.h + +#ifndef __IRR_IRRKLANG_VEC_3D_H_INCLUDED__ +#define __IRR_IRRKLANG_VEC_3D_H_INCLUDED__ + +#include +#include "ik_irrKlangTypes.h" + + +namespace irrklang +{ + + //! a 3d vector template class for representing vectors and points in 3d + template + class vec3d + { + public: + + vec3d(): X(0), Y(0), Z(0) {}; + vec3d(T nx, T ny, T nz) : X(nx), Y(ny), Z(nz) {}; + vec3d(const vec3d& other) :X(other.X), Y(other.Y), Z(other.Z) {}; + + //! constructor creating an irrklang vec3d from an irrlicht vector. + #ifdef __IRR_POINT_3D_H_INCLUDED__ + template + vec3d(const B& other) :X(other.X), Y(other.Y), Z(other.Z) {}; + #endif // __IRR_POINT_3D_H_INCLUDED__ + + // operators + + vec3d operator-() const { return vec3d(-X, -Y, -Z); } + + vec3d& operator=(const vec3d& other) { X = other.X; Y = other.Y; Z = other.Z; return *this; } + + vec3d operator+(const vec3d& other) const { return vec3d(X + other.X, Y + other.Y, Z + other.Z); } + vec3d& operator+=(const vec3d& other) { X+=other.X; Y+=other.Y; Z+=other.Z; return *this; } + + vec3d operator-(const vec3d& other) const { return vec3d(X - other.X, Y - other.Y, Z - other.Z); } + vec3d& operator-=(const vec3d& other) { X-=other.X; Y-=other.Y; Z-=other.Z; return *this; } + + vec3d operator*(const vec3d& other) const { return vec3d(X * other.X, Y * other.Y, Z * other.Z); } + vec3d& operator*=(const vec3d& other) { X*=other.X; Y*=other.Y; Z*=other.Z; return *this; } + vec3d operator*(const T v) const { return vec3d(X * v, Y * v, Z * v); } + vec3d& operator*=(const T v) { X*=v; Y*=v; Z*=v; return *this; } + + vec3d operator/(const vec3d& other) const { return vec3d(X / other.X, Y / other.Y, Z / other.Z); } + vec3d& operator/=(const vec3d& other) { X/=other.X; Y/=other.Y; Z/=other.Z; return *this; } + vec3d operator/(const T v) const { T i=(T)1.0/v; return vec3d(X * i, Y * i, Z * i); } + vec3d& operator/=(const T v) { T i=(T)1.0/v; X*=i; Y*=i; Z*=i; return *this; } + + bool operator<=(const vec3d&other) const { return X<=other.X && Y<=other.Y && Z<=other.Z;}; + bool operator>=(const vec3d&other) const { return X>=other.X && Y>=other.Y && Z>=other.Z;}; + + bool operator==(const vec3d& other) const { return other.X==X && other.Y==Y && other.Z==Z; } + bool operator!=(const vec3d& other) const { return other.X!=X || other.Y!=Y || other.Z!=Z; } + + // functions + + //! returns if this vector equalsfloat the other one, taking floating point rounding errors into account + bool equals(const vec3d& other) + { + return equalsfloat(X, other.X) && + equalsfloat(Y, other.Y) && + equalsfloat(Z, other.Z); + } + + void set(const T nx, const T ny, const T nz) {X=nx; Y=ny; Z=nz; } + void set(const vec3d& p) { X=p.X; Y=p.Y; Z=p.Z;} + + //! Returns length of the vector. + ik_f64 getLength() const { return sqrt(X*X + Y*Y + Z*Z); } + + //! Returns squared length of the vector. + /** This is useful because it is much faster then + getLength(). */ + ik_f64 getLengthSQ() const { return X*X + Y*Y + Z*Z; } + + //! Returns the dot product with another vector. + T dotProduct(const vec3d& other) const + { + return X*other.X + Y*other.Y + Z*other.Z; + } + + //! Returns distance from an other point. + /** Here, the vector is interpreted as point in 3 dimensional space. */ + ik_f64 getDistanceFrom(const vec3d& other) const + { + ik_f64 vx = X - other.X; ik_f64 vy = Y - other.Y; ik_f64 vz = Z - other.Z; + return sqrt(vx*vx + vy*vy + vz*vz); + } + + //! Returns squared distance from an other point. + /** Here, the vector is interpreted as point in 3 dimensional space. */ + ik_f32 getDistanceFromSQ(const vec3d& other) const + { + ik_f32 vx = X - other.X; ik_f32 vy = Y - other.Y; ik_f32 vz = Z - other.Z; + return (vx*vx + vy*vy + vz*vz); + } + + //! Calculates the cross product with another vector + vec3d crossProduct(const vec3d& p) const + { + return vec3d(Y * p.Z - Z * p.Y, Z * p.X - X * p.Z, X * p.Y - Y * p.X); + } + + //! Returns if this vector interpreted as a point is on a line between two other points. + /** It is assumed that the point is on the line. */ + bool isBetweenPoints(const vec3d& begin, const vec3d& end) const + { + ik_f32 f = (ik_f32)(end - begin).getLengthSQ(); + return (ik_f32)getDistanceFromSQ(begin) < f && + (ik_f32)getDistanceFromSQ(end) < f; + } + + //! Normalizes the vector. + vec3d& normalize() + { + T l = (T)getLength(); + if (l == 0) + return *this; + + l = (T)1.0 / l; + X *= l; + Y *= l; + Z *= l; + return *this; + } + + //! Sets the lenght of the vector to a new value + void setLength(T newlength) + { + normalize(); + *this *= newlength; + } + + //! Inverts the vector. + void invert() + { + X *= -1.0f; + Y *= -1.0f; + Z *= -1.0f; + } + + //! Rotates the vector by a specified number of degrees around the Y + //! axis and the specified center. + //! \param degrees: Number of degrees to rotate around the Y axis. + //! \param center: The center of the rotation. + void rotateXZBy(ik_f64 degrees, const vec3d& center) + { + degrees *= IK_DEGTORAD64; + T cs = (T)cos(degrees); + T sn = (T)sin(degrees); + X -= center.X; + Z -= center.Z; + set(X*cs - Z*sn, Y, X*sn + Z*cs); + X += center.X; + Z += center.Z; + } + + //! Rotates the vector by a specified number of degrees around the Z + //! axis and the specified center. + //! \param degrees: Number of degrees to rotate around the Z axis. + //! \param center: The center of the rotation. + void rotateXYBy(ik_f64 degrees, const vec3d& center) + { + degrees *= IK_DEGTORAD64; + T cs = (T)cos(degrees); + T sn = (T)sin(degrees); + X -= center.X; + Y -= center.Y; + set(X*cs - Y*sn, X*sn + Y*cs, Z); + X += center.X; + Y += center.Y; + } + + //! Rotates the vector by a specified number of degrees around the X + //! axis and the specified center. + //! \param degrees: Number of degrees to rotate around the X axis. + //! \param center: The center of the rotation. + void rotateYZBy(ik_f64 degrees, const vec3d& center) + { + degrees *= IK_DEGTORAD64; + T cs = (T)cos(degrees); + T sn = (T)sin(degrees); + Z -= center.Z; + Y -= center.Y; + set(X, Y*cs - Z*sn, Y*sn + Z*cs); + Z += center.Z; + Y += center.Y; + } + + //! Returns interpolated vector. + /** \param other: other vector to interpolate between + \param d: value between 0.0f and 1.0f. */ + vec3d getInterpolated(const vec3d& other, ik_f32 d) const + { + ik_f32 inv = 1.0f - d; + return vec3d(other.X*inv + X*d, + other.Y*inv + Y*d, + other.Z*inv + Z*d); + } + + //! Gets the Y and Z rotations of a vector. + /** Thanks to Arras on the Irrlicht forums to add this method. + \return A vector representing the rotation in degrees of + this vector. The Z component of the vector will always be 0. */ + vec3d getHorizontalAngle() + { + vec3d angle; + + angle.Y = (T)atan2(X, Z); + angle.Y *= (ik_f32)IK_RADTODEG; + + if (angle.Y < 0.0f) angle.Y += 360.0f; + if (angle.Y >= 360.0f) angle.Y -= 360.0f; + + ik_f32 z1 = (T)sqrt(X*X + Z*Z); + + angle.X = (T)atan2(z1, Y); + angle.X *= (ik_f32)IK_RADTODEG; + angle.X -= 90.0f; + + if (angle.X < 0.0f) angle.X += 360.0f; + if (angle.X >= 360) angle.X -= 360.0f; + + return angle; + } + + //! Fills an array of 4 values with the vector data (usually floats). + /** Useful for setting in shader constants for example. The fourth value + will always be 0. */ + void getAs4Values(T* array) + { + array[0] = X; + array[1] = Y; + array[2] = Z; + array[3] = 0; + } + + + // member variables + + T X, Y, Z; + }; + + + //! Typedef for a ik_f32 3d vector, a vector using floats for X, Y and Z + typedef vec3d vec3df; + + //! Typedef for an integer 3d vector, a vector using ints for X, Y and Z + typedef vec3d vec3di; + + template vec3d operator*(const S scalar, const vec3d& vector) { return vector*scalar; } + +} // end namespace irrklang + + +#endif + diff --git a/includes/irrKlang/irrKlang.h b/includes/irrKlang/irrKlang.h new file mode 100644 index 0000000..33f9ea0 --- /dev/null +++ b/includes/irrKlang/irrKlang.h @@ -0,0 +1,1040 @@ +/* irrKlang.h -- interface of the 'irrKlang' library + + Copyright (C) 2002-2018 Nikolaus Gebhardt + + 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. +*/ + +#ifndef __IRR_KLANG_H_INCLUDED__ +#define __IRR_KLANG_H_INCLUDED__ + +#include "ik_irrKlangTypes.h" +#include "ik_vec3d.h" + +#include "ik_IRefCounted.h" +#include "ik_IVirtualRefCounted.h" + +#include "ik_ESoundOutputDrivers.h" +#include "ik_ESoundEngineOptions.h" +#include "ik_EStreamModes.h" +#include "ik_SAudioStreamFormat.h" +#include "ik_ISoundEngine.h" +#include "ik_ISoundSource.h" +#include "ik_ISound.h" +#include "ik_IAudioStream.h" +#include "ik_IAudioStreamLoader.h" +#include "ik_ISoundEffectControl.h" +#include "ik_ISoundStopEventReceiver.h" +#include "ik_IFileFactory.h" +#include "ik_IFileReader.h" +#include "ik_ISoundDeviceList.h" +#include "ik_IAudioRecorder.h" +#include "ik_ISoundMixedOutputReceiver.h" + +//! irrKlang Version +#define IRR_KLANG_VERSION "1.6.0" + +/*! \mainpage irrKlang 1.6.0 API documentation + * + *
+ + * \section contents Contents + * General:
+ * @ref intro
+ * @ref features
+ * @ref links
+ * @ref tipsandtricks
+ *
+ * Programming irrKlang:
+ * @ref concept
+ * @ref playingSounds
+ * @ref changingSounds
+ * @ref soundSources
+ * @ref sound3d
+ * @ref removingSounds
+ * @ref events
+ * @ref memoryPlayback
+ * @ref effects
+ * @ref fileOverriding
+ * @ref audioDecoders
+ * @ref plugins
+ * @ref staticLib
+ * @ref enumeratingDevices
+ * @ref recordingAudio
+ * @ref unicode
+ *
+ * Short full examples:
+ * @ref quickstartexample
+ * @ref quickstartexample2
+ *
+ *
+ * + * \section intro Introduction + * + * Welcome to the irrKlang API documentation. This page should give you a short overview + * over irrKlang, the high level audio library. + * In this documentation files you'll find any information you'll need to develop applications with + * irrKlang using C++. If you are looking for a tutorial on how to start, you'll + * find some on the homepage of irrKlang at + * http://www.ambiera.com/irrklang + * or inside the SDK in the directory \examples. + * + * The irrKlang library is intended to be an easy-to-use 3d and 2d sound engine, so + * this documentation is an important part of it. If you have any questions or + * suggestions, please take a look into the ambiera.com forum or just send a mail. + * + *
+ *
+ * + * + * \section features Features of irrKlang + * + * irrKlang is a high level 2D and 3D + * cross platform sound engine and audio library. + * It has a very simply object orientated interface and was designed to be used + * in games, scientific simulations, architectural visualizations and similar. + * irrKlang plays several file formats such as + *
    + *
  • RIFF WAVE (*.wav)
  • + *
  • Ogg Vorbis (*.ogg)
  • + *
  • MPEG-1 Audio Layer 3 (*.mp3)
  • + *
  • Free Lossless Audio Codec (*.flac)
  • + *
  • Amiga Modules (*.mod)
  • + *
  • Impulse Tracker (*.it)
  • + *
  • Scream Tracker 3 (*.s3d)
  • + *
  • Fast Tracker 2 (*.xm)
  • + *
+ * It is also able to run on different operating systems and use several output drivers: + *
    + *
  • Windows 98, ME, NT 4, 2000, XP, Vista, Windows 7, Windows 8
  • + *
      + *
    • DirectSound
    • + *
    • DirectSound8
    • + *
    • WinMM
    • + *
    + *
  • Linux / *nix
  • + *
      + *
    • ALSA
    • + *
    + *
  • MacOSX (x86 and PPC)
  • + *
      + *
    • CoreAudio
    • + *
    + *
+ *
+ *
+ *
+ * + * + * + * \section links Links into the API documentation + * + * irrklang::ISoundEngine: The main class of irrKlang.
+ * Class list: List of all classes with descriptions.
+ * Class members: Good place to find forgotten features.
+ *
+ *
+ *
+ * + * + * + * \section tipsandtricks Tips and Tricks + * + * This section lists a few tips you might consider when implementing the sound part of your application + * using irrKlang: + * + *
    + *
  • If you can choose which audio file format is the primary one for your application, + * use .OGG files, instead of for example .MP3 files. irrKlang uses a lot less memory + * and CPU power when playing .OGGs.
  • + *
  • To keep your application simple, each time you play a sound, you can use for example + * play2D("filename.mp3") and let irrKlang handle the rest. There is no need to implement + * a preloading/caching/file management system for the audio playback. irrKlang will handle + * all this by itself and will never load a file twice.
  • + *
  • irrKlang is crashing in your application? This should not happen, irrKlang is pretty stable, + * and in most cases, this is a problem in your code: In a lot of cases the reason is simply + * a wrong call to irrklang::IRefCounted::drop(). Be sure you are doing it correctly. (If you are unsure, + * tempoarily remove all calls to irrklang::IRefCounted::drop() and see if this helps.)
  • + *
+ * + *
+ *
+ *
+ *
+ * + * + * + * \section concept Starting up the Engine + * + * irrKlang is designed so that it is very easy to achieve everything, its interface should + * be very simple to use. The @ref quickstartexample shows how to play and mp3 file, and there + * is another example, @ref quickstartexample2, showing some few more details.
+ * To start up the sound engine, you simply need to call createIrrKlangDevice(). To shut it down, + * call IRefCounted::drop(): + * + * \code + * #include + * + * // ... + * + * // start up the engine + * irrklang::ISoundEngine* engine = irrklang::createIrrKlangDevice(); + * + * // ... + * + * // after finished, + * // close the engine again, similar as calling 'delete' + * engine->drop(); + * \endcode + * + * The createIrrKlangDevice() function also accepts several parameters, so that you can + * specify which sound driver should be used, if plugins should be used, if irrKlang + * should run in multithreaded mode, and similar. + *
+ *
+ *
+ *
+ * + * + * + * \section playingSounds Playing Sounds + * + * Once you have irrKlang running (like in @ref concept), you can start playing sounds: + * + * \code + * engine->play2D("someSoundFile.wav"); + * \endcode + * + * This works with all supported file types. You can replace "someSoundFile.wav" with + * "someSoundFile.mp3", or "someSoundFile.ogg", for example.
+ * To play a sound looped, set the second parameter to 'true': + * + * \code + * engine->play2D("myMusic.mp3", true); + * \endcode + * + * To stop this looping sound again, use engine->\link irrklang::ISoundEngine::stopAllSounds stopAllSounds()\endlink to stop all sounds, or + * irrklang::ISound::stop() if you only want to stop that single sound. @ref changingSounds + * shows how to get to that ISound interface. + *
+ *
+ *
+ *
+ * + * + * \section changingSounds Influencing Sounds during Playback + * To influence parameters of the sound such as pan, volume or playback speed during runtime, + * to get the play position or stop playback of single playing sounds, + * you can use the irrklang::ISound interface. + * irrklang::ISoundEngine::play2D (but also play3D) returns + * a pointer to this interface when its third ('startPaused') or fourth ('track') parameter + * was set to true: + * + * \code + * irrklang::ISound* snd = engine->play2D("myMusic.mp3", true, false, true); + * + * // ... + * + * if (snd) + * snd->setVolume(someNewValue); + * + * // ... + * + * if (snd) + * { + * snd->drop(); // don't forget to release the pointer once it is no longer needed by you + * snd = 0; + * } + * \endcode + * + * The irrklang::ISound interface can also be used to test if the sound has been finished, + * set event receivers, pause and unpause sounds and similar. + *
+ *
+ *
+ *
+ * + * + * \section soundSources Using Sound Sources + * + * To be more flexible playing back sounds, irrKlang uses the concept of sound sources. + * A sound source can be simply the name of a sound file, such as "sound.wav". It is possible + * to add "sound.wav" as sound source to irrKlang, and play it using the sound source pointer: + * + * \code + * irrklang::ISoundSource* shootSound = engine->addSoundSourceFromFile("shoot.wav"); + * + * engine->play2D(shootSound); + * + * // note: you don't need to drop() the shootSound if you don't use it anymore + * \endcode + * + * The advantage of using irrklang::ISoundSource is that it is possible to set + * default values for this source, such + * as volume or distances if it should be used as 3D sound: + * + * \code + * irrklang::ISoundSource* shootSound = engine->addSoundSourceFromFile("shoot.wav"); + * + * shootSound->setDefaultVolume(0.5f); + * + * // shootSound will now be played with half its sound volume by default: + * engine->play2D(shootSound); + * \endcode + * + * It is also possible to have multiple settings for the same sound file: + * + * \code + * irrklang::ISoundSource* shootSound = engine->addSoundSourceFromFile("shoot.wav"); + * irrklang::ISoundSource* shootSound2 = engine->addSoundSourceAlias(shootSound, "silentShoot"); + * + * shootSound2->setDefaultVolume(0.1f); + * + * // shootSound will now be played with 100% of its sound volume by default, + * // shootSound2 will now be played 10% of its sound volume by default. It is + * // also possible to play it using engine->play("silentShoot"), now. + * \endcode + * + * Using addSoundSourceFromMemory(), it is also possible to play sounds back directly from memory, + * without files. + * Of course, it is not necessary to use sound sources. Using irrklang::ISound, it is + * possible to change the settings of all sounds, too. But using sound sources, it is + * not necessary to do this every time a sound is played. + *
+ *
+ *
+ *
+ * + * + * + * \section sound3d 3D Sound + * + * There is nothing difficult in playing sounds in 3D using irrKlang: Instead of using + * irrklang::ISoundEngine::play2D(), just use irrklang::ISoundEngine::play3D(), which + * takes a 3D position as additional parameter: + * + * \code + * irrklang::vec3df position(23,70,90); + * engine->play3D("yourSound.wav", position); + * \endcode + * + * But to make it sound realistic, you need to set a minimal sound + * distance: If your sound is caused by a bee, it will usually have a smaller + * sound radius than for example a jet engine. You can set default values using sound sources + * (see @ref soundSources) or set these values after you have started the sound paused: + * + * \code + * irrklang::vec3df position(23,70,90); + * + * // start the sound paused: + * irrklang::ISound* snd = engine->play3D("yourSound.wav", position, false, true); + * + * if (snd) + * { + * snd->setMinDistance(30.0f); // a loud sound + * snd->setIsPaused(false); // unpause the sound + * } + * \endcode + * + * There is also the possibility to change the maxDistance, but it is only necessary to change this + * in very rare cicumstances. + * If the sound moves, it is also a good idea to update its position from time to time: + * + * \code + * if (snd) + * snd->setPosition(newPosition); + * \endcode + * + * And don't forget to drop() the sound after you don't need it anymore. If you do, it's + * nothing severe because irrKlang will still clean up the sounds resources after it has + * finished, but you still would waste some few bytes of memory: + * + * \code + * if (snd) + * { + * snd->drop(); + * snd = 0; + * } + * \endcode + * + * To update the position of yourself, the listener of the 3D sounds, use this from + * time to time: + * + * \code + * irrklang::vec3df position(0,0,0); // position of the listener + * irrklang::vec3df lookDirection(10,0,10); // the direction the listener looks into + * irrklang::vec3df velPerSecond(0,0,0); // only relevant for doppler effects + * irrklang::vec3df upVector(0,1,0); // where 'up' is in your 3D scene + * + * engine->setListenerPosition(position, lookDirection, velPerSecond, upVector); + * \endcode + * + *
+ *
+ *
+ *
+ * + * + * \section removingSounds Removing Sounds + * + * irrKlang manages the memory usage of sounds by itself, so usually, you don't have + * to care about memory management. But if you know you need to reduce the + * amount of used memory at a certain point in your program, you can do this: + * + * \code + * engine->removeAllSoundSources(); + * \endcode + * + * This will remove all sounds and also cause all sounds to be stopped. To remove single + * sounds from the engine, use: + * + * \code + * engine->removeSoundSource(pointerToSomeSoundSource); + * // or: + * engine->removeSoundSource("nameOfASoundFile.wav"); + * \endcode + * + * Note: Only removing buffered sounds will reduce the amount of memory used by irrKlang, streamed + * sounds don't occupy a lot of memory when they are not played. + *
+ *
+ *
+ *
+ * + * + * + * \section events Using Sound Events + * + * In order to wait for a sound to be finished, it is simply possible to + * poll irrklang::ISound::isFinished(). Another way would be to constantly use + * irrklang::ISoundEngine::isCurrentlyPlaying to test wether a sound with that name or source + * is currently playing. But of course, an event based approach is a lot nicer. That's why irrKlang + * supports sound events.
+ * The key to sound events is the method + * \link irrklang::ISound::setSoundStopEventReceiver setSoundStopEventReceiver \endlink + * of the irrklang::ISound interface + * (See @ref changingSounds on how to get the ISound interface): + * + * \code + * irrklang::ISound* snd = engine->play2D("speech.mp3", false, false, true); + * if (snd) + * snd->setSoundStopEventReceiver(yourEventReceiver, 0); + * \endcode + * + * The optional second parameter of setSoundStopEventReceiver is a user pointer, set it to whatever you like. + * 'yourEventReceiver' must be an implementation of the irrklang::ISoundStopEventReceiver interface.
+ * A whole implementation could look like this: + * + * \code + * class MySoundEndReceiver : public irrklang::ISoundStopEventReceiver + * { + * public: + * virtual void OnSoundStopped (irrklang::ISound* sound, irrklang::E_STOP_EVENT_CAUSE reason, void* userData) + * { + * // called when the sound has ended playing + * printf("sound has ended"); + * } + * } + * + * // ... + * + * MySoundEndReceiver* myReceiver = new MySoundEndReceiver(); + * irrklang::ISound* snd = engine->play2D("speech.mp3", false, false, true); + * if (snd) + * snd->setSoundStopEventReceiver(myReceiver); + * + * myReceiver->drop(); // similar to delete + * \endcode + * + * The irrklang::ISoundStopEventReceiver::OnSoundStopped() method is guaranteed to be called when a sound or sound stream has stopped, + * either because the sound reached its playback end, its sound source was removed, + * ISoundEngine::stopAllSounds() has been called or the whole engine was deleted. + *
+ *
+ *
+ *
+ * + * + * + * \section memoryPlayback Memory Playback + * + * Using irrKlang, it is easily possible to play sounds directly from memory instead out of + * files. There is an example project showing this: In the SDK, in /examples/03.MemoryPlayback. + * But in short, it simply works by adding the memory as sound source (See @ref soundSources for + * details about sound sources): + * + * \code + * engine->addSoundSourceFromMemory(pointerToMemory, memorySize, "nameforthesound.wav"); + * + * // play sound now + * engine->play2D("nameforthesound.wav"); + * \endcode + * + * Or using a sound source pointer: + * + * \code + * irrklang::ISoundSource* snd = + * engine->addSoundSourceFromMemory(pointerToMemory, memorySize, "nameforthesound.wav"); + * + * // play sound now + * engine->play2D(snd); + * \endcode + * + * Note: It is also possible to overwrite the file access directly, don't use this Memory Playback + * feature for this. See @ref fileOverriding for details. + *
+ *
+ *
+ *
+ * + * + * + * \section effects Sound Effects + * + * irrKlang supports the effects Chorus, Compressor, Distortion, Echo, Flanger + * Gargle, 3DL2Reverb, ParamEq and WavesReverb, when using the sound driver + * irrklang::ESOD_DIRECT_SOUND_8, which selected by default when using Windows.
+ * + * Using the irrklang::ISound interface, you can optain the irrklang::ISoundEffectControl + * interface if the sound device supports sound effects and the last parameter ('enableSoundEffects') + * was set to true when calling play2D(): + * + * \code + * irrklang::ISound* snd = engine->play2D("sound.wav", true, false, true, ESM_AUTO_DETECT, true); + * + * if (snd) + * { + * irrklang::ISoundEffectControl* fx = snd->getSoundEffectControl(); + * if (fx) + * { + * // enable the echo sound effect for this sound + * fx->enableEchoSoundEffect(); + * } + * } + * + * snd->drop(); + * \endcode + * + * This enabled the echo sound effect for this sound. The method also supports a lot of + * parameters, and can be called multiple times to change those parameters over time if wished. + * There are a lot of other sound effects, see irrklang::ISoundEffectControl for details. + *
+ *
+ *
+ *
+ * + * + * + * \section fileOverriding Overriding File Access + * + * It is possible to let irrKlang use your own file access functions. + * This is useful if you want to read sounds from other sources than + * just files, for example from custom internet streams or + * an own encypted archive format. There is an example in the SDK in + * examples/04.OverrideFileAccess which shows this as well.
+ * + * The only thing to do for this is to implement your own irrklang::IFileFactory, + * and set it in irrKlang using irrklang::ISoundEngine::addFileFactory(): + * + * \code + * // a class implementing the IFileFactory interface to override irrklang file access + * class CMyFileFactory : public irrklang::IFileFactory + * { + * public: + * + * // Opens a file for read access. Simply return 0 if file not found. + * virtual irrklang::IFileReader* createFileReader(const ik_c8* filename) + * { + * // return your own irrklang::IFileReader implementation here, for example like that: + * return new CMyReadFile(filename); + * } + * }; + * + * // ... + * + * CMyFileFactory* myFactory = new CMyFileFactory(); + * engine->addFileFactory(myFactory); + * myFactory->drop(); + * \endcode + * + * For a full example implementation, just take a look into the SDK in examples/04.OverrideFileAccess. + *
+ *
+ *
+ *
+ * + * + * + * \section audioDecoders Adding Audio Decoders + * + * To add support for new file formats, it is possible to add new audio decoders + * to irrKlang. + * The only thing to do for this is to implement your own irrklang::IAudioStreamLoader, + * and irrklang::IAudioStream, and set it in irrKlang using + * irrklang::ISoundEngine::registerAudioStreamLoader(): + * + * \code + * class NewAudioStreamLoader : public irrklang::IAudioStreamLoader + * { + * // ... returns NewAudioDecoder and the used file name suffices. + * }; + * + * class NewAudioDecoder : public irrklang::IAudioStream + * { + * public: + * // ... decodes the new file format + * }; + * + * // ... + * + * NewAudioDecoder* loader = new NewAudioDecoder(); + * engine->registerAudioStreamLoader(loader); + * loader->drop(); + * \endcode + * + * There is an example audio decoder and loader with full source in plugins/ikpMP3, which + * adds MP3 audio decoding capabilities to irrKlang. + *
+ *
+ *
+ *
+ * + * + * + * \section plugins Creating irrKlang Plugins + * + * irrKlang plugins are ikp*.dll (Windows), ikp*.so (Unix) or ikp*.dylib (MacOS) + * files which are loaded by irrKlang at startup when the + * irrklang::ESEO_LOAD_PLUGINS was set (which is default) or + * irrklang::ISoundEngine::loadPlugins() was called.
+ * + * The plugin only needs to contain the following function which will be called by irrKlang: + * + * \code + * #ifdef WIN32 + * // Windows version + * __declspec(dllexport) void __stdcall irrKlangPluginInit(ISoundEngine* engine, const char* version) + * #else + * // Linux and Mac OS version + * void irrKlangPluginInit(ISoundEngine* engine, const char* version) + * #endif + * { + * // your implementation here + * } + * \endcode + * + * In there, it is for example possible to extend irrKlang with new audio decoders, + * see @ref audioDecoders for details.
+ * + * There is an example plugin with full source in plugins/ikpMP3, which + * adds MP3 audio decoding capabilities to irrKlang. + *
+ *
+ *
+ *
+ * + * + * + * \section staticLib Using irrKlang as static Lib + * + * If you don't want to use the irrKlang.DLL file and link irrKlang statically, you can do this + * by simply linking to the irrKlang.lib in the bin/win32-visualstudio_lib folder. This folder + * will only available in the pro versions of irrKlang, which you get when purchasing an irrKlang + * license. + * + * To use irrKlang in this way, just define IRRKLANG_STATIC before including irrklang.h, like this: + * + * \code + * #define IRRKLANG_STATIC + * #include + * \endcode + * + * Of course, IRRKLANG_STATIC can also simply be defined in the project/compiler settings instead of + * in the source file. + *
+ *
+ *
+ *
+ * + * + * + * \section enumeratingDevices Enumerating sound devices + * + * irrKlang uses the default sound device when playing sound when started without parameters. But if you want + * irrKlang to playback sound on one specific sound device, you may want to enumerate the available + * sound devices on your system and select one of them. Use irrklang::createSoundDeviceList() for this. + * This example code shows how to print a list of all available sound devices on the current system and lets + * the user choose one of them: + * + * \code + * int main(int argc, const char** argv) + * { + * // enumerate devices + * + * irrklang::ISoundDeviceList* deviceList = createSoundDeviceList(); + * + * // ask user for a sound device + * + * printf("Devices available:\n\n"); + * + * for (int i=0; igetDeviceCount(); ++i) + * printf("%d: %s\n", i, deviceList->getDeviceDescription(i)); + * + * printf("\nselect a device using the number (or press any key to use default):\n\n"); + * int deviceNumber = getch() - '0'; + * + * // create device with the selected driver + * + * const char* deviceID = deviceList->getDeviceID(deviceNumber); + * + * ISoundEngine* engine = createIrrKlangDevice(irrklang::ESOD_AUTO_DETECT, + * irrklang::ESEO_DEFAULT_OPTIONS, + * deviceID); + * + * deviceList->drop(); // delete device list + * + * // ... use engine now + * } + * \endcode + * + * In this way, it is also possible to play back sound using two devices at the same time: Simply + * create two irrKlang devices with each a different deviceID.
+ * Note: createSoundDeviceList() takes a driver type parameter (such as irrklang::ESOD_DIRECT_SOUND8), which you + * have to set to the same value as the first parameter you want to use with createIrrKlangDevice(), if it is + * other than irrklang::ESOD_AUTO_DETECT. + *
+ *
+ *
+ *
+ * + * + * + * \section recordingAudio Recording Audio + * + * irrKlang is able to record audio from sound capturing devices such as microphones (currently only + * supported in windows). Use the irrklang::IAudioRecorder interface to do this. The following example shows how + * to record some audio and play it back again using the engine: + * + * \code + * int main(int argc, const char** argv) + * { + * irrklang::ISoundEngine* engine = irrklang::createIrrKlangDevice(); + * irrklang::IAudioRecorder* recorder = irrklang::createIrrKlangAudioRecorder(engine); + * + * if (!engine || !recorder) + * { + * printf("Could not create audio engine or audio recoder\n"); + * return 1; + * } + * + * printf("\nPress any key to start recording audio...\n"); + * getch(); + * + * // record some audio + * + * recorder->startRecordingBufferedAudio(); + * + * printf("\nRECORDING. Press any key to stop...\n"); + * getch(); + * + * recorder->stopRecordingAudio(); + * + * printf("\nRecording done, recorded %dms of audio.\n", + * recorder->getAudioFormat().FrameCount * 1000 / recorder->getAudioFormat().SampleRate ); + * printf("Press any key to play back recorded audio...\n"); + * getch(); + * + * // play the recorded audio + * recorder->addSoundSourceFromRecordedAudio("myRecordedVoice"); + * engine->play2D("myRecordedVoice", true); + * + * // wait until user presses a key + * printf("\nPress any key to quit..."); + * getch(); + * + * recorder->drop(); + * engine->drop(); // delete engine + * + * return 0; + * } + * \endcode + * + * In order to select a specific audio capturing device for recording, it is necessary to enumerate + * the available devices. Simply replace the first to lines of code of the example above with code + * like this to list all devices and select one: + * + * \code + * // enumerate recording devices and ask user to select one + * + * irrklang::ISoundDeviceList* deviceList = irrklang::createAudioRecorderDeviceList(); + * + * printf("Devices available:\n\n"); + * + * for (int i=0; igetDeviceCount(); ++i) + * printf("%d: %s\n", i, deviceList->getDeviceDescription(i)); + * + * printf("\nselect a device using the number (or press any key to use default):\n\n"); + * int deviceNumber = getch() - '0'; + * + * // create recording device with the selected driver + * + * const char* deviceID = deviceList->getDeviceID(deviceNumber); + * irrklang::ISoundEngine* engine = irrklang::createIrrKlangDevice(); + * irrklang::IAudioRecorder* recorder = + * irrklang::createIrrKlangAudioRecorder(engine, irrklang::ESOD_AUTO_DETECT, deviceID); + * + * \endcode + * + *
+ *
+ *
+ *
+ * + * + * \section unicode Unicode support + * + * irrKlang supports unicode on all operating systems. Internally, it uses UTF8, and all functions accepting strings + * and file names take UTF8 strings. If you are running irrKlang on Windows, and are using the UNICODE define or using + * wchar_t* strings directly, you can do this as well. Use the irrKlang provided function makeUTF8fromUTF16string() to + * convert your wchar_t* string to a char* string. + * + * This example shows how: + * + * \code + * const wchar_t* yourFilename = L"SomeUnicodeFilename.wav"; // assuming this is the file name you get from some of your functions + * + * const int nBufferSize = 2048; // large enough, but best would be wcslen(yourFilename)*3. + * char strBuffer[nBufferSize]; + * irrklang::makeUTF8fromUTF16string(yourFilename, strBuffer, nBufferSize); + * + * // now the converted file name is in strBuffer. We can play it for example now: + * engine->play2D(strBuffer); + * \endcode + * + * Of course, you can use any other unicode converion function for this. makeUTF8fromUTF16string() is only provided + * for convenience. + *
+ *
+ *
+ *
+ * + * + * + * + * + * \section quickstartexample Quick Start Example + * + * To simply start the engine and play a mp3 file, use code like this: + * + * \code + * #include + * #include + * #pragma comment(lib, "irrKlang.lib") // link with irrKlang.dll + * + * int main(int argc, const char** argv) + * { + * irrklang::ISoundEngine* engine = irrklang::createIrrKlangDevice(); + * if (!engine) return 1; // could not start engine + * + * engine->play2D("someMusic.mp3", true); // play some mp3 file, looped + * + * std::cin.get(); // wait until user presses a key + * + * engine->drop(); // delete engine + * return 0; + * } + * \endcode + * + * A mp3 file is being played until the user presses enter in this example. + * As you can see, irrKlang uses namespaces, all of + * the classes are located in the namespace irrklang. If you don't want to write + * this in front of every class and function you are using, simply write + * + * \code + * using namespace irrklang; + * \endcode + * in front of your code, as also shown in the next example. + *
+ *
+ *
+ *
+ * + * + * + * \section quickstartexample2 Quick Start Example 2 + * + * The following is a simple interactive application, starting up the sound engine and + * playing some streaming .ogg music file and a .wav sound effect every time the user + * presses a key. + * + * \code + * #include + * #include + * using namespace irrklang; + * + * #pragma comment(lib, "irrKlang.lib") // link with irrKlang.dll + * + * + * int main(int argc, const char** argv) + * { + * // start the sound engine with default parameters + * ISoundEngine* engine = createIrrKlangDevice(); + * + * if (!engine) + * return 0; // error starting up the engine + * + * // play some sound stream, looped + * engine->play2D("../../media/helltroopers.ogg", true); + * + * std::cout << "\nHello World!\n"; + * + * char i = 0; + * + * while(i != 'q') + * { + * std::cout << "Press any key to play some sound, press 'q' to quit.\n"; + * + * // play a single sound + * engine->play2D("../../media/bell.wav"); + * + * std::cin >> i; // wait for user to press some key + * } + * + * engine->drop(); // delete engine + * return 0; + * } + * + * \endcode + */ + +#if defined(IRRKLANG_STATIC) + #define IRRKLANG_API +#else + #if (defined(WIN32) || defined(WIN64) || defined(_MSC_VER)) + #ifdef IRRKLANG_EXPORTS + #define IRRKLANG_API __declspec(dllexport) + #else + #define IRRKLANG_API __declspec(dllimport) + #endif // IRRKLANG_EXPORT + #else + #define IRRKLANG_API __attribute__((visibility("default"))) + #endif // defined(WIN32) || defined(WIN64) +#endif // IRRKLANG_STATIC + +#if defined(_STDCALL_SUPPORTED) +#define IRRKLANGCALLCONV __stdcall // Declare the calling convention. +#else +#define IRRKLANGCALLCONV +#endif // STDCALL_SUPPORTED + +//! Everything in the irrKlang Sound Engine can be found in this namespace. +namespace irrklang +{ + //! Creates an irrKlang device. The irrKlang device is the root object for using the sound engine. + /** \param driver The sound output driver to be used for sound output. Use irrklang::ESOD_AUTO_DETECT + to let irrKlang decide which driver will be best. + \param options A combination of irrklang::E_SOUND_ENGINE_OPTIONS literals. Default value is + irrklang::ESEO_DEFAULT_OPTIONS. + \param deviceID Some additional optional deviceID for the audio driver. If not needed, simple + set this to 0. + This can be used for example to set a specific ALSA output pcm device for output + ("default" or "hw", for example). For most driver types, available deviceIDs can be + enumerated using createSoundDeviceList(). + See @ref enumeratingDevices for an example or ISoundDeviceList or details. + \param sdk_version_do_not_use Don't use or change this parameter. Always set it to + IRRKLANG_SDK_VERSION, which is done by default. This is needed for sdk version checks. + \return Returns pointer to the created irrKlang device or null if the + device could not be created. If you don't need the device, use ISoundEngine::drop() to + delete it. See IRefCounted::drop() for details. + */ + IRRKLANG_API ISoundEngine* IRRKLANGCALLCONV createIrrKlangDevice( + E_SOUND_OUTPUT_DRIVER driver = ESOD_AUTO_DETECT, + int options = ESEO_DEFAULT_OPTIONS, + const char* deviceID = 0, + const char* sdk_version_do_not_use = IRR_KLANG_VERSION); + + + //! Creates a list of available sound devices for the driver type. + /** The device IDs in this list can be used as parameter to createIrrKlangDevice() to + make irrKlang use a special sound device. See @ref enumeratingDevices for an example on how + to use this. + \param driver The sound output driver of which the list is generated. Set it irrklang::ESOD_AUTO_DETECT + to let this function use the same device as createIrrKlangDevice() would choose. + \param sdk_version_do_not_use Don't use or change this parameter. Always set it to + IRRKLANG_SDK_VERSION, which is done by default. This is needed for sdk version checks. + \return Returns a pointer to the list of enumerated sound devices for the selected sound driver. + The device IDs in this list can be used as parameter to createIrrKlangDevice() to + make irrKlang use a special sound device. + After you don't need the list anymore, call ISoundDeviceList::drop() in order to free its memory. */ + IRRKLANG_API ISoundDeviceList* IRRKLANGCALLCONV createSoundDeviceList( + E_SOUND_OUTPUT_DRIVER driver = ESOD_AUTO_DETECT, + const char* sdk_version_do_not_use = IRR_KLANG_VERSION); + + + //! Creates an irrKlang audio recording device. The IAudioRecorder is the root object for recording audio. + /** If you want to play back recorded audio as well, create the ISoundEngine first using + createIrrKlangDevice() and then the IAudioRecorder using createIrrKlangAudioRecorder(), where + you set the ISoundEngine as first parameter. See @ref recordingAudio for an example on how to use this. + Note: audio recording is a very new feature a still beta in irrKlang. It currently only works in Windows + and with DirectSound (subject to change). + \param irrKlangDeviceForPlayback A pointer to the already existing sound device used for playback + of audio. Sound sources recorded with the IAudioRecorder will be added into that device so that + they can be played back there. + \param driver The sound output driver to be used for recording audio. Use irrklang::ESOD_AUTO_DETECT + to let irrKlang decide which driver will be best. + \param deviceID Some additional optional deviceID for the audio driver. If not needed, simple + set this to 0. Use createAudioRecorderDeviceList() to get a list of all deviceIDs. + \param sdk_version_do_not_use Don't use or change this parameter. Always set it to + IRRKLANG_SDK_VERSION, which is done by default. This is needed for sdk version checks. + \return Returns pointer to the created irrKlang device or null if the + device could not be created. If you don't need the device, use ISoundEngine::drop() to + delete it. See IRefCounted::drop() for details. + */ + IRRKLANG_API IAudioRecorder* IRRKLANGCALLCONV createIrrKlangAudioRecorder( + ISoundEngine* irrKlangDeviceForPlayback, + E_SOUND_OUTPUT_DRIVER driver = ESOD_AUTO_DETECT, + const char* deviceID = 0, + const char* sdk_version_do_not_use = IRR_KLANG_VERSION); + + //! Creates a list of available recording devices for the driver type. + /** The device IDs in this list can be used as parameter to createIrrKlangAudioRecorder() to + make irrKlang use a special recording device. + \param driver The sound output driver of which the list is generated. Set it irrklang::ESOD_AUTO_DETECT + to let this function use the same device as createIrrKlangDevice() would choose. + \param sdk_version_do_not_use Don't use or change this parameter. Always set it to + IRRKLANG_SDK_VERSION, which is done by default. This is needed for sdk version checks. + \return Returns a pointer to the list of enumerated recording devices for the selected sound driver. + The device IDs in this list can be used as parameter to createIrrKlangAudioRecorder() to + make irrKlang use a special sound device. + After you don't need the list anymore, call ISoundDeviceList::drop() in order to free its memory. */ + IRRKLANG_API ISoundDeviceList* IRRKLANGCALLCONV createAudioRecorderDeviceList( + E_SOUND_OUTPUT_DRIVER driver = ESOD_AUTO_DETECT, + const char* sdk_version_do_not_use = IRR_KLANG_VERSION); + + + //! Converts a wchar_t string to an utf8 string, useful when using Windows in unicode mode. + /** irrKlang works with unicode file names, and accepts char* strings as parameters for names and filenames. + If you are running irrKlang in Windows, and working with wchar_t* pointers instead of char* ones, + you can use this function to create a char* (UTF8) representation of your wchar_t* (UTF16) string. + Works for filenames and other strings. + \param pInputString zero terminated input string. + \param pOutputBuffer the buffer where the converted string is written to. Be sure that this buffer + has a big enough size. A good size would be three times the string length of your input buffer, like + wcslen(yourInputBuffer)*3. Because each wchar_t can be represented by up to 3 chars. + \param outputBufferSize size of your output buffer. + \return Returns true if successful, and false if not. If 'false' is returned, maybe your buffer was too small. */ + IRRKLANG_API bool IRRKLANGCALLCONV makeUTF8fromUTF16string( + const wchar_t* pInputString, char* pOutputBuffer, int outputBufferSize); + + +} // end namespace irrklang + + +/*! \file irrKlang.h + \brief Main header file of the irrKlang sound library, the only file needed to include. +*/ + +#endif + diff --git a/lib/irrKlang.lib b/lib/irrKlang.lib new file mode 100644 index 0000000..4c469ca Binary files /dev/null and b/lib/irrKlang.lib differ diff --git a/src/7.in_practice/3.2d_game/0.full_source/audio/bleep.mp3 b/src/7.in_practice/3.2d_game/audio/bleep.mp3 similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/audio/bleep.mp3 rename to src/7.in_practice/3.2d_game/audio/bleep.mp3 diff --git a/src/7.in_practice/3.2d_game/0.full_source/audio/bleep.wav b/src/7.in_practice/3.2d_game/audio/bleep.wav similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/audio/bleep.wav rename to src/7.in_practice/3.2d_game/audio/bleep.wav diff --git a/src/7.in_practice/3.2d_game/0.full_source/audio/breakout.mp3 b/src/7.in_practice/3.2d_game/audio/breakout.mp3 similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/audio/breakout.mp3 rename to src/7.in_practice/3.2d_game/audio/breakout.mp3 diff --git a/src/7.in_practice/3.2d_game/0.full_source/audio/powerup.wav b/src/7.in_practice/3.2d_game/audio/powerup.wav similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/audio/powerup.wav rename to src/7.in_practice/3.2d_game/audio/powerup.wav diff --git a/src/7.in_practice/3.2d_game/0.full_source/audio/solid.wav b/src/7.in_practice/3.2d_game/audio/solid.wav similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/audio/solid.wav rename to src/7.in_practice/3.2d_game/audio/solid.wav diff --git a/src/7.in_practice/3.2d_game/0.full_source/ball_object.cpp b/src/7.in_practice/3.2d_game/ball_object.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/ball_object.cpp rename to src/7.in_practice/3.2d_game/ball_object.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/ball_object.h b/src/7.in_practice/3.2d_game/ball_object.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/ball_object.h rename to src/7.in_practice/3.2d_game/ball_object.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/fonts/OCRAEXT.TTF b/src/7.in_practice/3.2d_game/fonts/OCRAEXT.TTF similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/fonts/OCRAEXT.TTF rename to src/7.in_practice/3.2d_game/fonts/OCRAEXT.TTF diff --git a/src/7.in_practice/3.2d_game/0.full_source/game.cpp b/src/7.in_practice/3.2d_game/game.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/game.cpp rename to src/7.in_practice/3.2d_game/game.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/game.h b/src/7.in_practice/3.2d_game/game.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/game.h rename to src/7.in_practice/3.2d_game/game.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/game_level.cpp b/src/7.in_practice/3.2d_game/game_level.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/game_level.cpp rename to src/7.in_practice/3.2d_game/game_level.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/game_level.h b/src/7.in_practice/3.2d_game/game_level.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/game_level.h rename to src/7.in_practice/3.2d_game/game_level.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/game_object.cpp b/src/7.in_practice/3.2d_game/game_object.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/game_object.cpp rename to src/7.in_practice/3.2d_game/game_object.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/game_object.h b/src/7.in_practice/3.2d_game/game_object.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/game_object.h rename to src/7.in_practice/3.2d_game/game_object.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/glad.c b/src/7.in_practice/3.2d_game/glad.c similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/glad.c rename to src/7.in_practice/3.2d_game/glad.c diff --git a/src/7.in_practice/3.2d_game/0.full_source/levels/four.lvl b/src/7.in_practice/3.2d_game/levels/four.lvl similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/levels/four.lvl rename to src/7.in_practice/3.2d_game/levels/four.lvl diff --git a/src/7.in_practice/3.2d_game/0.full_source/levels/one.lvl b/src/7.in_practice/3.2d_game/levels/one.lvl similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/levels/one.lvl rename to src/7.in_practice/3.2d_game/levels/one.lvl diff --git a/src/7.in_practice/3.2d_game/0.full_source/levels/three.lvl b/src/7.in_practice/3.2d_game/levels/three.lvl similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/levels/three.lvl rename to src/7.in_practice/3.2d_game/levels/three.lvl diff --git a/src/7.in_practice/3.2d_game/0.full_source/levels/two.lvl b/src/7.in_practice/3.2d_game/levels/two.lvl similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/levels/two.lvl rename to src/7.in_practice/3.2d_game/levels/two.lvl diff --git a/src/7.in_practice/3.2d_game/0.full_source/particle_generator.cpp b/src/7.in_practice/3.2d_game/particle_generator.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/particle_generator.cpp rename to src/7.in_practice/3.2d_game/particle_generator.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/particle_generator.h b/src/7.in_practice/3.2d_game/particle_generator.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/particle_generator.h rename to src/7.in_practice/3.2d_game/particle_generator.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/post_processor.cpp b/src/7.in_practice/3.2d_game/post_processor.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/post_processor.cpp rename to src/7.in_practice/3.2d_game/post_processor.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/post_processor.h b/src/7.in_practice/3.2d_game/post_processor.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/post_processor.h rename to src/7.in_practice/3.2d_game/post_processor.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/power_up.h b/src/7.in_practice/3.2d_game/power_up.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/power_up.h rename to src/7.in_practice/3.2d_game/power_up.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/program.cpp b/src/7.in_practice/3.2d_game/program.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/program.cpp rename to src/7.in_practice/3.2d_game/program.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/progress/2.game.cpp b/src/7.in_practice/3.2d_game/progress/2.game.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/progress/2.game.cpp rename to src/7.in_practice/3.2d_game/progress/2.game.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/progress/2.game.h b/src/7.in_practice/3.2d_game/progress/2.game.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/progress/2.game.h rename to src/7.in_practice/3.2d_game/progress/2.game.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/progress/2.program.cpp b/src/7.in_practice/3.2d_game/progress/2.program.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/progress/2.program.cpp rename to src/7.in_practice/3.2d_game/progress/2.program.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/progress/3.game.cpp b/src/7.in_practice/3.2d_game/progress/3.game.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/progress/3.game.cpp rename to src/7.in_practice/3.2d_game/progress/3.game.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/progress/4.game.cpp b/src/7.in_practice/3.2d_game/progress/4.game.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/progress/4.game.cpp rename to src/7.in_practice/3.2d_game/progress/4.game.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/progress/4.game.h b/src/7.in_practice/3.2d_game/progress/4.game.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/progress/4.game.h rename to src/7.in_practice/3.2d_game/progress/4.game.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/progress/5.1.ball_object_collisions.cpp b/src/7.in_practice/3.2d_game/progress/5.1.ball_object_collisions.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/progress/5.1.ball_object_collisions.cpp rename to src/7.in_practice/3.2d_game/progress/5.1.ball_object_collisions.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/progress/5.1.ball_object_collisions.h b/src/7.in_practice/3.2d_game/progress/5.1.ball_object_collisions.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/progress/5.1.ball_object_collisions.h rename to src/7.in_practice/3.2d_game/progress/5.1.ball_object_collisions.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/progress/5.game.cpp b/src/7.in_practice/3.2d_game/progress/5.game.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/progress/5.game.cpp rename to src/7.in_practice/3.2d_game/progress/5.game.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/progress/5.game.h b/src/7.in_practice/3.2d_game/progress/5.game.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/progress/5.game.h rename to src/7.in_practice/3.2d_game/progress/5.game.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/progress/6.game.cpp b/src/7.in_practice/3.2d_game/progress/6.game.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/progress/6.game.cpp rename to src/7.in_practice/3.2d_game/progress/6.game.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/progress/7.game.cpp b/src/7.in_practice/3.2d_game/progress/7.game.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/progress/7.game.cpp rename to src/7.in_practice/3.2d_game/progress/7.game.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/progress/8.game.cpp b/src/7.in_practice/3.2d_game/progress/8.game.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/progress/8.game.cpp rename to src/7.in_practice/3.2d_game/progress/8.game.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/progress/8.game.h b/src/7.in_practice/3.2d_game/progress/8.game.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/progress/8.game.h rename to src/7.in_practice/3.2d_game/progress/8.game.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/progress/9.game.cpp b/src/7.in_practice/3.2d_game/progress/9.game.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/progress/9.game.cpp rename to src/7.in_practice/3.2d_game/progress/9.game.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/resource_manager.cpp b/src/7.in_practice/3.2d_game/resource_manager.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/resource_manager.cpp rename to src/7.in_practice/3.2d_game/resource_manager.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/resource_manager.h b/src/7.in_practice/3.2d_game/resource_manager.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/resource_manager.h rename to src/7.in_practice/3.2d_game/resource_manager.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/shader.cpp b/src/7.in_practice/3.2d_game/shader.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/shader.cpp rename to src/7.in_practice/3.2d_game/shader.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/shader.h b/src/7.in_practice/3.2d_game/shader.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/shader.h rename to src/7.in_practice/3.2d_game/shader.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/shaders/particle.frag b/src/7.in_practice/3.2d_game/shaders/particle.frag similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/shaders/particle.frag rename to src/7.in_practice/3.2d_game/shaders/particle.frag diff --git a/src/7.in_practice/3.2d_game/0.full_source/shaders/particle.vs b/src/7.in_practice/3.2d_game/shaders/particle.vs similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/shaders/particle.vs rename to src/7.in_practice/3.2d_game/shaders/particle.vs diff --git a/src/7.in_practice/3.2d_game/0.full_source/shaders/post_processing.frag b/src/7.in_practice/3.2d_game/shaders/post_processing.frag similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/shaders/post_processing.frag rename to src/7.in_practice/3.2d_game/shaders/post_processing.frag diff --git a/src/7.in_practice/3.2d_game/0.full_source/shaders/post_processing.vs b/src/7.in_practice/3.2d_game/shaders/post_processing.vs similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/shaders/post_processing.vs rename to src/7.in_practice/3.2d_game/shaders/post_processing.vs diff --git a/src/7.in_practice/3.2d_game/0.full_source/shaders/sprite.frag b/src/7.in_practice/3.2d_game/shaders/sprite.frag similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/shaders/sprite.frag rename to src/7.in_practice/3.2d_game/shaders/sprite.frag diff --git a/src/7.in_practice/3.2d_game/0.full_source/shaders/sprite.vs b/src/7.in_practice/3.2d_game/shaders/sprite.vs similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/shaders/sprite.vs rename to src/7.in_practice/3.2d_game/shaders/sprite.vs diff --git a/src/7.in_practice/3.2d_game/0.full_source/shaders/text.frag b/src/7.in_practice/3.2d_game/shaders/text.frag similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/shaders/text.frag rename to src/7.in_practice/3.2d_game/shaders/text.frag diff --git a/src/7.in_practice/3.2d_game/0.full_source/shaders/text.vs b/src/7.in_practice/3.2d_game/shaders/text.vs similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/shaders/text.vs rename to src/7.in_practice/3.2d_game/shaders/text.vs diff --git a/src/7.in_practice/3.2d_game/0.full_source/sprite_renderer.cpp b/src/7.in_practice/3.2d_game/sprite_renderer.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/sprite_renderer.cpp rename to src/7.in_practice/3.2d_game/sprite_renderer.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/sprite_renderer.h b/src/7.in_practice/3.2d_game/sprite_renderer.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/sprite_renderer.h rename to src/7.in_practice/3.2d_game/sprite_renderer.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/stb_image.cpp b/src/7.in_practice/3.2d_game/stb_image.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/stb_image.cpp rename to src/7.in_practice/3.2d_game/stb_image.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/text_renderer.cpp b/src/7.in_practice/3.2d_game/text_renderer.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/text_renderer.cpp rename to src/7.in_practice/3.2d_game/text_renderer.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/text_renderer.h b/src/7.in_practice/3.2d_game/text_renderer.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/text_renderer.h rename to src/7.in_practice/3.2d_game/text_renderer.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/texture.cpp b/src/7.in_practice/3.2d_game/texture.cpp similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/texture.cpp rename to src/7.in_practice/3.2d_game/texture.cpp diff --git a/src/7.in_practice/3.2d_game/0.full_source/texture.h b/src/7.in_practice/3.2d_game/texture.h similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/texture.h rename to src/7.in_practice/3.2d_game/texture.h diff --git a/src/7.in_practice/3.2d_game/0.full_source/textures/awesomeface.png b/src/7.in_practice/3.2d_game/textures/awesomeface.png similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/textures/awesomeface.png rename to src/7.in_practice/3.2d_game/textures/awesomeface.png diff --git a/src/7.in_practice/3.2d_game/0.full_source/textures/background.jpg b/src/7.in_practice/3.2d_game/textures/background.jpg similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/textures/background.jpg rename to src/7.in_practice/3.2d_game/textures/background.jpg diff --git a/src/7.in_practice/3.2d_game/0.full_source/textures/block.png b/src/7.in_practice/3.2d_game/textures/block.png similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/textures/block.png rename to src/7.in_practice/3.2d_game/textures/block.png diff --git a/src/7.in_practice/3.2d_game/0.full_source/textures/block_solid.png b/src/7.in_practice/3.2d_game/textures/block_solid.png similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/textures/block_solid.png rename to src/7.in_practice/3.2d_game/textures/block_solid.png diff --git a/src/7.in_practice/3.2d_game/0.full_source/textures/paddle.png b/src/7.in_practice/3.2d_game/textures/paddle.png similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/textures/paddle.png rename to src/7.in_practice/3.2d_game/textures/paddle.png diff --git a/src/7.in_practice/3.2d_game/0.full_source/textures/particle.png b/src/7.in_practice/3.2d_game/textures/particle.png similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/textures/particle.png rename to src/7.in_practice/3.2d_game/textures/particle.png diff --git a/src/7.in_practice/3.2d_game/0.full_source/textures/powerup_chaos.png b/src/7.in_practice/3.2d_game/textures/powerup_chaos.png similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/textures/powerup_chaos.png rename to src/7.in_practice/3.2d_game/textures/powerup_chaos.png diff --git a/src/7.in_practice/3.2d_game/0.full_source/textures/powerup_confuse.png b/src/7.in_practice/3.2d_game/textures/powerup_confuse.png similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/textures/powerup_confuse.png rename to src/7.in_practice/3.2d_game/textures/powerup_confuse.png diff --git a/src/7.in_practice/3.2d_game/0.full_source/textures/powerup_increase.png b/src/7.in_practice/3.2d_game/textures/powerup_increase.png similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/textures/powerup_increase.png rename to src/7.in_practice/3.2d_game/textures/powerup_increase.png diff --git a/src/7.in_practice/3.2d_game/0.full_source/textures/powerup_passthrough.png b/src/7.in_practice/3.2d_game/textures/powerup_passthrough.png similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/textures/powerup_passthrough.png rename to src/7.in_practice/3.2d_game/textures/powerup_passthrough.png diff --git a/src/7.in_practice/3.2d_game/0.full_source/textures/powerup_speed.png b/src/7.in_practice/3.2d_game/textures/powerup_speed.png similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/textures/powerup_speed.png rename to src/7.in_practice/3.2d_game/textures/powerup_speed.png diff --git a/src/7.in_practice/3.2d_game/0.full_source/textures/powerup_sticky.png b/src/7.in_practice/3.2d_game/textures/powerup_sticky.png similarity index 100% rename from src/7.in_practice/3.2d_game/0.full_source/textures/powerup_sticky.png rename to src/7.in_practice/3.2d_game/textures/powerup_sticky.png