packages feed

mediabus-0.3.0.0: specs/Data/MediaBus/Conduit/Audio/Raw/ResampleSpec.hs

module Data.MediaBus.Conduit.Audio.Raw.ResampleSpec
  ( spec
  ) where

import Conduit
import Control.Monad.State.Strict
import Data.Default
import Data.MediaBus
import Test.Hspec
import Test.QuickCheck
import Control.Lens

spec :: Spec
spec =
  describe "Resampling of S16 samples from 8 to 16 kHz" $ do
    it "interpolates between samples" $
      let lastVal = 0
      in property $ \(NonEmpty samples) ->
           mediaBufferToList
             (view
                pcmMediaBuffer
                (resampleAndConsume (singleFrameFromList samples) lastVal)) `shouldBe`
           expectedResamplingResult samples lastVal
    it "interpolates also between frames" $
      let lastVal = 0
      in property $ \samplesLists ->
           mediaBufferToList
             (view
                pcmMediaBuffer
                (resampleAndConsume (framesFromLists samplesLists) lastVal)) `shouldBe`
           expectedResamplingResult (join samplesLists) lastVal

expectedResamplingResult :: [Pcm Mono S16] -> Pcm Mono S16 -> [Pcm Mono S16]
expectedResamplingResult xs lastVal =
  concatMap (\(x, y) -> [pcmAverage x y, y]) (zip (lastVal : xs) xs)

type AudioBuffer r = Audio (Hz r) Mono (Raw S16)

resampleAndConsume
  :: Source Identity (Stream SrcId32 SeqNum32 Ticks32At48000 () (AudioBuffer 8000))
  -> Pcm Mono S16
  -> AudioBuffer 16000
resampleAndConsume vvv lastVal =
  runConduitPure (vvv .| resample8to16kHz' lastVal .| concatStreamContents)

singleFrameFromList
  :: Monad m
  => [Pcm Mono S16]
  -> Source m (Stream SrcId32 SeqNum32 Ticks32At48000 () (AudioBuffer 8000))
singleFrameFromList x =
  mapOutput
    (MkStream . Next)
    (mapOutput (MkFrame () def) (yield (pcmMediaBuffer # mediaBufferFromList x)) .|
     deriveFrameTimestamp 0)

framesFromLists
  :: Monad m
  => [[Pcm Mono S16]]
  -> Source m (Stream SrcId32 SeqNum32 Ticks32At48000 () (AudioBuffer 8000))
framesFromLists xs =
  mapOutput
    (MkStream . Next)
    (mapOutput (MkFrame () def) (mapM_ (yield . view (from pcmMediaBuffer) . mediaBufferFromList) xs) .|
     deriveFrameTimestamp 0)