packages feed

HGamer3D-0.2.0: HGamer3D/APIs/Base/Audio/Audio.hs

-- This source file is part of HGamer3D
-- (A project to enable 3D game development in Haskell)
-- For the latest info, see http://www.althainz.de/HGamer3D.html
--
-- (c) 2011 Peter Althainz
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.

-- Audio.hs

-- |Base API, Audio Module, Audio Sub-Module.
-- Basic Audio functionality of the HGamer3D engine.


module HGamer3D.APIs.Base.Audio.Audio

(
	-- Enums
	--
	module HGamer3D.Bindings.SFML.EnumSoundSourceStatus,
	
	
	-- Data
	--
	AudioSource (..), 
	
	-- Listener Functions
	setAudioMainVolume,
	getAudioMainVolume,
	setAudioListenerPosition,
	setAudioListenerDirection,

	
	-- Source creation and delete Functions
	createMusic,
	createSound,
	deleteAudioSource,
	
	-- Source play function
	playAudioSource,
	pauseAudioSource,
	stopAudioSource,
	setAudioSourceLoop,
	getAudioSourceLoop,

	-- Source Functions
	getAudioSourceVolume,
	setAudioSourceVolume,

	getAudioSourcePitch,
	setAudioSourcePitch,

	getAudioSourcePosition,
	setAudioSourcePosition,

	getAudioSourceAttenuation,
	setAudioSourceAttenuation,

	getAudioSourceMinDistance,
	setAudioSourceMinDistance,

	setAudioSourcePositionDependent,
	isAudioSourcePositionDependent,
	
)

where

import GHC.Ptr

import HGamer3D.APIs.Base.Engine.Types

import HGamer3D.Bindings.SFML.ClassPtr
import HGamer3D.Bindings.SFML.Utils

import qualified HGamer3D.Bindings.SFML.ClassListener as Listener
import qualified HGamer3D.Bindings.SFML.ClassMusic as Music 
import qualified HGamer3D.Bindings.SFML.ClassSound as Sound
import qualified HGamer3D.Bindings.SFML.ClassSoundBuffer as SoundBuffer
import qualified HGamer3D.Bindings.SFML.ClassSoundSource as SoundSource
import qualified HGamer3D.Bindings.SFML.ClassSoundStream as SoundStream
import HGamer3D.Bindings.SFML.EnumSoundSourceStatus

import HGamer3D.Data.HG3DClass
import Control.Monad.Trans
import Control.Monad.Reader
import HGamer3D.Data.Vector

-- Source types

data AudioSource = Music HG3DClass | Sound HG3DClass HG3DClass


-- Listener Functions

-- | set overall main audio volume
setAudioMainVolume :: Float -- ^volume in a scale between 0 and 100.0
					-> MHGamer3D ()
setAudioMainVolume vol = liftIO $ Listener.setGlobalVolume vol

-- | get overall main audio volume
getAudioMainVolume :: MHGamer3D Float
getAudioMainVolume = liftIO $ Listener.getGlobalVolume

-- | set position of the listener, this is where the "micro" is located
setAudioListenerPosition :: Vec3 -- ^position of listener
							-> MHGamer3D ()
setAudioListenerPosition (Vec3 x y z) = liftIO $ Listener.setPosition x y z

-- | set direction of the listener, this is in which direction the listener hears
setAudioListenerDirection :: Vec3 -> MHGamer3D ()
setAudioListenerDirection (Vec3 x y z) = liftIO $ Listener.setDirection x y z


-- Music Functions, deletion and cretion of Audio types
--

-- | create music with filename, music is buffered stream
createMusic :: String -- ^filename of music without path
			-> MHGamer3D (Maybe AudioSource) -- ^audio source, which can be played
createMusic filename = do
	music <- liftIO $ Music.new
	rs <- ask
	let cs = commonSystem rs
	let dir = (csHG3DPath cs)
	let progdir = (csProgPath cs)
	-- first try in runtime folder
	fOk <- liftIO $ Music.openFromFile music (dir ++ "\\media\\sound\\" ++ filename)
	if fOk then
		return (Just (Music music))
		else do
			fOk <- liftIO $ Music.openFromFile music (progdir ++ "\\media\\sound\\" ++ filename)
			if fOk then
				return (Just (Music music))
				else do
					liftIO $ Music.delete music
					return Nothing

-- | create sound with filename, sound is not buffered but loaded completely into memory
createSound :: String -- ^filename of sound without path
					-> MHGamer3D (Maybe AudioSource) -- ^audio source, which can be played
createSound filename = do
	sound <- liftIO $ Sound.new
	buffer <- liftIO $ SoundBuffer.new
	rs <- ask
	let cs = commonSystem rs
	let dir = (csHG3DPath cs)
	let progdir = (csProgPath cs)
	fOk <- liftIO $ SoundBuffer.loadFromFile buffer (dir ++ "\\media\\sound\\" ++ filename)
	if fOk then do
		liftIO $ Sound.setBuffer sound buffer		
		return (Just (Sound sound buffer))
		else do
		fOk <- liftIO $ SoundBuffer.loadFromFile buffer (progdir ++ "\\media\\sound\\" ++ filename)
		if fOk then do
			liftIO $ Sound.setBuffer sound buffer		
			return (Just (Sound sound buffer))
			else do
				liftIO $ Sound.delete sound
				liftIO $ SoundBuffer.delete buffer
				return Nothing

deleteAudioSource :: AudioSource -> MHGamer3D ()
deleteAudioSource (Music music) = do
	liftIO $ Music.delete music
deleteAudioSource (Sound sound buffer) = do
	liftIO $ Sound.delete sound
	liftIO $ SoundBuffer.delete buffer


-- Source play, pause, stop
--

-- | starts playing audio, which can be music or sound
playAudioSource :: AudioSource -- ^the audio source
					-> MHGamer3D ()
playAudioSource (Music music) = do
	liftIO $ SoundStream.play music
playAudioSource (Sound sound buffer) = do
	liftIO $ Sound.play sound

-- | pause playing audio, remembers location
pauseAudioSource :: AudioSource -> MHGamer3D ()
pauseAudioSource (Music music) = do
	liftIO $ SoundStream.pause music
pauseAudioSource (Sound sound buffer) = do
	liftIO $ Sound.pause sound

-- | completely stops audio playing
stopAudioSource :: AudioSource -> MHGamer3D ()
stopAudioSource (Music music) = do
	liftIO $ SoundStream.stop music
stopAudioSource (Sound sound buffer) = do
	liftIO $ Sound.stop sound

-- | is audio play looping
getAudioSourceLoop :: AudioSource -- ^audio source
				-> MHGamer3D Bool -- ^true, loop is enabled, false loop is disabled
getAudioSourceLoop (Music music) = do
	fLoop <- liftIO $ SoundStream.getLoop music
	return fLoop
getAudioSourceLoop (Sound sound buffer) = do
	fLoop <- liftIO $ Sound.getLoop sound
	return fLoop

-- | set audio play is looping
setAudioSourceLoop :: AudioSource -- ^audio source
				-> Bool -- ^loop enabled
				-> MHGamer3D ()
setAudioSourceLoop (Music music) fLoop = do
	liftIO $ SoundStream.setLoop music fLoop
setAudioSourceLoop (Sound sound buffer) fLoop = do
	liftIO $ Sound.setLoop sound fLoop


-- Sound Source Functions
--

-- | get volume of a single audio source
getAudioSourceVolume :: AudioSource -- ^audio source
					-> MHGamer3D Float -- ^volume of audio source in scale of 0 to 100.0
					
getAudioSourceVolume (Music s) = liftIO $ SoundSource.getVolume s
getAudioSourceVolume (Sound s b) = liftIO $ SoundSource.getVolume s

-- | set volume of a single audio source
setAudioSourceVolume :: AudioSource -- ^audio source
				-> Float -> MHGamer3D () -- ^volume of this audio source in scale of 0 to 100.0
				
setAudioSourceVolume (Music s) v = liftIO $ SoundSource.setVolume s v
setAudioSourceVolume (Sound s b) v = liftIO $ SoundSource.setVolume s v

-- | get audio source pitch, the pitch is the frequency of the sound which also influences playing speed. The default value is 1.0.
getAudioSourcePitch :: AudioSource -- ^audio source
				-> MHGamer3D Float -- ^pitch, a 1.0 is no change to original sound
				
getAudioSourcePitch (Music s) = liftIO $ SoundSource.getPitch s
getAudioSourcePitch (Sound s b) = liftIO $ SoundSource.getPitch s

-- | sets the pitch of an audio source
setAudioSourcePitch :: AudioSource -> Float -> MHGamer3D ()
setAudioSourcePitch (Music s) p = liftIO $ SoundSource.setPitch s p
setAudioSourcePitch (Sound s b) p = liftIO $ SoundSource.setPitch s p

-- | sets the position of an audio source
setAudioSourcePosition :: AudioSource -- ^audio source
					-> Vec3 -> MHGamer3D () -- ^new position of this source
					
setAudioSourcePosition (Music s) (Vec3 x y z) = liftIO $ SoundSource.setPosition s x y z
setAudioSourcePosition (Sound s b) (Vec3 x y z) = liftIO $ SoundSource.setPosition s x y z

-- | gets the position of an audio source
getAudioSourcePosition :: AudioSource -- ^audio source
					-> MHGamer3D Vec3 -- ^position of the audio source
					
getAudioSourcePosition (Music s) = liftIO $ SoundSource.getPosition s
getAudioSourcePosition (Sound s b) = liftIO $ SoundSource.getPosition s

-- | gets the attenuation factor of an audio source
getAudioSourceAttenuation :: AudioSource -- ^audio source
			-> MHGamer3D Float -- ^attenuation is the damping factor by distance, default value is 1.0, 0.0 means no damping
getAudioSourceAttenuation (Music s) = liftIO $ SoundSource.getAttenuation s
getAudioSourceAttenuation (Sound s b) = liftIO $ SoundSource.getAttenuation s

-- | sets the attenuation factor of an audio source
setAudioSourceAttenuation :: AudioSource -- ^audio source
				-> Float -> MHGamer3D () -- ^attenuation factor
setAudioSourceAttenuation (Music s) a = liftIO $ SoundSource.setAttenuation s a
setAudioSourceAttenuation (Sound s b) a = liftIO $ SoundSource.setAttenuation s a

-- | gets audio source min distance, distance at which sound is played a volume 100.0
getAudioSourceMinDistance :: AudioSource -> MHGamer3D Float
getAudioSourceMinDistance (Music s) = liftIO $ SoundSource.getMinDistance s
getAudioSourceMinDistance (Sound s b) = liftIO $ SoundSource.getMinDistance s

-- | sets audio source min distance, distance at which sound is played a volume 100.0
setAudioSourceMinDistance :: AudioSource -> Float -> MHGamer3D ()
setAudioSourceMinDistance (Music s) d = liftIO $ SoundSource.setMinDistance s d
setAudioSourceMinDistance (Sound s b) d = liftIO $ SoundSource.setMinDistance s d

-- | set flag if audio source depends on position, default is FALSE (not dependent on position)
setAudioSourcePositionDependent :: AudioSource -> Bool -> MHGamer3D ()
setAudioSourcePositionDependent (Music s) isR = liftIO $ SoundSource.setRelativeToListener s isR
setAudioSourcePositionDependent (Sound s b) isR = liftIO $ SoundSource.setRelativeToListener s isR

-- | get flag if audio source depends on position, default is FALSE (not dependent on position)
isAudioSourcePositionDependent :: AudioSource -> MHGamer3D Bool
isAudioSourcePositionDependent (Music s) = liftIO $ SoundSource.isRelativeToListener s
isAudioSourcePositionDependent (Sound s b) = liftIO $ SoundSource.isRelativeToListener s