packages feed

HSoM (empty) → 1.0.0

raw patch · 63 files changed

+3545/−0 lines, 63 filesdep +Euterpeadep +HCodecsdep +UISFbuild-type:Customsetup-changedbinary-added

Dependencies added: Euterpea, HCodecs, UISF, array, arrows, base, containers, deepseq, ghc-prim, markov-chain, pure-fft, random

Files

+ .git/COMMIT_EDITMSG view
@@ -0,0 +1,1 @@+Requires Euterpea 2.0.3
+ .git/FETCH_HEAD view
@@ -0,0 +1,1 @@+75338cbac2a3e4a2cae32448ca729de421ecd404		branch 'master' of https://github.com/Euterpea/HSoM
+ .git/HEAD view
@@ -0,0 +1,1 @@+ref: refs/heads/master
+ .git/ORIG_HEAD view
@@ -0,0 +1,1 @@+b0227d9f423638807feb76dc0b2d0769072b6281
+ .git/config view
@@ -0,0 +1,13 @@+[core]+	repositoryformatversion = 0+	filemode = false+	bare = false+	logallrefupdates = true+	symlinks = false+	ignorecase = true+[remote "origin"]+	url = https://github.com/Euterpea/HSoM.git+	fetch = +refs/heads/*:refs/remotes/origin/*+[branch "master"]+	remote = origin+	merge = refs/heads/master
+ .git/description view
@@ -0,0 +1,1 @@+Unnamed repository; edit this file 'description' to name the repository.
+ .git/hooks/applypatch-msg.sample view
@@ -0,0 +1,15 @@+#!/bin/sh+#+# An example hook script to check the commit log message taken by+# applypatch from an e-mail message.+#+# The hook should exit with non-zero status after issuing an+# appropriate message if it wants to stop the commit.  The hook is+# allowed to edit the commit message file.+#+# To enable this hook, rename this file to "applypatch-msg".++. git-sh-setup+commitmsg="$(git rev-parse --git-path hooks/commit-msg)"+test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}+:
+ .git/hooks/commit-msg.sample view
@@ -0,0 +1,24 @@+#!/bin/sh+#+# An example hook script to check the commit log message.+# Called by "git commit" with one argument, the name of the file+# that has the commit message.  The hook should exit with non-zero+# status after issuing an appropriate message if it wants to stop the+# commit.  The hook is allowed to edit the commit message file.+#+# To enable this hook, rename this file to "commit-msg".++# Uncomment the below to add a Signed-off-by line to the message.+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg+# hook is more suited to it.+#+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"++# This example catches duplicate Signed-off-by lines.++test "" = "$(grep '^Signed-off-by: ' "$1" |+	 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {+	echo >&2 Duplicate Signed-off-by lines.+	exit 1+}
+ .git/hooks/post-update.sample view
@@ -0,0 +1,8 @@+#!/bin/sh+#+# An example hook script to prepare a packed repository for use over+# dumb transports.+#+# To enable this hook, rename this file to "post-update".++exec git update-server-info
+ .git/hooks/pre-applypatch.sample view
@@ -0,0 +1,14 @@+#!/bin/sh+#+# An example hook script to verify what is about to be committed+# by applypatch from an e-mail message.+#+# The hook should exit with non-zero status after issuing an+# appropriate message if it wants to stop the commit.+#+# To enable this hook, rename this file to "pre-applypatch".++. git-sh-setup+precommit="$(git rev-parse --git-path hooks/pre-commit)"+test -x "$precommit" && exec "$precommit" ${1+"$@"}+:
+ .git/hooks/pre-commit.sample view
@@ -0,0 +1,49 @@+#!/bin/sh+#+# An example hook script to verify what is about to be committed.+# Called by "git commit" with no arguments.  The hook should+# exit with non-zero status after issuing an appropriate message if+# it wants to stop the commit.+#+# To enable this hook, rename this file to "pre-commit".++if git rev-parse --verify HEAD >/dev/null 2>&1+then+	against=HEAD+else+	# Initial commit: diff against an empty tree object+	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904+fi++# If you want to allow non-ASCII filenames set this variable to true.+allownonascii=$(git config --bool hooks.allownonascii)++# Redirect output to stderr.+exec 1>&2++# Cross platform projects tend to avoid non-ASCII filenames; prevent+# them from being added to the repository. We exploit the fact that the+# printable range starts at the space character and ends with tilde.+if [ "$allownonascii" != "true" ] &&+	# Note that the use of brackets around a tr range is ok here, (it's+	# even required, for portability to Solaris 10's /usr/bin/tr), since+	# the square bracket bytes happen to fall in the designated range.+	test $(git diff --cached --name-only --diff-filter=A -z $against |+	  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0+then+	cat <<\EOF+Error: Attempt to add a non-ASCII file name.++This can cause problems if you want to work with people on other platforms.++To be portable it is advisable to rename the file.++If you know what you are doing you can disable this check using:++  git config hooks.allownonascii true+EOF+	exit 1+fi++# If there are whitespace errors, print the offending file names and fail.+exec git diff-index --check --cached $against --
+ .git/hooks/pre-push.sample view
@@ -0,0 +1,53 @@+#!/bin/sh++# An example hook script to verify what is about to be pushed.  Called by "git+# push" after it has checked the remote status, but before anything has been+# pushed.  If this script exits with a non-zero status nothing will be pushed.+#+# This hook is called with the following parameters:+#+# $1 -- Name of the remote to which the push is being done+# $2 -- URL to which the push is being done+#+# If pushing without using a named remote those arguments will be equal.+#+# Information about the commits which are being pushed is supplied as lines to+# the standard input in the form:+#+#   <local ref> <local sha1> <remote ref> <remote sha1>+#+# This sample shows how to prevent push of commits where the log message starts+# with "WIP" (work in progress).++remote="$1"+url="$2"++z40=0000000000000000000000000000000000000000++while read local_ref local_sha remote_ref remote_sha+do+	if [ "$local_sha" = $z40 ]+	then+		# Handle delete+		:+	else+		if [ "$remote_sha" = $z40 ]+		then+			# New branch, examine all commits+			range="$local_sha"+		else+			# Update to existing branch, examine new commits+			range="$remote_sha..$local_sha"+		fi++		# Check for WIP commit+		commit=`git rev-list -n 1 --grep '^WIP' "$range"`+		if [ -n "$commit" ]+		then+			echo >&2 "Found WIP commit in $local_ref, not pushing"+			exit 1+		fi+	fi+done++exit 0
+ .git/hooks/pre-rebase.sample view
@@ -0,0 +1,169 @@+#!/bin/sh+#+# Copyright (c) 2006, 2008 Junio C Hamano+#+# The "pre-rebase" hook is run just before "git rebase" starts doing+# its job, and can prevent the command from running by exiting with+# non-zero status.+#+# The hook is called with the following parameters:+#+# $1 -- the upstream the series was forked from.+# $2 -- the branch being rebased (or empty when rebasing the current branch).+#+# This sample shows how to prevent topic branches that are already+# merged to 'next' branch from getting rebased, because allowing it+# would result in rebasing already published history.++publish=next+basebranch="$1"+if test "$#" = 2+then+	topic="refs/heads/$2"+else+	topic=`git symbolic-ref HEAD` ||+	exit 0 ;# we do not interrupt rebasing detached HEAD+fi++case "$topic" in+refs/heads/??/*)+	;;+*)+	exit 0 ;# we do not interrupt others.+	;;+esac++# Now we are dealing with a topic branch being rebased+# on top of master.  Is it OK to rebase it?++# Does the topic really exist?+git show-ref -q "$topic" || {+	echo >&2 "No such branch $topic"+	exit 1+}++# Is topic fully merged to master?+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`+if test -z "$not_in_master"+then+	echo >&2 "$topic is fully merged to master; better remove it."+	exit 1 ;# we could allow it, but there is no point.+fi++# Is topic ever merged to next?  If so you should not be rebasing it.+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`+only_next_2=`git rev-list ^master           ${publish} | sort`+if test "$only_next_1" = "$only_next_2"+then+	not_in_topic=`git rev-list "^$topic" master`+	if test -z "$not_in_topic"+	then+		echo >&2 "$topic is already up-to-date with master"+		exit 1 ;# we could allow it, but there is no point.+	else+		exit 0+	fi+else+	not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`+	/usr/bin/perl -e '+		my $topic = $ARGV[0];+		my $msg = "* $topic has commits already merged to public branch:\n";+		my (%not_in_next) = map {+			/^([0-9a-f]+) /;+			($1 => 1);+		} split(/\n/, $ARGV[1]);+		for my $elem (map {+				/^([0-9a-f]+) (.*)$/;+				[$1 => $2];+			} split(/\n/, $ARGV[2])) {+			if (!exists $not_in_next{$elem->[0]}) {+				if ($msg) {+					print STDERR $msg;+					undef $msg;+				}+				print STDERR " $elem->[1]\n";+			}+		}+	' "$topic" "$not_in_next" "$not_in_master"+	exit 1+fi++exit 0++################################################################++This sample hook safeguards topic branches that have been+published from being rewound.++The workflow assumed here is:++ * Once a topic branch forks from "master", "master" is never+   merged into it again (either directly or indirectly).++ * Once a topic branch is fully cooked and merged into "master",+   it is deleted.  If you need to build on top of it to correct+   earlier mistakes, a new topic branch is created by forking at+   the tip of the "master".  This is not strictly necessary, but+   it makes it easier to keep your history simple.++ * Whenever you need to test or publish your changes to topic+   branches, merge them into "next" branch.++The script, being an example, hardcodes the publish branch name+to be "next", but it is trivial to make it configurable via+$GIT_DIR/config mechanism.++With this workflow, you would want to know:++(1) ... if a topic branch has ever been merged to "next".  Young+    topic branches can have stupid mistakes you would rather+    clean up before publishing, and things that have not been+    merged into other branches can be easily rebased without+    affecting other people.  But once it is published, you would+    not want to rewind it.++(2) ... if a topic branch has been fully merged to "master".+    Then you can delete it.  More importantly, you should not+    build on top of it -- other people may already want to+    change things related to the topic as patches against your+    "master", so if you need further changes, it is better to+    fork the topic (perhaps with the same name) afresh from the+    tip of "master".++Let's look at this example:++		   o---o---o---o---o---o---o---o---o---o "next"+		  /       /           /           /+		 /   a---a---b A     /           /+		/   /               /           /+	       /   /   c---c---c---c B         /+	      /   /   /             \         /+	     /   /   /   b---b C     \       /+	    /   /   /   /             \     /+    ---o---o---o---o---o---o---o---o---o---o---o "master"+++A, B and C are topic branches.++ * A has one fix since it was merged up to "next".++ * B has finished.  It has been fully merged up to "master" and "next",+   and is ready to be deleted.++ * C has not merged to "next" at all.++We would want to allow C to be rebased, refuse A, and encourage+B to be deleted.++To compute (1):++	git rev-list ^master ^topic next+	git rev-list ^master        next++	if these match, topic has not merged in next at all.++To compute (2):++	git rev-list master..topic++	if this is empty, it is fully merged to "master".
+ .git/hooks/pre-receive.sample view
@@ -0,0 +1,24 @@+#!/bin/sh+#+# An example hook script to make use of push options.+# The example simply echoes all push options that start with 'echoback='+# and rejects all pushes when the "reject" push option is used.+#+# To enable this hook, rename this file to "pre-receive".++if test -n "$GIT_PUSH_OPTION_COUNT"+then+	i=0+	while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"+	do+		eval "value=\$GIT_PUSH_OPTION_$i"+		case "$value" in+		echoback=*)+			echo "echo from the pre-receive-hook: ${value#*=}" >&2+			;;+		reject)+			exit 1+		esac+		i=$((i + 1))+	done+fi
+ .git/hooks/prepare-commit-msg.sample view
@@ -0,0 +1,36 @@+#!/bin/sh+#+# An example hook script to prepare the commit log message.+# Called by "git commit" with the name of the file that has the+# commit message, followed by the description of the commit+# message's source.  The hook's purpose is to edit the commit+# message file.  If the hook fails with a non-zero status,+# the commit is aborted.+#+# To enable this hook, rename this file to "prepare-commit-msg".++# This hook includes three examples.  The first comments out the+# "Conflicts:" part of a merge commit.+#+# The second includes the output of "git diff --name-status -r"+# into the message, just before the "git status" output.  It is+# commented because it doesn't cope with --amend or with squashed+# commits.+#+# The third example adds a Signed-off-by line to the message, that can+# still be edited.  This is rarely a good idea.++case "$2,$3" in+  merge,)+    /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;++# ,|template,)+#   /usr/bin/perl -i.bak -pe '+#      print "\n" . `git diff --cached --name-status -r`+#	 if /^#/ && $first++ == 0' "$1" ;;++  *) ;;+esac++# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+ .git/hooks/update.sample view
@@ -0,0 +1,128 @@+#!/bin/sh+#+# An example hook script to block unannotated tags from entering.+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new+#+# To enable this hook, rename this file to "update".+#+# Config+# ------+# hooks.allowunannotated+#   This boolean sets whether unannotated tags will be allowed into the+#   repository.  By default they won't be.+# hooks.allowdeletetag+#   This boolean sets whether deleting tags will be allowed in the+#   repository.  By default they won't be.+# hooks.allowmodifytag+#   This boolean sets whether a tag may be modified after creation. By default+#   it won't be.+# hooks.allowdeletebranch+#   This boolean sets whether deleting branches will be allowed in the+#   repository.  By default they won't be.+# hooks.denycreatebranch+#   This boolean sets whether remotely creating branches will be denied+#   in the repository.  By default this is allowed.+#++# --- Command line+refname="$1"+oldrev="$2"+newrev="$3"++# --- Safety check+if [ -z "$GIT_DIR" ]; then+	echo "Don't run this script from the command line." >&2+	echo " (if you want, you could supply GIT_DIR then run" >&2+	echo "  $0 <ref> <oldrev> <newrev>)" >&2+	exit 1+fi++if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then+	echo "usage: $0 <ref> <oldrev> <newrev>" >&2+	exit 1+fi++# --- Config+allowunannotated=$(git config --bool hooks.allowunannotated)+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)+denycreatebranch=$(git config --bool hooks.denycreatebranch)+allowdeletetag=$(git config --bool hooks.allowdeletetag)+allowmodifytag=$(git config --bool hooks.allowmodifytag)++# check for no description+projectdesc=$(sed -e '1q' "$GIT_DIR/description")+case "$projectdesc" in+"Unnamed repository"* | "")+	echo "*** Project description file hasn't been set" >&2+	exit 1+	;;+esac++# --- Check types+# if $newrev is 0000...0000, it's a commit to delete a ref.+zero="0000000000000000000000000000000000000000"+if [ "$newrev" = "$zero" ]; then+	newrev_type=delete+else+	newrev_type=$(git cat-file -t $newrev)+fi++case "$refname","$newrev_type" in+	refs/tags/*,commit)+		# un-annotated tag+		short_refname=${refname##refs/tags/}+		if [ "$allowunannotated" != "true" ]; then+			echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2+			echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2+			exit 1+		fi+		;;+	refs/tags/*,delete)+		# delete tag+		if [ "$allowdeletetag" != "true" ]; then+			echo "*** Deleting a tag is not allowed in this repository" >&2+			exit 1+		fi+		;;+	refs/tags/*,tag)+		# annotated tag+		if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1+		then+			echo "*** Tag '$refname' already exists." >&2+			echo "*** Modifying a tag is not allowed in this repository." >&2+			exit 1+		fi+		;;+	refs/heads/*,commit)+		# branch+		if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then+			echo "*** Creating a branch is not allowed in this repository" >&2+			exit 1+		fi+		;;+	refs/heads/*,delete)+		# delete branch+		if [ "$allowdeletebranch" != "true" ]; then+			echo "*** Deleting a branch is not allowed in this repository" >&2+			exit 1+		fi+		;;+	refs/remotes/*,commit)+		# tracking branch+		;;+	refs/remotes/*,delete)+		# delete tracking branch+		if [ "$allowdeletebranch" != "true" ]; then+			echo "*** Deleting a tracking branch is not allowed in this repository" >&2+			exit 1+		fi+		;;+	*)+		# Anything else (is there anything else?)+		echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2+		exit 1+		;;+esac++# --- Finished+exit 0
+ .git/index view

binary file changed (absent → 2852 bytes)

+ .git/info/exclude view
@@ -0,0 +1,6 @@+# git ls-files --others --exclude-from=.git/info/exclude+# Lines that start with '#' are comments.+# For a project mostly in C, the following would be a good set of+# exclude patterns (uncomment them if you want to use them):+# *.[oa]+# *~
+ .git/logs/HEAD view
@@ -0,0 +1,3 @@+0000000000000000000000000000000000000000 b0227d9f423638807feb76dc0b2d0769072b6281 Donya Quick <donyaquick@gmail.com> 1495035283 -0700	clone: from https://github.com/Euterpea/HSoM.git+b0227d9f423638807feb76dc0b2d0769072b6281 44ff8d50c43737d58946aa4413b947d87c8c35f3 Donya Quick <donyaquick@gmail.com> 1496256585 -0500	pull --no-rebase --progress origin: Fast-forward+44ff8d50c43737d58946aa4413b947d87c8c35f3 75338cbac2a3e4a2cae32448ca729de421ecd404 Donya Quick <donyaquick@gmail.com> 1496257746 -0500	commit: Requires Euterpea 2.0.3
+ .git/logs/refs/heads/master view
@@ -0,0 +1,3 @@+0000000000000000000000000000000000000000 b0227d9f423638807feb76dc0b2d0769072b6281 Donya Quick <donyaquick@gmail.com> 1495035283 -0700	clone: from https://github.com/Euterpea/HSoM.git+b0227d9f423638807feb76dc0b2d0769072b6281 44ff8d50c43737d58946aa4413b947d87c8c35f3 Donya Quick <donyaquick@gmail.com> 1496256585 -0500	pull --no-rebase --progress origin: Fast-forward+44ff8d50c43737d58946aa4413b947d87c8c35f3 75338cbac2a3e4a2cae32448ca729de421ecd404 Donya Quick <donyaquick@gmail.com> 1496257746 -0500	commit: Requires Euterpea 2.0.3
+ .git/logs/refs/remotes/origin/HEAD view
@@ -0,0 +1,1 @@+0000000000000000000000000000000000000000 b0227d9f423638807feb76dc0b2d0769072b6281 Donya Quick <donyaquick@gmail.com> 1495035283 -0700	clone: from https://github.com/Euterpea/HSoM.git
+ .git/logs/refs/remotes/origin/master view
@@ -0,0 +1,2 @@+b0227d9f423638807feb76dc0b2d0769072b6281 44ff8d50c43737d58946aa4413b947d87c8c35f3 Donya Quick <donyaquick@gmail.com> 1496256217 -0500	fetch --progress --prune origin: fast-forward+44ff8d50c43737d58946aa4413b947d87c8c35f3 75338cbac2a3e4a2cae32448ca729de421ecd404 Donya Quick <donyaquick@gmail.com> 1496257750 -0500	update by push
+ .git/objects/30/75eb05964f6d0466d9429d301ef889e2ef4df6 view

binary file changed (absent → 814 bytes)

+ .git/objects/44/ff8d50c43737d58946aa4413b947d87c8c35f3 view
@@ -0,0 +1,3 @@+xŽK+Â0@]繀2™É$)ˆ¸ð"ùL°ÓÚ¦‚·WŠpõÞæÁËÓã1vÈ‡¾ˆh‘ÊNL²2+U2ÈlƒË@œµÌ䁨9.ÒºN€èËP-’£ÀWIޕ	x7€Çä0·~Ÿ]¦öŽú¼ãõ¼6ék޳œ¾rÑÆìh†ô@åý®Ë¿ÿuê&³´"-²êm.±KQÞ8FÖ
+ .git/objects/6f/9dfbd6d9e474c3fdf6267e8afa7405ceaad234 view

binary file changed (absent → 844 bytes)

+ .git/objects/75/338cbac2a3e4a2cae32448ca729de421ecd404 view

binary file changed (absent → 172 bytes)

+ .git/objects/a7/cb694607d57876250d17ddbbc9681935048195 view

binary file changed (absent → 270 bytes)

+ .git/objects/c9/1c7ef73b14ee6c485fa2f09995ff5b3df7c7fd view

binary file changed (absent → 145 bytes)

+ .git/objects/ee/f56e1b438c2e3f31255486c035c644553703b0 view

binary file changed (absent → 270 bytes)

+ .git/objects/pack/pack-657e976d66993f23ab15b29cb1903b83553a3dda.idx view

binary file changed (absent → 5776 bytes)

+ .git/objects/pack/pack-657e976d66993f23ab15b29cb1903b83553a3dda.pack view

file too large to diff

+ .git/packed-refs view
@@ -0,0 +1,2 @@+# pack-refs with: peeled fully-peeled +b0227d9f423638807feb76dc0b2d0769072b6281 refs/remotes/origin/master
+ .git/refs/heads/master view
@@ -0,0 +1,1 @@+75338cbac2a3e4a2cae32448ca729de421ecd404
+ .git/refs/remotes/origin/HEAD view
@@ -0,0 +1,1 @@+ref: refs/remotes/origin/master
+ .git/refs/remotes/origin/master view
@@ -0,0 +1,1 @@+75338cbac2a3e4a2cae32448ca729de421ecd404
+ HSoM.cabal view
@@ -0,0 +1,56 @@+name:           HSoM
+version:        1.0.0
+Cabal-Version:  >= 1.8
+license:        BSD3
+license-file:	License
+copyright:      Copyright (c) 2008-2015 Paul Hudak and Donya Quick
+category:       Sound
+stability:      experimental
+build-type:     Custom
+author:         Paul Hudak <paul.hudak@yale.edu>,
+				Donya Quick <donyaquick@gmail.com>,
+                Dan Winograd-Cort <daniel.winograd-cort@yale.edu>
+maintainer:     Donya Quick <donyaquick@gmail.com>
+bug-reports:    https://github.com/Euterpea/HSoM/issues
+homepage:       http://www.euterpea.com
+synopsis:       Library for computer music education
+description:
+        Supporting library for the Haskell School of Music textbook.
+extra-source-files:
+        ReadMe.txt
+
+Library
+  hs-source-dirs: .
+  ghc-options: -O2 -funbox-strict-fields -fexcess-precision
+  extensions: CPP
+  exposed-modules: 
+        System.Random.Distributions,
+        HSoM,
+        HSoM.Performance,
+        HSoM.MUI.MidiWidgets,
+        HSoM.MUI,
+        HSoM.Examples.FFT,
+        HSoM.Examples.MoreMusic,
+        HSoM.Examples.RandomMusic,
+        HSoM.Examples.SoundCheck,
+        HSoM.Examples.SelfSimilar,
+        HSoM.Examples.SSF,
+        HSoM.Examples.Interlude,
+        HSoM.Examples.EuterpeaExamples,
+        HSoM.Examples.MUIExamples1,
+        HSoM.Examples.MUIExamples2,
+        HSoM.Examples.IntervalTrainer,
+        HSoM.Examples.NewResolutions,
+        HSoM.Examples.MusicToSignal,
+        HSoM.Examples.SpectrumAnalysis,
+        HSoM.Examples.Additive,
+        HSoM.Examples.AMandFM,
+        HSoM.Examples.PhysicalModeling
+  other-modules:
+  build-depends:
+        base >= 3 && < 5, arrows >= 0.4, array, deepseq, random, 
+        HCodecs >= 0.2, Euterpea >= 2.0.3, 
+        containers, markov-chain, pure-fft, 
+        UISF >= 0.4
+  if (impl(ghc >= 6.10))
+    build-depends: base >= 4 && < 5, ghc-prim
+ HSoM.lhs view
@@ -0,0 +1,12 @@+> {-# OPTIONS -XFlexibleInstances #-}
+> {-# OPTIONS -XTypeSynonymInstances #-}
+
+> module HSoM (
+>     module HSoM.MUI,
+>     module HSoM.Performance
+>     ) where
+> import Euterpea
+> import HSoM.MUI
+> import HSoM.Performance
+
+
+ HSoM/Examples/AMandFM.lhs view
@@ -0,0 +1,51 @@+> {-#  LANGUAGE Arrows  #-}
+
+> module HSoM.Examples.AMandFM where
+> import Euterpea
+> import FRP.UISF.AuxFunctions
+
+> tab1 = tableSinesN 4096 [1]
+
+> tremolo ::   Clock c =>
+>              Double -> Double -> SigFun c () Double
+> tremolo tfrq dep = proc () -> do
+>      trem  <- osc tab1 0 -< tfrq
+>      outA  -< 1 + dep*trem
+
+> amfmInst  :: Instr (Mono AudRate)
+>        -- Dur -> AbsPitch -> Volume -> AudSF () Double
+> amfmInst dur ap vol ps = 
+>   let  f    = apToHz ap
+>        v    = fromIntegral vol / 100
+>        d    = fromRational dur
+>        (tremAmt, tremFreq, vibAmt, vibFreq) =  
+>            if length ps < 4 then (0, 1, 0, 1)
+>            else (ps !! 0, ps !! 1, ps !! 2, ps !! 3)
+>   in proc () -> do
+>        asr <- envLineSeg [0,1,1,0] [d*0.01, d*0.98, d*0.01] -< ()
+>        vibSig <- osc tab1 0 -< vibFreq
+>        sineSig <- osc tab1 0 -< f + f*vibSig*vibAmt
+>        tremEnv <- tremolo tremFreq tremAmt -< ()
+>        outA -< (1-tremAmt) * asr * tremEnv * sineSig
+
+> iMap :: InstrMap (Mono AudRate)
+> iMap = [(CustomInstrument "AMFM", amfmInst)] 
+
+> mkAMFM :: FilePath -> [Double] -> IO ()
+> mkAMFM str p = writeWav str iMap $
+>     instrument (CustomInstrument "AMFM") $ 
+>     note 2 ((C,4::Octave), [Params p])
+
+> amfm1 =  mkAMFM "amfm1.wav" [] -- neither trem nor vib
+> amfm2 =  mkAMFM "amfm2.wav" [0.2,1.5,0.0,1.0] -- trem only
+> amfm3 =  mkAMFM "amfm3.wav" [0.0,1.0,0.02,4.0] -- vib only
+> amfm4 =  mkAMFM "amfm4.wav" [0.2,1.5,0.02,4.0] -- both
+
+Vibrato and tremolo into the audible frequency range:
+
+> amfm5 = mkAMFM "amfm5.wav" [0.2,50.0,0.0,1.0] -- trem only
+> amfm6 = mkAMFM "amfm6.wav" [0.0,1.0,0.05,100.0] -- vib only
+> amfm7 = mkAMFM "amfm7.wav" [0.2,50.0,0.05,100.0] -- both
+
+> writeAll = sequence [amfm1, amfm2, amfm3, amfm4, amfm5, amfm6, amfm7]
+
+ HSoM/Examples/Additive.lhs view
@@ -0,0 +1,234 @@+> {-#  LANGUAGE Arrows  #-}
+
+> module HSoM.Examples.Additive where
+> import Euterpea
+> import FRP.UISF.AuxFunctions
+
+
+> tab1 = tableSinesN 4096 [1]
+
+> bell1  :: Instr (Mono AudRate)
+>        -- Dur -> AbsPitch -> Volume -> AudSF () Double
+> bell1 dur ap vol [] = 
+>   let  f    = apToHz ap
+>        v    = fromIntegral vol / 100
+>        d    = fromRational dur
+>        sfs  = map  (\p-> constA (f*p) >>> osc tab1 0) 
+>                    [4.07, 3.76, 3, 2.74, 2, 1.71, 1.19, 0.92, 0.56]
+>   in proc () -> do
+>        aenv  <- envExponSeg [0,1,0.001] [0.003,d-0.003] -< ()
+>        a1    <- foldSF (+) 0 sfs -< ()
+>        outA -< a1*aenv*v/9
+
+
+> tab1' = tableSines3N 4096 [(4.07,1,0), (3.76,1,0), (3,1,0),
+>   (2.74,1,0), (2,1,0), (1.71,1,0), (1.19,1,0), (0.92,1,0), (0.56,1,0)]
+
+> bell'1  :: Instr (Mono AudRate)
+> bell'1 dur ap vol [] = 
+>   let  f    = apToHz ap
+>        v    = fromIntegral vol / 100
+>        d    = fromRational dur
+>   in proc () -> do
+>        aenv  <- envExponSeg [0,1,0.001] [0.003,d-0.003] -< ()
+>        a1    <- osc tab1' 0 -< f
+>        outA -< a1*aenv*v
+
+> bellTest1 = outFile "bell1.wav" 6 (bell1 6 (absPitch (C,5)) 100 []) 
+
+
+> mySF f d p = proc () -> do
+>                s     <- osc tab1 0 <<< constA (f*p) -< ()
+>                aenv  <- envExponSeg [0,1,0.001] [0.003,d/p-0.003] -< ()
+>                outA  -< s*aenv
+
+> bell2  :: Instr (Mono AudRate)
+>        -- Dur -> AbsPitch -> Volume -> AudSF () Double
+> bell2 dur ap vol [] = 
+>   let  f    = apToHz ap
+>        v    = fromIntegral vol / 100
+>        d    = fromRational dur
+>        sfs  = map  (mySF f d)
+>                    [4.07, 3.76, 3, 2.74, 2, 1.71, 1.19, 0.92, 0.56]
+>   in proc () -> do
+>        a1    <- foldSF (+) 0 sfs -< ()
+>        outA  -< a1*v/9
+
+> bellTest1' = outFile "bell'1.wav" 6 (bell'1 6 (absPitch (C,5)) 100 [])
+
+> bellTest2 = outFile "bell2.wav" 6 (bell2 6 (absPitch (C,5)) 100 []) 
+
+
+> sineTable :: Table
+> sineTable = tableSinesN 4096 [1]
+
+> env1 :: AudSF () Double
+> env1 = envExpon 20 10 10000
+
+> good = outFile "good.wav" 10 
+>        (osc sineTable 0 <<< envExpon 20 10 10000 :: AudSF () Double)
+
+> bad  = outFile "bad.wav" 10 
+>        (osc sineTable 0 <<< envLine  20 10 10000 :: AudSF () Double)
+
+> sfTest1 :: AudSF (Double,Double) Double -> Instr (Mono AudRate)
+>         -- AudSF (Double,Double) Double -> 
+>         -- Dur -> AbsPitch -> Volume -> [Double] -> AudSF () Double
+> sfTest1 sf dur ap vol [] =
+>   let f = apToHz ap
+>       v = fromIntegral vol / 100
+>   in proc () -> do
+>        a1 <- osc sineTable 0 <<< env1 -< () 
+>        a2 <- sf -< (a1,f)
+>        outA -< a2*v
+
+
+> tLow    =  outFile "low.wav" 10 $
+>            sfTest1 filterLowPass 10 (absPitch (C,5)) 80 []
+
+> tHi     =  outFile "hi.wav" 10 $
+>            sfTest1 filterHighPass 10 (absPitch (C,5)) 80 []
+
+> tLowBW  =  outFile "lowBW.wav" 10 $
+>            sfTest1 filterLowPassBW 10 (absPitch (C,5)) 80 []
+
+> tHiBW   =  outFile "hiBW.wav" 10 $
+>            sfTest1 filterHighPassBW 10 (absPitch (C,5)) 80 []
+
+> addBandWidth ::  AudSF (Double,Double,Double) Double ->
+>                  AudSF (Double,Double) Double
+
+> addBandWidth filter =
+>   proc (a,f) -> do filter -< (a,f,200)
+
+> tBP    =  outFile "bp.wav" 10 $
+>           sfTest1 (addBandWidth (filterBandPass 1)) 10 (absPitch (C,6)) 80 []
+
+> tBS    =  outFile "bs.wav" 10 $
+>           sfTest1 (addBandWidth (filterBandStop 1)) 10 (absPitch (C,6)) 80 []
+
+> tBPBW  =  outFile "bpBW.wav" 10 $
+>           sfTest1 (addBandWidth filterBandPassBW) 10 (absPitch (C,6)) 80 []
+
+> tBSBW  =  outFile "bsBW.wav" 10 $
+>           sfTest1 (addBandWidth filterBandStopBW) 10 (absPitch (C,6)) 80 []
+
+
+> noise1  :: Instr (Mono AudRate)
+>         -- Dur -> AbsPitch -> Volume -> [Double] -> AudSF () Double
+> noise1 dur ap vol [] = 
+>   let  v = fromIntegral vol / 100
+>   in proc () -> do
+>        a1    <- noiseWhite 42 -< ()
+>        outA  -< a1*v
+> test1 = outFile "noise1.wav" 6 (noise1 6 (absPitch (C,5)) 100 []) 
+
+
+> env2 :: AudSF () Double
+> env2 = envExpon 1 10 2000
+
+> sfTest2  :: AudSF (Double,Double,Double) Double -> Instr (Mono AudRate)
+>          -- AudSF (Double,Double,Double) Double -> 
+>          -- Dur -> AbsPitch -> Volume -> [Double] -> AudSF () Double
+> sfTest2 sf dur ap vol [] =
+>   let  f = apToHz ap
+>        v = fromIntegral vol / 100
+>   in proc () -> do
+>        a1 <- noiseWhite 42 -< ()
+>        bw <- env2 -< ()
+>        a2 <- sf -< (a1,f,bw)
+>        outA -< a2
+
+> tBP'    =  outFile "bp'.wav" 10 $
+>            sfTest2 (filterBandPass 1) 10 (absPitch (C,5)) 80 []
+
+> tBS'    =  outFile "bs'.wav" 10 $
+>            sfTest2 (filterBandStop 1) 10 (absPitch (C,5)) 80 []
+
+> tBPBW'  =  outFile "bpBW'.wav" 10 $
+>            sfTest2 filterBandPassBW 10 (absPitch (C,5)) 80 []
+
+> tBSBW'  =  outFile "bsBW'.wav" 10 $
+>            sfTest2 filterBandStopBW 10 (absPitch (C,5)) 80 []
+
+
+> noise2  :: Instr (Mono AudRate)
+> noise2 dur ap vol [] = 
+>   let  f = apToHz ap
+>        v = fromIntegral vol / 100
+>   in proc () -> do
+>        a1    <- noiseBLI 42 -< f
+>        outA  -< a1*v
+
+> test2 = outFile "noise2.wav" 6 (noise2 6 (absPitch (C,5)) 100 []) 
+
+
+> ss1  :: Instr (Mono AudRate)
+> ss1 dur ap vol [] = 
+>   let  v    = fromIntegral vol / 100
+>   in proc () -> do
+>        a1    <- noiseWhite 42 -< ()
+>        a2    <- filterBandPass 2 -< (a1, 1000, 200)
+>        outA  -< a2*v/5
+
+> test3 = outFile "ss1.wav" 6 (ss1 6 (absPitch (C,5)) 100 []) 
+
+
+> wind :: Instr (Mono AudRate)
+> wind dur ap vol [] = 
+>   let  f = apToHz ap
+>        v = fromIntegral vol / 100
+>   in proc () -> do
+>        a1    <- noiseWhite 42 -< ()
+>        lfo1  <- osc sineTable 0 -< 0.9
+>        lfo2  <- osc sineTable 0 -< 1.3
+>        a2    <- filterBandPass 2 -< (a1, f + 100*(lfo1+lfo2), 200)
+>        outA  -< a2*v/5
+
+> test4 = outFile "wind.wav" 6 (wind 6 (absPitch (C,7)) 100 []) 
+
+
+> buzzy  :: Instr (Mono AudRate)
+> buzzy dur ap vol [] = 
+>   let  f    = apToHz ap
+>        v    = fromIntegral vol / 100
+>   in proc () -> do
+>        a1 <- oscPartials sineTable 0 -< (f,20)
+>        outA -< a1*v
+
+> test5 = outFile "buzzy.wav" 6 (buzzy 6 (absPitch (C,5)) 100 []) 
+
+
+> buzzy2 :: Instr (Mono AudRate)
+> buzzy2 dur ap vol [] = 
+>   let  f    = apToHz ap
+>        v    = fromIntegral vol / 100
+>        d    = fromRational dur
+>   in proc () -> do
+>        a1   <- oscPartials sineTable 0 -< (f,20)
+>        env  <- envExponSeg [0, 1, 0.001] [0.003, d - 0.003] -< ()
+>        a2   <- filterLowPass -< (a1,20000*env)
+>        outA -< a2*v*env
+
+> test6 = outFile "buzzy2.wav" 6 (buzzy2 6 (absPitch (C,5)) 100 []) 
+
+> scifi1 :: Instr (Mono AudRate)
+> scifi1 dur ap vol [] = 
+>   let  v    = fromIntegral vol / 100
+>   in proc () -> do
+>        a1 <- noiseBLH 42 -< 8
+>        a2 <- osc sineTable 0 -< 600 + 200*a1
+>        outA -< a2*v
+
+> test7 = outFile "scifi1.wav" 10 (scifi1 10 (absPitch (C,5)) 100 []) 
+
+
+> scifi2 :: Instr (Mono AudRate)
+> scifi2 dur ap vol [] = 
+>   let  v    = fromIntegral vol / 100
+>   in proc () -> do
+>        a1 <- noiseBLI 44 -< 8
+>        a2 <- osc sineTable 0 -< 600 + 200*a1
+>        outA -< a2*v
+
+> test8 = outFile "scifi2.wav" 10 (scifi2 10 (absPitch (C,5)) 100 []) 
+ HSoM/Examples/EnableGUI.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE ForeignFunctionInterface #-}
+{--
+On Mac OS X, with versions of GHC prior to 7.8, you will have to use this
+``EnableGUI trick'' to run GUI programs for Euterpea from within ghci.
+
+To do so, first compile this file, EnableGUI.hs, to binary:
+    ghc -c -fffi EnableGUI.hs
+
+(Note: on some systems it is necessary to add the option
+``-framework ApplicationServices'')
+Then, run your Euterpea GUI programs in ghci like this:
+
+ghci UIExamples.hs EnableGUI
+*UIExamples> :m +EnableGUI
+*UIExamples EnableGUI> enableGUI >> main
+
+With this, GHCi will be able to fully activate the Graphics Window. (Fully
+compiled GUI programs do not suffer from this anomaly.)
+
+--}
+
+module EnableGUI(enableGUI) where
+
+import Data.Int
+import Foreign
+
+type ProcessSerialNumber = Int64
+
+foreign import ccall "GetCurrentProcess" getCurrentProcess :: Ptr ProcessSerialNumber -> IO Int16
+foreign import ccall "_CGSDefaultConnection" cgsDefaultConnection :: IO ()
+foreign import ccall "CPSEnableForegroundOperation" cpsEnableForegroundOperation :: Ptr ProcessSerialNumber -> IO ()
+foreign import ccall "CPSSignalAppReady" cpsSignalAppReady :: Ptr ProcessSerialNumber -> IO ()
+foreign import ccall "CPSSetFrontProcess" cpsSetFrontProcess :: Ptr ProcessSerialNumber -> IO ()
+
+enableGUI = alloca $ \psn -> do
+    getCurrentProcess psn
+    cgsDefaultConnection
+    cpsEnableForegroundOperation psn
+    cpsSignalAppReady psn
+    cpsSetFrontProcess psn
+ HSoM/Examples/EuterpeaExamples.lhs view
@@ -0,0 +1,179 @@+> module HSoM.Examples.EuterpeaExamples where
+> import Euterpea
+> import HSoM.Examples.MoreMusic
+> import HSoM.Examples.Interlude
+> import HSoM.Examples.SelfSimilar
+> import HSoM.Examples.SSF
+
+Simple examples of Euterpea in action.  Note that this module also
+imports modules Interlude and SelfSimilar.
+
+-----------------------------------------------------------------------------
+
+From the tutorial, try things such as pr12, cMajArp, cMajChd, etc. and
+try applying inversions, retrogrades, etc. on the same examples.  Also
+try "childSong6" imported from module Interlude.  For example:
+
+> t0 = play childSong6
+
+-----------------------------------------------------------------------------
+
+C Major scale for use in examples below:
+
+> cMajScale = Modify (Tempo 2)
+>             (line [c 4 en, d 4 en, e 4 en, f 4 en, 
+>                    g 4 en, a 4 en, b 4 en, c 5 en])
+>
+> cms' = line [c 4 en, d 4 en, e 4 en, f 4 en, 
+>              g 4 en, a 4 en, b 4 en, c 5 en]
+>
+> cms = cMajScale
+
+Test of various articulations and dynamics:
+
+> t1 = play (Modify (Instrument Percussion)
+>        (Modify (Phrase [Art (Staccato (1/10))]) cms :+:
+>         cms                             :+:
+>         Modify (Phrase [Art (Legato  (11/10))]) cms    ))
+>
+> temp = Modify (Instrument AcousticGrandPiano) 
+>          (Modify (Phrase [Dyn (Crescendo 4)]) (c 4 en))
+>
+> mu2 = Modify (Instrument Vibraphone)
+>        (Modify (Phrase [Dyn (Diminuendo (3/4))]) cms :+:
+>          (Modify (Phrase [Dyn (Crescendo 4), Dyn (Loudness 25)]) cms))
+> t2 = play mu2
+>
+> t3 = play (Modify (Instrument Flute) 
+>        (Modify (Phrase [Tmp (Accelerando 0.3)]) cms :+:
+>         Modify (Phrase [Tmp (Ritardando  0.6)]) cms    ))
+
+
+-----------------------------------------------------------------------------
+
+Example from the SelfSimilar module.
+
+> t10s   = play (rep (offset (dur ttm0)) (Modify (Transpose 4)) 2 ttm0)
+
+-----------------------------------------------------------------------------
+
+Example from the Interlude module.
+
+> cs6 = play childSong6
+
+-----------------------------------------------------------------------------
+
+Example from the Ssf (Stars and Stripes Forever) module.
+
+> ssf0 = play ssf
+
+-----------------------------------------------------------------------------
+
+Midi percussion test.  Plays all "notes" in a range.  (Requires adding
+an instrument for percussion to the UserPatchMap.)
+
+> drums a b = Modify (Instrument Percussion)
+>                   (line (map (\p-> Prim $ Note sn (pitch p)) [a..b]))
+> t11 a b = play (drums a b)
+
+-----------------------------------------------------------------------------
+
+Test of cut and shorten.
+
+> t12  = play (cut 4 childSong6)
+> t12a = play (cms /=: childSong6)
+
+-----------------------------------------------------------------------------
+
+Tests of the trill functions.
+
+> t13note = Prim (Note qn (C,5))
+> t13 =  play (trill   1 sn t13note)
+> t13a = play (trill'  2 dqn t13note)
+> t13b = play (trilln  1 5 t13note)
+> t13c = play (trilln' 3 7 t13note)
+> t13d = play (roll tn t13note)
+> t13e = play (Modify (Tempo (2/3)) 
+>               (Modify (Transpose 2) 
+>                 (Modify (Instrument AcousticGrandPiano) 
+>                   (trilln' 2 7 t13note))))
+
+-----------------------------------------------------------------------------
+
+Tests of drum.
+
+> t14 = play (Modify (Instrument Percussion) (perc AcousticSnare qn))
+
+> -- a "funk groove"
+> t14b = let p1 = perc LowTom        qn
+>            p2 = perc AcousticSnare en
+>        in play (Modify (Tempo 3) (Modify (Instrument Percussion) (cut 8 (forever
+>                  ((p1 :+: qnr :+: p2 :+: qnr :+: p2 :+:
+>                    p1 :+: p1 :+: qnr :+: p2 :+: enr)
+>                   :=: roll en (perc ClosedHiHat 2))))))
+
+> -- a "jazz groove"
+> t14c = let p1 = perc CrashCymbal2  qn
+>            p2 = perc AcousticSnare en
+>            p3 = perc LowTom        qn
+>        in play (Modify (Tempo 3) (Modify (Instrument Percussion) (cut 4 (forever
+>                  ((p1 :+: (Modify (Tempo (3/2)) (p2 :+: enr :+: p2))
+>                   :=: (p3 :+: qnr)) )))))
+
+> t14d = let p1 = perc LowTom        en
+>            p2 = perc AcousticSnare hn
+>        in play (Modify (Instrument Percussion)
+>                   (  roll tn p1
+>                  :+: p1
+>                  :+: p1
+>                  :+: Prim (Rest en)
+>                  :+: roll tn p1
+>                  :+: p1
+>                  :+: p1
+>                  :+: Prim (Rest qn)
+>                  :+: roll tn p2
+>                  :+: p1
+>                  :+: p1  ))
+
+-----------------------------------------------------------------------------
+
+Tests of the MIDI interface.
+
+> loadMidiFile fn = do
+>   r <- importFile fn 
+>   case r of
+>     Left err -> error err
+>     Right m  -> return m
+
+Music into a MIDI file.
+
+> tab m = writeMidi m
+
+Music to a Midi datatype and back to Music.
+
+> tad m = fromMidi $ toMidi $ perform m
+
+A MIDI file to a MidiFile datatype and back to a MIDI file.
+
+> tcb file = do
+>              x <- loadMidiFile file
+>              exportFile "test.mid" x
+
+MIDI file to MidiFile datatype.
+
+> tc file = do
+>             x <- loadMidiFile file
+>             print x
+
+MIDI file to Music, a UserPatchMap, and a Context.
+
+> tcd file = do
+>              x <- loadMidiFile file
+>              print $ fromMidi x
+
+A MIDI file to Music and back to a MIDI file.
+
+> tcdab file = do
+>              x <- loadMidiFile file
+>              exportFile "test.mid" $ toMidi $ perform $ fromMidi x
+
+ HSoM/Examples/FFT.lhs view
@@ -0,0 +1,60 @@+Filename: fft.hs
+Created by: Daniel Winograd-Cort
+Created on: unknown
+Last Modified by: Daniel Winograd-Cort
+Last Modified on: 16-Dec-2015 by Donya Quick
+
+This module requires the array and pure-fft packages.
+
+> {-# LANGUAGE Arrows #-}
+> module HSoM.Examples.FFT where
+> import FRP.UISF
+> import Control.Arrow.Operations
+> import Numeric.FFT (fft)
+> import Data.Complex
+> import Data.Map (Map)
+> import qualified Data.Map as Map
+
+
+
+Alternative for working with Math.FFT instead of Numeric.FFT
+import qualified Math.FFT as FFT
+import Data.Array.IArray
+import Data.Array.CArray
+myFFT n lst = elems $ (FFT.dft) (listArray (0, n-1) lst)
+
+
+--------------------------------------
+-- Fast Fourier Transform
+--------------------------------------
+
+Returns n samples of type b from the input stream at a time, 
+updating after k samples.  This function is good for chunking 
+data and is a critical component to fftA
+
+> quantize :: ArrowCircuit a => Int -> Int -> a b (SEvent [b])
+> quantize n k = proc d -> do
+>     rec (ds,c) <- delay ([],0) -< (take n (d:ds), c+1)
+>     returnA -< if c >= n && c `mod` k == 0 then Just ds else Nothing
+
+Converts the vector result of a dft into a map from frequency to magnitude.
+One common use is:
+fftA >>> arr (fmap $ presentFFT clockRate)
+
+> presentFFT :: Double -> [Double] -> Map Double Double
+> presentFFT clockRate a = Map.fromList $ zipWith (curry mkAssoc) [0..] a where 
+>     mkAssoc (i,c) = (freq, c) where
+>         samplesPerPeriod = fromIntegral (length a)
+>         freq = i * (clockRate / samplesPerPeriod)
+
+Given a quantization frequency (the number of samples between each 
+successive FFT calculation) and a fundamental period, this will decompose
+the input signal into its constituent frequencies.
+NOTE: The fundamental period must be a power of two!
+
+> fftA :: ArrowCircuit a => Int -> Int -> a Double (SEvent [Double])
+> fftA qf fp = proc d -> do
+>     carray <- quantize fp qf -< d :+ 0
+>     returnA -< fmap (map magnitude . take (fp `div` 2) . fft) carray
+
+
+ HSoM/Examples/Interlude.lhs view
@@ -0,0 +1,67 @@+> module  HSoM.Examples.Interlude
+>         (  childSong6,  --  :: Music Pitch,
+>            prefix       --  :: [Music a] -> Music a)
+>         )  where
+> import Euterpea
+
+> addDur       :: Dur -> [Dur -> Music a] -> Music a
+> addDur d ns  =  let f n = n d
+>                 in line (map f ns)
+
+> graceNote :: Int -> Music Pitch -> Music Pitch
+> graceNote n  (Prim (Note d p))  =
+>           note (d/8) (trans n p) :+: note (7*d/8) p
+> graceNote n  _                  = 
+>           error "Can only add a grace note to a note."
+
+> b1  = addDur dqn [b 2,   fs 3,  g 3,   fs 3]
+> b2  = addDur dqn [b 2,   es 3,  fs 3,  es 3]
+> b3  = addDur dqn [as 2,  fs 3,  g 3,   fs 3]
+
+> bassLine =  times 3 b1 :+: times 2 b2 :+: 
+>             times 4 b3 :+: times 5 b1
+
+> mainVoice = times 3 v1 :+: v2
+
+> v1   = v1a :+: graceNote (-1) (d 4 qn) :+: v1b                 --  bars 1-2
+> v1a  = addDur en [a 4, e 4, d 4, fs 4, cs 4, b 3, e 4, b 3]
+> v1b  = addDur en [cs 4, b 3]
+
+> v2 = v2a :+: v2b :+: v2c :+: v2d :+: v2e :+: v2f :+: v2g
+
+> v2a  =  line [  cs 4 (dhn+dhn), d 4 dhn, 
+>                 f 4 hn, gs 4 qn, fs 4 (hn+en), g 4 en]     --  bars 7-11
+> v2b  =  addDur en [  fs 4, e 4, cs 4, as 3] :+: a 3 dqn :+:
+>         addDur en [  as 3, cs 4, fs 4, e 4, fs 4]          --  bars 12-13
+> v2c  =  line [  g 4 en, as 4 en, cs 5 (hn+en), d 5 en, cs 5 en] :+:
+>         e 4 en :+: enr :+: 
+>         line [  as 4 en, a 4 en, g 4 en, d 4 qn, c 4 en, cs 4 en] 
+>                                                            --  bars 14-16
+> v2d  =  addDur en [  fs 4, cs 4, e 4, cs 4, 
+>                      a 3, as 3, d 4, e 4, fs 4]            --  bars 17-18.5
+> v2e  =  line [  graceNote 2 (e 4 qn), d 4 en, graceNote 2 (d 4 qn), cs 4 en,
+>                 graceNote 1 (cs 4 qn), b 3 (en+hn), cs 4 en, b 3 en ]  
+>                                                            --  bars 18.5-20
+> v2f  =  line [  fs 4 en, a 4 en, b 4 (hn+qn), a 4 en, fs 4 en, e 4 qn,
+>                 d 4 en, fs 4 en, e 4 hn, d 4 hn, fs 4 qn]  --  bars 21-23
+> v2g  =  tempo (3/2) (line [cs 4 en, d 4 en, cs 4 en]) :+: 
+>         b 3 (3*dhn+hn)                                     --  bars 24-28
+
+> childSong6 :: Music Pitch
+> childSong6 =  let t = (dhn/qn)*(69/120)
+>               in instrument  RhodesPiano 
+>                              (tempo t (bassLine :=: mainVoice))
+
+> prefixes         :: [a] -> [[a]]
+> prefixes []      =  []
+> prefixes (x:xs)  =  let f pf = x:pf
+>                     in [x] : map f (prefixes xs)
+
+> prefix :: [Music a] -> Music a
+> prefix mel =  let  m1  = line (concat (prefixes mel))
+>                    m2  = transpose 12 (line (concat (prefixes (reverse mel))))
+>                    m   = instrument Flute m1 :=: instrument VoiceOohs m2
+>               in m :+: transpose 5 m :+: m
+
+> mel1 = [c 4 en, e 4 sn, g 4 en, b 4 sn, a 4 en, f 4 sn, d 4 en, b 3 sn, c 4 en]
+> mel2 = [c 4 sn, e 4 sn, g 4 sn, b 4 sn, a 4 sn, f 3 sn, d 4 sn, b 3 sn, c 4 sn]
+ HSoM/Examples/IntervalTrainer.lhs view
@@ -0,0 +1,199 @@+> {-# LANGUAGE Arrows #-}
+
+> module HSoM.Examples.IntervalTrainer where
+> import HSoM
+> import Euterpea
+> import FRP.UISF
+> import System.Random (randomRIO)
+> import Codec.Midi (Message(ProgramChange))
+> import FRP.UISF.AuxFunctions (concatA, evMap)
+> import Data.Monoid
+
+
+> main = runMUI (defaultMUIParams {uiSize=(600,700), uiTitle="Interval Trainer"}) intervalTrainer
+
+> -- music theory name for intervals:
+> intNameList :: [String]
+> intNameList =
+>   ["uni","min2","Maj2","min3","Maj3","4th","aug4",
+>    "5th","min6","Maj6","min7","Maj7","oct"]
+
+States of the MUI's internal Finite State Machine:
+
+> data State = Start | Base | Guessed
+>   deriving (Eq,Ord,Show)
+
+State transition table:
+
+        | Next    | Repeat  | Giveup  | Guess   | Reset   |
+-----------------------------------------------------------
+Start   | Base    | Start   | Start   | Start   | Start   | 
+Base    | Base    | Base    | Guessed | Guessed | Start   |
+Guessed | Base    | Guessed | Guessed | Guessed | Start   |
+
+State variables:
+
+total:   number ofintervals generated
+correct: number guessed correctly
+repeats: number of repeat requests prior to making a guess
+answer:  a pair, the random root note and the random interval
+state:   the durrect FSA state (see above)
+
+State variable updates:
+
+Variable | Event : action
+------------------------------------------------------------------------
+total    | Next (Base) : incr, Guess (Base) : incr, Giveup (Base) : incr
+correct  | Guess (Base) /\ match : incr
+repeats  | Repeat (Base) : incr
+answer   | Next : generate and save new random root and interval
+state    | see State Transition Table
+
+Also, Reset forces total, correct, and repeats to 0, and answer to (0,0).
+
+The main UI:
+
+> intervalTrainer :: UISF () ()
+> intervalTrainer = proc _ -> do
+>     -- MIDI output select:
+>     mo <- setSize (600,90) $ selectOutput -< ()
+>     -- Play note:
+>     pns <- setSize (600,60) . title "Play notes" . leftRight $
+>             radio ["Together","Low then high","High then low"] 0 -< ()
+>     -- Note length:
+>     dur <- setSize (600,60) . title "Note length" . leftRight $ 
+>             radio ["Whole","Half","Quarter","Eighth"] 2 -< ()
+>     -- Max interval
+>     maxInt <- (| (setSize (600,60) . title "Maximum interval" . leftRight) (do
+>                 max <- shiSlider 1 (1,12) 12 -< ()
+>                 sDisplay -< intNameList !! max
+>                 returnA -< max )|)
+>     -- Range:
+>     range  <- (| (setSize (600,60) . title "Range in octaves" . leftRight) (do
+>                 range <- shiSlider 1 (2,10) 4 -< ()
+>                 sDisplay -< take 3 $ show $ fromIntegral range / 2
+>                 returnA -< range )|)
+>     -- Lowest octave:
+>     lowOct <- (| (setSize (600,60) . title "Lowest octave" . leftRight) (do
+>                 low <- shiSlider 1 (1,8) 4 -< ()
+>                 sDisplay -< show low
+>                 returnA -< low )|)
+>     -- Instrument:
+>     instr <- setSize (600,60) . title "Instrument" . leftRight $ 
+>               radio ["Acous Piano","Elec Piano","Violin","Saxophone","Flute"] 0 -< ()
+>     -- Control:
+>     (nextE,repeatE,giveUpE,resetE) <- (| (setSize (600,60) . title "Control" . leftRight) (do
+>         next   <- edge <<< button "Next"      -< ()
+>         repeat <- edge <<< button "Repeat"    -< ()
+>         giveUp <- edge <<< button "Give Up"   -< ()
+>         reset  <- edge <<< button "Reset"     -< ()
+>         returnA -< (next,repeat,giveUp,reset) )|)
+>     -- User Input:
+>     guesses <- (| (setSize (600,90) . title "Guess the interval") (do
+>         g1 <- leftRight $
+>                 concatA $ map (\s -> edge <<< button s) 
+>                            ["uni","min2","Maj2","min3","Maj3","4th","aug4"] -< repeat ()
+>         g2 <- leftRight $
+>                 concatA $ map (\s -> edge <<< button s)
+>                            ["5th","min6","Maj6","min7","Maj7","oct"] -< repeat ()
+>         returnA -< g1++g2) |)
+>     -- edge-detect pushbuttons:
+>     let guessesE = foldl1 (.|.) $ zipWith (->>) guesses intNameList
+>     rec -- the state
+>         state    <- delay Start <<< accum Start -< updates
+>         -- event filter based on MUI state
+>         let whileIn' :: SEvent a -> State -> SEvent a
+>             e `whileIn'` s = if s == state then e else Nothing
+>             updates  = (giveUpE `whileIn'` Base ->> const Guessed)         .|.
+>                        (nextE ->> const Base) .|. (resetE ->> const Start) .|.
+>                        (guessesE `whileIn'` Base ->> const Guessed)
+>     let whileIn :: SEvent a -> State -> SEvent a
+>         e `whileIn` s = if s == state then e else Nothing
+>  
+>     -- Random intervals:
+>     randIntE <- evMap (liftAIO mkRandInt) -< snapshot_ nextE (maxInt, lowOct, range)
+>     interval <- hold (0,0)  -< randIntE
+>     let trigger  = snapshot randIntE (dur, instr) .|.
+>                    snapshot_ repeatE (interval, (dur, instr))
+>     -- state variables:
+>     let matchE   = snapshot (guessesE `whileIn` Base) interval =>> 
+>                     \(g,(r,i)) -> if g==intNameList!!i then succ else id
+>     total   <- delay 0 <<< accum 0 -< ((guessesE `whileIn` Base ->> succ) .|.
+>                            (nextE    `whileIn` Base ->> succ) .|.
+>                            (giveUpE  `whileIn` Base ->> succ) .|.
+>                            (resetE ->> const 0)                  )
+>     correct <- delay 0 <<< accum 0 -< (matchE .|. (resetE ->> const 0))
+>     repeats <- delay 0 <<< accum 0 -< ((repeatE `whileIn` Base ->> succ) .|.
+>                            (resetE ->> const 0)                  )
+>     -- Note delays
+>     let f n pn dur = if pn==n then 1 / fromIntegral (2 ^ dur) else 0
+>         del0 = f 2 pns dur -- lo note delay only when "hi then lo"
+>         del1 = f 1 pns dur -- hi note delay only when "lo then hi"
+>     -- Random interval & Midi signals:
+>     note0 <- vdelay -< (del0, (trigger =>> mkNote 0))
+>     note1 <- vdelay -< (del1, (trigger =>> mkNote 1))
+>     nowE <- now -< ()
+>     let progChan = nowE ->> (map Std $
+>                     zipWith ProgramChange [0,1,2,3,4] [0,4,40,66,73])
+>         midiMsgs = progChan .|. (note0 `mappend` note1)
+>     -- Display results:
+>     (| (setSize (600,30) . leftRight) (do
+>         title "Score:"   $ display -< showScore correct total
+>         title "Repeats:" $ display -< show repeats
+>         title "Answer:"  $ display -< 
+>                 if state==Guessed then intNameList!!(snd interval) else ""
+>         returnA -< () )|)
+>     -- Midi output
+>     midiOut -< (mo, midiMsgs)
+>     returnA -< ()
+
+
+Auxilliary Functions:
+
+> sDisplay              = setSize (50,25) display
+> shiSlider inc ran pre = setSize (300,25) $ hiSlider inc ran pre
+> sButton str           = setSize (75,25)  $ button str
+
+> showScore     :: Int -> Int -> String
+> showScore c 0 = "0"
+> showScore c t = show c ++ "/" ++ show t ++ " = " ++ 
+>                 take 5 (show (100 * fromIntegral c / fromIntegral t)) ++ "%"
+
+> mkRandInt :: (Int,Int,Int) -> IO (Int,Int)
+> mkRandInt (maxInt,lowOct,range) = 
+>   do
+>     let low = lowOct*12
+>     int  <- randomRIO (0,maxInt) :: IO Int
+>     root <- randomRIO (low, low + range*6 - int) :: IO Int
+>     return (root,int)
+
+> mkNote :: Int -> ((Int,Int),(Int,Int)) -> [MidiMessage]
+> mkNote n ((root,int),(dur,instr)) =
+>   let durT = 1 / fromIntegral (2 ^ dur)
+>   in if n==0 then [ANote instr root 100 durT]
+>              else [ANote instr (root+int) 100 durT]
+
+0 whole   1   sec  1/2^0
+1 half    1/2 sec  1/2^1
+2 quarter 1/4 sec  1/2^2
+3 eighth  1/8 sec  1/2^3
+
+at 60 BPM a whole note is 1 sec
+
+ANote :: Channel -> Key -> Velocity -> Time -> MidiMessage
+
+--------------------------------------
+-- Yampa-style utilities
+--------------------------------------
+
+> (=>>) :: SEvent a -> (a -> b) -> SEvent b
+> (=>>) = flip fmap
+> (->>) :: SEvent a -> b -> SEvent b
+> (->>) = flip $ fmap . const
+> (.|.) :: SEvent a -> SEvent a -> SEvent a
+> (.|.) = flip $ flip maybe Just
+> 
+> snapshot :: SEvent a -> b -> SEvent (a,b)
+> snapshot = flip $ fmap . flip (,)
+> snapshot_ :: SEvent a -> b -> SEvent b
+> snapshot_ = flip $ fmap . const -- same as ->>
+ HSoM/Examples/LSystems.lhs view
@@ -0,0 +1,139 @@+> module HSoM.Examples.LSystems where
+> import Euterpea
+> import Data.List hiding (transpose)
+> import System.Random 
+
+> data DetGrammar a = DetGrammar  a           --  start symbol
+>                                 [(a,[a])]   --  productions
+>   deriving Show
+
+> detGenerate :: Eq a => DetGrammar a -> [[a]]
+> detGenerate (DetGrammar st ps) = iterate (concatMap f) [st]
+>             where f a = maybe [a] id (lookup a ps)
+
+> redAlgae = DetGrammar 'a'
+>                [  ('a',"b|c"),   ('b',"b"),  ('c',"b|d"),
+>                   ('d',"e\\d"),  ('e',"f"),  ('f',"g"),
+>                   ('g',"h(a)"),  ('h',"h"),  ('|',"|"),
+>                   ('(',"("),     (')',")"),  ('/',"\\"),
+>                   ('\\',"/")
+>                ]
+
+> t n g = sequence_ (map putStrLn (take n (detGenerate g)))
+
+> data Grammar a = Grammar  a          --  start sentence
+>                           (Rules a)  --  production rules
+>      deriving Show
+
+> data Rules a  =  Uni  [Rule a] 
+>               |  Sto  [(Rule a, Prob)]
+>      deriving (Eq, Ord, Show)
+
+> data Rule a = Rule { lhs :: a, rhs :: a }
+>      deriving (Eq, Ord, Show)
+
+> type Prob = Double
+> type ReplFun a  = [[(Rule a, Prob)]] -> (a, [Rand]) -> (a, [Rand])
+> type Rand       = Double
+
+> gen :: Ord a => ReplFun a -> Grammar a -> Int -> [a]
+> gen f (Grammar s rules) seed = 
+>     let  Sto newRules  = toStoRules rules
+>          rands         = randomRs (0.0,1.0) (mkStdGen seed)
+>     in  if checkProbs newRules
+>         then generate f newRules (s,rands)
+>         else (error "Stochastic rule-set is malformed.")
+
+> toStoRules :: (Ord a, Eq a) => Rules a -> Rules a  
+> toStoRules (Sto rs)  = Sto rs
+> toStoRules (Uni rs)  = 
+>   let rs' = groupBy (\r1 r2 -> lhs r1 == lhs r2) (sort rs)
+>   in Sto (concatMap insertProb rs')
+
+> insertProb :: [a] -> [(a, Prob)] 
+> insertProb rules =  let prb = 1.0 / fromIntegral (length rules)
+>                     in zip rules (repeat prb)
+
+> checkProbs :: (Ord a, Eq a) => [(Rule a, Prob)] -> Bool
+> checkProbs rs = and (map checkSum (groupBy sameLHS (sort rs)))
+
+> eps = 0.001 
+
+> checkSum :: [(Rule a, Prob)] -> Bool 
+> checkSum rules =  let mySum = sum (map snd rules)
+>                   in abs (1.0 - mySum) <= eps 
+
+> sameLHS :: Eq a => (Rule a, Prob) -> (Rule a, Prob) -> Bool 
+> sameLHS (r1,f1) (r2,f2) = lhs r1 == lhs r2
+
+> generate ::  Eq a =>  
+>              ReplFun a -> [(Rule a, Prob)] -> (a,[Rand]) -> [a] 
+> generate f rules xs = 
+>   let  newRules      =  map probDist (groupBy sameLHS rules)
+>        probDist rrs  =  let (rs,ps) = unzip rrs
+>                         in zip rs (tail (scanl (+) 0 ps))
+>   in map fst (iterate (f newRules) xs)
+
+> data LSys a  =  N a 
+>              |  LSys a   :+   LSys a 
+>              |  LSys a   :.   LSys a 
+>              |  Id 
+>      deriving (Eq, Ord, Show) 
+
+> replFun :: Eq a => ReplFun (LSys a)
+> replFun rules (s, rands) =
+>   case s of
+>     a :+ b  ->  let  (a',rands')   = replFun rules (a, rands )
+>                      (b',rands'')  = replFun rules (b, rands')
+>                 in (a' :+ b', rands'')
+>     a :. b  ->  let  (a',rands')   = replFun rules (a, rands )
+>                      (b',rands'')  = replFun rules (b, rands')
+>                 in (a' :. b', rands'')
+>     Id      ->  (Id, rands)
+>     N x     ->  (getNewRHS rules (N x) (head rands), tail rands)
+
+> getNewRHS :: Eq a => [[(Rule a, Prob)]] -> a -> Rand -> a
+> getNewRHS rrs ls rand = 
+>   let  loop ((r,p):rs)  = if rand <= p then rhs r else loop rs
+>        loop []          = error "getNewRHS anomaly"
+>   in case (find (\ ((r,p):_) -> lhs r == ls) rrs) of
+>         Just rs  -> loop rs
+>         Nothing  -> error "No rule match"
+
+> type IR a b = [(a, Music b -> Music b)]  --  ``interpetation rules'' 
+
+> interpret :: (Eq a) => LSys a -> IR a b -> Music b -> Music b
+> interpret (a :. b)  r m = interpret a r (interpret b r m)  
+> interpret (a :+ b)  r m = interpret a r m :+: interpret b r m
+> interpret Id        r m = m 
+> interpret (N x)     r m = case (lookup x r) of
+>                             Just f   -> f m
+>                             Nothing  -> error "No interpetation rule"
+
+> data LFun = Inc | Dec | Same
+>      deriving (Eq, Ord, Show)
+
+> ir :: IR LFun Pitch
+> ir = [ (Inc, transpose 1),
+>        (Dec, transpose (-1)),
+>        (Same, id)]
+
+> inc, dec, same :: LSys LFun
+> inc   = N Inc
+> dec   = N Dec
+> same  = N Same
+
+> sc = inc :+ dec
+
+> r1a  = Rule inc (sc :. sc)
+> r1b  = Rule inc sc
+> r2a  = Rule dec (sc :. sc)
+> r2b  = Rule dec sc
+> r3a  = Rule same inc
+> r3b  = Rule same dec
+> r3c  = Rule same same
+
+> g1 = Grammar same (Uni [r1b, r1a, r2b, r2a, r3a, r3b])
+
+> t1 n =  instrument Vibraphone $
+>         interpret (gen replFun g1 42 !! n) ir (c 5 tn)
+ HSoM/Examples/MUIExamples1.lhs view
@@ -0,0 +1,90 @@+> {-#  LANGUAGE Arrows, CPP  #-}
+
+> module HSoM.Examples.MUIExamples1 where
+> import Euterpea
+> import Data.Maybe (mapMaybe)
+> import HSoM
+> import FRP.UISF
+> import FRP.UISF.Graphics (withColor', rgbE, rectangleFilled)
+> import FRP.UISF.Widget.Construction (mkWidget)
+
+
+> ui0  ::  UISF () ()
+> ui0  =   proc _ -> do
+>     ap <- hiSlider 1 (0,100) 0 -< ()
+>     display -< pitch ap
+
+> mui0 = runMUI' ui0
+
+> ui1 ::  UISF () ()
+> ui1 =   setSize (150,150) $ 
+>   proc _ -> do
+>     ap <- title "Absolute Pitch" (hiSlider 1 (0,100) 0) -< ()
+>     title "Pitch" display -< pitch ap
+
+> mui1  =  runMUI' ui1
+
+> ui2   ::  UISF () ()
+> ui2   =   leftRight $
+>   proc _ -> do
+>     ap <- title "Absolute Pitch" (hiSlider 1 (0,100) 0) -< ()
+>     title "Pitch" display -< pitch ap
+
+> mui2  =  runMUI' ui2
+
+
+> ui3  ::  UISF () ()
+> ui3  =   proc _ -> do
+>     devid <- selectOutput -< ()
+>     ap <- title "Absolute Pitch" (hiSlider 1 (0,100) 0) -< ()
+>     title "Pitch" display -< pitch ap
+>     uap <- unique -< ap
+>     midiOut -< (devid, fmap (\k-> [ANote 0 k 100 0.1]) uap)
+
+> mui3  = runMUI' ui3
+
+
+> ui4   :: UISF () ()
+> ui4   = proc _ -> do
+>     mi  <- selectInput   -< ()
+>     mo  <- selectOutput  -< ()
+>     m   <- midiIn        -< mi
+>     midiOut -< (mo, m)
+
+> mui4  = runMUI' ui4
+
+> getDeviceIDs = topDown $
+>   proc () -> do
+>     mi    <- selectInput   -< ()
+>     mo    <- selectOutput  -< ()
+>     outA  -< (mi,mo)
+
+> mui'4 = runMUI  (defaultMUIParams 
+>                     {  uiTitle  = "MIDI Input / Output UI", 
+>                        uiSize   = (200,200)})
+>                 ui4
+
+> ui5 ::  UISF () ()
+> ui5 =   proc _ -> do
+>     devid   <- selectOutput -< ()
+>     ap      <- title "Absolute Pitch" (hiSlider 1 (0,100) 0) -< ()
+>     title "Pitch" display -< pitch ap
+>     f       <- title "Tempo" (hSlider (1,10) 1) -< ()
+>     tick    <- timer -< 1/f
+>     midiOut -< (devid, fmap (const [ANote 0 ap 100 0.1]) tick)
+
+> colorSwatchUI :: UISF () ()
+> colorSwatchUI = setSize (300, 220) $ pad (4,0,4,0) $ leftRight $ 
+>     proc _ -> do
+>         r <- newColorSlider "R" -< ()
+>         g <- newColorSlider "G" -< ()
+>         b <- newColorSlider "B" -< ()
+>         e <- unique -< (r,g,b)
+>         let rect = withColor' (rgbE r g b) (rectangleFilled ((0,0),d))
+>         pad (4,8,0,0) $ canvas d -< fmap (const rect) e
+>   where
+>     d = (170,170)
+>     newColorSlider l = title l $ withDisplay $ viSlider 16 (0,255) 0
+
+> colorSwatch = runMUI' colorSwatchUI
+
+ HSoM/Examples/MUIExamples2.lhs view
@@ -0,0 +1,178 @@+> {-# LANGUAGE Arrows #-}
+
+> module HSoM.Examples.MUIExamples2 where
+> import HSoM
+> import FRP.UISF
+> import Euterpea
+> import Data.Maybe (mapMaybe)
+
+
+=============
+Chord builder
+
+Here is a simple program that plays the selected chord when a root
+note is entered using a Midi input device.
+
+We define a mapping between chord extensions and their intervals with
+respect to the root note.
+
+> chordIntervals = [("Maj", [4,3,5]),
+>                   ("Maj7", [4,3,4,1]),
+>                   ("Maj9", [2,2,3,4,1]),
+>                   ("6", [4,3,2,3]),
+>                   ("m", [3,4,5]),
+>                   ("m7", [3,4,3,2]),
+>                   ("m9", [2,1,4,3,2]),
+>                   ("m7b5", [3,3,4,2]),
+>                   ("mMaj7", [3,4,4,1]),
+>                   ("dim", [3,3,3]),
+>                   ("7", [4,3,3,2]),
+>                   ("9", [2,2,3,3,2]),
+>                   ("7b9", [1,3,3,3,2])]
+
+We display the list of extensions on the screen as radio buttons for
+the user to click on.
+
+The toChord function takes in the index of the selected chord extension 
+and an input message as the root note, and outputs the notes of
+the selected chord based on the root note.  For simplicity, we only
+process the head of the message list and ignore everything else.
+
+> toChord :: Int -> [MidiMessage] -> [MidiMessage]
+> toChord i (ms@(m:_)) = 
+>   case m of 
+>     Std (NoteOn c k v) -> f NoteOn c k v
+>     Std (NoteOff c k v) -> f NoteOff c k v
+>     _ -> ms
+>   where f g c k v = map (\k -> Std (g c k v)) 
+>                         (scanl (+) k (snd (chordIntervals !! i)))
+
+The UI is arranged in the following way.  On the left side, the list
+of input and output devices are displayed top-down. On the right is
+the list of chord extensions.  We take the name of each extension from
+the chordIntervals list to create the radio buttons.  
+
+When a Midi input event occurs, the input message and the currently
+selected index to the list of chords is sent to the toChord function,
+and the resulting chord is sent to the output device.
+
+> buildChord = runMUI (defaultMUIParams {uiSize=(500,500), uiTitle="Chord Builder"}) $ leftRight $ proc _ -> do
+>   (mi,mo) <- topDown (selectInput &&& selectOutput) -< ()
+>   m <- midiIn -< mi
+>   i <- topDown $ title "Extension" $ radio (fst (unzip chordIntervals)) 0 -< ()
+>   midiOut -< (mo, fmap (toChord i) m)
+
+
+=================
+Bifurcate example
+
+Here is an example with some ideas borrowed from Gary Lee Nelson's
+composition "Bifurcate me, Baby!"
+
+The basic idea is to evaluate the logistic growth function at
+different points and convert the value to a musical note.  The growth
+function is given by
+
+  x_(n+1) = r x_n (1 - x_n)
+
+We start with an initial population x_0 and iteratively apply the
+growth function to it, where r is the growth rate.  For certain values
+of r, the population stablizes to a certain value, but as r increases,
+the period doubles, quadruples, and eventually leads to chaos.  It is
+one of the classic examples in chaos theory.
+
+First we define the growth function which, given a rate r and
+current population x, generates the next population.
+
+> grow :: Double -> Double -> Double
+> grow r x = r * x * (1-x)
+
+Then we define a signal 'tick' that pulsates at a given frequency
+specified by slider f.  This is the signal that will drive the
+simulation.  The timer function takes in a frequency.
+
+The next thing we need is a time-varying population.  This is where 
+the delay function and the rec keyword come in handy.  We initialize 
+the 'pop' signal with the value 0.1, and then on every tick, we 
+grow it with the instantaneous value of the growth rate signal.
+
+We can now write a simple function that maps a population value to a
+musical note:
+
+> popToNote :: Double -> [MidiMessage]
+> popToNote x = [ANote 0 n 64 0.05] where n = truncate (x * 127)
+
+Finally, to play the note, we simply send the current population to 
+popToNote, and send the result to the selected Midi output device.  
+
+> bifurcate = runMUI (defaultMUIParams {uiSize=(300,500), uiTitle="Bifurcate!"}) $ proc _ -> do
+>   mo <- selectOutput -< ()
+>   f  <- title "Frequency" $ withDisplay (hSlider (1, 10) 1) -< ()
+>   r  <- title "Growth rate" $ withDisplay (hSlider (2.4, 4.0) 2.4) -< ()
+>   
+>   tick <- timer -< 1.0 / f
+>   rec pop <- delay 0.1 -<  maybe pop (const $ grow r pop) tick
+>       
+>   _ <- title "Population" $ display -< pop
+>   midiOut -< (mo, fmap (const (popToNote pop)) tick)
+
+
+============
+Echo example
+
+Here we present a program that takes in a Midi event stream and, in
+addition to playing each note received from the input device, it also
+echoes the note at a given rate, while playing each successive note
+more softly until the velocity reduces to 0.
+
+The key component we need for this problem is a delay function that
+can delay a given event signal for a certain amount of time.  vdelay
+takes in the amount of time to delay and an input signal
+and outputs the delayed signal.
+
+There are two signals we want to attenuate.  One is the signal coming
+from the input device, and the other is the delayed and decayed signal
+containing the echoes.  In the code shown below, they are denoted as m
+and s, respectively.  We merge the two event streams into one and then 
+remove events with empty Midi messages by replacing them with Nothing.  
+The resulting signal, m', is then sent to the Midi output device.
+
+The echo signal s is created recursively from m' as follows.  We examine 
+the signal m' and decay any events that we find there, using the decay 
+rate indicated by the instantaneous value from the slider r.  This 
+decayed signal is fed into the vdelay signal function along with 
+the amount of time to delay (the inverse of the echo frequency, 
+which is given by the other slider f).
+
+> echo = runMUI (defaultMUIParams {uiSize=(500,500), uiTitle="Echo"}) $ proc _ -> do
+>   mi <- selectInput  -< ()
+>   mo <- selectOutput -< ()
+>   m <- midiIn -< mi
+>   r <- title "Decay rate" $ withDisplay (hSlider (0, 0.9) 0.5) -< ()
+>   f <- title "Echoing frequency" $ withDisplay (hSlider (1, 10) 10) -< ()
+>   
+>   rec let m' = removeNull $ mergeS m s
+>       s <- vdelay -< (1.0 / f, fmap (mapMaybe (decay 0.1 r)) m')
+>   
+>   midiOut -< (mo, m')
+
+> mergeS :: Maybe [MidiMessage] -> Maybe [MidiMessage] -> Maybe [MidiMessage]
+> mergeS (Just ns1) (Just ns2) = Just (ns1 ++ ns2)
+> mergeS n1         Nothing    = n1
+> mergeS Nothing    n2         = n2
+
+> removeNull :: Maybe [MidiMessage] -> Maybe [MidiMessage]
+> removeNull Nothing   = Nothing
+> removeNull (Just []) = Nothing
+> removeNull (Just xs) = Just xs
+
+> decay :: Time -> Double -> MidiMessage -> Maybe MidiMessage
+> decay dur r m = 
+>   let f c k v d = if v > 0 
+>                   then Just (ANote c k (truncate (fromIntegral v * r)) d)
+>                   else Nothing
+>   in case m of
+>     ANote c k v d -> f c k v d
+>     Std (NoteOn c k v) -> f c k v dur
+>     _ -> Nothing
+
+ HSoM/Examples/MoreMusic.lhs view
@@ -0,0 +1,103 @@+> module HSoM.Examples.MoreMusic where
+> import Euterpea
+
+> pr1, pr2 :: Pitch -> Music Pitch
+> pr1 p =  tempo (5/6) 
+>          (  tempo (4/3)  (  mkLn 1 p qn :+:
+>                             tempo (3/2) (  mkLn 3 p en  :+:
+>                                            mkLn 2 p sn  :+:
+>                                            mkLn 1 p qn     ) :+:
+>                             mkLn 1 p qn) :+:
+>             tempo (3/2)  (  mkLn 6 p en))
+
+> pr2 p = 
+>    let  m1   = tempo (5/4) (tempo (3/2) m2 :+: m2)
+>         m2   = mkLn 3 p en
+>    in tempo (7/6) (  m1 :+:
+>                      tempo (5/4) (mkLn 5 p en) :+:
+>                      m1 :+:
+>                      tempo (3/2) m2)
+
+> mkLn :: Int -> p -> Dur -> Music p
+> mkLn n p d = line $ take n $ repeat $ note d p
+
+> pr12  :: Music Pitch
+> pr12  = pr1 (C,4) :=: pr2 (G,4)
+
+
+> trill :: Int -> Dur -> Music Pitch -> Music Pitch
+> trill i sDur (Prim (Note tDur p)) =
+>    if sDur >= tDur  then note tDur p
+>                     else  note sDur p :+: 
+>                           trill  (negate i) sDur 
+>                                  (note (tDur-sDur) (trans i p))
+> trill i d (Modify (Tempo r) m)  = tempo r (trill i (d*r) m)
+> trill i d (Modify c m)          = Modify c (trill i d m)
+> trill _ _ _                     = 
+>       error "trill: input must be a single note."
+> {-# LINE 702 "MoreMusic.lhs" #-}
+> trill' :: Int -> Dur -> Music Pitch -> Music Pitch
+> trill' i sDur m = trill (negate i) sDur (transpose i m)
+
+> trilln :: Int -> Int -> Music Pitch -> Music Pitch
+> trilln i nTimes m = trill i (dur m / fromIntegral nTimes) m
+
+> trilln' :: Int -> Int -> Music Pitch -> Music Pitch
+> trilln' i nTimes m = trilln (negate i) nTimes (transpose i m)
+
+> roll  :: Dur -> Music Pitch -> Music Pitch
+> rolln :: Int -> Music Pitch -> Music Pitch
+
+> roll  dur    m = trill  0 dur m
+> rolln nTimes m = trilln 0 nTimes m
+
+> ssfMel :: Music Pitch
+> ssfMel = line (l1 ++ l2 ++ l3 ++ l4)
+>   where  l1  = [ trilln 2 5 (bf 6 en), ef 7 en, ef 6 en, ef 7 en ]
+>          l2  = [ bf 6 sn, c  7 sn, bf 6 sn, g 6 sn, ef 6 en, bf 5 en ]
+>          l3  = [ ef 6 sn, f 6 sn, g 6 sn, af 6 sn, bf 6 en, ef 7 en ]
+>          l4  = [ trill 2 tn (bf 6 qn), bf 6 sn, denr ]
+
+> starsAndStripes :: Music Pitch
+> starsAndStripes = instrument Flute ssfMel
+
+> grace :: Int -> Rational -> Music Pitch -> Music Pitch
+> grace n r (Prim (Note d p))  =
+>       note (r*d) (trans n p) :+: note ((1-r)*d) p
+> grace n r _                  = 
+>       error "grace: can only add a grace note to a note"
+
+> grace2 ::  Int -> Rational -> 
+>            Music Pitch -> Music Pitch -> Music Pitch
+> grace2 n r (Prim (Note d1 p1)) (Prim (Note d2 p2)) =
+>       note (d1-r*d2) p1 :+: note (r*d2) (trans n p2) :+: note d2 p2
+> grace2 _ _ _ _  = 
+>       error "grace2: can only add a grace note to a note"
+
+> funkGroove :: Music Pitch
+> funkGroove
+>   =  let  p1  = perc LowTom         qn
+>           p2  = perc AcousticSnare  en
+>      in  tempo 3 $ instrument Percussion $ cut 8 $ forever
+>          (  (  p1 :+: qnr :+: p2 :+: qnr :+: p2 :+:
+>                p1 :+: p1 :+: qnr :+: p2 :+: enr)
+>             :=: roll en (perc ClosedHiHat 2) )
+
+
+> rep ::  (Music a -> Music a) -> (Music a -> Music a) -> Int 
+>         -> Music a -> Music a
+> rep f g 0 m  = rest 0
+> rep f g n m  = m :=: g (rep f g (n-1) (f m))
+
+> run,  cascade,  cascades,  final :: Music Pitch
+> run', cascade', cascades', final' :: Music Pitch
+
+> run       = rep (transpose 5) (offset tn) 8 (c 4 tn)
+> cascade   = rep (transpose 4) (offset en) 8 run
+> cascades  = rep  id           (offset sn) 2 cascade
+
+> final = cascades :+: retro cascades
+> run'       = rep (offset tn) (transpose 5) 8 (c 4 tn)
+> cascade'   = rep (offset en) (transpose 4) 8 run'
+> cascades'  = rep (offset sn)  id           2 cascade'
+> final'     = cascades' :+: retro cascades'
+ HSoM/Examples/MusicToSignal.lhs view
@@ -0,0 +1,111 @@+> {-# LANGUAGE Arrows #-}
+
+This file demonstrates how to turn a Music value into an audio signal 
+using the Render module.
+
+> module HSoM.Examples.MusicToSignal where
+> import HSoM
+> import Euterpea
+
+First, define some instruments.
+
+> reedyWav = tableSinesN 1024 [0.4, 0.3, 0.35, 0.5, 0.1, 0.2, 0.15, 
+>                            0.0, 0.02, 0.05, 0.03]
+
+> reed :: Instr (Stereo AudRate)
+> reed dur pch vol params = 
+>     let reedy = osc reedyWav 0
+>         freq  = apToHz pch
+>         vel   = fromIntegral vol / 127 / 3
+>         env   = envLineSeg [0, 1, 0.8, 0.6, 0.7, 0.6, 0] 
+>                            (replicate 6 (fromRational dur/6))
+>     in proc _ -> do
+>       amp <- env -< ()
+>       r1 <- reedy -< freq
+>       r2 <- reedy -< freq + (0.023 * freq)
+>       r3 <- reedy -< freq + (0.019 * freq)
+>       let [a1, a2, a3] = map (* (amp * vel)) [r1, r2, r3]
+>       let rleft = a1 * 0.5 + a2 * 0.44 * 0.35 + a3 * 0.26 * 0.65
+>           rright = a1 * 0.5 + a2 * 0.44 * 0.65 + a3 * 0.26 * 0.35
+>       outA -< (rleft, rright)
+
+> saw = tableSinesN 4096 [1, 0.5, 0.333, 0.25, 0.2, 0.166, 0.142, 0.125, 
+>                         0.111, 0.1, 0.09, 0.083, 0.076, 0.071, 0.066, 0.062]
+
+> plk :: Instr (Stereo AudRate)
+> plk dur pch vol params = 
+>     let vel  = fromIntegral vol / 127 / 3
+>         freq = apToHz pch
+>         sf   = pluck saw freq SimpleAveraging
+>     in proc _ -> do
+>          a <- sf -< freq
+>          outA -< (a * vel * 0.4, a * vel * 0.6)
+
+Define some instruments:
+
+> myBass, myReed :: InstrumentName
+> myBass = CustomInstrument "pluck-like"
+> myReed = CustomInstrument "reed-like"
+
+Construct a custom instrument map.  An instrument map is just 
+an association list containing mappings from InstrumentName to Instr.
+
+> myMap :: InstrMap (Stereo AudRate)
+> myMap = [(myBass, plk), (myReed, reed)]
+
+> bass   = mMap (\p-> (p, 40 :: Volume)) $ instrument myBass bassLine
+> melody = mMap (\p-> (p,100 :: Volume)) $ instrument myReed mainVoice
+
+> childSong6 :: Music (Pitch, Volume)
+> childSong6 = tempo 1.5 (bass :=: melody)
+
+All instruments used in the same performance must output the same number 
+of channels, but renderSF supports both mono or stereo instruments 
+(and any instrument that produces samples in the AudioSample type class).
+The outFile function will produce a monaural or stereo file accordingly.
+
+> recordSong = uncurry (outFile "song.wav") (renderSF childSong6 myMap)
+
+> main = recordSong
+
+This stuff is taken from Euterpea.Examples.Interlude:
+
+> bassLine =  times 3 b1 :+: times 2 b2 :+: 
+>             times 4 b3 :+: times 5 b1
+
+> mainVoice = times 3 v1 :+: v2
+
+> v1   = v1a :+: graceNote (-1) (d 5 qn) :+: v1b                 -- bars 1-2
+> v1a  = addDur en [a 5, e 5, d 5, fs 5, cs 5, b 4, e 5, b 4]
+> v1b  = addDur en [cs 5, b 4]
+
+> v2 = v2a :+: v2b :+: v2c :+: v2d :+: v2e :+: v2f :+: v2g
+> v2a  =  line [  cs 5 (dhn+dhn), d 5 dhn, 
+>                 f 5 hn, gs 5 qn, fs 5 (hn+en), g 5 en]
+> v2b  =  addDur en [  fs 5, e 5, cs 5, as 4] :+: a 4 dqn :+:
+>         addDur en [  as 4, cs 5, fs 5, e 5, fs 5]
+> v2c  =  line [  g 5 en, as 5 en, cs 6 (hn+en), d 6 en, cs 6 en] :+:
+>         e 5 en :+: enr :+: 
+>         line [  as 5 en, a 5 en, g 5 en, d 5 qn, c 5 en, cs 5 en] 
+> v2d  =  addDur en [  fs 5, cs 5, e 5, cs 5, 
+>                      a 4, as 4, d 5, e 5, fs 5]
+> v2e  =  line [  graceNote 2 (e 5 qn), d 5 en, graceNote 2 (d 5 qn), cs 5 en,
+>                 graceNote 1 (cs 5 qn), b 4 (en+hn), cs 5 en, b 4 en ]  
+> v2f  =  line [  fs 5 en, a 5 en, b 5 (hn+qn), a 5 en, fs 5 en, e 5 qn,
+>                 d 5 en, fs 5 en, e 5 hn, d 5 hn, fs 5 qn]
+> v2g  =  tempo (3/2) (line [cs 5 en, d 5 en, cs 5 en]) :+: 
+>         b 4 (3*dhn+hn)
+
+> b1  = addDur dqn [b 3,   fs 4,  g 4,   fs 4]
+> b2  = addDur dqn [b 3,   es 4,  fs 4,  es 4]
+> b3  = addDur dqn [as 3,  fs 4,  g 4,   fs 4]
+
+> addDur       :: Dur -> [Dur -> Music a] -> Music a
+> addDur d ns  =  let f n = n d
+>                 in line (map f ns)
+
+> graceNote :: Int -> Music Pitch -> Music Pitch
+> graceNote n  (Prim (Note d p))  =
+>           note (d/8) (trans n p) :+: note (7*d/8) p
+> graceNote n  _                  = 
+>           error "Can only add a grace note to a note."
+ HSoM/Examples/NewResolutions.lhs view
@@ -0,0 +1,227 @@+New Resolutions by Jean-Luc Ponty, Scott O'Neil, and John Garvin
+
+> module HSoM.Examples.NewResolutions where
+> import Euterpea
+> import HSoM
+
+> nrContext = Context {cTime = 0,
+>                      cPlayer = fancyPlayer,
+>                      cInst = Marimba,
+>                      cDur = 1.0,
+>                      cPch = 0,
+>                      cKey = (C,Major),
+>                      cVol = 100}
+>
+
+
+> root, minThird, fifth, octave :: Pitch -> Dur -> Music Pitch
+> root       p dur = Prim $ Note dur p
+> minThird   p dur = Prim $ Note dur (trans 3 p)
+> majThird   p dur = Prim $ Note dur (trans 4 p)
+> fifth      p dur = Prim $ Note dur (trans 7 p)
+> majSixth   p dur = Prim $ Note dur (trans 9 p)
+> minSeventh p dur = Prim $ Note dur (trans 10 p)
+> octave     p dur = Prim $ Note dur (trans 12 p)
+> oMinThird  p dur = Prim $ Note dur (trans 15 p)
+> oFifth     p dur = Prim $ Note dur (trans 19 p)
+
+> minArpegUp, minArpegDown :: Pitch -> Dur -> Music Pitch
+> minArpegUp p d = root p d
+>                  :+: minThird p d
+>                  :+: fifth p d 
+>                  :+: octave p d
+> minArpegDown p d = octave p d
+>                :+: fifth p d
+>                :+: minThird p d
+>                :+: root p d
+> majArpegDown p d = octave p d
+>                :+: fifth p d
+>                :+: majThird p d
+>                :+: root p d
+> six3ArpegDown p d = octave p d
+>                 :+: majSixth p d
+>                 :+: majThird p d
+>                 :+: root p d
+
+> pattern = minArpegUp (D,5) sn
+>       :+: minArpegDown (C,5) sn
+>       :+: minArpegUp (A,4) sn
+>       :+: minArpegDown (G,4) sn
+>       :+: minArpegUp (F,4) sn
+>       :+: d 5 sn :+: a 4 sn :+: f 4 sn :+: a 4 sn
+
+> melPattern = d 6 en :+: c 6 en :+: d 6 en
+>          :+: snr
+>          :+: a 5 en :+: g 5 en :+: a 5 en
+
+> melody1 = melPattern :+: enr :+: d 5 sn
+>       :+: f 5 sn :+: g 5 en :+: f 5 sn :+: d 5 en :+: c 5 en
+>       :+: d 5 en :+: melPattern :+: d 5 sn
+>       :+: f 5 sn :+: f 5 sn :+: g 5 sn :+: f 5 sn
+>       :+: d 5 sn :+: c 5 en :+: d 5 den
+>       :+: melPattern :+: d 5 sn
+>       :+: f 5 sn :+: g 5 sn :+: f 5 sn :+: d 5 en
+>       :+: c 5 sn :+: d 5 en
+>       :+: d 6 en :+: c 6 en :+: d 6 den :+: c 6 en
+>       :+: a 5 en :+: c 6 en :+: a 5 sn :+: g 5 en
+>       :+: f 5 en :+: af 5 en
+>       :+: g 5 sn :+: f 5 sn :+: d 5 sn :+: c 5 sn 
+> -- last note removed to make fit with pattern
+
+> bellPart = d 7 en :+: f 7 en :+: c 7 en :+: d 7 en
+>        :+: a 6 en :+: c 7 en :+: g 6 en :+: a 6 en
+>        :+: f 6 en :+: g 6 en
+>        :+: d 6 sn :+: f 6 sn :+: a 6 sn :+: c 7 sn
+
+> vibesLine = d 5 qn :+: c 5 qn :+: a 4 qn
+>         :+: g 4 qn :+: f 4 qn :+: d 4 qn
+> vibesPart = vibesLine :=: Modify (Transpose 12) vibesLine
+
+> cMajorScale = [(C,0), (D,0), (E,0), (F,0), (G,0), (A,0), (B,0)]
+> gMajorScale = [(G,0), (A,0), (B,0), (C,1), (D,1), (E,1), (Fs,1)]
+> dPentMinScale = [(D,0), (F,0), (G,0), (A,0), (C,1)]
+
+> prevNote []         _       = error ("Scale empty")
+> prevNote [x]        _       = error ("Note not found in scale")
+> prevNote ((y,n):ys) (p,oct) | y == p = let (x,m) = last ys
+>                                        in (x, oct + m - n - 1)
+> prevNote ((x,m):(y,n):xys) (p,oct) | y == p    = (x, oct + m - n)
+>                                    | otherwise = prevNote ((y,n):xys) (p,oct)
+
+> nextNote scale note = nextNote' (head scale) scale note
+> nextNote' _ [] _ = error ("Scale empty")
+> nextNote' (fstP,fstO) [(x,m)]           (p,oct)
+>                                       | x == p    = (fstP, oct - m + fstO + 1)
+>                                       | otherwise = error ("Note not found in scale")
+> nextNote' fst         ((x,m):(y,n):xys) (p,oct)
+>                                       | x == p    = (y, oct - m + n)
+>                                       | otherwise = nextNote' fst ((y,n):xys) (p,oct)
+
+> back2Note s = prevNote s . prevNote s
+
+> nextNR = nextNote dPentMinScale
+> prevNR = prevNote dPentMinScale
+> back2NR = back2Note dPentMinScale
+
+> diddle p = snr :+: Prim (Note sn p) 
+>            :+: Prim (Note sn (prevNR p)) :+: Prim (Note sn p)
+
+> melody2 = d 6 sn :+: d 6 en :+: c 6 en :+: d 6 sn :+: c 6 en
+>       :+: a 5 en :+: g 5 sn :+: f 5 sn
+>       :+: g 5 sn :+: f 5 sn :+: d 5 sn :+: f 5 sn
+>       :+: diddle (D,5) :+: diddle (C,5)
+>       :+: diddle (D,6) :+: diddle (C,6) :+: diddle (A,5)
+>       :+: diddle (G,5) :+: diddle (F,5) :+: diddle (D,5)
+>       :+: snr :+: d 6 en :+: c 6 en :+: d 6 den
+>       :+: c 6 en :+: a 5 en :+: g 5 den
+>       :+: f 5 en :+: g 5 en :+: f 5 sn
+>       :+: g 5 sn :+: f 5 sn :+: d 5 sn :+: c 5 sn
+>       :+: d 5 den :+: d 6 en :+: c 6 den :+: a 5 en :+: g 5 den
+>       :+: f 5 en :+: d 5 den :+: c 5 en :+: d 5 qn
+
+> part1 = Modify (Instrument Marimba) (Modify (Phrase [Dyn (Loudness 70)]) pattern)
+>         :+:
+>         Modify (Instrument Xylophone) (Modify (Phrase [Dyn (Loudness 120)]) melody1)
+>     :=: Modify (Instrument Marimba) (Modify (Phrase [Dyn (Loudness 70)]) (times 4 pattern))
+> bridge = Modify (Instrument Xylophone) (d 5 hn) -- (d 5 hn [Volume 120])
+>      :=: (times 2 $
+>          Modify (Instrument Marimba) (Modify (Phrase [Dyn (Loudness 60)]) (Modify (Transpose (-12)) bellPart))
+>      :=: Modify (Instrument Vibraphone) (Modify (Phrase [Dyn (Loudness 40)]) vibesPart)
+>      :=: Modify (Instrument Glockenspiel) (Modify (Phrase [Dyn (Loudness 80)]) bellPart))
+> part2 = Modify (Instrument Xylophone) (Modify (Phrase [Dyn (Loudness 120)]) melody2)
+>     :=: Modify (Instrument Marimba) (Modify (Phrase [Dyn (Loudness 70)]) (times 3 pattern
+>                                                  :+: minArpegUp   (D,5) sn
+>                                                  :+: minArpegDown (C,5) sn
+>                                                  :+: minArpegUp   (A,4) sn
+>                                                  :+: minArpegDown (G,4) sn
+>                                                  :+: minArpegUp   (F,4) sn
+>                                                  :+: d 5 sn))
+>     :=: times 4 (Modify (Instrument Vibraphone) (Modify (Phrase [Dyn (Loudness 40)]) vibesPart))
+
+> run1 p d = root p d       :+: minThird p d  :+: fifth p d
+>        :+: minSeventh p d :+: octave p d    :+: oMinThird p d
+>        :+: oFifth p d     :+: oMinThird p d :+: octave p d
+>        :+: minSeventh p d :+: fifth p d      :+: minThird p d
+
+> part3Pattern el = el (D,4) sn :+: el (C,4) sn :+: el (D,4) sn :+: el (F,4) sn
+
+> run2 p d = times 2 $
+>       fifth p d     :+: minSeventh p d :+: octave p d
+>   :+: oMinThird p d :+: octave p d     :+: minSeventh p d
+
+> run3 p d = times 3 $
+>       oMinThird p d :+: octave p d :+: minSeventh p d :+: fifth p d
+
+> vibeLine3 = let el = \p -> octave p den :+: fifth p den
+>                        :+: minSeventh p den :+: octave p den
+>             in el (D,4) :+: el (C,4) :+: el (D,4)
+>                :+: f 5 den :+: c 5 den
+>                :+: ef 5 en :+: f 5 en :+: af 5 en
+> vibePart3 = vibeLine3 :=: Modify (Transpose 12) vibeLine3
+
+> melody3 = a 5 (11/16) :+: f 6 sn
+>       :+: ef 6 en :+: d 6 en :+: c 6 en :+: g 5 dqn
+>       :+: times 3 (a 5 sn :+: f 6 en) :+: a 5 en
+>       :+: f 6 en :+: af 5 en :+: f 6 en :+: af 5 en
+>       :+: minArpegDown (F,5) sn :+: snr
+>       :+: majArpegDown (F,5) sn :+: snr
+>       :+: six3ArpegDown (F,5) sn :+: snr :+: f 6 sn :+: d 6 sn
+>       :+: ef 6 sn :+: d 6 sn :+: c 6 sn :+: g 5 sn :+: snr
+>       :+: majArpegDown (Ef,5) sn :+: snr :+: ef 6 sn :+: c 6 sn
+>       :+: majArpegDown (F,5) sn :+: snr
+>       :+: six3ArpegDown (F,5) sn :+: snr :+: f 6 sn :+: d 6 sn
+>       :+: minArpegDown (F,5) sn :+: snr
+>       :+: minArpegDown (F,5) sn :+: af 5 sn :+: c 6 sn :+: f 6 sn
+>       :+: line (map (times 2) [f 6 sn, d 6 sn, c 6 sn,
+>                                a 5 sn, g 5 sn, f 5 sn])
+>       :+: ef 5 sn :+: f 5 sn :+: g 5 sn :+: bf 5 sn
+>       :+: c 6 sn :+: d 6 sn :+: ef 6 sn :+: d 6 sn
+>       :+: c 6 sn :+: bf 5 sn :+: a 5 sn :+: g 5 sn
+>       :+: times 4 (a 5 sn :+: a 5 sn :+: g 5 sn)
+>       :+: times 2 (af 5 sn :+: af 5 sn :+: g 5 sn)
+>       :+: times 2 (af 5 sn :+: g 5 sn :+: f 5 sn)
+>       :+: a 5 dqn
+>       :+: f 6 sn :+: d 6 sn :+: c 6 sn
+>       :+: a 5 sn :+: g 5 sn :+: f 5 sn
+>       :+: g 5 sn :+: bf 5 sn :+: ef 6 dqn
+>       :+: bf 6 den :+: bf 6 sn
+>       :+: a 6 en :+: a 6 sn :+: g 6 en :+: g 6 sn
+>       :+: f 6 den :+: a 5 sn :+: c 6 sn :+: d 6 sn
+>       :+: f 6 den :+: f 6 sn :+: d 6 sn :+: c 6 sn
+>       :+: af 5 sn :+: af 5 sn :+: g 5 sn
+>       :+: f 5 sn :+: d 5 sn :+: c 5 sn
+
+> harmony3 = Modify (Phrase [Dyn (Loudness 60)]) (part3Pattern run1
+>                                    :=: part3Pattern run2
+>                                    :=: Modify (Transpose 12) (part3Pattern run3))
+>        :=: Modify (Phrase [Dyn (Loudness 50)]) (Modify (Instrument Vibraphone) vibePart3)
+
+> part3 = Modify (Phrase [Dyn (Loudness 60)]) (part3Pattern run1)
+>     :+: (Modify (Phrase [Dyn (Loudness 60)]) (part3Pattern run1)
+>          :=: Modify (Phrase [Dyn (Loudness 90)]) (part3Pattern run2))
+>     :+: (Modify (Phrase [Dyn (Loudness 60)]) ((part3Pattern run1) 
+>                                               :=: (part3Pattern run2))
+>          :=: Modify (Phrase [Dyn (Loudness 100)]) (Modify (Transpose 12) (part3Pattern run3)))
+>     :+: Modify (Phrase [Dyn (Loudness 60)]) (part3Pattern run1
+>                                              :=: part3Pattern run2
+>                                              :=: Modify (Transpose 12) (part3Pattern run3))
+>     :=: Modify (Phrase [Dyn (Loudness 70)]) (Modify (Instrument Vibraphone) vibePart3)
+>     :+: (times 4 harmony3 :=: Modify (Phrase [Dyn (Loudness 100)]) (Modify (Instrument Xylophone) melody3)
+>                                                        :=: (Modify (Instrument Marimba) melody3))
+
+> all3Insts m = Modify (Instrument Marimba) m
+>           :=: Modify (Instrument Xylophone) m
+>           :=: Modify (Instrument Vibraphone) m
+
+> endEl n = Prim (Note sn n)          :+: Prim (Note sn (back2NR n))
+>       :+: Prim (Note sn (prevNR n)) :+: Prim (Note sn n)
+
+> endRun = line $ map endEl $ take 10 $ iterate nextNR (D,5)
+
+> ending = all3Insts $
+>       Prim (Note qn (D,5))
+>   :+: Modify (Phrase [Dyn (Loudness 120)]) (endRun :+: d 7 sn)
+
+> newResolutions = part1 :+: bridge :+: part2 :+: part3 :+: ending
+
+> nr = play newResolutions
+ HSoM/Examples/PhysicalModeling.lhs view
@@ -0,0 +1,58 @@+> {-#  LANGUAGE Arrows  #-}
+
+> module HSoM.Examples.PhysicalModeling where
+> import Euterpea
+> import FRP.UISF.AuxFunctions
+
+> sineTable441 :: Table
+> sineTable441 = tableSinesN 100 [1]
+
+> s441 :: AudSF () Double
+> s441 = proc () -> do
+>          rec s <- delayLineT 100 sineTable441 -< s
+>          outA -< s
+
+> ts441 = outFile "s441.wav" 5 s441
+
+> echo :: AudSF Double Double
+> echo = proc s -> do
+>          rec fb  <- delayLine 0.5 -< s + 0.7*fb
+>          outA -< fb/3
+
+
+> modVib :: Double -> Double -> AudSF Double Double
+> modVib rate depth =
+>   proc sin -> do
+>     vib   <- osc sineTable 0  -< rate
+>     sout  <- delayLine1 0.2   -< (sin,0.1+0.005*vib)
+>     outA -< sout
+
+> tModVib = outFile "modvib.wav" 6 $
+>                   constA 440 >>> osc sineTable 0 >>> modVib 5 0.005
+
+> sineTable :: Table
+> sineTable = tableSinesN 4096 [1]
+
+
+
+> flute ::  Time -> Double -> Double -> Double -> Double 
+>           -> AudSF () Double
+> flute dur amp fqc press breath = 
+>   proc () -> do
+>     env1   <- envLineSeg  [0, 1.1*press, press, press, 0] 
+>                           [0.06, 0.2, dur-0.16, 0.02]  -< ()
+>     env2   <- envLineSeg  [0, 1, 1, 0] 
+>                           [0.01, dur-0.02, 0.01]       -< ()
+>     envib  <- envLineSeg  [0, 0, 1, 1] 
+>                           [0.5, 0.5, dur-1]            -< ()
+>     flow   <- noiseWhite 42    -< ()
+>     vib    <- osc sineTable 0  -< 5
+>     let  emb = breath*flow*env1 + env1 + vib*0.1*envib
+>     rec  flute  <- delayLine (1/fqc)    -< out
+>          x      <- delayLine (1/fqc/2)  -< emb + flute*0.4
+>          out    <- filterLowPassBW -< (x-x*x*x + flute*0.4, 2000)
+>     outA -< out*amp*env2
+    
+
+> tFlute = outFile "tFlute.wav" 5 $ flute 5 0.3 440 0.99 0.2 
+> tFlute2 = outFileNorm "tFlute2.wav" 5 $ flute 5 0.7 440 0.99 0.2 
+ HSoM/Examples/RandomMusic.lhs view
@@ -0,0 +1,119 @@+> module HSoM.Examples.RandomMusic where
+> import Euterpea
+> import System.Random
+> import System.Random.Distributions
+> import qualified Data.MarkovChain as M
+
+
+> sGen :: StdGen
+> sGen = mkStdGen 42
+
+> randInts :: StdGen -> [Int]
+> randInts g =  let (x,g') = next g
+>               in x : randInts g'
+
+> randFloats :: [Float]
+> randFloats = randomRs (-1,1) sGen
+
+> randIntegers :: [Integer]
+> randIntegers = randomRs (0,100) sGen
+
+> randString :: String
+> randString = randomRs ('a','z') sGen
+
+> randIO :: IO Float
+> randIO = randomRIO (0,1)
+
+> randIO' :: IO ()
+> randIO' = do  r1 <- randomRIO (0,1) :: IO Float
+>               r2 <- randomRIO (0,1) :: IO Float
+>               print (r1 == r2)
+
+> toAbsP1    :: Float -> AbsPitch
+> toAbsP1 x  = round (40*x + 30)
+
+> mkNote1  :: AbsPitch -> Music Pitch
+> mkNote1  = note tn . pitch
+
+> mkLine1        :: [AbsPitch] -> Music Pitch
+> mkLine1 rands  = line (take 32 (map mkNote1 rands))
+
+uniform distribution
+
+> m1 :: Music Pitch
+> m1 = mkLine1 (randomRs (30,70) sGen)
+
+linear distribution
+
+> m2 :: Music Pitch
+> m2 =  let rs1 = rands linear sGen
+>       in mkLine1 (map toAbsP1 rs1)
+
+exponential distribution
+
+> m3      :: Float -> Music Pitch
+> m3 lam  =  let rs1 = rands (exponential lam) sGen
+>            in mkLine1 (map toAbsP1 rs1)
+
+Gaussian distribution
+
+> m4 :: Float -> Float -> Music Pitch
+> m4 sig mu   =  let rs1 = rands (gaussian sig mu) sGen
+>                in mkLine1 (map toAbsP1 rs1)
+
+
+Gaussian distribution with mean set to 0
+
+> m5      :: Float -> Music Pitch
+> m5 sig  =  let rs1 = rands (gaussian sig 0) sGen
+>            in mkLine2 50 (map toAbsP2 rs1)
+
+exponential distribution with mean adjusted to 0
+
+> m6      :: Float -> Music Pitch
+> m6 lam  =  let rs1 = rands (exponential lam) sGen
+>            in mkLine2 50 (map (toAbsP2 . subtract (1/lam)) rs1)
+
+> toAbsP2     :: Float -> AbsPitch
+> toAbsP2 x   = round (5*x)
+
+> mkLine2 :: AbsPitch -> [AbsPitch] -> Music Pitch
+> mkLine2 start rands = 
+>    line (take 64 (map mkNote1 (scanl (+) start rands)))
+
+> m2' = let rs1 = rands linear sGen
+>       in sum (take 1000 rs1) / 1000 :: Float
+
+> m5' sig = let rs1 = rands (gaussian sig 0) sGen
+>           in sum (take 1000 rs1)
+
+> m6' lam = let rs1 = rands (exponential lam) sGen
+>               rs2 = map (subtract (1/lam)) rs1
+>           in sum (take 1000 rs2)
+
+some sample training sequences
+
+> ps0,ps1,ps2 :: [Pitch]
+> ps0  = [(C,4), (D,4), (E,4)]
+> ps1  = [(C,4), (D,4), (E,4), (F,4), (G,4), (A,4), (B,4)]
+> ps2  = [  (C,4), (E,4), (G,4), (E,4), (F,4), (A,4), (G,4), (E,4),
+>           (C,4), (E,4), (G,4), (E,4), (F,4), (D,4), (C,4)]
+
+functions to package up run and runMulti
+
+> mc    ps   n = mkLine3 (M.run n ps 0 (mkStdGen 42))
+> mcm   pss  n = mkLine3 (concat (M.runMulti  n pss 0 
+>                                             (mkStdGen 42)))
+
+music-making functions
+
+> mkNote3     :: Pitch -> Music Pitch
+> mkNote3     = note tn
+
+> mkLine3     :: [Pitch] -> Music Pitch
+> mkLine3 ps  = line (take 64 (map mkNote3 ps))
+
+testing the Markov output directly
+
+> lc  ps n    = take 1000 (M.run n ps 0 (mkStdGen 42))
+> lcl pss n m = take 1000 (M.runMulti n pss 0 (mkStdGen 42) !! m)
+ HSoM/Examples/SSF.lhs view
@@ -0,0 +1,22 @@+The first phrase of the flute part of "Stars and Stripes Forever."
+
+> module HSoM.Examples.SSF where
+> import Euterpea
+> import HSoM.Examples.MoreMusic
+
+> legato = Legato (11/10)
+> staccato = Staccato (5/10)
+>
+> ssfMelody = line (m1 ++ m2 ++ m3 ++ m4)
+
+> m1 = [trilln 2 5 (bf 5 en), Modify (Phrase [Art staccato]) (line [ef 6 en, ef 5 en, ef 6 en])]
+
+> m2 = [Modify (Phrase [Art legato]) (line [bf 5 sn, c  6 sn, bf 5 sn, g  5 sn]),
+>	    Modify (Phrase [Art staccato])    (line [ef 5 en, bf 4 en])]
+
+> m3 = [Modify (Phrase [Art legato]) (line [ef 5 sn, f  5 sn, g  5 sn, af 5 sn]),
+>	    Modify (Phrase [Art staccato])    (line [bf 5 en, ef 6 en])]
+
+> m4 = [trill 2 tn (bf 5 qn), bf 5 sn, denr]
+
+> ssf = Modify (Instrument Flute) ssfMelody
+ HSoM/Examples/SelfSimilar.lhs view
@@ -0,0 +1,77 @@+
+
+> module HSoM.Examples.SelfSimilar where
+> import Euterpea
+
+> data Cluster  = Cluster SNote [Cluster]
+> type SNote    = (Dur,AbsPitch)
+
+> selfSim      :: [SNote] -> Cluster
+> selfSim pat  = Cluster (0,0) (map mkCluster pat)
+>     where mkCluster note =
+>             Cluster note (map (mkCluster . addMult note) pat)
+
+> addMult                  :: SNote -> SNote -> SNote
+> addMult (d0,p0) (d1,p1)  = (d0*d1,p0+p1)
+
+> fringe                       :: Int -> Cluster -> [SNote]
+> fringe 0 (Cluster note cls)  = [note]
+> fringe n (Cluster note cls)  = concatMap (fringe (n-1)) cls
+
+
+> simToMusic     :: [SNote] -> Music Pitch
+> simToMusic     = line . map mkNote
+
+> mkNote         :: (Dur,AbsPitch) -> Music Pitch
+> mkNote (d,ap)  = note d (pitch ap)
+
+
+> ss pat n tr te = 
+>    transpose tr $ tempo te $ simToMusic $ fringe n $ selfSim pat
+
+> m0   :: [SNote]
+> m0   = [(1,2),(1,0),(1,5),(1,7)]
+
+> tm0  = instrument Vibraphone (ss m0 4 50 20)
+> ttm0 = tm0 :=: transpose (12) (retro tm0)
+
+> m1   :: [SNote]
+> m1   = [(1,0),(0.5,0),(0.5,0)]
+
+> tm1  = instrument Percussion (ss m1 4 43 2)
+> m2   :: [SNote]
+> m2   = [(dqn,0),(qn,4)]
+
+> tm2  = ss m2 6 50 (1/50)
+> m3    :: [SNote]
+> m3    = [(hn,3),(qn,4),(qn,0),(hn,6)]
+
+> tm3   = ss m3 4 50 (1/4)
+
+> ttm3  =  let  l1 =  instrument Flute tm3
+>               l2 =  instrument AcousticBass $
+>                       transpose (-9) (retro tm3)
+>          in l1 :=: l2
+
+> m4    :: [SNote]
+> m4    = [  (hn,3),(hn,8),(hn,22),(qn,4),(qn,7),(qn,21),
+>            (qn,0),(qn,5),(qn,15),(wn,6),(wn,9),(wn,19) ]
+
+> tm4   = ss m4 3 50 8
+> fringe'                        :: Int -> Cluster -> [[SNote]]
+> fringe' 0  (Cluster note cls)  = [[note]]
+> fringe' n  (Cluster note cls)  = map (fringe (n-1)) cls
+
+> simToMusic'  :: [[SNote]] -> Music Pitch
+> simToMusic'  = chord . map (line . map mkNote)
+
+> ss' pat n tr te = 
+>    transpose tr $ tempo te $ simToMusic' $ fringe' n $ selfSim pat
+
+> ss1  = ss' m2 4 50 (1/8)
+> ss2  = ss' m3 4 50 (1/2)
+> ss3  = ss' m4 3 50 2
+
+> m5   = [(en,4),(sn,7),(en,0)]
+> ss5  = ss  m5 4 45 (1/500)
+> ss6  = ss' m5 4 45 (1/1000)
+ HSoM/Examples/SoundCheck.lhs view
@@ -0,0 +1,49 @@+> {-# LANGUAGE Arrows #-}
+
+> module HSoM.Examples.SoundCheck where
+> import Euterpea
+
+> sineTable     = tableSinesN 16384 [1]
+> sawtoothTable = tableSinesN 16384 
+>                   [1, 0.5, 0.3, 0.25, 0.2, 0.167, 0.14, 0.125, 0.111]
+
+> oscSine = osc sineTable 0
+
+> sine :: AudSF () Double
+> sine = 
+>     proc _ -> do
+>       oscSine -< 440
+
+> sine_am :: AudSF () Double
+> sine_am = 
+>     proc _ -> do
+>       amp  <- oscSine -< 5
+>       s    <- oscSine -< 440
+>       outA -< amp * s
+
+> sine_fm :: AudSF () Double
+> sine_fm = 
+>     proc _ -> do
+>       frq <- oscSine -< 3
+>       oscSine -< 330 + frq * 110 -- oscillates between 220 and 440 at 3 Hz
+
+> sine_fm2 :: AudSF () Double
+> sine_fm2 = 
+>     proc _ -> do
+>       modfrq <- oscSine -< 0.1
+>       frq    <- oscSine -< 3 + modfrq * 100
+>       oscSine -< 330 + frq * 110 -- oscillates between 220 and 440 at 3 Hz
+
+> sawtooth :: AudSF () Double
+> sawtooth = 
+>     proc _ -> do
+>       osc sawtoothTable 0 -< 440
+
+> squareWave :: AudSF () Double
+> squareWave =
+>     proc _ -> do
+>       frq <- oscSine -< 1000
+>       outA -< if frq > 0 then 0.99 else -0.99
+
+> test :: AudSF () Double -> IO ()
+> test = outFile "test.wav" 3.0
+ HSoM/Examples/SpectrumAnalysis.lhs view
@@ -0,0 +1,57 @@+> {-#  LANGUAGE Arrows  #-}
+
+> module HSoM.Examples.SpectrumAnalysis where
+> import Euterpea
+
+> import Data.Complex (Complex ((:+)), polar)
+> import Data.Maybe (listToMaybe, catMaybes)
+
+> dft :: RealFloat a => [Complex a] -> [Complex a]
+> dft xs = 
+>   let  lenI = length xs
+>        lenR = fromIntegral lenI
+>        lenC = lenR :+ 0
+>   in [  let i = -2 * pi * fromIntegral k / lenR
+>         in (1/lenC) * sum [  (xs!!n) * exp (0 :+ i * fromIntegral n)
+>                              | n <- [0,1..lenI-1] ]
+>         | k <- [0,1..lenI-1] ]
+
+> mkTerm :: Int -> Double -> [Complex Double]
+> mkTerm num n = let f = 2 * pi / fromIntegral num
+>                in [  sin (n * f * fromIntegral i) / n :+ 0
+>                      | i <- [0,1..num-1] ]
+
+> mkxa, mkxb, mkxc :: Int-> [Complex Double]
+> mkxa num = mkTerm num 1
+> mkxb num = zipWith (+) (mkxa num) (mkTerm num 3)
+> mkxc num = zipWith (+) (mkxb num) (mkTerm num 5)
+
+> printComplexL :: [Complex Double] -> IO ()
+> printComplexL xs  =
+>   let  f (i,rl:+im) = 
+>             do  putStr (spaces (3 - length (show i))  )
+>                 putStr (show i       ++ ":  ("        )
+>                 putStr (niceNum rl  ++ ", "           )
+>                 putStr (niceNum im  ++ ")\n"          )
+>   in mapM_ f (zip [0..length xs - 1] xs)
+
+> niceNum :: Double -> String
+> niceNum d =
+>   let  d' = fromIntegral (round (1e10 * d)) / 1e10
+>        (dec, fra)  = break (== '.') (show d')
+>        (fra',exp)  = break (== 'e') fra
+>   in  spaces (3  - length dec) ++ dec ++ take 11 fra'
+>       ++ exp ++ spaces (12 - length fra' - length exp)
+
+> spaces :: Int -> String
+> spaces  n = take n (repeat ' ')
+
+> mkPulse :: Int -> [Complex Double]
+> mkPulse n = 100 : take (n-1) (repeat 0)
+> {-# LINE 721 "SpectrumAnalysis.lhs" #-}
+> x1 num = let f = pi * 2 * pi / fromIntegral num
+>          in map (:+ 0) [  sin (f * fromIntegral i)
+>                           | i <- [0,1..num-1] ]
+> {-# LINE 757 "SpectrumAnalysis.lhs" #-}
+> mkPolars :: [Complex Double] -> [Complex Double]
+> mkPolars = map ((\(m,p)-> m:+p) . polar)
+ HSoM/MUI.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE FlexibleContexts #-}
+
+module HSoM.MUI 
+  ( -- UI functions
+    UISF 
+  , asyncV              -- :: NFData b => Integer -> Int -> SF a b -> UISF a ([b], Bool)
+  , Dimension           -- type Dimension = (Int, Int)
+  , topDown, bottomUp, leftRight, rightLeft    -- :: UISF a b -> UISF a b
+  , setSize             -- :: Dimension -> UISF a b -> UISF a b
+  , setLayout           -- :: Layout -> UISF a b -> UISF a b
+  , pad                 -- :: (Int, Int, Int, Int) -> UISF a b -> UISF a b
+  , defaultMUIParams    -- :: UIParams
+  , UIParams (..)       -- :: UISF () () -> IO ()
+  , runMUI              -- :: UIParams -> UISF () () -> IO ()
+  , runMUI'             -- :: UISF () () -> IO ()
+  , getTime             -- :: UISF () Time
+    -- Widgets
+  , label               -- :: String -> UISF a a
+  , displayStr          -- :: UISF String ()
+  , display             -- :: Show a => UISF a ()
+  , withDisplay         -- :: Show b => UISF a b -> UISF a b
+  , textboxE            -- :: String -> UISF (SEvent String) String
+  , textbox             -- :: String -> UISF (SEvent String) String
+  , title               -- :: String -> UISF a b -> UISF a b
+  , button              -- :: String -> UISF () Bool
+  , stickyButton        -- :: String -> UISF () Bool
+  , checkbox            -- :: String -> Bool -> UISF () Bool
+  , checkGroup          -- :: [(String, a)] -> UISF () [a]
+  , radio               -- :: [String] -> Int -> UISF () Int
+  , hSlider, vSlider    -- :: RealFrac a => (a, a) -> a -> UISF () a
+  , hiSlider, viSlider  -- :: Integral a => a -> (a, a) -> a -> UISF () a
+  , realtimeGraph       -- :: RealFrac a => Layout -> Time -> Color -> UISF (Time, [(a,Time)]) ()
+  , histogram           -- :: RealFrac a => Layout -> UISF (Event [a]) ()
+  , listbox             -- :: (Eq a, Show a) => UISF ([a], Int) Int
+  , midiIn              -- :: UISF (Maybe InputDeviceID) (SEvent [MidiMessage])
+  , midiOut             -- :: UISF (Maybe OutputDeviceID, SEvent [MidiMessage]) ()
+  , midiInM             -- :: UISF [InputDeviceID] (SEvent [MidiMessage])
+  , midiOutM            -- :: UISF [(OutputDeviceID, SEvent [MidiMessage])] ()
+  , midiOutB            -- :: UISF (Maybe OutputDeviceID, BufferOperation MidiMessage) Bool
+  , midiOutMB           -- :: UISF [(OutputDeviceID, BufferOperation MidiMessage)] Bool
+  , BufferOperation (..) -- Reexported for use with midiOutMB 
+  , selectInput         -- :: UISF () (Maybe InputDeviceID)
+  , selectOutput        -- :: UISF () (Maybe OutputDeviceID)
+  , selectInputM        -- :: UISF () [InputDeviceID]
+  , selectOutputM       -- :: UISF () [OutputDeviceID]
+  , canvas              -- :: Dimension -> UISF (Event Graphic) ()
+  , canvas'             -- :: Layout -> (a -> Dimension -> Graphic) -> UISF (Event a) ()
+  -- Widget Utilities
+  , makeLayout          -- :: LayoutType -> LayoutType -> Layout
+  , LayoutType (..)     -- data LayoutType = Stretchy { minSize :: Int } | Fixed { fixedSize :: Int }
+  , Color (..)          -- data Color = Black | Blue | Green | Cyan | Red | Magenta | Yellow | White
+  ) where
+
+import HSoM.MUI.MidiWidgets
+import Euterpea.IO.MIDI.MidiIO (initializeMidi, terminateMidi)
+import FRP.UISF hiding ((~++))
+
+defaultMUIParams :: UIParams
+defaultMUIParams = defaultUIParams { uiTitle = "MUI" }
+
+runMUI :: UIParams -> UISF () () -> IO ()
+runMUI params = runUI (params { uiInitialize = uiInitialize params >> initializeMidi, 
+                                uiClose = uiClose params >> terminateMidi})
+
+runMUI' :: UISF () () -> IO ()
+runMUI' = runMUI defaultMUIParams
+
+asyncV x = asyncVT x
+ HSoM/MUI/MidiWidgets.lhs view
@@ -0,0 +1,378 @@+> {-# LANGUAGE RecursiveDo, Arrows, TupleSections, ExistentialQuantification, ScopedTypeVariables, FlexibleContexts, CPP #-}
+
+Authors: Paul Hudak, Donya Quick, and Dan Winograd-Cort
+
+> module HSoM.MUI.MidiWidgets (
+>   midiIn
+> , midiOut
+> , midiInM
+> , midiOutM, midiOutB, midiOutMB
+> , runMidi, runMidiM, runMidiMFlood, runMidiMB, runMidiMBFlood
+> , musicToMsgs
+> , musicToBO
+> , selectInput,  selectOutput
+> , selectInputM, selectOutputM
+> , BufferOperation (..) -- Reexported for use with midiOutMB 
+> , asyncMidi, asyncMidiOn
+> ) where
+
+> import FRP.UISF hiding ((~++))
+> import Euterpea hiding (Time, SF, delay)
+
+> -- for musicToMsgs
+> import Data.List (nub, elemIndex, sortBy)
+> import Euterpea.IO.MIDI.MidiIO hiding (Time)
+
+> -- These three imports are for the runMidi functions
+> import FRP.UISF.UISF (addTerminationProc)
+> --import Euterpea.IO.MUI.UISFCompat
+> import Control.SF.SF
+> import Control.DeepSeq
+> import Control.Monad
+> import Control.Concurrent (ThreadId, threadDelay, killThread)
+> import Data.IORef
+> -- imports from UISFCompat
+> import Data.Monoid
+> import FRP.UISF.Asynchrony
+> import Data.Maybe (listToMaybe)
+> import FRP.UISF.AuxFunctions hiding ((~++))
+> import Control.Arrow.ArrowP
+> import Euterpea.IO.Audio.Types
+> import FRP.UISF.Asynchrony
+
+
+
+
+
+
+============================================================
+========================= Widgets ==========================
+============================================================
+
+-------------------
+ | Midi Controls | 
+-------------------
+midiIn is a widget that accepts a MIDI device ID and returns the event 
+stream of MidiMessages that that device is producing.
+
+midiOut is a widget that accepts a MIDI device ID as well as a stream 
+of MidiMessages and sends the MidiMessages to the device.
+
+> midiIn :: UISF (Maybe InputDeviceID) (SEvent [MidiMessage])
+> midiIn = liftAIO f where
+>  f Nothing = return Nothing
+>  f (Just dev) = do
+>   m <- pollMidi dev
+>   return $ fmap (\(_t, ms) -> map Std ms) m
+ 
+> midiOut :: UISF (Maybe OutputDeviceID, SEvent [MidiMessage]) ()
+> midiOut = liftAIO f where
+>   f (Nothing, _) = return ()
+>   f (Just dev, Nothing) = outputMidi dev
+>   f (Just dev, Just ms) = do
+>       outputMidi dev >> mapM_ (\m -> deliverMidiEvent dev (0, m)) ms
+
+ 
+The midiInM widget takes input from multiple devices and combines 
+it into a single stream. 
+
+> midiInM :: UISF [InputDeviceID] (SEvent [MidiMessage])
+> midiInM = foldA mappend Nothing (arr Just >>> midiIn)
+
+> midiInM' :: UISF [(InputDeviceID, Bool)] (SEvent [MidiMessage])
+> midiInM' = arr (map fst . filter snd) >>> midiInM
+
+
+A midiOutM widget sends output to multiple MIDI devices by sequencing
+the events through a single midiOut. The same messages are sent to 
+each device. The midiOutM is designed to be hooked up to a stream like
+that from a checkGroup.
+
+> midiOutM :: UISF [(OutputDeviceID, SEvent [MidiMessage])] ()
+> midiOutM = foldA const () (arr (first Just) >>> midiOut)
+
+> midiOutM' :: UISF ([(OutputDeviceID, Bool)], SEvent [MidiMessage]) ()
+> midiOutM' = arr fixData >>> midiOutM where
+>   fixData (lst, mmsgs) = map ((,mmsgs) . fst) $ filter snd lst
+
+
+A midiOutB widget wraps the regular midiOut widget with a buffer. 
+This allows for a timed series of messages to be prepared and sent
+to the widget at one time. With the regular midiOut, there is no
+timestamping of the messages and they are assumed to be played "now"
+rather than at some point in the future. Just as MIDI files have the
+events timed based on ticks since the last event, the events here 
+are timed based on seconds since the last event. If an event is 
+to occur 0.0 seconds after the last event, then it is assumed to be
+played at the same time as that other event and all simultaneous 
+events are handed to midiOut at the same timestep. Finally, the 
+widget returns a flat that is True if the buffer is empty and False
+if the buffer is full (meaning that items are still being played).
+
+> midiOutB :: UISF (Maybe OutputDeviceID, BufferOperation MidiMessage) Bool
+> midiOutB = proc (devID, bo) -> do
+>   (out, b) <- eventBuffer -< bo
+>   midiOut -< (devID, if shouldClear bo then Just clearMsgs `mappend` out else out)
+>   returnA -< b
+>  where clearMsgs = map (\c -> Std (ControlChange c 123 0)) [0..15]
+>        shouldClear ClearBuffer = True
+>        shouldClear (SkipAheadInBuffer _) = True
+>        shouldClear (SetBufferPlayStatus _ bo) = shouldClear bo
+>        shouldClear (SetBufferTempo      _ bo) = shouldClear bo
+>        shouldClear _ = False
+
+> midiOutB' :: UISF (Maybe OutputDeviceID, SEvent [(DeltaT, MidiMessage)]) Bool
+> midiOutB' = second (arr $ maybe NoBOp AppendToBuffer) >>> midiOutB
+
+
+The midiOutMB widget combines the power of midiOutM with midiOutB, allowing 
+multiple sets of buffer controlled midi messages to be sent to different 
+devices.  The Bool output is True if every buffer is empty (that is, no device 
+has any pending music to be played) and False otherwise.
+
+> midiOutMB :: UISF [(OutputDeviceID, BufferOperation MidiMessage)] Bool
+> midiOutMB = foldA (&&) True (arr (first Just) >>> midiOutB)
+
+> midiOutMB' :: UISF ([(OutputDeviceID, Bool)], SEvent [(DeltaT, MidiMessage)]) Bool
+> midiOutMB' = arr fixData >>> midiOutMB where
+>   fixData (lst, mmsgs) = map ((,maybe NoBOp AppendToBuffer mmsgs) . fst) $ filter snd lst
+
+
+-------------
+ | runMidi | 
+-------------
+The following functions are experimental functions for doing all Midi 
+behavior at once in an external thread.  There are mutiple versions 
+corresponding to Multiple input/output (M), Batch (B), and message 
+flooding (Flood).
+
+> runMidi :: (NFData b, NFData c)
+>         => SF (b, SEvent [MidiMessage]) 
+>               (c, SEvent [MidiMessage])
+>         -> UISF (b, (Maybe InputDeviceID, Maybe OutputDeviceID)) [c]
+> runMidi sf = asyncC' uisfAsyncThreadHandler (iAction . fst . snd, oAction) sf' where
+>   iAction Nothing = return Nothing
+>   iAction (Just idev) = do
+>     m <- pollMidi idev
+>     return $ fmap (\(_t, ms) -> map Std ms) m
+>   oAction (Nothing, _) = return ()
+>   oAction (Just odev, ms) = do
+>     outputMidi odev
+>     maybe (return ()) (mapM_ $ \m -> deliverMidiEvent odev (0, m)) ms
+>   sf' = toAutomaton $ arr (\((b,(idev,odev)),mms) -> ((b,mms),odev)) >>> first sf >>>
+>           arr (\((c,mms),odev) -> (c, (odev, mms)))
+
+> runMidiM :: (NFData b, NFData c)
+>          => SF (b, ([(InputDeviceID, SEvent [MidiMessage])], [OutputDeviceID]))
+>                (c, [(OutputDeviceID, SEvent [MidiMessage])])
+>          -> UISF (b, ([InputDeviceID],[OutputDeviceID])) [c]
+> runMidiM sf = asyncC' uisfAsyncThreadHandler (iAction . fst . snd, oAction) sf' where
+>   iAction [] = return []
+>   iAction (idev:devs) = do
+>     m <- pollMidi idev
+>     let ret = fmap (\(_t, ms) -> map Std ms) m
+>     rst <- iAction devs
+>     return $ (idev, ret):rst
+>   oAction [] = return ()
+>   oAction ((odev, ms):rst) = do
+>     outputMidi odev
+>     maybe (return ()) (mapM_ $ \m -> deliverMidiEvent odev (0, m)) ms
+>     oAction rst
+>   sf' = toAutomaton $ arr (\((b,(idevs,odevs)),mms) -> (b,(mms,odevs))) >>> sf
+
+> runMidiMFlood :: (NFData b, NFData c)
+>               => SF (b, SEvent [MidiMessage])
+>                     (c, SEvent [MidiMessage])
+>               -> UISF (b, ([InputDeviceID],[OutputDeviceID])) [c]
+> runMidiMFlood = runMidiFloodHelper runMidiM
+
+> runMidiMB :: (NFData b, NFData c)
+>           => SF (b, ([(InputDeviceID, SEvent [MidiMessage])], [OutputDeviceID]))
+>                 (c, [(OutputDeviceID, BufferOperation MidiMessage)])
+>           -> UISF (b, ([InputDeviceID],[OutputDeviceID])) [(c, Bool)] --([c], Bool)
+> runMidiMB sf = asyncC' uisfAsyncThreadHandler (iAction . fst . snd, oAction) sf' where
+>                   -- >>> arr (\lst -> let (cs, bools) = unzip lst in (cs, and bools)) >>> delay ([],True) where
+>   iAction idevs = do
+>     t <- getTimeNow
+>     mms <- iAction' idevs
+>     return (mms, t)
+>   iAction' [] = return []
+>   iAction' (idev:devs) = do
+>     m <- pollMidi idev
+>     let ret = fmap (\(_t, ms) -> map Std ms) m
+>     rst <- iAction' devs
+>     return $ (idev, ret):rst
+>   oAction [] = return ()
+>   oAction ((odev, ms):rst) = do
+>     outputMidi odev
+>     maybe (return ()) (mapM_ $ \m -> deliverMidiEvent odev (0, m)) ms
+>     oAction rst
+>   sf' = toAutomaton $ arr (\((b,(idevs,odevs)),(mms, t)) -> ((b,(mms,odevs)), t)) >>> first sf
+>           >>> arr (\((c, bos), t) -> (c, (map (,t) bos))) >>> second (foldA cons ([], True) buffer)
+>           >>> arr (\(c, (lst, bool)) -> ((c, bool), lst))
+>   cons (e, b) (lst, b') = (e:lst, b && b')
+>   buffer = proc ((dev, bo), t) -> do
+>       (out, b) <- eventBuffer' -< (bo, t)
+>       returnA -< ((dev, if shouldClear bo then Just clearMsgs `mappend` out else out), b)
+>   clearMsgs = map (\c -> Std (ControlChange c 123 0)) [0..15]
+>   shouldClear ClearBuffer = True
+>   shouldClear (SkipAheadInBuffer _) = True
+>   shouldClear (SetBufferPlayStatus _ bo) = shouldClear bo
+>   shouldClear (SetBufferTempo      _ bo) = shouldClear bo
+>   shouldClear _ = False
+
+
+> runMidiMBFlood :: (NFData b, NFData c)
+>                => SF (b, SEvent [MidiMessage])
+>                      (c, BufferOperation MidiMessage)
+>                -> UISF (b, ([InputDeviceID],[OutputDeviceID])) [(c, Bool)] --([c], Bool)
+> runMidiMBFlood = runMidiFloodHelper runMidiMB
+
+> runMidiFloodHelper :: Arrow a =>
+>      (a (b, ([(idev, SEvent [m])], [odev])) (c, [(odev, mms)]) -> t)
+>      -> a (b, SEvent [m]) (c, mms) -> t
+> runMidiFloodHelper runner sf = runner sf' where
+>   sf' = arr (\(b, (idevs, odevs)) -> ((b, foldl (flip (mappend . snd)) Nothing idevs), odevs)) >>> first sf >>> 
+>           arr (\((c, mms), odevs) -> (c, map (\d -> (d, mms)) odevs))
+
+
+
+
+
+
+The musicToMsgs function bridges the gap between a Music1 value and
+the input type of midiOutB. It turns a Music1 value into a series 
+of MidiMessages that are timestamped using the number of seconds 
+since the last event. The arguments are as follows:
+
+- True if allowing for an infinite music value, False if the input
+  value is known to be finite. 
+
+- InstrumentName overrides for channels for infinite case. When the
+  input is finite, an empty list can be supplied since the instruments
+  will be pulled from the Music1 value directly (which is obviously 
+  not possible to do in the infinite case).
+
+- The Music1 value to convert to timestamped MIDI messages.
+
+> musicToMsgs :: Bool -> [InstrumentName] -> Music1 -> [(DeltaT, MidiMessage)]
+> musicToMsgs inf is m = 
+>     let p = perform m -- obtain the performance
+>         instrs = if null is && not inf then nub $ map eInst p else is
+>         chan e = 1 + case elemIndex (eInst e) instrs of 
+>                          Just i -> i
+>                          Nothing -> error ("Instrument "++show (eInst e)++
+>                                     "is not assigned to a channel.")                               
+>         f e = (eTime e, ANote (chan e) (ePitch e) (eVol e) (fromRational $ eDur e))
+>         f2 e = [(eTime e, Std (NoteOn (chan e) (ePitch e) (eVol e))), 
+>                (eTime e + eDur e, Std (NoteOff (chan e) (ePitch e) (eVol e)))]
+>         evs = if inf then map f p else sortBy mOrder $ concatMap f2 p -- convert to MidiMessages
+>         times = map (fromRational.fst) evs -- absolute times
+>         newTimes = zipWith subtract (head times : times) times -- relative times
+>         progChanges = zipWith (\c i -> (0, Std $ ProgramChange c i)) 
+>                       [1..16] $ map toGM instrs
+>     in  if length instrs > 16 then error "too many instruments!" 
+>         else progChanges ++ zip newTimes (map snd evs) where
+>     mOrder (t1,m1) (t2,m2) = compare t1 t2
+
+> musicToBO :: Bool -> [InstrumentName] -> Music1 -> BufferOperation MidiMessage
+> musicToBO inf is m = AppendToBuffer $ musicToMsgs inf is m
+ 
+ 
+----------------------
+ | Device Selection | 
+----------------------
+selectInput and selectOutput are shortcut widgets for producing a set 
+of radio buttons corresponding to the available input and output devices 
+respectively.  The output is the DeviceID for the chosen device rather 
+that just the radio button index as the radio widget would return.
+
+> selectInput  :: UISF () (Maybe InputDeviceID)
+> selectOutput :: UISF () (Maybe OutputDeviceID)
+> selectInput  = selectDev "Input device"  (liftM fst $ getAllDevices)
+> selectOutput = selectDev "Output device" (liftM snd $ getAllDevices)
+
+> selectDev :: String -> IO [(deviceid, DeviceInfo)] -> UISF () (Maybe deviceid)
+> selectDev t getDevs = initialAIO getDevs $ \devices ->
+>   let devs = filter (\(i,d) -> name d /= "Microsoft MIDI Mapper") devices
+>       defaultChoice = if null devs then (-1) else 0
+>       names = if null devs then ["(No Devices)"] else map (name . snd) devs
+>   in  title t $ proc _ -> do
+>       r <- radio names 0 -< ()
+>       returnA -< if null devs then Nothing else Just $ fst (devs !! r)
+
+
+The selectInputM and selectOutputM widgets use checkboxes instead of 
+radio buttons to allow the user to select multiple inputs and outputs.
+These widgets should be used with midiInM and midiOutM respectively.
+
+> selectInputM  :: UISF () [InputDeviceID]
+> selectOutputM :: UISF () [OutputDeviceID]
+> selectInputM  = selectDevM "Input devices"  (liftM fst $ getAllDevices)
+> selectOutputM = selectDevM "Output devices" (liftM snd $ getAllDevices)
+
+> selectDevM :: String -> IO [(deviceid, DeviceInfo)] -> UISF () [deviceid]
+> selectDevM t getDevs = initialAIO getDevs $ \devices ->
+>   let devs = filter (\(i,d) -> name d /= "Microsoft MIDI Mapper") devices
+>   in  title t $ checkGroup $ map (\(i,d) -> (name d, i)) devs
+
+> -- For backward compatibility with runMidi, which should be rewritten
+> asyncC' :: (ArrowIO a, ArrowLoop a, ArrowCircuit a, ArrowChoice a, NFData b, NFData c) => 
+>            x -- ^ The thread handler
+>         -> (b -> IO d, e -> IO ()) -- ^ Effectful input and output channels for the automaton
+>         -> (Automaton (->) (b,d) (c,e))  -- ^ The automaton to convert to asynchronize
+>         -> a b [c]
+> asyncC' _ (ia, oa) sf = asyncCIO (return (), const $ return ()) sf' where
+>   sf' _ = (arr id &&& actionToIOAuto ia) >>> pureAutoToIOAuto sf >>> second (actionToIOAuto oa) >>> arr fst
+
+
+> asyncMidiHelper asy rinit (_defb, defc) dd f = asy (ini, term) sf >>> arr listToMaybe >>> hold defc where
+>   sf _ = proc b -> do
+>     rec r <- delay rinit -< r'
+>         (omt, r', c) <- arr f -< (r,b)
+>     actionToIOAuto action -< omt
+>     returnA -< c
+>   ini = return ()
+>   term _ = putStrLn "MIDI back-end terminated."
+>   action omt = do
+>     let td = sum $ map snd omt
+>     forM_ omt $ \(om, t) -> do
+>       forM_ om $ \(odev,mm) -> do
+>         outputMidi odev
+>         forM_ mm (\m -> deliverMidiEvent odev (0, m))
+>       when (t > 0) (threadDelay t)
+>     when (td <= 0) (threadDelay dd)
+
+
+
+> asyncMidi :: NFData c => r -> (b,c) -> Int -> ((r, b) -> ([([(OutputDeviceID, [MidiMessage])], Int)], r, c)) -> UISF b c
+> asyncMidi = asyncMidiHelper asyncCIO
+
+> asyncMidiOn :: NFData c => Int -> r -> (b,c) -> Int -> ((r, b) -> ([([(OutputDeviceID, [MidiMessage])], Int)], r, c)) -> UISF b c
+> asyncMidiOn n = asyncMidiHelper (asyncCIOOn n)
+
+=========================================================
+
+From UISFCompat.lhs
+
+
+> asyncUISFV x = asyncVT x
+
+The below function is useful for making use of asyncUISF*
+which both make use of Automatons rather than SFs.
+NOTE: Actually, SF and Automaton (->) are the same thing.  Perhaps we should 
+      replace our definition of SF with just a type synonym instead.
+
+> toAutomaton :: forall a b . SF a b -> Automaton (->) a b
+> toAutomaton ~(SF f) = Automaton $ \a -> let (b, sf) = f a in (b, toAutomaton sf)
+
+The below function is useful for directly asynchronizing AudSFs and CtrSFs in UISF.
+
+> clockedSFToUISF :: forall a b c . (NFData b, Clock c) => DeltaT -> SigFun c a b -> UISF a [(b, Time)]
+> clockedSFToUISF buffer ~(ArrowP sf) = let r = rate (undefined :: c) 
+>   in asyncUISFV r buffer (toAutomaton sf)
+
+This function is the standard UISF asynchronous thread handler:
+
+> uisfAsyncThreadHandler :: ThreadId -> UISF a a
+> uisfAsyncThreadHandler = addTerminationProc . killThread
+ HSoM/Performance.lhs view
@@ -0,0 +1,201 @@+> {-#  LANGUAGE FlexibleInstances, TypeSynonymInstances  #-}
+> module HSoM.Performance where
+> import Euterpea
+
+From Euterpea we have:
+
+type Performance = [MEvent]
+
+data MEvent = MEvent {  eTime    :: PTime, 
+                      eInst    :: InstrumentName, 
+                      ePitch   :: AbsPitch,
+                      eDur     :: DurT, 
+                      eVol     :: Volume, 
+                      eParams  :: [Double]}
+     deriving (Show,Eq,Ord)
+
+type PTime     = Rational
+type DurT      = Rational
+
+merge :: Performance -> Performance -> Performance
+merge []          es2         =  es2
+merge es1         []          =  es1
+merge a@(e1:es1)  b@(e2:es2)  =  
+  if eTime e1 < eTime e2  then  e1  : merge es1 b
+                          else  e2  : merge a es2
+
+
+> data Context a = Context {  cTime    :: PTime, 
+>                             cPlayer  :: Player a, 
+>                             cInst    :: InstrumentName, 
+>                             cDur     :: DurT, 
+>                             cPch     :: AbsPitch,
+>                             cVol     :: Volume,
+>                             cKey     :: (PitchClass, Mode) }
+>      deriving Show
+
+> metro              :: Int -> Dur -> DurT
+> metro setting dur  = 60 / (fromIntegral setting * dur)
+
+> type PMap a  = PlayerName -> Player a
+
+> hsomPerform :: PMap a -> Context a -> Music a -> Performance
+> hsomPerform pm c m = fst (perf pm c m)
+
+> perf :: PMap a -> Context a -> Music a -> (Performance, DurT)
+> perf pm 
+>   c@Context {cTime = t, cPlayer = pl, cDur = dt, cPch = k} m =
+>   case m of
+>      Prim (Note d p)            -> (playNote pl c d p, d*dt)
+>      Prim (Rest d)              -> ([], d*dt)
+>      m1 :+: m2                  ->  
+>              let  (pf1,d1)  = perf pm c m1
+>                   (pf2,d2)  = perf pm (c {cTime = t+d1}) m2
+>              in (pf1++pf2, d1+d2)
+>      m1 :=: m2                  -> 
+>              let  (pf1,d1)  = perf pm c m1
+>                   (pf2,d2)  = perf pm c m2
+>              in (merge pf1 pf2, max d1 d2)
+>      Modify  (Tempo r)       m  -> perf pm (c {cDur = dt / r})    m
+>      Modify  (Transpose p)   m  -> perf pm (c {cPch = k + p})     m
+>      Modify  (Instrument i)  m  -> perf pm (c {cInst = i})        m
+>      Modify  (KeySig pc mo)  m  -> perf pm (c {cKey = (pc,mo)})   m
+>      Modify  (Phrase pas)    m  -> interpPhrase pl pm c pas       m
+>      Modify  (Custom s)     m  -> 
+>          if take 7 s == "Player " then perf pm (c {cPlayer = pm $ drop 7 s})  m
+>          else perf pm c m
+
+> type PlayerName = String
+
+> data Player a = MkPlayer {  pName         :: PlayerName, 
+>                             playNote      :: NoteFun a,
+>                             interpPhrase  :: PhraseFun a}
+
+> type NoteFun a    =  Context a -> Dur -> a -> Performance
+> type PhraseFun a  =  PMap a -> Context a -> [PhraseAttribute]
+>                      -> Music a -> (Performance, DurT)
+
+> instance Show a => Show (Player a) where
+>    show p = pName p
+
+> defPlayer  :: Player Note1
+> defPlayer  = MkPlayer 
+>              {  pName         = "Default",
+>                 playNote      = defPlayNote      defNasHandler,
+>                 interpPhrase  = defInterpPhrase  defPasHandler}
+
+> defPlayNote ::  (Context (Pitch,[a]) -> a -> MEvent-> MEvent)
+>                 -> NoteFun (Pitch, [a])
+> defPlayNote nasHandler 
+>   c@(Context cTime cPlayer cInst cDur cPch cVol cKey) d (p,nas) =
+>     let initEv = MEvent {  eTime    = cTime,     eInst  = cInst,
+>                           eDur     = d * cDur,  eVol = cVol,
+>                           ePitch   = absPitch p + cPch,
+>                           eParams  = [] }
+>     in [ foldr (nasHandler c) initEv nas ]
+
+> defNasHandler :: Context a -> NoteAttribute -> MEvent -> MEvent
+> defNasHandler c (Volume v)     ev = ev {eVol = v}
+> defNasHandler c (Params pms)   ev = ev {eParams = pms}
+> defNasHandler _            _   ev = ev
+
+> defInterpPhrase :: 
+>    (PhraseAttribute -> Performance -> Performance) -> 
+>    (  PMap a -> Context a -> [PhraseAttribute] ->  -- PhraseFun
+>       Music a -> (Performance, DurT) )
+> defInterpPhrase pasHandler pm context pas m =
+>        let (pf,dur) = perf pm context m
+>        in (foldr pasHandler pf pas, dur)
+
+> defPasHandler :: PhraseAttribute -> Performance -> Performance
+> defPasHandler (Dyn (Accent x))    = 
+>     map (\e -> e {eVol = round (x * fromIntegral (eVol e))})
+> defPasHandler (Art (Staccato x))  = 
+>     map (\e -> e {eDur = x * eDur e})
+> defPasHandler (Art (Legato   x))  = 
+>     map (\e -> e {eDur = x * eDur e})
+> defPasHandler _                   = id
+
+
+> defPMap "Fancy"    = fancyPlayer
+> defPMap "Default"  = defPlayer
+> defPMap n          = defPlayer { pName = n }
+
+> defCon  :: Context Note1
+> defCon  = Context {  cTime    = 0,
+>                      cPlayer  = fancyPlayer,
+>                      cInst    = AcousticGrandPiano,
+>                      cDur     = metro 120 qn,
+>                      cPch     = 0,
+>                      cKey     = (C, Major),
+>                      cVol     = 127 }
+
+> fancyPlayer :: Player (Pitch, [NoteAttribute])
+> fancyPlayer  = MkPlayer {  pName         = "Fancy",
+>                            playNote      = defPlayNote defNasHandler,
+>                            interpPhrase  = fancyInterpPhrase}
+
+> fancyInterpPhrase             :: PhraseFun a
+> fancyInterpPhrase pm c [] m   = perf pm c m
+> fancyInterpPhrase pm 
+>   c@Context {  cTime = t, cPlayer = pl, cInst = i, 
+>                cDur = dt, cPch = k, cVol = v}
+>   (pa:pas) m =
+>   let  pfd@(pf,dur)  =  fancyInterpPhrase pm c pas m
+>        loud x        =  fancyInterpPhrase pm c (Dyn (Loudness x) : pas) m
+>        stretch x     =  let  t0 = eTime (head pf);  r  = x/dur
+>                              upd (e@MEvent {eTime = t, eDur = d}) = 
+>                                let  dt  = t-t0
+>                                     t'  = (1+dt*r)*dt + t0
+>                                     d'  = (1+(2*dt+d)*r)*d
+>                                in e {eTime = t', eDur = d'}
+>                         in (map upd pf, (1+x)*dur)
+>        inflate x     =  let  t0  = eTime (head pf);  
+>                              r   = x/dur
+>                              upd (e@MEvent {eTime = t, eVol = v}) = 
+>                                  e {eVol =  round ( (1+(t-t0)*r) * 
+>                                             fromIntegral v)}
+>                         in (map upd pf, dur)
+>   in case pa of
+>     Dyn (Accent x) ->
+>         ( map (\e-> e {eVol = round (x * fromIntegral (eVol e))}) pf, dur)
+>     Dyn (StdLoudness l) -> 
+>         case l of 
+>            PPP  -> loud 40;       PP -> loud 50;   P    -> loud 60
+>            MP   -> loud 70;       SF -> loud 80;   MF   -> loud 90
+>            NF   -> loud 100;      FF -> loud 110;  FFF  -> loud 120
+>     Dyn (Loudness x)     ->  fancyInterpPhrase pm
+>                              c{cVol = round x} pas m
+>     Dyn (Crescendo x)    ->  inflate   x ; Dyn (Diminuendo x)  -> inflate (-x)
+>     Tmp (Ritardando x)   ->  stretch   x ; Tmp (Accelerando x) -> stretch (-x)
+>     Art (Staccato x)     ->  (map (\e-> e {eDur = x * eDur e}) pf, dur)
+>     Art (Legato x)       ->  (map (\e-> e {eDur = x * eDur e}) pf, dur)
+>     Art (Slurred x)      -> 
+>         let  lastStartTime  = foldr (\e t -> max (eTime e) t) 0 pf
+>              setDur e       =   if eTime e < lastStartTime
+>                                 then e {eDur = x * eDur e}
+>                                 else e
+>         in (map setDur pf, dur) 
+>     Art _                -> pfd
+>     Orn _                -> pfd
+
+> class Performable a where
+>   perfDur :: PMap Note1 -> Context Note1 -> Music a -> (Performance, DurT)
+
+> instance Performable Note1 where
+>   perfDur pm c m = perf pm c m
+
+> instance Performable Pitch where
+>   perfDur pm c = perfDur pm c . toMusic1
+
+> instance Performable (Pitch, Volume) where
+>   perfDur pm c = perfDur pm c . toMusic1
+
+> defToPerf :: Performable a => Music a -> Performance
+> defToPerf = fst . perfDur defPMap defCon
+
+> toPerf :: Performable a => PMap Note1 -> Context Note1 -> Music a -> Performance
+> toPerf pm con = fst . perfDur pm con
+
+> playA myPMap myCon = playC defParams{perfAlg=hsomPerform myPMap myCon}
+> writeMidiA fn myPMap myCon = exportMidiFile fn . toMidi . hsomPerform myPMap myCon
+ License view
@@ -0,0 +1,20 @@+Copyright (c) 2008-2015 Paul Hudak and Donya Quick
+
+This software is provided 'as-is', without any express or implied
+warranty.  In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+   claim that you wrote the original software.  If you use this software
+   in a product, an acknowledgment in the product documentation would
+   be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not
+   be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+   distribution.
+ Setup.hs view
@@ -0,0 +1,51 @@+import Distribution.Simple
+main = defaultMain
+
+-- January 18, 2014
+-- The following setup script uses the CCA preprocessor (ccap) to preprocess 
+-- certain *.as files in the Euterpea code base.  As of January 18, 2014, only 
+-- one file is being preprocessed in this way (Euterpea.IO.Audio.Basics), and 
+-- as some users have had difficulty with installations due to this 
+-- preprocessing step, we are removing it from the installation procedure.
+-- 
+-- Now, to process *.as files, one can directly use the ArrowWrap module in 
+-- Euterpea.  In ArrowWrap, all files to be preprocessed must be declared in 
+-- the list called fileList.  Then, simply run main.
+-- 
+-- If this preprocessor is going to be reenabled, or if ArrowWrap is going 
+-- to be used, one must either add haskell-src-exts >= 1.14.0 to the cabal 
+-- build-depends or just install it directly.
+{-
+module Main (main) where
+
+import Distribution.Simple
+import Distribution.Simple.PreProcess
+import Distribution.Simple.Program
+import Distribution.Simple.Utils
+import System.Exit
+
+import ArrowWrap
+
+findArrowP verbosity = do
+  a <- findProgramLocation verbosity "ccap"
+  case a of 
+    Nothing -> error "Preprocessor ccap not found. Please make sure the \
+                     \CCA library is already installed, and ccap is in \
+                     \your PATH environment."
+    Just p  -> return p
+
+ppArrow bi lbi = PreProcessor {
+    platformIndependent = True,
+    runPreProcessor = 
+      mkSimplePreProcessor $ \inFile outFile verbosity ->
+        do info verbosity (inFile ++ " has been preprocessed to " ++ outFile)
+           arrowp <- findArrowP verbosity
+           runArrowP arrowp inFile outFile
+  }
+
+myHooks = simpleUserHooks 
+            { hookedPreProcessors = ("as", ppArrow) : knownSuffixHandlers }
+
+main :: IO ()
+main = defaultMainWithHooks myHooks
+-}
+ System/Random/Distributions.hs view
@@ -0,0 +1,135 @@+-- Algorithms taken from Dodge and Jerse's Computer Music: Synthesis,
+-- Composition, and Performance, Chapter 11. 
+
+module System.Random.Distributions (
+  -- * Random Distributions
+  linear, exponential, bilExp, gaussian, cauchy, poisson, frequency
+
+  -- * Utility Functions
+  , rands
+
+  ) where
+
+import System.Random
+
+{- | Given a random number generator, generates a linearly distributed
+random variable between 0 and 1.  Returns the random value together
+with a new random number generator.  The probability density function
+is given by
+
+> f(x) = 2(1-x)  0 <= x <= 1
+>      = 0       otherwise
+
+-}
+linear :: (RandomGen g, Floating a, Random a, Ord a) => g -> (a,g)
+linear g0 = 
+    let (r1, g1) = randomR (0, 1) g0
+        (r2, g2) = randomR (0, 1) g1
+    in (min r1 r2, g2)
+
+{- | Takes a random number generator and produces another one
+ that avoids generating the given number.
+-}
+avoid :: (Random a, Eq a, RandomGen g) => a -> (g -> (a,g)) -> g -> (a,g)
+avoid x f g = if r == x then avoid x f g' else (r,g')
+    where (r,g') = f g
+
+{- | Generates an exponentially distributed random variable given a
+spread parameter lambda.  A larger spread increases the probability of
+generating a small number.  The mean of the distribution is
+1/lambda.  The range of the generated number is [0,inf] although
+the chance of getting a very large number is very small.
+
+The probability density function is given by
+
+> f(x) = lambda e^(-lambda * x)
+-}
+exponential :: (RandomGen g, Floating a, Random a, Eq a) => 
+            a  -- ^ horizontal spread of the function.
+         -> g  -- ^ a random number generator.
+         -> (a,g)
+exponential lambda g0 = (-log r1 / lambda, g1)
+    where (r1, g1) = avoid 0 random g0
+
+{- | Generates a random number with a bilateral exponential distribution.  
+Similar to exponential, but the mean of the distribution is 0 and
+50% of the results fall between (-1/lambda, 1/lambda).
+
+-}
+bilExp :: (Floating a, Ord a, Random a, RandomGen g) =>
+          a    -- ^ horizontal spread of the function.
+       -> g    -- ^ a random number generator.
+       -> (a,g)
+bilExp lambda g0 = 
+    let (r', g1) = avoid 0 random g0
+        r = 2 * r'
+        u = if r > 1 then 2 - r else r
+    in (signum (1 - r) * log u / lambda, g1)
+
+{- | Generates a random number with a Gaussian distribution.  
+-}
+gaussian :: (Floating a, Random a, RandomGen g) =>
+            a     -- ^ standard deviation.
+         -> a     -- ^ mean.
+         -> g     -- ^ a random number generator.
+         -> (a,g)
+gaussian stddev center g0 = 
+    let n = 12
+        s = sum $ take n $ randoms g0
+    in (stddev * (s - fromIntegral n / 2) + center, fst (split g0))
+
+{- | Generates a Cauchy-distributed random variable.  
+The distribution is symmetric with a mean of 0.  
+
+-}
+cauchy :: (Floating a, Random a, RandomGen g, Eq a) =>
+          a   -- ^ alpha (density).
+       -> g   -- ^ a random number generator.
+       -> (a,g)
+cauchy density g0 = (density * tan (u * pi), g1)
+    where (u, g1) = avoid 0.5 random g0
+
+{- | Generates a Poisson-distributed random variable.
+The given parameter lambda is the mean of the distribution.  
+If lambda is an integer, the probability that the result j=lambda-1
+will be as great as that of j=lambda.  The Poisson distribution
+is discrete. The returned value will be a non-negative
+integer.
+
+-}
+poisson :: (Num t, Ord a, Floating a, RandomGen g, Random a) =>
+           a -> g -> (t, g)
+poisson lambda g0 = (k 0 us, g1)
+    where v   = exp (-lambda)
+          us  = scanl1 (*) (randoms g0)
+          g1  = fst (split g0)
+          k n (u:us)
+              | u >= v     = k (n+1) us
+              | otherwise  = n
+          k _ [] = error "System.Random.Distributions.poisson: randoms did not return an infinite list"
+
+{- | Given a list of weight-value pairs, generates a value randomly picked
+from the list, weighting the probability of choosing each value by the 
+weight given.
+
+-}
+frequency :: (Floating w, Ord w, Random w, RandomGen g) 
+             => [(w, a)] -> g -> (a,g)
+frequency xs g0 = (pick r xs, g1)
+    where (r, g1) = randomR (0, tot) g0
+          tot = sum (map fst xs)
+          pick n ((w,a):xs) 
+             | n <= w    = a
+             | otherwise = pick (n-w) xs
+          pick _ [] = error "System.Random.Distributions.frequency: The impossible happened"
+
+
+{- | Given a function generating a random number variable and a random
+number generator, produces an infinite list of random values 
+generated from the given function.
+
+-}
+rands :: (RandomGen g, Random a) => 
+         (g -> (a,g)) -> g -> [a]
+rands f g = x : rands f g' where (x,g') = f g
+
+ readme.txt view
@@ -0,0 +1,3 @@+Library to accompany the Haskell School of Music textbook.
+See License file for licensing information.
+Send questions/comments to Donya Quick (donyaquick@gmail.com).