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.GL.StateVar (
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 ( ALsizei, ALenum, ALfloat )
import Sound.OpenAL.AL.Buffer ( Buffer, MemoryRegion(..), BufferData(..) )
import Sound.OpenAL.AL.Format ( unmarshalFormat )
import Sound.OpenAL.ALC.Context ( Frequency )
import System.IO ( FilePath )
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
#ifdef __HADDOCK__
instance Eq (SoundDataSource a)
instance Ord (SoundDataSource a)
instance Show (SoundDataSource a)
#else
deriving ( Eq, Ord, Show )
#endif
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 -> alut_CreateBufferWaveform alut_WAVEFORM_SINE f p d
Square f p d -> alut_CreateBufferWaveform alut_WAVEFORM_SQUARE f p d
Sawtooth f p d -> alut_CreateBufferWaveform alut_WAVEFORM_SAWTOOTH f p d
Impulse f p d -> alut_CreateBufferWaveform alut_WAVEFORM_IMPULSE f p d
WhiteNoise d -> alut_CreateBufferWaveform alut_WAVEFORM_WHITENOISE 1 0 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 (alut_LoadMemoryWaveform alut_WAVEFORM_SINE f p d)
Square f p d -> loadWith (alut_LoadMemoryWaveform alut_WAVEFORM_SQUARE f p d)
Sawtooth f p d -> loadWith (alut_LoadMemoryWaveform alut_WAVEFORM_SAWTOOTH f p d)
Impulse f p d -> loadWith (alut_LoadMemoryWaveform alut_WAVEFORM_IMPULSE f p d)
WhiteNoise d -> loadWith (alut_LoadMemoryWaveform alut_WAVEFORM_WHITENOISE 1 0 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) 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