diff --git a/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,11 @@
+hosc-utils
+----------
+
+utilities related to [hosc][hosc]
+
+[hosc]: http://rd.slavepianos.org/?t=hosc
+
+© [stefan kersten][sk], 2011, [gpl]
+
+[sk]: http://space.k-hornz.de/
+[gpl]: http://gnu.org/copyleft/
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,3 @@
+#!/usr/bin/env runhaskell
+import Distribution.Simple
+main = defaultMain
diff --git a/benchmarks/Sound/OpenSoundControl/NFData.hs b/benchmarks/Sound/OpenSoundControl/NFData.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/Sound/OpenSoundControl/NFData.hs
@@ -0,0 +1,28 @@
+module Sound.OpenSoundControl.NFData () where
+
+import Control.DeepSeq (NFData(..))
+import Sound.OpenSoundControl
+
+instance NFData Time where
+    rnf (UTCr x1) = rnf x1 `seq` ()
+    rnf (NTPr x1) = rnf x1 `seq` ()
+    rnf (NTPi x1) = rnf x1 `seq` ()
+
+instance NFData Datum where
+    rnf (Int x1)        = rnf x1 `seq` ()
+    rnf (Float x1)      = rnf x1 `seq` ()
+    rnf (Double x1)     = rnf x1 `seq` ()
+    rnf (String x1)     = rnf x1 `seq` ()
+    rnf (Blob x1)       = rnf x1 `seq` ()
+    rnf (TimeStamp x1)  = rnf x1 `seq` ()
+    rnf (Midi x1)       = rnf x1 `seq` ()
+
+instance NFData Message where
+    rnf (Message x1 x2) = rnf x1 `seq` rnf x2 `seq` ()
+
+instance NFData Bundle where
+    rnf (Bundle x1 x2)  = rnf x1 `seq` rnf x2 `seq` ()
+
+instance NFData Packet where
+    rnf (Packet_Message x1) = rnf x1 `seq` ()
+    rnf (Packet_Bundle x1) = rnf x1 `seq` ()
diff --git a/benchmarks/benchmark.hs b/benchmarks/benchmark.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/benchmark.hs
@@ -0,0 +1,32 @@
+import Criterion.Main
+
+import qualified Data.ByteString.Lazy as B
+import Sound.OpenSoundControl
+import Sound.OpenSoundControl.NFData ()
+import qualified Sound.OpenSoundControl.Coding.Decode.Binary as Binary
+import qualified Sound.OpenSoundControl.Coding.Encode.Builder as Builder
+import qualified Sound.OpenSoundControl.Coding.Decode.Base as Decode
+import qualified Sound.OpenSoundControl.Coding.Encode.Base as Encode
+
+type EncodingFunc = Bundle -> B.ByteString
+type DecodingFunc = B.ByteString -> Packet
+
+main :: IO ()
+main =
+    defaultMain [
+        bgroup "encodeOSC" [
+            bench "Encode"  (nf (Encode.encodeBundle :: EncodingFunc) b)
+          , bench "Builder" (nf (Builder.encodeBundle :: EncodingFunc) b)
+          ]
+      , bgroup "decodeOSC" [
+            bench "Decode" (nf (Decode.decodePacket :: DecodingFunc) p)
+          , bench "Binary" (nf (Binary.decodePacket :: DecodingFunc) p)
+          ]
+      ]
+    where
+        m = Message "/fooblah" [Float 42
+                               ,Int 16
+                               ,String "yeah"
+                               ,Blob (B.pack [0..128])]
+        b = Bundle (NTPr pi) (replicate 12 m)
+        p = Encode.encodeBundle b
diff --git a/hosc-utils.cabal b/hosc-utils.cabal
new file mode 100644
--- /dev/null
+++ b/hosc-utils.cabal
@@ -0,0 +1,47 @@
+Name:              hosc-utils
+Version:           0.12
+Synopsis:          Haskell Open Sound Control Utilities
+Description:       hosc-utils
+License:           GPL
+Category:          Sound
+Copyright:         (c) Stefan Kersten and others, 2006-2012
+Author:            Stefan Kersten
+Maintainer:        rd@slavepianos.org
+Stability:         Experimental
+Homepage:          http://rd.slavepianos.org/?t=hosc-utils
+Tested-With:       GHC == 7.6.1
+Build-Type:        Simple
+Cabal-Version:     >= 1.8
+Data-Files:        README
+
+Executable hosc-utils-benchmark
+    Hs-Source-Dirs: benchmarks, .
+    Main-Is: benchmark.hs
+    Other-Modules:
+        Sound.OpenSoundControl.NFData
+    Build-Depends:
+        base == 4.*
+      , bytestring
+      , hosc == 0.12.*
+      , criterion
+      , deepseq
+    GHC-Options:      -Wall -fno-warn-orphans -fwarn-tabs -rtsopts
+    GHC-Prof-Options: -Wall -fwarn-tabs -rtsopts -auto-all
+
+Test-Suite hosc-utils-test
+    Type: exitcode-stdio-1.0
+    Hs-Source-Dirs: tests, .
+    Main-Is: test.hs
+    Other-Modules:
+        Sound.OpenSoundControl.Arbitrary
+    Build-Depends:
+        hosc == 0.12.*
+      , QuickCheck >= 2
+      , test-framework >= 0.2
+      , test-framework-quickcheck2 >= 0.2
+    GHC-Options:      -Wall -fno-warn-orphans -fwarn-tabs -rtsopts
+    GHC-Prof-Options: -Wall -fwarn-tabs -rtsopts -auto-all
+
+Source-Repository  head
+  Type:            darcs
+  Location:        http://rd.slavepianos.org/sw/hosc-utils
diff --git a/tests/Sound/OpenSoundControl/Arbitrary.hs b/tests/Sound/OpenSoundControl/Arbitrary.hs
new file mode 100644
--- /dev/null
+++ b/tests/Sound/OpenSoundControl/Arbitrary.hs
@@ -0,0 +1,36 @@
+module Sound.OpenSoundControl.Arbitrary () where
+
+import Control.Applicative
+import qualified Data.ByteString.Lazy as B
+import Sound.OpenSoundControl (Datum(..), OSC(..), Time(..), NTPi)
+import Test.QuickCheck
+
+instance Arbitrary Time where
+    arbitrary = oneof [
+        UTCr <$> realToFrac   <$> (arbitrary :: Gen (NonNegative Double))
+      , NTPr <$> realToFrac   <$> (arbitrary :: Gen (NonNegative Double))
+      , NTPi <$> fromIntegral <$> (arbitrary :: Gen (Positive NTPi))
+      ]
+
+instance Arbitrary Datum where
+    arbitrary = oneof [
+        Int       <$> arbitrary
+      , Float     <$> realToFrac <$> (arbitrary :: Gen Float)
+      , Double    <$> arbitrary
+      , String    <$> genString
+      , Blob      <$> B.pack <$> resize 128 arbitrary
+      , TimeStamp <$> arbitrary
+      , Midi      <$> arbitrary
+      ]
+
+genString :: Gen String
+genString = resize 128 (listOf (arbitrary `suchThat` (/= '\0')))
+
+genMessage :: Gen OSC
+genMessage = Message <$> ("/"++) <$> genString <*> resize 32 (listOf1 arbitrary)
+
+instance Arbitrary OSC where
+    arbitrary = oneof [
+        genMessage
+      , Bundle <$> arbitrary <*> resize 32 (listOf1 genMessage)
+      ]
diff --git a/tests/test.hs b/tests/test.hs
new file mode 100644
--- /dev/null
+++ b/tests/test.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+
+import           Sound.OpenSoundControl (OSC)
+import           Sound.OpenSoundControl.Arbitrary ()
+import qualified Sound.OpenSoundControl.OSC.Decode as Decode
+import qualified Sound.OpenSoundControl.OSC.Encode as Encode
+import qualified Sound.OpenSoundControl.OSC.Binary as Binary
+import qualified Sound.OpenSoundControl.OSC.Builder as Builder
+import           Test.Framework (Test, defaultMain)
+import           Test.Framework.Providers.QuickCheck2 (testProperty)
+
+tests :: [Test]
+tests =
+    [ testProperty "encodeOSC (Builder)" $ \(osc :: OSC) ->
+        Builder.encodeOSC osc == Encode.encodeOSC osc
+    , testProperty "encodeOSC/decodeOSC" $ \(osc :: OSC) ->
+        Decode.decodeOSC (Encode.encodeOSC osc) == osc
+    , testProperty "decodeOSC (Get)" $ \(osc :: OSC) ->
+        Binary.decodeOSC (Encode.encodeOSC osc) == osc
+    ]
+
+main :: IO ()
+main = defaultMain tests
