diff --git a/canvhs.cabal b/canvhs.cabal
--- a/canvhs.cabal
+++ b/canvhs.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               canvhs
-version:            0.2.0.0
+version:            0.2.0.1
 synopsis:           Simple HTML5 graphics for MicroHs
 description:        Simple HTML5 graphics and sound for MicroHs
 license:            Apache-2.0
@@ -26,7 +26,8 @@
                       Graphics.CanvHs.Color,
                       Graphics.CanvHs.Picture,
                       Graphics.CanvHs.Demo,
-                      Audio.AudHs.FFI
+                      Audio.AudHs.FFI,
+                      Audio.AudHs.Sound
     -- other-modules:
     -- other-extensions:
     build-depends:    base ^>=4.22.0.0
diff --git a/src/Audio/AudHs/Sound.hs b/src/Audio/AudHs/Sound.hs
new file mode 100644
--- /dev/null
+++ b/src/Audio/AudHs/Sound.hs
@@ -0,0 +1,40 @@
+module Audio.AudHs.Sound(
+  Waveform(..),
+  Sound(..),
+  silence,
+  playSound,
+  ) where
+import Audio.AudHs.FFI
+
+data Waveform = Sine | Square | Sawtooth | Triangle
+  deriving (Show, Eq, Ord, Enum, Bounded)
+
+data Sound = Sound
+    { wave     :: Waveform
+    , freq     :: Double               -- Hz
+    , volume   :: Double               -- 0.0 - 1.0
+    , duration :: Double               -- s
+    }
+    | Sounds [Sound]
+    deriving (Show)
+
+silence :: Sound
+silence = Sounds []
+
+playSound :: Sound -> IO ()
+playSound (Sound w f vol dur) = do
+    initAudio
+    now <- currentTime
+    
+    osc  <- createOscillator (fromEnum w)
+    gain <- createGain
+    connectNodes osc gain
+    connectNodes gain masterOutput
+    
+    setFrequency osc f now
+    setGain gain vol now
+    rampGain gain 0.0001 (now + dur)
+    
+    startNode osc now
+    stopNode osc (now + dur)
+playSound (Sounds ss) = mapM_ playSound ss
