2020 Election Mix in the browser
Tags: functional, webdev
Published: 2020-11-07 13:37:24

---
title: 2020 Election Mix in the browser
published: true
description: cnn beatz
tags: functional, webdev
cover_image: https://images.unsplash.com/photo-1511447333015-45b65e60f6d5?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1123&q=80
---

[Here](https://klank.dev/?k&ec&url=https://klank-share.s3.eu-west-1.amazonaws.com/K16047468353233859.purs).

```haskell
module E101.Election where

import Prelude
import Color (rgb)
import Data.Array (fold, index, length, range)
import Data.Int (floor, toNumber)
import Data.List (List(..), fold, (:))
import Data.Maybe (Maybe(..), fromMaybe)
import Data.NonEmpty ((:|))
import Data.Profunctor (lcmap)
import Data.Tuple (Tuple(..))
import Data.Typelevel.Num (D2)
import FRP.Behavior (Behavior)
import FRP.Behavior.Audio (AV(..), AudioParameter, AudioUnit, CanvasInfo(..), evalPiecewise, gainT_, gainT_', gain_', panner_, playBufWithOffset_, runInBrowser, speaker)
import Graphics.Drawing (Drawing, fillColor, filled, rectangle)
import Math (cos, pi, pow, sin, (%))
import Type.Klank.Dev (Klank, defaultEngineInfo, klank, makeBuffersKeepingCache)

tempo = 90.0 :: Number

q = 60.0 / tempo :: Number

_8 = 60.0 / (2.0 * tempo) :: Number

_16 = 60.0 / (4.0 * tempo) :: Number

_32 = 60.0 / (8.0 * tempo) :: Number

atT :: forall a. Number -> (Number -> a) -> (Number -> a)
atT t = lcmap (_ - t)

conv440 :: Int -> Number
conv440 i = 440.0 * (2.0 `pow` ((toNumber $ 0 + i) / 12.0))

boundPlayer :: forall a. Number -> (Number -> List a) -> Number -> List a
boundPlayer len a time = if (time) + kr >= 0.0 && time < (len) then a time else Nil

kr = (toNumber defaultEngineInfo.msBetweenSamples) / 1000.0 :: Number

epwf :: Array (Tuple Number Number) -> Number -> AudioParameter
epwf = evalPiecewise kr

ep :: Int -> String -> Number -> Number -> Number -> Number -> List (AudioUnit D2)
ep i' tag len rate os =
  let
    i = toNumber i'
  in
    boundPlayer len
      ( \t ->
          pure
            ( gainT_
                (tag <> "gain")
                (epwf [ Tuple 0.0 1.0, Tuple (len - 0.03) 1.0, Tuple len 0.0 ] t)
                ( (panner_ "p_cnn" (sin i) (playBufWithOffset_ (tag <> "buf_e") "election" 1.0 os))
                    :| ( ( if ( i' `mod` 16 /= 2
                              && i' `mod` 16
                              /= 5
                              && i' `mod` 16
                              /= 9
                              && i' `mod` 16
                              /= 14
                          ) then
                            (pure $ gain_' (tag <> "gt_e") (0.7 - 0.125 * 0.7 * (i % 8.0)) (playBufWithOffset_ (tag <> "buf_p") "nice" rate 0.0))
                          else
                            Nil
                        )
                          <> ( if ( true
                              ) then
                                (pure $ gain_' (tag <> "gt_z") 0.2 (playBufWithOffset_ (tag <> "buf_z") ("b" <> show (i' `mod` 8)) rate 0.0))
                              else
                                Nil
                            )
                      )
                )
            )
      )

xfy :: Int -> Int
xfy i = floor (8.0 * (0.5 + 0.5 * (sin $ toNumber i)))

rm :: Int -> Int -> Number -> Number -> Drawing
rm c r w h =
  let
    rw = w / (toNumber c)

    rh = h / (toNumber r)
  in
    fold (join (map (\i -> let ix = xfy i in map (\j -> let jx = xfy j in filled (fillColor (if (((j * r) + i) `mod` 2) == 0 then (rgb (255 - 10 * (ix + jx)) (ix * 8) (jx * 4)) else (rgb (jx * 3) (ix * 9) (255 - 10 * (ix + jx))))) (rectangle (toNumber i * rw) (toNumber j * rh) (rw) (rh))) (range 0 (r - 1))) (range 0 (c - 1))))

flen = 189.0 :: Number

scene ::
  Unit ->
  CanvasInfo ->
  Number ->
  Behavior (AV D2 Unit)
scene _ ci time =
  pure
    $ AV
        ( Just
            ( speaker
                ( zero
                    :| ( fold
                          ( map (\f -> f time)
                              ( (fac 0.0)
                                  <> (fac (q * 48.0))
                              )
                          )
                      )
                )
            )
        )
        ( Just
            $ (fold <<< fold)
                ( map (\f -> f time)
                    ( (fax ci 0.0)
                        <> (fax ci (q * 48.0))
                    )
                )
        )
        unit

main :: Klank
main =
  klank
    { run = runInBrowser scene
    , buffers =
      makeBuffersKeepingCache
        [ Tuple "election" "https://klank-share.s3-eu-west-1.amazonaws.com/e101/test/electionShort.ogg"
        , Tuple "b0" "https://freesound.org/data/previews/48/48527_100432-lq.mp3"
        , Tuple "b1" "https://freesound.org/data/previews/332/332643_5261755-lq.mp3"
        , Tuple "b2" "https://freesound.org/data/previews/422/422272_6672220-lq.mp3"
        , Tuple "b3" "https://freesound.org/data/previews/116/116830_2085593-lq.mp3"
        , Tuple "b4" "https://freesound.org/data/previews/128/128535_2345419-lq.mp3"
        , Tuple "b5" "https://freesound.org/data/previews/185/185079_3342732-lq.mp3"
        , Tuple "b6" "https://freesound.org/data/previews/121/121072_2193266-lq.mp3"
        , Tuple "b7" "https://freesound.org/data/previews/23/23563_150583-lq.mp3"
        , Tuple "b8" "https://freesound.org/data/previews/464/464227_1431924-lq.mp3"
        , Tuple "b9" "https://freesound.org/data/previews/26/26352_116671-lq.mp3"
        , Tuple "b10" "https://freesound.org/data/previews/0/907_838-lq.mp3"
        , Tuple "b11" "https://freesound.org/data/previews/321/321790_4701691-lq.mp3"
        , Tuple "nice" "https://freesound.org/data/previews/91/91781_1491361-lq.mp3"
        ]
    }

st :: Array Number
st = [ 0.26, 0.88, 2.38, 3.12, 3.80, 4.82, 5.68, 7.14 ]

lst = length st :: Int

fac :: Number -> Array (Number -> List (AudioUnit D2))
fac offset =
  ( map
      ( \i ->
          let
            n = toNumber i
          in
            atT (offset + n * q) $ ep i ("a" <> show i) (q + 0.04) (1.0 + 0.1 * sin n) (fromMaybe 0.0 $ index st (i `mod` lst))
      )
      (range 0 15)
  )
    <> ( map
          ( \i ->
              let
                n = toNumber i
              in
                atT (offset + (q * 16.0) + n * _8) $ ep i ("a" <> show i) (_8 + 0.04) (1.0 + 0.1 * sin n) (fromMaybe 0.0 $ index st (i `mod` lst))
          )
          (range 0 31)
      )
    <> ( map
          ( \i ->
              let
                n = toNumber i
              in
                atT (offset + (q * 32.0) + n * _16) $ ep i ("a" <> show i) (_16 + 0.04) (1.0 + 0.1 * sin n) (fromMaybe 0.0 $ index st (i `mod` lst))
          )
          (range 0 31)
      )
    <> ( map
          ( \i ->
              let
                n = toNumber i
              in
                atT (offset + (q * 40.0) + n * _32) $ ep i ("a" <> show i) (_32 * 1.5 + 0.04) (1.0 + 0.1 * sin n) (fromMaybe 0.0 $ index st (i `mod` lst))
          )
          (range 0 63)
      )

shuf = [ 1, 3, 5, 6, 7, 8, 9, 10 ] :: Array Int

lshuf = length shuf :: Int

shufx = [ 3, 5, 3, 4, 3, 5, 3, 4, 5, 4, 3 ] :: Array Int

lshufx = length shufx :: Int

fromShuf :: Int -> Int
fromShuf i = fromMaybe 3 (shuf `index` (i `mod` lshuf))

fromShufx :: Int -> Int
fromShufx i = fromMaybe 3 (shufx `index` (i `mod` lshufx))

fax :: CanvasInfo -> Number -> Array (Number -> List (Drawing))
fax (CanvasInfo ci) offset =
  ( map
      ( \i ->
          let
            n = toNumber i
          in
            atT (offset + n * q) $ boundPlayer q (\_ -> pure $ (rm (fromShuf i) (fromShuf (16 - i)) ci.w ci.h))
      )
      (range 0 48)
  )
    <> ( map
          ( \i ->
              let
                n = toNumber i
              in
                atT (offset + (q * 16.0) + n * _8) $ boundPlayer q (\_ -> pure $ (rm (fromShufx i) (fromShufx (16 - i)) ci.w ci.h))
          )
          (range 0 63)
      )
```