module Data.MediaBus.Audio.Channels ( ChannelLayout(..) , ChannelPair(..) , leftSample , rightSample , HasChannelLayout(..) ) where import Control.Lens import Foreign.Storable import Data.MediaBus.Ticks import Data.MediaBus.BlankMedia import Test.QuickCheck import Data.Proxy import GHC.Generics ( Generic ) import Control.DeepSeq data ChannelLayout = SingleChannel | ChannelPair deriving (Show, Eq, Ord, Enum, Generic) instance (CanBeBlank r) => CanBeBlank (ChannelPair r) where blank = MkChannelPair blank blank instance NFData ChannelLayout class HasChannelLayout c where channelLayout :: c -> ChannelLayout data ChannelPair a = MkChannelPair { _leftSample :: a , _rightSample :: a } deriving (Show, Eq, Ord, Generic) instance NFData a => NFData (ChannelPair a) instance Arbitrary a => Arbitrary (ChannelPair a) where arbitrary = MkChannelPair <$> arbitrary <*> arbitrary makeLenses ''ChannelPair instance HasChannelLayout a => HasChannelLayout (ChannelPair a) where channelLayout MkChannelPair{_leftSample,_rightSample} = case (channelLayout _leftSample, channelLayout _rightSample) of (SingleChannel, SingleChannel) -> ChannelPair other -> error ("Sorry this channel layout is not supported: " ++ show other) instance (HasDuration (Proxy a)) => HasDuration (Proxy (ChannelPair a)) where getDuration _ = getDuration (Proxy :: Proxy a) instance Storable s => Storable (ChannelPair s) where sizeOf s = 2 * sizeOf s alignment = alignment peekByteOff ptr off = do l <- peekByteOff ptr off let rOffset = sizeOf l r <- peekByteOff ptr (rOffset + off) return (MkChannelPair l r) pokeByteOff ptr off (MkChannelPair l r) = do pokeByteOff ptr off l let rOffset = sizeOf l pokeByteOff ptr (off + rOffset) r