module Synthesizer.Storable.ALSA.Play (
auto,
autoAndRecord,
monoToInt16,
stereoToInt16,
defaultChunkSize,
) where
import qualified Sound.ALSA.PCM as ALSA
import qualified Synthesizer.Frame.Stereo as Stereo
import qualified Synthesizer.Basic.Binary as BinSmp
import qualified Sound.Sox.Frame as SoxFrame
import qualified Sound.Sox.Write as SoxWrite
import qualified Sound.Sox.Option.Format as SoxOption
import Foreign.Storable (Storable, )
import Foreign.Marshal.Array (advancePtr, )
import Foreign.Ptr (Ptr, minusPtr, )
import qualified System.IO as IO
import qualified Synthesizer.Storable.Signal as SigSt
import qualified Data.StorableVector.Lazy as SVL
import qualified Data.StorableVector.Base as SVB
import qualified Algebra.RealRing as RealRing
import NumericPrelude.Numeric
import NumericPrelude.Base
defaultChunkSize :: SigSt.ChunkSize
defaultChunkSize = SigSt.chunkSize 256
makeSink ::
(ALSA.SampleFmt y, RealRing.C t) =>
t ->
ALSA.SampleFreq ->
ALSA.SoundSink y ALSA.Pcm
makeSink periodTime rate =
let
soundFormat :: ALSA.SoundFmt y
soundFormat =
ALSA.SoundFmt {
ALSA.sampleFreq = rate
}
in ALSA.alsaSoundSinkTime "plughw:0,0" soundFormat $
ALSA.SoundBufferTime
(round (5000000*periodTime))
(round (1000000*periodTime))
auto ::
(ALSA.SampleFmt y, RealRing.C t) =>
t ->
ALSA.SampleFreq ->
SigSt.T y -> IO ()
auto periodTime rate ys =
let sink = makeSink periodTime rate
in ALSA.withSoundSink sink $ \to ->
flip mapM_ (SVL.chunks ys) $ \c ->
SVB.withStartPtr c $ \ptr size ->
ALSA.soundSinkWrite sink to ptr size
arraySize :: Storable y => Ptr y -> Int -> Int
arraySize p n = advancePtr p n `minusPtr` p
autoAndRecord ::
(ALSA.SampleFmt y, SoxFrame.C y, RealRing.C t) =>
t ->
FilePath ->
ALSA.SampleFreq ->
SigSt.T y -> IO ()
autoAndRecord periodTime fileName rate =
let sink = makeSink periodTime rate
in (\act ->
fmap (const ()) .
SoxWrite.simple act SoxOption.none fileName rate) $ \h ys ->
ALSA.withSoundSink sink $ \to ->
flip mapM_ (SVL.chunks ys) $ \c ->
SVB.withStartPtr c $ \ptr size ->
ALSA.soundSinkWrite sink to ptr size >>
IO.hPutBuf h ptr (arraySize ptr size)
monoToInt16 ::
(Storable y, RealRing.C y, RealRing.C t) =>
t ->
ALSA.SampleFreq ->
SigSt.T y -> IO ()
monoToInt16 periodTime rate xs =
auto periodTime rate
(SigSt.map BinSmp.int16FromCanonical xs)
stereoToInt16 ::
(Storable y, RealRing.C y, RealRing.C t) =>
t ->
ALSA.SampleFreq ->
SigSt.T (Stereo.T y) -> IO ()
stereoToInt16 periodTime rate xs =
auto periodTime rate
(SigSt.map (fmap BinSmp.int16FromCanonical) xs)