-------------------------------------------------------------------------------- -- | -- Module : Sound.ALUT.Loaders -- Copyright : (c) Sven Panne 2005-2013 -- License : BSD3 -- -- Maintainer : Sven Panne -- Stability : stable -- Portability : portable -- -------------------------------------------------------------------------------- module Sound.ALUT.Loaders ( Phase, Duration, SoundDataSource(..), createBuffer, createBufferData, bufferMIMETypes, bufferDataMIMETypes ) where import Foreign.C.String ( peekCString, withCString ) import Foreign.Marshal.Alloc ( alloca ) import Foreign.Storable ( Storable(peek) ) import Foreign.Ptr ( Ptr ) import Graphics.Rendering.OpenGL ( GettableStateVar, makeGettableStateVar ) import Sound.ALUT.Config ( alut_CreateBufferFromFile, alut_CreateBufferFromFileImage, alut_CreateBufferHelloWorld, alut_CreateBufferWaveform, alut_LoadMemoryFromFile, alut_LoadMemoryFromFileImage, alut_LoadMemoryHelloWorld, alut_LoadMemoryWaveform, alut_GetMIMETypes ) import Sound.ALUT.Constants ( alut_WAVEFORM_SINE, alut_WAVEFORM_SQUARE, alut_WAVEFORM_SAWTOOTH, alut_WAVEFORM_IMPULSE, alut_WAVEFORM_WHITENOISE, alut_LOADER_BUFFER, alut_LOADER_MEMORY ) import Sound.ALUT.Errors ( makeBuffer, throwIfNullPtr ) import Sound.OpenAL.AL.BasicTypes import Sound.OpenAL.AL.Buffer ( Buffer, MemoryRegion(..), BufferData(..) ) import Sound.OpenAL.AL.Format ( unmarshalFormat ) import Sound.OpenAL.ALC.Context ( Frequency ) -------------------------------------------------------------------------------- type Phase = Float type Duration = Float data SoundDataSource a = File FilePath | FileImage (MemoryRegion a) | HelloWorld | Sine Frequency Phase Duration | Square Frequency Phase Duration | Sawtooth Frequency Phase Duration | Impulse Frequency Phase Duration | WhiteNoise Duration deriving ( Eq, Ord, Show ) -------------------------------------------------------------------------------- createBuffer :: SoundDataSource a -> IO Buffer createBuffer src = makeBuffer "createBuffer" $ case src of File filePath -> withCString filePath alut_CreateBufferFromFile FileImage (MemoryRegion buf size) -> alut_CreateBufferFromFileImage buf size HelloWorld -> alut_CreateBufferHelloWorld Sine f p d -> createBufferWaveform alut_WAVEFORM_SINE f p d Square f p d -> createBufferWaveform alut_WAVEFORM_SQUARE f p d Sawtooth f p d -> createBufferWaveform alut_WAVEFORM_SAWTOOTH f p d Impulse f p d -> createBufferWaveform alut_WAVEFORM_IMPULSE f p d WhiteNoise d -> createBufferWaveform alut_WAVEFORM_WHITENOISE 1 0 d createBufferWaveform :: ALenum -> Float -> Float -> Float -> IO ALuint createBufferWaveform w f p d = alut_CreateBufferWaveform w (realToFrac f) (realToFrac p) (realToFrac d) -------------------------------------------------------------------------------- createBufferData :: SoundDataSource a -> IO (BufferData b) createBufferData src = case src of File filePath -> withCString filePath $ \fp -> loadWith (alut_LoadMemoryFromFile fp) FileImage (MemoryRegion buf size) -> loadWith (alut_LoadMemoryFromFileImage buf size) HelloWorld -> loadWith alut_LoadMemoryHelloWorld Sine f p d -> loadWith (loadMemoryWaveform alut_WAVEFORM_SINE f p d) Square f p d -> loadWith (loadMemoryWaveform alut_WAVEFORM_SQUARE f p d) Sawtooth f p d -> loadWith (loadMemoryWaveform alut_WAVEFORM_SAWTOOTH f p d) Impulse f p d -> loadWith (loadMemoryWaveform alut_WAVEFORM_IMPULSE f p d) WhiteNoise d -> loadWith (loadMemoryWaveform alut_WAVEFORM_WHITENOISE 1 0 d) loadMemoryWaveform :: ALenum -> Float -> Float -> Float -> Ptr ALenum -> Ptr ALsizei -> Ptr ALfloat -> IO (Ptr b) loadMemoryWaveform w f p d = alut_LoadMemoryWaveform w (realToFrac f) (realToFrac p) (realToFrac d) loadWith :: (Ptr ALenum -> Ptr ALsizei -> Ptr ALfloat -> IO (Ptr b)) -> IO (BufferData b) loadWith loader = alloca $ \formatBuf -> alloca $ \sizeBuf -> alloca $ \frequencyBuf -> do buf <- throwIfNullPtr "createBufferData" $ loader formatBuf sizeBuf frequencyBuf format <- peek formatBuf size <- peek sizeBuf frequency <- peek frequencyBuf return $ BufferData (MemoryRegion buf size) (unmarshalFormat format) (realToFrac frequency) -------------------------------------------------------------------------------- bufferMIMETypes :: GettableStateVar [String] bufferMIMETypes = mimeTypes "bufferMIMETypes" alut_LOADER_BUFFER bufferDataMIMETypes :: GettableStateVar [String] bufferDataMIMETypes = mimeTypes "bufferDataMIMETypes" alut_LOADER_MEMORY mimeTypes :: String -> ALenum -> GettableStateVar [String] mimeTypes name loaderType = makeGettableStateVar $ do ts <- throwIfNullPtr name $ alut_GetMIMETypes loaderType fmap (splitBy (== ',')) $ peekCString ts splitBy :: (a -> Bool) -> [a] -> [[a]] splitBy _ [] = [] splitBy p xs = case break p xs of (ys, [] ) -> [ys] (ys, _:zs) -> ys : splitBy p zs