Merged changes in the trunk up to revision 39826.
Made a major amount of conflict resolution for code adaptation to the animation system updates introduced in the Pepper branch recently merged to the trunk. Resolved conflicts: source/blender/blenkernel/intern/anim_sys.c source/blender/blenkernel/intern/library.c source/blender/editors/animation/anim_channels_defines.c source/blender/editors/animation/anim_channels_edit.c source/blender/editors/animation/anim_filter.c source/blender/editors/animation/keyframes_draw.c source/blender/editors/animation/keyframes_edit.c source/blender/editors/include/ED_anim_api.h source/blender/editors/space_nla/nla_buttons.c source/blender/editors/space_nla/nla_channels.c source/blender/makesdna/DNA_action_types.h source/blender/makesdna/intern/makesdna.c source/blender/makesrna/intern/rna_main_api.c
This commit is contained in:
		| @@ -14,7 +14,7 @@ USE_SDK=True | |||||||
| ###################     Cocoa & architecture settings      ################## | ###################     Cocoa & architecture settings      ################## | ||||||
| ############################################################################# | ############################################################################# | ||||||
| WITH_GHOST_COCOA=True | WITH_GHOST_COCOA=True | ||||||
| MACOSX_ARCHITECTURE = 'i386' # valid archs: ppc, i386, ppc64, x86_64 | MACOSX_ARCHITECTURE = 'x86_64' # valid archs: ppc, i386, ppc64, x86_64 | ||||||
|  |  | ||||||
|  |  | ||||||
| cmd = 'uname -p' | cmd = 'uname -p' | ||||||
| @@ -104,14 +104,26 @@ BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' | |||||||
| BF_FFMPEG_LIB = 'avcodec avdevice avformat avutil mp3lame swscale x264 xvidcore theora theoradec theoraenc vorbis vorbisenc vorbisfile ogg bz2' | BF_FFMPEG_LIB = 'avcodec avdevice avformat avutil mp3lame swscale x264 xvidcore theora theoradec theoraenc vorbis vorbisenc vorbisfile ogg bz2' | ||||||
| #bz2 is a standard osx dynlib | #bz2 is a standard osx dynlib | ||||||
|  |  | ||||||
| # python 3.1 uses precompiled libraries in bf svn /lib by default |  | ||||||
| BF_PYTHON_VERSION = '3.2' | BF_PYTHON_VERSION = '3.2' | ||||||
|  | WITH_OSX_STATICPYTHON = True | ||||||
|  |  | ||||||
|  | if WITH_OSX_STATICPYTHON: | ||||||
|  | 	# python 3.2 uses precompiled libraries in bf svn /lib by default | ||||||
|  |  | ||||||
| 	BF_PYTHON = LIBDIR + '/python' | 	BF_PYTHON = LIBDIR + '/python' | ||||||
| 	BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' | 	BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' | ||||||
| 	# BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' | 	# BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' | ||||||
| 	BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' | 	BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' | ||||||
| 	BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/python${BF_PYTHON_VERSION}' | 	BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/python${BF_PYTHON_VERSION}' | ||||||
| 	# BF_PYTHON_LINKFLAGS = ['-u', '_PyMac_Error', '-framework', 'System'] | 	# BF_PYTHON_LINKFLAGS = ['-u', '_PyMac_Error', '-framework', 'System'] | ||||||
|  | else: | ||||||
|  | 	# python 3.2 uses Python-framework additionally installed in /Library/Frameworks | ||||||
|  | 	 | ||||||
|  | 	BF_PYTHON = '/Library/Frameworks/Python.framework/Versions/' | ||||||
|  | 	BF_PYTHON_INC = '${BF_PYTHON}${BF_PYTHON_VERSION}/include/python${BF_PYTHON_VERSION}m' | ||||||
|  | 	BF_PYTHON_BINARY = '${BF_PYTHON}${BF_PYTHON_VERSION}/bin/python${BF_PYTHON_VERSION}' | ||||||
|  | 	#BF_PYTHON_LIB = '' | ||||||
|  | 	BF_PYTHON_LIBPATH = '${BF_PYTHON}${BF_PYTHON_VERSION}/lib/python${BF_PYTHON_VERSION}/config-3.2m' | ||||||
| 	 | 	 | ||||||
| WITH_BF_OPENAL = True | WITH_BF_OPENAL = True | ||||||
| #different lib must be used  following version of gcc | #different lib must be used  following version of gcc | ||||||
| @@ -315,6 +327,10 @@ if WITH_BF_QUICKTIME: | |||||||
| 	else: | 	else: | ||||||
| 		PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QuickTime'] | 		PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QuickTime'] | ||||||
|  |  | ||||||
|  | if not WITH_OSX_STATICPYTHON: | ||||||
|  | 		PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','Python'] | ||||||
|  |  | ||||||
|  |  | ||||||
| #note to build succesfully on 10.3.9 SDK you need to patch  10.3.9 by adding the SystemStubs.a lib from 10.4 | #note to build succesfully on 10.3.9 SDK you need to patch  10.3.9 by adding the SystemStubs.a lib from 10.4 | ||||||
| #for 10.7.sdk, SystemStubs needs to be excluded (lib doesn't exist anymore) | #for 10.7.sdk, SystemStubs needs to be excluded (lib doesn't exist anymore) | ||||||
| if MACOSX_DEPLOYMENT_TARGET == '10.7': | if MACOSX_DEPLOYMENT_TARGET == '10.7': | ||||||
|   | |||||||
| @@ -40,7 +40,7 @@ BF_JACK_INC = '${BF_JACK}/include ${BF_FFMPEG}/include/msvc' | |||||||
| BF_JACK_LIB = 'libjack' | BF_JACK_LIB = 'libjack' | ||||||
| BF_JACK_LIBPATH = '${BF_JACK}/lib' | BF_JACK_LIBPATH = '${BF_JACK}/lib' | ||||||
|  |  | ||||||
| WITH_BF_SNDFILE = False | WITH_BF_SNDFILE = True | ||||||
| BF_SNDFILE = LIBDIR + '/sndfile' | BF_SNDFILE = LIBDIR + '/sndfile' | ||||||
| BF_SNDFILE_INC = '${BF_SNDFILE}/include' | BF_SNDFILE_INC = '${BF_SNDFILE}/include' | ||||||
| BF_SNDFILE_LIB = 'libsndfile-1' | BF_SNDFILE_LIB = 'libsndfile-1' | ||||||
|   | |||||||
| @@ -536,7 +536,10 @@ def AppIt(target=None, source=None, env=None): | |||||||
|     print("Installing to %s"%(installdir)) |     print("Installing to %s"%(installdir)) | ||||||
|     # TODO, use tar. |     # TODO, use tar. | ||||||
|     python_zip = 'python_' + osxarch + '.zip' # set specific python_arch.zip |     python_zip = 'python_' + osxarch + '.zip' # set specific python_arch.zip | ||||||
|  |     if env['WITH_OSX_STATICPYTHON']: | ||||||
|         print("unzipping to app-bundle: %s"%(python_zip)) |         print("unzipping to app-bundle: %s"%(python_zip)) | ||||||
|  |     else: | ||||||
|  |         print("dynamic build - make sure to have python3.x-framework installed") | ||||||
|     bldroot = env.Dir('.').abspath |     bldroot = env.Dir('.').abspath | ||||||
|     binary = env['BINARYKIND'] |     binary = env['BINARYKIND'] | ||||||
|       |       | ||||||
| @@ -569,6 +572,7 @@ def AppIt(target=None, source=None, env=None): | |||||||
|     commands.getoutput(cmd) |     commands.getoutput(cmd) | ||||||
|     cmd = 'cp %s/release/bin/%s/.Blanguages %s/%s.app/Contents/Resources/'%(bldroot,VERSION,installdir,binary) |     cmd = 'cp %s/release/bin/%s/.Blanguages %s/%s.app/Contents/Resources/'%(bldroot,VERSION,installdir,binary) | ||||||
|     commands.getoutput(cmd) |     commands.getoutput(cmd) | ||||||
|  |     if env['WITH_OSX_STATICPYTHON']: | ||||||
|         cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/python/'%(installdir,binary, VERSION) |         cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/python/'%(installdir,binary, VERSION) | ||||||
|         commands.getoutput(cmd) |         commands.getoutput(cmd) | ||||||
|         cmd = 'unzip -q %s/release/%s -d %s/%s.app/Contents/MacOS/%s/python/'%(libdir,python_zip,installdir,binary,VERSION) |         cmd = 'unzip -q %s/release/%s -d %s/%s.app/Contents/MacOS/%s/python/'%(libdir,python_zip,installdir,binary,VERSION) | ||||||
|   | |||||||
| @@ -78,7 +78,7 @@ def print_arguments(args, bc): | |||||||
|  |  | ||||||
| def validate_arguments(args, bc): | def validate_arguments(args, bc): | ||||||
|     opts_list = [ |     opts_list = [ | ||||||
|             'WITH_BF_PYTHON', 'WITH_BF_PYTHON_SAFETY', 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'WITH_BF_STATICPYTHON', 'BF_PYTHON_LIB_STATIC', 'BF_PYTHON_DLL', 'BF_PYTHON_ABI_FLAGS',  |             'WITH_BF_PYTHON', 'WITH_BF_PYTHON_SAFETY', 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'WITH_BF_STATICPYTHON', 'WITH_OSX_STATICPYTHON', 'BF_PYTHON_LIB_STATIC', 'BF_PYTHON_DLL', 'BF_PYTHON_ABI_FLAGS',  | ||||||
|             'WITH_BF_OPENAL', 'BF_OPENAL', 'BF_OPENAL_INC', 'BF_OPENAL_LIB', 'BF_OPENAL_LIBPATH', 'WITH_BF_STATICOPENAL', 'BF_OPENAL_LIB_STATIC', |             'WITH_BF_OPENAL', 'BF_OPENAL', 'BF_OPENAL_INC', 'BF_OPENAL_LIB', 'BF_OPENAL_LIBPATH', 'WITH_BF_STATICOPENAL', 'BF_OPENAL_LIB_STATIC', | ||||||
|             'WITH_BF_SDL', 'BF_SDL', 'BF_SDL_INC', 'BF_SDL_LIB', 'BF_SDL_LIBPATH', |             'WITH_BF_SDL', 'BF_SDL', 'BF_SDL_INC', 'BF_SDL_LIB', 'BF_SDL_LIBPATH', | ||||||
|             'BF_LIBSAMPLERATE', 'BF_LIBSAMPLERATE_INC', 'BF_LIBSAMPLERATE_LIB', 'BF_LIBSAMPLERATE_LIBPATH', 'WITH_BF_STATICLIBSAMPLERATE', 'BF_LIBSAMPLERATE_LIB_STATIC', |             'BF_LIBSAMPLERATE', 'BF_LIBSAMPLERATE_INC', 'BF_LIBSAMPLERATE_LIB', 'BF_LIBSAMPLERATE_LIBPATH', 'WITH_BF_STATICLIBSAMPLERATE', 'BF_LIBSAMPLERATE_LIB_STATIC', | ||||||
| @@ -230,6 +230,7 @@ def read_opts(env, cfg, args): | |||||||
|         ('BF_PYTHON_LIBPATH', 'Library path', ''), |         ('BF_PYTHON_LIBPATH', 'Library path', ''), | ||||||
|         ('BF_PYTHON_LINKFLAGS', 'Python link flags', ''), |         ('BF_PYTHON_LINKFLAGS', 'Python link flags', ''), | ||||||
|         (BoolVariable('WITH_BF_STATICPYTHON', 'Staticly link to python', False)), |         (BoolVariable('WITH_BF_STATICPYTHON', 'Staticly link to python', False)), | ||||||
|  |         (BoolVariable('WITH_OSX_STATICPYTHON', 'Staticly link to python', True)), | ||||||
|         ('BF_PYTHON_ABI_FLAGS', 'Python ABI flags (suffix in library version: m, mu, etc)', ''), |         ('BF_PYTHON_ABI_FLAGS', 'Python ABI flags (suffix in library version: m, mu, etc)', ''), | ||||||
|  |  | ||||||
|         (BoolVariable('BF_NO_ELBEEM', 'Disable Fluid Sim', False)), |         (BoolVariable('BF_NO_ELBEEM', 'Disable Fluid Sim', False)), | ||||||
|   | |||||||
| @@ -215,6 +215,18 @@ Functions | |||||||
|    :type setting: string (lights, shaders, shadows, ramps, nodes, extra_textures) |    :type setting: string (lights, shaders, shadows, ramps, nodes, extra_textures) | ||||||
|    :rtype: boolean |    :rtype: boolean | ||||||
|  |  | ||||||
|  | .. function:: setAnisotropicFiltering(level) | ||||||
|  |  | ||||||
|  |    Set the anisotropic filtering level for textures. | ||||||
|  |     | ||||||
|  |    :arg level: The new anisotropic filtering level to use | ||||||
|  |    :type level: integer (must be one of 1, 2, 4, 8, 16) | ||||||
|  |     | ||||||
|  | .. function:: getAnisotropicFiltering() | ||||||
|  |  | ||||||
|  |    Get the anisotropic filtering level used for textures. | ||||||
|  |     | ||||||
|  |    :rtype: integer (one of 1, 2, 4, 8, 16) | ||||||
|     |     | ||||||
| .. function:: drawLine(fromVec,toVec,color) | .. function:: drawLine(fromVec,toVec,color) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1539,6 +1539,67 @@ Game Types (bge.types) | |||||||
|       Return the value matching key, or the default value if its not found. |       Return the value matching key, or the default value if its not found. | ||||||
|       :return: The key value or a default. |       :return: The key value or a default. | ||||||
|  |  | ||||||
|  |    .. method:: playAction(name, start_frame, end_frame, layer=0, priority=0 blendin=0, play_mode=ACT_MODE_PLAY, layer_weight=0.0, ipo_flags=0, speed=1.0) | ||||||
|  |  | ||||||
|  |       Plays an action. | ||||||
|  |        | ||||||
|  |       :arg name: the name of the action | ||||||
|  |       :type name: string | ||||||
|  |       :arg start: the start frame of the action | ||||||
|  |       :type start: float | ||||||
|  |       :arg end: the end frame of the action | ||||||
|  |       :type end: float | ||||||
|  |       :arg layer: the layer the action will play in (actions in different layers are added/blended together) | ||||||
|  |       :type layer: integer | ||||||
|  |       :arg priority: only play this action if there isn't an action currently playing in this layer with a higher (lower number) priority | ||||||
|  |       :type priority: integer | ||||||
|  |       :arg blendin: the amount of blending between this animation and the previous one on this layer | ||||||
|  |       :type blendin: float | ||||||
|  |       :arg play_mode: the play mode | ||||||
|  |       :type play_mode: KX_ACTION_PLAY, KX_ACTION_LOOP, or KX_ACTION_PING_PONG | ||||||
|  |       :arg layer_weight: how much of the previous layer to use for blending (0 = add) | ||||||
|  |       :type layer_weight: float | ||||||
|  |       :arg ipo_flags: flags for the old IPO behaviors (force, etc) | ||||||
|  |       :type ipo_flags: int bitfield | ||||||
|  |       :arg speed: the playback speed of the action as a factor (1.0 = normal speed, 2.0 = 2x speed, etc) | ||||||
|  |       :type speed: float | ||||||
|  |  | ||||||
|  |    .. method:: stopAction(layer=0) | ||||||
|  |        | ||||||
|  |       Stop playing the action on the given layer. | ||||||
|  |        | ||||||
|  |       :arg layer: The layer to stop playing. | ||||||
|  |       :type layer: integer | ||||||
|  |        | ||||||
|  |    .. method:: getActionFrame(layer=0) | ||||||
|  |     | ||||||
|  |       Gets the current frame of the action playing in the supplied layer. | ||||||
|  |        | ||||||
|  |       :arg layer: The layer that you want to get the frame from. | ||||||
|  |       :type layer: integer | ||||||
|  |        | ||||||
|  |       :return: The current frame of the action | ||||||
|  |       :rtype: float | ||||||
|  |        | ||||||
|  |    .. method:: setActionFrame(frame, layer=0) | ||||||
|  |     | ||||||
|  |       Set the current frame of the action playing in the supplied layer. | ||||||
|  |        | ||||||
|  |       :arg layer: The layer where you want to set the frame | ||||||
|  |       :type layer: integer | ||||||
|  |       :arg frame: The frame to set the action to | ||||||
|  |       :type frame: float | ||||||
|  |  | ||||||
|  |    .. method:: isPlayingAction(layer=0) | ||||||
|  |     | ||||||
|  |        Checks to see if there is an action playing in the given layer. | ||||||
|  |         | ||||||
|  |        :arg layer: The layer to check for a playing action. | ||||||
|  |        :type layer: integer | ||||||
|  |         | ||||||
|  |        :return: Whether or not the action is playing | ||||||
|  |        :rtype: boolean | ||||||
|  |  | ||||||
| .. class:: KX_IpoActuator(SCA_IActuator) | .. class:: KX_IpoActuator(SCA_IActuator) | ||||||
|  |  | ||||||
|    IPO actuator activates an animation. |    IPO actuator activates an animation. | ||||||
|   | |||||||
| @@ -1236,7 +1236,6 @@ def rna2sphinx(BASEPATH): | |||||||
|  |  | ||||||
|     shutil.copy2(os.path.join(BASEPATH, "..", "rst", "change_log.rst"), BASEPATH) |     shutil.copy2(os.path.join(BASEPATH, "..", "rst", "change_log.rst"), BASEPATH) | ||||||
|  |  | ||||||
|  |  | ||||||
|     if not EXCLUDE_INFO_DOCS: |     if not EXCLUDE_INFO_DOCS: | ||||||
|         for info, info_desc in INFO_DOCS: |         for info, info_desc in INFO_DOCS: | ||||||
|             shutil.copy2(os.path.join(BASEPATH, "..", "rst", info), BASEPATH) |             shutil.copy2(os.path.join(BASEPATH, "..", "rst", info), BASEPATH) | ||||||
|   | |||||||
| @@ -41,6 +41,8 @@ set(SRC | |||||||
| 	FX/AUD_DelayReader.cpp | 	FX/AUD_DelayReader.cpp | ||||||
| 	FX/AUD_DoubleFactory.cpp | 	FX/AUD_DoubleFactory.cpp | ||||||
| 	FX/AUD_DoubleReader.cpp | 	FX/AUD_DoubleReader.cpp | ||||||
|  | 	FX/AUD_DynamicIIRFilterFactory.cpp | ||||||
|  | 	FX/AUD_DynamicIIRFilterReader.cpp | ||||||
| 	FX/AUD_EffectFactory.cpp | 	FX/AUD_EffectFactory.cpp | ||||||
| 	FX/AUD_EffectReader.cpp | 	FX/AUD_EffectReader.cpp | ||||||
| 	FX/AUD_EnvelopeFactory.cpp | 	FX/AUD_EnvelopeFactory.cpp | ||||||
| @@ -66,6 +68,8 @@ set(SRC | |||||||
| 	FX/AUD_SuperposeReader.cpp | 	FX/AUD_SuperposeReader.cpp | ||||||
| 	FX/AUD_VolumeFactory.cpp | 	FX/AUD_VolumeFactory.cpp | ||||||
| 	intern/AUD_3DMath.h | 	intern/AUD_3DMath.h | ||||||
|  | 	intern/AUD_AnimateableProperty.cpp | ||||||
|  | 	intern/AUD_AnimateableProperty.h | ||||||
| 	intern/AUD_Buffer.cpp | 	intern/AUD_Buffer.cpp | ||||||
| 	intern/AUD_Buffer.h | 	intern/AUD_Buffer.h | ||||||
| 	intern/AUD_BufferReader.cpp | 	intern/AUD_BufferReader.cpp | ||||||
| @@ -82,14 +86,21 @@ set(SRC | |||||||
| 	intern/AUD_ConverterFunctions.h | 	intern/AUD_ConverterFunctions.h | ||||||
| 	intern/AUD_ConverterReader.cpp | 	intern/AUD_ConverterReader.cpp | ||||||
| 	intern/AUD_ConverterReader.h | 	intern/AUD_ConverterReader.h | ||||||
| 	intern/AUD_DefaultMixer.cpp |  | ||||||
| 	intern/AUD_DefaultMixer.h |  | ||||||
| 	intern/AUD_FileFactory.cpp | 	intern/AUD_FileFactory.cpp | ||||||
| 	intern/AUD_FileFactory.h | 	intern/AUD_FileFactory.h | ||||||
|  | 	intern/AUD_FileWriter.cpp | ||||||
|  | 	intern/AUD_FileWriter.h | ||||||
| 	intern/AUD_I3DDevice.h | 	intern/AUD_I3DDevice.h | ||||||
|  | 	intern/AUD_I3DHandle.h | ||||||
| 	intern/AUD_IDevice.h | 	intern/AUD_IDevice.h | ||||||
| 	intern/AUD_IFactory.h | 	intern/AUD_IFactory.h | ||||||
|  | 	intern/AUD_IHandle.h | ||||||
| 	intern/AUD_IReader.h | 	intern/AUD_IReader.h | ||||||
|  | 	intern/AUD_IWriter.h | ||||||
|  | 	intern/AUD_JOSResampleFactory.cpp | ||||||
|  | 	intern/AUD_JOSResampleFactory.h | ||||||
|  | 	intern/AUD_JOSResampleReader.cpp | ||||||
|  | 	intern/AUD_JOSResampleReader.h | ||||||
| 	intern/AUD_LinearResampleFactory.cpp | 	intern/AUD_LinearResampleFactory.cpp | ||||||
| 	intern/AUD_LinearResampleFactory.h | 	intern/AUD_LinearResampleFactory.h | ||||||
| 	intern/AUD_LinearResampleReader.cpp | 	intern/AUD_LinearResampleReader.cpp | ||||||
| @@ -104,9 +115,16 @@ set(SRC | |||||||
| 	intern/AUD_ReadDevice.cpp | 	intern/AUD_ReadDevice.cpp | ||||||
| 	intern/AUD_ReadDevice.h | 	intern/AUD_ReadDevice.h | ||||||
| 	intern/AUD_Reference.h | 	intern/AUD_Reference.h | ||||||
|  | 	intern/AUD_ReferenceHandler.cpp | ||||||
| 	intern/AUD_ResampleFactory.h | 	intern/AUD_ResampleFactory.h | ||||||
|  | 	intern/AUD_ResampleReader.cpp | ||||||
|  | 	intern/AUD_ResampleReader.h | ||||||
|  | 	intern/AUD_SequencerEntry.cpp | ||||||
|  | 	intern/AUD_SequencerEntry.h | ||||||
| 	intern/AUD_SequencerFactory.cpp | 	intern/AUD_SequencerFactory.cpp | ||||||
| 	intern/AUD_SequencerFactory.h | 	intern/AUD_SequencerFactory.h | ||||||
|  | 	intern/AUD_SequencerHandle.cpp | ||||||
|  | 	intern/AUD_SequencerHandle.h | ||||||
| 	intern/AUD_SequencerReader.cpp | 	intern/AUD_SequencerReader.cpp | ||||||
| 	intern/AUD_SequencerReader.h | 	intern/AUD_SequencerReader.h | ||||||
| 	intern/AUD_SilenceFactory.cpp | 	intern/AUD_SilenceFactory.cpp | ||||||
| @@ -131,6 +149,8 @@ set(SRC | |||||||
| 	FX/AUD_DelayReader.h | 	FX/AUD_DelayReader.h | ||||||
| 	FX/AUD_DoubleFactory.h | 	FX/AUD_DoubleFactory.h | ||||||
| 	FX/AUD_DoubleReader.h | 	FX/AUD_DoubleReader.h | ||||||
|  | 	FX/AUD_DynamicIIRFilterFactory.h | ||||||
|  | 	FX/AUD_DynamicIIRFilterReader.h | ||||||
| 	FX/AUD_EffectFactory.h | 	FX/AUD_EffectFactory.h | ||||||
| 	FX/AUD_EffectReader.h | 	FX/AUD_EffectReader.h | ||||||
| 	FX/AUD_EnvelopeFactory.h | 	FX/AUD_EnvelopeFactory.h | ||||||
| @@ -168,9 +188,11 @@ if(WITH_CODEC_FFMPEG) | |||||||
| 	list(APPEND SRC | 	list(APPEND SRC | ||||||
| 		ffmpeg/AUD_FFMPEGFactory.cpp | 		ffmpeg/AUD_FFMPEGFactory.cpp | ||||||
| 		ffmpeg/AUD_FFMPEGReader.cpp | 		ffmpeg/AUD_FFMPEGReader.cpp | ||||||
|  | 		ffmpeg/AUD_FFMPEGWriter.cpp | ||||||
|  |  | ||||||
| 		ffmpeg/AUD_FFMPEGFactory.h | 		ffmpeg/AUD_FFMPEGFactory.h | ||||||
| 		ffmpeg/AUD_FFMPEGReader.h | 		ffmpeg/AUD_FFMPEGReader.h | ||||||
|  | 		ffmpeg/AUD_FFMPEGWriter.h | ||||||
| 	) | 	) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
| @@ -230,9 +252,11 @@ if(WITH_CODEC_SNDFILE) | |||||||
| 	list(APPEND SRC | 	list(APPEND SRC | ||||||
| 		sndfile/AUD_SndFileFactory.cpp | 		sndfile/AUD_SndFileFactory.cpp | ||||||
| 		sndfile/AUD_SndFileReader.cpp | 		sndfile/AUD_SndFileReader.cpp | ||||||
|  | 		sndfile/AUD_SndFileWriter.cpp | ||||||
|  |  | ||||||
| 		sndfile/AUD_SndFileFactory.h | 		sndfile/AUD_SndFileFactory.h | ||||||
| 		sndfile/AUD_SndFileReader.h | 		sndfile/AUD_SndFileReader.h | ||||||
|  | 		sndfile/AUD_SndFileWriter.h | ||||||
| 	) | 	) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ | |||||||
| #include "AUD_AccumulatorFactory.h" | #include "AUD_AccumulatorFactory.h" | ||||||
| #include "AUD_CallbackIIRFilterReader.h" | #include "AUD_CallbackIIRFilterReader.h" | ||||||
|  |  | ||||||
| sample_t accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* useless) | sample_t AUD_AccumulatorFactory::accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* useless) | ||||||
| { | { | ||||||
| 	float in = reader->x(0); | 	float in = reader->x(0); | ||||||
| 	float lastin = reader->x(-1); | 	float lastin = reader->x(-1); | ||||||
| @@ -42,7 +42,7 @@ sample_t accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* us | |||||||
| 	return out; | 	return out; | ||||||
| } | } | ||||||
|  |  | ||||||
| sample_t accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless) | sample_t AUD_AccumulatorFactory::accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless) | ||||||
| { | { | ||||||
| 	float in = reader->x(0); | 	float in = reader->x(0); | ||||||
| 	float lastin = reader->x(-1); | 	float lastin = reader->x(-1); | ||||||
| @@ -52,14 +52,14 @@ sample_t accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless) | |||||||
| 	return out; | 	return out; | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_AccumulatorFactory::AUD_AccumulatorFactory(AUD_IFactory* factory, | AUD_AccumulatorFactory::AUD_AccumulatorFactory(AUD_Reference<AUD_IFactory> factory, | ||||||
| 											   bool additive) : | 											   bool additive) : | ||||||
| 		AUD_EffectFactory(factory), | 		AUD_EffectFactory(factory), | ||||||
| 		m_additive(additive) | 		m_additive(additive) | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_AccumulatorFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_AccumulatorFactory::createReader() | ||||||
| { | { | ||||||
| 	return new AUD_CallbackIIRFilterReader(getReader(), 2, 2, | 	return new AUD_CallbackIIRFilterReader(getReader(), 2, 2, | ||||||
| 							m_additive ? accumulatorFilterAdditive : accumulatorFilter); | 							m_additive ? accumulatorFilterAdditive : accumulatorFilter); | ||||||
|   | |||||||
| @@ -33,9 +33,14 @@ | |||||||
| #define AUD_ACCUMULATORFACTORY | #define AUD_ACCUMULATORFACTORY | ||||||
|  |  | ||||||
| #include "AUD_EffectFactory.h" | #include "AUD_EffectFactory.h" | ||||||
|  | class AUD_CallbackIIRFilterReader; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This factory creates an accumulator reader. |  * This factory creates an accumulator reader. | ||||||
|  |  * | ||||||
|  |  * The accumulator adds the difference at the input to the last output in case | ||||||
|  |  * it's positive. In additive mode it additionaly adds the difference always. | ||||||
|  |  * So in case the difference is positive, it's added twice. | ||||||
|  */ |  */ | ||||||
| class AUD_AccumulatorFactory : public AUD_EffectFactory | class AUD_AccumulatorFactory : public AUD_EffectFactory | ||||||
| { | { | ||||||
| @@ -55,9 +60,12 @@ public: | |||||||
| 	 * \param factory The input factory. | 	 * \param factory The input factory. | ||||||
| 	 * \param additive Whether the accumulator is additive. | 	 * \param additive Whether the accumulator is additive. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_AccumulatorFactory(AUD_IFactory* factory, bool additive = false); | 	AUD_AccumulatorFactory(AUD_Reference<AUD_IFactory> factory, bool additive = false); | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
|  |  | ||||||
|  | 	static sample_t accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* useless); | ||||||
|  | 	static sample_t accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_ACCUMULATORFACTORY | #endif //AUD_ACCUMULATORFACTORY | ||||||
|   | |||||||
| @@ -33,20 +33,20 @@ | |||||||
|  |  | ||||||
| #include <cstring> | #include <cstring> | ||||||
|  |  | ||||||
| #define CC m_channels + m_channel | #define CC m_specs.channels + m_channel | ||||||
|  |  | ||||||
| AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(AUD_IReader* reader, int in, | AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in, | ||||||
| 												 int out) : | 												 int out) : | ||||||
| 		AUD_EffectReader(reader), | 		AUD_EffectReader(reader), | ||||||
| 		m_channels(reader->getSpecs().channels), | 		m_specs(reader->getSpecs()), | ||||||
| 		m_xlen(in), m_ylen(out), | 		m_xlen(in), m_ylen(out), | ||||||
| 		m_xpos(0), m_ypos(0), m_channel(0) | 		m_xpos(0), m_ypos(0), m_channel(0) | ||||||
| { | { | ||||||
| 	m_x = new sample_t[in * m_channels]; | 	m_x = new sample_t[m_xlen * m_specs.channels]; | ||||||
| 	m_y = new sample_t[out * m_channels]; | 	m_y = new sample_t[m_ylen * m_specs.channels]; | ||||||
|  |  | ||||||
| 	memset(m_x, 0, sizeof(sample_t) * in * m_channels); | 	memset(m_x, 0, sizeof(sample_t) * m_xlen * m_specs.channels); | ||||||
| 	memset(m_y, 0, sizeof(sample_t) * out * m_channels); | 	memset(m_y, 0, sizeof(sample_t) * m_ylen * m_specs.channels); | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_BaseIIRFilterReader::~AUD_BaseIIRFilterReader() | AUD_BaseIIRFilterReader::~AUD_BaseIIRFilterReader() | ||||||
| @@ -55,24 +55,77 @@ AUD_BaseIIRFilterReader::~AUD_BaseIIRFilterReader() | |||||||
| 	delete[] m_y; | 	delete[] m_y; | ||||||
| } | } | ||||||
|  |  | ||||||
| void AUD_BaseIIRFilterReader::read(int & length, sample_t* & buffer) | void AUD_BaseIIRFilterReader::setLengths(int in, int out) | ||||||
| { | { | ||||||
| 	sample_t* buf; | 	if(in != m_xlen) | ||||||
|  | 	{ | ||||||
|  | 		sample_t* xn = new sample_t[in * m_specs.channels]; | ||||||
|  | 		memset(xn, 0, sizeof(sample_t) * in * m_specs.channels); | ||||||
|  |  | ||||||
| 	int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs()); | 		for(m_channel = 0; m_channel < m_specs.channels; m_channel++) | ||||||
|  | 		{ | ||||||
|  | 			for(int i = 1; i <= in && i <= m_xlen; i++) | ||||||
|  | 			{ | ||||||
|  | 				xn[(in - i) * CC] = x(-i); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 	m_reader->read(length, buf); | 		delete[] m_x; | ||||||
|  | 		m_x = xn; | ||||||
|  | 		m_xpos = 0; | ||||||
|  | 		m_xlen = in; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if(m_buffer.getSize() < length * samplesize) | 	if(out != m_ylen) | ||||||
| 		m_buffer.resize(length * samplesize); | 	{ | ||||||
|  | 		sample_t* yn = new sample_t[out * m_specs.channels]; | ||||||
|  | 		memset(yn, 0, sizeof(sample_t) * out * m_specs.channels); | ||||||
|  |  | ||||||
| 	buffer = m_buffer.getBuffer(); | 		for(m_channel = 0; m_channel < m_specs.channels; m_channel++) | ||||||
|  | 		{ | ||||||
|  | 			for(int i = 1; i <= out && i <= m_ylen; i++) | ||||||
|  | 			{ | ||||||
|  | 				yn[(out - i) * CC] = y(-i); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 	for(m_channel = 0; m_channel < m_channels; m_channel++) | 		delete[] m_y; | ||||||
|  | 		m_y = yn; | ||||||
|  | 		m_ypos = 0; | ||||||
|  | 		m_ylen = out; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AUD_BaseIIRFilterReader::read(int& length, bool& eos, sample_t* buffer) | ||||||
|  | { | ||||||
|  | 	AUD_Specs specs = m_reader->getSpecs(); | ||||||
|  | 	if(specs.channels != m_specs.channels) | ||||||
|  | 	{ | ||||||
|  | 		m_specs.channels = specs.channels; | ||||||
|  |  | ||||||
|  | 		delete[] m_x; | ||||||
|  | 		delete[] m_y; | ||||||
|  |  | ||||||
|  | 		m_x = new sample_t[m_xlen * m_specs.channels]; | ||||||
|  | 		m_y = new sample_t[m_ylen * m_specs.channels]; | ||||||
|  |  | ||||||
|  | 		memset(m_x, 0, sizeof(sample_t) * m_xlen * m_specs.channels); | ||||||
|  | 		memset(m_y, 0, sizeof(sample_t) * m_ylen * m_specs.channels); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if(specs.rate != m_specs.rate) | ||||||
|  | 	{ | ||||||
|  | 		m_specs = specs; | ||||||
|  | 		sampleRateChanged(m_specs.rate); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	m_reader->read(length, eos, buffer); | ||||||
|  |  | ||||||
|  | 	for(m_channel = 0; m_channel < m_specs.channels; m_channel++) | ||||||
| 	{ | 	{ | ||||||
| 		for(int i = 0; i < length; i++) | 		for(int i = 0; i < length; i++) | ||||||
| 		{ | 		{ | ||||||
| 			m_x[m_xpos * CC] = buf[i * CC]; | 			m_x[m_xpos * CC] = buffer[i * CC]; | ||||||
| 			m_y[m_ypos * CC] = buffer[i * CC] = filter(); | 			m_y[m_ypos * CC] = buffer[i * CC] = filter(); | ||||||
|  |  | ||||||
| 			m_xpos = (m_xpos + 1) % m_xlen; | 			m_xpos = (m_xpos + 1) % m_xlen; | ||||||
| @@ -80,3 +133,7 @@ void AUD_BaseIIRFilterReader::read(int & length, sample_t* & buffer) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void AUD_BaseIIRFilterReader::sampleRateChanged(AUD_SampleRate rate) | ||||||
|  | { | ||||||
|  | } | ||||||
|   | |||||||
| @@ -42,24 +42,19 @@ class AUD_BaseIIRFilterReader : public AUD_EffectReader | |||||||
| { | { | ||||||
| private: | private: | ||||||
| 	/** | 	/** | ||||||
| 	 * Channel count. | 	 * Specs. | ||||||
| 	 */ | 	 */ | ||||||
| 	const int m_channels; | 	AUD_Specs m_specs; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Length of input samples needed. | 	 * Length of input samples needed. | ||||||
| 	 */ | 	 */ | ||||||
| 	const int m_xlen; | 	int m_xlen; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Length of output samples needed. | 	 * Length of output samples needed. | ||||||
| 	 */ | 	 */ | ||||||
| 	const int m_ylen; | 	int m_ylen; | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * The playback buffer. |  | ||||||
| 	 */ |  | ||||||
| 	AUD_Buffer m_buffer; |  | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The last in samples array. | 	 * The last in samples array. | ||||||
| @@ -97,24 +92,46 @@ protected: | |||||||
| 	 * \param in The count of past input samples needed. | 	 * \param in The count of past input samples needed. | ||||||
| 	 * \param out The count of past output samples needed. | 	 * \param out The count of past output samples needed. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_BaseIIRFilterReader(AUD_IReader* reader, int in, int out); | 	AUD_BaseIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in, int out); | ||||||
|  |  | ||||||
|  | 	void setLengths(int in, int out); | ||||||
|  |  | ||||||
| public: | public: | ||||||
|  | 	/** | ||||||
|  | 	 * Retrieves the last input samples. | ||||||
|  | 	 * \param pos The position, valid are 0 (current) or negative values. | ||||||
|  | 	 * \return The sample value. | ||||||
|  | 	 */ | ||||||
| 	inline sample_t x(int pos) | 	inline sample_t x(int pos) | ||||||
| 	{ | 	{ | ||||||
| 		return m_x[(m_xpos + pos + m_xlen) % m_xlen * m_channels + m_channel]; | 		return m_x[(m_xpos + pos + m_xlen) % m_xlen * m_specs.channels + m_channel]; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Retrieves the last output samples. | ||||||
|  | 	 * \param pos The position, valid are negative values. | ||||||
|  | 	 * \return The sample value. | ||||||
|  | 	 */ | ||||||
| 	inline sample_t y(int pos) | 	inline sample_t y(int pos) | ||||||
| 	{ | 	{ | ||||||
| 		return m_y[(m_ypos + pos + m_ylen) % m_ylen * m_channels + m_channel]; | 		return m_y[(m_ypos + pos + m_ylen) % m_ylen * m_specs.channels + m_channel]; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	virtual ~AUD_BaseIIRFilterReader(); | 	virtual ~AUD_BaseIIRFilterReader(); | ||||||
|  |  | ||||||
| 	virtual void read(int & length, sample_t* & buffer); | 	virtual void read(int& length, bool& eos, sample_t* buffer); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Runs the filtering function. | ||||||
|  | 	 * \return The current output sample value. | ||||||
|  | 	 */ | ||||||
| 	virtual sample_t filter()=0; | 	virtual sample_t filter()=0; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Notifies the filter about a sample rate change. | ||||||
|  | 	 * \param rate The new sample rate. | ||||||
|  | 	 */ | ||||||
|  | 	virtual void sampleRateChanged(AUD_SampleRate rate); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_BASEIIRFILTERREADER | #endif //AUD_BASEIIRFILTERREADER | ||||||
|   | |||||||
| @@ -41,19 +41,18 @@ | |||||||
| #define BWPB41 0.76536686473 | #define BWPB41 0.76536686473 | ||||||
| #define BWPB42 1.84775906502 | #define BWPB42 1.84775906502 | ||||||
|  |  | ||||||
| AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_IFactory* factory, | AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_Reference<AUD_IFactory> factory, | ||||||
| 											   float frequency) : | 											   float frequency) : | ||||||
| 		AUD_EffectFactory(factory), | 		AUD_DynamicIIRFilterFactory(factory), | ||||||
| 		m_frequency(frequency) | 		m_frequency(frequency) | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_ButterworthFactory::createReader() const | void AUD_ButterworthFactory::recalculateCoefficients(AUD_SampleRate rate, | ||||||
|  | 													 std::vector<float> &b, | ||||||
|  | 													 std::vector<float> &a) | ||||||
| { | { | ||||||
| 	AUD_IReader* reader = getReader(); | 	float omega = 2 * tan(m_frequency * M_PI / rate); | ||||||
|  |  | ||||||
| 	// calculate coefficients |  | ||||||
| 	float omega = 2 * tan(m_frequency * M_PI / reader->getSpecs().rate); |  | ||||||
| 	float o2 = omega * omega; | 	float o2 = omega * omega; | ||||||
| 	float o4 = o2 * o2; | 	float o4 = o2 * o2; | ||||||
| 	float x1 = o2 + 2 * BWPB41 * omega + 4; | 	float x1 = o2 + 2 * BWPB41 * omega + 4; | ||||||
| @@ -62,7 +61,6 @@ AUD_IReader* AUD_ButterworthFactory::createReader() const | |||||||
| 	float y2 = o2 - 2 * BWPB42 * omega + 4; | 	float y2 = o2 - 2 * BWPB42 * omega + 4; | ||||||
| 	float o228 = 2 * o2 - 8; | 	float o228 = 2 * o2 - 8; | ||||||
| 	float norm = x1 * x2; | 	float norm = x1 * x2; | ||||||
| 	std::vector<float> a, b; |  | ||||||
| 	a.push_back(1); | 	a.push_back(1); | ||||||
| 	a.push_back((x1 + x2) * o228 / norm); | 	a.push_back((x1 + x2) * o228 / norm); | ||||||
| 	a.push_back((x1 * y2 + x2 * y1 + o228 * o228) / norm); | 	a.push_back((x1 * y2 + x2 * y1 + o228 * o228) / norm); | ||||||
| @@ -73,6 +71,4 @@ AUD_IReader* AUD_ButterworthFactory::createReader() const | |||||||
| 	b.push_back(6 * o4 / norm); | 	b.push_back(6 * o4 / norm); | ||||||
| 	b.push_back(b[1]); | 	b.push_back(b[1]); | ||||||
| 	b.push_back(b[0]); | 	b.push_back(b[0]); | ||||||
|  |  | ||||||
| 	return new AUD_IIRFilterReader(reader, b, a); |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -32,12 +32,12 @@ | |||||||
| #ifndef AUD_BUTTERWORTHFACTORY | #ifndef AUD_BUTTERWORTHFACTORY | ||||||
| #define AUD_BUTTERWORTHFACTORY | #define AUD_BUTTERWORTHFACTORY | ||||||
|  |  | ||||||
| #include "AUD_EffectFactory.h" | #include "AUD_DynamicIIRFilterFactory.h" | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This factory creates a butterworth filter reader. |  * This factory creates a butterworth lowpass filter reader. | ||||||
|  */ |  */ | ||||||
| class AUD_ButterworthFactory : public AUD_EffectFactory | class AUD_ButterworthFactory : public AUD_DynamicIIRFilterFactory | ||||||
| { | { | ||||||
| private: | private: | ||||||
| 	/** | 	/** | ||||||
| @@ -55,9 +55,11 @@ public: | |||||||
| 	 * \param factory The input factory. | 	 * \param factory The input factory. | ||||||
| 	 * \param frequency The cutoff frequency. | 	 * \param frequency The cutoff frequency. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_ButterworthFactory(AUD_IFactory* factory, float frequency); | 	AUD_ButterworthFactory(AUD_Reference<AUD_IFactory> factory, float frequency); | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual void recalculateCoefficients(AUD_SampleRate rate, | ||||||
|  | 										 std::vector<float>& b, | ||||||
|  | 										 std::vector<float>& a); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_BUTTERWORTHFACTORY | #endif //AUD_BUTTERWORTHFACTORY | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ | |||||||
|  |  | ||||||
| #include "AUD_CallbackIIRFilterReader.h" | #include "AUD_CallbackIIRFilterReader.h" | ||||||
|  |  | ||||||
| AUD_CallbackIIRFilterReader::AUD_CallbackIIRFilterReader(AUD_IReader* reader, | AUD_CallbackIIRFilterReader::AUD_CallbackIIRFilterReader(AUD_Reference<AUD_IReader> reader, | ||||||
| 														 int in, int out, | 														 int in, int out, | ||||||
| 														 doFilterIIR doFilter, | 														 doFilterIIR doFilter, | ||||||
| 														 endFilterIIR endFilter, | 														 endFilterIIR endFilter, | ||||||
|   | |||||||
| @@ -76,7 +76,7 @@ public: | |||||||
| 	 * \param endFilter The finishing callback. | 	 * \param endFilter The finishing callback. | ||||||
| 	 * \param data Data pointer for the callbacks. | 	 * \param data Data pointer for the callbacks. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_CallbackIIRFilterReader(AUD_IReader* reader, int in, int out, | 	AUD_CallbackIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in, int out, | ||||||
| 								doFilterIIR doFilter, | 								doFilterIIR doFilter, | ||||||
| 								endFilterIIR endFilter = 0, | 								endFilterIIR endFilter = 0, | ||||||
| 								void* data = 0); | 								void* data = 0); | ||||||
|   | |||||||
| @@ -33,7 +33,7 @@ | |||||||
| #include "AUD_DelayReader.h" | #include "AUD_DelayReader.h" | ||||||
| #include "AUD_Space.h" | #include "AUD_Space.h" | ||||||
|  |  | ||||||
| AUD_DelayFactory::AUD_DelayFactory(AUD_IFactory* factory, float delay) : | AUD_DelayFactory::AUD_DelayFactory(AUD_Reference<AUD_IFactory> factory, float delay) : | ||||||
| 		AUD_EffectFactory(factory), | 		AUD_EffectFactory(factory), | ||||||
| 		m_delay(delay) | 		m_delay(delay) | ||||||
| { | { | ||||||
| @@ -44,7 +44,7 @@ float AUD_DelayFactory::getDelay() const | |||||||
| 	return m_delay; | 	return m_delay; | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_DelayFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_DelayFactory::createReader() | ||||||
| { | { | ||||||
| 	return new AUD_DelayReader(getReader(), m_delay); | 	return new AUD_DelayReader(getReader(), m_delay); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -55,14 +55,14 @@ public: | |||||||
| 	 * \param factory The input factory. | 	 * \param factory The input factory. | ||||||
| 	 * \param delay The desired delay in seconds. | 	 * \param delay The desired delay in seconds. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_DelayFactory(AUD_IFactory* factory, float delay = 0); | 	AUD_DelayFactory(AUD_Reference<AUD_IFactory> factory, float delay = 0); | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Returns the delay in seconds. | 	 * Returns the delay in seconds. | ||||||
| 	 */ | 	 */ | ||||||
| 	float getDelay() const; | 	float getDelay() const; | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_DELAYFACTORY | #endif //AUD_DELAYFACTORY | ||||||
|   | |||||||
| @@ -33,11 +33,10 @@ | |||||||
|  |  | ||||||
| #include <cstring> | #include <cstring> | ||||||
|  |  | ||||||
| AUD_DelayReader::AUD_DelayReader(AUD_IReader* reader, float delay) : | AUD_DelayReader::AUD_DelayReader(AUD_Reference<AUD_IReader> reader, float delay) : | ||||||
| 		AUD_EffectReader(reader), | 		AUD_EffectReader(reader), | ||||||
| 		m_delay(int(delay * reader->getSpecs().rate)), | 		m_delay(int(delay * reader->getSpecs().rate)), | ||||||
| 		m_remdelay(int(delay * reader->getSpecs().rate)), | 		m_remdelay(int(delay * reader->getSpecs().rate)) | ||||||
| 		m_empty(true) |  | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -70,49 +69,30 @@ int AUD_DelayReader::getPosition() const | |||||||
| 	return m_reader->getPosition() + m_delay; | 	return m_reader->getPosition() + m_delay; | ||||||
| } | } | ||||||
|  |  | ||||||
| void AUD_DelayReader::read(int & length, sample_t* & buffer) | void AUD_DelayReader::read(int& length, bool& eos, sample_t* buffer) | ||||||
| { | { | ||||||
| 	if(m_remdelay > 0) | 	if(m_remdelay > 0) | ||||||
| 	{ | 	{ | ||||||
| 		AUD_Specs specs = m_reader->getSpecs(); | 		AUD_Specs specs = m_reader->getSpecs(); | ||||||
| 		int samplesize = AUD_SAMPLE_SIZE(specs); | 		int samplesize = AUD_SAMPLE_SIZE(specs); | ||||||
|  |  | ||||||
| 		if(m_buffer.getSize() < length * samplesize) |  | ||||||
| 		{ |  | ||||||
| 			m_buffer.resize(length * samplesize); |  | ||||||
| 			m_empty = false; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		buffer = m_buffer.getBuffer(); |  | ||||||
|  |  | ||||||
| 		if(length > m_remdelay) | 		if(length > m_remdelay) | ||||||
| 		{ | 		{ | ||||||
| 			if(!m_empty) |  | ||||||
| 			memset(buffer, 0, m_remdelay * samplesize); | 			memset(buffer, 0, m_remdelay * samplesize); | ||||||
|  |  | ||||||
| 			int len = length - m_remdelay; | 			int len = length - m_remdelay; | ||||||
| 			sample_t* buf; | 			m_reader->read(len, eos, buffer + m_remdelay * specs.channels); | ||||||
| 			m_reader->read(len, buf); |  | ||||||
|  |  | ||||||
| 			memcpy(buffer + m_remdelay * specs.channels, |  | ||||||
| 				   buf, len * samplesize); |  | ||||||
|  |  | ||||||
| 			if(len < length-m_remdelay) |  | ||||||
| 			length = m_remdelay + len; | 			length = m_remdelay + len; | ||||||
|  |  | ||||||
| 			m_remdelay = 0; | 			m_remdelay = 0; | ||||||
| 			m_empty = false; |  | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ |  | ||||||
| 			if(!m_empty) |  | ||||||
| 		{ | 		{ | ||||||
| 			memset(buffer, 0, length * samplesize); | 			memset(buffer, 0, length * samplesize); | ||||||
| 				m_empty = true; |  | ||||||
| 			} |  | ||||||
| 			m_remdelay -= length; | 			m_remdelay -= length; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 		m_reader->read(length, buffer); | 		m_reader->read(length, eos, buffer); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -36,16 +36,11 @@ | |||||||
| #include "AUD_Buffer.h" | #include "AUD_Buffer.h" | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This class reads another reader and changes it's delay. |  * This class reads another reader and delays it. | ||||||
|  */ |  */ | ||||||
| class AUD_DelayReader : public AUD_EffectReader | class AUD_DelayReader : public AUD_EffectReader | ||||||
| { | { | ||||||
| private: | private: | ||||||
| 	/** |  | ||||||
| 	 * The playback buffer. |  | ||||||
| 	 */ |  | ||||||
| 	AUD_Buffer m_buffer; |  | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The delay level. | 	 * The delay level. | ||||||
| 	 */ | 	 */ | ||||||
| @@ -56,11 +51,6 @@ private: | |||||||
| 	 */ | 	 */ | ||||||
| 	int m_remdelay; | 	int m_remdelay; | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * Whether the buffer is currently filled with zeros. |  | ||||||
| 	 */ |  | ||||||
| 	bool m_empty; |  | ||||||
|  |  | ||||||
| 	// hide copy constructor and operator= | 	// hide copy constructor and operator= | ||||||
| 	AUD_DelayReader(const AUD_DelayReader&); | 	AUD_DelayReader(const AUD_DelayReader&); | ||||||
| 	AUD_DelayReader& operator=(const AUD_DelayReader&); | 	AUD_DelayReader& operator=(const AUD_DelayReader&); | ||||||
| @@ -71,12 +61,12 @@ public: | |||||||
| 	 * \param reader The reader to read from. | 	 * \param reader The reader to read from. | ||||||
| 	 * \param delay The delay in seconds. | 	 * \param delay The delay in seconds. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_DelayReader(AUD_IReader* reader, float delay); | 	AUD_DelayReader(AUD_Reference<AUD_IReader> reader, float delay); | ||||||
|  |  | ||||||
| 	virtual void seek(int position); | 	virtual void seek(int position); | ||||||
| 	virtual int getLength() const; | 	virtual int getLength() const; | ||||||
| 	virtual int getPosition() const; | 	virtual int getPosition() const; | ||||||
| 	virtual void read(int & length, sample_t* & buffer); | 	virtual void read(int& length, bool& eos, sample_t* buffer); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_DELAYREADER | #endif //AUD_DELAYREADER | ||||||
|   | |||||||
| @@ -32,25 +32,15 @@ | |||||||
| #include "AUD_DoubleFactory.h" | #include "AUD_DoubleFactory.h" | ||||||
| #include "AUD_DoubleReader.h" | #include "AUD_DoubleReader.h" | ||||||
|  |  | ||||||
| AUD_DoubleFactory::AUD_DoubleFactory(AUD_IFactory* factory1, AUD_IFactory* factory2) : | AUD_DoubleFactory::AUD_DoubleFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2) : | ||||||
| 		m_factory1(factory1), m_factory2(factory2) | 		m_factory1(factory1), m_factory2(factory2) | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_DoubleFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_DoubleFactory::createReader() | ||||||
| { | { | ||||||
| 	AUD_IReader* reader1 = m_factory1->createReader(); | 	AUD_Reference<AUD_IReader> reader1 = m_factory1->createReader(); | ||||||
| 	AUD_IReader* reader2; | 	AUD_Reference<AUD_IReader> reader2 = m_factory2->createReader(); | ||||||
|  |  | ||||||
| 	try |  | ||||||
| 	{ |  | ||||||
| 		reader2 = m_factory2->createReader(); |  | ||||||
| 	} |  | ||||||
| 	catch(AUD_Exception&) |  | ||||||
| 	{ |  | ||||||
| 		delete reader1; |  | ||||||
| 		throw; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return new AUD_DoubleReader(reader1, reader2); | 	return new AUD_DoubleReader(reader1, reader2); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -36,7 +36,6 @@ | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This factory plays two other factories behind each other. |  * This factory plays two other factories behind each other. | ||||||
|  * \note Readers from the underlying factories must have the same sample rate and channel count. |  | ||||||
|  */ |  */ | ||||||
| class AUD_DoubleFactory : public AUD_IFactory | class AUD_DoubleFactory : public AUD_IFactory | ||||||
| { | { | ||||||
| @@ -44,12 +43,12 @@ private: | |||||||
| 	/** | 	/** | ||||||
| 	 * First played factory. | 	 * First played factory. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_IFactory* m_factory1; | 	AUD_Reference<AUD_IFactory> m_factory1; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Second played factory. | 	 * Second played factory. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_IFactory* m_factory2; | 	AUD_Reference<AUD_IFactory> m_factory2; | ||||||
|  |  | ||||||
| 	// hide copy constructor and operator= | 	// hide copy constructor and operator= | ||||||
| 	AUD_DoubleFactory(const AUD_DoubleFactory&); | 	AUD_DoubleFactory(const AUD_DoubleFactory&); | ||||||
| @@ -61,9 +60,9 @@ public: | |||||||
| 	 * \param factory1 The first input factory. | 	 * \param factory1 The first input factory. | ||||||
| 	 * \param factory2 The second input factory. | 	 * \param factory2 The second input factory. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_DoubleFactory(AUD_IFactory* factory1, AUD_IFactory* factory2); | 	AUD_DoubleFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2); | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_DOUBLEFACTORY | #endif //AUD_DOUBLEFACTORY | ||||||
|   | |||||||
| @@ -33,28 +33,17 @@ | |||||||
|  |  | ||||||
| #include <cstring> | #include <cstring> | ||||||
|  |  | ||||||
| static const char* specs_error = "AUD_DoubleReader: Both readers have to have " | AUD_DoubleReader::AUD_DoubleReader(AUD_Reference<AUD_IReader> reader1, | ||||||
| 								 "the same specs."; | 								   AUD_Reference<AUD_IReader> reader2) : | ||||||
|  |  | ||||||
| AUD_DoubleReader::AUD_DoubleReader(AUD_IReader* reader1, |  | ||||||
| 								   AUD_IReader* reader2) : |  | ||||||
| 		m_reader1(reader1), m_reader2(reader2), m_finished1(false) | 		m_reader1(reader1), m_reader2(reader2), m_finished1(false) | ||||||
| { | { | ||||||
| 	AUD_Specs s1, s2; | 	AUD_Specs s1, s2; | ||||||
| 	s1 = reader1->getSpecs(); | 	s1 = reader1->getSpecs(); | ||||||
| 	s2 = reader2->getSpecs(); | 	s2 = reader2->getSpecs(); | ||||||
| 	if(memcmp(&s1, &s2, sizeof(AUD_Specs)) != 0) |  | ||||||
| 	{ |  | ||||||
| 		delete reader1; |  | ||||||
| 		delete reader2; |  | ||||||
| 		AUD_THROW(AUD_ERROR_SPECS, specs_error); |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_DoubleReader::~AUD_DoubleReader() | AUD_DoubleReader::~AUD_DoubleReader() | ||||||
| { | { | ||||||
| 	delete m_reader1; |  | ||||||
| 	delete m_reader2; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| bool AUD_DoubleReader::isSeekable() const | bool AUD_DoubleReader::isSeekable() const | ||||||
| @@ -90,43 +79,36 @@ int AUD_DoubleReader::getPosition() const | |||||||
|  |  | ||||||
| AUD_Specs AUD_DoubleReader::getSpecs() const | AUD_Specs AUD_DoubleReader::getSpecs() const | ||||||
| { | { | ||||||
| 	return m_reader1->getSpecs(); | 	return m_finished1 ? m_reader1->getSpecs() : m_reader2->getSpecs(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void AUD_DoubleReader::read(int & length, sample_t* & buffer) | void AUD_DoubleReader::read(int& length, bool& eos, sample_t* buffer) | ||||||
| { | { | ||||||
|  | 	eos = false; | ||||||
|  |  | ||||||
| 	if(!m_finished1) | 	if(!m_finished1) | ||||||
| 	{ | 	{ | ||||||
| 		int len = length; | 		int len = length; | ||||||
| 		m_reader1->read(len, buffer); |  | ||||||
|  | 		m_reader1->read(len, m_finished1, buffer); | ||||||
|  |  | ||||||
| 		if(len < length) | 		if(len < length) | ||||||
| 		{ | 		{ | ||||||
| 			AUD_Specs specs = m_reader1->getSpecs(); | 			AUD_Specs specs1, specs2; | ||||||
| 			int samplesize = AUD_SAMPLE_SIZE(specs); | 			specs1 = m_reader1->getSpecs(); | ||||||
|  | 			specs2 = m_reader2->getSpecs(); | ||||||
| 			if(m_buffer.getSize() < length * samplesize) | 			if(AUD_COMPARE_SPECS(specs1, specs2)) | ||||||
| 				m_buffer.resize(length * samplesize); | 			{ | ||||||
|  | 				int len2 = length - len; | ||||||
| 			sample_t* buf = buffer; | 				m_reader2->read(len2, eos, buffer + specs1.channels * len); | ||||||
| 			buffer = m_buffer.getBuffer(); | 				length = len + len2; | ||||||
|  | 			} | ||||||
| 			memcpy(buffer, buf, len * samplesize); | 			else | ||||||
|  | 				length = len; | ||||||
| 			len = length - len; |  | ||||||
| 			length -= len; |  | ||||||
| 			m_reader2->read(len, buf); |  | ||||||
|  |  | ||||||
| 			memcpy(buffer + length * specs.channels, buf, |  | ||||||
| 				   len * samplesize); |  | ||||||
|  |  | ||||||
| 			length += len; |  | ||||||
|  |  | ||||||
| 			m_finished1 = true; |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		m_reader2->read(length, buffer); | 		m_reader2->read(length, eos, buffer); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -34,9 +34,10 @@ | |||||||
|  |  | ||||||
| #include "AUD_IReader.h" | #include "AUD_IReader.h" | ||||||
| #include "AUD_Buffer.h" | #include "AUD_Buffer.h" | ||||||
|  | #include "AUD_Reference.h" | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This reader plays two readers with the same specs sequently. |  * This reader plays two readers sequently. | ||||||
|  */ |  */ | ||||||
| class AUD_DoubleReader : public AUD_IReader | class AUD_DoubleReader : public AUD_IReader | ||||||
| { | { | ||||||
| @@ -44,35 +45,29 @@ private: | |||||||
| 	/** | 	/** | ||||||
| 	 * The first reader. | 	 * The first reader. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_IReader* m_reader1; | 	AUD_Reference<AUD_IReader> m_reader1; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The second reader. | 	 * The second reader. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_IReader* m_reader2; | 	AUD_Reference<AUD_IReader> m_reader2; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Whether we've reached the end of the first reader. | 	 * Whether we've reached the end of the first reader. | ||||||
| 	 */ | 	 */ | ||||||
| 	bool m_finished1; | 	bool m_finished1; | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * The playback buffer for the intersecting part. |  | ||||||
| 	 */ |  | ||||||
| 	AUD_Buffer m_buffer; |  | ||||||
|  |  | ||||||
| 	// hide copy constructor and operator= | 	// hide copy constructor and operator= | ||||||
| 	AUD_DoubleReader(const AUD_DoubleReader&); | 	AUD_DoubleReader(const AUD_DoubleReader&); | ||||||
| 	AUD_DoubleReader& operator=(const AUD_DoubleReader&); | 	AUD_DoubleReader& operator=(const AUD_DoubleReader&); | ||||||
|  |  | ||||||
| public: | public: | ||||||
| 	/** | 	/** | ||||||
| 	 * Creates a new ping pong reader. | 	 * Creates a new double reader. | ||||||
| 	 * \param reader1 The first reader to read from. | 	 * \param reader1 The first reader to read from. | ||||||
| 	 * \param reader2 The second reader to read from. | 	 * \param reader2 The second reader to read from. | ||||||
| 	 * \exception AUD_Exception Thrown if the specs from the readers differ. |  | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_DoubleReader(AUD_IReader* reader1, AUD_IReader* reader2); | 	AUD_DoubleReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<AUD_IReader> reader2); | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Destroys the reader. | 	 * Destroys the reader. | ||||||
| @@ -84,7 +79,7 @@ public: | |||||||
| 	virtual int getLength() const; | 	virtual int getLength() const; | ||||||
| 	virtual int getPosition() const; | 	virtual int getPosition() const; | ||||||
| 	virtual AUD_Specs getSpecs() const; | 	virtual AUD_Specs getSpecs() const; | ||||||
| 	virtual void read(int & length, sample_t* & buffer); | 	virtual void read(int& length, bool& eos, sample_t* buffer); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_DOUBLEREADER | #endif //AUD_DOUBLEREADER | ||||||
|   | |||||||
							
								
								
									
										42
									
								
								intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | |||||||
|  | /* | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |  * ***** BEGIN GPL LICENSE BLOCK ***** | ||||||
|  |  * | ||||||
|  |  * Copyright 2009-2011 Jörg Hermann Müller | ||||||
|  |  * | ||||||
|  |  * This file is part of AudaSpace. | ||||||
|  |  * | ||||||
|  |  * Audaspace is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation; either version 2 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * AudaSpace is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with Audaspace; if not, write to the Free Software Foundation, | ||||||
|  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||||
|  |  * | ||||||
|  |  * ***** END GPL LICENSE BLOCK ***** | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** \file audaspace/FX/AUD_DynamicIIRFilterFactory.cpp | ||||||
|  |  *  \ingroup audfx | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "AUD_DynamicIIRFilterFactory.h" | ||||||
|  | #include "AUD_DynamicIIRFilterReader.h" | ||||||
|  |  | ||||||
|  | AUD_DynamicIIRFilterFactory::AUD_DynamicIIRFilterFactory(AUD_Reference<AUD_IFactory> factory) : | ||||||
|  | 	AUD_EffectFactory(factory) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AUD_Reference<AUD_IReader> AUD_DynamicIIRFilterFactory::createReader() | ||||||
|  | { | ||||||
|  | 	return new AUD_DynamicIIRFilterReader(getReader(), this); | ||||||
|  | } | ||||||
							
								
								
									
										65
									
								
								intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | |||||||
|  | /* | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |  * ***** BEGIN GPL LICENSE BLOCK ***** | ||||||
|  |  * | ||||||
|  |  * Copyright 2009-2011 Jörg Hermann Müller | ||||||
|  |  * | ||||||
|  |  * This file is part of AudaSpace. | ||||||
|  |  * | ||||||
|  |  * Audaspace is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation; either version 2 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * AudaSpace is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with Audaspace; if not, write to the Free Software Foundation, | ||||||
|  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||||
|  |  * | ||||||
|  |  * ***** END GPL LICENSE BLOCK ***** | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** \file audaspace/FX/AUD_DynamicIIRFilterFactory.h | ||||||
|  |  *  \ingroup audfx | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef AUD_DYNAMICIIRFILTERFACTORY | ||||||
|  | #define AUD_DYNAMICIIRFILTERFACTORY | ||||||
|  |  | ||||||
|  | #include "AUD_EffectFactory.h" | ||||||
|  | #include <vector> | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * This factory creates a IIR filter reader. | ||||||
|  |  * | ||||||
|  |  * This means that on sample rate change the filter recalculates its | ||||||
|  |  * coefficients. | ||||||
|  |  */ | ||||||
|  | class AUD_DynamicIIRFilterFactory : public AUD_EffectFactory | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a new Dynmic IIR filter factory. | ||||||
|  | 	 * \param factory The input factory. | ||||||
|  | 	 */ | ||||||
|  | 	AUD_DynamicIIRFilterFactory(AUD_Reference<AUD_IFactory> factory); | ||||||
|  |  | ||||||
|  | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Recalculates the filter coefficients. | ||||||
|  | 	 * \param rate The sample rate of the audio data. | ||||||
|  | 	 * \param[out] b The input filter coefficients. | ||||||
|  | 	 * \param[out] a The output filter coefficients. | ||||||
|  | 	 */ | ||||||
|  | 	virtual void recalculateCoefficients(AUD_SampleRate rate, | ||||||
|  | 										 std::vector<float>& b, | ||||||
|  | 										 std::vector<float>& a)=0; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #endif // AUD_DYNAMICIIRFILTERFACTORY | ||||||
							
								
								
									
										45
									
								
								intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | /* | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |  * ***** BEGIN GPL LICENSE BLOCK ***** | ||||||
|  |  * | ||||||
|  |  * Copyright 2009-2011 Jörg Hermann Müller | ||||||
|  |  * | ||||||
|  |  * This file is part of AudaSpace. | ||||||
|  |  * | ||||||
|  |  * Audaspace is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation; either version 2 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * AudaSpace is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with Audaspace; if not, write to the Free Software Foundation, | ||||||
|  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||||
|  |  * | ||||||
|  |  * ***** END GPL LICENSE BLOCK ***** | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** \file audaspace/FX/AUD_DynamicIIRFilterReader.cpp | ||||||
|  |  *  \ingroup audfx | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "AUD_DynamicIIRFilterReader.h" | ||||||
|  |  | ||||||
|  | AUD_DynamicIIRFilterReader::AUD_DynamicIIRFilterReader(AUD_Reference<AUD_IReader> reader, | ||||||
|  | 													   AUD_Reference<AUD_DynamicIIRFilterFactory> factory) : | ||||||
|  | 	AUD_IIRFilterReader(reader, std::vector<float>(), std::vector<float>()) | ||||||
|  | { | ||||||
|  | 	sampleRateChanged(reader->getSpecs().rate); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AUD_DynamicIIRFilterReader::sampleRateChanged(AUD_SampleRate rate) | ||||||
|  | { | ||||||
|  | 	std::vector<float> a, b; | ||||||
|  | 	m_factory->recalculateCoefficients(rate, b, a); | ||||||
|  | 	setCoefficients(b, a); | ||||||
|  | } | ||||||
							
								
								
									
										56
									
								
								intern/audaspace/FX/AUD_DynamicIIRFilterReader.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								intern/audaspace/FX/AUD_DynamicIIRFilterReader.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | |||||||
|  | /* | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |  * ***** BEGIN GPL LICENSE BLOCK ***** | ||||||
|  |  * | ||||||
|  |  * Copyright 2009-2011 Jörg Hermann Müller | ||||||
|  |  * | ||||||
|  |  * This file is part of AudaSpace. | ||||||
|  |  * | ||||||
|  |  * Audaspace is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation; either version 2 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * AudaSpace is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with Audaspace; if not, write to the Free Software Foundation, | ||||||
|  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||||
|  |  * | ||||||
|  |  * ***** END GPL LICENSE BLOCK ***** | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** \file audaspace/FX/AUD_DynamicIIRFilterReader.h | ||||||
|  |  *  \ingroup audfx | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef AUD_DYNAMICIIRFILTERREADER | ||||||
|  | #define AUD_DYNAMICIIRFILTERREADER | ||||||
|  |  | ||||||
|  | #include "AUD_IIRFilterReader.h" | ||||||
|  | #include "AUD_DynamicIIRFilterFactory.h" | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * This class is for dynamic infinite impulse response filters with simple | ||||||
|  |  * coefficients that change depending on the sample rate. | ||||||
|  |  */ | ||||||
|  | class AUD_DynamicIIRFilterReader : public AUD_IIRFilterReader | ||||||
|  | { | ||||||
|  | private: | ||||||
|  | 	/** | ||||||
|  | 	 * The factory for dynamically recalculating filter coefficients. | ||||||
|  | 	 */ | ||||||
|  | 	AUD_Reference<AUD_DynamicIIRFilterFactory> m_factory; | ||||||
|  |  | ||||||
|  | public: | ||||||
|  | 	AUD_DynamicIIRFilterReader(AUD_Reference<AUD_IReader> reader, | ||||||
|  | 							   AUD_Reference<AUD_DynamicIIRFilterFactory> factory); | ||||||
|  |  | ||||||
|  | 	virtual void sampleRateChanged(AUD_SampleRate rate); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #endif // AUD_DYNAMICIIRFILTERREADER | ||||||
| @@ -32,7 +32,7 @@ | |||||||
| #include "AUD_EffectFactory.h" | #include "AUD_EffectFactory.h" | ||||||
| #include "AUD_IReader.h" | #include "AUD_IReader.h" | ||||||
|  |  | ||||||
| AUD_EffectFactory::AUD_EffectFactory(AUD_IFactory* factory) | AUD_EffectFactory::AUD_EffectFactory(AUD_Reference<AUD_IFactory> factory) | ||||||
| { | { | ||||||
| 	m_factory = factory; | 	m_factory = factory; | ||||||
| } | } | ||||||
| @@ -41,7 +41,7 @@ AUD_EffectFactory::~AUD_EffectFactory() | |||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IFactory* AUD_EffectFactory::getFactory() const | AUD_Reference<AUD_IFactory> AUD_EffectFactory::getFactory() const | ||||||
| { | { | ||||||
| 	return m_factory; | 	return m_factory; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -49,7 +49,7 @@ protected: | |||||||
| 	/** | 	/** | ||||||
| 	 * If there is no reader it is created out of this factory. | 	 * If there is no reader it is created out of this factory. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_IFactory* m_factory; | 	AUD_Reference<AUD_IFactory> m_factory; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Returns the reader created out of the factory. | 	 * Returns the reader created out of the factory. | ||||||
| @@ -57,7 +57,7 @@ protected: | |||||||
| 	 * classes. | 	 * classes. | ||||||
| 	 * \return The reader created out of the factory. | 	 * \return The reader created out of the factory. | ||||||
| 	 */ | 	 */ | ||||||
| 	inline AUD_IReader* getReader() const | 	inline AUD_Reference<AUD_IReader> getReader() const | ||||||
| 	{ | 	{ | ||||||
| 		return m_factory->createReader(); | 		return m_factory->createReader(); | ||||||
| 	} | 	} | ||||||
| @@ -67,7 +67,7 @@ public: | |||||||
| 	 * Creates a new factory. | 	 * Creates a new factory. | ||||||
| 	 * \param factory The input factory. | 	 * \param factory The input factory. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_EffectFactory(AUD_IFactory* factory); | 	AUD_EffectFactory(AUD_Reference<AUD_IFactory> factory); | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Destroys the factory. | 	 * Destroys the factory. | ||||||
| @@ -78,7 +78,7 @@ public: | |||||||
| 	 * Returns the saved factory. | 	 * Returns the saved factory. | ||||||
| 	 * \return The factory or NULL if there has no factory been saved. | 	 * \return The factory or NULL if there has no factory been saved. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_IFactory* getFactory() const; | 	AUD_Reference<AUD_IFactory> getFactory() const; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_EFFECTFACTORY | #endif //AUD_EFFECTFACTORY | ||||||
|   | |||||||
| @@ -31,14 +31,13 @@ | |||||||
|  |  | ||||||
| #include "AUD_EffectReader.h" | #include "AUD_EffectReader.h" | ||||||
|  |  | ||||||
| AUD_EffectReader::AUD_EffectReader(AUD_IReader* reader) | AUD_EffectReader::AUD_EffectReader(AUD_Reference<AUD_IReader> reader) | ||||||
| { | { | ||||||
| 	m_reader = reader; | 	m_reader = reader; | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_EffectReader::~AUD_EffectReader() | AUD_EffectReader::~AUD_EffectReader() | ||||||
| { | { | ||||||
| 	delete m_reader; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| bool AUD_EffectReader::isSeekable() const | bool AUD_EffectReader::isSeekable() const | ||||||
| @@ -66,7 +65,7 @@ AUD_Specs AUD_EffectReader::getSpecs() const | |||||||
| 	return m_reader->getSpecs(); | 	return m_reader->getSpecs(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void AUD_EffectReader::read(int & length, sample_t* & buffer) | void AUD_EffectReader::read(int& length, bool& eos, sample_t* buffer) | ||||||
| { | { | ||||||
| 	m_reader->read(length, buffer); | 	m_reader->read(length, eos, buffer); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -33,6 +33,7 @@ | |||||||
| #define AUD_EFFECTREADER | #define AUD_EFFECTREADER | ||||||
|  |  | ||||||
| #include "AUD_IReader.h" | #include "AUD_IReader.h" | ||||||
|  | #include "AUD_Reference.h" | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This reader is a base class for all effect readers that take one other reader |  * This reader is a base class for all effect readers that take one other reader | ||||||
| @@ -49,14 +50,14 @@ protected: | |||||||
| 	/** | 	/** | ||||||
| 	 * The reader to read from. | 	 * The reader to read from. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_IReader* m_reader; | 	AUD_Reference<AUD_IReader> m_reader; | ||||||
|  |  | ||||||
| public: | public: | ||||||
| 	/** | 	/** | ||||||
| 	 * Creates a new effect reader. | 	 * Creates a new effect reader. | ||||||
| 	 * \param reader The reader to read from. | 	 * \param reader The reader to read from. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_EffectReader(AUD_IReader* reader); | 	AUD_EffectReader(AUD_Reference<AUD_IReader> reader); | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Destroys the reader. | 	 * Destroys the reader. | ||||||
| @@ -68,7 +69,7 @@ public: | |||||||
| 	virtual int getLength() const; | 	virtual int getLength() const; | ||||||
| 	virtual int getPosition() const; | 	virtual int getPosition() const; | ||||||
| 	virtual AUD_Specs getSpecs() const; | 	virtual AUD_Specs getSpecs() const; | ||||||
| 	virtual void read(int & length, sample_t* & buffer); | 	virtual void read(int& length, bool& eos, sample_t* buffer); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_EFFECTREADER | #endif //AUD_EFFECTREADER | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ struct EnvelopeParameters | |||||||
| 	float arthreshold; | 	float arthreshold; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| sample_t envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters* param) | sample_t AUD_EnvelopeFactory::envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters* param) | ||||||
| { | { | ||||||
| 	float in = fabs(reader->x(0)); | 	float in = fabs(reader->x(0)); | ||||||
| 	float out = reader->y(-1); | 	float out = reader->y(-1); | ||||||
| @@ -51,12 +51,12 @@ sample_t envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters* | |||||||
| 	return (in > out ? param->attack : param->release) * (out - in) + in; | 	return (in > out ? param->attack : param->release) * (out - in) + in; | ||||||
| } | } | ||||||
|  |  | ||||||
| void endEnvelopeFilter(EnvelopeParameters* param) | void AUD_EnvelopeFactory::endEnvelopeFilter(EnvelopeParameters* param) | ||||||
| { | { | ||||||
| 	delete param; | 	delete param; | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack, | AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_Reference<AUD_IFactory> factory, float attack, | ||||||
| 										 float release, float threshold, | 										 float release, float threshold, | ||||||
| 										 float arthreshold) : | 										 float arthreshold) : | ||||||
| 		AUD_EffectFactory(factory), | 		AUD_EffectFactory(factory), | ||||||
| @@ -67,14 +67,14 @@ AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack, | |||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_EnvelopeFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_EnvelopeFactory::createReader() | ||||||
| { | { | ||||||
| 	AUD_IReader* reader = getReader(); | 	AUD_Reference<AUD_IReader> reader = getReader(); | ||||||
|  |  | ||||||
| 	EnvelopeParameters* param = new EnvelopeParameters(); | 	EnvelopeParameters* param = new EnvelopeParameters(); | ||||||
| 	param->arthreshold = m_arthreshold; | 	param->arthreshold = m_arthreshold; | ||||||
| 	param->attack = pow(m_arthreshold, 1.0f/(reader->getSpecs().rate * m_attack)); | 	param->attack = pow(m_arthreshold, 1.0f/(static_cast<float>(reader->getSpecs().rate) * m_attack)); | ||||||
| 	param->release = pow(m_arthreshold, 1.0f/(reader->getSpecs().rate * m_release)); | 	param->release = pow(m_arthreshold, 1.0f/(static_cast<float>(reader->getSpecs().rate) * m_release)); | ||||||
| 	param->threshold = m_threshold; | 	param->threshold = m_threshold; | ||||||
|  |  | ||||||
| 	return new AUD_CallbackIIRFilterReader(reader, 1, 2, | 	return new AUD_CallbackIIRFilterReader(reader, 1, 2, | ||||||
|   | |||||||
| @@ -33,6 +33,8 @@ | |||||||
| #define AUD_ENVELOPEFACTORY | #define AUD_ENVELOPEFACTORY | ||||||
|  |  | ||||||
| #include "AUD_EffectFactory.h" | #include "AUD_EffectFactory.h" | ||||||
|  | class AUD_CallbackIIRFilterReader; | ||||||
|  | struct EnvelopeParameters; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This factory creates an envelope follower reader. |  * This factory creates an envelope follower reader. | ||||||
| @@ -73,10 +75,13 @@ public: | |||||||
| 	 * \param threshold The threshold value. | 	 * \param threshold The threshold value. | ||||||
| 	 * \param arthreshold The attack/release threshold value. | 	 * \param arthreshold The attack/release threshold value. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_EnvelopeFactory(AUD_IFactory* factory, float attack, float release, | 	AUD_EnvelopeFactory(AUD_Reference<AUD_IFactory> factory, float attack, float release, | ||||||
| 						float threshold, float arthreshold); | 						float threshold, float arthreshold); | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
|  |  | ||||||
|  | 	static sample_t envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters* param); | ||||||
|  | 	static void endEnvelopeFilter(EnvelopeParameters* param); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_ENVELOPEFACTORY | #endif //AUD_ENVELOPEFACTORY | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ | |||||||
| #include "AUD_FaderFactory.h" | #include "AUD_FaderFactory.h" | ||||||
| #include "AUD_FaderReader.h" | #include "AUD_FaderReader.h" | ||||||
|  |  | ||||||
| AUD_FaderFactory::AUD_FaderFactory(AUD_IFactory* factory, AUD_FadeType type, | AUD_FaderFactory::AUD_FaderFactory(AUD_Reference<AUD_IFactory> factory, AUD_FadeType type, | ||||||
| 								   float start, float length) : | 								   float start, float length) : | ||||||
| 		AUD_EffectFactory(factory), | 		AUD_EffectFactory(factory), | ||||||
| 		m_type(type), | 		m_type(type), | ||||||
| @@ -56,7 +56,7 @@ float AUD_FaderFactory::getLength() const | |||||||
| 	return m_length; | 	return m_length; | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_FaderFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_FaderFactory::createReader() | ||||||
| { | { | ||||||
| 	return new AUD_FaderReader(getReader(), m_type, m_start, m_length); | 	return new AUD_FaderReader(getReader(), m_type, m_start, m_length); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -69,7 +69,7 @@ public: | |||||||
| 	 * \param start The time where fading should start in seconds. | 	 * \param start The time where fading should start in seconds. | ||||||
| 	 * \param length How long fading should last in seconds. | 	 * \param length How long fading should last in seconds. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_FaderFactory(AUD_IFactory* factory, | 	AUD_FaderFactory(AUD_Reference<AUD_IFactory> factory, | ||||||
| 					  AUD_FadeType type = AUD_FADE_IN, | 					  AUD_FadeType type = AUD_FADE_IN, | ||||||
| 					  float start = 0.0f, float length = 1.0f); | 					  float start = 0.0f, float length = 1.0f); | ||||||
|  |  | ||||||
| @@ -88,7 +88,7 @@ public: | |||||||
| 	 */ | 	 */ | ||||||
| 	float getLength() const; | 	float getLength() const; | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_FADERFACTORY | #endif //AUD_FADERFACTORY | ||||||
|   | |||||||
| @@ -33,68 +33,39 @@ | |||||||
|  |  | ||||||
| #include <cstring> | #include <cstring> | ||||||
|  |  | ||||||
| AUD_FaderReader::AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type, | AUD_FaderReader::AUD_FaderReader(AUD_Reference<AUD_IReader> reader, AUD_FadeType type, | ||||||
| 								 float start,float length) : | 								 float start,float length) : | ||||||
| 		AUD_EffectReader(reader), | 		AUD_EffectReader(reader), | ||||||
| 		m_type(type), | 		m_type(type), | ||||||
| 		m_start(start), | 		m_start(start), | ||||||
| 		m_length(length), | 		m_length(length) | ||||||
| 		m_empty(true) |  | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| void AUD_FaderReader::read(int & length, sample_t* & buffer) | void AUD_FaderReader::read(int& length, bool& eos, sample_t* buffer) | ||||||
| { | { | ||||||
| 	int position = m_reader->getPosition(); | 	int position = m_reader->getPosition(); | ||||||
| 	AUD_Specs specs = m_reader->getSpecs(); | 	AUD_Specs specs = m_reader->getSpecs(); | ||||||
| 	int samplesize = AUD_SAMPLE_SIZE(specs); | 	int samplesize = AUD_SAMPLE_SIZE(specs); | ||||||
|  |  | ||||||
| 	m_reader->read(length, buffer); | 	m_reader->read(length, eos, buffer); | ||||||
|  |  | ||||||
| 	if((position + length) / (float)specs.rate <= m_start) | 	if((position + length) / (float)specs.rate <= m_start) | ||||||
| 	{ | 	{ | ||||||
| 		if(m_type != AUD_FADE_OUT) | 		if(m_type != AUD_FADE_OUT) | ||||||
| 		{ |  | ||||||
| 			if(m_buffer.getSize() < length * samplesize) |  | ||||||
| 			{ |  | ||||||
| 				m_buffer.resize(length * samplesize); |  | ||||||
| 				m_empty = false; |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			buffer = m_buffer.getBuffer(); |  | ||||||
|  |  | ||||||
| 			if(!m_empty) |  | ||||||
| 		{ | 		{ | ||||||
| 			memset(buffer, 0, length * samplesize); | 			memset(buffer, 0, length * samplesize); | ||||||
| 				m_empty = true; |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else if(position / (float)specs.rate >= m_start+m_length) | 	else if(position / (float)specs.rate >= m_start+m_length) | ||||||
| 	{ | 	{ | ||||||
| 		if(m_type == AUD_FADE_OUT) | 		if(m_type == AUD_FADE_OUT) | ||||||
| 		{ |  | ||||||
| 			if(m_buffer.getSize() < length * samplesize) |  | ||||||
| 			{ |  | ||||||
| 				m_buffer.resize(length * samplesize); |  | ||||||
| 				m_empty = false; |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			buffer = m_buffer.getBuffer(); |  | ||||||
|  |  | ||||||
| 			if(!m_empty) |  | ||||||
| 		{ | 		{ | ||||||
| 			memset(buffer, 0, length * samplesize); | 			memset(buffer, 0, length * samplesize); | ||||||
| 				m_empty = true; |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		if(m_buffer.getSize() < length * samplesize) |  | ||||||
| 			m_buffer.resize(length * samplesize); |  | ||||||
|  |  | ||||||
| 		sample_t* buf = m_buffer.getBuffer(); |  | ||||||
| 		float volume = 1.0f; | 		float volume = 1.0f; | ||||||
|  |  | ||||||
| 		for(int i = 0; i < length * specs.channels; i++) | 		for(int i = 0; i < length * specs.channels; i++) | ||||||
| @@ -111,10 +82,7 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer) | |||||||
| 					volume = 1.0f - volume; | 					volume = 1.0f - volume; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			buf[i] = buffer[i] * volume; | 			buffer[i] = buffer[i] * volume; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		buffer = buf; |  | ||||||
| 		m_empty = false; |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -58,16 +58,6 @@ private: | |||||||
| 	 */ | 	 */ | ||||||
| 	const float m_length; | 	const float m_length; | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * The playback buffer. |  | ||||||
| 	 */ |  | ||||||
| 	AUD_Buffer m_buffer; |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * Whether the buffer is empty. |  | ||||||
| 	 */ |  | ||||||
| 	bool m_empty; |  | ||||||
|  |  | ||||||
| 	// hide copy constructor and operator= | 	// hide copy constructor and operator= | ||||||
| 	AUD_FaderReader(const AUD_FaderReader&); | 	AUD_FaderReader(const AUD_FaderReader&); | ||||||
| 	AUD_FaderReader& operator=(const AUD_FaderReader&); | 	AUD_FaderReader& operator=(const AUD_FaderReader&); | ||||||
| @@ -79,10 +69,10 @@ public: | |||||||
| 	 * \param start The time where fading should start in seconds. | 	 * \param start The time where fading should start in seconds. | ||||||
| 	 * \param length How long fading should last in seconds. | 	 * \param length How long fading should last in seconds. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type, | 	AUD_FaderReader(AUD_Reference<AUD_IReader> reader, AUD_FadeType type, | ||||||
| 					float start,float length); | 					float start,float length); | ||||||
|  |  | ||||||
| 	virtual void read(int & length, sample_t* & buffer); | 	virtual void read(int& length, bool& eos, sample_t* buffer); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_FADERREADER | #endif //AUD_FADERREADER | ||||||
|   | |||||||
| @@ -38,30 +38,26 @@ | |||||||
| #define M_PI 3.14159265358979323846 | #define M_PI 3.14159265358979323846 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| AUD_HighpassFactory::AUD_HighpassFactory(AUD_IFactory* factory, float frequency, | AUD_HighpassFactory::AUD_HighpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, | ||||||
| 										 float Q) : | 										 float Q) : | ||||||
| 		AUD_EffectFactory(factory), | 		AUD_DynamicIIRFilterFactory(factory), | ||||||
| 		m_frequency(frequency), | 		m_frequency(frequency), | ||||||
| 		m_Q(Q) | 		m_Q(Q) | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_HighpassFactory::createReader() const | void AUD_HighpassFactory::recalculateCoefficients(AUD_SampleRate rate, | ||||||
|  | 												  std::vector<float> &b, | ||||||
|  | 												  std::vector<float> &a) | ||||||
| { | { | ||||||
| 	AUD_IReader* reader = getReader(); | 	float w0 = 2 * M_PI * m_frequency / rate; | ||||||
|  |  | ||||||
| 	// calculate coefficients |  | ||||||
| 	float w0 = 2 * M_PI * m_frequency / reader->getSpecs().rate; |  | ||||||
| 	float alpha = sin(w0) / (2 * m_Q); | 	float alpha = sin(w0) / (2 * m_Q); | ||||||
| 	float norm = 1 + alpha; | 	float norm = 1 + alpha; | ||||||
| 	float c = cos(w0); | 	float c = cos(w0); | ||||||
| 	std::vector<float> a, b; |  | ||||||
| 	a.push_back(1); | 	a.push_back(1); | ||||||
| 	a.push_back(-2 * c / norm); | 	a.push_back(-2 * c / norm); | ||||||
| 	a.push_back((1 - alpha) / norm); | 	a.push_back((1 - alpha) / norm); | ||||||
| 	b.push_back((1 + c) / (2 * norm)); | 	b.push_back((1 + c) / (2 * norm)); | ||||||
| 	b.push_back((-1 - c) / norm); | 	b.push_back((-1 - c) / norm); | ||||||
| 	b.push_back(b[0]); | 	b.push_back(b[0]); | ||||||
|  |  | ||||||
| 	return new AUD_IIRFilterReader(reader, b, a); |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -32,16 +32,16 @@ | |||||||
| #ifndef AUD_HIGHPASSFACTORY | #ifndef AUD_HIGHPASSFACTORY | ||||||
| #define AUD_HIGHPASSFACTORY | #define AUD_HIGHPASSFACTORY | ||||||
|  |  | ||||||
| #include "AUD_EffectFactory.h" | #include "AUD_DynamicIIRFilterFactory.h" | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This factory creates a highpass filter reader. |  * This factory creates a highpass filter reader. | ||||||
|  */ |  */ | ||||||
| class AUD_HighpassFactory : public AUD_EffectFactory | class AUD_HighpassFactory : public AUD_DynamicIIRFilterFactory | ||||||
| { | { | ||||||
| private: | private: | ||||||
| 	/** | 	/** | ||||||
| 	 * The attack value in seconds. | 	 * The cutoff frequency. | ||||||
| 	 */ | 	 */ | ||||||
| 	const float m_frequency; | 	const float m_frequency; | ||||||
|  |  | ||||||
| @@ -61,9 +61,9 @@ public: | |||||||
| 	 * \param frequency The cutoff frequency. | 	 * \param frequency The cutoff frequency. | ||||||
| 	 * \param Q The Q factor. | 	 * \param Q The Q factor. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_HighpassFactory(AUD_IFactory* factory, float frequency, float Q = 1.0f); | 	AUD_HighpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, float Q = 1.0f); | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual void recalculateCoefficients(AUD_SampleRate rate, std::vector<float> &b, std::vector<float> &a); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_HIGHPASSFACTORY | #endif //AUD_HIGHPASSFACTORY | ||||||
|   | |||||||
| @@ -32,14 +32,14 @@ | |||||||
| #include "AUD_IIRFilterFactory.h" | #include "AUD_IIRFilterFactory.h" | ||||||
| #include "AUD_IIRFilterReader.h" | #include "AUD_IIRFilterReader.h" | ||||||
|  |  | ||||||
| AUD_IIRFilterFactory::AUD_IIRFilterFactory(AUD_IFactory* factory, | AUD_IIRFilterFactory::AUD_IIRFilterFactory(AUD_Reference<AUD_IFactory> factory, | ||||||
| 										   std::vector<float> b, | 										   std::vector<float> b, | ||||||
| 										   std::vector<float> a) : | 										   std::vector<float> a) : | ||||||
| 		AUD_EffectFactory(factory), m_a(a), m_b(b) | 		AUD_EffectFactory(factory), m_a(a), m_b(b) | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_IIRFilterFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_IIRFilterFactory::createReader() | ||||||
| { | { | ||||||
| 	return new AUD_IIRFilterReader(getReader(), m_b, m_a); | 	return new AUD_IIRFilterReader(getReader(), m_b, m_a); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -63,10 +63,10 @@ public: | |||||||
| 	 * \param b The input filter coefficients. | 	 * \param b The input filter coefficients. | ||||||
| 	 * \param a The output filter coefficients. | 	 * \param a The output filter coefficients. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_IIRFilterFactory(AUD_IFactory* factory, std::vector<float> b, | 	AUD_IIRFilterFactory(AUD_Reference<AUD_IFactory> factory, std::vector<float> b, | ||||||
| 						 std::vector<float> a); | 						 std::vector<float> a); | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_IIRFILTERFACTORY | #endif //AUD_IIRFILTERFACTORY | ||||||
|   | |||||||
| @@ -31,9 +31,9 @@ | |||||||
|  |  | ||||||
| #include "AUD_IIRFilterReader.h" | #include "AUD_IIRFilterReader.h" | ||||||
|  |  | ||||||
| AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_IReader* reader, | AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_Reference<AUD_IReader> reader, | ||||||
| 										 std::vector<float> b, | 										 const std::vector<float>& b, | ||||||
| 										 std::vector<float> a) : | 										 const std::vector<float>& a) : | ||||||
| 	AUD_BaseIIRFilterReader(reader, b.size(), a.size()), m_a(a), m_b(b) | 	AUD_BaseIIRFilterReader(reader, b.size(), a.size()), m_a(a), m_b(b) | ||||||
| { | { | ||||||
| 	for(int i = 1; i < m_a.size(); i++) | 	for(int i = 1; i < m_a.size(); i++) | ||||||
| @@ -54,3 +54,11 @@ sample_t AUD_IIRFilterReader::filter() | |||||||
|  |  | ||||||
| 	return out; | 	return out; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void AUD_IIRFilterReader::setCoefficients(const std::vector<float>& b, | ||||||
|  | 										  const std::vector<float>& a) | ||||||
|  | { | ||||||
|  | 	setLengths(m_b.size(), m_a.size()); | ||||||
|  | 	m_a = a; | ||||||
|  | 	m_b = b; | ||||||
|  | } | ||||||
|   | |||||||
| @@ -63,10 +63,13 @@ public: | |||||||
| 	 * \param b The input filter coefficients. | 	 * \param b The input filter coefficients. | ||||||
| 	 * \param a The output filter coefficients. | 	 * \param a The output filter coefficients. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_IIRFilterReader(AUD_IReader* reader, std::vector<float> b, | 	AUD_IIRFilterReader(AUD_Reference<AUD_IReader> reader, const std::vector<float>& b, | ||||||
| 						std::vector<float> a); | 						const std::vector<float>& a); | ||||||
|  |  | ||||||
| 	virtual sample_t filter(); | 	virtual sample_t filter(); | ||||||
|  |  | ||||||
|  | 	void setCoefficients(const std::vector<float>& b, | ||||||
|  | 						 const std::vector<float>& a); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_IIRFILTERREADER | #endif //AUD_IIRFILTERREADER | ||||||
|   | |||||||
| @@ -33,7 +33,7 @@ | |||||||
| #include "AUD_LimiterReader.h" | #include "AUD_LimiterReader.h" | ||||||
| #include "AUD_Space.h" | #include "AUD_Space.h" | ||||||
|  |  | ||||||
| AUD_LimiterFactory::AUD_LimiterFactory(AUD_IFactory* factory, | AUD_LimiterFactory::AUD_LimiterFactory(AUD_Reference<AUD_IFactory> factory, | ||||||
| 									   float start, float end) : | 									   float start, float end) : | ||||||
| 		AUD_EffectFactory(factory), | 		AUD_EffectFactory(factory), | ||||||
| 		m_start(start), | 		m_start(start), | ||||||
| @@ -51,7 +51,7 @@ float AUD_LimiterFactory::getEnd() const | |||||||
| 	return m_end; | 	return m_end; | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_LimiterFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_LimiterFactory::createReader() | ||||||
| { | { | ||||||
| 	return new AUD_LimiterReader(getReader(), m_start, m_end); | 	return new AUD_LimiterReader(getReader(), m_start, m_end); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -62,7 +62,7 @@ public: | |||||||
| 	 * \param end The desired end time, a negative value signals that it should | 	 * \param end The desired end time, a negative value signals that it should | ||||||
| 	 *            play to the end. | 	 *            play to the end. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_LimiterFactory(AUD_IFactory* factory, | 	AUD_LimiterFactory(AUD_Reference<AUD_IFactory> factory, | ||||||
| 					   float start = 0, float end = -1); | 					   float start = 0, float end = -1); | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @@ -75,7 +75,7 @@ public: | |||||||
| 	 */ | 	 */ | ||||||
| 	float getEnd() const; | 	float getEnd() const; | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_LIMITERFACTORY | #endif //AUD_LIMITERFACTORY | ||||||
|   | |||||||
| @@ -32,30 +32,46 @@ | |||||||
| #include "AUD_LimiterReader.h" | #include "AUD_LimiterReader.h" | ||||||
| #include "AUD_Buffer.h" | #include "AUD_Buffer.h" | ||||||
|  |  | ||||||
| #include <iostream> | AUD_LimiterReader::AUD_LimiterReader(AUD_Reference<AUD_IReader> reader, | ||||||
|  |  | ||||||
| AUD_LimiterReader::AUD_LimiterReader(AUD_IReader* reader, |  | ||||||
| 									 float start, float end) : | 									 float start, float end) : | ||||||
| 		AUD_EffectReader(reader), | 		AUD_EffectReader(reader), | ||||||
| 		m_start(int(start * reader->getSpecs().rate)), | 		m_start(start), | ||||||
| 		m_end(int(end * reader->getSpecs().rate)) | 		m_end(end) | ||||||
| { | { | ||||||
| 	if(m_start > 0) | 	if(m_start > 0) | ||||||
| 	{ | 	{ | ||||||
|  | 		AUD_Specs specs = m_reader->getSpecs(); | ||||||
|  | 		AUD_Specs specs2; | ||||||
|  |  | ||||||
| 		if(m_reader->isSeekable()) | 		if(m_reader->isSeekable()) | ||||||
| 			m_reader->seek(m_start); | 			m_reader->seek(m_start * specs.rate); | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			// skip first m_start samples by reading them | 			// skip first m_start samples by reading them | ||||||
| 			int length = AUD_DEFAULT_BUFFER_SIZE; | 			int length = AUD_DEFAULT_BUFFER_SIZE; | ||||||
| 			sample_t* buffer; | 			AUD_Buffer buffer(AUD_DEFAULT_BUFFER_SIZE * AUD_SAMPLE_SIZE(specs)); | ||||||
| 			for(int len = m_start; | 			bool eos = false; | ||||||
| 				length == AUD_DEFAULT_BUFFER_SIZE; | 			for(int len = m_start * specs.rate; | ||||||
| 				len -= AUD_DEFAULT_BUFFER_SIZE) | 				length > 0 && !eos; | ||||||
|  | 				len -= length) | ||||||
| 			{ | 			{ | ||||||
| 				if(len < AUD_DEFAULT_BUFFER_SIZE) | 				if(len < AUD_DEFAULT_BUFFER_SIZE) | ||||||
| 					length = len; | 					length = len; | ||||||
| 				m_reader->read(length, buffer); |  | ||||||
|  | 				m_reader->read(length, eos, buffer.getBuffer()); | ||||||
|  |  | ||||||
|  | 				specs2 = m_reader->getSpecs(); | ||||||
|  | 				if(specs2.rate != specs.rate) | ||||||
|  | 				{ | ||||||
|  | 					len = len * specs2.rate / specs.rate; | ||||||
|  | 					specs.rate = specs2.rate; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if(specs2.channels != specs.channels) | ||||||
|  | 				{ | ||||||
|  | 					specs = specs2; | ||||||
|  | 					buffer.assureSize(AUD_DEFAULT_BUFFER_SIZE * AUD_SAMPLE_SIZE(specs)); | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -63,35 +79,71 @@ AUD_LimiterReader::AUD_LimiterReader(AUD_IReader* reader, | |||||||
|  |  | ||||||
| void AUD_LimiterReader::seek(int position) | void AUD_LimiterReader::seek(int position) | ||||||
| { | { | ||||||
| 	m_reader->seek(position + m_start); | 	m_reader->seek(position + m_start * m_reader->getSpecs().rate); | ||||||
| } | } | ||||||
|  |  | ||||||
| int AUD_LimiterReader::getLength() const | int AUD_LimiterReader::getLength() const | ||||||
| { | { | ||||||
| 	int len = m_reader->getLength(); | 	int len = m_reader->getLength(); | ||||||
| 	if(len < 0 || (len > m_end && m_end >= 0)) | 	AUD_SampleRate rate = m_reader->getSpecs().rate; | ||||||
| 		len = m_end; | 	if(len < 0 || (len > m_end * rate && m_end >= 0)) | ||||||
| 	return len - m_start; | 		len = m_end * rate; | ||||||
|  | 	return len - m_start * rate; | ||||||
| } | } | ||||||
|  |  | ||||||
| int AUD_LimiterReader::getPosition() const | int AUD_LimiterReader::getPosition() const | ||||||
| { | { | ||||||
| 	int pos = m_reader->getPosition(); | 	int pos = m_reader->getPosition(); | ||||||
| 	return AUD_MIN(pos, m_end) - m_start; | 	AUD_SampleRate rate = m_reader->getSpecs().rate; | ||||||
|  | 	return AUD_MIN(pos, m_end * rate) - m_start * rate; | ||||||
| } | } | ||||||
|  |  | ||||||
| void AUD_LimiterReader::read(int & length, sample_t* & buffer) | void AUD_LimiterReader::read(int& length, bool& eos, sample_t* buffer) | ||||||
| { | { | ||||||
|  | 	eos = false; | ||||||
| 	if(m_end >= 0) | 	if(m_end >= 0) | ||||||
| 	{ | 	{ | ||||||
| 		int position = m_reader->getPosition(); | 		int position = m_reader->getPosition(); | ||||||
| 		if(position + length > m_end) | 		AUD_SampleRate rate = m_reader->getSpecs().rate; | ||||||
| 			length = m_end - position; |  | ||||||
|  | 		if(position + length > m_end * rate) | ||||||
|  | 		{ | ||||||
|  | 			length = m_end * rate - position; | ||||||
|  | 			eos = true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if(position < m_start * rate) | ||||||
|  | 		{ | ||||||
|  | 			int len2 = length; | ||||||
|  | 			for(int len = m_start * rate - position; | ||||||
|  | 				len2 == length && !eos; | ||||||
|  | 				len -= length) | ||||||
|  | 			{ | ||||||
|  | 				if(len < length) | ||||||
|  | 					len2 = len; | ||||||
|  |  | ||||||
|  | 				m_reader->read(len2, eos, buffer); | ||||||
|  | 				position += len2; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if(position < m_start * rate) | ||||||
|  | 			{ | ||||||
|  | 				length = 0; | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		if(length < 0) | 		if(length < 0) | ||||||
| 		{ | 		{ | ||||||
| 			length = 0; | 			length = 0; | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	m_reader->read(length, buffer); | 	if(eos) | ||||||
|  | 	{ | ||||||
|  | 		m_reader->read(length, eos, buffer); | ||||||
|  | 		eos = true; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 		m_reader->read(length, eos, buffer); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ | |||||||
| #include "AUD_EffectReader.h" | #include "AUD_EffectReader.h" | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This reader limits another reader in start and end sample. |  * This reader limits another reader in start and end times. | ||||||
|  */ |  */ | ||||||
| class AUD_LimiterReader : public AUD_EffectReader | class AUD_LimiterReader : public AUD_EffectReader | ||||||
| { | { | ||||||
| @@ -43,12 +43,12 @@ private: | |||||||
| 	/** | 	/** | ||||||
| 	 * The start sample: inclusive. | 	 * The start sample: inclusive. | ||||||
| 	 */ | 	 */ | ||||||
| 	const int m_start; | 	const float m_start; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The end sample: exlusive. | 	 * The end sample: exlusive. | ||||||
| 	 */ | 	 */ | ||||||
| 	const int m_end; | 	const float m_end; | ||||||
|  |  | ||||||
| 	// hide copy constructor and operator= | 	// hide copy constructor and operator= | ||||||
| 	AUD_LimiterReader(const AUD_LimiterReader&); | 	AUD_LimiterReader(const AUD_LimiterReader&); | ||||||
| @@ -58,16 +58,16 @@ public: | |||||||
| 	/** | 	/** | ||||||
| 	 * Creates a new limiter reader. | 	 * Creates a new limiter reader. | ||||||
| 	 * \param reader The reader to read from. | 	 * \param reader The reader to read from. | ||||||
| 	 * \param start The desired start sample (inclusive). | 	 * \param start The desired start time (inclusive). | ||||||
| 	 * \param end The desired end sample (exklusive), a negative value signals | 	 * \param end The desired end time (sample exklusive), a negative value | ||||||
| 	 *            that it should play to the end. | 	 *            signals that it should play to the end. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_LimiterReader(AUD_IReader* reader, float start = 0, float end = -1); | 	AUD_LimiterReader(AUD_Reference<AUD_IReader> reader, float start = 0, float end = -1); | ||||||
|  |  | ||||||
| 	virtual void seek(int position); | 	virtual void seek(int position); | ||||||
| 	virtual int getLength() const; | 	virtual int getLength() const; | ||||||
| 	virtual int getPosition() const; | 	virtual int getPosition() const; | ||||||
| 	virtual void read(int & length, sample_t* & buffer); | 	virtual void read(int& length, bool& eos, sample_t* buffer); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_LIMITERREADER | #endif //AUD_LIMITERREADER | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ | |||||||
| #include "AUD_LoopFactory.h" | #include "AUD_LoopFactory.h" | ||||||
| #include "AUD_LoopReader.h" | #include "AUD_LoopReader.h" | ||||||
|  |  | ||||||
| AUD_LoopFactory::AUD_LoopFactory(AUD_IFactory* factory, int loop) : | AUD_LoopFactory::AUD_LoopFactory(AUD_Reference<AUD_IFactory> factory, int loop) : | ||||||
| 		AUD_EffectFactory(factory), | 		AUD_EffectFactory(factory), | ||||||
| 		m_loop(loop) | 		m_loop(loop) | ||||||
| { | { | ||||||
| @@ -43,7 +43,7 @@ int AUD_LoopFactory::getLoop() const | |||||||
| 	return m_loop; | 	return m_loop; | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_LoopFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_LoopFactory::createReader() | ||||||
| { | { | ||||||
| 	return new AUD_LoopReader(getReader(), m_loop); | 	return new AUD_LoopReader(getReader(), m_loop); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -57,14 +57,14 @@ public: | |||||||
| 	 * \param loop The desired loop count, negative values result in endless | 	 * \param loop The desired loop count, negative values result in endless | ||||||
| 	 *        looping. | 	 *        looping. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_LoopFactory(AUD_IFactory* factory, int loop = -1); | 	AUD_LoopFactory(AUD_Reference<AUD_IFactory> factory, int loop = -1); | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Returns the loop count. | 	 * Returns the loop count. | ||||||
| 	 */ | 	 */ | ||||||
| 	int getLoop() const; | 	int getLoop() const; | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_LOOPFACTORY | #endif //AUD_LOOPFACTORY | ||||||
|   | |||||||
| @@ -34,7 +34,7 @@ | |||||||
|  |  | ||||||
| #include <cstring> | #include <cstring> | ||||||
|  |  | ||||||
| AUD_LoopReader::AUD_LoopReader(AUD_IReader* reader, int loop) : | AUD_LoopReader::AUD_LoopReader(AUD_Reference<AUD_IReader> reader, int loop) : | ||||||
| 		AUD_EffectReader(reader), m_count(loop), m_left(loop) | 		AUD_EffectReader(reader), m_count(loop), m_left(loop) | ||||||
| { | { | ||||||
| } | } | ||||||
| @@ -68,29 +68,20 @@ int AUD_LoopReader::getPosition() const | |||||||
| 	return m_reader->getPosition() * (m_count < 0 ? 1 : m_count); | 	return m_reader->getPosition() * (m_count < 0 ? 1 : m_count); | ||||||
| } | } | ||||||
|  |  | ||||||
| void AUD_LoopReader::read(int & length, sample_t* & buffer) | void AUD_LoopReader::read(int& length, bool& eos, sample_t* buffer) | ||||||
| { | { | ||||||
| 	AUD_Specs specs = m_reader->getSpecs(); | 	const AUD_Specs specs = m_reader->getSpecs(); | ||||||
| 	int samplesize = AUD_SAMPLE_SIZE(specs); |  | ||||||
|  |  | ||||||
| 	int len = length; | 	int len = length; | ||||||
|  |  | ||||||
| 	m_reader->read(len, buffer); | 	m_reader->read(length, eos, buffer); | ||||||
|  |  | ||||||
| 	if(len < length && m_left) | 	if(length < len && eos && m_left) | ||||||
| 	{ | 	{ | ||||||
| 		int pos = 0; | 		int pos = length; | ||||||
|  | 		length = len; | ||||||
|  |  | ||||||
| 		if(m_buffer.getSize() < length * samplesize) | 		while(pos < length && eos && m_left) | ||||||
| 			m_buffer.resize(length * samplesize); |  | ||||||
|  |  | ||||||
| 		sample_t* buf = m_buffer.getBuffer(); |  | ||||||
|  |  | ||||||
| 		memcpy(buf + pos * specs.channels, buffer, len * samplesize); |  | ||||||
|  |  | ||||||
| 		pos += len; |  | ||||||
|  |  | ||||||
| 		while(pos < length && m_left) |  | ||||||
| 		{ | 		{ | ||||||
| 			if(m_left > 0) | 			if(m_left > 0) | ||||||
| 				m_left--; | 				m_left--; | ||||||
| @@ -98,20 +89,15 @@ void AUD_LoopReader::read(int & length, sample_t* & buffer) | |||||||
| 			m_reader->seek(0); | 			m_reader->seek(0); | ||||||
|  |  | ||||||
| 			len = length - pos; | 			len = length - pos; | ||||||
| 			m_reader->read(len, buffer); | 			m_reader->read(len, eos, buffer + pos * specs.channels); | ||||||
|  |  | ||||||
| 			// prevent endless loop | 			// prevent endless loop | ||||||
| 			if(!len) | 			if(!len) | ||||||
| 				break; | 				break; | ||||||
|  |  | ||||||
| 			memcpy(buf + pos * specs.channels, buffer, len * samplesize); |  | ||||||
|  |  | ||||||
| 			pos += len; | 			pos += len; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		length = pos; | 		length = pos; | ||||||
| 		buffer = buf; |  | ||||||
| 	} | 	} | ||||||
| 	else |  | ||||||
| 		length = len; |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -42,11 +42,6 @@ | |||||||
| class AUD_LoopReader : public AUD_EffectReader | class AUD_LoopReader : public AUD_EffectReader | ||||||
| { | { | ||||||
| private: | private: | ||||||
| 	/** |  | ||||||
| 	 * The playback buffer. |  | ||||||
| 	 */ |  | ||||||
| 	AUD_Buffer m_buffer; |  | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The loop count. | 	 * The loop count. | ||||||
| 	 */ | 	 */ | ||||||
| @@ -68,12 +63,12 @@ public: | |||||||
| 	 * \param loop The desired loop count, negative values result in endless | 	 * \param loop The desired loop count, negative values result in endless | ||||||
| 	 *        looping. | 	 *        looping. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_LoopReader(AUD_IReader* reader, int loop); | 	AUD_LoopReader(AUD_Reference<AUD_IReader> reader, int loop); | ||||||
|  |  | ||||||
| 	virtual void seek(int position); | 	virtual void seek(int position); | ||||||
| 	virtual int getLength() const; | 	virtual int getLength() const; | ||||||
| 	virtual int getPosition() const; | 	virtual int getPosition() const; | ||||||
| 	virtual void read(int & length, sample_t* & buffer); | 	virtual void read(int& length, bool& eos, sample_t* buffer); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_LOOPREADER | #endif //AUD_LOOPREADER | ||||||
|   | |||||||
| @@ -38,30 +38,26 @@ | |||||||
| #define M_PI 3.14159265358979323846 | #define M_PI 3.14159265358979323846 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| AUD_LowpassFactory::AUD_LowpassFactory(AUD_IFactory* factory, float frequency, | AUD_LowpassFactory::AUD_LowpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, | ||||||
| 									   float Q) : | 									   float Q) : | ||||||
| 		AUD_EffectFactory(factory), | 		AUD_DynamicIIRFilterFactory(factory), | ||||||
| 		m_frequency(frequency), | 		m_frequency(frequency), | ||||||
| 		m_Q(Q) | 		m_Q(Q) | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_LowpassFactory::createReader() const | void AUD_LowpassFactory::recalculateCoefficients(AUD_SampleRate rate, | ||||||
|  | 												 std::vector<float> &b, | ||||||
|  | 												 std::vector<float> &a) | ||||||
| { | { | ||||||
| 	AUD_IReader* reader = getReader(); | 	float w0 = 2 * M_PI * m_frequency / rate; | ||||||
|  |  | ||||||
| 	// calculate coefficients |  | ||||||
| 	float w0 = 2 * M_PI * m_frequency / reader->getSpecs().rate; |  | ||||||
| 	float alpha = sin(w0) / (2 * m_Q); | 	float alpha = sin(w0) / (2 * m_Q); | ||||||
| 	float norm = 1 + alpha; | 	float norm = 1 + alpha; | ||||||
| 	float c = cos(w0); | 	float c = cos(w0); | ||||||
| 	std::vector<float> a, b; |  | ||||||
| 	a.push_back(1); | 	a.push_back(1); | ||||||
| 	a.push_back(-2 * c / norm); | 	a.push_back(-2 * c / norm); | ||||||
| 	a.push_back((1 - alpha) / norm); | 	a.push_back((1 - alpha) / norm); | ||||||
| 	b.push_back((1 - c) / (2 * norm)); | 	b.push_back((1 - c) / (2 * norm)); | ||||||
| 	b.push_back((1 - c) / norm); | 	b.push_back((1 - c) / norm); | ||||||
| 	b.push_back(b[0]); | 	b.push_back(b[0]); | ||||||
|  |  | ||||||
| 	return new AUD_IIRFilterReader(reader, b, a); |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -32,16 +32,16 @@ | |||||||
| #ifndef AUD_LOWPASSFACTORY | #ifndef AUD_LOWPASSFACTORY | ||||||
| #define AUD_LOWPASSFACTORY | #define AUD_LOWPASSFACTORY | ||||||
|  |  | ||||||
| #include "AUD_EffectFactory.h" | #include "AUD_DynamicIIRFilterFactory.h" | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This factory creates a lowpass filter reader. |  * This factory creates a lowpass filter reader. | ||||||
|  */ |  */ | ||||||
| class AUD_LowpassFactory : public AUD_EffectFactory | class AUD_LowpassFactory : public AUD_DynamicIIRFilterFactory | ||||||
| { | { | ||||||
| private: | private: | ||||||
| 	/** | 	/** | ||||||
| 	 * The attack value in seconds. | 	 * The cutoff frequency. | ||||||
| 	 */ | 	 */ | ||||||
| 	const float m_frequency; | 	const float m_frequency; | ||||||
|  |  | ||||||
| @@ -61,9 +61,9 @@ public: | |||||||
| 	 * \param frequency The cutoff frequency. | 	 * \param frequency The cutoff frequency. | ||||||
| 	 * \param Q The Q factor. | 	 * \param Q The Q factor. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_LowpassFactory(AUD_IFactory* factory, float frequency, float Q = 1.0f); | 	AUD_LowpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, float Q = 1.0f); | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual void recalculateCoefficients(AUD_SampleRate rate, std::vector<float> &b, std::vector<float> &a); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_LOWPASSFACTORY | #endif //AUD_LOWPASSFACTORY | ||||||
|   | |||||||
| @@ -33,26 +33,16 @@ | |||||||
| #include "AUD_DoubleReader.h" | #include "AUD_DoubleReader.h" | ||||||
| #include "AUD_ReverseFactory.h" | #include "AUD_ReverseFactory.h" | ||||||
|  |  | ||||||
| AUD_PingPongFactory::AUD_PingPongFactory(AUD_IFactory* factory) : | AUD_PingPongFactory::AUD_PingPongFactory(AUD_Reference<AUD_IFactory> factory) : | ||||||
| 		AUD_EffectFactory(factory) | 		AUD_EffectFactory(factory) | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_PingPongFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_PingPongFactory::createReader() | ||||||
| { | { | ||||||
| 	AUD_IReader* reader = getReader(); | 	AUD_Reference<AUD_IReader> reader = getReader(); | ||||||
| 	AUD_IReader* reader2; |  | ||||||
| 	AUD_ReverseFactory factory(m_factory); | 	AUD_ReverseFactory factory(m_factory); | ||||||
|  | 	AUD_Reference<AUD_IReader> reader2 = factory.createReader(); | ||||||
| 	try |  | ||||||
| 	{ |  | ||||||
| 		reader2 = factory.createReader(); |  | ||||||
| 	} |  | ||||||
| 	catch(AUD_Exception&) |  | ||||||
| 	{ |  | ||||||
| 		delete reader; |  | ||||||
| 		throw; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return new AUD_DoubleReader(reader, reader2); | 	return new AUD_DoubleReader(reader, reader2); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -36,7 +36,7 @@ | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This factory plays another factory first normal, then reversed. |  * This factory plays another factory first normal, then reversed. | ||||||
|  * \note Readers from the underlying factory must be from the buffer type. |  * \note Readers from the underlying factory must be reversable with seeking. | ||||||
|  */ |  */ | ||||||
| class AUD_PingPongFactory : public AUD_EffectFactory | class AUD_PingPongFactory : public AUD_EffectFactory | ||||||
| { | { | ||||||
| @@ -50,9 +50,9 @@ public: | |||||||
| 	 * Creates a new ping pong factory. | 	 * Creates a new ping pong factory. | ||||||
| 	 * \param factory The input factory. | 	 * \param factory The input factory. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_PingPongFactory(AUD_IFactory* factory); | 	AUD_PingPongFactory(AUD_Reference<AUD_IFactory> factory); | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_PINGPONGFACTORY | #endif //AUD_PINGPONGFACTORY | ||||||
|   | |||||||
| @@ -33,13 +33,13 @@ | |||||||
| #include "AUD_PitchReader.h" | #include "AUD_PitchReader.h" | ||||||
| #include "AUD_Space.h" | #include "AUD_Space.h" | ||||||
|  |  | ||||||
| AUD_PitchFactory::AUD_PitchFactory(AUD_IFactory* factory, float pitch) : | AUD_PitchFactory::AUD_PitchFactory(AUD_Reference<AUD_IFactory> factory, float pitch) : | ||||||
| 		AUD_EffectFactory(factory), | 		AUD_EffectFactory(factory), | ||||||
| 		m_pitch(pitch) | 		m_pitch(pitch) | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_PitchFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_PitchFactory::createReader() | ||||||
| { | { | ||||||
| 	return new AUD_PitchReader(getReader(), m_pitch); | 	return new AUD_PitchReader(getReader(), m_pitch); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -55,9 +55,9 @@ public: | |||||||
| 	 * \param factory The input factory. | 	 * \param factory The input factory. | ||||||
| 	 * \param pitch The desired pitch. | 	 * \param pitch The desired pitch. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_PitchFactory(AUD_IFactory* factory, float pitch); | 	AUD_PitchFactory(AUD_Reference<AUD_IFactory> factory, float pitch); | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_PITCHFACTORY | #endif //AUD_PITCHFACTORY | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ | |||||||
|  |  | ||||||
| #include "AUD_PitchReader.h" | #include "AUD_PitchReader.h" | ||||||
|  |  | ||||||
| AUD_PitchReader::AUD_PitchReader(AUD_IReader* reader, float pitch) : | AUD_PitchReader::AUD_PitchReader(AUD_Reference<AUD_IReader> reader, float pitch) : | ||||||
| 		AUD_EffectReader(reader), m_pitch(pitch) | 		AUD_EffectReader(reader), m_pitch(pitch) | ||||||
| { | { | ||||||
| } | } | ||||||
| @@ -39,6 +39,16 @@ AUD_PitchReader::AUD_PitchReader(AUD_IReader* reader, float pitch) : | |||||||
| AUD_Specs AUD_PitchReader::getSpecs() const | AUD_Specs AUD_PitchReader::getSpecs() const | ||||||
| { | { | ||||||
| 	AUD_Specs specs = m_reader->getSpecs(); | 	AUD_Specs specs = m_reader->getSpecs(); | ||||||
| 	specs.rate = (AUD_SampleRate)((int)(specs.rate * m_pitch)); | 	specs.rate *= m_pitch; | ||||||
| 	return specs; | 	return specs; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | float AUD_PitchReader::getPitch() const | ||||||
|  | { | ||||||
|  | 	return m_pitch; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AUD_PitchReader::setPitch(float pitch) | ||||||
|  | { | ||||||
|  | 	m_pitch = pitch; | ||||||
|  | } | ||||||
|   | |||||||
| @@ -43,7 +43,7 @@ private: | |||||||
| 	/** | 	/** | ||||||
| 	 * The pitch level. | 	 * The pitch level. | ||||||
| 	 */ | 	 */ | ||||||
| 	const float m_pitch; | 	float m_pitch; | ||||||
|  |  | ||||||
| 	// hide copy constructor and operator= | 	// hide copy constructor and operator= | ||||||
| 	AUD_PitchReader(const AUD_PitchReader&); | 	AUD_PitchReader(const AUD_PitchReader&); | ||||||
| @@ -53,11 +53,23 @@ public: | |||||||
| 	/** | 	/** | ||||||
| 	 * Creates a new pitch reader. | 	 * Creates a new pitch reader. | ||||||
| 	 * \param reader The reader to read from. | 	 * \param reader The reader to read from. | ||||||
| 	 * \param pitch The size of the buffer. | 	 * \param pitch The pitch value. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_PitchReader(AUD_IReader* reader, float pitch); | 	AUD_PitchReader(AUD_Reference<AUD_IReader> reader, float pitch); | ||||||
|  |  | ||||||
| 	virtual AUD_Specs getSpecs() const; | 	virtual AUD_Specs getSpecs() const; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Retrieves the pitch. | ||||||
|  | 	 * \return The current pitch value. | ||||||
|  | 	 */ | ||||||
|  | 	float getPitch() const; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Sets the pitch. | ||||||
|  | 	 * \param pitch The new pitch value. | ||||||
|  | 	 */ | ||||||
|  | 	void setPitch(float pitch); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_PITCHREADER | #endif //AUD_PITCHREADER | ||||||
|   | |||||||
| @@ -34,17 +34,17 @@ | |||||||
|  |  | ||||||
| #include <cmath> | #include <cmath> | ||||||
|  |  | ||||||
| sample_t rectifyFilter(AUD_CallbackIIRFilterReader* reader, void* useless) | sample_t AUD_RectifyFactory::rectifyFilter(AUD_CallbackIIRFilterReader* reader, void* useless) | ||||||
| { | { | ||||||
| 	return fabs(reader->x(0)); | 	return fabs(reader->x(0)); | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_RectifyFactory::AUD_RectifyFactory(AUD_IFactory* factory) : | AUD_RectifyFactory::AUD_RectifyFactory(AUD_Reference<AUD_IFactory> factory) : | ||||||
| 		AUD_EffectFactory(factory) | 		AUD_EffectFactory(factory) | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_RectifyFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_RectifyFactory::createReader() | ||||||
| { | { | ||||||
| 	return new AUD_CallbackIIRFilterReader(getReader(), 1, 1, rectifyFilter); | 	return new AUD_CallbackIIRFilterReader(getReader(), 1, 1, rectifyFilter); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -33,6 +33,7 @@ | |||||||
| #define AUD_RECTIFYFACTORY | #define AUD_RECTIFYFACTORY | ||||||
|  |  | ||||||
| #include "AUD_EffectFactory.h" | #include "AUD_EffectFactory.h" | ||||||
|  | class AUD_CallbackIIRFilterReader; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This factory rectifies another factory. |  * This factory rectifies another factory. | ||||||
| @@ -49,9 +50,11 @@ public: | |||||||
| 	 * Creates a new rectify factory. | 	 * Creates a new rectify factory. | ||||||
| 	 * \param factory The input factory. | 	 * \param factory The input factory. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_RectifyFactory(AUD_IFactory* factory); | 	AUD_RectifyFactory(AUD_Reference<AUD_IFactory> factory); | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
|  |  | ||||||
|  | 	static sample_t rectifyFilter(AUD_CallbackIIRFilterReader* reader, void* useless); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_RECTIFYFACTORY | #endif //AUD_RECTIFYFACTORY | ||||||
|   | |||||||
| @@ -33,12 +33,12 @@ | |||||||
| #include "AUD_ReverseReader.h" | #include "AUD_ReverseReader.h" | ||||||
| #include "AUD_Space.h" | #include "AUD_Space.h" | ||||||
|  |  | ||||||
| AUD_ReverseFactory::AUD_ReverseFactory(AUD_IFactory* factory) : | AUD_ReverseFactory::AUD_ReverseFactory(AUD_Reference<AUD_IFactory> factory) : | ||||||
| 		AUD_EffectFactory(factory) | 		AUD_EffectFactory(factory) | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_ReverseFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_ReverseFactory::createReader() | ||||||
| { | { | ||||||
| 	return new AUD_ReverseReader(getReader()); | 	return new AUD_ReverseReader(getReader()); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -36,7 +36,7 @@ | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This factory reads another factory reverted. |  * This factory reads another factory reverted. | ||||||
|  * \note Readers from the underlying factory must be from the buffer type. |  * \note Readers from the underlying factory must be seekable. | ||||||
|  */ |  */ | ||||||
| class AUD_ReverseFactory : public AUD_EffectFactory | class AUD_ReverseFactory : public AUD_EffectFactory | ||||||
| { | { | ||||||
| @@ -50,9 +50,9 @@ public: | |||||||
| 	 * Creates a new reverse factory. | 	 * Creates a new reverse factory. | ||||||
| 	 * \param factory The input factory. | 	 * \param factory The input factory. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_ReverseFactory(AUD_IFactory* factory); | 	AUD_ReverseFactory(AUD_Reference<AUD_IFactory> factory); | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_REVERSEFACTORY | #endif //AUD_REVERSEFACTORY | ||||||
|   | |||||||
| @@ -36,7 +36,7 @@ | |||||||
| static const char* props_error = "AUD_ReverseReader: The reader has to be " | static const char* props_error = "AUD_ReverseReader: The reader has to be " | ||||||
| 								 "seekable and a finite length."; | 								 "seekable and a finite length."; | ||||||
|  |  | ||||||
| AUD_ReverseReader::AUD_ReverseReader(AUD_IReader* reader) : | AUD_ReverseReader::AUD_ReverseReader(AUD_Reference<AUD_IReader> reader) : | ||||||
| 		AUD_EffectReader(reader), | 		AUD_EffectReader(reader), | ||||||
| 		m_length(reader->getLength()), | 		m_length(reader->getLength()), | ||||||
| 		m_position(0) | 		m_position(0) | ||||||
| @@ -60,7 +60,7 @@ int AUD_ReverseReader::getPosition() const | |||||||
| 	return m_position; | 	return m_position; | ||||||
| } | } | ||||||
|  |  | ||||||
| void AUD_ReverseReader::read(int & length, sample_t* & buffer) | void AUD_ReverseReader::read(int& length, bool& eos, sample_t* buffer) | ||||||
| { | { | ||||||
| 	// first correct the length | 	// first correct the length | ||||||
| 	if(m_position + length > m_length) | 	if(m_position + length > m_length) | ||||||
| @@ -69,39 +69,39 @@ void AUD_ReverseReader::read(int & length, sample_t* & buffer) | |||||||
| 	if(length <= 0) | 	if(length <= 0) | ||||||
| 	{ | 	{ | ||||||
| 		length = 0; | 		length = 0; | ||||||
|  | 		eos = true; | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	AUD_Specs specs = getSpecs(); | 	const AUD_Specs specs = getSpecs(); | ||||||
| 	int samplesize = AUD_SAMPLE_SIZE(specs); | 	const int samplesize = AUD_SAMPLE_SIZE(specs); | ||||||
|  |  | ||||||
| 	// resize buffer if needed | 	sample_t temp[AUD_CHANNEL_MAX]; | ||||||
| 	if(m_buffer.getSize() < length * samplesize) |  | ||||||
| 		m_buffer.resize(length * samplesize); |  | ||||||
|  |  | ||||||
| 	buffer = m_buffer.getBuffer(); |  | ||||||
|  |  | ||||||
| 	sample_t* buf; |  | ||||||
| 	int len = length; | 	int len = length; | ||||||
|  |  | ||||||
| 	// read from reader | 	// read from reader | ||||||
| 	m_reader->seek(m_length - m_position - len); | 	m_reader->seek(m_length - m_position - len); | ||||||
| 	m_reader->read(len, buf); | 	m_reader->read(len, eos, buffer); | ||||||
|  |  | ||||||
| 	// set null if reader didn't give enough data | 	// set null if reader didn't give enough data | ||||||
| 	if(len < length) | 	if(len < length) | ||||||
| 	{ |  | ||||||
| 		memset(buffer, 0, (length - len) * samplesize); | 		memset(buffer, 0, (length - len) * samplesize); | ||||||
| 		buffer += (length - len) * specs.channels; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// copy the samples reverted | 	// copy the samples reverted | ||||||
| 	for(int i = 0; i < len; i++) | 	for(int i = 0; i < length / 2; i++) | ||||||
| 		memcpy(buffer + i * specs.channels, | 	{ | ||||||
| 			   buf + (len - 1 - i) * specs.channels, | 		memcpy(temp, | ||||||
|  | 			   buffer + (len - 1 - i) * specs.channels, | ||||||
| 			   samplesize); | 			   samplesize); | ||||||
|  | 		memcpy(buffer + (len - 1 - i) * specs.channels, | ||||||
|  | 			   buffer + i * specs.channels, | ||||||
|  | 			   samplesize); | ||||||
|  | 		memcpy(buffer + i * specs.channels, | ||||||
|  | 			   temp, | ||||||
|  | 			   samplesize); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	m_position += length; | 	m_position += length; | ||||||
|  | 	eos = false; | ||||||
| 	buffer = m_buffer.getBuffer(); |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This class reads another reader from back to front. |  * This class reads another reader from back to front. | ||||||
|  * \note The underlying reader must be a buffer. |  * \note The underlying reader must be seekable. | ||||||
|  */ |  */ | ||||||
| class AUD_ReverseReader : public AUD_EffectReader | class AUD_ReverseReader : public AUD_EffectReader | ||||||
| { | { | ||||||
| @@ -52,11 +52,6 @@ private: | |||||||
| 	 */ | 	 */ | ||||||
| 	int m_position; | 	int m_position; | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * The playback buffer. |  | ||||||
| 	 */ |  | ||||||
| 	AUD_Buffer m_buffer; |  | ||||||
|  |  | ||||||
| 	// hide copy constructor and operator= | 	// hide copy constructor and operator= | ||||||
| 	AUD_ReverseReader(const AUD_ReverseReader&); | 	AUD_ReverseReader(const AUD_ReverseReader&); | ||||||
| 	AUD_ReverseReader& operator=(const AUD_ReverseReader&); | 	AUD_ReverseReader& operator=(const AUD_ReverseReader&); | ||||||
| @@ -68,12 +63,12 @@ public: | |||||||
| 	 * \exception AUD_Exception Thrown if the reader specified has an | 	 * \exception AUD_Exception Thrown if the reader specified has an | ||||||
| 	 *            undeterminable/infinite length or is not seekable. | 	 *            undeterminable/infinite length or is not seekable. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_ReverseReader(AUD_IReader* reader); | 	AUD_ReverseReader(AUD_Reference<AUD_IReader> reader); | ||||||
|  |  | ||||||
| 	virtual void seek(int position); | 	virtual void seek(int position); | ||||||
| 	virtual int getLength() const; | 	virtual int getLength() const; | ||||||
| 	virtual int getPosition() const; | 	virtual int getPosition() const; | ||||||
| 	virtual void read(int & length, sample_t* & buffer); | 	virtual void read(int& length, bool& eos, sample_t* buffer); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_REVERSEREADER | #endif //AUD_REVERSEREADER | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ | |||||||
| #include "AUD_SquareFactory.h" | #include "AUD_SquareFactory.h" | ||||||
| #include "AUD_CallbackIIRFilterReader.h" | #include "AUD_CallbackIIRFilterReader.h" | ||||||
|  |  | ||||||
| sample_t squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold) | sample_t AUD_SquareFactory::squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold) | ||||||
| { | { | ||||||
| 	float in = reader->x(0); | 	float in = reader->x(0); | ||||||
| 	if(in >= *threshold) | 	if(in >= *threshold) | ||||||
| @@ -43,12 +43,12 @@ sample_t squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold) | |||||||
| 		return 0; | 		return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| void endSquareFilter(float* threshold) | void AUD_SquareFactory::endSquareFilter(float* threshold) | ||||||
| { | { | ||||||
| 	delete threshold; | 	delete threshold; | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_SquareFactory::AUD_SquareFactory(AUD_IFactory* factory, float threshold) : | AUD_SquareFactory::AUD_SquareFactory(AUD_Reference<AUD_IFactory> factory, float threshold) : | ||||||
| 		AUD_EffectFactory(factory), | 		AUD_EffectFactory(factory), | ||||||
| 		m_threshold(threshold) | 		m_threshold(threshold) | ||||||
| { | { | ||||||
| @@ -59,7 +59,7 @@ float AUD_SquareFactory::getThreshold() const | |||||||
| 	return m_threshold; | 	return m_threshold; | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_SquareFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_SquareFactory::createReader() | ||||||
| { | { | ||||||
| 	return new AUD_CallbackIIRFilterReader(getReader(), 1, 1, | 	return new AUD_CallbackIIRFilterReader(getReader(), 1, 1, | ||||||
| 										   (doFilterIIR) squareFilter, | 										   (doFilterIIR) squareFilter, | ||||||
|   | |||||||
| @@ -33,6 +33,7 @@ | |||||||
| #define AUD_SQUAREFACTORY | #define AUD_SQUAREFACTORY | ||||||
|  |  | ||||||
| #include "AUD_EffectFactory.h" | #include "AUD_EffectFactory.h" | ||||||
|  | class AUD_CallbackIIRFilterReader; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This factory Transforms any signal to a square signal. |  * This factory Transforms any signal to a square signal. | ||||||
| @@ -55,14 +56,17 @@ public: | |||||||
| 	 * \param factory The input factory. | 	 * \param factory The input factory. | ||||||
| 	 * \param threshold The threshold. | 	 * \param threshold The threshold. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_SquareFactory(AUD_IFactory* factory, float threshold = 0.0f); | 	AUD_SquareFactory(AUD_Reference<AUD_IFactory> factory, float threshold = 0.0f); | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Returns the threshold. | 	 * Returns the threshold. | ||||||
| 	 */ | 	 */ | ||||||
| 	float getThreshold() const; | 	float getThreshold() const; | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
|  |  | ||||||
|  | 	static sample_t squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold); | ||||||
|  | 	static void endSquareFilter(float* threshold); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_SQUAREFACTORY | #endif //AUD_SQUAREFACTORY | ||||||
|   | |||||||
| @@ -32,12 +32,12 @@ | |||||||
| #include "AUD_SumFactory.h" | #include "AUD_SumFactory.h" | ||||||
| #include "AUD_IIRFilterReader.h" | #include "AUD_IIRFilterReader.h" | ||||||
|  |  | ||||||
| AUD_SumFactory::AUD_SumFactory(AUD_IFactory* factory) : | AUD_SumFactory::AUD_SumFactory(AUD_Reference<AUD_IFactory> factory) : | ||||||
| 		AUD_EffectFactory(factory) | 		AUD_EffectFactory(factory) | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_SumFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_SumFactory::createReader() | ||||||
| { | { | ||||||
| 	std::vector<float> a, b; | 	std::vector<float> a, b; | ||||||
| 	a.push_back(1); | 	a.push_back(1); | ||||||
|   | |||||||
| @@ -49,9 +49,9 @@ public: | |||||||
| 	 * Creates a new sum factory. | 	 * Creates a new sum factory. | ||||||
| 	 * \param factory The input factory. | 	 * \param factory The input factory. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_SumFactory(AUD_IFactory* factory); | 	AUD_SumFactory(AUD_Reference<AUD_IFactory> factory); | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_SUMFACTORY | #endif //AUD_SUMFACTORY | ||||||
|   | |||||||
| @@ -32,24 +32,15 @@ | |||||||
| #include "AUD_SuperposeFactory.h" | #include "AUD_SuperposeFactory.h" | ||||||
| #include "AUD_SuperposeReader.h" | #include "AUD_SuperposeReader.h" | ||||||
|  |  | ||||||
| AUD_SuperposeFactory::AUD_SuperposeFactory(AUD_IFactory* factory1, AUD_IFactory* factory2) : | AUD_SuperposeFactory::AUD_SuperposeFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2) : | ||||||
| 		m_factory1(factory1), m_factory2(factory2) | 		m_factory1(factory1), m_factory2(factory2) | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_SuperposeFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_SuperposeFactory::createReader() | ||||||
| { | { | ||||||
| 	AUD_IReader* reader1 = m_factory1->createReader(); | 	AUD_Reference<AUD_IReader> reader1 = m_factory1->createReader(); | ||||||
| 	AUD_IReader* reader2; | 	AUD_Reference<AUD_IReader> reader2 = m_factory2->createReader(); | ||||||
| 	try |  | ||||||
| 	{ |  | ||||||
| 		reader2 = m_factory2->createReader(); |  | ||||||
| 	} |  | ||||||
| 	catch(AUD_Exception&) |  | ||||||
| 	{ |  | ||||||
| 		delete reader1; |  | ||||||
| 		throw; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return new AUD_SuperposeReader(reader1, reader2); | 	return new AUD_SuperposeReader(reader1, reader2); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -35,8 +35,9 @@ | |||||||
| #include "AUD_IFactory.h" | #include "AUD_IFactory.h" | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This factory plays two other factories behind each other. |  * This factory mixes two other factories, playing them the same time. | ||||||
|  * \note Readers from the underlying factories must have the same sample rate and channel count. |  * \note Readers from the underlying factories must have the same sample rate | ||||||
|  |  *       and channel count. | ||||||
|  */ |  */ | ||||||
| class AUD_SuperposeFactory : public AUD_IFactory | class AUD_SuperposeFactory : public AUD_IFactory | ||||||
| { | { | ||||||
| @@ -44,12 +45,12 @@ private: | |||||||
| 	/** | 	/** | ||||||
| 	 * First played factory. | 	 * First played factory. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_IFactory* m_factory1; | 	AUD_Reference<AUD_IFactory> m_factory1; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Second played factory. | 	 * Second played factory. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_IFactory* m_factory2; | 	AUD_Reference<AUD_IFactory> m_factory2; | ||||||
|  |  | ||||||
| 	// hide copy constructor and operator= | 	// hide copy constructor and operator= | ||||||
| 	AUD_SuperposeFactory(const AUD_SuperposeFactory&); | 	AUD_SuperposeFactory(const AUD_SuperposeFactory&); | ||||||
| @@ -61,9 +62,9 @@ public: | |||||||
| 	 * \param factory1 The first input factory. | 	 * \param factory1 The first input factory. | ||||||
| 	 * \param factory2 The second input factory. | 	 * \param factory2 The second input factory. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_SuperposeFactory(AUD_IFactory* factory1, AUD_IFactory* factory2); | 	AUD_SuperposeFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2); | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_SUPERPOSEFACTORY | #endif //AUD_SUPERPOSEFACTORY | ||||||
|   | |||||||
| @@ -36,30 +36,13 @@ | |||||||
| static const char* specs_error = "AUD_SuperposeReader: Both readers have to " | static const char* specs_error = "AUD_SuperposeReader: Both readers have to " | ||||||
| 								 "have the same specs."; | 								 "have the same specs."; | ||||||
|  |  | ||||||
| AUD_SuperposeReader::AUD_SuperposeReader(AUD_IReader* reader1, AUD_IReader* reader2) : | AUD_SuperposeReader::AUD_SuperposeReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<AUD_IReader> reader2) : | ||||||
| 	m_reader1(reader1), m_reader2(reader2) | 	m_reader1(reader1), m_reader2(reader2) | ||||||
| { | { | ||||||
| 	try |  | ||||||
| 	{ |  | ||||||
| 		AUD_Specs s1, s2; |  | ||||||
| 		s1 = reader1->getSpecs(); |  | ||||||
| 		s2 = reader2->getSpecs(); |  | ||||||
| 		if(memcmp(&s1, &s2, sizeof(AUD_Specs))) |  | ||||||
| 			AUD_THROW(AUD_ERROR_SPECS, specs_error); |  | ||||||
| 	} |  | ||||||
| 	catch(AUD_Exception&) |  | ||||||
| 	{ |  | ||||||
| 		delete reader1; |  | ||||||
| 		delete reader2; |  | ||||||
|  |  | ||||||
| 		throw; |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_SuperposeReader::~AUD_SuperposeReader() | AUD_SuperposeReader::~AUD_SuperposeReader() | ||||||
| { | { | ||||||
| 	delete m_reader1; |  | ||||||
| 	delete m_reader2; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| bool AUD_SuperposeReader::isSeekable() const | bool AUD_SuperposeReader::isSeekable() const | ||||||
| @@ -94,28 +77,31 @@ AUD_Specs AUD_SuperposeReader::getSpecs() const | |||||||
| 	return m_reader1->getSpecs(); | 	return m_reader1->getSpecs(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void AUD_SuperposeReader::read(int & length, sample_t* & buffer) | void AUD_SuperposeReader::read(int& length, bool& eos, sample_t* buffer) | ||||||
| { | { | ||||||
| 	AUD_Specs specs = m_reader1->getSpecs(); | 	AUD_Specs specs = m_reader1->getSpecs(); | ||||||
|  | 	AUD_Specs s2 = m_reader2->getSpecs(); | ||||||
|  | 	if(!AUD_COMPARE_SPECS(specs, s2)) | ||||||
|  | 		AUD_THROW(AUD_ERROR_SPECS, specs_error); | ||||||
|  |  | ||||||
| 	int samplesize = AUD_SAMPLE_SIZE(specs); | 	int samplesize = AUD_SAMPLE_SIZE(specs); | ||||||
|  |  | ||||||
| 	if(m_buffer.getSize() < length * samplesize) | 	m_buffer.assureSize(length * samplesize); | ||||||
| 		m_buffer.resize(length * samplesize); |  | ||||||
| 	buffer = m_buffer.getBuffer(); |  | ||||||
|  |  | ||||||
| 	int len1 = length; | 	int len1 = length; | ||||||
| 	sample_t* buf; | 	m_reader1->read(len1, eos, buffer); | ||||||
| 	m_reader1->read(len1, buf); |  | ||||||
| 	memcpy(buffer, buf, len1 * samplesize); |  | ||||||
|  |  | ||||||
| 	if(len1 < length) | 	if(len1 < length) | ||||||
| 		memset(buffer + len1 * specs.channels, 0, (length - len1) * samplesize); | 		memset(buffer + len1 * specs.channels, 0, (length - len1) * samplesize); | ||||||
|  |  | ||||||
| 	int len2 = length; | 	int len2 = length; | ||||||
| 	m_reader2->read(len2, buf); | 	bool eos2; | ||||||
|  | 	sample_t* buf = m_buffer.getBuffer(); | ||||||
|  | 	m_reader2->read(len2, eos2, buf); | ||||||
|  |  | ||||||
| 	for(int i = 0; i < len2 * specs.channels; i++) | 	for(int i = 0; i < len2 * specs.channels; i++) | ||||||
| 		buffer[i] += buf[i]; | 		buffer[i] += buf[i]; | ||||||
|  |  | ||||||
| 	length = AUD_MAX(len1, len2); | 	length = AUD_MAX(len1, len2); | ||||||
|  | 	eos &= eos2; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -34,9 +34,10 @@ | |||||||
|  |  | ||||||
| #include "AUD_IReader.h" | #include "AUD_IReader.h" | ||||||
| #include "AUD_Buffer.h" | #include "AUD_Buffer.h" | ||||||
|  | #include "AUD_Reference.h" | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This reader plays two readers with the same specs sequently. |  * This reader plays two readers with the same specs in parallel. | ||||||
|  */ |  */ | ||||||
| class AUD_SuperposeReader : public AUD_IReader | class AUD_SuperposeReader : public AUD_IReader | ||||||
| { | { | ||||||
| @@ -44,15 +45,15 @@ private: | |||||||
| 	/** | 	/** | ||||||
| 	 * The first reader. | 	 * The first reader. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_IReader* m_reader1; | 	AUD_Reference<AUD_IReader> m_reader1; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The second reader. | 	 * The second reader. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_IReader* m_reader2; | 	AUD_Reference<AUD_IReader> m_reader2; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The playback buffer for the intersecting part. | 	 * Buffer used for mixing. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_Buffer m_buffer; | 	AUD_Buffer m_buffer; | ||||||
|  |  | ||||||
| @@ -67,7 +68,7 @@ public: | |||||||
| 	 * \param reader2 The second reader to read from. | 	 * \param reader2 The second reader to read from. | ||||||
| 	 * \exception AUD_Exception Thrown if the specs from the readers differ. | 	 * \exception AUD_Exception Thrown if the specs from the readers differ. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_SuperposeReader(AUD_IReader* reader1, AUD_IReader* reader2); | 	AUD_SuperposeReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<AUD_IReader> reader2); | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Destroys the reader. | 	 * Destroys the reader. | ||||||
| @@ -79,7 +80,7 @@ public: | |||||||
| 	virtual int getLength() const; | 	virtual int getLength() const; | ||||||
| 	virtual int getPosition() const; | 	virtual int getPosition() const; | ||||||
| 	virtual AUD_Specs getSpecs() const; | 	virtual AUD_Specs getSpecs() const; | ||||||
| 	virtual void read(int & length, sample_t* & buffer); | 	virtual void read(int& length, bool& eos, sample_t* buffer); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_SUPERPOSEREADER | #endif //AUD_SUPERPOSEREADER | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ | |||||||
| #include "AUD_VolumeFactory.h" | #include "AUD_VolumeFactory.h" | ||||||
| #include "AUD_IIRFilterReader.h" | #include "AUD_IIRFilterReader.h" | ||||||
|  |  | ||||||
| AUD_VolumeFactory::AUD_VolumeFactory(AUD_IFactory* factory, float volume) : | AUD_VolumeFactory::AUD_VolumeFactory(AUD_Reference<AUD_IFactory> factory, float volume) : | ||||||
| 		AUD_EffectFactory(factory), | 		AUD_EffectFactory(factory), | ||||||
| 		m_volume(volume) | 		m_volume(volume) | ||||||
| { | { | ||||||
| @@ -43,7 +43,7 @@ float AUD_VolumeFactory::getVolume() const | |||||||
| 	return m_volume; | 	return m_volume; | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_VolumeFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_VolumeFactory::createReader() | ||||||
| { | { | ||||||
| 	std::vector<float> a, b; | 	std::vector<float> a, b; | ||||||
| 	a.push_back(1); | 	a.push_back(1); | ||||||
|   | |||||||
| @@ -57,14 +57,15 @@ public: | |||||||
| 	 * \param factory The input factory. | 	 * \param factory The input factory. | ||||||
| 	 * \param volume The desired volume. | 	 * \param volume The desired volume. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_VolumeFactory(AUD_IFactory* factory, float volume); | 	AUD_VolumeFactory(AUD_Reference<AUD_IFactory> factory, float volume); | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Returns the volume. | 	 * Returns the volume. | ||||||
|  | 	 * \return The current volume. | ||||||
| 	 */ | 	 */ | ||||||
| 	float getVolume() const; | 	float getVolume() const; | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_VOLUMEFACTORY | #endif //AUD_VOLUMEFACTORY | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -33,9 +33,11 @@ | |||||||
| #define AUD_OPENALDEVICE | #define AUD_OPENALDEVICE | ||||||
|  |  | ||||||
| #include "AUD_IDevice.h" | #include "AUD_IDevice.h" | ||||||
|  | #include "AUD_IHandle.h" | ||||||
| #include "AUD_I3DDevice.h" | #include "AUD_I3DDevice.h" | ||||||
| struct AUD_OpenALHandle; | #include "AUD_I3DHandle.h" | ||||||
| struct AUD_OpenALBufferedFactory; | #include "AUD_Buffer.h" | ||||||
|  | //struct AUD_OpenALBufferedFactory; | ||||||
|  |  | ||||||
| #include <AL/al.h> | #include <AL/al.h> | ||||||
| #include <AL/alc.h> | #include <AL/alc.h> | ||||||
| @@ -48,6 +50,110 @@ struct AUD_OpenALBufferedFactory; | |||||||
| class AUD_OpenALDevice : public AUD_IDevice, public AUD_I3DDevice | class AUD_OpenALDevice : public AUD_IDevice, public AUD_I3DDevice | ||||||
| { | { | ||||||
| private: | private: | ||||||
|  | 	/// Saves the data for playback. | ||||||
|  | 	class AUD_OpenALHandle : public AUD_IHandle, public AUD_I3DHandle | ||||||
|  | 	{ | ||||||
|  | 	public: | ||||||
|  | 		static const int CYCLE_BUFFERS = 3; | ||||||
|  |  | ||||||
|  | 		/// Whether it's a buffered or a streamed source. | ||||||
|  | 		bool m_isBuffered; | ||||||
|  |  | ||||||
|  | 		/// The reader source. | ||||||
|  | 		AUD_Reference<AUD_IReader> m_reader; | ||||||
|  |  | ||||||
|  | 		/// Whether to keep the source if end of it is reached. | ||||||
|  | 		bool m_keep; | ||||||
|  |  | ||||||
|  | 		/// OpenAL sample format. | ||||||
|  | 		ALenum m_format; | ||||||
|  |  | ||||||
|  | 		/// OpenAL source. | ||||||
|  | 		ALuint m_source; | ||||||
|  |  | ||||||
|  | 		/// OpenAL buffers. | ||||||
|  | 		ALuint m_buffers[CYCLE_BUFFERS]; | ||||||
|  |  | ||||||
|  | 		/// The first buffer to be read next. | ||||||
|  | 		int m_current; | ||||||
|  |  | ||||||
|  | 		/// Whether the stream doesn't return any more data. | ||||||
|  | 		bool m_eos; | ||||||
|  |  | ||||||
|  | 		/// The loop count of the source. | ||||||
|  | 		int m_loopcount; | ||||||
|  |  | ||||||
|  | 		/// The stop callback. | ||||||
|  | 		stopCallback m_stop; | ||||||
|  |  | ||||||
|  | 		/// Stop callback data. | ||||||
|  | 		void* m_stop_data; | ||||||
|  |  | ||||||
|  | 		/// Orientation. | ||||||
|  | 		AUD_Quaternion m_orientation; | ||||||
|  |  | ||||||
|  | 		/// Current status of the handle | ||||||
|  | 		AUD_Status m_status; | ||||||
|  |  | ||||||
|  | 		/// Own device. | ||||||
|  | 		AUD_OpenALDevice* m_device; | ||||||
|  |  | ||||||
|  | 	public: | ||||||
|  |  | ||||||
|  | 		/** | ||||||
|  | 		 * Creates a new OpenAL handle. | ||||||
|  | 		 * \param device The OpenAL device the handle belongs to. | ||||||
|  | 		 * \param format The AL format. | ||||||
|  | 		 * \param reader The reader this handle plays. | ||||||
|  | 		 * \param keep Whether to keep the handle alive when the reader ends. | ||||||
|  | 		 */ | ||||||
|  | 		AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, AUD_Reference<AUD_IReader> reader, bool keep); | ||||||
|  |  | ||||||
|  | 		virtual ~AUD_OpenALHandle() {} | ||||||
|  | 		virtual bool pause(); | ||||||
|  | 		virtual bool resume(); | ||||||
|  | 		virtual bool stop(); | ||||||
|  | 		virtual bool getKeep(); | ||||||
|  | 		virtual bool setKeep(bool keep); | ||||||
|  | 		virtual bool seek(float position); | ||||||
|  | 		virtual float getPosition(); | ||||||
|  | 		virtual AUD_Status getStatus(); | ||||||
|  | 		virtual float getVolume(); | ||||||
|  | 		virtual bool setVolume(float volume); | ||||||
|  | 		virtual float getPitch(); | ||||||
|  | 		virtual bool setPitch(float pitch); | ||||||
|  | 		virtual int getLoopCount(); | ||||||
|  | 		virtual bool setLoopCount(int count); | ||||||
|  | 		virtual bool setStopCallback(stopCallback callback = 0, void* data = 0); | ||||||
|  |  | ||||||
|  | 		virtual AUD_Vector3 getSourceLocation(); | ||||||
|  | 		virtual bool setSourceLocation(const AUD_Vector3& location); | ||||||
|  | 		virtual AUD_Vector3 getSourceVelocity(); | ||||||
|  | 		virtual bool setSourceVelocity(const AUD_Vector3& velocity); | ||||||
|  | 		virtual AUD_Quaternion getSourceOrientation(); | ||||||
|  | 		virtual bool setSourceOrientation(const AUD_Quaternion& orientation); | ||||||
|  | 		virtual bool isRelative(); | ||||||
|  | 		virtual bool setRelative(bool relative); | ||||||
|  | 		virtual float getVolumeMaximum(); | ||||||
|  | 		virtual bool setVolumeMaximum(float volume); | ||||||
|  | 		virtual float getVolumeMinimum(); | ||||||
|  | 		virtual bool setVolumeMinimum(float volume); | ||||||
|  | 		virtual float getDistanceMaximum(); | ||||||
|  | 		virtual bool setDistanceMaximum(float distance); | ||||||
|  | 		virtual float getDistanceReference(); | ||||||
|  | 		virtual bool setDistanceReference(float distance); | ||||||
|  | 		virtual float getAttenuation(); | ||||||
|  | 		virtual bool setAttenuation(float factor); | ||||||
|  | 		virtual float getConeAngleOuter(); | ||||||
|  | 		virtual bool setConeAngleOuter(float angle); | ||||||
|  | 		virtual float getConeAngleInner(); | ||||||
|  | 		virtual bool setConeAngleInner(float angle); | ||||||
|  | 		virtual float getConeVolumeOuter(); | ||||||
|  | 		virtual bool setConeVolumeOuter(float volume); | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	typedef std::list<AUD_Reference<AUD_OpenALHandle> >::iterator AUD_HandleIterator; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The OpenAL device handle. | 	 * The OpenAL device handle. | ||||||
| 	 */ | 	 */ | ||||||
| @@ -71,17 +177,17 @@ private: | |||||||
| 	/** | 	/** | ||||||
| 	 * The list of sounds that are currently playing. | 	 * The list of sounds that are currently playing. | ||||||
| 	 */ | 	 */ | ||||||
| 	std::list<AUD_OpenALHandle*>* m_playingSounds; | 	std::list<AUD_Reference<AUD_OpenALHandle> > m_playingSounds; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The list of sounds that are currently paused. | 	 * The list of sounds that are currently paused. | ||||||
| 	 */ | 	 */ | ||||||
| 	std::list<AUD_OpenALHandle*>* m_pausedSounds; | 	std::list<AUD_Reference<AUD_OpenALHandle> > m_pausedSounds; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The list of buffered factories. | 	 * The list of buffered factories. | ||||||
| 	 */ | 	 */ | ||||||
| 	std::list<AUD_OpenALBufferedFactory*>* m_bufferedFactories; | 	//std::list<AUD_OpenALBufferedFactory*>* m_bufferedFactories; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The mutex for locking. | 	 * The mutex for locking. | ||||||
| @@ -104,16 +210,20 @@ private: | |||||||
| 	int m_buffersize; | 	int m_buffersize; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Starts the streaming thread. | 	 * Device buffer. | ||||||
| 	 */ | 	 */ | ||||||
| 	void start(bool join = true); | 	AUD_Buffer m_buffer; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Checks if a handle is valid. | 	 * Orientation. | ||||||
| 	 * \param handle The handle to check. |  | ||||||
| 	 * \return Whether the handle is valid. |  | ||||||
| 	 */ | 	 */ | ||||||
| 	bool isValid(AUD_Handle* handle); | 	AUD_Quaternion m_orientation; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Starts the streaming thread. | ||||||
|  | 	 * \param Whether the previous thread should be joined. | ||||||
|  | 	 */ | ||||||
|  | 	void start(bool join = true); | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Gets the format according to the specs. | 	 * Gets the format according to the specs. | ||||||
| @@ -147,27 +257,13 @@ public: | |||||||
| 	virtual ~AUD_OpenALDevice(); | 	virtual ~AUD_OpenALDevice(); | ||||||
|  |  | ||||||
| 	virtual AUD_DeviceSpecs getSpecs() const; | 	virtual AUD_DeviceSpecs getSpecs() const; | ||||||
| 	virtual AUD_Handle* play(AUD_IReader* reader, bool keep = false); | 	virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false); | ||||||
| 	virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false); | 	virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IFactory> factory, bool keep = false); | ||||||
| 	virtual bool pause(AUD_Handle* handle); | 	virtual void stopAll(); | ||||||
| 	virtual bool resume(AUD_Handle* handle); |  | ||||||
| 	virtual bool stop(AUD_Handle* handle); |  | ||||||
| 	virtual bool getKeep(AUD_Handle* handle); |  | ||||||
| 	virtual bool setKeep(AUD_Handle* handle, bool keep); |  | ||||||
| 	virtual bool seek(AUD_Handle* handle, float position); |  | ||||||
| 	virtual float getPosition(AUD_Handle* handle); |  | ||||||
| 	virtual AUD_Status getStatus(AUD_Handle* handle); |  | ||||||
| 	virtual void lock(); | 	virtual void lock(); | ||||||
| 	virtual void unlock(); | 	virtual void unlock(); | ||||||
| 	virtual float getVolume() const; | 	virtual float getVolume() const; | ||||||
| 	virtual void setVolume(float volume); | 	virtual void setVolume(float volume); | ||||||
| 	virtual float getVolume(AUD_Handle* handle); |  | ||||||
| 	virtual bool setVolume(AUD_Handle* handle, float volume); |  | ||||||
| 	virtual float getPitch(AUD_Handle* handle); |  | ||||||
| 	virtual bool setPitch(AUD_Handle* handle, float pitch); |  | ||||||
| 	virtual int getLoopCount(AUD_Handle* handle); |  | ||||||
| 	virtual bool setLoopCount(AUD_Handle* handle, int count); |  | ||||||
| 	virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = NULL, void* data = NULL); |  | ||||||
|  |  | ||||||
| 	virtual AUD_Vector3 getListenerLocation() const; | 	virtual AUD_Vector3 getListenerLocation() const; | ||||||
| 	virtual void setListenerLocation(const AUD_Vector3& location); | 	virtual void setListenerLocation(const AUD_Vector3& location); | ||||||
| @@ -181,30 +277,6 @@ public: | |||||||
| 	virtual void setDopplerFactor(float factor); | 	virtual void setDopplerFactor(float factor); | ||||||
| 	virtual AUD_DistanceModel getDistanceModel() const; | 	virtual AUD_DistanceModel getDistanceModel() const; | ||||||
| 	virtual void setDistanceModel(AUD_DistanceModel model); | 	virtual void setDistanceModel(AUD_DistanceModel model); | ||||||
| 	virtual AUD_Vector3 getSourceLocation(AUD_Handle* handle); |  | ||||||
| 	virtual bool setSourceLocation(AUD_Handle* handle, const AUD_Vector3& location); |  | ||||||
| 	virtual AUD_Vector3 getSourceVelocity(AUD_Handle* handle); |  | ||||||
| 	virtual bool setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity); |  | ||||||
| 	virtual AUD_Quaternion getSourceOrientation(AUD_Handle* handle); |  | ||||||
| 	virtual bool setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation); |  | ||||||
| 	virtual bool isRelative(AUD_Handle* handle); |  | ||||||
| 	virtual bool setRelative(AUD_Handle* handle, bool relative); |  | ||||||
| 	virtual float getVolumeMaximum(AUD_Handle* handle); |  | ||||||
| 	virtual bool setVolumeMaximum(AUD_Handle* handle, float volume); |  | ||||||
| 	virtual float getVolumeMinimum(AUD_Handle* handle); |  | ||||||
| 	virtual bool setVolumeMinimum(AUD_Handle* handle, float volume); |  | ||||||
| 	virtual float getDistanceMaximum(AUD_Handle* handle); |  | ||||||
| 	virtual bool setDistanceMaximum(AUD_Handle* handle, float distance); |  | ||||||
| 	virtual float getDistanceReference(AUD_Handle* handle); |  | ||||||
| 	virtual bool setDistanceReference(AUD_Handle* handle, float distance); |  | ||||||
| 	virtual float getAttenuation(AUD_Handle* handle); |  | ||||||
| 	virtual bool setAttenuation(AUD_Handle* handle, float factor); |  | ||||||
| 	virtual float getConeAngleOuter(AUD_Handle* handle); |  | ||||||
| 	virtual bool setConeAngleOuter(AUD_Handle* handle, float angle); |  | ||||||
| 	virtual float getConeAngleInner(AUD_Handle* handle); |  | ||||||
| 	virtual bool setConeAngleInner(AUD_Handle* handle, float angle); |  | ||||||
| 	virtual float getConeVolumeOuter(AUD_Handle* handle); |  | ||||||
| 	virtual bool setConeVolumeOuter(AUD_Handle* handle, float volume); |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_OPENALDEVICE | #endif //AUD_OPENALDEVICE | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -36,35 +36,38 @@ | |||||||
|  |  | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| #include "AUD_IDevice.h" |  | ||||||
| #else | #else | ||||||
| typedef void AUD_IFactory; | typedef void AUD_IFactory; | ||||||
| typedef void AUD_IDevice; | typedef void AUD_IDevice; | ||||||
| typedef void AUD_Handle; | typedef void AUD_IHandle; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | typedef void AUD_Reference_AUD_IFactory; | ||||||
|  | typedef void AUD_Reference_AUD_IDevice; | ||||||
|  | typedef void AUD_Reference_AUD_IHandle; | ||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
| 	PyObject_HEAD | 	PyObject_HEAD | ||||||
| 	PyObject* child_list; | 	PyObject* child_list; | ||||||
| 	AUD_IFactory* factory; | 	AUD_Reference_AUD_IFactory* factory; | ||||||
| } Factory; | } Factory; | ||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
| 	PyObject_HEAD | 	PyObject_HEAD | ||||||
| 	AUD_Handle* handle; | 	AUD_Reference_AUD_IHandle* handle; | ||||||
| 	PyObject* device; |  | ||||||
| } Handle; | } Handle; | ||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
| 	PyObject_HEAD | 	PyObject_HEAD | ||||||
| 	AUD_IDevice* device; | 	AUD_Reference_AUD_IDevice* device; | ||||||
| } Device; | } Device; | ||||||
|  |  | ||||||
| PyMODINIT_FUNC | PyMODINIT_FUNC | ||||||
| PyInit_aud(void); | PyInit_aud(void); | ||||||
|  |  | ||||||
| extern PyObject * | extern PyObject* Device_empty(); | ||||||
| Device_empty(); | extern PyObject* Factory_empty(); | ||||||
|  | extern Factory* checkFactory(PyObject* factory); | ||||||
|  |  | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
|   | |||||||
| @@ -32,18 +32,13 @@ | |||||||
| #include "AUD_SRCResampleFactory.h" | #include "AUD_SRCResampleFactory.h" | ||||||
| #include "AUD_SRCResampleReader.h" | #include "AUD_SRCResampleReader.h" | ||||||
|  |  | ||||||
| AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IFactory* factory, | AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_Reference<AUD_IFactory> factory, | ||||||
| 											   AUD_DeviceSpecs specs) : | 											   AUD_DeviceSpecs specs) : | ||||||
| 		AUD_ResampleFactory(factory, specs) | 		AUD_MixerFactory(factory, specs) | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_SRCResampleFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_SRCResampleFactory::createReader() | ||||||
| { | { | ||||||
| 	AUD_IReader* reader = getReader(); | 	return new AUD_SRCResampleReader(getReader(), m_specs.specs); | ||||||
|  |  | ||||||
| 	if(reader->getSpecs().rate != m_specs.rate) |  | ||||||
| 		reader = new AUD_SRCResampleReader(reader, m_specs.specs); |  | ||||||
|  |  | ||||||
| 	return reader; |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -32,13 +32,13 @@ | |||||||
| #ifndef AUD_SRCRESAMPLEFACTORY | #ifndef AUD_SRCRESAMPLEFACTORY | ||||||
| #define AUD_SRCRESAMPLEFACTORY | #define AUD_SRCRESAMPLEFACTORY | ||||||
|  |  | ||||||
| #include "AUD_ResampleFactory.h" | #include "AUD_MixerFactory.h" | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This factory creates a resampling reader that uses libsamplerate for |  * This factory creates a resampling reader that uses libsamplerate for | ||||||
|  * resampling. |  * resampling. | ||||||
|  */ |  */ | ||||||
| class AUD_SRCResampleFactory : public AUD_ResampleFactory | class AUD_SRCResampleFactory : public AUD_MixerFactory | ||||||
| { | { | ||||||
| private: | private: | ||||||
| 	// hide copy constructor and operator= | 	// hide copy constructor and operator= | ||||||
| @@ -46,9 +46,14 @@ private: | |||||||
| 	AUD_SRCResampleFactory& operator=(const AUD_SRCResampleFactory&); | 	AUD_SRCResampleFactory& operator=(const AUD_SRCResampleFactory&); | ||||||
|  |  | ||||||
| public: | public: | ||||||
| 	AUD_SRCResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); | 	/** | ||||||
|  | 	 * Creates a new factory. | ||||||
|  | 	 * \param factory The input factory. | ||||||
|  | 	 * \param specs The target specifications. | ||||||
|  | 	 */ | ||||||
|  | 	AUD_SRCResampleFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs); | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_SRCRESAMPLEFACTORY | #endif //AUD_SRCRESAMPLEFACTORY | ||||||
|   | |||||||
| @@ -43,20 +43,16 @@ static long src_callback(void *cb_data, float **data) | |||||||
| static const char* state_error = "AUD_SRCResampleReader: SRC State couldn't be " | static const char* state_error = "AUD_SRCResampleReader: SRC State couldn't be " | ||||||
| 								 "created."; | 								 "created."; | ||||||
|  |  | ||||||
| AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* reader, | AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_Reference<AUD_IReader> reader, | ||||||
| 											 AUD_Specs specs) : | 											 AUD_Specs specs) : | ||||||
| 		AUD_EffectReader(reader), | 		AUD_ResampleReader(reader, specs.rate), | ||||||
| 		m_sspecs(reader->getSpecs()), | 		m_channels(reader->getSpecs().channels), | ||||||
| 		m_factor(double(specs.rate) / double(m_sspecs.rate)), |  | ||||||
| 		m_tspecs(specs), |  | ||||||
| 		m_position(0) | 		m_position(0) | ||||||
| { | { | ||||||
| 	m_tspecs.channels = m_sspecs.channels; |  | ||||||
|  |  | ||||||
| 	int error; | 	int error; | ||||||
| 	m_src = src_callback_new(src_callback, | 	m_src = src_callback_new(src_callback, | ||||||
| 							 SRC_SINC_MEDIUM_QUALITY, | 							 SRC_SINC_MEDIUM_QUALITY, | ||||||
| 							 m_sspecs.channels, | 							 m_channels, | ||||||
| 							 &error, | 							 &error, | ||||||
| 							 this); | 							 this); | ||||||
|  |  | ||||||
| @@ -74,25 +70,32 @@ AUD_SRCResampleReader::~AUD_SRCResampleReader() | |||||||
|  |  | ||||||
| long AUD_SRCResampleReader::doCallback(float** data) | long AUD_SRCResampleReader::doCallback(float** data) | ||||||
| { | { | ||||||
| 	int length = m_buffer.getSize() / AUD_SAMPLE_SIZE(m_tspecs); | 	AUD_Specs specs; | ||||||
| 	sample_t* buffer; | 	specs.channels = m_channels; | ||||||
|  | 	specs.rate = m_rate; | ||||||
|  |  | ||||||
| 	m_reader->read(length, buffer); | 	int length = m_buffer.getSize() / AUD_SAMPLE_SIZE(specs); | ||||||
|  |  | ||||||
|  | 	*data = m_buffer.getBuffer(); | ||||||
|  | 	m_reader->read(length, m_eos, *data); | ||||||
|  |  | ||||||
| 	*data = buffer; |  | ||||||
| 	return length; | 	return length; | ||||||
| } | } | ||||||
|  |  | ||||||
| void AUD_SRCResampleReader::seek(int position) | void AUD_SRCResampleReader::seek(int position) | ||||||
| { | { | ||||||
| 	m_reader->seek(position / m_factor); | 	AUD_Specs specs = m_reader->getSpecs(); | ||||||
|  | 	double factor = double(m_rate) / double(specs.rate); | ||||||
|  | 	m_reader->seek(position / factor); | ||||||
| 	src_reset(m_src); | 	src_reset(m_src); | ||||||
| 	m_position = position; | 	m_position = position; | ||||||
| } | } | ||||||
|  |  | ||||||
| int AUD_SRCResampleReader::getLength() const | int AUD_SRCResampleReader::getLength() const | ||||||
| { | { | ||||||
| 	return m_reader->getLength() * m_factor; | 	AUD_Specs specs = m_reader->getSpecs(); | ||||||
|  | 	double factor = double(m_rate) / double(specs.rate); | ||||||
|  | 	return m_reader->getLength() * factor; | ||||||
| } | } | ||||||
|  |  | ||||||
| int AUD_SRCResampleReader::getPosition() const | int AUD_SRCResampleReader::getPosition() const | ||||||
| @@ -102,19 +105,48 @@ int AUD_SRCResampleReader::getPosition() const | |||||||
|  |  | ||||||
| AUD_Specs AUD_SRCResampleReader::getSpecs() const | AUD_Specs AUD_SRCResampleReader::getSpecs() const | ||||||
| { | { | ||||||
| 	return m_tspecs; | 	AUD_Specs specs = m_reader->getSpecs(); | ||||||
|  | 	specs.rate = m_rate; | ||||||
|  | 	return specs; | ||||||
| } | } | ||||||
|  |  | ||||||
| void AUD_SRCResampleReader::read(int & length, sample_t* & buffer) | void AUD_SRCResampleReader::read(int& length, bool& eos, sample_t* buffer) | ||||||
| { | { | ||||||
| 	int size = length * AUD_SAMPLE_SIZE(m_tspecs); | 	AUD_Specs specs = m_reader->getSpecs(); | ||||||
|  |  | ||||||
| 	if(m_buffer.getSize() < size) | 	double factor = double(m_rate) / double(specs.rate); | ||||||
| 		m_buffer.resize(size); |  | ||||||
|  |  | ||||||
| 	buffer = m_buffer.getBuffer(); | 	specs.rate = m_rate; | ||||||
|  |  | ||||||
| 	length = src_callback_read(m_src, m_factor, length, buffer); | 	int size = length; | ||||||
|  |  | ||||||
|  | 	m_buffer.assureSize(length * AUD_SAMPLE_SIZE(specs)); | ||||||
|  |  | ||||||
|  | 	if(specs.channels != m_channels) | ||||||
|  | 	{ | ||||||
|  | 		src_delete(m_src); | ||||||
|  |  | ||||||
|  | 		m_channels = specs.channels; | ||||||
|  |  | ||||||
|  | 		int error; | ||||||
|  | 		m_src = src_callback_new(src_callback, | ||||||
|  | 								 SRC_SINC_MEDIUM_QUALITY, | ||||||
|  | 								 m_channels, | ||||||
|  | 								 &error, | ||||||
|  | 								 this); | ||||||
|  |  | ||||||
|  | 		if(!m_src) | ||||||
|  | 		{ | ||||||
|  | 			// XXX printf("%s\n", src_strerror(error)); | ||||||
|  | 			AUD_THROW(AUD_ERROR_SRC, state_error); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	m_eos = false; | ||||||
|  |  | ||||||
|  | 	length = src_callback_read(m_src, factor, length, buffer); | ||||||
|  |  | ||||||
| 	m_position += length; | 	m_position += length; | ||||||
|  |  | ||||||
|  | 	eos = m_eos && (length < size); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ | |||||||
| #ifndef AUD_SRCRESAMPLEREADER | #ifndef AUD_SRCRESAMPLEREADER | ||||||
| #define AUD_SRCRESAMPLEREADER | #define AUD_SRCRESAMPLEREADER | ||||||
|  |  | ||||||
| #include "AUD_EffectReader.h" | #include "AUD_ResampleReader.h" | ||||||
| #include "AUD_Buffer.h" | #include "AUD_Buffer.h" | ||||||
|  |  | ||||||
| #include <samplerate.h> | #include <samplerate.h> | ||||||
| @@ -40,28 +40,18 @@ | |||||||
| /** | /** | ||||||
|  * This resampling reader uses libsamplerate for resampling. |  * This resampling reader uses libsamplerate for resampling. | ||||||
|  */ |  */ | ||||||
| class AUD_SRCResampleReader : public AUD_EffectReader | class AUD_SRCResampleReader : public AUD_ResampleReader | ||||||
| { | { | ||||||
| private: | private: | ||||||
| 	/** |  | ||||||
| 	 * The sample specification of the source. |  | ||||||
| 	 */ |  | ||||||
| 	const AUD_Specs m_sspecs; |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * The resampling factor. |  | ||||||
| 	 */ |  | ||||||
| 	const double m_factor; |  | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The sound output buffer. | 	 * The sound output buffer. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_Buffer m_buffer; | 	AUD_Buffer m_buffer; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The target specification. | 	 * The reader channels. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_Specs m_tspecs; | 	AUD_Channels m_channels; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The src state structure. | 	 * The src state structure. | ||||||
| @@ -73,6 +63,11 @@ private: | |||||||
| 	 */ | 	 */ | ||||||
| 	int m_position; | 	int m_position; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Whether reader reached end of stream. | ||||||
|  | 	 */ | ||||||
|  | 	bool m_eos; | ||||||
|  |  | ||||||
| 	// hide copy constructor and operator= | 	// hide copy constructor and operator= | ||||||
| 	AUD_SRCResampleReader(const AUD_SRCResampleReader&); | 	AUD_SRCResampleReader(const AUD_SRCResampleReader&); | ||||||
| 	AUD_SRCResampleReader& operator=(const AUD_SRCResampleReader&); | 	AUD_SRCResampleReader& operator=(const AUD_SRCResampleReader&); | ||||||
| @@ -85,7 +80,7 @@ public: | |||||||
| 	 * \exception AUD_Exception Thrown if the source specification cannot be | 	 * \exception AUD_Exception Thrown if the source specification cannot be | ||||||
| 	 *            resampled to the target specification. | 	 *            resampled to the target specification. | ||||||
| 	 */ | 	 */ | ||||||
| 	AUD_SRCResampleReader(AUD_IReader* reader, AUD_Specs specs); | 	AUD_SRCResampleReader(AUD_Reference<AUD_IReader> reader, AUD_Specs specs); | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Destroys the reader. | 	 * Destroys the reader. | ||||||
| @@ -104,7 +99,7 @@ public: | |||||||
| 	virtual int getLength() const; | 	virtual int getLength() const; | ||||||
| 	virtual int getPosition() const; | 	virtual int getPosition() const; | ||||||
| 	virtual AUD_Specs getSpecs() const; | 	virtual AUD_Specs getSpecs() const; | ||||||
| 	virtual void read(int & length, sample_t* & buffer); | 	virtual void read(int& length, bool& eos, sample_t* buffer); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_SRCRESAMPLEREADER | #endif //AUD_SRCRESAMPLEREADER | ||||||
|   | |||||||
| @@ -36,7 +36,6 @@ | |||||||
|  |  | ||||||
| #include "AUD_FFMPEGFactory.h" | #include "AUD_FFMPEGFactory.h" | ||||||
| #include "AUD_FFMPEGReader.h" | #include "AUD_FFMPEGReader.h" | ||||||
| #include "AUD_Buffer.h" |  | ||||||
|  |  | ||||||
| AUD_FFMPEGFactory::AUD_FFMPEGFactory(std::string filename) : | AUD_FFMPEGFactory::AUD_FFMPEGFactory(std::string filename) : | ||||||
| 		m_filename(filename) | 		m_filename(filename) | ||||||
| @@ -46,13 +45,13 @@ AUD_FFMPEGFactory::AUD_FFMPEGFactory(std::string filename) : | |||||||
| AUD_FFMPEGFactory::AUD_FFMPEGFactory(const data_t* buffer, int size) : | AUD_FFMPEGFactory::AUD_FFMPEGFactory(const data_t* buffer, int size) : | ||||||
| 		m_buffer(new AUD_Buffer(size)) | 		m_buffer(new AUD_Buffer(size)) | ||||||
| { | { | ||||||
| 	memcpy(m_buffer.get()->getBuffer(), buffer, size); | 	memcpy(m_buffer->getBuffer(), buffer, size); | ||||||
| } | } | ||||||
|  |  | ||||||
| AUD_IReader* AUD_FFMPEGFactory::createReader() const | AUD_Reference<AUD_IReader> AUD_FFMPEGFactory::createReader() | ||||||
| { | { | ||||||
| 	if(m_buffer.get()) | 	if(m_buffer.isNull()) | ||||||
| 		return new AUD_FFMPEGReader(m_buffer); |  | ||||||
| 	else |  | ||||||
| 		return new AUD_FFMPEGReader(m_filename); | 		return new AUD_FFMPEGReader(m_filename); | ||||||
|  | 	else | ||||||
|  | 		return new AUD_FFMPEGReader(m_buffer); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -34,7 +34,7 @@ | |||||||
|  |  | ||||||
| #include "AUD_IFactory.h" | #include "AUD_IFactory.h" | ||||||
| #include "AUD_Reference.h" | #include "AUD_Reference.h" | ||||||
| class AUD_Buffer; | #include "AUD_Buffer.h" | ||||||
|  |  | ||||||
| #include <string> | #include <string> | ||||||
|  |  | ||||||
| @@ -74,7 +74,7 @@ public: | |||||||
| 	 */ | 	 */ | ||||||
| 	AUD_FFMPEGFactory(const data_t* buffer, int size); | 	AUD_FFMPEGFactory(const data_t* buffer, int size); | ||||||
|  |  | ||||||
| 	virtual AUD_IReader* createReader() const; | 	virtual AUD_Reference<AUD_IReader> createReader(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_FFMPEGFACTORY | #endif //AUD_FFMPEGFACTORY | ||||||
|   | |||||||
| @@ -39,6 +39,7 @@ | |||||||
| extern "C" { | extern "C" { | ||||||
| #include <libavcodec/avcodec.h> | #include <libavcodec/avcodec.h> | ||||||
| #include <libavformat/avformat.h> | #include <libavformat/avformat.h> | ||||||
|  | #include <libavformat/avio.h> | ||||||
| #include "ffmpeg_compat.h" | #include "ffmpeg_compat.h" | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -176,11 +177,12 @@ static const char* fileopen_error = "AUD_FFMPEGReader: File couldn't be " | |||||||
|  |  | ||||||
| AUD_FFMPEGReader::AUD_FFMPEGReader(std::string filename) : | AUD_FFMPEGReader::AUD_FFMPEGReader(std::string filename) : | ||||||
| 	m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1), | 	m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1), | ||||||
| 	m_byteiocontext(NULL), | 	m_formatCtx(NULL), | ||||||
|  | 	m_aviocontext(NULL), | ||||||
| 	m_membuf(NULL) | 	m_membuf(NULL) | ||||||
| { | { | ||||||
| 	// open file | 	// open file | ||||||
| 	if(av_open_input_file(&m_formatCtx, filename.c_str(), NULL, 0, NULL)!=0) | 	if(avformat_open_input(&m_formatCtx, filename.c_str(), NULL, NULL)!=0) | ||||||
| 		AUD_THROW(AUD_ERROR_FILE, fileopen_error); | 		AUD_THROW(AUD_ERROR_FILE, fileopen_error); | ||||||
|  |  | ||||||
| 	try | 	try | ||||||
| @@ -204,25 +206,20 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) : | |||||||
| { | { | ||||||
| 	m_membuf = reinterpret_cast<data_t*>(av_malloc(FF_MIN_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE)); | 	m_membuf = reinterpret_cast<data_t*>(av_malloc(FF_MIN_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE)); | ||||||
|  |  | ||||||
| 	m_byteiocontext = av_alloc_put_byte(m_membuf, FF_MIN_BUFFER_SIZE, 0, this, | 	m_aviocontext = avio_alloc_context(m_membuf, FF_MIN_BUFFER_SIZE, 0, this, | ||||||
| 									   read_packet, NULL, seek_packet); | 									   read_packet, NULL, seek_packet); | ||||||
|  |  | ||||||
| 	if(!m_byteiocontext) | 	if(!m_aviocontext) | ||||||
| 	{ | 	{ | ||||||
| 		av_free(m_byteiocontext); | 		av_free(m_aviocontext); | ||||||
| 		AUD_THROW(AUD_ERROR_FILE, fileopen_error); | 		AUD_THROW(AUD_ERROR_FILE, fileopen_error); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	AVProbeData probe_data; | 	m_formatCtx = avformat_alloc_context(); | ||||||
| 	probe_data.filename = ""; | 	m_formatCtx->pb = m_aviocontext; | ||||||
| 	probe_data.buf = reinterpret_cast<data_t*>(buffer.get()->getBuffer()); | 	if(avformat_open_input(&m_formatCtx, "", NULL, NULL)!=0) | ||||||
| 	probe_data.buf_size = buffer.get()->getSize(); |  | ||||||
| 	AVInputFormat* fmt = av_probe_input_format(&probe_data, 1); |  | ||||||
|  |  | ||||||
| 	// open stream |  | ||||||
| 	if(av_open_input_stream(&m_formatCtx, m_byteiocontext, "", fmt, NULL)!=0) |  | ||||||
| 	{ | 	{ | ||||||
| 		av_free(m_byteiocontext); | 		av_free(m_aviocontext); | ||||||
| 		AUD_THROW(AUD_ERROR_FILE, streamopen_error); | 		AUD_THROW(AUD_ERROR_FILE, streamopen_error); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -233,7 +230,7 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) : | |||||||
| 	catch(AUD_Exception&) | 	catch(AUD_Exception&) | ||||||
| 	{ | 	{ | ||||||
| 		av_close_input_stream(m_formatCtx); | 		av_close_input_stream(m_formatCtx); | ||||||
| 		av_free(m_byteiocontext); | 		av_free(m_aviocontext); | ||||||
| 		throw; | 		throw; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -242,10 +239,10 @@ AUD_FFMPEGReader::~AUD_FFMPEGReader() | |||||||
| { | { | ||||||
| 	avcodec_close(m_codecCtx); | 	avcodec_close(m_codecCtx); | ||||||
|  |  | ||||||
| 	if(m_byteiocontext) | 	if(m_aviocontext) | ||||||
| 	{ | 	{ | ||||||
| 		av_close_input_stream(m_formatCtx); | 		av_close_input_stream(m_formatCtx); | ||||||
| 		av_free(m_byteiocontext); | 		av_free(m_aviocontext); | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 		av_close_input_file(m_formatCtx); | 		av_close_input_file(m_formatCtx); | ||||||
| @@ -255,12 +252,12 @@ int AUD_FFMPEGReader::read_packet(void* opaque, uint8_t* buf, int buf_size) | |||||||
| { | { | ||||||
| 	AUD_FFMPEGReader* reader = reinterpret_cast<AUD_FFMPEGReader*>(opaque); | 	AUD_FFMPEGReader* reader = reinterpret_cast<AUD_FFMPEGReader*>(opaque); | ||||||
|  |  | ||||||
| 	int size = AUD_MIN(buf_size, reader->m_membuffer.get()->getSize() - reader->m_membufferpos); | 	int size = AUD_MIN(buf_size, reader->m_membuffer->getSize() - reader->m_membufferpos); | ||||||
|  |  | ||||||
| 	if(size < 0) | 	if(size < 0) | ||||||
| 		return -1; | 		return -1; | ||||||
|  |  | ||||||
| 	memcpy(buf, ((data_t*)reader->m_membuffer.get()->getBuffer()) + reader->m_membufferpos, size); | 	memcpy(buf, ((data_t*)reader->m_membuffer->getBuffer()) + reader->m_membufferpos, size); | ||||||
| 	reader->m_membufferpos += size; | 	reader->m_membufferpos += size; | ||||||
|  |  | ||||||
| 	return size; | 	return size; | ||||||
| @@ -276,10 +273,10 @@ int64_t AUD_FFMPEGReader::seek_packet(void* opaque, int64_t offset, int whence) | |||||||
| 		reader->m_membufferpos = 0; | 		reader->m_membufferpos = 0; | ||||||
| 		break; | 		break; | ||||||
| 	case SEEK_END: | 	case SEEK_END: | ||||||
| 		reader->m_membufferpos = reader->m_membuffer.get()->getSize(); | 		reader->m_membufferpos = reader->m_membuffer->getSize(); | ||||||
| 		break; | 		break; | ||||||
| 	case AVSEEK_SIZE: | 	case AVSEEK_SIZE: | ||||||
| 		return reader->m_membuffer.get()->getSize(); | 		return reader->m_membuffer->getSize(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return (reader->m_membufferpos += offset); | 	return (reader->m_membufferpos += offset); | ||||||
| @@ -341,14 +338,15 @@ void AUD_FFMPEGReader::seek(int position) | |||||||
| 						{ | 						{ | ||||||
| 							// read until we're at the right position | 							// read until we're at the right position | ||||||
| 							int length = AUD_DEFAULT_BUFFER_SIZE; | 							int length = AUD_DEFAULT_BUFFER_SIZE; | ||||||
| 							sample_t* buffer; | 							AUD_Buffer buffer(length * AUD_SAMPLE_SIZE(m_specs)); | ||||||
|  | 							bool eos; | ||||||
| 							for(int len = position - m_position; | 							for(int len = position - m_position; | ||||||
| 								length == AUD_DEFAULT_BUFFER_SIZE; | 								length == AUD_DEFAULT_BUFFER_SIZE; | ||||||
| 								len -= AUD_DEFAULT_BUFFER_SIZE) | 								len -= AUD_DEFAULT_BUFFER_SIZE) | ||||||
| 							{ | 							{ | ||||||
| 								if(len < AUD_DEFAULT_BUFFER_SIZE) | 								if(len < AUD_DEFAULT_BUFFER_SIZE) | ||||||
| 									length = len; | 									length = len; | ||||||
| 								read(length, buffer); | 								read(length, eos, buffer.getBuffer()); | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| @@ -381,7 +379,7 @@ AUD_Specs AUD_FFMPEGReader::getSpecs() const | |||||||
| 	return m_specs.specs; | 	return m_specs.specs; | ||||||
| } | } | ||||||
|  |  | ||||||
| void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) | void AUD_FFMPEGReader::read(int& length, bool& eos, sample_t* buffer) | ||||||
| { | { | ||||||
| 	// read packages and decode them | 	// read packages and decode them | ||||||
| 	AVPacket packet; | 	AVPacket packet; | ||||||
| @@ -390,11 +388,7 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) | |||||||
| 	int left = length; | 	int left = length; | ||||||
| 	int sample_size = AUD_DEVICE_SAMPLE_SIZE(m_specs); | 	int sample_size = AUD_DEVICE_SAMPLE_SIZE(m_specs); | ||||||
|  |  | ||||||
| 	// resize output buffer if necessary | 	sample_t* buf = buffer; | ||||||
| 	if(m_buffer.getSize() < length * AUD_SAMPLE_SIZE(m_specs)) |  | ||||||
| 		m_buffer.resize(length * AUD_SAMPLE_SIZE(m_specs)); |  | ||||||
|  |  | ||||||
| 	buffer = m_buffer.getBuffer(); |  | ||||||
| 	pkgbuf_pos = m_pkgbuf_left; | 	pkgbuf_pos = m_pkgbuf_left; | ||||||
| 	m_pkgbuf_left = 0; | 	m_pkgbuf_left = 0; | ||||||
|  |  | ||||||
| @@ -402,9 +396,9 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) | |||||||
| 	if(pkgbuf_pos > 0) | 	if(pkgbuf_pos > 0) | ||||||
| 	{ | 	{ | ||||||
| 		data_size = AUD_MIN(pkgbuf_pos, left * sample_size); | 		data_size = AUD_MIN(pkgbuf_pos, left * sample_size); | ||||||
| 		m_convert((data_t*) buffer, (data_t*) m_pkgbuf.getBuffer(), | 		m_convert((data_t*) buf, (data_t*) m_pkgbuf.getBuffer(), | ||||||
| 				  data_size / AUD_FORMAT_SIZE(m_specs.format)); | 				  data_size / AUD_FORMAT_SIZE(m_specs.format)); | ||||||
| 		buffer += data_size / AUD_FORMAT_SIZE(m_specs.format); | 		buf += data_size / AUD_FORMAT_SIZE(m_specs.format); | ||||||
| 		left -= data_size/sample_size; | 		left -= data_size/sample_size; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -419,9 +413,9 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) | |||||||
|  |  | ||||||
| 			// copy to output buffer | 			// copy to output buffer | ||||||
| 			data_size = AUD_MIN(pkgbuf_pos, left * sample_size); | 			data_size = AUD_MIN(pkgbuf_pos, left * sample_size); | ||||||
| 			m_convert((data_t*) buffer, (data_t*) m_pkgbuf.getBuffer(), | 			m_convert((data_t*) buf, (data_t*) m_pkgbuf.getBuffer(), | ||||||
| 					  data_size / AUD_FORMAT_SIZE(m_specs.format)); | 					  data_size / AUD_FORMAT_SIZE(m_specs.format)); | ||||||
| 			buffer += data_size / AUD_FORMAT_SIZE(m_specs.format); | 			buf += data_size / AUD_FORMAT_SIZE(m_specs.format); | ||||||
| 			left -= data_size/sample_size; | 			left -= data_size/sample_size; | ||||||
| 		} | 		} | ||||||
| 		av_free_packet(&packet); | 		av_free_packet(&packet); | ||||||
| @@ -435,9 +429,8 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) | |||||||
| 				pkgbuf_pos-data_size); | 				pkgbuf_pos-data_size); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	buffer = m_buffer.getBuffer(); | 	if((eos = (left > 0))) | ||||||
|  |  | ||||||
| 	if(left > 0) |  | ||||||
| 		length -= left; | 		length -= left; | ||||||
|  |  | ||||||
| 	m_position += length; | 	m_position += length; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -49,8 +49,6 @@ extern "C" { | |||||||
|  * \warning Seeking may not be accurate! Moreover the position is updated after |  * \warning Seeking may not be accurate! Moreover the position is updated after | ||||||
|  *          a buffer reading call. So calling getPosition right after seek |  *          a buffer reading call. So calling getPosition right after seek | ||||||
|  *          normally results in a wrong value. |  *          normally results in a wrong value. | ||||||
|  * \warning Playback of an ogg with some outdated ffmpeg versions results in a |  | ||||||
|  *          segfault on windows. |  | ||||||
|  */ |  */ | ||||||
| class AUD_FFMPEGReader : public AUD_IReader | class AUD_FFMPEGReader : public AUD_IReader | ||||||
| { | { | ||||||
| @@ -60,11 +58,6 @@ private: | |||||||
| 	 */ | 	 */ | ||||||
| 	int m_position; | 	int m_position; | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * The playback buffer. |  | ||||||
| 	 */ |  | ||||||
| 	AUD_Buffer m_buffer; |  | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The specification of the audio data. | 	 * The specification of the audio data. | ||||||
| 	 */ | 	 */ | ||||||
| @@ -91,9 +84,9 @@ private: | |||||||
| 	AVCodecContext* m_codecCtx; | 	AVCodecContext* m_codecCtx; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The ByteIOContext to read the data from. | 	 * The AVIOContext to read the data from. | ||||||
| 	 */ | 	 */ | ||||||
| 	ByteIOContext* m_byteiocontext; | 	AVIOContext* m_aviocontext; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * The stream ID in the file. | 	 * The stream ID in the file. | ||||||
| @@ -167,7 +160,7 @@ public: | |||||||
| 	virtual int getLength() const; | 	virtual int getLength() const; | ||||||
| 	virtual int getPosition() const; | 	virtual int getPosition() const; | ||||||
| 	virtual AUD_Specs getSpecs() const; | 	virtual AUD_Specs getSpecs() const; | ||||||
| 	virtual void read(int & length, sample_t* & buffer); | 	virtual void read(int& length, bool& eos, sample_t* buffer); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_FFMPEGREADER | #endif //AUD_FFMPEGREADER | ||||||
|   | |||||||
							
								
								
									
										305
									
								
								intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										305
									
								
								intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,305 @@ | |||||||
|  | /* | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |  * ***** BEGIN GPL LICENSE BLOCK ***** | ||||||
|  |  * | ||||||
|  |  * Copyright 2009-2011 Jörg Hermann Müller | ||||||
|  |  * | ||||||
|  |  * This file is part of AudaSpace. | ||||||
|  |  * | ||||||
|  |  * Audaspace is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation; either version 2 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * AudaSpace is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with Audaspace; if not, write to the Free Software Foundation, | ||||||
|  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||||
|  |  * | ||||||
|  |  * ***** END GPL LICENSE BLOCK ***** | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** \file audaspace/ffmpeg/AUD_FFMPEGWriter.cpp | ||||||
|  |  *  \ingroup audffmpeg | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // needed for INT64_C | ||||||
|  | #ifndef __STDC_CONSTANT_MACROS | ||||||
|  | #define __STDC_CONSTANT_MACROS | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #include "AUD_FFMPEGWriter.h" | ||||||
|  |  | ||||||
|  | extern "C" { | ||||||
|  | #include <libavcodec/avcodec.h> | ||||||
|  | #include <libavformat/avformat.h> | ||||||
|  | #include <libavformat/avio.h> | ||||||
|  | #include "ffmpeg_compat.h" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static const char* context_error = "AUD_FFMPEGWriter: Couldn't allocate context."; | ||||||
|  | static const char* codec_error = "AUD_FFMPEGWriter: Invalid codec or codec not found."; | ||||||
|  | static const char* stream_error = "AUD_FFMPEGWriter: Couldn't allocate stream."; | ||||||
|  | static const char* format_error = "AUD_FFMPEGWriter: Unsupported sample format."; | ||||||
|  | static const char* file_error = "AUD_FFMPEGWriter: File couldn't be written."; | ||||||
|  | static const char* write_error = "AUD_FFMPEGWriter: Error writing packet."; | ||||||
|  |  | ||||||
|  | AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate) : | ||||||
|  | 	m_position(0), | ||||||
|  | 	m_specs(specs), | ||||||
|  | 	m_input_samples(0) | ||||||
|  | { | ||||||
|  | 	static const char* formats[] = { NULL, "ac3", "flac", "matroska", "mp2", "mp3", "ogg", "wav" }; | ||||||
|  |  | ||||||
|  | 	if(avformat_alloc_output_context2(&m_formatCtx, NULL, formats[format], filename.c_str())) | ||||||
|  | 		AUD_THROW(AUD_ERROR_FFMPEG, context_error); | ||||||
|  |  | ||||||
|  | 	m_outputFmt = m_formatCtx->oformat; | ||||||
|  |  | ||||||
|  | 	switch(codec) | ||||||
|  | 	{ | ||||||
|  | 	case AUD_CODEC_AAC: | ||||||
|  | 		m_outputFmt->audio_codec = CODEC_ID_AAC; | ||||||
|  | 		break; | ||||||
|  | 	case AUD_CODEC_AC3: | ||||||
|  | 		m_outputFmt->audio_codec = CODEC_ID_AC3; | ||||||
|  | 		break; | ||||||
|  | 	case AUD_CODEC_FLAC: | ||||||
|  | 		m_outputFmt->audio_codec = CODEC_ID_FLAC; | ||||||
|  | 		break; | ||||||
|  | 	case AUD_CODEC_MP2: | ||||||
|  | 		m_outputFmt->audio_codec = CODEC_ID_MP2; | ||||||
|  | 		break; | ||||||
|  | 	case AUD_CODEC_MP3: | ||||||
|  | 		m_outputFmt->audio_codec = CODEC_ID_MP3; | ||||||
|  | 		break; | ||||||
|  | 	case AUD_CODEC_PCM: | ||||||
|  | 		switch(specs.format) | ||||||
|  | 		{ | ||||||
|  | 		case AUD_FORMAT_U8: | ||||||
|  | 			m_outputFmt->audio_codec = CODEC_ID_PCM_U8; | ||||||
|  | 			break; | ||||||
|  | 		case AUD_FORMAT_S16: | ||||||
|  | 			m_outputFmt->audio_codec = CODEC_ID_PCM_S16LE; | ||||||
|  | 			break; | ||||||
|  | 		case AUD_FORMAT_S24: | ||||||
|  | 			m_outputFmt->audio_codec = CODEC_ID_PCM_S24LE; | ||||||
|  | 			break; | ||||||
|  | 		case AUD_FORMAT_S32: | ||||||
|  | 			m_outputFmt->audio_codec = CODEC_ID_PCM_S32LE; | ||||||
|  | 			break; | ||||||
|  | 		case AUD_FORMAT_FLOAT32: | ||||||
|  | 			m_outputFmt->audio_codec = CODEC_ID_PCM_F32LE; | ||||||
|  | 			break; | ||||||
|  | 		case AUD_FORMAT_FLOAT64: | ||||||
|  | 			m_outputFmt->audio_codec = CODEC_ID_PCM_F64LE; | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			m_outputFmt->audio_codec = CODEC_ID_NONE; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case AUD_CODEC_VORBIS: | ||||||
|  | 		m_outputFmt->audio_codec = CODEC_ID_VORBIS; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		m_outputFmt->audio_codec = CODEC_ID_NONE; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	try | ||||||
|  | 	{ | ||||||
|  | 		if(m_outputFmt->audio_codec == CODEC_ID_NONE) | ||||||
|  | 			AUD_THROW(AUD_ERROR_SPECS, codec_error); | ||||||
|  |  | ||||||
|  | 		m_stream = av_new_stream(m_formatCtx, 0); | ||||||
|  | 		if(!m_stream) | ||||||
|  | 			AUD_THROW(AUD_ERROR_FFMPEG, stream_error); | ||||||
|  |  | ||||||
|  | 		m_codecCtx = m_stream->codec; | ||||||
|  | 		m_codecCtx->codec_id = m_outputFmt->audio_codec; | ||||||
|  | 		m_codecCtx->codec_type = AVMEDIA_TYPE_AUDIO; | ||||||
|  | 		m_codecCtx->bit_rate = bitrate; | ||||||
|  | 		m_codecCtx->sample_rate = int(m_specs.rate); | ||||||
|  | 		m_codecCtx->channels = m_specs.channels; | ||||||
|  | 		m_codecCtx->time_base.num = 1; | ||||||
|  | 		m_codecCtx->time_base.den = m_codecCtx->sample_rate; | ||||||
|  |  | ||||||
|  | 		switch(m_specs.format) | ||||||
|  | 		{ | ||||||
|  | 		case AUD_FORMAT_U8: | ||||||
|  | 			m_convert = AUD_convert_float_u8; | ||||||
|  | 			m_codecCtx->sample_fmt = SAMPLE_FMT_U8; | ||||||
|  | 			break; | ||||||
|  | 		case AUD_FORMAT_S16: | ||||||
|  | 			m_convert = AUD_convert_float_s16; | ||||||
|  | 			m_codecCtx->sample_fmt = SAMPLE_FMT_S16; | ||||||
|  | 			break; | ||||||
|  | 		case AUD_FORMAT_S32: | ||||||
|  | 			m_convert = AUD_convert_float_s32; | ||||||
|  | 			m_codecCtx->sample_fmt = SAMPLE_FMT_S32; | ||||||
|  | 			break; | ||||||
|  | 		case AUD_FORMAT_FLOAT32: | ||||||
|  | 			m_convert = AUD_convert_copy<float>; | ||||||
|  | 			m_codecCtx->sample_fmt = SAMPLE_FMT_FLT; | ||||||
|  | 			break; | ||||||
|  | 		case AUD_FORMAT_FLOAT64: | ||||||
|  | 			m_convert = AUD_convert_float_double; | ||||||
|  | 			m_codecCtx->sample_fmt = SAMPLE_FMT_DBL; | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			AUD_THROW(AUD_ERROR_FFMPEG, format_error); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		try | ||||||
|  | 		{ | ||||||
|  | 			if(m_formatCtx->oformat->flags & AVFMT_GLOBALHEADER) | ||||||
|  | 				m_codecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER; | ||||||
|  |  | ||||||
|  | 			AVCodec* codec = avcodec_find_encoder(m_codecCtx->codec_id); | ||||||
|  | 			if(!codec) | ||||||
|  | 				AUD_THROW(AUD_ERROR_FFMPEG, codec_error); | ||||||
|  |  | ||||||
|  | 			if(avcodec_open(m_codecCtx, codec)) | ||||||
|  | 				AUD_THROW(AUD_ERROR_FFMPEG, codec_error); | ||||||
|  |  | ||||||
|  | 			m_output_buffer.resize(FF_MIN_BUFFER_SIZE); | ||||||
|  | 			int samplesize = AUD_MAX(AUD_SAMPLE_SIZE(m_specs), AUD_DEVICE_SAMPLE_SIZE(m_specs)); | ||||||
|  |  | ||||||
|  | 			if(m_codecCtx->frame_size <= 1) | ||||||
|  | 				m_input_size = 0; | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				m_input_buffer.resize(m_codecCtx->frame_size * samplesize); | ||||||
|  | 				m_input_size = m_codecCtx->frame_size; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				if(avio_open(&m_formatCtx->pb, filename.c_str(), AVIO_FLAG_WRITE)) | ||||||
|  | 					AUD_THROW(AUD_ERROR_FILE, file_error); | ||||||
|  |  | ||||||
|  | 				avformat_write_header(m_formatCtx, NULL); | ||||||
|  | 			} | ||||||
|  | 			catch(AUD_Exception&) | ||||||
|  | 			{ | ||||||
|  | 				avcodec_close(m_codecCtx); | ||||||
|  | 				av_freep(&m_formatCtx->streams[0]->codec); | ||||||
|  | 				throw; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		catch(AUD_Exception&) | ||||||
|  | 		{ | ||||||
|  | 			av_freep(&m_formatCtx->streams[0]); | ||||||
|  | 			throw; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	catch(AUD_Exception&) | ||||||
|  | 	{ | ||||||
|  | 		av_free(m_formatCtx); | ||||||
|  | 		throw; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AUD_FFMPEGWriter::~AUD_FFMPEGWriter() | ||||||
|  | { | ||||||
|  | 	// writte missing data | ||||||
|  | 	if(m_input_samples) | ||||||
|  | 	{ | ||||||
|  | 		sample_t* buf = m_input_buffer.getBuffer(); | ||||||
|  | 		memset(buf + m_specs.channels * m_input_samples, 0, | ||||||
|  | 			   (m_input_size - m_input_samples) * AUD_DEVICE_SAMPLE_SIZE(m_specs)); | ||||||
|  |  | ||||||
|  | 		encode(buf); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	av_write_trailer(m_formatCtx); | ||||||
|  |  | ||||||
|  | 	avcodec_close(m_codecCtx); | ||||||
|  |  | ||||||
|  | 	av_freep(&m_formatCtx->streams[0]->codec); | ||||||
|  | 	av_freep(&m_formatCtx->streams[0]); | ||||||
|  |  | ||||||
|  | 	avio_close(m_formatCtx->pb); | ||||||
|  | 	av_free(m_formatCtx); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int AUD_FFMPEGWriter::getPosition() const | ||||||
|  | { | ||||||
|  | 	return m_position; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AUD_DeviceSpecs AUD_FFMPEGWriter::getSpecs() const | ||||||
|  | { | ||||||
|  | 	return m_specs; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AUD_FFMPEGWriter::encode(sample_t* data) | ||||||
|  | { | ||||||
|  | 	sample_t* outbuf = m_output_buffer.getBuffer(); | ||||||
|  |  | ||||||
|  | 	// convert first | ||||||
|  | 	if(m_input_size) | ||||||
|  | 		m_convert(reinterpret_cast<data_t*>(data), reinterpret_cast<data_t*>(data), m_input_size * m_specs.channels); | ||||||
|  |  | ||||||
|  | 	AVPacket packet; | ||||||
|  | 	av_init_packet(&packet); | ||||||
|  | 	packet.size = avcodec_encode_audio(m_codecCtx, reinterpret_cast<uint8_t*>(outbuf), m_output_buffer.getSize(), reinterpret_cast<short*>(data)); | ||||||
|  | 	if(m_codecCtx->coded_frame && m_codecCtx->coded_frame->pts != AV_NOPTS_VALUE) | ||||||
|  | 		packet.pts = av_rescale_q(m_codecCtx->coded_frame->pts, m_codecCtx->time_base, m_stream->time_base); | ||||||
|  | 	packet.flags |= AV_PKT_FLAG_KEY; | ||||||
|  | 	packet.stream_index = m_stream->index; | ||||||
|  | 	packet.data = reinterpret_cast<uint8_t*>(outbuf); | ||||||
|  |  | ||||||
|  | 	if(av_interleaved_write_frame(m_formatCtx, &packet)) | ||||||
|  | 		AUD_THROW(AUD_ERROR_FFMPEG, write_error); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AUD_FFMPEGWriter::write(unsigned int length, sample_t* buffer) | ||||||
|  | { | ||||||
|  | 	unsigned int samplesize = AUD_SAMPLE_SIZE(m_specs); | ||||||
|  |  | ||||||
|  | 	if(m_input_size) | ||||||
|  | 	{ | ||||||
|  | 		sample_t* inbuf = m_input_buffer.getBuffer(); | ||||||
|  |  | ||||||
|  | 		while(length) | ||||||
|  | 		{ | ||||||
|  | 			unsigned int len = AUD_MIN(m_input_size - m_input_samples, length); | ||||||
|  |  | ||||||
|  | 			memcpy(inbuf + m_input_samples * m_specs.channels, buffer, len * samplesize); | ||||||
|  |  | ||||||
|  | 			buffer += len * m_specs.channels; | ||||||
|  | 			m_input_samples += len; | ||||||
|  | 			m_position += len; | ||||||
|  | 			length -= len; | ||||||
|  |  | ||||||
|  | 			if(m_input_samples == m_input_size) | ||||||
|  | 			{ | ||||||
|  | 				encode(inbuf); | ||||||
|  |  | ||||||
|  | 				m_input_samples = 0; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else // PCM data, can write directly! | ||||||
|  | 	{ | ||||||
|  | 		int samplesize = AUD_SAMPLE_SIZE(m_specs); | ||||||
|  | 		if(m_output_buffer.getSize() != length * m_specs.channels * m_codecCtx->bits_per_coded_sample / 8) | ||||||
|  | 			m_output_buffer.resize(length * m_specs.channels * m_codecCtx->bits_per_coded_sample / 8); | ||||||
|  | 		m_input_buffer.assureSize(length * AUD_MAX(AUD_DEVICE_SAMPLE_SIZE(m_specs), samplesize)); | ||||||
|  |  | ||||||
|  | 		sample_t* buf = m_input_buffer.getBuffer(); | ||||||
|  | 		m_convert(reinterpret_cast<data_t*>(buf), reinterpret_cast<data_t*>(buffer), length * m_specs.channels); | ||||||
|  |  | ||||||
|  | 		encode(buf); | ||||||
|  |  | ||||||
|  | 		m_position += length; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										140
									
								
								intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | |||||||
|  | /* | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |  * ***** BEGIN GPL LICENSE BLOCK ***** | ||||||
|  |  * | ||||||
|  |  * Copyright 2009-2011 Jörg Hermann Müller | ||||||
|  |  * | ||||||
|  |  * This file is part of AudaSpace. | ||||||
|  |  * | ||||||
|  |  * Audaspace is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation; either version 2 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * AudaSpace is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with Audaspace; if not, write to the Free Software Foundation, | ||||||
|  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||||
|  |  * | ||||||
|  |  * ***** END GPL LICENSE BLOCK ***** | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** \file audaspace/ffmpeg/AUD_FFMPEGWriter.h | ||||||
|  |  *  \ingroup audffmpeg | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #ifndef AUD_FFMPEGWRITER | ||||||
|  | #define AUD_FFMPEGWRITER | ||||||
|  |  | ||||||
|  | #include "AUD_ConverterFunctions.h" | ||||||
|  | #include "AUD_Buffer.h" | ||||||
|  | #include "AUD_IWriter.h" | ||||||
|  |  | ||||||
|  | #include <string> | ||||||
|  |  | ||||||
|  | struct AVCodecContext; | ||||||
|  | extern "C" { | ||||||
|  | #include <libavformat/avformat.h> | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * This class writes a sound file via ffmpeg. | ||||||
|  |  */ | ||||||
|  | class AUD_FFMPEGWriter : public AUD_IWriter | ||||||
|  | { | ||||||
|  | private: | ||||||
|  | 	/** | ||||||
|  | 	 * The current position in samples. | ||||||
|  | 	 */ | ||||||
|  | 	int m_position; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * The specification of the audio data. | ||||||
|  | 	 */ | ||||||
|  | 	AUD_DeviceSpecs m_specs; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * The AVFormatContext structure for using ffmpeg. | ||||||
|  | 	 */ | ||||||
|  | 	AVFormatContext* m_formatCtx; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * The AVCodecContext structure for using ffmpeg. | ||||||
|  | 	 */ | ||||||
|  | 	AVCodecContext* m_codecCtx; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * The AVOutputFormat structure for using ffmpeg. | ||||||
|  | 	 */ | ||||||
|  | 	AVOutputFormat* m_outputFmt; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * The AVStream structure for using ffmpeg. | ||||||
|  | 	 */ | ||||||
|  | 	AVStream* m_stream; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * The input buffer for the format converted data before encoding. | ||||||
|  | 	 */ | ||||||
|  | 	AUD_Buffer m_input_buffer; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * The output buffer for the encoded audio data. | ||||||
|  | 	 */ | ||||||
|  | 	AUD_Buffer m_output_buffer; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * The count of input samples we have so far. | ||||||
|  | 	 */ | ||||||
|  | 	unsigned int m_input_samples; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * The count of input samples necessary to encode a packet. | ||||||
|  | 	 */ | ||||||
|  | 	unsigned int m_input_size; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Converter function. | ||||||
|  | 	 */ | ||||||
|  | 	AUD_convert_f m_convert; | ||||||
|  |  | ||||||
|  | 	// hide copy constructor and operator= | ||||||
|  | 	AUD_FFMPEGWriter(const AUD_FFMPEGWriter&); | ||||||
|  | 	AUD_FFMPEGWriter& operator=(const AUD_FFMPEGWriter&); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Encodes to the output buffer. | ||||||
|  | 	 * \param data Pointer to the data to encode. | ||||||
|  | 	 */ | ||||||
|  | 	void encode(sample_t* data); | ||||||
|  |  | ||||||
|  | public: | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a new writer. | ||||||
|  | 	 * \param filename The path to the file to be read. | ||||||
|  | 	 * \param specs The file's audio specification. | ||||||
|  | 	 * \param format The file's container format. | ||||||
|  | 	 * \param codec The codec used for encoding the audio data. | ||||||
|  | 	 * \param bitrate The bitrate for encoding. | ||||||
|  | 	 * \exception AUD_Exception Thrown if the file specified does not exist or | ||||||
|  | 	 *            cannot be read with ffmpeg. | ||||||
|  | 	 */ | ||||||
|  | 	AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Destroys the writer and closes the file. | ||||||
|  | 	 */ | ||||||
|  | 	virtual ~AUD_FFMPEGWriter(); | ||||||
|  |  | ||||||
|  | 	virtual int getPosition() const; | ||||||
|  | 	virtual AUD_DeviceSpecs getSpecs() const; | ||||||
|  | 	virtual void write(unsigned int length, sample_t* buffer); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #endif //AUD_FFMPEGWRITER | ||||||
| @@ -71,8 +71,7 @@ void AUD_BandPassReader::read(int & length, sample_t* & buffer) | |||||||
|  |  | ||||||
| 	if(length > 0) | 	if(length > 0) | ||||||
| 	{ | 	{ | ||||||
| 		if(length * AUD_SAMPLE_SIZE(specs) > m_buffer->getSize()) | 		m_buffer->assureSize(length * AUD_SAMPLE_SIZE(specs)); | ||||||
| 			m_buffer->resize(length * AUD_SAMPLE_SIZE(specs)); |  | ||||||
|  |  | ||||||
| 		if(length != m_length) | 		if(length != m_length) | ||||||
| 		{ | 		{ | ||||||
|   | |||||||
| @@ -32,9 +32,188 @@ | |||||||
| #ifndef AUD_3DMATH | #ifndef AUD_3DMATH | ||||||
| #define AUD_3DMATH | #define AUD_3DMATH | ||||||
|  |  | ||||||
|  | #include <cmath> | ||||||
|  | #include <cstring> | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * This class represents a 3 dimensional vector. | ||||||
|  |  */ | ||||||
|  | class AUD_Vector3 | ||||||
|  | { | ||||||
|  | private: | ||||||
|  | 	/** | ||||||
|  | 	 * The vector components. | ||||||
|  | 	 */ | ||||||
|  | 	union | ||||||
|  | 	{ | ||||||
|  | 		float m_v[3]; | ||||||
|  | 		struct | ||||||
|  | 		{ | ||||||
|  | 			float m_x; | ||||||
|  | 			float m_y; | ||||||
|  | 			float m_z; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | public: | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a new 3 dimensional vector. | ||||||
|  | 	 * \param x The x component. | ||||||
|  | 	 * \param y The y component. | ||||||
|  | 	 * \param z The z component. | ||||||
|  | 	 */ | ||||||
|  | 	inline AUD_Vector3(float x = 0, float y = 0, float z = 0) : | ||||||
|  | 		m_x(x), m_y(y), m_z(z) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Retrieves the x component of the vector. | ||||||
|  | 	 * \return The x component. | ||||||
|  | 	 */ | ||||||
|  | 	inline const float& x() const | ||||||
|  | 	{ | ||||||
|  | 		return m_x; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Retrieves the y component of the vector. | ||||||
|  | 	 * \return The y component. | ||||||
|  | 	 */ | ||||||
|  | 	inline const float& y() const | ||||||
|  | 	{ | ||||||
|  | 		return m_y; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Retrieves the z component of the vector. | ||||||
|  | 	 * \return The z component. | ||||||
|  | 	 */ | ||||||
|  | 	inline const float& z() const | ||||||
|  | 	{ | ||||||
|  | 		return m_z; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Retrieves the components of the vector. | ||||||
|  | 	 * \param destination Where the 3 float values should be saved to. | ||||||
|  | 	 */ | ||||||
|  | 	inline void get(float* destination) const | ||||||
|  | 	{ | ||||||
|  | 		memcpy(destination, m_v, sizeof(m_v)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Retrieves the components of the vector. | ||||||
|  | 	 * \return The components as float[3]. | ||||||
|  | 	 */ | ||||||
|  | 	inline float* get() | ||||||
|  | 	{ | ||||||
|  | 		return m_v; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Retrieves the components of the vector. | ||||||
|  | 	 * \return The components as float[3]. | ||||||
|  | 	 */ | ||||||
|  | 	inline const float* get() const | ||||||
|  | 	{ | ||||||
|  | 		return m_v; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Retrieves the length of the vector. | ||||||
|  | 	 * \return The length of the vector. | ||||||
|  | 	 */ | ||||||
|  | 	inline float length() const | ||||||
|  | 	{ | ||||||
|  | 		return sqrt(m_x*m_x + m_y*m_y + m_z*m_z); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Retrieves the cross product. | ||||||
|  | 	 * \param op The second operand. | ||||||
|  | 	 * \return The cross product of the two vectors. | ||||||
|  | 	 */ | ||||||
|  | 	inline AUD_Vector3 cross(const AUD_Vector3& op) const | ||||||
|  | 	{ | ||||||
|  | 		return AUD_Vector3(m_y * op.m_z - m_z * op.m_y, | ||||||
|  | 						   m_z * op.m_x - m_x * op.m_z, | ||||||
|  | 						   m_x * op.m_y - m_y * op.m_x); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Retrieves the dot product. | ||||||
|  | 	 * \param op The second operand. | ||||||
|  | 	 * \return The dot product of the two vectors. | ||||||
|  | 	 */ | ||||||
|  | 	inline float operator*(const AUD_Vector3& op) const | ||||||
|  | 	{ | ||||||
|  | 		return m_x * op.m_x + m_y * op.m_y + m_z * op.m_z; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Retrieves the product with a scalar. | ||||||
|  | 	 * \param op The second operand. | ||||||
|  | 	 * \return The scaled vector. | ||||||
|  | 	 */ | ||||||
|  | 	inline AUD_Vector3 operator*(const float& op) const | ||||||
|  | 	{ | ||||||
|  | 		return AUD_Vector3(m_x * op, m_y * op, m_z * op); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Adds two vectors. | ||||||
|  | 	 * \param op The second operand. | ||||||
|  | 	 * \return The sum vector. | ||||||
|  | 	 */ | ||||||
|  | 	inline AUD_Vector3 operator+(const AUD_Vector3& op) const | ||||||
|  | 	{ | ||||||
|  | 		return AUD_Vector3(m_x + op.m_x, m_y + op.m_y, m_z + op.m_z); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Subtracts two vectors. | ||||||
|  | 	 * \param op The second operand. | ||||||
|  | 	 * \return The difference vector. | ||||||
|  | 	 */ | ||||||
|  | 	inline AUD_Vector3 operator-(const AUD_Vector3& op) const | ||||||
|  | 	{ | ||||||
|  | 		return AUD_Vector3(m_x - op.m_x, m_y - op.m_y, m_z - op.m_z); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Negates the vector. | ||||||
|  | 	 * \return The vector facing in the opposite direction. | ||||||
|  | 	 */ | ||||||
|  | 	inline AUD_Vector3 operator-() const | ||||||
|  | 	{ | ||||||
|  | 		return AUD_Vector3(-m_x, -m_y, -m_z); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Subtracts the second vector. | ||||||
|  | 	 * \param op The second operand. | ||||||
|  | 	 * \return The difference vector. | ||||||
|  | 	 */ | ||||||
|  | 	inline AUD_Vector3& operator-=(const AUD_Vector3& op) | ||||||
|  | 	{ | ||||||
|  | 		m_x -= op.m_x; | ||||||
|  | 		m_y -= op.m_y; | ||||||
|  | 		m_z -= op.m_z; | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * This class represents a quaternion used for 3D rotations. | ||||||
|  |  */ | ||||||
| class AUD_Quaternion | class AUD_Quaternion | ||||||
| { | { | ||||||
| private: | private: | ||||||
|  | 	/** | ||||||
|  | 	 * The quaternion components. | ||||||
|  | 	 */ | ||||||
| 	union | 	union | ||||||
| 	{ | 	{ | ||||||
| 		float m_v[4]; | 		float m_v[4]; | ||||||
| @@ -55,7 +234,7 @@ public: | |||||||
| 	 * \param y The y component. | 	 * \param y The y component. | ||||||
| 	 * \param z The z component. | 	 * \param z The z component. | ||||||
| 	 */ | 	 */ | ||||||
| 	inline AUD_Quaternion(float w, float x, float y, float z) : | 	inline AUD_Quaternion(float w = 1, float x = 0, float y = 0, float z = 0) : | ||||||
| 		m_w(w), m_x(x), m_y(y), m_z(z) | 		m_w(w), m_x(x), m_y(y), m_z(z) | ||||||
| 	{ | 	{ | ||||||
| 	} | 	} | ||||||
| @@ -102,10 +281,16 @@ public: | |||||||
| 	 */ | 	 */ | ||||||
| 	inline void get(float* destination) const | 	inline void get(float* destination) const | ||||||
| 	{ | 	{ | ||||||
| 		destination[0] = m_w; | 		memcpy(destination, m_v, sizeof(m_v)); | ||||||
| 		destination[1] = m_x; | 	} | ||||||
| 		destination[2] = m_y; |  | ||||||
| 		destination[3] = m_z; | 	/** | ||||||
|  | 	 * Retrieves the components of the vector. | ||||||
|  | 	 * \return The components as float[4]. | ||||||
|  | 	 */ | ||||||
|  | 	inline float* get() | ||||||
|  | 	{ | ||||||
|  | 		return m_v; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @@ -116,79 +301,29 @@ public: | |||||||
| 	{ | 	{ | ||||||
| 		return m_v; | 		return m_v; | ||||||
| 	} | 	} | ||||||
| }; |  | ||||||
|  |  | ||||||
| class AUD_Vector3 |  | ||||||
| { |  | ||||||
| private: |  | ||||||
| 	union |  | ||||||
| 	{ |  | ||||||
| 		float m_v[3]; |  | ||||||
| 		struct |  | ||||||
| 		{ |  | ||||||
| 			float m_x; |  | ||||||
| 			float m_y; |  | ||||||
| 			float m_z; |  | ||||||
| 		}; |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| public: |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Creates a new 3 dimensional vector. | 	 * When the quaternion represents an orientation, this returns the negative | ||||||
| 	 * \param x The x component. | 	 * z axis vector. | ||||||
| 	 * \param y The y component. | 	 * \return The negative z axis vector. | ||||||
| 	 * \param z The z component. |  | ||||||
| 	 */ | 	 */ | ||||||
| 	inline AUD_Vector3(float x, float y, float z) : | 	inline AUD_Vector3 getLookAt() const | ||||||
| 		m_x(x), m_y(y), m_z(z) |  | ||||||
| 	{ | 	{ | ||||||
|  | 		return AUD_Vector3(-2 * (m_w * m_y + m_x * m_z), | ||||||
|  | 							2 * (m_x * m_w - m_z * m_y), | ||||||
|  | 							2 * (m_x * m_x + m_y * m_y) - 1); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Retrieves the x component of the vector. | 	 * When the quaternion represents an orientation, this returns the y axis | ||||||
| 	 * \return The x component. | 	 * vector. | ||||||
|  | 	 * \return The y axis vector. | ||||||
| 	 */ | 	 */ | ||||||
| 	inline const float& x() const | 	inline AUD_Vector3 getUp() const | ||||||
| 	{ | 	{ | ||||||
| 		return m_x; | 		return AUD_Vector3(2 * (m_x * m_y - m_w * m_z), | ||||||
| 	} | 							1 - 2 * (m_x * m_x + m_z * m_z), | ||||||
|  | 							2 * (m_w * m_x + m_y * m_z)); | ||||||
| 	/** |  | ||||||
| 	 * Retrieves the y component of the vector. |  | ||||||
| 	 * \return The y component. |  | ||||||
| 	 */ |  | ||||||
| 	inline const float& y() const |  | ||||||
| 	{ |  | ||||||
| 		return m_y; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * Retrieves the z component of the vector. |  | ||||||
| 	 * \return The z component. |  | ||||||
| 	 */ |  | ||||||
| 	inline const float& z() const |  | ||||||
| 	{ |  | ||||||
| 		return m_z; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * Retrieves the components of the vector. |  | ||||||
| 	 * \param destination Where the 3 float values should be saved to. |  | ||||||
| 	 */ |  | ||||||
| 	inline void get(float* destination) const |  | ||||||
| 	{ |  | ||||||
| 		destination[0] = m_x; |  | ||||||
| 		destination[1] = m_y; |  | ||||||
| 		destination[2] = m_z; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * Retrieves the components of the vector. |  | ||||||
| 	 * \return The components as float[3]. |  | ||||||
| 	 */ |  | ||||||
| 	inline const float* get() const |  | ||||||
| 	{ |  | ||||||
| 		return m_v; |  | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										159
									
								
								intern/audaspace/intern/AUD_AnimateableProperty.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								intern/audaspace/intern/AUD_AnimateableProperty.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | |||||||
|  | /* | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |  * ***** BEGIN GPL LICENSE BLOCK ***** | ||||||
|  |  * | ||||||
|  |  * Copyright 2009-2011 Jörg Hermann Müller | ||||||
|  |  * | ||||||
|  |  * This file is part of AudaSpace. | ||||||
|  |  * | ||||||
|  |  * Audaspace is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation; either version 2 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * AudaSpace is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with Audaspace; if not, write to the Free Software Foundation, | ||||||
|  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||||
|  |  * | ||||||
|  |  * ***** END GPL LICENSE BLOCK ***** | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** \file audaspace/intern/AUD_AnimateableProperty.cpp | ||||||
|  |  *  \ingroup audaspaceintern | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #include "AUD_AnimateableProperty.h" | ||||||
|  |  | ||||||
|  | #include <cstring> | ||||||
|  | #include <cmath> | ||||||
|  |  | ||||||
|  | AUD_AnimateableProperty::AUD_AnimateableProperty(int count) : | ||||||
|  | 	AUD_Buffer(count * sizeof(float)), m_count(count), m_isAnimated(false) | ||||||
|  | { | ||||||
|  | 	memset(getBuffer(), 0, count * sizeof(float)); | ||||||
|  |  | ||||||
|  | 	pthread_mutexattr_t attr; | ||||||
|  | 	pthread_mutexattr_init(&attr); | ||||||
|  | 	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); | ||||||
|  |  | ||||||
|  | 	pthread_mutex_init(&m_mutex, &attr); | ||||||
|  |  | ||||||
|  | 	pthread_mutexattr_destroy(&attr); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AUD_AnimateableProperty::~AUD_AnimateableProperty() | ||||||
|  | { | ||||||
|  | 	pthread_mutex_destroy(&m_mutex); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AUD_AnimateableProperty::lock() | ||||||
|  | { | ||||||
|  | 	pthread_mutex_lock(&m_mutex); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AUD_AnimateableProperty::unlock() | ||||||
|  | { | ||||||
|  | 	pthread_mutex_unlock(&m_mutex); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AUD_AnimateableProperty::write(const float* data) | ||||||
|  | { | ||||||
|  | 	lock(); | ||||||
|  |  | ||||||
|  | 	m_isAnimated = false; | ||||||
|  | 	memcpy(getBuffer(), data, m_count * sizeof(float)); | ||||||
|  |  | ||||||
|  | 	unlock(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AUD_AnimateableProperty::write(const float* data, int position, int count) | ||||||
|  | { | ||||||
|  | 	lock(); | ||||||
|  |  | ||||||
|  | 	m_isAnimated = true; | ||||||
|  |  | ||||||
|  | 	int pos = getSize() / (sizeof(float) * m_count); | ||||||
|  |  | ||||||
|  | 	assureSize((count + position) * m_count * sizeof(float), true); | ||||||
|  |  | ||||||
|  | 	float* buf = getBuffer(); | ||||||
|  |  | ||||||
|  | 	memcpy(buf + position * m_count, data, count * m_count * sizeof(float)); | ||||||
|  |  | ||||||
|  | 	for(int i = pos; i < position; i++) | ||||||
|  | 		memcpy(buf + i * m_count, buf + (pos - 1) * m_count, m_count * sizeof(float)); | ||||||
|  |  | ||||||
|  | 	unlock(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AUD_AnimateableProperty::read(float position, float* out) | ||||||
|  | { | ||||||
|  | 	lock(); | ||||||
|  |  | ||||||
|  | 	if(!m_isAnimated) | ||||||
|  | 	{ | ||||||
|  | 		memcpy(out, getBuffer(), m_count * sizeof(float)); | ||||||
|  | 		unlock(); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	int last = getSize() / (sizeof(float) * m_count) - 1; | ||||||
|  | 	float t = position - floor(position); | ||||||
|  |  | ||||||
|  | 	if(position >= last) | ||||||
|  | 	{ | ||||||
|  | 		position = last; | ||||||
|  | 		t = 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if(t == 0) | ||||||
|  | 	{ | ||||||
|  | 		memcpy(out, getBuffer() + int(floor(position)) * m_count, m_count * sizeof(float)); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		int pos = int(floor(position)) * m_count; | ||||||
|  | 		float t2 = t * t; | ||||||
|  | 		float t3 = t2 * t; | ||||||
|  | 		float m0, m1; | ||||||
|  | 		float* p0; | ||||||
|  | 		float* p1 = getBuffer() + pos; | ||||||
|  | 		float* p2; | ||||||
|  | 		float* p3; | ||||||
|  | 		last *= m_count; | ||||||
|  |  | ||||||
|  | 		if(pos == 0) | ||||||
|  | 			p0 = p1; | ||||||
|  | 		else | ||||||
|  | 			p0 = p1 - m_count; | ||||||
|  |  | ||||||
|  | 		p2 = p1 + m_count; | ||||||
|  | 		if(pos + m_count == last) | ||||||
|  | 			p3 = p2; | ||||||
|  | 		else | ||||||
|  | 			p3 = p2 + m_count; | ||||||
|  |  | ||||||
|  | 		for(int i = 0; i < m_count; i++) | ||||||
|  | 		{ | ||||||
|  | 			m0 = (p2[i] - p0[i]) / 2.0f; | ||||||
|  | 			m1 = (p3[i] - p1[i]) / 2.0f; | ||||||
|  |  | ||||||
|  | 			out[i] = (2 * t3 - 3 * t2 + 1) * p0[i] + (-2 * t3 + 3 * t2) * p1[i] + | ||||||
|  | 					 (t3 - 2 * t2 + t) * m0 + (t3 - t2) * m1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	unlock(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool AUD_AnimateableProperty::isAnimated() const | ||||||
|  | { | ||||||
|  | 	return m_isAnimated; | ||||||
|  | } | ||||||
							
								
								
									
										108
									
								
								intern/audaspace/intern/AUD_AnimateableProperty.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								intern/audaspace/intern/AUD_AnimateableProperty.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | |||||||
|  | /* | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |  * ***** BEGIN GPL LICENSE BLOCK ***** | ||||||
|  |  * | ||||||
|  |  * Copyright 2009-2011 Jörg Hermann Müller | ||||||
|  |  * | ||||||
|  |  * This file is part of AudaSpace. | ||||||
|  |  * | ||||||
|  |  * Audaspace is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation; either version 2 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * AudaSpace is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with Audaspace; if not, write to the Free Software Foundation, | ||||||
|  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||||
|  |  * | ||||||
|  |  * ***** END GPL LICENSE BLOCK ***** | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** \file audaspace/intern/AUD_AnimateableProperty.h | ||||||
|  |  *  \ingroup audaspaceintern | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #ifndef AUD_ANIMATEABLEPROPERTY | ||||||
|  | #define AUD_ANIMATEABLEPROPERTY | ||||||
|  |  | ||||||
|  | #include "AUD_Buffer.h" | ||||||
|  |  | ||||||
|  | #include <pthread.h> | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * This class saves animation data for float properties. | ||||||
|  |  */ | ||||||
|  | class AUD_AnimateableProperty : private AUD_Buffer | ||||||
|  | { | ||||||
|  | private: | ||||||
|  | 	/// The count of floats for a single property. | ||||||
|  | 	const int m_count; | ||||||
|  |  | ||||||
|  | 	/// Whether the property is animated or not. | ||||||
|  | 	bool m_isAnimated; | ||||||
|  |  | ||||||
|  | 	/// The mutex for locking. | ||||||
|  | 	pthread_mutex_t m_mutex; | ||||||
|  |  | ||||||
|  | 	// hide copy constructor and operator= | ||||||
|  | 	AUD_AnimateableProperty(const AUD_AnimateableProperty&); | ||||||
|  | 	AUD_AnimateableProperty& operator=(const AUD_AnimateableProperty&); | ||||||
|  |  | ||||||
|  | public: | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a new animateable property. | ||||||
|  | 	 * \param count The count of floats for a single property. | ||||||
|  | 	 */ | ||||||
|  | 	AUD_AnimateableProperty(int count = 1); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Destroys the animateable property. | ||||||
|  | 	 */ | ||||||
|  | 	~AUD_AnimateableProperty(); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Locks the property. | ||||||
|  | 	 */ | ||||||
|  | 	void lock(); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Unlocks the previously locked property. | ||||||
|  | 	 */ | ||||||
|  | 	void unlock(); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Writes the properties value and marks it non-animated. | ||||||
|  | 	 * \param data The new value. | ||||||
|  | 	 */ | ||||||
|  | 	void write(const float* data); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Writes the properties value and marks it animated. | ||||||
|  | 	 * \param data The new value. | ||||||
|  | 	 * \param position The position in the animation in frames. | ||||||
|  | 	 * \param count The count of frames to write. | ||||||
|  | 	 */ | ||||||
|  | 	void write(const float* data, int position, int count); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Reads the properties value. | ||||||
|  | 	 * \param position The position in the animation in frames. | ||||||
|  | 	 * \param[out] out Where to write the value to. | ||||||
|  | 	 */ | ||||||
|  | 	void read(float position, float* out); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Returns whether the property is animated. | ||||||
|  | 	 * \return Whether the property is animated. | ||||||
|  | 	 */ | ||||||
|  | 	bool isAnimated() const; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #endif //AUD_ANIMATEABLEPROPERTY | ||||||
| @@ -74,3 +74,9 @@ void AUD_Buffer::resize(int size, bool keep) | |||||||
|  |  | ||||||
| 	m_size = size; | 	m_size = size; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void AUD_Buffer::assureSize(int size, bool keep) | ||||||
|  | { | ||||||
|  | 	if(m_size < size) | ||||||
|  | 		resize(size, keep); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -80,6 +80,16 @@ public: | |||||||
| 	 *        the data at the end will be lost. | 	 *        the data at the end will be lost. | ||||||
| 	 */ | 	 */ | ||||||
| 	void resize(int size, bool keep = false); | 	void resize(int size, bool keep = false); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Makes sure the buffer has a minimum size. | ||||||
|  | 	 * If size is >= current size, nothing will happen. | ||||||
|  | 	 * Otherwise the buffer is resized with keep as parameter. | ||||||
|  | 	 * \param size The new minimum size of the buffer, measured in bytes. | ||||||
|  | 	 * \param keep Whether to keep the old data. If the new buffer is smaller, | ||||||
|  | 	 *        the data at the end will be lost. | ||||||
|  | 	 */ | ||||||
|  | 	void assureSize(int size, bool keep = false); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_BUFFER | #endif //AUD_BUFFER | ||||||
|   | |||||||
| @@ -33,6 +33,8 @@ | |||||||
| #include "AUD_Buffer.h" | #include "AUD_Buffer.h" | ||||||
| #include "AUD_Space.h" | #include "AUD_Space.h" | ||||||
|  |  | ||||||
|  | #include <cstring> | ||||||
|  |  | ||||||
| AUD_BufferReader::AUD_BufferReader(AUD_Reference<AUD_Buffer> buffer, | AUD_BufferReader::AUD_BufferReader(AUD_Reference<AUD_Buffer> buffer, | ||||||
| 								   AUD_Specs specs) : | 								   AUD_Specs specs) : | ||||||
| 	m_position(0), m_buffer(buffer), m_specs(specs) | 	m_position(0), m_buffer(buffer), m_specs(specs) | ||||||
| @@ -51,7 +53,7 @@ void AUD_BufferReader::seek(int position) | |||||||
|  |  | ||||||
| int AUD_BufferReader::getLength() const | int AUD_BufferReader::getLength() const | ||||||
| { | { | ||||||
| 	return m_buffer.get()->getSize() / AUD_SAMPLE_SIZE(m_specs); | 	return m_buffer->getSize() / AUD_SAMPLE_SIZE(m_specs); | ||||||
| } | } | ||||||
|  |  | ||||||
| int AUD_BufferReader::getPosition() const | int AUD_BufferReader::getPosition() const | ||||||
| @@ -64,17 +66,27 @@ AUD_Specs AUD_BufferReader::getSpecs() const | |||||||
| 	return m_specs; | 	return m_specs; | ||||||
| } | } | ||||||
|  |  | ||||||
| void AUD_BufferReader::read(int & length, sample_t* & buffer) | void AUD_BufferReader::read(int& length, bool& eos, sample_t* buffer) | ||||||
| { | { | ||||||
|  | 	eos = false; | ||||||
|  |  | ||||||
| 	int sample_size = AUD_SAMPLE_SIZE(m_specs); | 	int sample_size = AUD_SAMPLE_SIZE(m_specs); | ||||||
|  |  | ||||||
| 	buffer = m_buffer.get()->getBuffer() + m_position * m_specs.channels; | 	sample_t* buf = m_buffer->getBuffer() + m_position * m_specs.channels; | ||||||
|  |  | ||||||
| 	// in case the end of the buffer is reached | 	// in case the end of the buffer is reached | ||||||
| 	if(m_buffer.get()->getSize() < (m_position + length) * sample_size) | 	if(m_buffer->getSize() < (m_position + length) * sample_size) | ||||||
| 		length = m_buffer.get()->getSize() / sample_size - m_position; | 	{ | ||||||
|  | 		length = m_buffer->getSize() / sample_size - m_position; | ||||||
|  | 		eos = true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if(length < 0) | 	if(length < 0) | ||||||
|  | 	{ | ||||||
| 		length = 0; | 		length = 0; | ||||||
| 	m_position += length; | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	m_position += length; | ||||||
|  | 	memcpy(buffer, buf, length * sample_size); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -76,7 +76,7 @@ public: | |||||||
| 	virtual int getLength() const; | 	virtual int getLength() const; | ||||||
| 	virtual int getPosition() const; | 	virtual int getPosition() const; | ||||||
| 	virtual AUD_Specs getSpecs() const; | 	virtual AUD_Specs getSpecs() const; | ||||||
| 	virtual void read(int & length, sample_t* & buffer); | 	virtual void read(int& length, bool& eos, sample_t* buffer); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif //AUD_BUFFERREADER | #endif //AUD_BUFFERREADER | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -31,12 +31,17 @@ | |||||||
| #ifndef AUD_CAPI | #ifndef AUD_CAPI | ||||||
| #define AUD_CAPI | #define AUD_CAPI | ||||||
|  |  | ||||||
|  | #ifdef WITH_PYTHON | ||||||
|  | #include "Python.h" | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #include "AUD_Space.h" | #include "AUD_Space.h" | ||||||
|  |  | ||||||
|  | /// Supported output devices. | ||||||
| typedef enum | typedef enum | ||||||
| { | { | ||||||
| 	AUD_NULL_DEVICE = 0, | 	AUD_NULL_DEVICE = 0, | ||||||
| @@ -45,6 +50,7 @@ typedef enum | |||||||
| 	AUD_JACK_DEVICE | 	AUD_JACK_DEVICE | ||||||
| } AUD_DeviceType; | } AUD_DeviceType; | ||||||
|  |  | ||||||
|  | /// Sound information structure. | ||||||
| typedef struct | typedef struct | ||||||
| { | { | ||||||
| 	AUD_Specs specs; | 	AUD_Specs specs; | ||||||
| @@ -53,9 +59,9 @@ typedef struct | |||||||
|  |  | ||||||
| #ifndef AUD_CAPI_IMPLEMENTATION | #ifndef AUD_CAPI_IMPLEMENTATION | ||||||
| 	typedef void AUD_Sound; | 	typedef void AUD_Sound; | ||||||
| 	typedef void AUD_Channel; | 	typedef void AUD_Handle; | ||||||
| 	typedef void AUD_Device; | 	typedef void AUD_Device; | ||||||
| 	typedef void AUD_SequencerEntry; | 	typedef void AUD_SEntry; | ||||||
| 	typedef float (*AUD_volumeFunction)(void*, void*, float); | 	typedef float (*AUD_volumeFunction)(void*, void*, float); | ||||||
| 	typedef void (*AUD_syncFunction)(void*, int, float); | 	typedef void (*AUD_syncFunction)(void*, int, float); | ||||||
| #endif | #endif | ||||||
| @@ -118,6 +124,13 @@ extern AUD_Sound* AUD_loadBuffer(unsigned char* buffer, int size); | |||||||
|  */ |  */ | ||||||
| extern AUD_Sound* AUD_bufferSound(AUD_Sound* sound); | extern AUD_Sound* AUD_bufferSound(AUD_Sound* sound); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Rechannels the sound to be mono. | ||||||
|  |  * \param sound The sound to rechannel. | ||||||
|  |  * \return The mono sound. | ||||||
|  |  */ | ||||||
|  | extern AUD_Sound* AUD_monoSound(AUD_Sound* sound); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Delays a sound. |  * Delays a sound. | ||||||
|  * \param sound The sound to dealy. |  * \param sound The sound to dealy. | ||||||
| @@ -155,7 +168,7 @@ extern AUD_Sound* AUD_loopSound(AUD_Sound* sound); | |||||||
|  * \param loops The count of remaining loops, -1 for infinity. |  * \param loops The count of remaining loops, -1 for infinity. | ||||||
|  * \return Whether the handle is valid. |  * \return Whether the handle is valid. | ||||||
|  */ |  */ | ||||||
| extern int AUD_setLoop(AUD_Channel* handle, int loops); | extern int AUD_setLoop(AUD_Handle* handle, int loops); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Rectifies a sound. |  * Rectifies a sound. | ||||||
| @@ -177,28 +190,28 @@ extern void AUD_unload(AUD_Sound* sound); | |||||||
|  *             paused when its end has been reached. |  *             paused when its end has been reached. | ||||||
|  * \return A handle to the played back sound. |  * \return A handle to the played back sound. | ||||||
|  */ |  */ | ||||||
| extern AUD_Channel* AUD_play(AUD_Sound* sound, int keep); | extern AUD_Handle* AUD_play(AUD_Sound* sound, int keep); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Pauses a played back sound. |  * Pauses a played back sound. | ||||||
|  * \param handle The handle to the sound. |  * \param handle The handle to the sound. | ||||||
|  * \return Whether the handle has been playing or not. |  * \return Whether the handle has been playing or not. | ||||||
|  */ |  */ | ||||||
| extern int AUD_pause(AUD_Channel* handle); | extern int AUD_pause(AUD_Handle* handle); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Resumes a paused sound. |  * Resumes a paused sound. | ||||||
|  * \param handle The handle to the sound. |  * \param handle The handle to the sound. | ||||||
|  * \return Whether the handle has been paused or not. |  * \return Whether the handle has been paused or not. | ||||||
|  */ |  */ | ||||||
| extern int AUD_resume(AUD_Channel* handle); | extern int AUD_resume(AUD_Handle* handle); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Stops a playing or paused sound. |  * Stops a playing or paused sound. | ||||||
|  * \param handle The handle to the sound. |  * \param handle The handle to the sound. | ||||||
|  * \return Whether the handle has been valid or not. |  * \return Whether the handle has been valid or not. | ||||||
|  */ |  */ | ||||||
| extern int AUD_stop(AUD_Channel* handle); | extern int AUD_stop(AUD_Handle* handle); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sets the end behaviour of a playing or paused sound. |  * Sets the end behaviour of a playing or paused sound. | ||||||
| @@ -207,7 +220,7 @@ extern int AUD_stop(AUD_Channel* handle); | |||||||
|  *             paused when its end has been reached. |  *             paused when its end has been reached. | ||||||
|  * \return Whether the handle has been valid or not. |  * \return Whether the handle has been valid or not. | ||||||
|  */ |  */ | ||||||
| extern int AUD_setKeep(AUD_Channel* handle, int keep); | extern int AUD_setKeep(AUD_Handle* handle, int keep); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Seeks a playing or paused sound. |  * Seeks a playing or paused sound. | ||||||
| @@ -215,7 +228,7 @@ extern int AUD_setKeep(AUD_Channel* handle, int keep); | |||||||
|  * \param seekTo From where the sound file should be played back in seconds. |  * \param seekTo From where the sound file should be played back in seconds. | ||||||
|  * \return Whether the handle has been valid or not. |  * \return Whether the handle has been valid or not. | ||||||
|  */ |  */ | ||||||
| extern int AUD_seek(AUD_Channel* handle, float seekTo); | extern int AUD_seek(AUD_Handle* handle, float seekTo); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Retrieves the playback position of a handle. |  * Retrieves the playback position of a handle. | ||||||
| @@ -223,14 +236,14 @@ extern int AUD_seek(AUD_Channel* handle, float seekTo); | |||||||
|  * \return The current playback position in seconds or 0.0 if the handle is |  * \return The current playback position in seconds or 0.0 if the handle is | ||||||
|  *         invalid. |  *         invalid. | ||||||
|  */ |  */ | ||||||
| extern float AUD_getPosition(AUD_Channel* handle); | extern float AUD_getPosition(AUD_Handle* handle); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Returns the status of a playing, paused or stopped sound. |  * Returns the status of a playing, paused or stopped sound. | ||||||
|  * \param handle The handle to the sound. |  * \param handle The handle to the sound. | ||||||
|  * \return The status of the sound behind the handle. |  * \return The status of the sound behind the handle. | ||||||
|  */ |  */ | ||||||
| extern AUD_Status AUD_getStatus(AUD_Channel* handle); | extern AUD_Status AUD_getStatus(AUD_Handle* handle); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sets the listener location. |  * Sets the listener location. | ||||||
| @@ -277,7 +290,7 @@ extern int AUD_setDistanceModel(AUD_DistanceModel model); | |||||||
|  * \param location The new location. |  * \param location The new location. | ||||||
|  * \return Whether the action succeeded. |  * \return Whether the action succeeded. | ||||||
|  */ |  */ | ||||||
| extern int AUD_setSourceLocation(AUD_Channel* handle, const float* location); | extern int AUD_setSourceLocation(AUD_Handle* handle, const float* location); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sets the velocity of a source. |  * Sets the velocity of a source. | ||||||
| @@ -285,7 +298,7 @@ extern int AUD_setSourceLocation(AUD_Channel* handle, const float* location); | |||||||
|  * \param velocity The new velocity. |  * \param velocity The new velocity. | ||||||
|  * \return Whether the action succeeded. |  * \return Whether the action succeeded. | ||||||
|  */ |  */ | ||||||
| extern int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity); | extern int AUD_setSourceVelocity(AUD_Handle* handle, const float* velocity); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sets the orientation of a source. |  * Sets the orientation of a source. | ||||||
| @@ -293,7 +306,7 @@ extern int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity); | |||||||
|  * \param orientation The new orientation as quaternion. |  * \param orientation The new orientation as quaternion. | ||||||
|  * \return Whether the action succeeded. |  * \return Whether the action succeeded. | ||||||
|  */ |  */ | ||||||
| extern int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation); | extern int AUD_setSourceOrientation(AUD_Handle* handle, const float* orientation); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sets whether the source location, velocity and orientation are relative |  * Sets whether the source location, velocity and orientation are relative | ||||||
| @@ -302,7 +315,7 @@ extern int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientatio | |||||||
|  * \param relative Whether the source is relative. |  * \param relative Whether the source is relative. | ||||||
|  * \return Whether the action succeeded. |  * \return Whether the action succeeded. | ||||||
|  */ |  */ | ||||||
| extern int AUD_setRelative(AUD_Channel* handle, int relative); | extern int AUD_setRelative(AUD_Handle* handle, int relative); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sets the maximum volume of a source. |  * Sets the maximum volume of a source. | ||||||
| @@ -310,7 +323,7 @@ extern int AUD_setRelative(AUD_Channel* handle, int relative); | |||||||
|  * \param volume The new maximum volume. |  * \param volume The new maximum volume. | ||||||
|  * \return Whether the action succeeded. |  * \return Whether the action succeeded. | ||||||
|  */ |  */ | ||||||
| extern int AUD_setVolumeMaximum(AUD_Channel* handle, float volume); | extern int AUD_setVolumeMaximum(AUD_Handle* handle, float volume); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sets the minimum volume of a source. |  * Sets the minimum volume of a source. | ||||||
| @@ -318,7 +331,7 @@ extern int AUD_setVolumeMaximum(AUD_Channel* handle, float volume); | |||||||
|  * \param volume The new minimum volume. |  * \param volume The new minimum volume. | ||||||
|  * \return Whether the action succeeded. |  * \return Whether the action succeeded. | ||||||
|  */ |  */ | ||||||
| extern int AUD_setVolumeMinimum(AUD_Channel* handle, float volume); | extern int AUD_setVolumeMinimum(AUD_Handle* handle, float volume); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sets the maximum distance of a source. |  * Sets the maximum distance of a source. | ||||||
| @@ -328,7 +341,7 @@ extern int AUD_setVolumeMinimum(AUD_Channel* handle, float volume); | |||||||
|  * \param distance The new maximum distance. |  * \param distance The new maximum distance. | ||||||
|  * \return Whether the action succeeded. |  * \return Whether the action succeeded. | ||||||
|  */ |  */ | ||||||
| extern int AUD_setDistanceMaximum(AUD_Channel* handle, float distance); | extern int AUD_setDistanceMaximum(AUD_Handle* handle, float distance); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sets the reference distance of a source. |  * Sets the reference distance of a source. | ||||||
| @@ -336,7 +349,7 @@ extern int AUD_setDistanceMaximum(AUD_Channel* handle, float distance); | |||||||
|  * \param distance The new reference distance. |  * \param distance The new reference distance. | ||||||
|  * \return Whether the action succeeded. |  * \return Whether the action succeeded. | ||||||
|  */ |  */ | ||||||
| extern int AUD_setDistanceReference(AUD_Channel* handle, float distance); | extern int AUD_setDistanceReference(AUD_Handle* handle, float distance); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sets the attenuation of a source. |  * Sets the attenuation of a source. | ||||||
| @@ -345,7 +358,7 @@ extern int AUD_setDistanceReference(AUD_Channel* handle, float distance); | |||||||
|  * \param factor The new attenuation. |  * \param factor The new attenuation. | ||||||
|  * \return Whether the action succeeded. |  * \return Whether the action succeeded. | ||||||
|  */ |  */ | ||||||
| extern int AUD_setAttenuation(AUD_Channel* handle, float factor); | extern int AUD_setAttenuation(AUD_Handle* handle, float factor); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sets the outer angle of the cone of a source. |  * Sets the outer angle of the cone of a source. | ||||||
| @@ -353,7 +366,7 @@ extern int AUD_setAttenuation(AUD_Channel* handle, float factor); | |||||||
|  * \param angle The new outer angle of the cone. |  * \param angle The new outer angle of the cone. | ||||||
|  * \return Whether the action succeeded. |  * \return Whether the action succeeded. | ||||||
|  */ |  */ | ||||||
| extern int AUD_setConeAngleOuter(AUD_Channel* handle, float angle); | extern int AUD_setConeAngleOuter(AUD_Handle* handle, float angle); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sets the inner angle of the cone of a source. |  * Sets the inner angle of the cone of a source. | ||||||
| @@ -361,7 +374,7 @@ extern int AUD_setConeAngleOuter(AUD_Channel* handle, float angle); | |||||||
|  * \param angle The new inner angle of the cone. |  * \param angle The new inner angle of the cone. | ||||||
|  * \return Whether the action succeeded. |  * \return Whether the action succeeded. | ||||||
|  */ |  */ | ||||||
| extern int AUD_setConeAngleInner(AUD_Channel* handle, float angle); | extern int AUD_setConeAngleInner(AUD_Handle* handle, float angle); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sets the outer volume of the cone of a source. |  * Sets the outer volume of the cone of a source. | ||||||
| @@ -371,7 +384,7 @@ extern int AUD_setConeAngleInner(AUD_Channel* handle, float angle); | |||||||
|  * \param volume The new outer volume of the cone. |  * \param volume The new outer volume of the cone. | ||||||
|  * \return Whether the action succeeded. |  * \return Whether the action succeeded. | ||||||
|  */ |  */ | ||||||
| extern int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume); | extern int AUD_setConeVolumeOuter(AUD_Handle* handle, float volume); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sets the volume of a played back sound. |  * Sets the volume of a played back sound. | ||||||
| @@ -379,7 +392,7 @@ extern int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume); | |||||||
|  * \param volume The new volume, must be between 0.0 and 1.0. |  * \param volume The new volume, must be between 0.0 and 1.0. | ||||||
|  * \return Whether the action succeeded. |  * \return Whether the action succeeded. | ||||||
|  */ |  */ | ||||||
| extern int AUD_setSoundVolume(AUD_Channel* handle, float volume); | extern int AUD_setSoundVolume(AUD_Handle* handle, float volume); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sets the pitch of a played back sound. |  * Sets the pitch of a played back sound. | ||||||
| @@ -387,7 +400,7 @@ extern int AUD_setSoundVolume(AUD_Channel* handle, float volume); | |||||||
|  * \param pitch The new pitch. |  * \param pitch The new pitch. | ||||||
|  * \return Whether the action succeeded. |  * \return Whether the action succeeded. | ||||||
|  */ |  */ | ||||||
| extern int AUD_setSoundPitch(AUD_Channel* handle, float pitch); | extern int AUD_setSoundPitch(AUD_Handle* handle, float pitch); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Opens a read device, with which audio data can be read. |  * Opens a read device, with which audio data can be read. | ||||||
| @@ -411,18 +424,7 @@ extern int AUD_setDeviceVolume(AUD_Device* device, float volume); | |||||||
|  * \param seek The position where the sound should be seeked to. |  * \param seek The position where the sound should be seeked to. | ||||||
|  * \return A handle to the played back sound. |  * \return A handle to the played back sound. | ||||||
|  */ |  */ | ||||||
| extern AUD_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek); | extern AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek); | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Sets the volume of a played back sound of a read device. |  | ||||||
|  * \param device The read device. |  | ||||||
|  * \param handle The handle to the sound. |  | ||||||
|  * \param volume The new volume, must be between 0.0 and 1.0. |  | ||||||
|  * \return Whether the action succeeded. |  | ||||||
|  */ |  | ||||||
| extern int AUD_setDeviceSoundVolume(AUD_Device* device, |  | ||||||
| 									AUD_Channel* handle, |  | ||||||
| 									float volume); |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Reads the next samples into the supplied buffer. |  * Reads the next samples into the supplied buffer. | ||||||
| @@ -448,7 +450,7 @@ extern void AUD_closeReadDevice(AUD_Device* device); | |||||||
| extern float* AUD_readSoundBuffer(const char* filename, float low, float high, | extern float* AUD_readSoundBuffer(const char* filename, float low, float high, | ||||||
| 								  float attack, float release, float threshold, | 								  float attack, float release, float threshold, | ||||||
| 								  int accumulate, int additive, int square, | 								  int accumulate, int additive, int square, | ||||||
| 								  float sthreshold, int samplerate, | 								  float sthreshold, double samplerate, | ||||||
| 								  int* length); | 								  int* length); | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -457,43 +459,302 @@ extern float* AUD_readSoundBuffer(const char* filename, float low, float high, | |||||||
|  * \param time The time in seconds. |  * \param time The time in seconds. | ||||||
|  * \return The silence handle. |  * \return The silence handle. | ||||||
|  */ |  */ | ||||||
| extern AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds); | extern AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds); | ||||||
|  |  | ||||||
| extern AUD_Sound* AUD_createSequencer(int muted, void* data, AUD_volumeFunction volume); | /** | ||||||
|  |  * Creates a new sequenced sound scene. | ||||||
|  |  * \param fps The FPS of the scene. | ||||||
|  |  * \param muted Whether the scene is muted. | ||||||
|  |  * \return The new sound scene. | ||||||
|  |  */ | ||||||
|  | extern AUD_Sound* AUD_createSequencer(float fps, int muted); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Deletes a sound scene. | ||||||
|  |  * \param sequencer The sound scene. | ||||||
|  |  */ | ||||||
| extern void AUD_destroySequencer(AUD_Sound* sequencer); | extern void AUD_destroySequencer(AUD_Sound* sequencer); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Sets the muting state of the scene. | ||||||
|  |  * \param sequencer The sound scene. | ||||||
|  |  * \param muted Whether the scene is muted. | ||||||
|  |  */ | ||||||
| extern void AUD_setSequencerMuted(AUD_Sound* sequencer, int muted); | extern void AUD_setSequencerMuted(AUD_Sound* sequencer, int muted); | ||||||
|  |  | ||||||
| extern AUD_SequencerEntry* AUD_addSequencer(AUD_Sound** sequencer, AUD_Sound* sound, | /** | ||||||
| 										float begin, float end, float skip, void* data); |  * Sets the scene's FPS. | ||||||
|  |  * \param sequencer The sound scene. | ||||||
|  |  * \param fps The new FPS. | ||||||
|  |  */ | ||||||
|  | extern void AUD_setSequencerFPS(AUD_Sound* sequencer, float fps); | ||||||
|  |  | ||||||
| extern void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry); | /** | ||||||
|  |  * Adds a new entry to the scene. | ||||||
| extern void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, |  * \param sequencer The sound scene. | ||||||
|  |  * \param sound The sound this entry should play. | ||||||
|  |  * \param begin The start time. | ||||||
|  |  * \param end The end time or a negative value if determined by the sound. | ||||||
|  |  * \param skip How much seconds should be skipped at the beginning. | ||||||
|  |  * \return The entry added. | ||||||
|  |  */ | ||||||
|  | extern AUD_SEntry* AUD_addSequence(AUD_Sound* sequencer, AUD_Sound* sound, | ||||||
| 								   float begin, float end, float skip); | 								   float begin, float end, float skip); | ||||||
|  |  | ||||||
| extern void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, | /** | ||||||
| 						  char mute); |  * Removes an entry from the scene. | ||||||
|  |  * \param sequencer The sound scene. | ||||||
|  |  * \param entry The entry to remove. | ||||||
|  |  */ | ||||||
|  | extern void AUD_removeSequence(AUD_Sound* sequencer, AUD_SEntry* entry); | ||||||
|  |  | ||||||
| extern int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length); | /** | ||||||
|  |  * Moves the entry. | ||||||
|  |  * \param entry The sequenced entry. | ||||||
|  |  * \param begin The new start time. | ||||||
|  |  * \param end The new end time or a negative value if unknown. | ||||||
|  |  * \param skip How many seconds to skip at the beginning. | ||||||
|  |  */ | ||||||
|  | extern void AUD_moveSequence(AUD_SEntry* entry, float begin, float end, float skip); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Sets the muting state of the entry. | ||||||
|  |  * \param entry The sequenced entry. | ||||||
|  |  * \param mute Whether the entry should be muted or not. | ||||||
|  |  */ | ||||||
|  | extern void AUD_muteSequence(AUD_SEntry* entry, char mute); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Sets whether the entrie's location, velocity and orientation are relative | ||||||
|  |  * to the listener. | ||||||
|  |  * \param entry The sequenced entry. | ||||||
|  |  * \param relative Whether the source is relative. | ||||||
|  |  * \return Whether the action succeeded. | ||||||
|  |  */ | ||||||
|  | extern void AUD_setRelativeSequence(AUD_SEntry* entry, char relative); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Sets the sound of the entry. | ||||||
|  |  * \param entry The sequenced entry. | ||||||
|  |  * \param sound The new sound. | ||||||
|  |  */ | ||||||
|  | extern void AUD_updateSequenceSound(AUD_SEntry* entry, AUD_Sound* sound); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Writes animation data to a sequenced entry. | ||||||
|  |  * \param entry The sequenced entry. | ||||||
|  |  * \param type The type of animation data. | ||||||
|  |  * \param frame The frame this data is for. | ||||||
|  |  * \param data The data to write. | ||||||
|  |  * \param animated Whether the attribute is animated. | ||||||
|  |  */ | ||||||
|  | extern void AUD_setSequenceAnimData(AUD_SEntry* entry, AUD_AnimateablePropertyType type, int frame, float* data, char animated); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Writes animation data to a sequenced entry. | ||||||
|  |  * \param sequencer The sound scene. | ||||||
|  |  * \param type The type of animation data. | ||||||
|  |  * \param frame The frame this data is for. | ||||||
|  |  * \param data The data to write. | ||||||
|  |  * \param animated Whether the attribute is animated. | ||||||
|  |  */ | ||||||
|  | extern void AUD_setSequencerAnimData(AUD_Sound* sequencer, AUD_AnimateablePropertyType type, int frame, float* data, char animated); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Updates all non-animated parameters of the entry. | ||||||
|  |  * \param entry The sequenced entry. | ||||||
|  |  * \param volume_max The maximum volume. | ||||||
|  |  * \param volume_min The minimum volume. | ||||||
|  |  * \param distance_max The maximum distance. | ||||||
|  |  * \param distance_reference The reference distance. | ||||||
|  |  * \param attenuation The attenuation. | ||||||
|  |  * \param cone_angle_outer The outer cone opening angle. | ||||||
|  |  * \param cone_angle_inner The inner cone opening angle. | ||||||
|  |  * \param cone_volume_outer The volume outside the outer cone. | ||||||
|  |  */ | ||||||
|  | extern void AUD_updateSequenceData(AUD_SEntry* entry, float volume_max, float volume_min, | ||||||
|  | 								   float distance_max, float distance_reference, float attenuation, | ||||||
|  | 								   float cone_angle_outer, float cone_angle_inner, float cone_volume_outer); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Updates all non-animated parameters of the entry. | ||||||
|  |  * \param sequencer The sound scene. | ||||||
|  |  * \param speed_of_sound The speed of sound for doppler calculation. | ||||||
|  |  * \param factor The doppler factor to control the effect's strength. | ||||||
|  |  * \param model The distance model for distance calculation. | ||||||
|  |  */ | ||||||
|  | extern void AUD_updateSequencerData(AUD_Sound* sequencer, float speed_of_sound, | ||||||
|  | 									float factor, AUD_DistanceModel model); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Sets the audio output specification of the sound scene to the specs of the | ||||||
|  |  * current playback device. | ||||||
|  |  * \param sequencer The sound scene. | ||||||
|  |  */ | ||||||
|  | extern void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Sets the audio output specification of the sound scene. | ||||||
|  |  * \param sequencer The sound scene. | ||||||
|  |  * \param specs The new specification. | ||||||
|  |  */ | ||||||
|  | extern void AUD_setSequencerSpecs(AUD_Sound* sequencer, AUD_Specs specs); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Seeks sequenced sound scene playback. | ||||||
|  |  * \param handle Playback handle. | ||||||
|  |  * \param time Time in seconds to seek to. | ||||||
|  |  */ | ||||||
|  | extern void AUD_seekSequencer(AUD_Handle* handle, float time); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Returns the current sound scene playback time. | ||||||
|  |  * \param handle Playback handle. | ||||||
|  |  * \return The playback time in seconds. | ||||||
|  |  */ | ||||||
|  | extern float AUD_getSequencerPosition(AUD_Handle* handle); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Starts the playback of jack transport if possible. | ||||||
|  |  */ | ||||||
| extern void AUD_startPlayback(void); | extern void AUD_startPlayback(void); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Stops the playback of jack transport if possible. | ||||||
|  |  */ | ||||||
| extern void AUD_stopPlayback(void); | extern void AUD_stopPlayback(void); | ||||||
|  |  | ||||||
| extern void AUD_seekSequencer(AUD_Channel* handle, float time); |  | ||||||
|  |  | ||||||
| extern float AUD_getSequencerPosition(AUD_Channel* handle); |  | ||||||
|  |  | ||||||
| #ifdef WITH_JACK | #ifdef WITH_JACK | ||||||
|  | /** | ||||||
|  |  * Sets the sync callback for jack transport. | ||||||
|  |  * \param function The callback function. | ||||||
|  |  * \param data The data parameter for the callback. | ||||||
|  |  */ | ||||||
| extern void AUD_setSyncCallback(AUD_syncFunction function, void* data); | extern void AUD_setSyncCallback(AUD_syncFunction function, void* data); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Returns whether jack transport is currently playing. | ||||||
|  |  * \return Whether jack transport is currently playing. | ||||||
|  |  */ | ||||||
| extern int AUD_doesPlayback(void); | extern int AUD_doesPlayback(void); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Reads a sound into a buffer for drawing at a specific sampling rate. | ||||||
|  |  * \param sound The sound to read. | ||||||
|  |  * \param buffer The buffer to write to. Must have a size of 3*4*length. | ||||||
|  |  * \param length How many samples to read from the sound. | ||||||
|  |  * \param samples_per_second How many samples to read per second of the sound. | ||||||
|  |  * \return How many samples really have been read. Always <= length. | ||||||
|  |  */ | ||||||
|  | extern int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length, int samples_per_second); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Copies a sound. | ||||||
|  |  * \param sound Sound to copy. | ||||||
|  |  * \return Copied sound. | ||||||
|  |  */ | ||||||
|  | extern AUD_Sound* AUD_copy(AUD_Sound* sound); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Frees a handle. | ||||||
|  |  * \param channel Handle to free. | ||||||
|  |  */ | ||||||
|  | extern void AUD_freeHandle(AUD_Handle* channel); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Creates a new set. | ||||||
|  |  * \return The new set. | ||||||
|  |  */ | ||||||
|  | extern void* AUD_createSet(void); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Deletes a set. | ||||||
|  |  * \param set The set to delete. | ||||||
|  |  */ | ||||||
|  | extern void AUD_destroySet(void* set); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Removes an entry from a set. | ||||||
|  |  * \param set The set work on. | ||||||
|  |  * \param entry The entry to remove. | ||||||
|  |  * \return Whether the entry was in the set or not. | ||||||
|  |  */ | ||||||
|  | extern char AUD_removeSet(void* set, void* entry); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Adds a new entry to a set. | ||||||
|  |  * \param set The set work on. | ||||||
|  |  * \param entry The entry to add. | ||||||
|  |  */ | ||||||
|  | extern void AUD_addSet(void* set, void* entry); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Removes one entry from a set and returns it. | ||||||
|  |  * \param set The set work on. | ||||||
|  |  * \return The entry or NULL if the set is empty. | ||||||
|  |  */ | ||||||
|  | extern void* AUD_getSet(void* set); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Mixes a sound down into a file. | ||||||
|  |  * \param sound The sound scene to mix down. | ||||||
|  |  * \param start The start frame. | ||||||
|  |  * \param length The count of frames to write. | ||||||
|  |  * \param buffersize How many samples should be written at once. | ||||||
|  |  * \param filename The file to write to. | ||||||
|  |  * \param specs The file's audio specification. | ||||||
|  |  * \param format The file's container format. | ||||||
|  |  * \param codec The codec used for encoding the audio data. | ||||||
|  |  * \param bitrate The bitrate for encoding. | ||||||
|  |  * \return An error message or NULL in case of success. | ||||||
|  |  */ | ||||||
|  | extern const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Opens a read device and prepares it for mixdown of the sound scene. | ||||||
|  |  * \param specs Output audio specifications. | ||||||
|  |  * \param sequencer The sound scene to mix down. | ||||||
|  |  * \param volume The overall mixdown volume. | ||||||
|  |  * \param start The start time of the mixdown in the sound scene. | ||||||
|  |  * \return The read device for the mixdown. | ||||||
|  |  */ | ||||||
|  | extern AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, float start); | ||||||
|  |  | ||||||
|  | #ifdef WITH_PYTHON | ||||||
|  | /** | ||||||
|  |  * Retrieves the python factory of a sound. | ||||||
|  |  * \param sound The sound factory. | ||||||
|  |  * \return The python factory. | ||||||
|  |  */ | ||||||
|  | extern PyObject* AUD_getPythonFactory(AUD_Sound* sound); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Retrieves the sound factory of a python factory. | ||||||
|  |  * \param sound The python factory. | ||||||
|  |  * \return The sound factory. | ||||||
|  |  */ | ||||||
|  | extern AUD_Sound* AUD_getPythonSound(PyObject* sound); | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #include "AUD_Reference.h" | ||||||
|  | class AUD_IDevice; | ||||||
|  | class AUD_I3DDevice; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Returns the current playback device. | ||||||
|  |  * \return The playback device. | ||||||
|  |  */ | ||||||
|  | AUD_Reference<AUD_IDevice> AUD_getDevice(); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Returns the current playback 3D device. | ||||||
|  |  * \return The playback 3D device. | ||||||
|  |  */ | ||||||
|  | AUD_I3DDevice* AUD_get3DDevice(); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #endif //AUD_CAPI | #endif //AUD_CAPI | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user