{-# LINE 1 "src/Codec/Audio/Opus/Internal/Opus.hsc" #-}
{-# LANGUAGE CPP                      #-}
{-# LANGUAGE ForeignFunctionInterface #-}
-- | This module contains the raw FFI bindings to the Opus library. It is not
-- meant to be consumed directly by users of this library, but rather to be
-- used by the higher-level API in "Codec.Audio.Opus".
module Codec.Audio.Opus.Internal.Opus where

import           Foreign
import           Foreign.C.Types
import           Foreign.C.String



-- | Raw error codes returned by the Opus library, represented as an int.
newtype ErrorCode = ErrorCode { ErrorCode -> CInt
unErrorCode :: CInt }
    deriving (ErrorCode -> ErrorCode -> Bool
(ErrorCode -> ErrorCode -> Bool)
-> (ErrorCode -> ErrorCode -> Bool) -> Eq ErrorCode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ErrorCode -> ErrorCode -> Bool
== :: ErrorCode -> ErrorCode -> Bool
$c/= :: ErrorCode -> ErrorCode -> Bool
/= :: ErrorCode -> ErrorCode -> Bool
Eq, Int -> ErrorCode -> ShowS
[ErrorCode] -> ShowS
ErrorCode -> String
(Int -> ErrorCode -> ShowS)
-> (ErrorCode -> String)
-> ([ErrorCode] -> ShowS)
-> Show ErrorCode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ErrorCode -> ShowS
showsPrec :: Int -> ErrorCode -> ShowS
$cshow :: ErrorCode -> String
show :: ErrorCode -> String
$cshowList :: [ErrorCode] -> ShowS
showList :: [ErrorCode] -> ShowS
Show)

-- | Storable instance for 'ErrorCode' which is necessary for using it an
-- argument in FFI calls.
instance Storable ErrorCode where
  sizeOf :: ErrorCode -> Int
sizeOf (ErrorCode CInt
e) = CInt -> Int
forall a. Storable a => a -> Int
sizeOf CInt
e
  alignment :: ErrorCode -> Int
alignment (ErrorCode CInt
e) = CInt -> Int
forall a. Storable a => a -> Int
alignment CInt
e
  peek :: Ptr ErrorCode -> IO ErrorCode
peek Ptr ErrorCode
p = CInt -> ErrorCode
ErrorCode (CInt -> ErrorCode) -> IO CInt -> IO ErrorCode
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr CInt -> IO CInt
forall a. Storable a => Ptr a -> IO a
peek (Ptr ErrorCode -> Ptr CInt
forall a b. Ptr a -> Ptr b
castPtr Ptr ErrorCode
p)
  poke :: Ptr ErrorCode -> ErrorCode -> IO ()
poke Ptr ErrorCode
p = Ptr CInt -> CInt -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke (Ptr ErrorCode -> Ptr CInt
forall a b. Ptr a -> Ptr b
castPtr Ptr ErrorCode
p) (CInt -> IO ()) -> (ErrorCode -> CInt) -> ErrorCode -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ErrorCode -> CInt
unErrorCode

-- | libopus error: No error.
opus_ok :: ErrorCode
opus_ok :: ErrorCode
opus_ok = CInt -> ErrorCode
ErrorCode (CInt
0)
{-# LINE 29 "src/Codec/Audio/Opus/Internal/Opus.hsc" #-}

-- | libopus error: One or more invalid/out of range arguments.
opus_bad_arg :: ErrorCode
opus_bad_arg :: ErrorCode
opus_bad_arg = CInt -> ErrorCode
ErrorCode (-CInt
1)
{-# LINE 33 "src/Codec/Audio/Opus/Internal/Opus.hsc" #-}

-- | libopus error: Not enough bytes allocated in the buffer.
opus_buffer_too_small :: ErrorCode
opus_buffer_too_small :: ErrorCode
opus_buffer_too_small = CInt -> ErrorCode
ErrorCode (-CInt
2)
{-# LINE 37 "src/Codec/Audio/Opus/Internal/Opus.hsc" #-}

-- | libopus error: An internal error was detected.
opus_internal_error :: ErrorCode
opus_internal_error :: ErrorCode
opus_internal_error = CInt -> ErrorCode
ErrorCode (-CInt
3)
{-# LINE 41 "src/Codec/Audio/Opus/Internal/Opus.hsc" #-}

-- | libopus error: The compressed data passed is corrupted.
opus_invalid_packet :: ErrorCode
opus_invalid_packet :: ErrorCode
opus_invalid_packet = CInt -> ErrorCode
ErrorCode (-CInt
4)
{-# LINE 45 "src/Codec/Audio/Opus/Internal/Opus.hsc" #-}

-- | libopus error: Invalid/unsupported request number.
opus_unimplemented :: ErrorCode
opus_unimplemented :: ErrorCode
opus_unimplemented = CInt -> ErrorCode
ErrorCode (-CInt
5)
{-# LINE 49 "src/Codec/Audio/Opus/Internal/Opus.hsc" #-}

-- | libopus error: An encoder or decoder structure is invalid or already freed.
opus_invalid_state :: ErrorCode
opus_invalid_state :: ErrorCode
opus_invalid_state = CInt -> ErrorCode
ErrorCode (-CInt
6)
{-# LINE 53 "src/Codec/Audio/Opus/Internal/Opus.hsc" #-}

-- | libopus error: Memory allocation has failed.
opus_alloc_fail :: ErrorCode
opus_alloc_fail :: ErrorCode
opus_alloc_fail = CInt -> ErrorCode
ErrorCode (-CInt
7)
{-# LINE 57 "src/Codec/Audio/Opus/Internal/Opus.hsc" #-}

-- | Coding mode for the Opus encoder, represented as an int.
newtype CodingMode = CodingMode { CodingMode -> CInt
unCodingMode :: CInt }
    deriving (CodingMode -> CodingMode -> Bool
(CodingMode -> CodingMode -> Bool)
-> (CodingMode -> CodingMode -> Bool) -> Eq CodingMode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CodingMode -> CodingMode -> Bool
== :: CodingMode -> CodingMode -> Bool
$c/= :: CodingMode -> CodingMode -> Bool
/= :: CodingMode -> CodingMode -> Bool
Eq)

-- | Show instance for 'CodingMode'.
instance Show CodingMode where
  show :: CodingMode -> String
show CodingMode
a
    | CodingMode
app_voip CodingMode -> CodingMode -> Bool
forall a. Eq a => a -> a -> Bool
== CodingMode
a = String
"voip coding"
    | CodingMode
app_audio CodingMode -> CodingMode -> Bool
forall a. Eq a => a -> a -> Bool
== CodingMode
a = String
"audio coding"
    | CodingMode
app_lowdelay CodingMode -> CodingMode -> Bool
forall a. Eq a => a -> a -> Bool
== CodingMode
a = String
"lowdelay coding"
    | Bool
otherwise = String
"unknown coding"

-- | Best for most VoIP/videoconference applications where listening quality and
-- intelligibility matter most.
app_voip :: CodingMode
app_voip :: CodingMode
app_voip = CInt -> CodingMode
CodingMode (CInt
2048)
{-# LINE 74 "src/Codec/Audio/Opus/Internal/Opus.hsc" #-}

-- | Best for broadcast/high-fidelity application where the decoded audio should
-- be as close as possible to the input.
app_audio :: CodingMode
app_audio :: CodingMode
app_audio = CInt -> CodingMode
CodingMode (CInt
2049)
{-# LINE 79 "src/Codec/Audio/Opus/Internal/Opus.hsc" #-}

-- | Only use when lowest-achievable latency is what matters most.
app_lowdelay :: CodingMode
app_lowdelay :: CodingMode
app_lowdelay = CInt -> CodingMode
CodingMode (CInt
2051)
{-# LINE 83 "src/Codec/Audio/Opus/Internal/Opus.hsc" #-}

-- | Sampling rate for the Opus encoder, represented as an int.
newtype SamplingRate = SamplingRate { SamplingRate -> Int
unSamplingRate :: Int }
    deriving (SamplingRate -> SamplingRate -> Bool
(SamplingRate -> SamplingRate -> Bool)
-> (SamplingRate -> SamplingRate -> Bool) -> Eq SamplingRate
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SamplingRate -> SamplingRate -> Bool
== :: SamplingRate -> SamplingRate -> Bool
$c/= :: SamplingRate -> SamplingRate -> Bool
/= :: SamplingRate -> SamplingRate -> Bool
Eq)

-- | Show instance for 'SamplingRate' makes it human-readable.
instance Show SamplingRate where
  show :: SamplingRate -> String
show (SamplingRate Int
r) = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [Int -> String
forall a. Show a => a -> String
show (Int -> String) -> Int -> String
forall a b. (a -> b) -> a -> b
$ Int
r Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
1000, String
"kHz"]

-- | Sampling rate 8kHz
opusSR8k :: SamplingRate
opusSR8k :: SamplingRate
opusSR8k = Int -> SamplingRate
SamplingRate Int
8000

-- | Sampling rate 12kHz
opusSR12k :: SamplingRate
opusSR12k :: SamplingRate
opusSR12k = Int -> SamplingRate
SamplingRate Int
12000

-- | Sampling rate 16kHz
opusSR16k :: SamplingRate
opusSR16k :: SamplingRate
opusSR16k = Int -> SamplingRate
SamplingRate Int
16000

-- | Sampling rate 24kHz
opusSR24k :: SamplingRate
opusSR24k :: SamplingRate
opusSR24k = Int -> SamplingRate
SamplingRate Int
24000

-- | Sampling rate 48kHz
opusSR48k :: SamplingRate
opusSR48k :: SamplingRate
opusSR48k = Int -> SamplingRate
SamplingRate Int
48000

-- Declare empty (i.e. opaque) data types for the encoder and decoder states.
-- This is not meant to be consumed by Haskell code, but is rather meant to
-- encapsulate the C types that FFI calls return and expect to be passed
-- modified in a subsequent FFI call.
--
-- For example, the encoder state can be created only by 'c_opus_encoder_create',
-- and destroyed by 'cp_opus_encoder_destroy'.

-- | Encoder state. Can be created only by 'c_opus_encoder_create',
-- and destroyed by 'cp_opus_encoder_destroy'.
data EncoderT

-- | Decoder state. Can be created only by 'c_opus_decoder_create',
-- and destroyed by 'cp_opus_decoder_destroy'.
data DecoderT


-- | Allocates and initializes an encoder state.
foreign import ccall unsafe "opus.h opus_encoder_create"
    c_opus_encoder_create
      :: SamplingRate
      -- ^ Sampling rate of input signal (Hz).
      -> Int32
      -- ^ Number of channels (1 or 2) in input signal
      -> CodingMode
      -- ^ Coding mode. (See 'app_voip', 'app_audio', 'app_lowdelay')
      -> Ptr ErrorCode
      -- ^ 'ErrorCode' pointer
      -> IO (Ptr EncoderT)

-- | Frees an 'EncoderT' that has been created using 'c_opus_encoder_create'.
foreign import ccall unsafe "opus.h &opus_encoder_destroy"
    cp_opus_encoder_destroy
      :: FunPtr (Ptr EncoderT -> IO ())

-- | Encode an Opus frame.
foreign import ccall unsafe "opus.h opus_encode"
    c_opus_encode
      :: Ptr EncoderT
      -- ^ Encoder state
      -> Ptr CShort
      -- ^ Input signal
      -> Int32
      -- ^ Frame size
      -> CString
      -- ^ Output payload
      -> Int32
      -- ^ Max data bytes
      -> IO Int32
      -- ^ Number of bytes written or negative in case of error

-- | Allocates and initializes a decoder state.
foreign import ccall unsafe "opus.h opus_decoder_create"
    c_opus_decoder_create
      :: SamplingRate
      -- ^ Sampling rate, same as encoder_create
      -> Int32
      -- ^ Number of channels in input signal
      -> Ptr ErrorCode
      -- ^ 'ErrorCode' pointer
      -> IO (Ptr DecoderT)

-- | Frees a 'DecoderT' that has been created using 'c_opus_decoder_create'.
foreign import ccall unsafe "opus.h &opus_decoder_destroy"
    cp_opus_decoder_destroy
      :: FunPtr (Ptr DecoderT -> IO ())

-- | Decodes an Opus frame.
foreign import ccall unsafe "opus.h opus_decode"
    c_opus_decode
      :: Ptr DecoderT
      -- ^ Decoder state
      -> Ptr CChar
      -- ^ Byte array of compressed data
      -> Int32
      -- ^ Exact number of bytes in the payload
      -> Ptr CShort
      -- ^ Decoded audio data
      -> Int32
      -- ^ Max duration of the frame in samples that can fit
      -> CInt
      -- ^ Flag to request that any in-band forward error correction data be
      -- decoded. If no such data is available, the frame is decoded as if it
      -- were lost.
      -> IO Int32
      -- ^ Number of decoded samples, or negative in case of error