packages feed

sdr 0.1.0.8 → 0.1.0.9

raw patch · 7 files changed

+69/−65 lines, 7 filesdep ~sdrPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: sdr

API changes (from Hackage documentation)

- SDR.FFT: fftw :: (Vector v (Complex CDouble)) => Int -> IO (Pipe (v (Complex CDouble)) (Vector (Complex CDouble)) IO ())
+ SDR.FFT: fftw :: (Vector v (Complex Double)) => Int -> IO (Pipe (v (Complex Double)) (Vector (Complex Double)) IO ())
- SDR.FFT: fftw' :: (Vector v (Complex CDouble)) => Int -> IO (v (Complex CDouble) -> IO (Vector (Complex CDouble)))
+ SDR.FFT: fftw' :: (Vector v (Complex Double)) => Int -> IO (v (Complex Double) -> IO (Vector (Complex Double)))
- SDR.FFT: fftwParallel :: (Vector v (Complex CDouble)) => Int -> Int -> IO (Pipe (v (Complex CDouble)) (Vector (Complex CDouble)) IO ())
+ SDR.FFT: fftwParallel :: (Vector v (Complex Double)) => Int -> Int -> IO (Pipe (v (Complex Double)) (Vector (Complex Double)) IO ())
- SDR.FFT: fftwReal :: (Vector v CDouble) => Int -> IO (Pipe (v CDouble) (Vector (Complex CDouble)) IO ())
+ SDR.FFT: fftwReal :: (Vector v Double) => Int -> IO (Pipe (v Double) (Vector (Complex Double)) IO ())
- SDR.FFT: fftwReal' :: (Vector v CDouble) => Int -> IO (v CDouble -> IO (Vector (Complex CDouble)))
+ SDR.FFT: fftwReal' :: (Vector v Double) => Int -> IO (v Double -> IO (Vector (Complex Double)))
- SDR.FilterDesign: plotFrequency :: [Double] -> IO ()
+ SDR.FilterDesign: plotFrequency :: [Double] -> FilePath -> IO ()

Files

Readme.md view
@@ -2,6 +2,8 @@  A Software Defined Radio library written in Haskell +See the [blog post](https://adamwalker.github.io/Introducing-SDR/).+ # Features * Write software defined radio applications in Haskell * Signal processing blocks can be chained together using the [Pipes](https://hackage.haskell.org/package/pipes) library@@ -23,7 +25,7 @@ # Screenshot A chunk of the FM broadcast spectrum. Captured with an RTLSDR device and drawn as a waterfall using the [Plot](https://github.com/adamwalker/sdr/blob/master/hs_sources/SDR/Plot.hs) module. -![Screenshot](../screenshots/screenshots/screenshot.png?raw=true)+![Screenshot](https://raw.githubusercontent.com/adamwalker/sdr/screenshots/screenshots/screenshot.png?raw=true)   # Getting Started@@ -88,8 +90,8 @@ import           Data.Vector.Generic        as VG  import           Pipes import qualified Pipes.Prelude              as P-import           Foreign.Storable.Complex + import SDR.Filter  import SDR.RTLSDRStream import SDR.Util@@ -107,7 +109,7 @@      info <- lift getCPUInfo -    str  <- sdrStream frequency 1280000 1 (fromIntegral samples * 2)+    str  <- sdrStream (defaultRTLSDRParams frequency 1280000) 1 (fromIntegral samples * 2)      lift $ do @@ -118,7 +120,7 @@         filt <- fastFilterSymR info coeffsAudioFilter          runEffect $   str-                  >-> P.map convertCAVX +                  >-> P.map (interleavedIQUnsignedByteToFloatFast info)                   >-> firDecimator deci samples                    >-> fmDemod                   >-> firResampler resp samples 
benchmarks/Benchmarks.hs view
@@ -11,7 +11,7 @@ import qualified Data.Vector.Generic.Mutable       as VGM import qualified Data.Vector.Storable              as VS import qualified Data.Vector.Storable.Mutable      as VSM-import qualified Data.Vector.Fusion.Stream         as VFS+import qualified Data.Vector.Fusion.Bundle         as VFS import qualified Data.Vector.Fusion.Stream.Monadic as VFSM  import           Foreign.Storable.Complex
hs_sources/SDR/FFT.hs view
@@ -23,6 +23,7 @@ import           Foreign.ForeignPtr import           Control.Concurrent           hiding (yield) import qualified Data.Map                     as Map+import           Data.Coerce  import qualified Data.Vector.Generic          as VG import qualified Data.Vector.Storable         as VS@@ -40,9 +41,9 @@     newForeignPtr fftwFreePtr ptr  -- | Creates a function that performs a complex to complex DFT.-fftw' :: (VG.Vector v (Complex CDouble)) +fftw' :: (VG.Vector v (Complex Double))       => Int -- ^ The size of the input and output buffers-     -> IO (v (Complex CDouble) -> IO (VS.Vector (Complex CDouble)))+     -> IO (v (Complex Double) -> IO (VS.Vector (Complex Double))) fftw' samples = do     ina <- mallocForeignBufferAligned samples     out <- mallocForeignBufferAligned samples@@ -60,24 +61,24 @@          let (fp, offset, length) = VSM.unsafeToForeignPtr inv -        withForeignPtr fp $ \fpp -> -            withForeignPtr out $ \op -> +        withForeignPtr (coerce fp) $ \fpp -> +            withForeignPtr (coerce out) $ \op ->                  executeDFT plan fpp op          return $ VS.unsafeFromForeignPtr0 out samples  -- | Creates a Pipe that performs a complex to complex DFT.-fftw :: (VG.Vector v (Complex CDouble)) +fftw :: (VG.Vector v (Complex Double))       => Int -- ^ The size of the input and output buffers-     -> IO (Pipe (v (Complex CDouble)) (VS.Vector (Complex CDouble)) IO ())+     -> IO (Pipe (v (Complex Double)) (VS.Vector (Complex Double)) IO ()) fftw samples = do     func <- fftw' samples     return $ for cat $ \dat -> lift (func dat) >>= yield  -- | Creates a function that performs a real to complex DFT.-fftwReal' :: (VG.Vector v CDouble) +fftwReal' :: (VG.Vector v Double)           => Int -- ^ The size of the input Vector-         -> IO (v CDouble -> IO (VS.Vector (Complex CDouble)))+         -> IO (v Double -> IO (VS.Vector (Complex Double))) fftwReal' samples = do     --Allocate in and out buffers that wont be used because there doesnt seem to be a way to create a plan without them     ina <- mallocForeignBufferAligned samples@@ -95,16 +96,16 @@         copyInto inv inv'         let (fp, offset, length) = VSM.unsafeToForeignPtr inv -        withForeignPtr fp  $ \fpp -> -            withForeignPtr out $ \op -> +        withForeignPtr (coerce fp)  $ \fpp -> +            withForeignPtr (coerce out) $ \op ->                  executeDFTR2C plan fpp op          return $ VS.unsafeFromForeignPtr0 out samples  -- | Creates a pipe that performs a real to complex DFT.-fftwReal :: (VG.Vector v CDouble) +fftwReal :: (VG.Vector v Double)           => Int -- ^ The size of the input Vector-         -> IO (Pipe (v CDouble) (VS.Vector (Complex CDouble)) IO ())+         -> IO (Pipe (v Double) (VS.Vector (Complex Double)) IO ()) fftwReal samples = do     func <- fftwReal' samples     return $ for cat $ \dat -> lift (func dat) >>= yield@@ -114,10 +115,10 @@     a pool of threads to perform the DFT. Then, if a thread has finished     performing a previous DFT, the result is yielded. -}-fftwParallel :: (VG.Vector v (Complex CDouble)) +fftwParallel :: (VG.Vector v (Complex Double))               => Int -- ^ The number of threads to use              -> Int -- ^ The size of the input Vector-             -> IO (Pipe (v (Complex CDouble)) (VS.Vector (Complex CDouble)) IO ())+             -> IO (Pipe (v (Complex Double)) (VS.Vector (Complex Double)) IO ()) fftwParallel threads samples = do     --plan the DFT     ina <- mallocForeignBufferAligned samples@@ -142,8 +143,8 @@          let (fp, offset, length) = VSM.unsafeToForeignPtr inv -        withForeignPtr fp $ \fpp -> -            withForeignPtr out $ \op -> +        withForeignPtr (coerce fp) $ \fpp -> +            withForeignPtr (coerce out) $ \op ->                  executeDFT plan fpp op          theMap <- takeMVar outMap
hs_sources/SDR/FilterDesign.hs view
@@ -72,10 +72,11 @@     where     func phase = magnitude $ sum $ zipWith (\index mag -> mkPolar mag (phase * (- index))) (iterate (+ 1) (- ((fromIntegral (length coeffs) - 1) / 2))) coeffs --- | Given filter coefficients, plot their frequency response and save the graph as "frequency_response.png".+-- | Given filter coefficients, plot their frequency response and save the graph as a png file plotFrequency :: [Double] -- ^ The filter coefficients+              -> FilePath -- ^ The filename                -> IO ()-plotFrequency coeffs = toFile def "frequency_response.png" $ do+plotFrequency coeffs fName = toFile def fName $ do     layout_title .= "Frequency Response"     plot (line "Frequency Response" [signal coeffs $ takeWhile (< pi) $ iterate (+ 0.01) 0]) 
hs_sources/SDR/FilterInternal.hs view
@@ -10,7 +10,7 @@ import           Control.Monad import           Foreign.C.Types import           Foreign.Ptr-import           Unsafe.Coerce+import           Data.Coerce import           Data.Complex import           Foreign.Marshal.Array import           Foreign.Marshal.Alloc@@ -65,16 +65,16 @@  filterFFIR :: FilterCRR -> FilterRR  filterFFIR func coeffs num inBuf outBuf = -    VS.unsafeWith (unsafeCoerce coeffs) $ \cPtr -> -        VS.unsafeWith (unsafeCoerce inBuf) $ \iPtr -> -            VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> +    VS.unsafeWith (coerce coeffs) $ \cPtr -> +        VS.unsafeWith (coerce inBuf) $ \iPtr -> +            VSM.unsafeWith (coerce outBuf) $ \oPtr ->                  func (fromIntegral num) (fromIntegral $ VG.length coeffs) cPtr iPtr oPtr  filterFFIC :: FilterCRR -> FilterRC  filterFFIC func coeffs num inBuf outBuf = -    VS.unsafeWith (unsafeCoerce coeffs) $ \cPtr -> -        VS.unsafeWith (unsafeCoerce inBuf) $ \iPtr -> -            VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> +    VS.unsafeWith (coerce coeffs) $ \cPtr -> +        VS.unsafeWith (coerce inBuf) $ \iPtr -> +            VSM.unsafeWith (coerce outBuf) $ \oPtr ->                  func (fromIntegral num) (fromIntegral $ VG.length coeffs) cPtr iPtr oPtr  foreign import ccall unsafe "filterRR"@@ -164,16 +164,16 @@  decimateFFIR :: DecimateCRR -> DecimateRR  decimateFFIR func factor coeffs num inBuf outBuf = -    VS.unsafeWith (unsafeCoerce coeffs) $ \cPtr -> -        VS.unsafeWith (unsafeCoerce inBuf) $ \iPtr -> -            VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> +    VS.unsafeWith (coerce coeffs) $ \cPtr -> +        VS.unsafeWith (coerce inBuf) $ \iPtr -> +            VSM.unsafeWith (coerce outBuf) $ \oPtr ->                  func (fromIntegral num) (fromIntegral factor) (fromIntegral $ VG.length coeffs) cPtr iPtr oPtr  decimateFFIC :: DecimateCRR -> DecimateRC  decimateFFIC func factor coeffs num inBuf outBuf = -    VS.unsafeWith (unsafeCoerce coeffs) $ \cPtr -> -        VS.unsafeWith (unsafeCoerce inBuf) $ \iPtr -> -            VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> +    VS.unsafeWith (coerce coeffs) $ \cPtr -> +        VS.unsafeWith (coerce inBuf) $ \iPtr -> +            VSM.unsafeWith (coerce outBuf) $ \oPtr ->                  func (fromIntegral num) (fromIntegral factor) (fromIntegral $ VG.length coeffs) cPtr iPtr oPtr  foreign import ccall unsafe "decimateRR"@@ -269,9 +269,9 @@  resampleCRR :: Int -> Int -> Int -> Int -> VS.Vector Float -> VS.Vector Float -> VS.MVector RealWorld Float -> IO () resampleCRR num interpolation decimation offset coeffs inBuf outBuf = -    VS.unsafeWith (unsafeCoerce coeffs) $ \cPtr -> -        VS.unsafeWith (unsafeCoerce inBuf) $ \iPtr -> -            VS.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> +    VS.unsafeWith (coerce coeffs) $ \cPtr -> +        VS.unsafeWith (coerce inBuf) $ \iPtr -> +            VSM.unsafeWith (coerce outBuf) $ \oPtr ->                  resample_c (fromIntegral num) (fromIntegral $ VG.length coeffs) (fromIntegral interpolation) (fromIntegral decimation) (fromIntegral offset) cPtr iPtr oPtr  pad :: a -> Int -> [a] -> [a]@@ -320,14 +320,14 @@  resampleFFIR :: (Ptr CFloat -> Ptr CFloat -> IO CInt) -> VS.Vector Float -> VSM.MVector RealWorld Float -> IO Int resampleFFIR func inBuf outBuf = liftM fromIntegral $-    VS.unsafeWith (unsafeCoerce inBuf) $ \iPtr -> -        VS.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> +    VS.unsafeWith (coerce inBuf) $ \iPtr -> +        VSM.unsafeWith (coerce outBuf) $ \oPtr ->              func iPtr oPtr  resampleFFIC :: (Ptr CFloat -> Ptr CFloat -> IO CInt) -> VS.Vector (Complex Float) -> VSM.MVector RealWorld (Complex Float) -> IO Int resampleFFIC func inBuf outBuf = liftM fromIntegral $-    VS.unsafeWith (unsafeCoerce inBuf) $ \iPtr -> -        VS.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> +    VS.unsafeWith (coerce inBuf) $ \iPtr -> +        VSM.unsafeWith (coerce outBuf) $ \oPtr ->              func iPtr oPtr  type ResampleR = CInt -> CInt -> CInt -> CInt -> Ptr CInt -> Ptr (Ptr CFloat) -> Ptr CFloat -> Ptr CFloat -> IO CInt@@ -429,8 +429,8 @@ dcBlocker num lastSample lastOutput inBuf outBuf =      alloca $ \fsp ->          alloca $ \fop -> -            VS.unsafeWith (unsafeCoerce inBuf) $ \iPtr -> -                VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> do+            VS.unsafeWith (coerce inBuf) $ \iPtr -> +                VSM.unsafeWith (coerce outBuf) $ \oPtr -> do                     c_dcBlocker (fromIntegral num) (realToFrac lastSample) (realToFrac lastOutput) fsp fop iPtr oPtr                     r1 <- peek fsp                     r2 <- peek fop
hs_sources/SDR/Util.hs view
@@ -59,7 +59,7 @@ import qualified Data.Vector.Storable         as VS    import qualified Data.Vector.Storable.Mutable as VSM   import           Control.Monad.Primitive-import           Unsafe.Coerce+import           Data.Coerce import           Foreign.Ptr import           System.IO.Unsafe import           Foreign.Storable.Complex@@ -105,7 +105,7 @@ interleavedIQUnsignedByteToFloat inBuf = unsafePerformIO $ do     outBuf <- VGM.new $ VG.length inBuf `quot` 2     VS.unsafeWith inBuf $ \iPtr -> -        VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> +        VSM.unsafeWith (coerce outBuf) $ \oPtr ->              convertC_c (fromIntegral $ VG.length inBuf) iPtr oPtr     VG.freeze outBuf @@ -117,7 +117,7 @@ interleavedIQUnsignedByteToFloatSSE inBuf = unsafePerformIO $ do     outBuf <- VGM.new $ VG.length inBuf `quot` 2     VS.unsafeWith inBuf $ \iPtr -> -        VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> +        VSM.unsafeWith (coerce outBuf) $ \oPtr ->              convertCSSE_c (fromIntegral $ VG.length inBuf) iPtr oPtr     VG.freeze outBuf @@ -129,7 +129,7 @@ interleavedIQUnsignedByteToFloatAVX inBuf = unsafePerformIO $ do     outBuf <- VGM.new $ VG.length inBuf `quot` 2     VS.unsafeWith inBuf $ \iPtr -> -        VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> +        VSM.unsafeWith (coerce outBuf) $ \oPtr ->              convertCAVX_c (fromIntegral $ VG.length inBuf) iPtr oPtr     VG.freeze outBuf @@ -155,7 +155,7 @@ interleavedIQSignedWordToFloat inBuf = unsafePerformIO $ do     outBuf <- VGM.new $ VG.length inBuf `quot` 2     VS.unsafeWith inBuf $ \iPtr -> -        VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> +        VSM.unsafeWith (coerce outBuf) $ \oPtr ->              convertCBladeRF_c (fromIntegral $ VG.length inBuf) iPtr oPtr     VG.freeze outBuf @@ -167,7 +167,7 @@ interleavedIQSignedWordToFloatSSE inBuf = unsafePerformIO $ do     outBuf <- VGM.new $ VG.length inBuf `quot` 2     VS.unsafeWith inBuf $ \iPtr -> -        VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> +        VSM.unsafeWith (coerce outBuf) $ \oPtr ->              convertCSSEBladeRF_c (fromIntegral $ VG.length inBuf) iPtr oPtr     VG.freeze outBuf @@ -179,7 +179,7 @@ interleavedIQSignedWordToFloatAVX inBuf = unsafePerformIO $ do     outBuf <- VGM.new $ VG.length inBuf `quot` 2     VS.unsafeWith inBuf $ \iPtr -> -        VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> +        VSM.unsafeWith (coerce outBuf) $ \oPtr ->              convertCAVXBladeRF_c (fromIntegral $ VG.length inBuf) iPtr oPtr     VG.freeze outBuf @@ -205,7 +205,7 @@ complexFloatToInterleavedIQSignedWord :: VS.Vector (Complex Float) -> VS.Vector CShort complexFloatToInterleavedIQSignedWord inBuf = unsafePerformIO $ do     outBuf <- VGM.new $ VG.length inBuf * 2-    VS.unsafeWith (unsafeCoerce inBuf) $ \iPtr -> +    VS.unsafeWith (coerce inBuf) $ \iPtr ->          VSM.unsafeWith outBuf $ \oPtr ->              convertBladeRFTransmit_c (fromIntegral $ VG.length inBuf * 2) iPtr oPtr     VG.freeze outBuf@@ -220,9 +220,9 @@        -> VS.MVector RealWorld Float -- ^ Output vector        -> IO () scaleC factor inBuf outBuf = -    VS.unsafeWith (unsafeCoerce inBuf) $ \iPtr -> -        VS.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> -            scale_c (fromIntegral (VG.length inBuf)) (unsafeCoerce factor) iPtr oPtr+    VS.unsafeWith (coerce inBuf) $ \iPtr -> +        VSM.unsafeWith (coerce outBuf) $ \oPtr -> +            scale_c (fromIntegral (VG.length inBuf)) (coerce factor) iPtr oPtr  foreign import ccall unsafe "scaleSSE"     scaleSSE_c :: CInt -> CFloat -> Ptr CFloat -> Ptr CFloat-> IO ()@@ -233,9 +233,9 @@           -> VS.MVector RealWorld Float -- ^ Output vector           -> IO () scaleCSSE factor inBuf outBuf = -    VS.unsafeWith (unsafeCoerce inBuf) $ \iPtr -> -        VS.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> -            scaleSSE_c (fromIntegral (VG.length inBuf)) (unsafeCoerce factor) iPtr oPtr+    VS.unsafeWith (coerce inBuf) $ \iPtr -> +        VSM.unsafeWith (coerce outBuf) $ \oPtr -> +            scaleSSE_c (fromIntegral (VG.length inBuf)) (coerce factor) iPtr oPtr  foreign import ccall unsafe "scaleAVX"     scaleAVX_c :: CInt -> CFloat -> Ptr CFloat -> Ptr CFloat -> IO ()@@ -246,9 +246,9 @@           -> VS.MVector RealWorld Float -- ^ Output vector           -> IO () scaleCAVX factor inBuf outBuf = -    VS.unsafeWith (unsafeCoerce inBuf) $ \iPtr -> -        VS.unsafeWith (unsafeCoerce outBuf) $ \oPtr -> -            scaleAVX_c (fromIntegral (VG.length inBuf)) (unsafeCoerce factor) iPtr oPtr+    VS.unsafeWith (coerce inBuf) $ \iPtr -> +        VSM.unsafeWith (coerce outBuf) $ \oPtr -> +            scaleAVX_c (fromIntegral (VG.length inBuf)) (coerce factor) iPtr oPtr  -- | Scale a vector. Uses the fastest SIMD instruction set your processor supports. scaleFast :: CPUInfo -> Float -> VS.Vector Float -> VS.MVector RealWorld Float -> IO ()
sdr.cabal view
@@ -1,5 +1,5 @@ name:                sdr-version:             0.1.0.8+version:             0.1.0.9 synopsis:            A software defined radio library description:              Write software defined radio applications in Haskell.@@ -117,7 +117,7 @@         base                       >=4.6  && <5,          QuickCheck                 >=2.8  && <2.10,          vector                     >=0.11 && <0.12, -        sdr                        ==0.1.0.8, +        sdr                        ==0.1.0.9,          primitive                  >=0.5  && <0.7,          storable-complex           >=0.2  && <0.3,         test-framework             >=0.8  && <0.9,@@ -133,7 +133,7 @@         base             >=4.6  && <5,          criterion        >=1.0  && <1.2,         vector           >=0.11 && <0.12, -        sdr              ==0.1.0.8, +        sdr              ==0.1.0.9,          primitive        >=0.5  && <0.7,          storable-complex >=0.2  && <0.3     hs-source-dirs:      benchmarks