diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Revision history for essence-of-live-coding-pulse
 
-## 0.1.0.0 -- YYYY-mm-dd
+## 0.2.3
 
-* First version. Released on an unsuspecting world.
+* Added sawtooth
+
+## Earlier versions
+
+See in essence-of-live-coding/CHANGELOG.md.
diff --git a/essence-of-live-coding-pulse.cabal b/essence-of-live-coding-pulse.cabal
--- a/essence-of-live-coding-pulse.cabal
+++ b/essence-of-live-coding-pulse.cabal
@@ -1,5 +1,5 @@
 name:                essence-of-live-coding-pulse
-version:             0.2.2
+version:             0.2.3
 synopsis: General purpose live coding framework - pulse backend
 description:
   essence-of-live-coding is a general purpose and type safe live coding framework.
@@ -30,7 +30,7 @@
     LiveCoding.Pulse
   build-depends:
       base >= 4.11 && < 5
-    , essence-of-live-coding >= 0.2.2
+    , essence-of-live-coding >= 0.2.3
     , transformers >= 0.5
     , pulse-simple >= 0.1
     , foreign-store >= 0.2
diff --git a/src/LiveCoding/Pulse.hs b/src/LiveCoding/Pulse.hs
--- a/src/LiveCoding/Pulse.hs
+++ b/src/LiveCoding/Pulse.hs
@@ -91,6 +91,11 @@
 wrapIntegral :: (Monad m, Data a, RealFloat a) => Cell m a a
 wrapIntegral = arr (/ sampleRate) >>> wrapSum
 
+-- | A sawtooth, or triangle wave, generator,
+--   outputting a sawtooth wave with the given input as frequency.
+sawtooth :: (Monad m, Data a, RealFloat a) => Cell m a a
+sawtooth = wrapIntegral
+
 modSum :: (Monad m, Data a, Integral a) => a -> Cell m a a
 modSum denominator = Cell
   { cellState = 0
