diff --git a/.git/COMMIT_EDITMSG b/.git/COMMIT_EDITMSG
--- a/.git/COMMIT_EDITMSG
+++ b/.git/COMMIT_EDITMSG
@@ -1,4 +1,1 @@
-dependency caps and audio render update
-
-Dependencies are capped more strictly and audio rendering will now clip
-by default (rather than overflowing) when values exceed +/-1.
+Dependency versions narrowed again
diff --git a/.git/FETCH_HEAD b/.git/FETCH_HEAD
--- a/.git/FETCH_HEAD
+++ b/.git/FETCH_HEAD
@@ -1,1 +1,1 @@
-896621f361866ce787d0bad1dfd5434d371b5679		branch 'master' of https://github.com/Euterpea/Euterpea2
+40d6be12def8fc357df4248d9943bd3cc1f75f89		branch 'master' of https://github.com/Euterpea/Euterpea2
diff --git a/.git/ORIG_HEAD b/.git/ORIG_HEAD
--- a/.git/ORIG_HEAD
+++ b/.git/ORIG_HEAD
@@ -1,1 +1,1 @@
-b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85
+aa72de41851f42d3f1023c01ae0edc5832c47ebd
diff --git a/.git/index b/.git/index
Binary files a/.git/index and b/.git/index differ
diff --git a/.git/logs/HEAD b/.git/logs/HEAD
--- a/.git/logs/HEAD
+++ b/.git/logs/HEAD
@@ -1,21 +1,10 @@
-0000000000000000000000000000000000000000 f8154e00ed87f700e71790ab9966fc8414807b8a donya <donyavq@netscape.net> 1450296215 -0500	commit (initial): Initial commit
-f8154e00ed87f700e71790ab9966fc8414807b8a 4f1c6161cd6b76930d6ab63910f661e4c9280c64 donya <donyavq@netscape.net> 1450311885 -0500	commit: Renaming & restructuring
-4f1c6161cd6b76930d6ab63910f661e4c9280c64 85af43da1948ffbdf3b1fff153d88119842852b9 donya <donyavq@netscape.net> 1450315255 -0500	commit: Field renaming for MContext
-85af43da1948ffbdf3b1fff153d88119842852b9 5ea6aeb96d1894c8e38cc8f865fadb85bcacaad2 donya <donyavq@netscape.net> 1451596992 -0500	pull --progress --rebase --prune origin master: checkout 5ea6aeb96d1894c8e38cc8f865fadb85bcacaad2
-5ea6aeb96d1894c8e38cc8f865fadb85bcacaad2 5ea6aeb96d1894c8e38cc8f865fadb85bcacaad2 donya <donyavq@netscape.net> 1451596993 -0500	rebase finished: returning to refs/heads/master
-5ea6aeb96d1894c8e38cc8f865fadb85bcacaad2 8ca262164429aa9765dfd2fa47331f3349869329 donya <donyavq@netscape.net> 1451597251 -0500	commit: Dependency on UISF removed
-8ca262164429aa9765dfd2fa47331f3349869329 9bc107a80e863822b328bf64a795c3ef54e001b1 donya <donyavq@netscape.net> 1451597503 -0500	commit: Reame updated
-9bc107a80e863822b328bf64a795c3ef54e001b1 31ba3d0f73a9b2159cfa27d8e11e275daee8c481 donya <donyavq@netscape.net> 1451954740 -0500	pull --progress --rebase --prune origin master: checkout 31ba3d0f73a9b2159cfa27d8e11e275daee8c481
-31ba3d0f73a9b2159cfa27d8e11e275daee8c481 31ba3d0f73a9b2159cfa27d8e11e275daee8c481 donya <donyavq@netscape.net> 1451954740 -0500	rebase finished: returning to refs/heads/master
-31ba3d0f73a9b2159cfa27d8e11e275daee8c481 877cdbe88a44c2962bc9bc66e021ad8a9c185268 Donya Quick <donyavq@netscape.net> 1452131260 -0500	commit: Added writeWav
-877cdbe88a44c2962bc9bc66e021ad8a9c185268 323835bed7c98ee14e0445126cfc2df5cbed9bae Donya Quick <donyavq@netscape.net> 1452451734 -0500	pull --progress --rebase --prune origin master: checkout 323835bed7c98ee14e0445126cfc2df5cbed9bae
-323835bed7c98ee14e0445126cfc2df5cbed9bae 323835bed7c98ee14e0445126cfc2df5cbed9bae Donya Quick <donyavq@netscape.net> 1452451735 -0500	rebase finished: returning to refs/heads/master
-323835bed7c98ee14e0445126cfc2df5cbed9bae 73bc3b4c2d2ca70c8a8844a118e3d3db3aeb4d0c Donya Quick <donyavq@netscape.net> 1452537818 -0500	pull --progress --rebase --prune origin master: checkout 73bc3b4c2d2ca70c8a8844a118e3d3db3aeb4d0c
-73bc3b4c2d2ca70c8a8844a118e3d3db3aeb4d0c 73bc3b4c2d2ca70c8a8844a118e3d3db3aeb4d0c Donya Quick <donyavq@netscape.net> 1452537818 -0500	rebase finished: returning to refs/heads/master
-73bc3b4c2d2ca70c8a8844a118e3d3db3aeb4d0c 61d09a71180e5a1a4ea1d893f82a4709d8e79c27 Donya Quick <donyavq@netscape.net> 1453084077 -0500	commit: removeInstruments fixed
-61d09a71180e5a1a4ea1d893f82a4709d8e79c27 b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85 Donya Quick <donyavq@netscape.net> 1455221540 -0500	commit: invert fix
-b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85 086557985556cc77f5a559d74d0502a2d761babd Donya Quick <donyavq@netscape.net> 1456862557 -0500	pull --progress --rebase --prune origin master: checkout 086557985556cc77f5a559d74d0502a2d761babd
-086557985556cc77f5a559d74d0502a2d761babd 086557985556cc77f5a559d74d0502a2d761babd Donya Quick <donyavq@netscape.net> 1456862558 -0500	rebase finished: returning to refs/heads/master
-086557985556cc77f5a559d74d0502a2d761babd 7a5e865406dc8dc8d2bd730b7625656fc4c80036 Donya Quick <donyavq@netscape.net> 1459959169 -0400	commit: Dependency version changes
-7a5e865406dc8dc8d2bd730b7625656fc4c80036 896621f361866ce787d0bad1dfd5434d371b5679 Donya Quick <donyavq@netscape.net> 1461339370 -0400	commit: Exports added
-896621f361866ce787d0bad1dfd5434d371b5679 4afd6ed7d81c474bf5c88c395a584e4f68b039ce Donya Quick <donyavq@netscape.net> 1462819240 -0400	commit: dependency caps and audio render update
+0000000000000000000000000000000000000000 61d09a71180e5a1a4ea1d893f82a4709d8e79c27 donya <donyavq@netscape.net> 1453085786 -0500	clone: from https://github.com/Euterpea/Euterpea2.git
+61d09a71180e5a1a4ea1d893f82a4709d8e79c27 b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85 donya <donyavq@netscape.net> 1455231002 -0500	pull --progress --rebase --prune origin master: checkout b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85
+b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85 b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85 donya <donyavq@netscape.net> 1455231002 -0500	rebase finished: returning to refs/heads/master
+b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85 086557985556cc77f5a559d74d0502a2d761babd donya <donyavq@netscape.net> 1456848084 -0500	commit: ToMusic1 instance for AbsPitch added
+086557985556cc77f5a559d74d0502a2d761babd e461c0ab2477605902ab7a9c42969603f38bd586 donya <donyavq@netscape.net> 1465925605 -0500	pull --progress --rebase --prune origin master: checkout e461c0ab2477605902ab7a9c42969603f38bd586
+e461c0ab2477605902ab7a9c42969603f38bd586 e461c0ab2477605902ab7a9c42969603f38bd586 donya <donyavq@netscape.net> 1465925606 -0500	rebase finished: returning to refs/heads/master
+e461c0ab2477605902ab7a9c42969603f38bd586 aa72de41851f42d3f1023c01ae0edc5832c47ebd donya <donyavq@netscape.net> 1465930431 -0500	commit: Dependency versions temporarily relaxed
+aa72de41851f42d3f1023c01ae0edc5832c47ebd 40d6be12def8fc357df4248d9943bd3cc1f75f89 donya <donyavq@netscape.net> 1466564399 -0500	pull --progress --rebase --prune origin master: checkout 40d6be12def8fc357df4248d9943bd3cc1f75f89
+40d6be12def8fc357df4248d9943bd3cc1f75f89 40d6be12def8fc357df4248d9943bd3cc1f75f89 donya <donyavq@netscape.net> 1466564400 -0500	rebase finished: returning to refs/heads/master
+40d6be12def8fc357df4248d9943bd3cc1f75f89 fd7be762cd1a7bbca6b0eeec10ab260858db340d donya <donyavq@netscape.net> 1467320139 -0500	commit: Dependency versions narrowed again
diff --git a/.git/logs/refs/heads/master b/.git/logs/refs/heads/master
--- a/.git/logs/refs/heads/master
+++ b/.git/logs/refs/heads/master
@@ -1,16 +1,7 @@
-0000000000000000000000000000000000000000 f8154e00ed87f700e71790ab9966fc8414807b8a donya <donyavq@netscape.net> 1450296215 -0500	commit (initial): Initial commit
-f8154e00ed87f700e71790ab9966fc8414807b8a 4f1c6161cd6b76930d6ab63910f661e4c9280c64 donya <donyavq@netscape.net> 1450311885 -0500	commit: Renaming & restructuring
-4f1c6161cd6b76930d6ab63910f661e4c9280c64 85af43da1948ffbdf3b1fff153d88119842852b9 donya <donyavq@netscape.net> 1450315255 -0500	commit: Field renaming for MContext
-85af43da1948ffbdf3b1fff153d88119842852b9 5ea6aeb96d1894c8e38cc8f865fadb85bcacaad2 donya <donyavq@netscape.net> 1451596992 -0500	rebase finished: refs/heads/master onto 5ea6aeb96d1894c8e38cc8f865fadb85bcacaad2
-5ea6aeb96d1894c8e38cc8f865fadb85bcacaad2 8ca262164429aa9765dfd2fa47331f3349869329 donya <donyavq@netscape.net> 1451597251 -0500	commit: Dependency on UISF removed
-8ca262164429aa9765dfd2fa47331f3349869329 9bc107a80e863822b328bf64a795c3ef54e001b1 donya <donyavq@netscape.net> 1451597503 -0500	commit: Reame updated
-9bc107a80e863822b328bf64a795c3ef54e001b1 31ba3d0f73a9b2159cfa27d8e11e275daee8c481 donya <donyavq@netscape.net> 1451954740 -0500	rebase finished: refs/heads/master onto 31ba3d0f73a9b2159cfa27d8e11e275daee8c481
-31ba3d0f73a9b2159cfa27d8e11e275daee8c481 877cdbe88a44c2962bc9bc66e021ad8a9c185268 Donya Quick <donyavq@netscape.net> 1452131260 -0500	commit: Added writeWav
-877cdbe88a44c2962bc9bc66e021ad8a9c185268 323835bed7c98ee14e0445126cfc2df5cbed9bae Donya Quick <donyavq@netscape.net> 1452451735 -0500	rebase finished: refs/heads/master onto 323835bed7c98ee14e0445126cfc2df5cbed9bae
-323835bed7c98ee14e0445126cfc2df5cbed9bae 73bc3b4c2d2ca70c8a8844a118e3d3db3aeb4d0c Donya Quick <donyavq@netscape.net> 1452537818 -0500	rebase finished: refs/heads/master onto 73bc3b4c2d2ca70c8a8844a118e3d3db3aeb4d0c
-73bc3b4c2d2ca70c8a8844a118e3d3db3aeb4d0c 61d09a71180e5a1a4ea1d893f82a4709d8e79c27 Donya Quick <donyavq@netscape.net> 1453084077 -0500	commit: removeInstruments fixed
-61d09a71180e5a1a4ea1d893f82a4709d8e79c27 b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85 Donya Quick <donyavq@netscape.net> 1455221540 -0500	commit: invert fix
-b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85 086557985556cc77f5a559d74d0502a2d761babd Donya Quick <donyavq@netscape.net> 1456862558 -0500	rebase finished: refs/heads/master onto 086557985556cc77f5a559d74d0502a2d761babd
-086557985556cc77f5a559d74d0502a2d761babd 7a5e865406dc8dc8d2bd730b7625656fc4c80036 Donya Quick <donyavq@netscape.net> 1459959169 -0400	commit: Dependency version changes
-7a5e865406dc8dc8d2bd730b7625656fc4c80036 896621f361866ce787d0bad1dfd5434d371b5679 Donya Quick <donyavq@netscape.net> 1461339370 -0400	commit: Exports added
-896621f361866ce787d0bad1dfd5434d371b5679 4afd6ed7d81c474bf5c88c395a584e4f68b039ce Donya Quick <donyavq@netscape.net> 1462819240 -0400	commit: dependency caps and audio render update
+0000000000000000000000000000000000000000 61d09a71180e5a1a4ea1d893f82a4709d8e79c27 donya <donyavq@netscape.net> 1453085786 -0500	clone: from https://github.com/Euterpea/Euterpea2.git
+61d09a71180e5a1a4ea1d893f82a4709d8e79c27 b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85 donya <donyavq@netscape.net> 1455231002 -0500	rebase finished: refs/heads/master onto b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85
+b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85 086557985556cc77f5a559d74d0502a2d761babd donya <donyavq@netscape.net> 1456848084 -0500	commit: ToMusic1 instance for AbsPitch added
+086557985556cc77f5a559d74d0502a2d761babd e461c0ab2477605902ab7a9c42969603f38bd586 donya <donyavq@netscape.net> 1465925606 -0500	rebase finished: refs/heads/master onto e461c0ab2477605902ab7a9c42969603f38bd586
+e461c0ab2477605902ab7a9c42969603f38bd586 aa72de41851f42d3f1023c01ae0edc5832c47ebd donya <donyavq@netscape.net> 1465930431 -0500	commit: Dependency versions temporarily relaxed
+aa72de41851f42d3f1023c01ae0edc5832c47ebd 40d6be12def8fc357df4248d9943bd3cc1f75f89 donya <donyavq@netscape.net> 1466564400 -0500	rebase finished: refs/heads/master onto 40d6be12def8fc357df4248d9943bd3cc1f75f89
+40d6be12def8fc357df4248d9943bd3cc1f75f89 fd7be762cd1a7bbca6b0eeec10ab260858db340d donya <donyavq@netscape.net> 1467320139 -0500	commit: Dependency versions narrowed again
diff --git a/.git/logs/refs/remotes/origin/HEAD b/.git/logs/refs/remotes/origin/HEAD
--- a/.git/logs/refs/remotes/origin/HEAD
+++ b/.git/logs/refs/remotes/origin/HEAD
@@ -1,1 +1,1 @@
-0000000000000000000000000000000000000000 9bc107a80e863822b328bf64a795c3ef54e001b1 Donya Quick <donyavq@netscape.net> 1451691193 -0800	clone: from https://github.com/Euterpea/Euterpea2.git
+0000000000000000000000000000000000000000 61d09a71180e5a1a4ea1d893f82a4709d8e79c27 donya <donyavq@netscape.net> 1453085786 -0500	clone: from https://github.com/Euterpea/Euterpea2.git
diff --git a/.git/logs/refs/remotes/origin/master b/.git/logs/refs/remotes/origin/master
--- a/.git/logs/refs/remotes/origin/master
+++ b/.git/logs/refs/remotes/origin/master
@@ -1,16 +1,5 @@
-0000000000000000000000000000000000000000 f8154e00ed87f700e71790ab9966fc8414807b8a donya <donyavq@netscape.net> 1450296225 -0500	update by push
-f8154e00ed87f700e71790ab9966fc8414807b8a 4f1c6161cd6b76930d6ab63910f661e4c9280c64 donya <donyavq@netscape.net> 1450311899 -0500	update by push
-4f1c6161cd6b76930d6ab63910f661e4c9280c64 85af43da1948ffbdf3b1fff153d88119842852b9 donya <donyavq@netscape.net> 1450315267 -0500	update by push
-85af43da1948ffbdf3b1fff153d88119842852b9 5ea6aeb96d1894c8e38cc8f865fadb85bcacaad2 donya <donyavq@netscape.net> 1451596991 -0500	pull --progress --rebase --prune origin master: fast-forward
-5ea6aeb96d1894c8e38cc8f865fadb85bcacaad2 8ca262164429aa9765dfd2fa47331f3349869329 donya <donyavq@netscape.net> 1451597262 -0500	update by push
-8ca262164429aa9765dfd2fa47331f3349869329 9bc107a80e863822b328bf64a795c3ef54e001b1 donya <donyavq@netscape.net> 1451597514 -0500	update by push
-9bc107a80e863822b328bf64a795c3ef54e001b1 31ba3d0f73a9b2159cfa27d8e11e275daee8c481 donya <donyavq@netscape.net> 1451954738 -0500	pull --progress --rebase --prune origin master: fast-forward
-31ba3d0f73a9b2159cfa27d8e11e275daee8c481 877cdbe88a44c2962bc9bc66e021ad8a9c185268 Donya Quick <donyavq@netscape.net> 1452131278 -0500	update by push
-877cdbe88a44c2962bc9bc66e021ad8a9c185268 323835bed7c98ee14e0445126cfc2df5cbed9bae Donya Quick <donyavq@netscape.net> 1452451733 -0500	pull --progress --rebase --prune origin master: fast-forward
-323835bed7c98ee14e0445126cfc2df5cbed9bae 73bc3b4c2d2ca70c8a8844a118e3d3db3aeb4d0c Donya Quick <donyavq@netscape.net> 1452537816 -0500	pull --progress --rebase --prune origin master: fast-forward
-73bc3b4c2d2ca70c8a8844a118e3d3db3aeb4d0c 61d09a71180e5a1a4ea1d893f82a4709d8e79c27 Donya Quick <donyavq@netscape.net> 1453084100 -0500	update by push
-61d09a71180e5a1a4ea1d893f82a4709d8e79c27 b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85 Donya Quick <donyavq@netscape.net> 1455221559 -0500	update by push
-b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85 086557985556cc77f5a559d74d0502a2d761babd Donya Quick <donyavq@netscape.net> 1456862556 -0500	pull --progress --rebase --prune origin master: fast-forward
-086557985556cc77f5a559d74d0502a2d761babd 7a5e865406dc8dc8d2bd730b7625656fc4c80036 Donya Quick <donyavq@netscape.net> 1459959184 -0400	update by push
-7a5e865406dc8dc8d2bd730b7625656fc4c80036 896621f361866ce787d0bad1dfd5434d371b5679 Donya Quick <donyavq@netscape.net> 1461339414 -0400	update by push
-896621f361866ce787d0bad1dfd5434d371b5679 4afd6ed7d81c474bf5c88c395a584e4f68b039ce Donya Quick <donyavq@netscape.net> 1462819260 -0400	update by push
+61d09a71180e5a1a4ea1d893f82a4709d8e79c27 b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85 donya <donyavq@netscape.net> 1455231001 -0500	pull --progress --rebase --prune origin master: fast-forward
+b1eb4e6bd0c330b7cbe720d59df11bf3105b2b85 086557985556cc77f5a559d74d0502a2d761babd donya <donyavq@netscape.net> 1456848102 -0500	update by push
+086557985556cc77f5a559d74d0502a2d761babd e461c0ab2477605902ab7a9c42969603f38bd586 donya <donyavq@netscape.net> 1465925602 -0500	pull --progress --rebase --prune origin master: fast-forward
+e461c0ab2477605902ab7a9c42969603f38bd586 aa72de41851f42d3f1023c01ae0edc5832c47ebd donya <donyavq@netscape.net> 1465930440 -0500	update by push
+aa72de41851f42d3f1023c01ae0edc5832c47ebd 40d6be12def8fc357df4248d9943bd3cc1f75f89 donya <donyavq@netscape.net> 1466564397 -0500	pull --progress --rebase --prune origin master: fast-forward
diff --git a/.git/objects/07/34c378fd990e9ab7a7f9fb2fe361a84d41e95e b/.git/objects/07/34c378fd990e9ab7a7f9fb2fe361a84d41e95e
deleted file mode 100644
Binary files a/.git/objects/07/34c378fd990e9ab7a7f9fb2fe361a84d41e95e and /dev/null differ
diff --git a/.git/objects/08/1fa266eebe94ad9d1401de24163f05d6d378b3 b/.git/objects/08/1fa266eebe94ad9d1401de24163f05d6d378b3
new file mode 100644
Binary files /dev/null and b/.git/objects/08/1fa266eebe94ad9d1401de24163f05d6d378b3 differ
diff --git a/.git/objects/08/cf131880f52ce6a6d1e8dd2f0afb8ee0f30bcf b/.git/objects/08/cf131880f52ce6a6d1e8dd2f0afb8ee0f30bcf
new file mode 100644
Binary files /dev/null and b/.git/objects/08/cf131880f52ce6a6d1e8dd2f0afb8ee0f30bcf differ
diff --git a/.git/objects/09/53e4337fcc90c2a5c2ec957f9d46b4aa32ca99 b/.git/objects/09/53e4337fcc90c2a5c2ec957f9d46b4aa32ca99
new file mode 100644
Binary files /dev/null and b/.git/objects/09/53e4337fcc90c2a5c2ec957f9d46b4aa32ca99 differ
diff --git a/.git/objects/0c/262c7a72c9e17768fa826a90472e376c09767a b/.git/objects/0c/262c7a72c9e17768fa826a90472e376c09767a
new file mode 100644
Binary files /dev/null and b/.git/objects/0c/262c7a72c9e17768fa826a90472e376c09767a differ
diff --git a/.git/objects/0e/40a7618f3033863399b53fd837057d05c90d33 b/.git/objects/0e/40a7618f3033863399b53fd837057d05c90d33
new file mode 100644
Binary files /dev/null and b/.git/objects/0e/40a7618f3033863399b53fd837057d05c90d33 differ
diff --git a/.git/objects/0e/668119469c51796e6d599be3210067a29b2519 b/.git/objects/0e/668119469c51796e6d599be3210067a29b2519
deleted file mode 100644
Binary files a/.git/objects/0e/668119469c51796e6d599be3210067a29b2519 and /dev/null differ
diff --git a/.git/objects/0f/40bd8185ca44ac857d80e28f1571f7dc4c2f0b b/.git/objects/0f/40bd8185ca44ac857d80e28f1571f7dc4c2f0b
deleted file mode 100644
Binary files a/.git/objects/0f/40bd8185ca44ac857d80e28f1571f7dc4c2f0b and /dev/null differ
diff --git a/.git/objects/10/aedf5be4cd4cba55b64d5f6995b2848da5156b b/.git/objects/10/aedf5be4cd4cba55b64d5f6995b2848da5156b
new file mode 100644
Binary files /dev/null and b/.git/objects/10/aedf5be4cd4cba55b64d5f6995b2848da5156b differ
diff --git a/.git/objects/12/422ea17098ee8ef49c69ec4f706610531ff7a5 b/.git/objects/12/422ea17098ee8ef49c69ec4f706610531ff7a5
deleted file mode 100644
Binary files a/.git/objects/12/422ea17098ee8ef49c69ec4f706610531ff7a5 and /dev/null differ
diff --git a/.git/objects/13/ff9346b625728e873af12be8d41ba411d16d3a b/.git/objects/13/ff9346b625728e873af12be8d41ba411d16d3a
new file mode 100644
Binary files /dev/null and b/.git/objects/13/ff9346b625728e873af12be8d41ba411d16d3a differ
diff --git a/.git/objects/15/3be0645392d0fcd358365100287c8153667803 b/.git/objects/15/3be0645392d0fcd358365100287c8153667803
deleted file mode 100644
Binary files a/.git/objects/15/3be0645392d0fcd358365100287c8153667803 and /dev/null differ
diff --git a/.git/objects/16/053d551af0017fc14257241ace886edd2afc02 b/.git/objects/16/053d551af0017fc14257241ace886edd2afc02
new file mode 100644
Binary files /dev/null and b/.git/objects/16/053d551af0017fc14257241ace886edd2afc02 differ
diff --git a/.git/objects/18/120c7891df6d6b7a4edb6505c550b9a48dcfc6 b/.git/objects/18/120c7891df6d6b7a4edb6505c550b9a48dcfc6
deleted file mode 100644
Binary files a/.git/objects/18/120c7891df6d6b7a4edb6505c550b9a48dcfc6 and /dev/null differ
diff --git a/.git/objects/18/2a0398ba6a070c251b036c128fb0d923b1b04a b/.git/objects/18/2a0398ba6a070c251b036c128fb0d923b1b04a
new file mode 100644
Binary files /dev/null and b/.git/objects/18/2a0398ba6a070c251b036c128fb0d923b1b04a differ
diff --git a/.git/objects/19/0569154271005cf561a49b93e0dacf5d237670 b/.git/objects/19/0569154271005cf561a49b93e0dacf5d237670
deleted file mode 100644
Binary files a/.git/objects/19/0569154271005cf561a49b93e0dacf5d237670 and /dev/null differ
diff --git a/.git/objects/19/a4d9c645f7e4b9f5414e5bb1b45de9a1c3ea40 b/.git/objects/19/a4d9c645f7e4b9f5414e5bb1b45de9a1c3ea40
deleted file mode 100644
Binary files a/.git/objects/19/a4d9c645f7e4b9f5414e5bb1b45de9a1c3ea40 and /dev/null differ
diff --git a/.git/objects/1b/963cb16e69a4719c07d01041419fc0016888e9 b/.git/objects/1b/963cb16e69a4719c07d01041419fc0016888e9
new file mode 100644
Binary files /dev/null and b/.git/objects/1b/963cb16e69a4719c07d01041419fc0016888e9 differ
diff --git a/.git/objects/1d/4d0774da205784863ae2d06988d4c525dd5b22 b/.git/objects/1d/4d0774da205784863ae2d06988d4c525dd5b22
deleted file mode 100644
Binary files a/.git/objects/1d/4d0774da205784863ae2d06988d4c525dd5b22 and /dev/null differ
diff --git a/.git/objects/1d/865ab036c3dafe78300b3876f46e7fc91b1836 b/.git/objects/1d/865ab036c3dafe78300b3876f46e7fc91b1836
new file mode 100644
Binary files /dev/null and b/.git/objects/1d/865ab036c3dafe78300b3876f46e7fc91b1836 differ
diff --git a/.git/objects/1e/e46d0b56ddaa82b9a081a21369c1509b84402e b/.git/objects/1e/e46d0b56ddaa82b9a081a21369c1509b84402e
new file mode 100644
Binary files /dev/null and b/.git/objects/1e/e46d0b56ddaa82b9a081a21369c1509b84402e differ
diff --git a/.git/objects/1f/0b51995096b04b9c0bb36b633333ee53cf6ede b/.git/objects/1f/0b51995096b04b9c0bb36b633333ee53cf6ede
deleted file mode 100644
Binary files a/.git/objects/1f/0b51995096b04b9c0bb36b633333ee53cf6ede and /dev/null differ
diff --git a/.git/objects/22/9b691fbf867126dc4e40ed8b5bf16facc90e7a b/.git/objects/22/9b691fbf867126dc4e40ed8b5bf16facc90e7a
deleted file mode 100644
Binary files a/.git/objects/22/9b691fbf867126dc4e40ed8b5bf16facc90e7a and /dev/null differ
diff --git a/.git/objects/23/e8522114db4fb8526a9948e7c91250c63a9928 b/.git/objects/23/e8522114db4fb8526a9948e7c91250c63a9928
deleted file mode 100644
Binary files a/.git/objects/23/e8522114db4fb8526a9948e7c91250c63a9928 and /dev/null differ
diff --git a/.git/objects/26/252acd178a04d8b98a75016a754d8b7bc4dfdd b/.git/objects/26/252acd178a04d8b98a75016a754d8b7bc4dfdd
deleted file mode 100644
Binary files a/.git/objects/26/252acd178a04d8b98a75016a754d8b7bc4dfdd and /dev/null differ
diff --git a/.git/objects/26/d1e77943b1fe7cb446dd7ac0fef7cc1c495845 b/.git/objects/26/d1e77943b1fe7cb446dd7ac0fef7cc1c495845
new file mode 100644
--- /dev/null
+++ b/.git/objects/26/d1e77943b1fe7cb446dd7ac0fef7cc1c495845
@@ -0,0 +1,6 @@
+xTQoÚ@Þóý
++OJ"J7:¡1i+tªZvÓ¦I½
+]+\Xr)l¿¾vrPÄç³?Ûí³"Ó·çïÞäEZgnYVóimd¹|ø{e¥
+Ýki>+=QeP¼Q±'Â'£ZndBGçD×*_E.×ïª¤Ðh&¬²©|U~×"SJ¦pQhSY4Ý$re0tgOèÑÏ6Oð­àGQ8gdMõ³*KmÀÇðÜÜ2«SL"&Y^Í`4ü~¿]Í:nÈ"pBç:Þæ5pY	Õ&Ø©ÆN÷^¿×û+Ío5:±ÛÈUË"ÊKSu¦îÁ¼ç?*¤óOi®4~V+âóo@ÅóDÄ"ã£z¬ùÞêìý0\câÅº
+Ë$<NûÑçn¤ÂAÔúá¥þõ·Nn×_òé©®îfÃåÆc¶ÆãÓ~eà¦4KÞÄ¼²G¼4ÇØ±ëEK¸Ý$;±ÝthX«j;õà¹æí yø|N\JSZu@)µk~¤=VÝÐ¼MpN¥bû¿cõ.û¸ÂÈ¶Ñ{hÛ«p¿C¹m;»¸½
+R©î±ÛÝKûLìöçS#ø$ÒJ©¿dÄ¡ÎvÆ§»ð8÷èKn{é+ñ@
diff --git a/.git/objects/27/f49fd3429321b1ee2c1546eb63256dc0730c1f b/.git/objects/27/f49fd3429321b1ee2c1546eb63256dc0730c1f
new file mode 100644
Binary files /dev/null and b/.git/objects/27/f49fd3429321b1ee2c1546eb63256dc0730c1f differ
diff --git a/.git/objects/28/0bbfa003c4249f5fc4a59ad5fa724272bc2d02 b/.git/objects/28/0bbfa003c4249f5fc4a59ad5fa724272bc2d02
deleted file mode 100644
Binary files a/.git/objects/28/0bbfa003c4249f5fc4a59ad5fa724272bc2d02 and /dev/null differ
diff --git a/.git/objects/28/fb2df2b4bf2f8be62602e7b3b6ad99289fefac b/.git/objects/28/fb2df2b4bf2f8be62602e7b3b6ad99289fefac
deleted file mode 100644
Binary files a/.git/objects/28/fb2df2b4bf2f8be62602e7b3b6ad99289fefac and /dev/null differ
diff --git a/.git/objects/29/09458fe91e193322f78abdafd7c8b9c2480b9f b/.git/objects/29/09458fe91e193322f78abdafd7c8b9c2480b9f
deleted file mode 100644
Binary files a/.git/objects/29/09458fe91e193322f78abdafd7c8b9c2480b9f and /dev/null differ
diff --git a/.git/objects/29/3bd1d6053e165fb63a1bc860ce65d28160759f b/.git/objects/29/3bd1d6053e165fb63a1bc860ce65d28160759f
new file mode 100644
# file too large to diff: .git/objects/29/3bd1d6053e165fb63a1bc860ce65d28160759f
diff --git a/.git/objects/2c/1360591bec55fca7893b298b53197be3c867ba b/.git/objects/2c/1360591bec55fca7893b298b53197be3c867ba
deleted file mode 100644
Binary files a/.git/objects/2c/1360591bec55fca7893b298b53197be3c867ba and /dev/null differ
diff --git a/.git/objects/2c/230b496eb8d7ee15595fc8bb6e0893af19008b b/.git/objects/2c/230b496eb8d7ee15595fc8bb6e0893af19008b
new file mode 100644
Binary files /dev/null and b/.git/objects/2c/230b496eb8d7ee15595fc8bb6e0893af19008b differ
diff --git a/.git/objects/2e/0b0c295239ecdf1e63e6a7536505ac813f47f9 b/.git/objects/2e/0b0c295239ecdf1e63e6a7536505ac813f47f9
deleted file mode 100644
Binary files a/.git/objects/2e/0b0c295239ecdf1e63e6a7536505ac813f47f9 and /dev/null differ
diff --git a/.git/objects/31/5c172ba4c6d45564249a225f0e075f671c5fbb b/.git/objects/31/5c172ba4c6d45564249a225f0e075f671c5fbb
deleted file mode 100644
--- a/.git/objects/31/5c172ba4c6d45564249a225f0e075f671c5fbb
+++ /dev/null
@@ -1,3 +0,0 @@
-x+)JMU022e040031QpJ,ÎLÎLw+Í+ÖËÉ(f	8¹yQðBÃ
-E®Gfä"«-Ö*Ê©XÇ|?Gú°é§Ã7¥6O«½ÈÕUä_6jÃ¡'Y¬=6Ýshë¤éÚ÷í¡ª<ýAÆ·aæ¨v.`î rãòç"¡
-RóRR@ÔTµÎw±ÜØÙUÊUêÛ]}äþ]¨¢ÊT°{ÎnÌ­ò­yxwK~WºêLµSÕ_X2
diff --git a/.git/objects/31/ba3d0f73a9b2159cfa27d8e11e275daee8c481 b/.git/objects/31/ba3d0f73a9b2159cfa27d8e11e275daee8c481
deleted file mode 100644
Binary files a/.git/objects/31/ba3d0f73a9b2159cfa27d8e11e275daee8c481 and /dev/null differ
diff --git a/.git/objects/32/3835bed7c98ee14e0445126cfc2df5cbed9bae b/.git/objects/32/3835bed7c98ee14e0445126cfc2df5cbed9bae
deleted file mode 100644
Binary files a/.git/objects/32/3835bed7c98ee14e0445126cfc2df5cbed9bae and /dev/null differ
diff --git a/.git/objects/32/eee8d97247283b82f847ae18b0739f135577c6 b/.git/objects/32/eee8d97247283b82f847ae18b0739f135577c6
new file mode 100644
--- /dev/null
+++ b/.git/objects/32/eee8d97247283b82f847ae18b0739f135577c6
@@ -0,0 +1,1 @@
+x+)JMU°0g040031QH,É(w--I-*HMÔË(fP»ø¼Òyã¿-nw«üû~FÆ3Âª891)1'>71¹(¿X/áö¦7334â¦òO<÷õ¨CáµÛÌJ(s
diff --git a/.git/objects/35/05de91ee4ca4ab2c00ab4d0e05daae68dde53b b/.git/objects/35/05de91ee4ca4ab2c00ab4d0e05daae68dde53b
new file mode 100644
Binary files /dev/null and b/.git/objects/35/05de91ee4ca4ab2c00ab4d0e05daae68dde53b differ
diff --git a/.git/objects/35/8436995aff5176e643cebf3c5d070536ac57cb b/.git/objects/35/8436995aff5176e643cebf3c5d070536ac57cb
deleted file mode 100644
Binary files a/.git/objects/35/8436995aff5176e643cebf3c5d070536ac57cb and /dev/null differ
diff --git a/.git/objects/36/e8447f23fe4c9fc02644fae5965b7b9fe966fd b/.git/objects/36/e8447f23fe4c9fc02644fae5965b7b9fe966fd
new file mode 100644
Binary files /dev/null and b/.git/objects/36/e8447f23fe4c9fc02644fae5965b7b9fe966fd differ
diff --git a/.git/objects/37/3df86f01c69ae7dcc599f9c11e786415e4d1e6 b/.git/objects/37/3df86f01c69ae7dcc599f9c11e786415e4d1e6
new file mode 100644
Binary files /dev/null and b/.git/objects/37/3df86f01c69ae7dcc599f9c11e786415e4d1e6 differ
diff --git a/.git/objects/38/79732a59fd96782ac7fec01e882bc419a650f6 b/.git/objects/38/79732a59fd96782ac7fec01e882bc419a650f6
deleted file mode 100644
Binary files a/.git/objects/38/79732a59fd96782ac7fec01e882bc419a650f6 and /dev/null differ
diff --git a/.git/objects/39/1156a543887fc398238ebd6b61194807e1c8df b/.git/objects/39/1156a543887fc398238ebd6b61194807e1c8df
deleted file mode 100644
Binary files a/.git/objects/39/1156a543887fc398238ebd6b61194807e1c8df and /dev/null differ
diff --git a/.git/objects/3a/77dd1cc37ae544654eafe0d6106d0322fcd6d6 b/.git/objects/3a/77dd1cc37ae544654eafe0d6106d0322fcd6d6
deleted file mode 100644
Binary files a/.git/objects/3a/77dd1cc37ae544654eafe0d6106d0322fcd6d6 and /dev/null differ
diff --git a/.git/objects/3a/f2137fd14e17ec39cd86c35eb817be41236fa3 b/.git/objects/3a/f2137fd14e17ec39cd86c35eb817be41236fa3
deleted file mode 100644
Binary files a/.git/objects/3a/f2137fd14e17ec39cd86c35eb817be41236fa3 and /dev/null differ
diff --git a/.git/objects/3e/ee7432174ba6920cdc77a546f40abea4363bb0 b/.git/objects/3e/ee7432174ba6920cdc77a546f40abea4363bb0
deleted file mode 100644
Binary files a/.git/objects/3e/ee7432174ba6920cdc77a546f40abea4363bb0 and /dev/null differ
diff --git a/.git/objects/40/0528d8d6e72ec2edc4fee57e208bc972fdc90f b/.git/objects/40/0528d8d6e72ec2edc4fee57e208bc972fdc90f
new file mode 100644
--- /dev/null
+++ b/.git/objects/40/0528d8d6e72ec2edc4fee57e208bc972fdc90f
@@ -0,0 +1,2 @@
+x+)JMU03e040031QvÓËÈdØQäÖÌ*Ûûêä;âþA+
+ò>i§>Lßú*d3«h¯¡Y÷Ël
diff --git a/.git/objects/40/d6be12def8fc357df4248d9943bd3cc1f75f89 b/.git/objects/40/d6be12def8fc357df4248d9943bd3cc1f75f89
new file mode 100644
--- /dev/null
+++ b/.git/objects/40/d6be12def8fc357df4248d9943bd3cc1f75f89
@@ -0,0 +1,1 @@
+xMNÃ0FYûs*ÿ%R@p0«	RoOÚ]·ì¾·xÕesOÚD ëìØ#eáH)ö#ÆáÆh1è|VÌMbò,ÑËÑsÈÎú@Ö¡Xaêà)&Ùà®Úà³+Â×>Ñ7ù¿?oEt#\åtWp±ïC\Lðl;kÝUþg\×ùúQ¶:o°Ô&Ðê¸ojÌ;³0 ó¤S-8á&ä#4VÐÀãMÞÝùß[hÀ
diff --git a/.git/objects/41/2224f723a4330a7004dc7c1eb1f62ddef2c206 b/.git/objects/41/2224f723a4330a7004dc7c1eb1f62ddef2c206
new file mode 100644
Binary files /dev/null and b/.git/objects/41/2224f723a4330a7004dc7c1eb1f62ddef2c206 differ
diff --git a/.git/objects/41/d19a4642f6660a4179f3c71e91735989598daf b/.git/objects/41/d19a4642f6660a4179f3c71e91735989598daf
deleted file mode 100644
Binary files a/.git/objects/41/d19a4642f6660a4179f3c71e91735989598daf and /dev/null differ
diff --git a/.git/objects/42/4bc74689367dde97ffde93f82558e7dc6c0bf2 b/.git/objects/42/4bc74689367dde97ffde93f82558e7dc6c0bf2
new file mode 100644
Binary files /dev/null and b/.git/objects/42/4bc74689367dde97ffde93f82558e7dc6c0bf2 differ
diff --git a/.git/objects/42/e3ec9572ed4138542efdf91a07554c835f4882 b/.git/objects/42/e3ec9572ed4138542efdf91a07554c835f4882
deleted file mode 100644
Binary files a/.git/objects/42/e3ec9572ed4138542efdf91a07554c835f4882 and /dev/null differ
diff --git a/.git/objects/46/4199cbe596b6d8e366c3f5900c87740c819acf b/.git/objects/46/4199cbe596b6d8e366c3f5900c87740c819acf
deleted file mode 100644
Binary files a/.git/objects/46/4199cbe596b6d8e366c3f5900c87740c819acf and /dev/null differ
diff --git a/.git/objects/46/d74297ecb00ced0498fca2d37ef1123967d685 b/.git/objects/46/d74297ecb00ced0498fca2d37ef1123967d685
deleted file mode 100644
Binary files a/.git/objects/46/d74297ecb00ced0498fca2d37ef1123967d685 and /dev/null differ
diff --git a/.git/objects/4d/011c28a383821201d0c2da48db909df774df62 b/.git/objects/4d/011c28a383821201d0c2da48db909df774df62
deleted file mode 100644
Binary files a/.git/objects/4d/011c28a383821201d0c2da48db909df774df62 and /dev/null differ
diff --git a/.git/objects/4f/1c6161cd6b76930d6ab63910f661e4c9280c64 b/.git/objects/4f/1c6161cd6b76930d6ab63910f661e4c9280c64
deleted file mode 100644
--- a/.git/objects/4f/1c6161cd6b76930d6ab63910f661e4c9280c64
+++ /dev/null
@@ -1,1 +0,0 @@
-xN»NÄ0¤öWlu÷Ç	¡k(Añ~¬HÄâï±BEI53Íø¼®Kò¦fÐg6ÎÓJ#irGrj¢ æÑgVÇ9ÍN"¡YJd¢éhÐÌÒºy¦èiÄ¤qdmõ-9}[¸;àóã¸îÞn<tr8j©4ÜJ-¥ðÇ»ÊÿíNv]ÒNPx¯¥ùÚJ×B<s¹¬Ö½s·zÔ¯ù±íGñÐúÜÆv8ôð+ÿRXvHùþÄ7eÈ
diff --git a/.git/objects/50/3f8ef4dd7e6196ceb6045ca57275d8e337e43b b/.git/objects/50/3f8ef4dd7e6196ceb6045ca57275d8e337e43b
deleted file mode 100644
--- a/.git/objects/50/3f8ef4dd7e6196ceb6045ca57275d8e337e43b
+++ /dev/null
@@ -1,3 +0,0 @@
-x=Â0]Í¯¸±ÒIÐÅAÁB)XÁ95§òañßSDBÖ{÷½F5Àj½YÅüpðFZ·]½ó+P@
-Ö{jùµç÷ÆK[2jN:¿4æ¶ËütBÉÐTd9îðB!X	ÓÂVÆý÷ü©±lÇiÜvi6Ç&än
-~¤l!®wD«l&öì@?Rä\(ïn9¿g`	y­I 4
diff --git a/.git/objects/52/8e6cd0e3e16d9dbb927d3bb4bcd83ecf8dfad6 b/.git/objects/52/8e6cd0e3e16d9dbb927d3bb4bcd83ecf8dfad6
deleted file mode 100644
--- a/.git/objects/52/8e6cd0e3e16d9dbb927d3bb4bcd83ecf8dfad6
+++ /dev/null
@@ -1,6 +0,0 @@
-xUÙnÛ8g}ÅAúP)µÜÊ0 à¦étÉL¾4EÙÄÐ"AQþ{ï¥$/>¾Û9wõÜØ9?ÿ:ûã¿ü>Í¾¼¿½¿ÂÌ{{ßpµÖMPuÐÂüÝ
-úVZ m=Â;£ÖznÔ¥­Z2¾Ö©òvãÔ7áµ ]gùÏ$YÙ²5
-WmPÞ)1þøu<kKmÇoD£e4lf#ÐCS¸fDoiÛ:¼µ÷w¥­kÄÊÅo'·öÃÃÂñ7Ép¿T^%^9ëÃósKPO¤[&ÌºÔ·f«pT8þê8îÔ¹^'IÂyáüiaz9æj
-á=tIûÄÙº²TCvnÜ{^j/[ F¸4Vþ#Å¨×l·¶¥÷]´)0* ¢ÀKu´­KUéZè²h¦k8o%ÖÈ/PÚ(¼1~N4^ú¢õZ¯ñ:G©Øàò×ÐÏ{eÌI²í&ãEâÛ¤¸(ëÀ iÆï=ó5¡FVß÷X1§=T"L ÈQDàÇ°wî8è!Yý©Ëð)&ó sH¸n²måÒj©¸EØv¶Ø¾&dÃr2ëÉçíº_ÐDI®ÎN4aÑRE©-¢{Üz÷©ö­ÞÃsÓ÷ÜÉ åãFW,»ÂçÂRÕÔeEÒ]zÏî³aw}¦S2=ç´	^;T·rýÏAø#âtC÷ ¼íÈyóø0{
-OùÒüÃÛ@ÃSÇÇ¡kä§èz\º¶a{~hR½¨­°Ôº;Ýbcïû_'òÐ=è³'AÜíhÑ-iLtqÜr%IãÆ®ÚFU-v­~ª­%ñfþ¼Ê]/ jÌæÍµr	J
-HåFò5§£FI[ÙyÒ]\õwÆÒ-dç8;/ó`%x³ÎÎ^ÑÝàôiåí¶<z¤¤Î!Çt6:Ë2ºSEÆCö$¤âaZÅD?<'ýÁSJmä3ØÐÝÿoq×Ó
diff --git a/.git/objects/52/c3e648f28c37c75cbad302221d9d7e63b8b83e b/.git/objects/52/c3e648f28c37c75cbad302221d9d7e63b8b83e
new file mode 100644
Binary files /dev/null and b/.git/objects/52/c3e648f28c37c75cbad302221d9d7e63b8b83e differ
diff --git a/.git/objects/52/e7bb8b5351858b6c18b368d3947dc1231a5f9f b/.git/objects/52/e7bb8b5351858b6c18b368d3947dc1231a5f9f
deleted file mode 100644
Binary files a/.git/objects/52/e7bb8b5351858b6c18b368d3947dc1231a5f9f and /dev/null differ
diff --git a/.git/objects/53/d8a923285953866fc263789d67e4c38525c4fa b/.git/objects/53/d8a923285953866fc263789d67e4c38525c4fa
deleted file mode 100644
Binary files a/.git/objects/53/d8a923285953866fc263789d67e4c38525c4fa and /dev/null differ
diff --git a/.git/objects/54/5758c9b40f03a253a47131d9207245c4986c51 b/.git/objects/54/5758c9b40f03a253a47131d9207245c4986c51
deleted file mode 100644
Binary files a/.git/objects/54/5758c9b40f03a253a47131d9207245c4986c51 and /dev/null differ
diff --git a/.git/objects/54/7dcd3ab2847acaaa664560053063485e9799af b/.git/objects/54/7dcd3ab2847acaaa664560053063485e9799af
new file mode 100644
--- /dev/null
+++ b/.git/objects/54/7dcd3ab2847acaaa664560053063485e9799af
@@ -0,0 +1,2 @@
+xA
+Â0E]çs%iÒv".¼GÌL°HZSÁÛ[=»÷á}x\Æq¨ÐxÜÕEmZ$Ìì]Ö¦ì5%bK>'/ÌLNeéTzAÇ¡)·È~S[rÉúÈjh­·²À¥Loë:ðò¯ÇyÒúdõ°Á	\èt1Æö6Xkø×Xõ¿·¹^Ç­êP&Xg¡ªb>	ÿN©
diff --git a/.git/objects/55/ec0b6acfed4cda746ba489cbfaa0a78a12330e b/.git/objects/55/ec0b6acfed4cda746ba489cbfaa0a78a12330e
new file mode 100644
Binary files /dev/null and b/.git/objects/55/ec0b6acfed4cda746ba489cbfaa0a78a12330e differ
diff --git a/.git/objects/57/c5213c0484db428f6c4cf6e6214e89a8ae1495 b/.git/objects/57/c5213c0484db428f6c4cf6e6214e89a8ae1495
new file mode 100644
Binary files /dev/null and b/.git/objects/57/c5213c0484db428f6c4cf6e6214e89a8ae1495 differ
diff --git a/.git/objects/59/22faa1f075f43bf5ff192ef560a4c1ee5ac7d8 b/.git/objects/59/22faa1f075f43bf5ff192ef560a4c1ee5ac7d8
deleted file mode 100644
Binary files a/.git/objects/59/22faa1f075f43bf5ff192ef560a4c1ee5ac7d8 and /dev/null differ
diff --git a/.git/objects/5a/0a4abb675bb7edeeb1581ef36c3107d9ddabc0 b/.git/objects/5a/0a4abb675bb7edeeb1581ef36c3107d9ddabc0
new file mode 100644
Binary files /dev/null and b/.git/objects/5a/0a4abb675bb7edeeb1581ef36c3107d9ddabc0 differ
diff --git a/.git/objects/5a/7588690dec40ed5e79d4831b388b095febcb2f b/.git/objects/5a/7588690dec40ed5e79d4831b388b095febcb2f
deleted file mode 100644
Binary files a/.git/objects/5a/7588690dec40ed5e79d4831b388b095febcb2f and /dev/null differ
diff --git a/.git/objects/5a/db5e8db2e5525db664ff2e17de8b87ff0f8670 b/.git/objects/5a/db5e8db2e5525db664ff2e17de8b87ff0f8670
new file mode 100644
Binary files /dev/null and b/.git/objects/5a/db5e8db2e5525db664ff2e17de8b87ff0f8670 differ
diff --git a/.git/objects/5b/f300951510805ff5a3fe166487788a031778a5 b/.git/objects/5b/f300951510805ff5a3fe166487788a031778a5
deleted file mode 100644
Binary files a/.git/objects/5b/f300951510805ff5a3fe166487788a031778a5 and /dev/null differ
diff --git a/.git/objects/5e/a6aeb96d1894c8e38cc8f865fadb85bcacaad2 b/.git/objects/5e/a6aeb96d1894c8e38cc8f865fadb85bcacaad2
deleted file mode 100644
Binary files a/.git/objects/5e/a6aeb96d1894c8e38cc8f865fadb85bcacaad2 and /dev/null differ
diff --git a/.git/objects/60/492b4c521313c25cb4c46b57d0b72cc74d7cbd b/.git/objects/60/492b4c521313c25cb4c46b57d0b72cc74d7cbd
new file mode 100644
Binary files /dev/null and b/.git/objects/60/492b4c521313c25cb4c46b57d0b72cc74d7cbd differ
diff --git a/.git/objects/61/d09a71180e5a1a4ea1d893f82a4709d8e79c27 b/.git/objects/61/d09a71180e5a1a4ea1d893f82a4709d8e79c27
deleted file mode 100644
Binary files a/.git/objects/61/d09a71180e5a1a4ea1d893f82a4709d8e79c27 and /dev/null differ
diff --git a/.git/objects/64/0e75d56b3758363d58a86d728c5403aa92c840 b/.git/objects/64/0e75d56b3758363d58a86d728c5403aa92c840
deleted file mode 100644
Binary files a/.git/objects/64/0e75d56b3758363d58a86d728c5403aa92c840 and /dev/null differ
diff --git a/.git/objects/64/5249b0b24a3bd4e03e6fc30606002c2e91696d b/.git/objects/64/5249b0b24a3bd4e03e6fc30606002c2e91696d
deleted file mode 100644
--- a/.git/objects/64/5249b0b24a3bd4e03e6fc30606002c2e91696d
+++ /dev/null
@@ -1,1 +0,0 @@
-xuËjÃ0E»öWd@¤U(tyñ"[?&d@ÖI&6¡ÿ^7Æ©º»{h®RÍ)¬>ÞßÖp3>cO Î5¥q>1:¯àÕOaÓc±5Î+°¯<Ú·¼¦2¬eòÈ»q9i©Hnªø_ªÁ-oYËµ|ë_ÉÁÚ&Ð.Ël9ÇLÓãu¬K¶þ@@E??ÐnW´¬Û­CÏªÀÓF?-~É¨Â0îOºº_Q6ñÄÆÁ7U¦,
diff --git a/.git/objects/66/08033e85b06e8aa5ef9fe4a115b47500a073f0 b/.git/objects/66/08033e85b06e8aa5ef9fe4a115b47500a073f0
deleted file mode 100644
Binary files a/.git/objects/66/08033e85b06e8aa5ef9fe4a115b47500a073f0 and /dev/null differ
diff --git a/.git/objects/66/a5ca12ace8806a4001b7082db3bdb8b35267eb b/.git/objects/66/a5ca12ace8806a4001b7082db3bdb8b35267eb
deleted file mode 100644
Binary files a/.git/objects/66/a5ca12ace8806a4001b7082db3bdb8b35267eb and /dev/null differ
diff --git a/.git/objects/67/eab6e41d9b7d3b8cce4cfc4b5ad44649fba760 b/.git/objects/67/eab6e41d9b7d3b8cce4cfc4b5ad44649fba760
new file mode 100644
Binary files /dev/null and b/.git/objects/67/eab6e41d9b7d3b8cce4cfc4b5ad44649fba760 differ
diff --git a/.git/objects/68/440e1520af9fb733724b7b81e907a4dab956b8 b/.git/objects/68/440e1520af9fb733724b7b81e907a4dab956b8
deleted file mode 100644
Binary files a/.git/objects/68/440e1520af9fb733724b7b81e907a4dab956b8 and /dev/null differ
diff --git a/.git/objects/68/afa542d4797b1b25cc5a255fb4ae50014fcc65 b/.git/objects/68/afa542d4797b1b25cc5a255fb4ae50014fcc65
deleted file mode 100644
Binary files a/.git/objects/68/afa542d4797b1b25cc5a255fb4ae50014fcc65 and /dev/null differ
diff --git a/.git/objects/69/680bdab02d8e951979477178f796b43bd5df01 b/.git/objects/69/680bdab02d8e951979477178f796b43bd5df01
deleted file mode 100644
Binary files a/.git/objects/69/680bdab02d8e951979477178f796b43bd5df01 and /dev/null differ
diff --git a/.git/objects/69/fdad39ac0a3e2e0c9b5347e7e6f666d8f769a4 b/.git/objects/69/fdad39ac0a3e2e0c9b5347e7e6f666d8f769a4
deleted file mode 100644
Binary files a/.git/objects/69/fdad39ac0a3e2e0c9b5347e7e6f666d8f769a4 and /dev/null differ
diff --git a/.git/objects/6b/cae40f355478a4d15eee9b66d161e7a0a12dd2 b/.git/objects/6b/cae40f355478a4d15eee9b66d161e7a0a12dd2
new file mode 100644
Binary files /dev/null and b/.git/objects/6b/cae40f355478a4d15eee9b66d161e7a0a12dd2 differ
diff --git a/.git/objects/6c/080e1fa918201ddbbdf7faa8bf8426e590092d b/.git/objects/6c/080e1fa918201ddbbdf7faa8bf8426e590092d
deleted file mode 100644
Binary files a/.git/objects/6c/080e1fa918201ddbbdf7faa8bf8426e590092d and /dev/null differ
diff --git a/.git/objects/6c/78ae03df6c1bc335f2c3d91ab317967dd10a8b b/.git/objects/6c/78ae03df6c1bc335f2c3d91ab317967dd10a8b
deleted file mode 100644
Binary files a/.git/objects/6c/78ae03df6c1bc335f2c3d91ab317967dd10a8b and /dev/null differ
diff --git a/.git/objects/6d/983efc33facf5d019fefdc11c253042f6f1a57 b/.git/objects/6d/983efc33facf5d019fefdc11c253042f6f1a57
deleted file mode 100644
Binary files a/.git/objects/6d/983efc33facf5d019fefdc11c253042f6f1a57 and /dev/null differ
diff --git a/.git/objects/70/c3238c627e9fc1187b9828d5583a470e9ad056 b/.git/objects/70/c3238c627e9fc1187b9828d5583a470e9ad056
new file mode 100644
Binary files /dev/null and b/.git/objects/70/c3238c627e9fc1187b9828d5583a470e9ad056 differ
diff --git a/.git/objects/72/00e3a6391ba70ec0e19bf5e6a7effdbcdd0cf6 b/.git/objects/72/00e3a6391ba70ec0e19bf5e6a7effdbcdd0cf6
deleted file mode 100644
Binary files a/.git/objects/72/00e3a6391ba70ec0e19bf5e6a7effdbcdd0cf6 and /dev/null differ
diff --git a/.git/objects/72/420aa90b49de8264d659eee043ad94c94f08f0 b/.git/objects/72/420aa90b49de8264d659eee043ad94c94f08f0
deleted file mode 100644
Binary files a/.git/objects/72/420aa90b49de8264d659eee043ad94c94f08f0 and /dev/null differ
diff --git a/.git/objects/72/44f2a719afed28d42fdd235e91ba80a76bf8c8 b/.git/objects/72/44f2a719afed28d42fdd235e91ba80a76bf8c8
deleted file mode 100644
--- a/.git/objects/72/44f2a719afed28d42fdd235e91ba80a76bf8c8
+++ /dev/null
@@ -1,2 +0,0 @@
-xu=Â@­ó+lÜm®Ä;aS\6;aw	ÿÝhÈ]"±yæTs
-õl¿bÑw¬¢ã	ÄÏAcM©FeOLæâ¼¶â¦ÄScØ4Å¸Ø6Î+ðUy´%&°h3xMeX9ÊVHErWåÄoi¨>ÕîÙxËZî¬åkGøBÖ4v9[.`Ï9f2¤×±.Ùúi\ýüDK¸^Ðb°m·ý}ÕùOä½ü4zÿö0îÓrËawð¹J´'6.îY!
diff --git a/.git/objects/73/bc3b4c2d2ca70c8a8844a118e3d3db3aeb4d0c b/.git/objects/73/bc3b4c2d2ca70c8a8844a118e3d3db3aeb4d0c
deleted file mode 100644
--- a/.git/objects/73/bc3b4c2d2ca70c8a8844a118e3d3db3aeb4d0c
+++ /dev/null
@@ -1,1 +0,0 @@
-xMNÃ0Yû³	ÊØñO\q®à'M¤Æn··ÇjaÏjÞÓ÷>i(/Ë\¡Ãþ®fõÒhå$¢¡ÑX´|ÇC«QuÎ:P85Qu}g|Ï,5£ÖF*K#©8jÈE8Õ)9}x¹óñ=q])xÓÂHm¶Ê9'4®ßUþ§×÷¿ø+MNËÐ\Ê¥0Õ9'qÏÃz[PNg.kCò¦°BÆ¼ßçËv°Öb(qáÏ¹ÿ|Ôâ,nÄ»Þd
diff --git a/.git/objects/76/62906e1fb8860b48907234e40addbfdc4bd604 b/.git/objects/76/62906e1fb8860b48907234e40addbfdc4bd604
deleted file mode 100644
Binary files a/.git/objects/76/62906e1fb8860b48907234e40addbfdc4bd604 and /dev/null differ
diff --git a/.git/objects/79/e1abc7ad5a3aa84e9c723999da1a2977b07839 b/.git/objects/79/e1abc7ad5a3aa84e9c723999da1a2977b07839
deleted file mode 100644
Binary files a/.git/objects/79/e1abc7ad5a3aa84e9c723999da1a2977b07839 and /dev/null differ
diff --git a/.git/objects/7a/7cacc4ba4fa2ca82e2d85abf6b44e7f93625ce b/.git/objects/7a/7cacc4ba4fa2ca82e2d85abf6b44e7f93625ce
deleted file mode 100644
Binary files a/.git/objects/7a/7cacc4ba4fa2ca82e2d85abf6b44e7f93625ce and /dev/null differ
diff --git a/.git/objects/7b/f4417449debcc857e7444b200faf64d6cb58a2 b/.git/objects/7b/f4417449debcc857e7444b200faf64d6cb58a2
deleted file mode 100644
Binary files a/.git/objects/7b/f4417449debcc857e7444b200faf64d6cb58a2 and /dev/null differ
diff --git a/.git/objects/80/1751ee70ac4794f625f38c9417be1408ff90df b/.git/objects/80/1751ee70ac4794f625f38c9417be1408ff90df
deleted file mode 100644
Binary files a/.git/objects/80/1751ee70ac4794f625f38c9417be1408ff90df and /dev/null differ
diff --git a/.git/objects/80/c8d821ef0e1310670d9383a0164a161ef6d896 b/.git/objects/80/c8d821ef0e1310670d9383a0164a161ef6d896
new file mode 100644
Binary files /dev/null and b/.git/objects/80/c8d821ef0e1310670d9383a0164a161ef6d896 differ
diff --git a/.git/objects/81/64db06d50157acee8946c245af5c82e93298f7 b/.git/objects/81/64db06d50157acee8946c245af5c82e93298f7
new file mode 100644
Binary files /dev/null and b/.git/objects/81/64db06d50157acee8946c245af5c82e93298f7 differ
diff --git a/.git/objects/85/af43da1948ffbdf3b1fff153d88119842852b9 b/.git/objects/85/af43da1948ffbdf3b1fff153d88119842852b9
deleted file mode 100644
Binary files a/.git/objects/85/af43da1948ffbdf3b1fff153d88119842852b9 and /dev/null differ
diff --git a/.git/objects/87/7cdbe88a44c2962bc9bc66e021ad8a9c185268 b/.git/objects/87/7cdbe88a44c2962bc9bc66e021ad8a9c185268
deleted file mode 100644
--- a/.git/objects/87/7cdbe88a44c2962bc9bc66e021ad8a9c185268
+++ /dev/null
@@ -1,4 +0,0 @@
-xM
-Â0F]çs%3iD¼+×ÓÌ´ÕoïÏÜ}Þ/OÃÐW :«B
-|b£K¹a*1Pé¬´JEG(Ï:VpØ±[¢ãÔúSüèJÑ«¶¹iÑð½¦öÓøb8Üû|µ|áqÝZo/ºú`ã	R°°´ÞZ«þW
-<ç¾êævúI
diff --git a/.git/objects/88/37a8a5670a0e0375d119c9d20d4353b5913a03 b/.git/objects/88/37a8a5670a0e0375d119c9d20d4353b5913a03
deleted file mode 100644
Binary files a/.git/objects/88/37a8a5670a0e0375d119c9d20d4353b5913a03 and /dev/null differ
diff --git a/.git/objects/88/3ee63aca3703b5c269e0fa4bf0880ade5a9984 b/.git/objects/88/3ee63aca3703b5c269e0fa4bf0880ade5a9984
deleted file mode 100644
Binary files a/.git/objects/88/3ee63aca3703b5c269e0fa4bf0880ade5a9984 and /dev/null differ
diff --git a/.git/objects/89/367b0736b710c6e9c383ef2e019fb07f6cf51c b/.git/objects/89/367b0736b710c6e9c383ef2e019fb07f6cf51c
deleted file mode 100644
Binary files a/.git/objects/89/367b0736b710c6e9c383ef2e019fb07f6cf51c and /dev/null differ
diff --git a/.git/objects/8c/a262164429aa9765dfd2fa47331f3349869329 b/.git/objects/8c/a262164429aa9765dfd2fa47331f3349869329
deleted file mode 100644
Binary files a/.git/objects/8c/a262164429aa9765dfd2fa47331f3349869329 and /dev/null differ
diff --git a/.git/objects/8f/926490ec9977aaa657c03492a2092cd96ed879 b/.git/objects/8f/926490ec9977aaa657c03492a2092cd96ed879
new file mode 100644
Binary files /dev/null and b/.git/objects/8f/926490ec9977aaa657c03492a2092cd96ed879 differ
diff --git a/.git/objects/90/f10f0ae98fa550ed4f3ba96b2726b2fa0f5948 b/.git/objects/90/f10f0ae98fa550ed4f3ba96b2726b2fa0f5948
new file mode 100644
Binary files /dev/null and b/.git/objects/90/f10f0ae98fa550ed4f3ba96b2726b2fa0f5948 differ
diff --git a/.git/objects/95/4c9cf3acd7bc7d436c9548c6d50a7936b3055c b/.git/objects/95/4c9cf3acd7bc7d436c9548c6d50a7936b3055c
deleted file mode 100644
Binary files a/.git/objects/95/4c9cf3acd7bc7d436c9548c6d50a7936b3055c and /dev/null differ
diff --git a/.git/objects/95/530bd9f8b33aa4403e449541aca8782fcf58d7 b/.git/objects/95/530bd9f8b33aa4403e449541aca8782fcf58d7
new file mode 100644
Binary files /dev/null and b/.git/objects/95/530bd9f8b33aa4403e449541aca8782fcf58d7 differ
diff --git a/.git/objects/96/325c6d0739c4a2f762fb0d8e9f6de13202272d b/.git/objects/96/325c6d0739c4a2f762fb0d8e9f6de13202272d
deleted file mode 100644
Binary files a/.git/objects/96/325c6d0739c4a2f762fb0d8e9f6de13202272d and /dev/null differ
diff --git a/.git/objects/97/d0dbaf178d03770a923bdd241b477208b116bf b/.git/objects/97/d0dbaf178d03770a923bdd241b477208b116bf
new file mode 100644
Binary files /dev/null and b/.git/objects/97/d0dbaf178d03770a923bdd241b477208b116bf differ
diff --git a/.git/objects/98/70f262ba46f8c63923b4c9d373b5502d534bff b/.git/objects/98/70f262ba46f8c63923b4c9d373b5502d534bff
new file mode 100644
Binary files /dev/null and b/.git/objects/98/70f262ba46f8c63923b4c9d373b5502d534bff differ
diff --git a/.git/objects/9b/c107a80e863822b328bf64a795c3ef54e001b1 b/.git/objects/9b/c107a80e863822b328bf64a795c3ef54e001b1
deleted file mode 100644
--- a/.git/objects/9b/c107a80e863822b328bf64a795c3ef54e001b1
+++ /dev/null
@@ -1,1 +0,0 @@
-xË!@=Shf` 1Æì`èa?®¬Ýk¶Oï]^òÊ<n=¤C_U­2{,[¡V9QB K<hõì¸bYuê6ñÑC$òY$sµUß"å3úldë÷yµu>bÏ;ÞÏë¤ýUdÑÓO.(@ÈÚ£Î²ßuý·37Qí¶TéZÍCDÅ
diff --git a/.git/objects/9d/73156b57d5c16c87c54244219f4be0df7a4d9c b/.git/objects/9d/73156b57d5c16c87c54244219f4be0df7a4d9c
new file mode 100644
Binary files /dev/null and b/.git/objects/9d/73156b57d5c16c87c54244219f4be0df7a4d9c differ
diff --git a/.git/objects/9d/78fa8fa693d03da04df9e4e1644ed7a5b5d237 b/.git/objects/9d/78fa8fa693d03da04df9e4e1644ed7a5b5d237
deleted file mode 100644
Binary files a/.git/objects/9d/78fa8fa693d03da04df9e4e1644ed7a5b5d237 and /dev/null differ
diff --git a/.git/objects/9e/ad253d2b2018bf4a7fb68a0470bb225793668e b/.git/objects/9e/ad253d2b2018bf4a7fb68a0470bb225793668e
new file mode 100644
Binary files /dev/null and b/.git/objects/9e/ad253d2b2018bf4a7fb68a0470bb225793668e differ
diff --git a/.git/objects/a1/b5f177c89e03bb1f90afbc3ee699d9c9b063de b/.git/objects/a1/b5f177c89e03bb1f90afbc3ee699d9c9b063de
deleted file mode 100644
Binary files a/.git/objects/a1/b5f177c89e03bb1f90afbc3ee699d9c9b063de and /dev/null differ
diff --git a/.git/objects/a1/bd5bad273b384e804013a76ba56070c418244b b/.git/objects/a1/bd5bad273b384e804013a76ba56070c418244b
deleted file mode 100644
Binary files a/.git/objects/a1/bd5bad273b384e804013a76ba56070c418244b and /dev/null differ
diff --git a/.git/objects/a2/e4ba96b68cfb636a59754dc68261df30cc6530 b/.git/objects/a2/e4ba96b68cfb636a59754dc68261df30cc6530
deleted file mode 100644
Binary files a/.git/objects/a2/e4ba96b68cfb636a59754dc68261df30cc6530 and /dev/null differ
diff --git a/.git/objects/a2/f609f631d66e93917a5ace7ad8e9d3e1ff7dcd b/.git/objects/a2/f609f631d66e93917a5ace7ad8e9d3e1ff7dcd
deleted file mode 100644
Binary files a/.git/objects/a2/f609f631d66e93917a5ace7ad8e9d3e1ff7dcd and /dev/null differ
diff --git a/.git/objects/a6/92c6ff1f43e7f0e6048501efab53476b451697 b/.git/objects/a6/92c6ff1f43e7f0e6048501efab53476b451697
deleted file mode 100644
Binary files a/.git/objects/a6/92c6ff1f43e7f0e6048501efab53476b451697 and /dev/null differ
diff --git a/.git/objects/a9/232c0b57605a3ad8a06faad4de4c75fde6ba1a b/.git/objects/a9/232c0b57605a3ad8a06faad4de4c75fde6ba1a
new file mode 100644
Binary files /dev/null and b/.git/objects/a9/232c0b57605a3ad8a06faad4de4c75fde6ba1a differ
diff --git a/.git/objects/a9/2acc695c112526737719cae217919dd26cc8b0 b/.git/objects/a9/2acc695c112526737719cae217919dd26cc8b0
deleted file mode 100644
Binary files a/.git/objects/a9/2acc695c112526737719cae217919dd26cc8b0 and /dev/null differ
diff --git a/.git/objects/a9/e9e0080f3f5357b79e1034457f57c4c50a61c1 b/.git/objects/a9/e9e0080f3f5357b79e1034457f57c4c50a61c1
deleted file mode 100644
Binary files a/.git/objects/a9/e9e0080f3f5357b79e1034457f57c4c50a61c1 and /dev/null differ
diff --git a/.git/objects/aa/6d02eafa38dd2e10940244f0951551753f3060 b/.git/objects/aa/6d02eafa38dd2e10940244f0951551753f3060
new file mode 100644
Binary files /dev/null and b/.git/objects/aa/6d02eafa38dd2e10940244f0951551753f3060 differ
diff --git a/.git/objects/aa/72de41851f42d3f1023c01ae0edc5832c47ebd b/.git/objects/aa/72de41851f42d3f1023c01ae0edc5832c47ebd
new file mode 100644
Binary files /dev/null and b/.git/objects/aa/72de41851f42d3f1023c01ae0edc5832c47ebd differ
diff --git a/.git/objects/ab/dbdc6ad3b69bcd244b80ee836215e015658a56 b/.git/objects/ab/dbdc6ad3b69bcd244b80ee836215e015658a56
new file mode 100644
Binary files /dev/null and b/.git/objects/ab/dbdc6ad3b69bcd244b80ee836215e015658a56 differ
diff --git a/.git/objects/ad/3a905fb36fe44c5f0f7d1bf0e6fab3d36b4d61 b/.git/objects/ad/3a905fb36fe44c5f0f7d1bf0e6fab3d36b4d61
deleted file mode 100644
Binary files a/.git/objects/ad/3a905fb36fe44c5f0f7d1bf0e6fab3d36b4d61 and /dev/null differ
diff --git a/.git/objects/ad/790ff8bd9f52c7ddfb2b28093a8ff21940e3b6 b/.git/objects/ad/790ff8bd9f52c7ddfb2b28093a8ff21940e3b6
deleted file mode 100644
Binary files a/.git/objects/ad/790ff8bd9f52c7ddfb2b28093a8ff21940e3b6 and /dev/null differ
diff --git a/.git/objects/ad/934e32017310e7df1888d183754ae30fa6c67e b/.git/objects/ad/934e32017310e7df1888d183754ae30fa6c67e
deleted file mode 100644
Binary files a/.git/objects/ad/934e32017310e7df1888d183754ae30fa6c67e and /dev/null differ
diff --git a/.git/objects/af/a69c96947b53fb4d8c3f13d2597f42f166b954 b/.git/objects/af/a69c96947b53fb4d8c3f13d2597f42f166b954
new file mode 100644
Binary files /dev/null and b/.git/objects/af/a69c96947b53fb4d8c3f13d2597f42f166b954 differ
diff --git a/.git/objects/b0/9012e440f3043b48b074cdbcc2b592972bdf3f b/.git/objects/b0/9012e440f3043b48b074cdbcc2b592972bdf3f
deleted file mode 100644
Binary files a/.git/objects/b0/9012e440f3043b48b074cdbcc2b592972bdf3f and /dev/null differ
diff --git a/.git/objects/b1/030551f45c9a9ab195759fb1b77e5b346421fb b/.git/objects/b1/030551f45c9a9ab195759fb1b77e5b346421fb
deleted file mode 100644
Binary files a/.git/objects/b1/030551f45c9a9ab195759fb1b77e5b346421fb and /dev/null differ
diff --git a/.git/objects/b1/127851608df2ad2af6966e3558157bf768a183 b/.git/objects/b1/127851608df2ad2af6966e3558157bf768a183
new file mode 100644
Binary files /dev/null and b/.git/objects/b1/127851608df2ad2af6966e3558157bf768a183 differ
diff --git a/.git/objects/b1/3d346f7417c0e401862c9a2473787ff583afd1 b/.git/objects/b1/3d346f7417c0e401862c9a2473787ff583afd1
new file mode 100644
Binary files /dev/null and b/.git/objects/b1/3d346f7417c0e401862c9a2473787ff583afd1 differ
diff --git a/.git/objects/b2/4b2515b2d6b41f2101bf7c8ea8e825495d0168 b/.git/objects/b2/4b2515b2d6b41f2101bf7c8ea8e825495d0168
deleted file mode 100644
Binary files a/.git/objects/b2/4b2515b2d6b41f2101bf7c8ea8e825495d0168 and /dev/null differ
diff --git a/.git/objects/b3/dac8fd881bc1fd8dfe20ab121cfa7344ace238 b/.git/objects/b3/dac8fd881bc1fd8dfe20ab121cfa7344ace238
new file mode 100644
Binary files /dev/null and b/.git/objects/b3/dac8fd881bc1fd8dfe20ab121cfa7344ace238 differ
diff --git a/.git/objects/b6/af0dcb1cc69563bda463208ca520057e2e11b3 b/.git/objects/b6/af0dcb1cc69563bda463208ca520057e2e11b3
new file mode 100644
Binary files /dev/null and b/.git/objects/b6/af0dcb1cc69563bda463208ca520057e2e11b3 differ
diff --git a/.git/objects/b7/d28caad2a4b8583bee99a026cabed13ed818d6 b/.git/objects/b7/d28caad2a4b8583bee99a026cabed13ed818d6
new file mode 100644
Binary files /dev/null and b/.git/objects/b7/d28caad2a4b8583bee99a026cabed13ed818d6 differ
diff --git a/.git/objects/b8/4d39c532ad044ad8b60cee3bc5292061de39a6 b/.git/objects/b8/4d39c532ad044ad8b60cee3bc5292061de39a6
deleted file mode 100644
Binary files a/.git/objects/b8/4d39c532ad044ad8b60cee3bc5292061de39a6 and /dev/null differ
diff --git a/.git/objects/b8/724b568863051d8deac9e814dc00174f5281a9 b/.git/objects/b8/724b568863051d8deac9e814dc00174f5281a9
new file mode 100644
Binary files /dev/null and b/.git/objects/b8/724b568863051d8deac9e814dc00174f5281a9 differ
diff --git a/.git/objects/b9/499a0096c52a092b1f7dd5d9ebabfcaeff6f96 b/.git/objects/b9/499a0096c52a092b1f7dd5d9ebabfcaeff6f96
deleted file mode 100644
Binary files a/.git/objects/b9/499a0096c52a092b1f7dd5d9ebabfcaeff6f96 and /dev/null differ
diff --git a/.git/objects/bc/3466a48bc1ea669750415e2741d93b7f244611 b/.git/objects/bc/3466a48bc1ea669750415e2741d93b7f244611
deleted file mode 100644
Binary files a/.git/objects/bc/3466a48bc1ea669750415e2741d93b7f244611 and /dev/null differ
diff --git a/.git/objects/bc/7e70f191403e2d3c97a09b11bcf2476f038a60 b/.git/objects/bc/7e70f191403e2d3c97a09b11bcf2476f038a60
new file mode 100644
Binary files /dev/null and b/.git/objects/bc/7e70f191403e2d3c97a09b11bcf2476f038a60 differ
diff --git a/.git/objects/be/dc2220c923720d40fbf6b318d4b16245c73a55 b/.git/objects/be/dc2220c923720d40fbf6b318d4b16245c73a55
deleted file mode 100644
--- a/.git/objects/be/dc2220c923720d40fbf6b318d4b16245c73a55
+++ /dev/null
@@ -1,3 +0,0 @@
-xK
-1]ç¹ÒI:¸ðzîØ£LFÇ(x{?Gp÷ª àif½6«ÚA]ôÀ}î%<Jr!1YrìÌg­Íf)îã	º@ÞKð$}r,Aû
-àÄ~´ó4ÛÝT_l÷¡\ìúøçm[µÝ_uõë0ºäíÀßÇ¦ÿÕæ Ç¡ÌX>Fê
diff --git a/.git/objects/be/ff554d699578a58c434cccfd0b09b8be1b872d b/.git/objects/be/ff554d699578a58c434cccfd0b09b8be1b872d
new file mode 100644
Binary files /dev/null and b/.git/objects/be/ff554d699578a58c434cccfd0b09b8be1b872d differ
diff --git a/.git/objects/c1/1295cd418389633d038186b951bd6617e7f6e4 b/.git/objects/c1/1295cd418389633d038186b951bd6617e7f6e4
deleted file mode 100644
Binary files a/.git/objects/c1/1295cd418389633d038186b951bd6617e7f6e4 and /dev/null differ
diff --git a/.git/objects/c1/7ffce0743beb137344a74f6ae5fb5046c955b1 b/.git/objects/c1/7ffce0743beb137344a74f6ae5fb5046c955b1
deleted file mode 100644
Binary files a/.git/objects/c1/7ffce0743beb137344a74f6ae5fb5046c955b1 and /dev/null differ
diff --git a/.git/objects/c1/ba0d1945a06d1610f61128dbe0355002d90c2f b/.git/objects/c1/ba0d1945a06d1610f61128dbe0355002d90c2f
deleted file mode 100644
Binary files a/.git/objects/c1/ba0d1945a06d1610f61128dbe0355002d90c2f and /dev/null differ
diff --git a/.git/objects/c4/3ce9302dcd23cedd4cf553e09c685e528e587d b/.git/objects/c4/3ce9302dcd23cedd4cf553e09c685e528e587d
new file mode 100644
Binary files /dev/null and b/.git/objects/c4/3ce9302dcd23cedd4cf553e09c685e528e587d differ
diff --git a/.git/objects/c5/fc3c5cebdf7ad00414095d73e7f628cd20d4b4 b/.git/objects/c5/fc3c5cebdf7ad00414095d73e7f628cd20d4b4
new file mode 100644
Binary files /dev/null and b/.git/objects/c5/fc3c5cebdf7ad00414095d73e7f628cd20d4b4 differ
diff --git a/.git/objects/c7/3c5f5403087b409710374014d8d3f3b91489d1 b/.git/objects/c7/3c5f5403087b409710374014d8d3f3b91489d1
deleted file mode 100644
Binary files a/.git/objects/c7/3c5f5403087b409710374014d8d3f3b91489d1 and /dev/null differ
diff --git a/.git/objects/c8/2f114a3376658176753aa69cb1882ff9e34024 b/.git/objects/c8/2f114a3376658176753aa69cb1882ff9e34024
deleted file mode 100644
Binary files a/.git/objects/c8/2f114a3376658176753aa69cb1882ff9e34024 and /dev/null differ
diff --git a/.git/objects/c8/66ed10fcb19f4a2fb6382721b1d617638ba958 b/.git/objects/c8/66ed10fcb19f4a2fb6382721b1d617638ba958
new file mode 100644
Binary files /dev/null and b/.git/objects/c8/66ed10fcb19f4a2fb6382721b1d617638ba958 differ
diff --git a/.git/objects/cc/07b21458a8fc31fe26df3ebb0b95a3fb3dabda b/.git/objects/cc/07b21458a8fc31fe26df3ebb0b95a3fb3dabda
new file mode 100644
Binary files /dev/null and b/.git/objects/cc/07b21458a8fc31fe26df3ebb0b95a3fb3dabda differ
diff --git a/.git/objects/cc/2e92fccfecefca2ba40533b089ace71f5bba65 b/.git/objects/cc/2e92fccfecefca2ba40533b089ace71f5bba65
deleted file mode 100644
Binary files a/.git/objects/cc/2e92fccfecefca2ba40533b089ace71f5bba65 and /dev/null differ
diff --git a/.git/objects/cd/023c5127ad0de2f22259fb58b303ab534b75b4 b/.git/objects/cd/023c5127ad0de2f22259fb58b303ab534b75b4
new file mode 100644
Binary files /dev/null and b/.git/objects/cd/023c5127ad0de2f22259fb58b303ab534b75b4 differ
diff --git a/.git/objects/cd/b16d7a4d7ce1ddb46f600a67259900ad69e165 b/.git/objects/cd/b16d7a4d7ce1ddb46f600a67259900ad69e165
deleted file mode 100644
Binary files a/.git/objects/cd/b16d7a4d7ce1ddb46f600a67259900ad69e165 and /dev/null differ
diff --git a/.git/objects/ce/7bb09495716bdbad1408f0d4969fdc39100142 b/.git/objects/ce/7bb09495716bdbad1408f0d4969fdc39100142
new file mode 100644
Binary files /dev/null and b/.git/objects/ce/7bb09495716bdbad1408f0d4969fdc39100142 differ
diff --git a/.git/objects/cf/2b919bc619dd9c7d058d324954872788d208e9 b/.git/objects/cf/2b919bc619dd9c7d058d324954872788d208e9
deleted file mode 100644
Binary files a/.git/objects/cf/2b919bc619dd9c7d058d324954872788d208e9 and /dev/null differ
diff --git a/.git/objects/cf/aafd13c43ed1207a8a323d7532ac25ce643e36 b/.git/objects/cf/aafd13c43ed1207a8a323d7532ac25ce643e36
deleted file mode 100644
Binary files a/.git/objects/cf/aafd13c43ed1207a8a323d7532ac25ce643e36 and /dev/null differ
diff --git a/.git/objects/cf/df673ee21dc78ee19e2f2c4403ff9c81ffa1f4 b/.git/objects/cf/df673ee21dc78ee19e2f2c4403ff9c81ffa1f4
new file mode 100644
Binary files /dev/null and b/.git/objects/cf/df673ee21dc78ee19e2f2c4403ff9c81ffa1f4 differ
diff --git a/.git/objects/d0/ded1ec1f5916aa8e3df243a7a2e953e49abfb7 b/.git/objects/d0/ded1ec1f5916aa8e3df243a7a2e953e49abfb7
deleted file mode 100644
Binary files a/.git/objects/d0/ded1ec1f5916aa8e3df243a7a2e953e49abfb7 and /dev/null differ
diff --git a/.git/objects/d2/ba530f2b786897d2b6b681d5f438efa154b349 b/.git/objects/d2/ba530f2b786897d2b6b681d5f438efa154b349
deleted file mode 100644
Binary files a/.git/objects/d2/ba530f2b786897d2b6b681d5f438efa154b349 and /dev/null differ
diff --git a/.git/objects/d2/cf53ff238e7f97c925f41e114e7100ed259734 b/.git/objects/d2/cf53ff238e7f97c925f41e114e7100ed259734
new file mode 100644
Binary files /dev/null and b/.git/objects/d2/cf53ff238e7f97c925f41e114e7100ed259734 differ
diff --git a/.git/objects/d3/9da1469f1f05215ea3284392a585730464e8de b/.git/objects/d3/9da1469f1f05215ea3284392a585730464e8de
new file mode 100644
Binary files /dev/null and b/.git/objects/d3/9da1469f1f05215ea3284392a585730464e8de differ
diff --git a/.git/objects/d6/32a8bbb2a5162fba6f031bf3a3a8c58167c034 b/.git/objects/d6/32a8bbb2a5162fba6f031bf3a3a8c58167c034
deleted file mode 100644
Binary files a/.git/objects/d6/32a8bbb2a5162fba6f031bf3a3a8c58167c034 and /dev/null differ
diff --git a/.git/objects/d7/b27434f174e0dbe05f8bef916760dfee482141 b/.git/objects/d7/b27434f174e0dbe05f8bef916760dfee482141
deleted file mode 100644
Binary files a/.git/objects/d7/b27434f174e0dbe05f8bef916760dfee482141 and /dev/null differ
diff --git a/.git/objects/d8/a75f45fc2a9f796ef5af34dd139f243f0e1df6 b/.git/objects/d8/a75f45fc2a9f796ef5af34dd139f243f0e1df6
deleted file mode 100644
Binary files a/.git/objects/d8/a75f45fc2a9f796ef5af34dd139f243f0e1df6 and /dev/null differ
diff --git a/.git/objects/d9/712de374ecf26cff922a1fa3eaf739bfa71471 b/.git/objects/d9/712de374ecf26cff922a1fa3eaf739bfa71471
deleted file mode 100644
Binary files a/.git/objects/d9/712de374ecf26cff922a1fa3eaf739bfa71471 and /dev/null differ
diff --git a/.git/objects/db/b2c0d96968285e950f91cef5c54071d6e1c387 b/.git/objects/db/b2c0d96968285e950f91cef5c54071d6e1c387
new file mode 100644
Binary files /dev/null and b/.git/objects/db/b2c0d96968285e950f91cef5c54071d6e1c387 differ
diff --git a/.git/objects/dc/277dc4fd142e9bdf214b89824f0ecd5c5910ec b/.git/objects/dc/277dc4fd142e9bdf214b89824f0ecd5c5910ec
deleted file mode 100644
Binary files a/.git/objects/dc/277dc4fd142e9bdf214b89824f0ecd5c5910ec and /dev/null differ
diff --git a/.git/objects/de/0e0984670170b610524acf8c55af1102969233 b/.git/objects/de/0e0984670170b610524acf8c55af1102969233
deleted file mode 100644
Binary files a/.git/objects/de/0e0984670170b610524acf8c55af1102969233 and /dev/null differ
diff --git a/.git/objects/de/184f0f48f080cd952b4906bd6d10ce95d657aa b/.git/objects/de/184f0f48f080cd952b4906bd6d10ce95d657aa
deleted file mode 100644
Binary files a/.git/objects/de/184f0f48f080cd952b4906bd6d10ce95d657aa and /dev/null differ
diff --git a/.git/objects/de/1cc98e65c7c80ceea57473bdadce3f65ea49a7 b/.git/objects/de/1cc98e65c7c80ceea57473bdadce3f65ea49a7
deleted file mode 100644
Binary files a/.git/objects/de/1cc98e65c7c80ceea57473bdadce3f65ea49a7 and /dev/null differ
diff --git a/.git/objects/df/b22ee42cf26aa1d33211add3c6fdc1a8d117be b/.git/objects/df/b22ee42cf26aa1d33211add3c6fdc1a8d117be
new file mode 100644
Binary files /dev/null and b/.git/objects/df/b22ee42cf26aa1d33211add3c6fdc1a8d117be differ
diff --git a/.git/objects/e0/947bc61ee49f66c63fe1c930c899cbd6b1a368 b/.git/objects/e0/947bc61ee49f66c63fe1c930c899cbd6b1a368
deleted file mode 100644
Binary files a/.git/objects/e0/947bc61ee49f66c63fe1c930c899cbd6b1a368 and /dev/null differ
diff --git a/.git/objects/e1/a32ab024ca47185d08c172e66b5ae83b6d8ea5 b/.git/objects/e1/a32ab024ca47185d08c172e66b5ae83b6d8ea5
deleted file mode 100644
Binary files a/.git/objects/e1/a32ab024ca47185d08c172e66b5ae83b6d8ea5 and /dev/null differ
diff --git a/.git/objects/e2/bdf760d4a28556c3c8bdcec92c5cb51c376e8a b/.git/objects/e2/bdf760d4a28556c3c8bdcec92c5cb51c376e8a
new file mode 100644
Binary files /dev/null and b/.git/objects/e2/bdf760d4a28556c3c8bdcec92c5cb51c376e8a differ
diff --git a/.git/objects/e4/61c0ab2477605902ab7a9c42969603f38bd586 b/.git/objects/e4/61c0ab2477605902ab7a9c42969603f38bd586
new file mode 100644
--- /dev/null
+++ b/.git/objects/e4/61c0ab2477605902ab7a9c42969603f38bd586
@@ -0,0 +1,2 @@
+xÎM
+Â0a×9Å\@Ió;½GdF,Ò¤ÖTðöVàîû¼¹NÓØÀXÜµERd¹mé{Ò&dJÂÆ9¨)¼ÙR2è"mBp>hí­Ö¡>nþªhm·ºÀPËà²ùGþ×ã\¤=3ÍrØÆ	:§­½vZ«üklòVCÍë´µRkufjÂêDM\
diff --git a/.git/objects/e5/c124001e0bd84a9c3f6f42ee520c39fcba32cc b/.git/objects/e5/c124001e0bd84a9c3f6f42ee520c39fcba32cc
new file mode 100644
Binary files /dev/null and b/.git/objects/e5/c124001e0bd84a9c3f6f42ee520c39fcba32cc differ
diff --git a/.git/objects/e6/e7d977a11bc0f0fd2d821ba0faff4eab5e22bd b/.git/objects/e6/e7d977a11bc0f0fd2d821ba0faff4eab5e22bd
deleted file mode 100644
Binary files a/.git/objects/e6/e7d977a11bc0f0fd2d821ba0faff4eab5e22bd and /dev/null differ
diff --git a/.git/objects/e7/a64b8b7d8600b944a2d7a5ffff8f590b4199b7 b/.git/objects/e7/a64b8b7d8600b944a2d7a5ffff8f590b4199b7
deleted file mode 100644
Binary files a/.git/objects/e7/a64b8b7d8600b944a2d7a5ffff8f590b4199b7 and /dev/null differ
diff --git a/.git/objects/ea/e7723c93fc4fd784831416d1f087bed2707fba b/.git/objects/ea/e7723c93fc4fd784831416d1f087bed2707fba
deleted file mode 100644
Binary files a/.git/objects/ea/e7723c93fc4fd784831416d1f087bed2707fba and /dev/null differ
diff --git a/.git/objects/eb/02119459572b6b0cf79a2f9b4895b3b9764380 b/.git/objects/eb/02119459572b6b0cf79a2f9b4895b3b9764380
deleted file mode 100644
Binary files a/.git/objects/eb/02119459572b6b0cf79a2f9b4895b3b9764380 and /dev/null differ
diff --git a/.git/objects/eb/2a0d24372b9029567ea502f851b922edc3f462 b/.git/objects/eb/2a0d24372b9029567ea502f851b922edc3f462
new file mode 100644
Binary files /dev/null and b/.git/objects/eb/2a0d24372b9029567ea502f851b922edc3f462 differ
diff --git a/.git/objects/eb/4dfc2eece871c74eeab502a3943f85884afdad b/.git/objects/eb/4dfc2eece871c74eeab502a3943f85884afdad
new file mode 100644
Binary files /dev/null and b/.git/objects/eb/4dfc2eece871c74eeab502a3943f85884afdad differ
diff --git a/.git/objects/ed/8ca5964cb76d44755cdcb3ed22fd070676ebc7 b/.git/objects/ed/8ca5964cb76d44755cdcb3ed22fd070676ebc7
new file mode 100644
Binary files /dev/null and b/.git/objects/ed/8ca5964cb76d44755cdcb3ed22fd070676ebc7 differ
diff --git a/.git/objects/ed/fb8f1378c1c0021ed0a0f847618b4b310c14f1 b/.git/objects/ed/fb8f1378c1c0021ed0a0f847618b4b310c14f1
deleted file mode 100644
--- a/.git/objects/ed/fb8f1378c1c0021ed0a0f847618b4b310c14f1
+++ /dev/null
@@ -1,3 +0,0 @@
-x½RÑjÂ0Ýs¿âB_,8Q	JÙÜX7ÛØcö¶bSîß¦ÆMÙÛ^JrÎÍ=çÛ9ãsïn®BØ_ûD¯ÓhzqöáeÍM «÷]1#R¢ìÃÃ-3|ª¤"ÕÂb^)Ü*	þõç°âù!4°àl	Á7í7Í6EtUs¡N.ÀY(Ê+éù´,&ÑÛtö=FoÏ÷IeNàv4üÝ &
-K.v
-dëaIsZÐë>Ð<ð|¬rZ4Þ*Ü(=;ç)¨aX`R	ZÃx¬¹ÑcÿmìXKúí$ìn½N-8Æhg.Íµ9°.JØcÑÕô¸LÄVÑtnåÚã-"¸­Ì=0R}W`KiIÄ&èÖu2) CJé4DénùÔfÂyíDd®v\ý¸+aM©åN¢0Ì¹ðc*kªØ>?4rddÔàÙl¼ätnï¸ÐaqaÑöO=çm¨÷uY
diff --git a/.git/objects/ef/337b7200de9c55fdc48320e19a26e19564d79b b/.git/objects/ef/337b7200de9c55fdc48320e19a26e19564d79b
deleted file mode 100644
Binary files a/.git/objects/ef/337b7200de9c55fdc48320e19a26e19564d79b and /dev/null differ
diff --git a/.git/objects/f2/2b65e167b5ea54b84305158d31368b9c10f0a7 b/.git/objects/f2/2b65e167b5ea54b84305158d31368b9c10f0a7
new file mode 100644
Binary files /dev/null and b/.git/objects/f2/2b65e167b5ea54b84305158d31368b9c10f0a7 differ
diff --git a/.git/objects/f2/9871f63fcf1a8c2cc7ea8d7e2d3505f641c08e b/.git/objects/f2/9871f63fcf1a8c2cc7ea8d7e2d3505f641c08e
deleted file mode 100644
Binary files a/.git/objects/f2/9871f63fcf1a8c2cc7ea8d7e2d3505f641c08e and /dev/null differ
diff --git a/.git/objects/f2/bba23a1c3bbf6ff9964d90731485399a69b8a9 b/.git/objects/f2/bba23a1c3bbf6ff9964d90731485399a69b8a9
new file mode 100644
Binary files /dev/null and b/.git/objects/f2/bba23a1c3bbf6ff9964d90731485399a69b8a9 differ
diff --git a/.git/objects/f4/077bc12e204876fb485cac9bb75ac11a651c0c b/.git/objects/f4/077bc12e204876fb485cac9bb75ac11a651c0c
deleted file mode 100644
Binary files a/.git/objects/f4/077bc12e204876fb485cac9bb75ac11a651c0c and /dev/null differ
diff --git a/.git/objects/f5/602af44f15d195f373445ff4ea9525fe659cdc b/.git/objects/f5/602af44f15d195f373445ff4ea9525fe659cdc
new file mode 100644
Binary files /dev/null and b/.git/objects/f5/602af44f15d195f373445ff4ea9525fe659cdc differ
diff --git a/.git/objects/f8/154e00ed87f700e71790ab9966fc8414807b8a b/.git/objects/f8/154e00ed87f700e71790ab9966fc8414807b8a
deleted file mode 100644
--- a/.git/objects/f8/154e00ed87f700e71790ab9966fc8414807b8a
+++ /dev/null
@@ -1,2 +0,0 @@
-xA
-1E]÷¹L©·#ÖN«c¼½2ÀÕ÷~îÓT(ÒÊfU¤I·X|aÏñú89dF)§]úçÞÞ»e^÷CS{d¹éæ{ À8¤q 52¢ËËé¿;¶jU®ð¸Ä17«
diff --git a/.git/objects/fd/70ab6de3c28ef42e6450fabade4e4bbdd5869e b/.git/objects/fd/70ab6de3c28ef42e6450fabade4e4bbdd5869e
new file mode 100644
Binary files /dev/null and b/.git/objects/fd/70ab6de3c28ef42e6450fabade4e4bbdd5869e differ
diff --git a/.git/objects/fd/7be762cd1a7bbca6b0eeec10ab260858db340d b/.git/objects/fd/7be762cd1a7bbca6b0eeec10ab260858db340d
new file mode 100644
Binary files /dev/null and b/.git/objects/fd/7be762cd1a7bbca6b0eeec10ab260858db340d differ
diff --git a/.git/objects/fe/09b1a7385815667ec69a1b68be676d0eb7cf46 b/.git/objects/fe/09b1a7385815667ec69a1b68be676d0eb7cf46
deleted file mode 100644
Binary files a/.git/objects/fe/09b1a7385815667ec69a1b68be676d0eb7cf46 and /dev/null differ
diff --git a/.git/objects/fe/3a486f7a94b12d196d8e17a1fdb728e26dbff3 b/.git/objects/fe/3a486f7a94b12d196d8e17a1fdb728e26dbff3
new file mode 100644
Binary files /dev/null and b/.git/objects/fe/3a486f7a94b12d196d8e17a1fdb728e26dbff3 differ
diff --git a/.git/objects/fe/977d416f9d343f9e97002d5664550eeed16ee0 b/.git/objects/fe/977d416f9d343f9e97002d5664550eeed16ee0
deleted file mode 100644
Binary files a/.git/objects/fe/977d416f9d343f9e97002d5664550eeed16ee0 and /dev/null differ
diff --git a/.git/objects/pack/pack-070189755adac644d6a1c3fd2d044e268ceae11e.idx b/.git/objects/pack/pack-070189755adac644d6a1c3fd2d044e268ceae11e.idx
new file mode 100644
Binary files /dev/null and b/.git/objects/pack/pack-070189755adac644d6a1c3fd2d044e268ceae11e.idx differ
diff --git a/.git/objects/pack/pack-070189755adac644d6a1c3fd2d044e268ceae11e.pack b/.git/objects/pack/pack-070189755adac644d6a1c3fd2d044e268ceae11e.pack
new file mode 100644
Binary files /dev/null and b/.git/objects/pack/pack-070189755adac644d6a1c3fd2d044e268ceae11e.pack differ
diff --git a/.git/packed-refs b/.git/packed-refs
--- a/.git/packed-refs
+++ b/.git/packed-refs
@@ -1,2 +1,2 @@
 # pack-refs with: peeled fully-peeled 
-9bc107a80e863822b328bf64a795c3ef54e001b1 refs/remotes/origin/master
+61d09a71180e5a1a4ea1d893f82a4709d8e79c27 refs/remotes/origin/master
diff --git a/.git/refs/heads/master b/.git/refs/heads/master
--- a/.git/refs/heads/master
+++ b/.git/refs/heads/master
@@ -1,1 +1,1 @@
-4afd6ed7d81c474bf5c88c395a584e4f68b039ce
+fd7be762cd1a7bbca6b0eeec10ab260858db340d
diff --git a/.git/refs/remotes/origin/master b/.git/refs/remotes/origin/master
--- a/.git/refs/remotes/origin/master
+++ b/.git/refs/remotes/origin/master
@@ -1,1 +1,1 @@
-4afd6ed7d81c474bf5c88c395a584e4f68b039ce
+40d6be12def8fc357df4248d9943bd3cc1f75f89
diff --git a/Control/Arrow/ArrowP.lhs b/Control/Arrow/ArrowP.lhs
--- a/Control/Arrow/ArrowP.lhs
+++ b/Control/Arrow/ArrowP.lhs
@@ -1,38 +1,38 @@
-> {-# LANGUAGE CPP, MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}
-
-> module Control.Arrow.ArrowP where
-
-> import Control.Arrow
-> import Control.Arrow.Operations
-#if __GLASGOW_HASKELL__ >= 610
-> import Control.Category
-> import Prelude hiding ((.), id)
-#endif
-
-> newtype ArrowP a p b c = ArrowP { strip :: a b c }
-
-#if __GLASGOW_HASKELL__ >= 610
-> instance Category a => Category (ArrowP a p) where
->   id = ArrowP id
->   ArrowP g . ArrowP f = ArrowP (g . f)
-
-> instance Arrow a => Arrow (ArrowP a p) where
->   arr f = ArrowP (arr f)
->   first (ArrowP f) = ArrowP (first f)
-#else
-> instance Arrow a => Arrow (ArrowP a p) where
->   arr f = ArrowP (arr f)
->   first (ArrowP f) = ArrowP (first f)
->   ArrowP f >>> ArrowP g = ArrowP (f >>> g)
-#endif
-
-> instance ArrowLoop a => ArrowLoop (ArrowP a p) where
->   loop (ArrowP f) = ArrowP (loop f)
-
-> instance ArrowCircuit a => ArrowCircuit (ArrowP a p) where
->   delay i = ArrowP (delay i)
-
-> instance ArrowChoice a => ArrowChoice (ArrowP a p) where
->   left (ArrowP f) = ArrowP (left f)
->   ArrowP f ||| ArrowP g = ArrowP (f ||| g)
-
+> {-# LANGUAGE CPP, MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}
+
+> module Control.Arrow.ArrowP where
+
+> import Control.Arrow
+> import Control.Arrow.Operations
+#if __GLASGOW_HASKELL__ >= 610
+> import Control.Category
+> import Prelude hiding ((.), id)
+#endif
+
+> newtype ArrowP a p b c = ArrowP { strip :: a b c }
+
+#if __GLASGOW_HASKELL__ >= 610
+> instance Category a => Category (ArrowP a p) where
+>   id = ArrowP id
+>   ArrowP g . ArrowP f = ArrowP (g . f)
+
+> instance Arrow a => Arrow (ArrowP a p) where
+>   arr f = ArrowP (arr f)
+>   first (ArrowP f) = ArrowP (first f)
+#else
+> instance Arrow a => Arrow (ArrowP a p) where
+>   arr f = ArrowP (arr f)
+>   first (ArrowP f) = ArrowP (first f)
+>   ArrowP f >>> ArrowP g = ArrowP (f >>> g)
+#endif
+
+> instance ArrowLoop a => ArrowLoop (ArrowP a p) where
+>   loop (ArrowP f) = ArrowP (loop f)
+
+> instance ArrowCircuit a => ArrowCircuit (ArrowP a p) where
+>   delay i = ArrowP (delay i)
+
+> instance ArrowChoice a => ArrowChoice (ArrowP a p) where
+>   left (ArrowP f) = ArrowP (left f)
+>   ArrowP f ||| ArrowP g = ArrowP (f ||| g)
+
diff --git a/Control/SF/SF.lhs b/Control/SF/SF.lhs
--- a/Control/SF/SF.lhs
+++ b/Control/SF/SF.lhs
@@ -1,113 +1,113 @@
-> {-# LANGUAGE CPP, BangPatterns #-}
-
-> module Control.SF.SF where
-
-#if __GLASGOW_HASKELL__ >= 610
-> import Control.Category
-> import Prelude hiding ((.), id)
-#endif
-
-> import Control.Arrow
-> import Control.Arrow.ArrowP
-> import Control.Arrow.Operations
-
-
-> newtype SF a b = SF { runSF :: (a -> (b, SF a b)) }
-
-#if __GLASGOW_HASKELL__ >= 610
-> instance Category SF where
->   id = SF h where h x = (x, SF h)
->   g . f = SF (h f g)
->     where
->       h f g x =
->         let (y, f') = runSF f x
->             (z, g') = runSF g y
->         in f' `seq` g' `seq` (z, SF (h f' g'))
-
-> instance Arrow SF where
->   arr f = g
->     where g = SF (\x -> (f x, g))
->   first f = SF (g f)
->     where
->       g f (x, z) = f' `seq` ((y, z), SF (g f'))
->         where (y, f') = runSF f x
->   f &&& g = SF (h f g)
->     where
->       h f g x =
->         let (y, f') = runSF f x
->             (z, g') = runSF g x 
->         in ((y, z), SF (h f' g'))
->   f *** g = SF (h f g)
->     where
->       h f g x =
->         let (y, f') = runSF f (fst x)
->             (z, g') = runSF g (snd x) 
->         in ((y, z), SF (h f' g'))
-#else
-> instance Arrow SF where
->   arr f = g
->     where g = SF (\x -> (f x, g))
->   f >>> g = SF (h f g)
->     where
->       h f g x =
->         let (y, f') = runSF f x
->             (z, g') = runSF g y
->         in (z, SF (h f' g'))
->   first f = SF (g f)
->     where
->       g f (x, z) = ((y, z), SF (g f'))
->         where (y, f') = runSF f x
->   f &&& g = SF (h f g)
->     where
->       h f g x =
->         let (y, f') = runSF f x
->             (z, g') = runSF g x 
->         in ((y, z), SF (h f' g'))
->   f *** g = SF (h f g)
->     where
->       h f g x =
->         let (y, f') = runSF f (fst x)
->             (z, g') = runSF g (snd x) 
->         in ((y, z), SF (h f' g'))
-#endif
-
-> instance ArrowLoop SF where
->   loop sf = SF (g sf)
->     where
->       g f x = f' `seq` (y, SF (g f'))
->         where ((y, z), f') = runSF f (x, z)
-
-> instance ArrowChoice SF where
->    left sf = SF (g sf)
->        where 
->          g f x = case x of
->                    Left a -> let (y, f') = runSF f a in f' `seq` (Left y, SF (g f'))
->                    Right b -> (Right b, SF (g f))
-> 
-> instance ArrowCircuit SF where
->   delay i = SF (f i)
->     where f i x = (i, SF (f x))
-
-> run :: SF a b -> [a] -> [b]
-> run _ [] = []
-> run (SF f) (x:xs) =
->   let (y, f') = f x 
->   in y `seq` f' `seq` (y : run f' xs)
-> 
-> unfold :: SF () a -> [a]
-> unfold = flip run inp
->   where inp = () : inp
->
-> 
-> nth :: Int -> SF () a -> a
-> nth n (SF f) = x `seq` if n == 0 then x else nth (n - 1) f'
->   where (x, f') = f ()
-> 
-> nth' :: Int -> (b, ((), b) -> (a, b)) -> a
-> nth' !n (i, f) = n `seq` i `seq` f `seq` aux n i
->   where
->     aux !n !i = x `seq` i' `seq` if n == 0 then x else aux (n-1) i'
->       where (x, i') = f ((), i)
-> 
-
-
+> {-# LANGUAGE CPP, BangPatterns #-}
+
+> module Control.SF.SF where
+
+#if __GLASGOW_HASKELL__ >= 610
+> import Control.Category
+> import Prelude hiding ((.), id)
+#endif
+
+> import Control.Arrow
+> import Control.Arrow.ArrowP
+> import Control.Arrow.Operations
+
+
+> newtype SF a b = SF { runSF :: (a -> (b, SF a b)) }
+
+#if __GLASGOW_HASKELL__ >= 610
+> instance Category SF where
+>   id = SF h where h x = (x, SF h)
+>   g . f = SF (h f g)
+>     where
+>       h f g x =
+>         let (y, f') = runSF f x
+>             (z, g') = runSF g y
+>         in f' `seq` g' `seq` (z, SF (h f' g'))
+
+> instance Arrow SF where
+>   arr f = g
+>     where g = SF (\x -> (f x, g))
+>   first f = SF (g f)
+>     where
+>       g f (x, z) = f' `seq` ((y, z), SF (g f'))
+>         where (y, f') = runSF f x
+>   f &&& g = SF (h f g)
+>     where
+>       h f g x =
+>         let (y, f') = runSF f x
+>             (z, g') = runSF g x 
+>         in ((y, z), SF (h f' g'))
+>   f *** g = SF (h f g)
+>     where
+>       h f g x =
+>         let (y, f') = runSF f (fst x)
+>             (z, g') = runSF g (snd x) 
+>         in ((y, z), SF (h f' g'))
+#else
+> instance Arrow SF where
+>   arr f = g
+>     where g = SF (\x -> (f x, g))
+>   f >>> g = SF (h f g)
+>     where
+>       h f g x =
+>         let (y, f') = runSF f x
+>             (z, g') = runSF g y
+>         in (z, SF (h f' g'))
+>   first f = SF (g f)
+>     where
+>       g f (x, z) = ((y, z), SF (g f'))
+>         where (y, f') = runSF f x
+>   f &&& g = SF (h f g)
+>     where
+>       h f g x =
+>         let (y, f') = runSF f x
+>             (z, g') = runSF g x 
+>         in ((y, z), SF (h f' g'))
+>   f *** g = SF (h f g)
+>     where
+>       h f g x =
+>         let (y, f') = runSF f (fst x)
+>             (z, g') = runSF g (snd x) 
+>         in ((y, z), SF (h f' g'))
+#endif
+
+> instance ArrowLoop SF where
+>   loop sf = SF (g sf)
+>     where
+>       g f x = f' `seq` (y, SF (g f'))
+>         where ((y, z), f') = runSF f (x, z)
+
+> instance ArrowChoice SF where
+>    left sf = SF (g sf)
+>        where 
+>          g f x = case x of
+>                    Left a -> let (y, f') = runSF f a in f' `seq` (Left y, SF (g f'))
+>                    Right b -> (Right b, SF (g f))
+> 
+> instance ArrowCircuit SF where
+>   delay i = SF (f i)
+>     where f i x = (i, SF (f x))
+
+> run :: SF a b -> [a] -> [b]
+> run _ [] = []
+> run (SF f) (x:xs) =
+>   let (y, f') = f x 
+>   in y `seq` f' `seq` (y : run f' xs)
+> 
+> unfold :: SF () a -> [a]
+> unfold = flip run inp
+>   where inp = () : inp
+>
+> 
+> nth :: Int -> SF () a -> a
+> nth n (SF f) = x `seq` if n == 0 then x else nth (n - 1) f'
+>   where (x, f') = f ()
+> 
+> nth' :: Int -> (b, ((), b) -> (a, b)) -> a
+> nth' !n (i, f) = n `seq` i `seq` f `seq` aux n i
+>   where
+>     aux !n !i = x `seq` i' `seq` if n == 0 then x else aux (n-1) i'
+>       where (x, i') = f ((), i)
+> 
+
+
diff --git a/Euterpea.cabal b/Euterpea.cabal
--- a/Euterpea.cabal
+++ b/Euterpea.cabal
@@ -1,5 +1,5 @@
 name:           Euterpea
-version:        2.0.0
+version:        2.0.1
 Cabal-Version:  >= 1.8
 license:        BSD3
 license-file:	License
@@ -25,12 +25,7 @@
         wide-spectrum DSL, suitable for high-level music representation, 
         algorithmic composition, and analysis; mid-level concepts such as 
         MIDI; and low-level audio processing, sound synthesis, and instrument
-        design.  It also includes a "musical user interface," a set of 
-        computer-music specific GUI widgets such as keyboards, pushbuttons, 
-        sliders, and so on.  The performance of Euterpea is intended to be 
-        as good as any other computer music language, with the goal of being 
-        able to develop real-time applications, using both MIDI and a 
-        high-performance back-end for real-time audio.  
+        design.  
 extra-source-files:
         ReadMe.txt,
         Euterpea/Examples/EnableGUI.hs
@@ -70,6 +65,6 @@
         HCodecs == 0.5, 
         stm==2.4.2, 
         containers>=0.5.5.1 && <=0.5.7.1, 
-        bytestring>=0.10.4.0 && <= 0.10.8.0, 
+        bytestring>=0.10.4.0 && <= 0.10.8.0,
         heap == 0.6.0, 
         ghc-prim
diff --git a/Euterpea.lhs b/Euterpea.lhs
--- a/Euterpea.lhs
+++ b/Euterpea.lhs
@@ -1,19 +1,19 @@
-> {-# OPTIONS -XFlexibleInstances #-}
-> {-# OPTIONS -XTypeSynonymInstances #-}
-
-> module Euterpea (
->   module Euterpea.Music,
->   module Euterpea.IO.Audio,
->   module Euterpea.IO.MIDI,
->   module Control.Arrow,
->   -- This next line is from Codec.Midi
->   exportFile, importFile
->   ) where
->
-> import Euterpea.Music
-> import Euterpea.IO.Audio
-> import Euterpea.IO.MIDI
-> import Control.Arrow
-> import Codec.Midi(exportFile, importFile)
-> import Control.Arrow.Operations
-
+> {-# OPTIONS -XFlexibleInstances #-}
+> {-# OPTIONS -XTypeSynonymInstances #-}
+
+> module Euterpea (
+>   module Euterpea.Music,
+>   module Euterpea.IO.Audio,
+>   module Euterpea.IO.MIDI,
+>   module Control.Arrow,
+>   -- This next line is from Codec.Midi
+>   exportFile, importFile
+>   ) where
+>
+> import Euterpea.Music
+> import Euterpea.IO.Audio
+> import Euterpea.IO.MIDI
+> import Control.Arrow
+> import Codec.Midi(exportFile, importFile)
+> import Control.Arrow.Operations
+
diff --git a/Euterpea/IO/Audio/IO.hs b/Euterpea/IO/Audio/IO.hs
--- a/Euterpea/IO/Audio/IO.hs
+++ b/Euterpea/IO/Audio/IO.hs
@@ -1,204 +1,204 @@
-{-# LANGUAGE BangPatterns, ExistentialQuantification, 
-    ScopedTypeVariables, FlexibleContexts #-}
-
-module Euterpea.IO.Audio.IO (
-    outFile,  outFileNorm, 
---    outFileA, outFileNormA, RecordStatus, 
-    maxSample) where
-
-import Control.Arrow.ArrowP
-import Control.SF.SF
-import Euterpea.IO.Audio.Types hiding (Signal)
-
-import Codec.Wav
-import Data.Audio
-import Data.Array.Unboxed
-import Data.Int
-
---import Data.IORef
---import Foreign.C
---import Foreign.Marshal.Array
---import Foreign.Marshal.Utils
---import Foreign.Ptr
---import Foreign.Storable
---import Control.CCA.Types
---import Control.Arrow
---import Control.Concurrent.MonadIO
---import Sound.RtAudio
-
-type Signal clk a b = ArrowP SF clk a b
-
--- | Writes sound to a wave file (.wav)
-outFile :: forall a p. (AudioSample a, Clock p) => 
-           String              -- ^ Filename to write to.
-        -> Double              -- ^ Duration of the wav in seconds.
-        -> Signal p () a       -- ^ Signal representing the sound.
-        -> IO ()
-outFile = outFileHelp' id
-
-normList :: [Double] -> [Double]
-normList xs = map (/ mx) xs 
-    where mx = max 1.0 (maximum (map abs xs))
-
--- | Like outFile, but normalizes the output if the amplitude of 
--- the signal goes above 1.  If the maximum sample is less than
--- or equal to 1, the output is not normalized.
--- Currently this requires storing the entire output stream in memory
--- before writing to the file.
-outFileNorm :: forall a p. (AudioSample a, Clock p) => 
-            String              -- ^ Filename to write to.
-         -> Double              -- ^ Duration of the wav in seconds.
-         -> Signal p () a       -- ^ Signal representing the sound.
-         -> IO ()
-outFileNorm = outFileHelp' normList
-
-outFileHelp :: forall a p. (AudioSample a, Clock p) => 
-            ([Double] -> [Double]) -- ^ Post-processing function.
-         -> String              -- ^ Filename to write to.
-         -> Double              -- ^ Duration of the wav in seconds.
-         -> Signal p () a       -- ^ Signal representing the sound.
-         -> IO ()
-outFileHelp f filepath dur sf = 
-  let sr          = rate (undefined :: p)
-      numChannels = numChans (undefined :: a)
-      numSamples  = truncate (dur * sr) * numChannels
-      dat         = map (fromSample . (*0.999)) 
-                        (f (toSamples dur sf)) :: [Int32]
-                    -- multiply by 0.999 to avoid wraparound at 1.0
-      array       = listArray (0, numSamples-1) dat
-      aud = Audio { sampleRate    = truncate sr,
-                    channelNumber = numChannels,
-                    sampleData    = array }
-  in exportFile filepath aud
-  
-{-
-Alternative definition of the above that enforces a clipping behavior when 
-the value exceeds the [-1.0, 1.0] range. The overflow behavior makes it 
-very hard to debug sound modeling problems that involve certain waveforms, 
-such as saw waves. Clipping is also a more common behavior in other audio 
-software rather than overflowing or wrap-around.
--}
-  
-outFileHelp' :: forall a p. (AudioSample a, Clock p) => 
-            ([Double] -> [Double]) -- ^ Post-processing function.
-         -> String              -- ^ Filename to write to.
-         -> Double              -- ^ Duration of the wav in seconds.
-         -> Signal p () a       -- ^ Signal representing the sound.
-         -> IO ()
-outFileHelp' f filepath dur sf = 
-  let sr          = rate (undefined :: p)
-      numChannels = numChans (undefined :: a)
-      numSamples  = truncate (dur * sr) * numChannels
-      dat         = map (fromSample . (*0.999) . clipFix) 
-                        (f (toSamples dur sf)) :: [Int32]
-      array       = listArray (0, numSamples-1) dat
-      aud = Audio { sampleRate    = truncate sr,
-                    channelNumber = numChannels,
-                    sampleData    = array }
-  in exportFile filepath aud where
-      clipFix x = if x > 1.0 then 1.0 else if x < -1.0 then -1.0 else x
-
-
-{-
-data RecordStatus = Pause | Record | Clear | Write
-
-outFileA :: forall a. AudioSample a => 
-            String               -- ^ Filename to write to.
-         -> Double               -- ^ Sample rate of the incoming signal.
-         -> UISF (a, RecordStatus) ()
-outFileA = outFileHelpA id
-
-outFileNormA :: forall a. AudioSample a => 
-                String               -- ^ Filename to write to.
-             -> Double               -- ^ Sample rate of the incoming signal.
-             -> UISF (a, RecordStatus) ()
-outFileNormA = outFileHelpA normList
-
-outFileHelpA :: forall a. AudioSample a => 
-             ([Double] -> [Double]) -- ^ Post-processing function.
-          -> String                 -- ^ Filename to write to.
-          -> Double                 -- ^ Sample rate of the incoming signal.
-          -> UISF (a, RecordStatus) ()
-outFileHelpA f filepath sr = 
-  let numChannels = numChans (undefined :: a)
-      writeWavSink = sink (writeWav f filepath sr numChannels)
-  in proc (a, rs) -> do
-        rec dat <- delay [] -< dat'
-            dat' <- case rs of
-                        Pause  -> returnA -< dat
-                        Record -> returnA -< a:dat
-                        Clear  -> returnA -< []
-                        Write  -> do writeWavSink -< dat
-                                     returnA -< a:dat
-        returnA -< ()
--}
-{-
-writeWav :: AudioSample a => ([Double] -> [Double]) -> String -> Double -> Int -> [a] -> UI ()
-writeWav f filepath sr numChannels adat = 
-  let dat         = map (fromSample . (*0.999)) 
-                        (f (concatMap collapse adat)) :: [Int32]
-                    -- multiply by 0.999 to avoid wraparound at 1.0
-      array       = listArray (0, (length dat)-1) dat
-      aud = Audio { sampleRate    = truncate sr,
-                    channelNumber = numChannels,
-                    sampleData    = array }
-  in liftIO $ exportFile filepath aud
--}
-
-
-  
-
-toSamples :: forall a p. (AudioSample a, Clock p) =>
-             Double -> Signal p () a -> [Double]
-toSamples dur sf = 
-  let sr          = rate     (undefined :: p)
-      numChannels = numChans (undefined :: a)
-      numSamples  = truncate (dur * sr) * numChannels
-  in take numSamples $ concatMap collapse $ unfold $ strip sf
-
--- | Compute the maximum sample of an SF in the first 'dur' seconds.
-maxSample :: forall a p. (AudioSample a, Clock p) =>
-             Double -> Signal p () a -> Double
-maxSample dur sf = maximum (map abs (toSamples dur sf))
-
-
-{-
-chunk !nFrames !(i, f) ref buf = nFrames `seq` i `seq` f `seq` aux nFrames i 
-    where aux !n !i = x `seq` i `seq` i' `seq`
-                       if n == 0 then do
-                                  writeIORef ref i
-                                  return ()
-                       else do
-                        pokeElemOff buf (fromIntegral nFrames-n) (realToFrac x)
-                        aux (n-1) i'
-              where (x, i') = f ((), i)
-{-# INLINE [0] chunk #-}
-
-chunkify !i !f !secs = do
-  --userData <- new i
-  ref <- newIORef i
-  let cb :: RtAudioCallback 
-      cb oBuf iBuf nFrames nSecs status userData = do
-                      
-                      lastState <- readIORef ref
-                      -- Fill output buffer with nFrames of samples
-                      chunk (fromIntegral nFrames) (lastState,f) ref oBuf
-                      if secs < (realToFrac nSecs) then return 2 else return 0
-                              
-                                                          
-  mkAudioCallback cb                                 
-
-
-
-playPure :: Show b => Double -> (b, ((), b) -> (Double, b)) -> IO ()
-playPure !secs !(i, f) = do
-  rtaCloseStream
-  rtaInitialize
-  dev <- rtaGetDefaultOutputDevice
-  callback <- chunkify i f secs
-  with (StreamParameters dev 1 0) (\params -> do
-         rtaOpenStream params nullPtr float64 44100 4096 callback nullPtr nullPtr)
-  rtaStartStream
-  return ()
-  
--}
+{-# LANGUAGE BangPatterns, ExistentialQuantification, 
+    ScopedTypeVariables, FlexibleContexts #-}
+
+module Euterpea.IO.Audio.IO (
+    outFile,  outFileNorm, 
+--    outFileA, outFileNormA, RecordStatus, 
+    maxSample) where
+
+import Control.Arrow.ArrowP
+import Control.SF.SF
+import Euterpea.IO.Audio.Types hiding (Signal)
+
+import Codec.Wav
+import Data.Audio
+import Data.Array.Unboxed
+import Data.Int
+
+--import Data.IORef
+--import Foreign.C
+--import Foreign.Marshal.Array
+--import Foreign.Marshal.Utils
+--import Foreign.Ptr
+--import Foreign.Storable
+--import Control.CCA.Types
+--import Control.Arrow
+--import Control.Concurrent.MonadIO
+--import Sound.RtAudio
+
+type Signal clk a b = ArrowP SF clk a b
+
+-- | Writes sound to a wave file (.wav)
+outFile :: forall a p. (AudioSample a, Clock p) => 
+           String              -- ^ Filename to write to.
+        -> Double              -- ^ Duration of the wav in seconds.
+        -> Signal p () a       -- ^ Signal representing the sound.
+        -> IO ()
+outFile = outFileHelp' id
+
+normList :: [Double] -> [Double]
+normList xs = map (/ mx) xs 
+    where mx = max 1.0 (maximum (map abs xs))
+
+-- | Like outFile, but normalizes the output if the amplitude of 
+-- the signal goes above 1.  If the maximum sample is less than
+-- or equal to 1, the output is not normalized.
+-- Currently this requires storing the entire output stream in memory
+-- before writing to the file.
+outFileNorm :: forall a p. (AudioSample a, Clock p) => 
+            String              -- ^ Filename to write to.
+         -> Double              -- ^ Duration of the wav in seconds.
+         -> Signal p () a       -- ^ Signal representing the sound.
+         -> IO ()
+outFileNorm = outFileHelp' normList
+
+outFileHelp :: forall a p. (AudioSample a, Clock p) => 
+            ([Double] -> [Double]) -- ^ Post-processing function.
+         -> String              -- ^ Filename to write to.
+         -> Double              -- ^ Duration of the wav in seconds.
+         -> Signal p () a       -- ^ Signal representing the sound.
+         -> IO ()
+outFileHelp f filepath dur sf = 
+  let sr          = rate (undefined :: p)
+      numChannels = numChans (undefined :: a)
+      numSamples  = truncate (dur * sr) * numChannels
+      dat         = map (fromSample . (*0.999)) 
+                        (f (toSamples dur sf)) :: [Int32]
+                    -- multiply by 0.999 to avoid wraparound at 1.0
+      array       = listArray (0, numSamples-1) dat
+      aud = Audio { sampleRate    = truncate sr,
+                    channelNumber = numChannels,
+                    sampleData    = array }
+  in exportFile filepath aud
+  
+{-
+Alternative definition of the above that enforces a clipping behavior when 
+the value exceeds the [-1.0, 1.0] range. The overflow behavior makes it 
+very hard to debug sound modeling problems that involve certain waveforms, 
+such as saw waves. Clipping is also a more common behavior in other audio 
+software rather than overflowing or wrap-around.
+-}
+  
+outFileHelp' :: forall a p. (AudioSample a, Clock p) => 
+            ([Double] -> [Double]) -- ^ Post-processing function.
+         -> String              -- ^ Filename to write to.
+         -> Double              -- ^ Duration of the wav in seconds.
+         -> Signal p () a       -- ^ Signal representing the sound.
+         -> IO ()
+outFileHelp' f filepath dur sf = 
+  let sr          = rate (undefined :: p)
+      numChannels = numChans (undefined :: a)
+      numSamples  = truncate (dur * sr) * numChannels
+      dat         = map (fromSample . (*0.999) . clipFix) 
+                        (f (toSamples dur sf)) :: [Int32]
+      array       = listArray (0, numSamples-1) dat
+      aud = Audio { sampleRate    = truncate sr,
+                    channelNumber = numChannels,
+                    sampleData    = array }
+  in exportFile filepath aud where
+      clipFix x = if x > 1.0 then 1.0 else if x < -1.0 then -1.0 else x
+
+
+{-
+data RecordStatus = Pause | Record | Clear | Write
+
+outFileA :: forall a. AudioSample a => 
+            String               -- ^ Filename to write to.
+         -> Double               -- ^ Sample rate of the incoming signal.
+         -> UISF (a, RecordStatus) ()
+outFileA = outFileHelpA id
+
+outFileNormA :: forall a. AudioSample a => 
+                String               -- ^ Filename to write to.
+             -> Double               -- ^ Sample rate of the incoming signal.
+             -> UISF (a, RecordStatus) ()
+outFileNormA = outFileHelpA normList
+
+outFileHelpA :: forall a. AudioSample a => 
+             ([Double] -> [Double]) -- ^ Post-processing function.
+          -> String                 -- ^ Filename to write to.
+          -> Double                 -- ^ Sample rate of the incoming signal.
+          -> UISF (a, RecordStatus) ()
+outFileHelpA f filepath sr = 
+  let numChannels = numChans (undefined :: a)
+      writeWavSink = sink (writeWav f filepath sr numChannels)
+  in proc (a, rs) -> do
+        rec dat <- delay [] -< dat'
+            dat' <- case rs of
+                        Pause  -> returnA -< dat
+                        Record -> returnA -< a:dat
+                        Clear  -> returnA -< []
+                        Write  -> do writeWavSink -< dat
+                                     returnA -< a:dat
+        returnA -< ()
+-}
+{-
+writeWav :: AudioSample a => ([Double] -> [Double]) -> String -> Double -> Int -> [a] -> UI ()
+writeWav f filepath sr numChannels adat = 
+  let dat         = map (fromSample . (*0.999)) 
+                        (f (concatMap collapse adat)) :: [Int32]
+                    -- multiply by 0.999 to avoid wraparound at 1.0
+      array       = listArray (0, (length dat)-1) dat
+      aud = Audio { sampleRate    = truncate sr,
+                    channelNumber = numChannels,
+                    sampleData    = array }
+  in liftIO $ exportFile filepath aud
+-}
+
+
+  
+
+toSamples :: forall a p. (AudioSample a, Clock p) =>
+             Double -> Signal p () a -> [Double]
+toSamples dur sf = 
+  let sr          = rate     (undefined :: p)
+      numChannels = numChans (undefined :: a)
+      numSamples  = truncate (dur * sr) * numChannels
+  in take numSamples $ concatMap collapse $ unfold $ strip sf
+
+-- | Compute the maximum sample of an SF in the first 'dur' seconds.
+maxSample :: forall a p. (AudioSample a, Clock p) =>
+             Double -> Signal p () a -> Double
+maxSample dur sf = maximum (map abs (toSamples dur sf))
+
+
+{-
+chunk !nFrames !(i, f) ref buf = nFrames `seq` i `seq` f `seq` aux nFrames i 
+    where aux !n !i = x `seq` i `seq` i' `seq`
+                       if n == 0 then do
+                                  writeIORef ref i
+                                  return ()
+                       else do
+                        pokeElemOff buf (fromIntegral nFrames-n) (realToFrac x)
+                        aux (n-1) i'
+              where (x, i') = f ((), i)
+{-# INLINE [0] chunk #-}
+
+chunkify !i !f !secs = do
+  --userData <- new i
+  ref <- newIORef i
+  let cb :: RtAudioCallback 
+      cb oBuf iBuf nFrames nSecs status userData = do
+                      
+                      lastState <- readIORef ref
+                      -- Fill output buffer with nFrames of samples
+                      chunk (fromIntegral nFrames) (lastState,f) ref oBuf
+                      if secs < (realToFrac nSecs) then return 2 else return 0
+                              
+                                                          
+  mkAudioCallback cb                                 
+
+
+
+playPure :: Show b => Double -> (b, ((), b) -> (Double, b)) -> IO ()
+playPure !secs !(i, f) = do
+  rtaCloseStream
+  rtaInitialize
+  dev <- rtaGetDefaultOutputDevice
+  callback <- chunkify i f secs
+  with (StreamParameters dev 1 0) (\params -> do
+         rtaOpenStream params nullPtr float64 44100 4096 callback nullPtr nullPtr)
+  rtaStartStream
+  return ()
+  
+-}
diff --git a/Euterpea/IO/Audio/Types.hs b/Euterpea/IO/Audio/Types.hs
--- a/Euterpea/IO/Audio/Types.hs
+++ b/Euterpea/IO/Audio/Types.hs
@@ -1,51 +1,51 @@
-{-# LANGUAGE EmptyDataDecls, FlexibleInstances #-}
-
-module Euterpea.IO.Audio.Types where
-
-import Control.Arrow.ArrowP
-import Control.SF.SF
-
-
-class Clock p where
-    rate :: p -> Double  -- sampling rate
-
-data AudRate
-data CtrRate
-
-instance Clock AudRate where
-    rate _ = 44100
-
-instance Clock CtrRate where
-    rate _ = 4410
-
-type AudSF a b  = SigFun AudRate a b
-type CtrSF a b  = SigFun CtrRate a b
-
-type Signal clk a b    = ArrowP SF clk a b
-type SigFun clk a b    = ArrowP SF clk a b
-
--- Arbitrary number of channels (say, 5.1) can be supported by just adding more
--- instances of the AudioSample type class.
-
-class AudioSample a where
-    zero :: a
-    mix :: a -> a -> a
-    collapse :: a -> [Double]
-    numChans :: a -> Int   
-      -- allows us to reify the number of channels from the type.
-
-instance AudioSample Double where
-    zero = 0
-    mix = (+)
-    collapse a = [a]
-    numChans _ = 1
-
-instance AudioSample (Double,Double) where
-    zero = (0,0)
-    mix (a,b) (c,d) = (a+c,b+d)
-    collapse (a,b) = [a,b]
-    numChans _ = 2
-
--- Some useful type synonyms:
-type Mono p = Signal p () Double
-type Stereo p = Signal p () (Double,Double)
+{-# LANGUAGE EmptyDataDecls, FlexibleInstances #-}
+
+module Euterpea.IO.Audio.Types where
+
+import Control.Arrow.ArrowP
+import Control.SF.SF
+
+
+class Clock p where
+    rate :: p -> Double  -- sampling rate
+
+data AudRate
+data CtrRate
+
+instance Clock AudRate where
+    rate _ = 44100
+
+instance Clock CtrRate where
+    rate _ = 4410
+
+type AudSF a b  = SigFun AudRate a b
+type CtrSF a b  = SigFun CtrRate a b
+
+type Signal clk a b    = ArrowP SF clk a b
+type SigFun clk a b    = ArrowP SF clk a b
+
+-- Arbitrary number of channels (say, 5.1) can be supported by just adding more
+-- instances of the AudioSample type class.
+
+class AudioSample a where
+    zero :: a
+    mix :: a -> a -> a
+    collapse :: a -> [Double]
+    numChans :: a -> Int   
+      -- allows us to reify the number of channels from the type.
+
+instance AudioSample Double where
+    zero = 0
+    mix = (+)
+    collapse a = [a]
+    numChans _ = 1
+
+instance AudioSample (Double,Double) where
+    zero = (0,0)
+    mix (a,b) (c,d) = (a+c,b+d)
+    collapse (a,b) = [a,b]
+    numChans _ = 2
+
+-- Some useful type synonyms:
+type Mono p = Signal p () Double
+type Stereo p = Signal p () (Double,Double)
diff --git a/Euterpea/IO/MIDI/ExportMidiFile.lhs b/Euterpea/IO/MIDI/ExportMidiFile.lhs
--- a/Euterpea/IO/MIDI/ExportMidiFile.lhs
+++ b/Euterpea/IO/MIDI/ExportMidiFile.lhs
@@ -1,282 +1,282 @@
-MIDI File-writing module for use with Euterpea
-Donya Quick
-Last modified: 19-June-2013
-
-This file fixes some file-writing bugs in Codec.Midi that 
-prevent some multi-instrument output from showing up correctly. 
-It defines the function exportMidiFile, which can be used like
-Codec.Midi's exportFile function. Additionally, it defines two
-functions for writing MIDI files, writeMidi and writeMidiA that
-are like test and testA respectively but with an additional file
-path argument.
-
-NOTE #1: some of the binary handling should be redone at some 
-point. Currently, parts of it are using conversion to a String 
-type, and although it works, it should not be necessary (or at 
-least a cleaner way should be found).
-
-NOTE #2: many MIDI messages are currently unsupported. The set 
-of supported messages is limited to those that can be produced by 
-Euterpea.
-
-> module Euterpea.IO.MIDI.ExportMidiFile
->     (exportMidiFile)  where
-> import Codec.Midi
-> import Numeric
-> import Data.Char
-> import qualified Data.ByteString as Byte 
-
-A standard MIDI file has two main sections: a header and a 
-series of track chunks. Track chunks each have a track header
-section and end with an end-of-track marker. Detailed infomation
-on the file format can be found here:
-
-http://faydoc.tripod.com/formats/mid.htm
-
-
-> makeFile :: Midi -> Byte.ByteString
-> makeFile (Midi ft td trs) = 
->     let ticksPerQn = 
->             case td of TicksPerBeat x -> x
->                        TicksPerSecond x y -> 
->                            error ("(makeFile) Don't know how "++
->                            "to handle TicksPerSecond yet.")
->         header = makeHeader ft (length trs) ticksPerQn
->         body = map makeTrack trs
->     in  Byte.concat (header:body)
-
-============
-
-BUILD FILE HEADER
-
-The standard MIDI file header starts with the following value:
-4D 54 68 00 00 00 06 ff ff nn nn dd dd
-
-ff ff is the format of the file: single-track, multi-track, or 
-multi-track/multi-pattern. Only the first two cases are addressed 
-here.
-
-nn nn is the number of tracks in the file.
-
-dd dd is the delta-time in ticks for a quarternote or beat.
-
-> midiHeaderConst :: Byte.ByteString
-> midiHeaderConst = 
->     Byte.pack [0x4D, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06] 
-
-> type TrackCount = Int
-> type TicksPerQN = Int
-
-
-The MIDI file header is built as described above. 
-
-> makeHeader :: FileType -> TrackCount -> TicksPerQN -> Byte.ByteString
-> makeHeader ft numTracks ticksPerQn = 
->     let 
->         ft' = case ft of SingleTrack -> [0x00, 0x00]
->                          MultiTrack -> [0x00, 0x01]
->                          MultiPattern -> error ("(makeHeader) Don't know "++
->                                          "how to handle multi-pattern yet.")
->         numTracks' = padByte 2 numTracks
->         ticksPerQn' = padByte 2 ticksPerQn
->     in  if numTracks > 16 then error ("(makeHeader) Don't know how to "++
->                                "handle >16 tracks!")
->         else Byte.concat [midiHeaderConst, Byte.pack ft', numTracks', ticksPerQn']
-
-> padByte :: Integral a => Int -> a -> Byte.ByteString
-> padByte byteCount i = 
->   let b = Byte.pack [fromIntegral i] 
->       n = Byte.length b
->       padding = Byte.pack $ take (byteCount - n) $ repeat 0x00
->   in  if n < byteCount then Byte.concat [padding, b] else b
-
-================
-
-BUILDING TRACKS
-
-A track consists of a track header, event information, and an 
-end-of-track marker. The track header has the format:
-
-4D 54 72 6B xx xx xx xx
-
-xx xx xx xx is the total number of BYTES in the track that 
-follows the header. This includes the end marker! This value
-is obtained by generating the track first and then generating
-its header.
-
-> makeTrack :: Track Ticks -> Byte.ByteString
-> makeTrack t = 
->     let body = makeTrackBody t
->         header = makeTrackHeader body
->     in  Byte.concat [header, body]
-
-> trackHeaderConst :: Byte.ByteString
-> trackHeaderConst = Byte.pack [0x4D, 0x54, 0x72, 0x6B] 
-
-> makeTrackHeader :: Byte.ByteString -> Byte.ByteString
-> makeTrackHeader tbody = 
->     let len = Byte.length tbody
->         f = Byte.pack . map (fromIntegral . binStrToNum . reverse) . 
->             breakBinStrs 8 . pad (8*4) '0' . numToBinStr
->     in  Byte.concat [trackHeaderConst, f len]
-
-Track events have two components: a variable-length delta-time and
-a message. The delta-time is the number of ticks between the last 
-message and the next one. The format will be: time message time message ...
-
-However, delta-times are tricky things. The fact that they can be 
-any length requires that they be encoded in a special way. The binary
-value of the number is split into 7-bit sections. This splitting 
-goes from RIGHT TO LEFT (this is not in any documentation I have read,
-but was the only way that worked). For n sections, the first start 
-with a 1 and the last starts with a 0 - thereby indicating the last 
-byte of the number. The following is an example of the conversion:
-
-192 track ticks = C0 (hex) = 1100 0000 (bin) 
-==> converts to 8140 (hex)
-
-Split into 7-bit groups:        [1]  [100 0000]
-Apply padding:           [000 0001]  [100 0000]
-Add flags:              [1000 0001] [0100 0000]
-Result as hex               8    1      4    0
-
-> makeTrackBody :: Track Ticks -> Byte.ByteString 
-> makeTrackBody [] = endOfTrack -- end marker, very important!
-> makeTrackBody ((ticks, msg):rest) = 
->     let b = msgToBytes msg
->         b' = [to7Bits ticks, msgToBytes msg, makeTrackBody rest]
->     in  if Byte.length b > 0 then Byte.concat b'             
->         else makeTrackBody rest
-
-The end of track marker is set 96 ticks after the last event in the 
-track. This offset is arbitrary, but it helps avoid clipping the notes
-at the end of a file during playback in a program like Winamp or
-Quicktime.
-
-> endOfTrack = Byte.concat [to7Bits 96, Byte.pack [0xFF, 0x2F, 0x00]]
-
-Splitting numbers into 7-bit sections and applying flags is done
-by the following process:
-- convert to a binary string representation
-- pad the number to be full bytes
-- split from right to left into groups of 7 and apply flags
-- convert each 8-bit chunk back to a byte representation
-
-> to7Bits :: (Integral a, Show a) => a -> Byte.ByteString
-> to7Bits =  Byte.pack . map (fromIntegral . binStrToNum . reverse) .
->            fixBinStrs . map (padTo 7 . reverse). reverse . 
->            breakBinStrs 7 . reverse . padTo 8 . numToBinStr
-
-Pad a binary string to be a multiple of 8 bits:
-
-> padTo :: Int -> String -> String
-> padTo i xs = if length xs `mod` i == 0 then xs else padTo i ('0':xs)
-
-Break a string into chunks of length i:
-
-> breakBinStrs :: Int -> String -> [String]
-> breakBinStrs i s = 
->     if length s <= i then [s] else take i s : breakBinStrs i (drop i s)
-
-Convert a number to a binary string:
-
-> numToBinStr :: (Integral a, Show a) => a -> String
-> numToBinStr i = showIntAtBase 2 intToDigit i ""
-
-Convert a binary string to an integer:
-
-> binStrToNum :: String -> Int
-> binStrToNum [] = 0
-> binStrToNum ('0':xs) = 2* binStrToNum xs
-> binStrToNum ('1':xs) = 1 + 2*binStrToNum xs
-> binStrToNum _ = error "bad data."
-
-Append flags to a string (note, the string must be BACKWARDS):
-
-> fixBinStrs :: [String] -> [String]
-> fixBinStrs xs = 
->     let n = length xs
->         bits = take (n-1) (repeat '1') ++ "0"
->     in  Prelude.zipWith (:) bits xs
-
-Pad a list from the left until it is a fixed length:
-
-> pad :: Int -> a -> [a] -> [a]
-> pad b x xs = if length xs >= b then xs else pad b x (x:xs)
-
-Messages have the following encodings:
-
-8x nn vv	Note Off for pitch nn at velocity vv, channel x
-9x nn vv	Note On for pitch nn at velocity vv, channel x
-Ax nn vv	Key aftertouch for pitch nn at velocity vv, channel x
-Bx cc vv	Control Change for controller cc with value vv, channel x
-Cx pp		Program Change to patch pp for channel x
-Dx cc 		Channel after-touch to cc on channel x
-Ex bb tt 	Pitch wheel to value ttbb, channel x (2000 hex is "normal") 
-            (note: bb are least significant bits, tt are most significant)
-
-Currently, only note on/off, control change, and program change are supported.
-
-There are also META -EVENTS. This are events that have no channel number.
-All meta-events have the format
-
-FF xx nn nn dd dd ...
-
-where xx is the command code, and nnnn is the number of bytes in the data (dd).
-
-FF 00 nn ssss		Set track sequence number
-FF 01 nn tt...		Text event
-FF 02 nn tt...		Copyright info
-FF 03 nn tt...		Track name
-FF 04 nn tt...		Track instrument name
-FF 05 nn tt...		Lyric
-FF 06 nn tt...		Marker
-FF 07 nn tt...		Cue point
-FF 2F 00			END OF TRACK MARKER
-FF 51 03 tttttt		Tempo change marker, where tttttt is the microseconds per qn
-FF 48 04 nnddccbb	Time signature nn/dd with cc ticks per beat and bb 32nds/qn
-FF 59 02 sfmi		Key signature with sf sharps/flats and mi mode in {0,1}
-
-Of these, only the end of track and tempo marker are implemented.
-
-> msgToBytes :: Message -> Byte.ByteString
-> msgToBytes (NoteOn c k v) = 
->     Byte.concat [Byte.pack [0x90 + fromIntegral c], padByte 1 k, padByte 1 v]
-> msgToBytes (NoteOff c k v) = 
->     Byte.concat [Byte.pack [0x80 + fromIntegral c], padByte 1 k, padByte 1 v]
-> msgToBytes (ProgramChange c p) =  
->     Byte.concat [Byte.pack [0xC0 + fromIntegral c], padByte 1 p]
-> msgToBytes (ControlChange c n v) =  
->     Byte.concat [Byte.pack [0xB0 + fromIntegral c], padByte 1 n, padByte 1 v]
-> msgToBytes (TempoChange t) = -- META EVENT, HAS NO CHANNEL NUMBER
->     Byte.concat [Byte.pack [0xFF, 0x51, 0x03], fixTempo t]
-> msgToBytes x = error ("(msgToBytes) Message type not currently "++ 
->                "supported: "++show x)
-
-Fix a tempo value to be exactly 3 bytes:
-
-> fixTempo = Byte.pack . map (fromIntegral . binStrToNum . reverse) . 
->            breakBinStrs 8 . pad (4*6) '0' . numToBinStr
-
-> exportMidiFile :: FilePath -> Midi -> IO ()
-> exportMidiFile fn = Byte.writeFile fn . makeFile
-
-
-=================
-
-USAGE
-
-The exportMidiFile can now be used as follows in place of Codec.Midi's exportFile:
-
- writeMidi :: (ToMusic1 a) => FilePath -> Music a -> IO ()
- writeMidi fn = exportMidiFile fn . testMidi
-
- writeMidiA :: (ToMusic1 a) => FilePath -> PMap Note1 -> Context Note1 -> Music a -> IO ()
- writeMidiA fn pm con m = exportMidiFile fn $ testMidiA pm con m
-
- test :: (ToMusic1 a) => Music a -> IO ()
- test = exportMidiFile "test.mid" . testMidi
- 
- testA :: ToMusic1 a => PMap Note1 -> Context Note1 -> Music a -> IO ()
- testA pm con m = exportMidiFile "test.mid" (testMidiA pm con m)
+MIDI File-writing module for use with Euterpea
+Donya Quick
+Last modified: 19-June-2013
+
+This file fixes some file-writing bugs in Codec.Midi that 
+prevent some multi-instrument output from showing up correctly. 
+It defines the function exportMidiFile, which can be used like
+Codec.Midi's exportFile function. Additionally, it defines two
+functions for writing MIDI files, writeMidi and writeMidiA that
+are like test and testA respectively but with an additional file
+path argument.
+
+NOTE #1: some of the binary handling should be redone at some 
+point. Currently, parts of it are using conversion to a String 
+type, and although it works, it should not be necessary (or at 
+least a cleaner way should be found).
+
+NOTE #2: many MIDI messages are currently unsupported. The set 
+of supported messages is limited to those that can be produced by 
+Euterpea.
+
+> module Euterpea.IO.MIDI.ExportMidiFile
+>     (exportMidiFile)  where
+> import Codec.Midi
+> import Numeric
+> import Data.Char
+> import qualified Data.ByteString as Byte 
+
+A standard MIDI file has two main sections: a header and a 
+series of track chunks. Track chunks each have a track header
+section and end with an end-of-track marker. Detailed infomation
+on the file format can be found here:
+
+http://faydoc.tripod.com/formats/mid.htm
+
+
+> makeFile :: Midi -> Byte.ByteString
+> makeFile (Midi ft td trs) = 
+>     let ticksPerQn = 
+>             case td of TicksPerBeat x -> x
+>                        TicksPerSecond x y -> 
+>                            error ("(makeFile) Don't know how "++
+>                            "to handle TicksPerSecond yet.")
+>         header = makeHeader ft (length trs) ticksPerQn
+>         body = map makeTrack trs
+>     in  Byte.concat (header:body)
+
+============
+
+BUILD FILE HEADER
+
+The standard MIDI file header starts with the following value:
+4D 54 68 00 00 00 06 ff ff nn nn dd dd
+
+ff ff is the format of the file: single-track, multi-track, or 
+multi-track/multi-pattern. Only the first two cases are addressed 
+here.
+
+nn nn is the number of tracks in the file.
+
+dd dd is the delta-time in ticks for a quarternote or beat.
+
+> midiHeaderConst :: Byte.ByteString
+> midiHeaderConst = 
+>     Byte.pack [0x4D, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06] 
+
+> type TrackCount = Int
+> type TicksPerQN = Int
+
+
+The MIDI file header is built as described above. 
+
+> makeHeader :: FileType -> TrackCount -> TicksPerQN -> Byte.ByteString
+> makeHeader ft numTracks ticksPerQn = 
+>     let 
+>         ft' = case ft of SingleTrack -> [0x00, 0x00]
+>                          MultiTrack -> [0x00, 0x01]
+>                          MultiPattern -> error ("(makeHeader) Don't know "++
+>                                          "how to handle multi-pattern yet.")
+>         numTracks' = padByte 2 numTracks
+>         ticksPerQn' = padByte 2 ticksPerQn
+>     in  if numTracks > 16 then error ("(makeHeader) Don't know how to "++
+>                                "handle >16 tracks!")
+>         else Byte.concat [midiHeaderConst, Byte.pack ft', numTracks', ticksPerQn']
+
+> padByte :: Integral a => Int -> a -> Byte.ByteString
+> padByte byteCount i = 
+>   let b = Byte.pack [fromIntegral i] 
+>       n = Byte.length b
+>       padding = Byte.pack $ take (byteCount - n) $ repeat 0x00
+>   in  if n < byteCount then Byte.concat [padding, b] else b
+
+================
+
+BUILDING TRACKS
+
+A track consists of a track header, event information, and an 
+end-of-track marker. The track header has the format:
+
+4D 54 72 6B xx xx xx xx
+
+xx xx xx xx is the total number of BYTES in the track that 
+follows the header. This includes the end marker! This value
+is obtained by generating the track first and then generating
+its header.
+
+> makeTrack :: Track Ticks -> Byte.ByteString
+> makeTrack t = 
+>     let body = makeTrackBody t
+>         header = makeTrackHeader body
+>     in  Byte.concat [header, body]
+
+> trackHeaderConst :: Byte.ByteString
+> trackHeaderConst = Byte.pack [0x4D, 0x54, 0x72, 0x6B] 
+
+> makeTrackHeader :: Byte.ByteString -> Byte.ByteString
+> makeTrackHeader tbody = 
+>     let len = Byte.length tbody
+>         f = Byte.pack . map (fromIntegral . binStrToNum . reverse) . 
+>             breakBinStrs 8 . pad (8*4) '0' . numToBinStr
+>     in  Byte.concat [trackHeaderConst, f len]
+
+Track events have two components: a variable-length delta-time and
+a message. The delta-time is the number of ticks between the last 
+message and the next one. The format will be: time message time message ...
+
+However, delta-times are tricky things. The fact that they can be 
+any length requires that they be encoded in a special way. The binary
+value of the number is split into 7-bit sections. This splitting 
+goes from RIGHT TO LEFT (this is not in any documentation I have read,
+but was the only way that worked). For n sections, the first start 
+with a 1 and the last starts with a 0 - thereby indicating the last 
+byte of the number. The following is an example of the conversion:
+
+192 track ticks = C0 (hex) = 1100 0000 (bin) 
+==> converts to 8140 (hex)
+
+Split into 7-bit groups:        [1]  [100 0000]
+Apply padding:           [000 0001]  [100 0000]
+Add flags:              [1000 0001] [0100 0000]
+Result as hex               8    1      4    0
+
+> makeTrackBody :: Track Ticks -> Byte.ByteString 
+> makeTrackBody [] = endOfTrack -- end marker, very important!
+> makeTrackBody ((ticks, msg):rest) = 
+>     let b = msgToBytes msg
+>         b' = [to7Bits ticks, msgToBytes msg, makeTrackBody rest]
+>     in  if Byte.length b > 0 then Byte.concat b'             
+>         else makeTrackBody rest
+
+The end of track marker is set 96 ticks after the last event in the 
+track. This offset is arbitrary, but it helps avoid clipping the notes
+at the end of a file during playback in a program like Winamp or
+Quicktime.
+
+> endOfTrack = Byte.concat [to7Bits 96, Byte.pack [0xFF, 0x2F, 0x00]]
+
+Splitting numbers into 7-bit sections and applying flags is done
+by the following process:
+- convert to a binary string representation
+- pad the number to be full bytes
+- split from right to left into groups of 7 and apply flags
+- convert each 8-bit chunk back to a byte representation
+
+> to7Bits :: (Integral a, Show a) => a -> Byte.ByteString
+> to7Bits =  Byte.pack . map (fromIntegral . binStrToNum . reverse) .
+>            fixBinStrs . map (padTo 7 . reverse). reverse . 
+>            breakBinStrs 7 . reverse . padTo 8 . numToBinStr
+
+Pad a binary string to be a multiple of 8 bits:
+
+> padTo :: Int -> String -> String
+> padTo i xs = if length xs `mod` i == 0 then xs else padTo i ('0':xs)
+
+Break a string into chunks of length i:
+
+> breakBinStrs :: Int -> String -> [String]
+> breakBinStrs i s = 
+>     if length s <= i then [s] else take i s : breakBinStrs i (drop i s)
+
+Convert a number to a binary string:
+
+> numToBinStr :: (Integral a, Show a) => a -> String
+> numToBinStr i = showIntAtBase 2 intToDigit i ""
+
+Convert a binary string to an integer:
+
+> binStrToNum :: String -> Int
+> binStrToNum [] = 0
+> binStrToNum ('0':xs) = 2* binStrToNum xs
+> binStrToNum ('1':xs) = 1 + 2*binStrToNum xs
+> binStrToNum _ = error "bad data."
+
+Append flags to a string (note, the string must be BACKWARDS):
+
+> fixBinStrs :: [String] -> [String]
+> fixBinStrs xs = 
+>     let n = length xs
+>         bits = take (n-1) (repeat '1') ++ "0"
+>     in  Prelude.zipWith (:) bits xs
+
+Pad a list from the left until it is a fixed length:
+
+> pad :: Int -> a -> [a] -> [a]
+> pad b x xs = if length xs >= b then xs else pad b x (x:xs)
+
+Messages have the following encodings:
+
+8x nn vv	Note Off for pitch nn at velocity vv, channel x
+9x nn vv	Note On for pitch nn at velocity vv, channel x
+Ax nn vv	Key aftertouch for pitch nn at velocity vv, channel x
+Bx cc vv	Control Change for controller cc with value vv, channel x
+Cx pp		Program Change to patch pp for channel x
+Dx cc 		Channel after-touch to cc on channel x
+Ex bb tt 	Pitch wheel to value ttbb, channel x (2000 hex is "normal") 
+            (note: bb are least significant bits, tt are most significant)
+
+Currently, only note on/off, control change, and program change are supported.
+
+There are also META -EVENTS. This are events that have no channel number.
+All meta-events have the format
+
+FF xx nn nn dd dd ...
+
+where xx is the command code, and nnnn is the number of bytes in the data (dd).
+
+FF 00 nn ssss		Set track sequence number
+FF 01 nn tt...		Text event
+FF 02 nn tt...		Copyright info
+FF 03 nn tt...		Track name
+FF 04 nn tt...		Track instrument name
+FF 05 nn tt...		Lyric
+FF 06 nn tt...		Marker
+FF 07 nn tt...		Cue point
+FF 2F 00			END OF TRACK MARKER
+FF 51 03 tttttt		Tempo change marker, where tttttt is the microseconds per qn
+FF 48 04 nnddccbb	Time signature nn/dd with cc ticks per beat and bb 32nds/qn
+FF 59 02 sfmi		Key signature with sf sharps/flats and mi mode in {0,1}
+
+Of these, only the end of track and tempo marker are implemented.
+
+> msgToBytes :: Message -> Byte.ByteString
+> msgToBytes (NoteOn c k v) = 
+>     Byte.concat [Byte.pack [0x90 + fromIntegral c], padByte 1 k, padByte 1 v]
+> msgToBytes (NoteOff c k v) = 
+>     Byte.concat [Byte.pack [0x80 + fromIntegral c], padByte 1 k, padByte 1 v]
+> msgToBytes (ProgramChange c p) =  
+>     Byte.concat [Byte.pack [0xC0 + fromIntegral c], padByte 1 p]
+> msgToBytes (ControlChange c n v) =  
+>     Byte.concat [Byte.pack [0xB0 + fromIntegral c], padByte 1 n, padByte 1 v]
+> msgToBytes (TempoChange t) = -- META EVENT, HAS NO CHANNEL NUMBER
+>     Byte.concat [Byte.pack [0xFF, 0x51, 0x03], fixTempo t]
+> msgToBytes x = error ("(msgToBytes) Message type not currently "++ 
+>                "supported: "++show x)
+
+Fix a tempo value to be exactly 3 bytes:
+
+> fixTempo = Byte.pack . map (fromIntegral . binStrToNum . reverse) . 
+>            breakBinStrs 8 . pad (4*6) '0' . numToBinStr
+
+> exportMidiFile :: FilePath -> Midi -> IO ()
+> exportMidiFile fn = Byte.writeFile fn . makeFile
+
+
+=================
+
+USAGE
+
+The exportMidiFile can now be used as follows in place of Codec.Midi's exportFile:
+
+ writeMidi :: (ToMusic1 a) => FilePath -> Music a -> IO ()
+ writeMidi fn = exportMidiFile fn . testMidi
+
+ writeMidiA :: (ToMusic1 a) => FilePath -> PMap Note1 -> Context Note1 -> Music a -> IO ()
+ writeMidiA fn pm con m = exportMidiFile fn $ testMidiA pm con m
+
+ test :: (ToMusic1 a) => Music a -> IO ()
+ test = exportMidiFile "test.mid" . testMidi
+ 
+ testA :: ToMusic1 a => PMap Note1 -> Context Note1 -> Music a -> IO ()
+ testA pm con m = exportMidiFile "test.mid" (testMidiA pm con m)
  
diff --git a/Euterpea/IO/MIDI/FromMidi.lhs b/Euterpea/IO/MIDI/FromMidi.lhs
--- a/Euterpea/IO/MIDI/FromMidi.lhs
+++ b/Euterpea/IO/MIDI/FromMidi.lhs
@@ -1,267 +1,267 @@
-> module Euterpea.IO.MIDI.FromMidi (fromMidi) where
-> import Euterpea.Music
-> import Euterpea.IO.MIDI.ToMidi
-> import Euterpea.IO.MIDI.GeneralMidi
-> import Data.List
-> import Codec.Midi
-
-
-Donya Quick
-Last updated 15-Oct-2013.
-
-Changes since last major version (15-Jan-2013):
-- makeUPM: (is !! i, 10) changed to (is !! i, 9) for Percussion.
-- Instrument numbers <0 are interpreted as Percussion.
-- ProgChange 10 x is now assigned (-1) as an instrument number.
-
-KNOWN ISSUES:
-- Tempo changes occuring between matching note on/off events may not be 
-  interpreted optimally. A performance-correct representation rather 
-  than a score-correct representation could be accomplished by looking 
-  for these sorts of between-on-off tempo changes when calculating a 
-  note's duration. 
-  
-This code was originally developed for research purposes and then 
-adapted for CPSC 431/531 to overcome some problems exhibited by the
-original implementation of fromMidi. 
-
-This code has functions to read Midi values into an intermediate type,
-SimpleMsg, before conversion to Music (Pitch, Volume) to make processing 
-instrument changes easier. The following features will be retained from 
-the input file:
-- Placement of notes relative to the beat (assumed to be quarternotes).
-- The pitch, volume, and instrument of each note.
-- Tempo changes indicated by TempoChange MIDI events
-
-Other MIDI controller information is currently not supported. This includes 
-events such as pitch bends and modulations. For these controllers, there is 
-no simple way to capture the information in a Music data structure.
-
-The following datatype is for a simplification of MIDI events into simple 
-On/off events for pitches occurring at different times. There are two 
-types of events considered: tempo changes and note events. The note events
-are represented by tuples of:
-- exact onset time, Rational
-- absolute pitch, AbsPitch
-- volume from 0-127, Volume
-- instrument number, Int. The value (-1) is used for Percussion.
-- on/off type, NEvent
-
-> data NEvent = On | Off
->   deriving (Eq, Show, Ord)
-
-> data SimpleMsg = SE (Rational, AbsPitch, Volume, Int, NEvent) |
->               T (Rational, Rational)
->   deriving (Eq, Show)
-> instance Ord (SimpleMsg) where
->     compare (SE(t,p,v,i,e)) (SE(t',p',v',i',e')) = 
->         if t<t' then LT else if t>t' then GT else EQ
->     compare (T(t,x)) (SE(t',p',v',i',e')) = 
->         if t<t' then LT else if t>t' then GT else EQ
->     compare (SE(t,p,v,i,e)) (T(t',x)) = 
->         if t<t' then LT else if t>t' then GT else EQ
->     compare (T(t,x)) (T(t',x')) =
->         if t<t' then LT else if t>t' then GT else EQ
-
-The importFile function places track ticks (Ticks) in a format where 
-each value attached to a message represents the number of ticks that 
-have passed SINCE THE LAST MESSAGE. The following function will convert 
-input in that format into a list of pairs where the ticks are absolute. 
-In otherwords, ticks in the output will represent the exact point in 
-time of an event. This means that unsupported events (e.g. pitch bend) 
-can later be filtered out without affecting the timing of support events.
-
-> addTrackTicks :: Int -> [(Ticks, a)] -> [(Ticks, a)]
-> addTrackTicks sum [] = []
-> addTrackTicks sum ((t,x):ts) = (t+sum,x) : addTrackTicks (t+sum) ts
-
-The following function addresses a ticks to Music duration conversion.
-
-> applyTD :: TimeDiv -> SimpleMsg -> SimpleMsg
-> applyTD tdw x = 
->     case x of T(t,i) -> T(fixT tdw t, i) 
->               SE(t,p,v,i,e) -> SE(fixT tdw t, p, v, i, e) where
-
-> fixT tdw t = 
->     case tdw of TicksPerBeat td -> t / (fromIntegral td * 4)
->                 TicksPerSecond fps tpf -> t / fromIntegral (fps * tpf)
-
-
-The midiToEvents function will take a Midi structure (from importFile, 
-for example) and convert it to a list of lists of SimpleMsgs. Each outer 
-list represents a track in the original Midi. 
-
-> midiToEvents :: Midi -> [[SimpleMsg]]
-> midiToEvents m = 
->     let ts = map (simplifyTrack 0) $ map (addTrackTicks 0) (tracks m) 
->     in  distributeTempos $ map (map (applyTD $ timeDiv m)) ts where 
->   simplifyTrack :: Int -> [(Ticks, Message)] -> [SimpleMsg]
->   simplifyTrack icur [] = []
->   simplifyTrack icur ((t,m):ts) = 
->     case m of (NoteOn c p v) -> 
->                   SE (fromIntegral t, p, v, icur, On) : simplifyTrack icur ts
->               (NoteOff c p v) -> 
->                   SE (fromIntegral t, p, v, icur, Off) : simplifyTrack icur ts
->               (ProgramChange c p) -> simplifyTrack (if c==9 then (-1) else p) ts 
->               (TempoChange x) -> T (fromIntegral t, fromIntegral x) : simplifyTrack icur ts
->               _ -> simplifyTrack icur ts 
-
-
-The first track is the tempo track. It's events need to be distributed
-across the other tracks. This function below is called for that purpose
-in midiToEvents above.
-
-> distributeTempos :: [[SimpleMsg]] -> [[SimpleMsg]]
-> distributeTempos tracks = 
->     if length tracks > 1 then map (sort . (head tracks ++)) (tail tracks)
->     else tracks -- must be a single-track file with embedded tempo changes.
-
-
-The eventsToMusic function will convert a list of lists of SimpleMsgs 
-(output from midiToEvents) to a Music(Pitch,Volume) structure. All 
-notes will be connected together using the (:=:) constructor. For 
-example, the first line of "Frere Jaque", which would normally be
-written as:
-
-c 5 qn :+: d 5 qn :+: e 5 qn :+: c 5 qn
-
-would actually get represented like this when read in from a MIDI:
-
-	(rest 0 :+: c 5 qn) :=:
-      (rest qn :+: d 5 qn) :=:
-      (rest hn :+: e 5 qn) :=:
-      (rest dhn :+: c 5 qn)
-
-This structure is clearly more complicated than it needs to be.
-However, identifying melodic lines and phrases inorder to group the
-events in a more musically appropriate manor is non-trivial, since
-it requires both phrase and voice identification within an instrument 
-To see why this is the case, consider a Piano, which may have right 
-and lef thand lines that might be best separated by :=: at the 
-outermost level. In a MIDI, however, we are likely to get all of the
-events for both hands lumped into the same track. 
-
-The parallelized structure is also required for keeping tempo changes
-syced between instruments. While MIDI files allow tempo changes to 
-occur in the middle of a note, Euterpea's Music values do not.
-      
-Instruments will be grouped at the outermost level. For example, if 
-there are 2 instruments with music values m1 and m2 repsectively, the
-structure would be:
-
-    (instrument i1 m1) :=: (instrument i2 m1)
-	
-Tempo changes are processed within each instrument.
-
-> eventsToMusic :: [[SimpleMsg]] -> Music (Pitch, Volume)
-> eventsToMusic tracks = 
->     let tracks' = splitByInstruments tracks -- handle any mid-track program changes
->         is = map toInstr $ map getInstrument $ filter (not.null) tracks' -- instruments
->         tDef = 500000 -- current tempo, 120bpm as microseconds per qn
->     in  chord $ zipWith instrument is $ map (seToMusic tDef) tracks' where
->   
->   toInstr :: Int -> InstrumentName
->   toInstr i = if i<0 then Percussion else toEnum i 
->
->   seToMusic :: Rational -> [SimpleMsg] -> Music (Pitch, Volume)
->   seToMusic tCurr [] = rest 0
->   seToMusic tCurr (e1@(SE(t,p,v,ins,On)):es) = 
->     let piMatch (SE(t1,p1,v1,ins1,e1)) = (p1==p && ins1==ins) && e1==Off
->         piMatch (T(t1,x)) = False
->         is = findIndices piMatch es -- find mactching note-offs
->         SE(t1,p1,v1,ins1, e) = es !! (is !! 0) -- pick the first matching note-off
->         n = (rest t :+: note (t1-t) (pitch p,v)) -- create a Music note
->     in  if v > 0 then -- a zero volume note is silence
->              if length is > 0 then n :=: seToMusic tCurr es -- found an off
->              else seToMusic tCurr ((e1:es)++[correctOff e1 es]) -- missing off case
->         else seToMusic tCurr es
->   seToMusic tCurr (e1@(T (t,newTempo)):es) = 
->     let t2 = getTime $ head es -- find time of next event after tempo change
->         tfact = tCurr / newTempo -- calculate tempo change factor
->         es' = map (changeTime (subtract t)) es -- adjust start times
->         m = rest t :+: tempo tfact (seToMusic newTempo es')  
->     in  if null es then rest 0 else m where
->         changeTime f (SE (t,p,v,i,e)) = SE (f t,p,v,i,e)
->         changeTime f (T (t,x)) = T (f t, x)
->   seToMusic tCurr (_:es) = seToMusic tCurr es -- ignore note-offs (already handled)
-
-
-Finding the time of an event.
-
-> getTime (SE(t,p,v,i,e)) = t
-> getTime (T (t,x)) = t
-
-
-Finding the instrument associated with a track. Only the first
-instrument label to appear is chosen. If a program change happens
-mid-track, it will not be counted.
-
-> getInstrument ((SE(t,p,v,i,e)):xs) = i
-> getInstrument ((T x) : xs) = getInstrument xs
-> getInstrument [] = -1 -- No instrument assigned
-
-
-The following function ensure that only one instrument appears in 
-each list of SimpleMsgs. This is necessary in order to ensure that 
-instrument assignments occur at the outermost level of the Music.
-
-> splitByInstruments :: [[SimpleMsg]] -> [[SimpleMsg]] 
-> splitByInstruments [] = []
-> splitByInstruments (t:ts) = 
->     let i = getInstrument t
->         (t',t'') = splitByI i t
->         ts' = if or $ map isSE t'' then splitByInstruments (t'':ts) 
->               else splitByInstruments ts
->     in  if or $ map isSE t' then t' : ts' else ts'
-
-> isSE :: SimpleMsg -> Bool
-> isSE (SE xs) = True
-> isSE (T i) = False
-
-
-The splitByI function partitions a stream to select a specific instrument's events.
-
-> splitByI :: Int -> [SimpleMsg] -> ([SimpleMsg],[SimpleMsg])
-> splitByI i0 [] = ([],[])
-> splitByI i0 (x:xs) = 
->     let (ts,fs) = splitByI i0 xs
->         f (SE(_,_,_,i1,_)) = i0 == i1
->         f _ = False
->     in  case x of SE x' -> if f x then (x:ts,fs) else (ts,x:fs)
->                   T i -> (x:ts, x:fs) -- add tempos to both streams
-
-
-This function is an error-handling method for MIDI files which have 
-mismatched note on/off events. This seems to be common in output from 
-some software. The solution used here is to assume that the note lasts 
-until the the time of the last event in the list. 
-
-> correctOff (SE(t,p,v,ins,e)) [] = SE(t,p,v,ins,Off)
-> correctOff (SE(t,p,v,ins,e)) es = 
->     let SE(t1,p1,v1,ins1,e1) = last $ filter isSE es
->     in  SE(t1,p,v,ins,Off) 
-
-
-The fromMidi function wraps the combination of midiToEvents and 
-eventsToMusic and performs the final conversion to Music1.
-
-> fromMidi :: Midi -> Music1
-> fromMidi m = 
->     let seList = midiToEvents m
->         iNums = filter (>0) $ map getInstrument seList
->         upm = makeUPM $ map toEnum iNums
->     in  mMap (\(p,v) -> (p, [Volume v])) $ eventsToMusic seList
-
-
-This function is to correct for the fact that channel 10 is
-traditionally reserved for percussion. If there is no percussion,
-then channel 10 must remain empty. Channels are indexed from zero 
-in this representation, so channel 1 is 0, channel 10 is 9, etc.
-
-> makeUPM :: [InstrumentName] -> UserPatchMap
-> makeUPM is = 
->     case findIndex (==Percussion) is of 
->         Nothing -> zip is ([0..8]++[10..]) -- no percussion
->         Just i -> (is !! i, 9) : 
->                   zip (take i is ++ drop (i+1) is) ([0..8]++[10..])
-
+> module Euterpea.IO.MIDI.FromMidi (fromMidi) where
+> import Euterpea.Music
+> import Euterpea.IO.MIDI.ToMidi
+> import Euterpea.IO.MIDI.GeneralMidi
+> import Data.List
+> import Codec.Midi
+
+
+Donya Quick
+Last updated 15-Oct-2013.
+
+Changes since last major version (15-Jan-2013):
+- makeUPM: (is !! i, 10) changed to (is !! i, 9) for Percussion.
+- Instrument numbers <0 are interpreted as Percussion.
+- ProgChange 10 x is now assigned (-1) as an instrument number.
+
+KNOWN ISSUES:
+- Tempo changes occuring between matching note on/off events may not be 
+  interpreted optimally. A performance-correct representation rather 
+  than a score-correct representation could be accomplished by looking 
+  for these sorts of between-on-off tempo changes when calculating a 
+  note's duration. 
+  
+This code was originally developed for research purposes and then 
+adapted for CPSC 431/531 to overcome some problems exhibited by the
+original implementation of fromMidi. 
+
+This code has functions to read Midi values into an intermediate type,
+SimpleMsg, before conversion to Music (Pitch, Volume) to make processing 
+instrument changes easier. The following features will be retained from 
+the input file:
+- Placement of notes relative to the beat (assumed to be quarternotes).
+- The pitch, volume, and instrument of each note.
+- Tempo changes indicated by TempoChange MIDI events
+
+Other MIDI controller information is currently not supported. This includes 
+events such as pitch bends and modulations. For these controllers, there is 
+no simple way to capture the information in a Music data structure.
+
+The following datatype is for a simplification of MIDI events into simple 
+On/off events for pitches occurring at different times. There are two 
+types of events considered: tempo changes and note events. The note events
+are represented by tuples of:
+- exact onset time, Rational
+- absolute pitch, AbsPitch
+- volume from 0-127, Volume
+- instrument number, Int. The value (-1) is used for Percussion.
+- on/off type, NEvent
+
+> data NEvent = On | Off
+>   deriving (Eq, Show, Ord)
+
+> data SimpleMsg = SE (Rational, AbsPitch, Volume, Int, NEvent) |
+>               T (Rational, Rational)
+>   deriving (Eq, Show)
+> instance Ord (SimpleMsg) where
+>     compare (SE(t,p,v,i,e)) (SE(t',p',v',i',e')) = 
+>         if t<t' then LT else if t>t' then GT else EQ
+>     compare (T(t,x)) (SE(t',p',v',i',e')) = 
+>         if t<t' then LT else if t>t' then GT else EQ
+>     compare (SE(t,p,v,i,e)) (T(t',x)) = 
+>         if t<t' then LT else if t>t' then GT else EQ
+>     compare (T(t,x)) (T(t',x')) =
+>         if t<t' then LT else if t>t' then GT else EQ
+
+The importFile function places track ticks (Ticks) in a format where 
+each value attached to a message represents the number of ticks that 
+have passed SINCE THE LAST MESSAGE. The following function will convert 
+input in that format into a list of pairs where the ticks are absolute. 
+In otherwords, ticks in the output will represent the exact point in 
+time of an event. This means that unsupported events (e.g. pitch bend) 
+can later be filtered out without affecting the timing of support events.
+
+> addTrackTicks :: Int -> [(Ticks, a)] -> [(Ticks, a)]
+> addTrackTicks sum [] = []
+> addTrackTicks sum ((t,x):ts) = (t+sum,x) : addTrackTicks (t+sum) ts
+
+The following function addresses a ticks to Music duration conversion.
+
+> applyTD :: TimeDiv -> SimpleMsg -> SimpleMsg
+> applyTD tdw x = 
+>     case x of T(t,i) -> T(fixT tdw t, i) 
+>               SE(t,p,v,i,e) -> SE(fixT tdw t, p, v, i, e) where
+
+> fixT tdw t = 
+>     case tdw of TicksPerBeat td -> t / (fromIntegral td * 4)
+>                 TicksPerSecond fps tpf -> t / fromIntegral (fps * tpf)
+
+
+The midiToEvents function will take a Midi structure (from importFile, 
+for example) and convert it to a list of lists of SimpleMsgs. Each outer 
+list represents a track in the original Midi. 
+
+> midiToEvents :: Midi -> [[SimpleMsg]]
+> midiToEvents m = 
+>     let ts = map (simplifyTrack 0) $ map (addTrackTicks 0) (tracks m) 
+>     in  distributeTempos $ map (map (applyTD $ timeDiv m)) ts where 
+>   simplifyTrack :: Int -> [(Ticks, Message)] -> [SimpleMsg]
+>   simplifyTrack icur [] = []
+>   simplifyTrack icur ((t,m):ts) = 
+>     case m of (NoteOn c p v) -> 
+>                   SE (fromIntegral t, p, v, icur, On) : simplifyTrack icur ts
+>               (NoteOff c p v) -> 
+>                   SE (fromIntegral t, p, v, icur, Off) : simplifyTrack icur ts
+>               (ProgramChange c p) -> simplifyTrack (if c==9 then (-1) else p) ts 
+>               (TempoChange x) -> T (fromIntegral t, fromIntegral x) : simplifyTrack icur ts
+>               _ -> simplifyTrack icur ts 
+
+
+The first track is the tempo track. It's events need to be distributed
+across the other tracks. This function below is called for that purpose
+in midiToEvents above.
+
+> distributeTempos :: [[SimpleMsg]] -> [[SimpleMsg]]
+> distributeTempos tracks = 
+>     if length tracks > 1 then map (sort . (head tracks ++)) (tail tracks)
+>     else tracks -- must be a single-track file with embedded tempo changes.
+
+
+The eventsToMusic function will convert a list of lists of SimpleMsgs 
+(output from midiToEvents) to a Music(Pitch,Volume) structure. All 
+notes will be connected together using the (:=:) constructor. For 
+example, the first line of "Frere Jaque", which would normally be
+written as:
+
+c 5 qn :+: d 5 qn :+: e 5 qn :+: c 5 qn
+
+would actually get represented like this when read in from a MIDI:
+
+	(rest 0 :+: c 5 qn) :=:
+      (rest qn :+: d 5 qn) :=:
+      (rest hn :+: e 5 qn) :=:
+      (rest dhn :+: c 5 qn)
+
+This structure is clearly more complicated than it needs to be.
+However, identifying melodic lines and phrases inorder to group the
+events in a more musically appropriate manor is non-trivial, since
+it requires both phrase and voice identification within an instrument 
+To see why this is the case, consider a Piano, which may have right 
+and lef thand lines that might be best separated by :=: at the 
+outermost level. In a MIDI, however, we are likely to get all of the
+events for both hands lumped into the same track. 
+
+The parallelized structure is also required for keeping tempo changes
+syced between instruments. While MIDI files allow tempo changes to 
+occur in the middle of a note, Euterpea's Music values do not.
+      
+Instruments will be grouped at the outermost level. For example, if 
+there are 2 instruments with music values m1 and m2 repsectively, the
+structure would be:
+
+    (instrument i1 m1) :=: (instrument i2 m1)
+	
+Tempo changes are processed within each instrument.
+
+> eventsToMusic :: [[SimpleMsg]] -> Music (Pitch, Volume)
+> eventsToMusic tracks = 
+>     let tracks' = splitByInstruments tracks -- handle any mid-track program changes
+>         is = map toInstr $ map getInstrument $ filter (not.null) tracks' -- instruments
+>         tDef = 500000 -- current tempo, 120bpm as microseconds per qn
+>     in  chord $ zipWith instrument is $ map (seToMusic tDef) tracks' where
+>   
+>   toInstr :: Int -> InstrumentName
+>   toInstr i = if i<0 then Percussion else toEnum i 
+>
+>   seToMusic :: Rational -> [SimpleMsg] -> Music (Pitch, Volume)
+>   seToMusic tCurr [] = rest 0
+>   seToMusic tCurr (e1@(SE(t,p,v,ins,On)):es) = 
+>     let piMatch (SE(t1,p1,v1,ins1,e1)) = (p1==p && ins1==ins) && e1==Off
+>         piMatch (T(t1,x)) = False
+>         is = findIndices piMatch es -- find mactching note-offs
+>         SE(t1,p1,v1,ins1, e) = es !! (is !! 0) -- pick the first matching note-off
+>         n = (rest t :+: note (t1-t) (pitch p,v)) -- create a Music note
+>     in  if v > 0 then -- a zero volume note is silence
+>              if length is > 0 then n :=: seToMusic tCurr es -- found an off
+>              else seToMusic tCurr ((e1:es)++[correctOff e1 es]) -- missing off case
+>         else seToMusic tCurr es
+>   seToMusic tCurr (e1@(T (t,newTempo)):es) = 
+>     let t2 = getTime $ head es -- find time of next event after tempo change
+>         tfact = tCurr / newTempo -- calculate tempo change factor
+>         es' = map (changeTime (subtract t)) es -- adjust start times
+>         m = rest t :+: tempo tfact (seToMusic newTempo es')  
+>     in  if null es then rest 0 else m where
+>         changeTime f (SE (t,p,v,i,e)) = SE (f t,p,v,i,e)
+>         changeTime f (T (t,x)) = T (f t, x)
+>   seToMusic tCurr (_:es) = seToMusic tCurr es -- ignore note-offs (already handled)
+
+
+Finding the time of an event.
+
+> getTime (SE(t,p,v,i,e)) = t
+> getTime (T (t,x)) = t
+
+
+Finding the instrument associated with a track. Only the first
+instrument label to appear is chosen. If a program change happens
+mid-track, it will not be counted.
+
+> getInstrument ((SE(t,p,v,i,e)):xs) = i
+> getInstrument ((T x) : xs) = getInstrument xs
+> getInstrument [] = -1 -- No instrument assigned
+
+
+The following function ensure that only one instrument appears in 
+each list of SimpleMsgs. This is necessary in order to ensure that 
+instrument assignments occur at the outermost level of the Music.
+
+> splitByInstruments :: [[SimpleMsg]] -> [[SimpleMsg]] 
+> splitByInstruments [] = []
+> splitByInstruments (t:ts) = 
+>     let i = getInstrument t
+>         (t',t'') = splitByI i t
+>         ts' = if or $ map isSE t'' then splitByInstruments (t'':ts) 
+>               else splitByInstruments ts
+>     in  if or $ map isSE t' then t' : ts' else ts'
+
+> isSE :: SimpleMsg -> Bool
+> isSE (SE xs) = True
+> isSE (T i) = False
+
+
+The splitByI function partitions a stream to select a specific instrument's events.
+
+> splitByI :: Int -> [SimpleMsg] -> ([SimpleMsg],[SimpleMsg])
+> splitByI i0 [] = ([],[])
+> splitByI i0 (x:xs) = 
+>     let (ts,fs) = splitByI i0 xs
+>         f (SE(_,_,_,i1,_)) = i0 == i1
+>         f _ = False
+>     in  case x of SE x' -> if f x then (x:ts,fs) else (ts,x:fs)
+>                   T i -> (x:ts, x:fs) -- add tempos to both streams
+
+
+This function is an error-handling method for MIDI files which have 
+mismatched note on/off events. This seems to be common in output from 
+some software. The solution used here is to assume that the note lasts 
+until the the time of the last event in the list. 
+
+> correctOff (SE(t,p,v,ins,e)) [] = SE(t,p,v,ins,Off)
+> correctOff (SE(t,p,v,ins,e)) es = 
+>     let SE(t1,p1,v1,ins1,e1) = last $ filter isSE es
+>     in  SE(t1,p,v,ins,Off) 
+
+
+The fromMidi function wraps the combination of midiToEvents and 
+eventsToMusic and performs the final conversion to Music1.
+
+> fromMidi :: Midi -> Music1
+> fromMidi m = 
+>     let seList = midiToEvents m
+>         iNums = filter (>0) $ map getInstrument seList
+>         upm = makeUPM $ map toEnum iNums
+>     in  mMap (\(p,v) -> (p, [Volume v])) $ eventsToMusic seList
+
+
+This function is to correct for the fact that channel 10 is
+traditionally reserved for percussion. If there is no percussion,
+then channel 10 must remain empty. Channels are indexed from zero 
+in this representation, so channel 1 is 0, channel 10 is 9, etc.
+
+> makeUPM :: [InstrumentName] -> UserPatchMap
+> makeUPM is = 
+>     case findIndex (==Percussion) is of 
+>         Nothing -> zip is ([0..8]++[10..]) -- no percussion
+>         Just i -> (is !! i, 9) : 
+>                   zip (take i is ++ drop (i+1) is) ([0..8]++[10..])
+
diff --git a/Euterpea/IO/MIDI/MEvent.lhs b/Euterpea/IO/MIDI/MEvent.lhs
--- a/Euterpea/IO/MIDI/MEvent.lhs
+++ b/Euterpea/IO/MIDI/MEvent.lhs
@@ -43,13 +43,15 @@
 >     -- timing musicToMEventss
 >     metro :: Int -> Dur -> DurT
 >     metro setting dur  = 60 / (fromIntegral setting * dur)
->     applyControls :: Music1 -> Music1
->     applyControls (Modify (Tempo r) m) = scaleDurations r $ applyControls m
->     applyControls (Modify (Transpose k) m) = shiftPitches1 k $ applyControls m
->     applyControls (m1 :+: m2) = applyControls m1 :+: applyControls m2
->     applyControls (m1 :=: m2) = applyControls m1 :=: applyControls m2
->     applyControls x = x
 
+> applyControls :: Music1 -> Music1
+> applyControls (Modify (Tempo r) m) = scaleDurations r $ applyControls m
+> applyControls (Modify (Transpose k) m) = shiftPitches1 k $ applyControls m
+> applyControls (Modify x m) = Modify x $ applyControls m
+> applyControls (m1 :+: m2) = applyControls m1 :+: applyControls m2
+> applyControls (m1 :=: m2) = applyControls m1 :=: applyControls m2
+> applyControls x = x
+
 > musicToMEvents :: MContext -> Music1 -> (Performance, DurT)
 > musicToMEvents c@MContext{mcTime=t, mcDur=dt} (Prim (Note d p)) = ([noteToMEvent c d p], d*dt)
 > musicToMEvents c@MContext{mcTime=t, mcDur=dt}  (Prim (Rest d)) = ([], d*dt)
@@ -63,7 +65,9 @@
 >     in  (merge evs1 evs2, max d1 d2)
 > musicToMEvents c (Modify (Instrument i) m) = musicToMEvents c{mcInst=i} m
 > musicToMEvents c (Modify (Phrase pas) m) = phraseToMEvents c pas m
-> musicToMEvents c (Modify x m) = musicToMEvents c m -- Transpose and Tempo addressed by applyControls
+> musicToMEvents c (Modify (KeySig x y) m) = musicToMEvents c m -- KeySig causes no change
+> musicToMEvents c (Modify (Custom x) m) = musicToMEvents c m -- Custom cuases no change
+> musicToMEvents c m@(Modify x m') = musicToMEvents c $ applyControls m -- Transpose and Tempo addressed by applyControls
 
 > noteToMEvent :: MContext -> Dur -> (Pitch, [NoteAttribute]) -> MEvent
 > noteToMEvent c@(MContext ct ci cdur cvol) d (p, nas) = 
diff --git a/Euterpea/IO/MIDI/MidiIO.lhs b/Euterpea/IO/MIDI/MidiIO.lhs
--- a/Euterpea/IO/MIDI/MidiIO.lhs
+++ b/Euterpea/IO/MIDI/MidiIO.lhs
@@ -1,665 +1,665 @@
-
-> {-# LANGUAGE GeneralizedNewtypeDeriving #-}
-> module Euterpea.IO.MIDI.MidiIO (
->   getAllDevices, --isValidInputDevice, isValidOutputDevice, -- Used only by Euterpea.IO.MUI.MidiWidgets
->   terminateMidi, initializeMidi, -- Used only by Euterpea.IO.MUI
->   outputMidi, deliverMidiEvent, -- Used only by Euterpea.IO.MUI.MidiWidgets (particularly by midiOut)
->   pollMidi, -- Used only by Euterpea.IO.MUI.MidiWidgets (particularly by midiIn)
->   defaultOutput, defaultInput,
->   playMidi, 
->   MidiMessage (ANote, Std), 
->   getTimeNow,
->   DeviceInfo(..), InputDeviceID, OutputDeviceID, Message(..), Time,
->   unsafeInputID, unsafeOutputID,
-> ) where
-
-> import Codec.Midi (Time, Channel, Key, Velocity, 
->                    Message (..), Midi (..), Track, 
->                    toRealTime, toAbsTime, toSingleTrack, isTrackEnd)
-> import Sound.PortMidi (DeviceInfo (..), getDeviceInfo, 
->                        DeviceID, countDevices, time, 
->                        getDefaultOutputDeviceID, getDefaultInputDeviceID, 
->                        openInput, openOutput, readEvents, 
->                        close, writeShort, getErrorText, terminate, initialize, 
->                        PMError (NoError, BufferOverflow), PMStream, 
->                        PMEvent (..), PMMsg (PMMsg))
-> import Control.Exception (finally)
-> import Control.Concurrent
-> import Control.Concurrent.STM.TChan
-> import Control.Monad.STM (atomically)
-> import Data.IORef
-
-> import Data.Bits (shiftR, shiftL, (.|.), (.&.))
-> import Data.List (findIndex)
-> import Data.Maybe (mapMaybe)
-> import qualified Data.Heap as Heap
-
-> import System.IO (hPutStrLn, stderr)
-> import System.IO.Unsafe (unsafePerformIO)
-> import Control.DeepSeq (NFData)
-
-
-----------------------------
- | Midi Type declarations | 
-----------------------------
-
-> type MidiEvent = (Time, MidiMessage)
-
-> data MidiMessage = ANote { channel :: !Channel, key :: !Key,
->                           velocity :: !Velocity, duration :: !Time }
->                  | Std Message
->   deriving Show
-
-> newtype InputDeviceID  = InputDeviceID  DeviceID
->   deriving (Eq, Show, NFData)
-> newtype OutputDeviceID = OutputDeviceID DeviceID
->   deriving (Eq, Show, NFData)
-
-> unsafeInputID :: Int -> InputDeviceID
-> unsafeInputID = InputDeviceID
-
-> unsafeOutputID :: Int -> OutputDeviceID
-> unsafeOutputID = OutputDeviceID
-
-----------
- | Time | 
-----------
-
-Is this the time we want?  This comes from PortMidi, but there's also the 
-function FRP.UISF.SOE.timeGetTime which uses time data from GLFW.
-
-> getTimeNow :: IO Time 
-> getTimeNow = do
->   t <- time
->   return (fromIntegral t / 1000)
-
-
-----------------------
- | Device Functions | 
-----------------------
-
-getAllDevices returns a list of all of the DeviceInfos found.
-It calls Port.Midi.getDeviceInfo over all device numbers
-
-> getAllDevices :: IO ([(InputDeviceID, DeviceInfo)], [(OutputDeviceID, DeviceInfo)])
-> getAllDevices = do
->   n <- countDevices
->   deviceInfos <- mapM getDeviceInfo [0..n-1]
->   let devs = zip [0..n-1] deviceInfos
->   return ([ (InputDeviceID  d, i) | (d,i) <- devs, input  i], 
->           [ (OutputDeviceID d, i) | (d,i) <- devs, output i])
-
-
-isValidInputDevice and isValideOutputDevice check whether the given 
-devices are respectively valid for input or output.
-
-isValidInputDevice, isValidOutputDevice :: DeviceID -> IO Bool
-isValidInputDevice = isValidDevice input
-isValidOutputDevice = isValidDevice output
-isValidDevice :: (DeviceInfo -> Bool) -> DeviceID -> IO Bool
-isValidDevice pred i = do
-  n <- countDevices   
-  info <- getAllDevices
-  return $ 
-    i >= 0 && i < n && pred (snd $ info !! i)
-
-
----------------------
- | Default devices | 
----------------------
-
-Rather than export the deviceIDs directly, these two functions allow 
-the caller to use the DeviceID without directly controlling it.
-
-They take a function (such as playMidi) and an auxiary argument and 
-apply them together with the default device.  If no default device 
-exists, an error is thrown.
-
-> defaultOutput :: (OutputDeviceID -> a -> IO b) -> a -> IO b
-> defaultOutput f a = do
->   i <- getDefaultOutputDeviceID
->   case i of
->     Nothing -> error "No MIDI output device found"
->     Just i  -> f (OutputDeviceID i) a
-> 
-> defaultInput :: (InputDeviceID -> a -> IO b) -> a -> IO b
-> defaultInput f a = do
->   i <- getDefaultInputDeviceID
->   case i of
->     Nothing -> error "No MIDI input device found"
->     Just i  -> f (InputDeviceID i) a
-
-
------------------------
- | Priority Channels | 
------------------------
-
-The priority channel data type and a constructor for it will be used 
-by devices.  We define them here.
-
-> data PrioChannel a b = PrioChannel
->     { get           :: IO (Heap.MinPrioHeap a b),
->       push          :: a -> b -> IO (),
->       pop           :: IO (a,b),
->       peek          :: IO (Maybe (a,b)) }
-
-> makePriorityChannel :: IO (PrioChannel Time Message)
-> makePriorityChannel = do
->   heapRef <- newIORef (Heap.empty :: Heap.MinPrioHeap Time Message)
->   let get = readIORef heapRef
->       push a b = modifyIORef heapRef (Heap.insert (a,b))
->       pop = do
->         h <- get
->         let (a, h') = Heap.extractHead h
->         modifyIORef heapRef (\_ -> h')
->         return a
->       peek = do
->         h <- get
->         if Heap.isEmpty h 
->           then return Nothing 
->           else return $ Just $ Heap.head h
->         
->   return $ PrioChannel get push pop peek
-
-
-------------------------
- | Global Device Data | 
-------------------------
-
-We keep a mapping from DeviceID to the priority channel for keeping
-track of future MIDI messages, an output function to produce sound, 
-and a stop function.  This mapping is stored in the global ref 
-outDevMap, and it is accessed by getOutDev (which looks up info 
-and adds associations if necessary) and terminateMidi (which calls 
-the stop function on all elements and clears the mapping).
-
-outDevMap is the global mapping.
-
-> outDevMap :: IORef [(OutputDeviceID, 
->                      (PrioChannel Time Message, -- priority channel
->                       (Time, Message) -> IO (), -- sound output function
->                       IO ()))]                  -- stop/terminate function
-> outDevMap = unsafePerformIO $ newIORef []
-
-
-outPort and inPort are global memory refs that contain a mapping of 
-DeviceID to Port Midi Streams.  They are modified with addPort (which 
-adds a new mapping to the list) and lookupPort (which, given a DeviceID, 
-returns the Port Midi Stream associated with it).
-
-> outPort :: IORef [(OutputDeviceID, PMStream)]
-> inPort  :: IORef [(InputDeviceID,  PMStream)]
-> outPort = unsafePerformIO (newIORef [])
-> inPort  = unsafePerformIO (newIORef [])
-
-> lookupPort :: (Eq deviceid) => IORef [(deviceid, PMStream)] -> deviceid -> IO (Maybe PMStream)
-> lookupPort p i = readIORef p >>= (return . lookup i)
-
-> addPort :: IORef [(deviceid, PMStream)] -> (deviceid, PMStream) -> IO ()
-> addPort p is = modifyIORef p (is:)
-
-
---------------------------------------------------
- | Global Device Initialization and Termination | 
---------------------------------------------------
-
-initializeMidi just initializes PortMidi
-
-> initializeMidi :: IO ()
-> initializeMidi = do
->   e <- initialize
->   if e == NoError 
->       then return () 
->       else reportError "initializeMidi" e
-
-terminateMidi calls the stop function on all elements of outDevMap 
-and clears the mapping entirely.  It also clears outPort and inPort.
-
-> terminateMidi :: IO ()
-> terminateMidi = do
->   inits <- readIORef outDevMap
->   mapM_ (\(_, (_,_out,stop)) -> stop) inits
->   terminate
->   modifyIORef outDevMap (const [])
->   writeIORef outPort []
->   writeIORef inPort []
-
-
--------------------
- | Device Lookup | 
--------------------
-
-getOutDev looks up info in outDevMap and adds associations if necessary.  
-It is accessed as a helper function for outputMidi and deliverMidiEvent.
-
-> getOutDev :: OutputDeviceID -> IO (PrioChannel Time Message, (Time, Message) -> IO (), IO ())
-> getOutDev devId = do
->   inits <- readIORef outDevMap
->   case lookup devId inits of
->     Just f -> return f
->     Nothing -> do
->         x <- midiOutRealTime' devId -- Changes made by Donya Quick: this line used to pattern match against Just.
->         pChan <- makePriorityChannel
->         case x of Just (mout,stop) -> do -- Case statement added.
->         				modifyIORef outDevMap ((devId,(pChan,mout,stop)):)
->         				return (pChan,mout,stop)
->                   Nothing -> return (pChan, const (return ()), return ()) -- Nothing case added
-
-
-----------------
- | Midi Input | 
-----------------
-
-pollMidi take an input device and a callback function and polls the device 
-for midi events.  Any events are sent, along with the current time, to 
-the callback function.
-DWC NOTE: Why is the time even used?  All messages get the same time?
-
-> pollMidiCB :: InputDeviceID -> ((Time, [Message]) -> IO ()) -> IO ()
-> pollMidiCB idid@(InputDeviceID devId) callback = do
->   s <- lookupPort inPort idid 
->   case s of
->     Nothing -> do
->       r <- openInput devId 
->       case r of
->         Right e -> reportError "pollMidiCB" e
->         Left s -> addPort inPort (idid, s) >> input s
->     Just s -> input s 
->   where
->     input :: PMStream -> IO ()
->     input s = do
->       e <- readEvents s
->       case e of
->         Right e -> if e == NoError 
->           then return () 
->           else reportError "pollMidiCB" e
->         Left l -> do
->           now <- getTimeNow
->           case mapMaybe (msgToMidi . message) l of
->             [] -> return ()
->             ms -> callback (now, ms)
-
-> pollMidi :: InputDeviceID -> IO (Maybe (Time, [Message]))
-> pollMidi idid@(InputDeviceID devId) = do
->   s <- lookupPort inPort idid 
->   case s of
->     Nothing -> do
->       r <- openInput devId 
->       case r of
->         Right e -> reportError "pollMIDI" e >> return Nothing
->         Left s -> addPort inPort (idid, s) >> input s
->     Just s -> input s 
->   where
->     input :: PMStream -> IO (Maybe (Time, [Message]))
->     input s = do
->       e <- readEvents s
->       case e of
->         Right e -> if e == NoError 
->           then return Nothing
->           else reportError "pollMIDI" e >> return Nothing
->         Left l -> do
->           now <- getTimeNow
->           case mapMaybe (msgToMidi . message) l of
->             [] -> return Nothing
->             ms -> return $ Just (now, ms)
-
-
----------------------------------------------
- | Midi Output for inidividual Midi events | 
----------------------------------------------
-
-The following two functions are for sending and playing individual 
-Midi events to devices.  Typically, usage will be to call outputMidi 
-to play anything that's ready to play and then send in the latest 
-messages with deliverMidiEvent.  Of course, if no new messages are 
-ready to be delivered, that step can be omitted.  Either way, 
-outputMidi should be called many times per second to assure that 
-all Midi messages are played approximately when scheduled.
-
-deliverMidiEvent sends the given MidiEvent to the given device.  If 
-the event is scheduled to happen ``now'', then it is immediately 
-played.  Otherwise, it is queued for later.
-
-> deliverMidiEvent :: OutputDeviceID -> MidiEvent -> IO ()
-> deliverMidiEvent devId (t,m) = do
->   (pChan, out, _stop) <- getOutDev devId
->   now <- getTimeNow
->   let deliver t m = do
->       if t == 0
->         then out (now,m) 
->         else push pChan (now+t) m
->              
->   case m of
->     Std m -> deliver t m
->     ANote c k v d -> do
->         deliver t     (NoteOn c k v)
->         deliver (t+d) (NoteOff c k v)
-
-
-outputMidi plays all midi events that are waiting in this device's 
-priority queue whose time to play has come.
-
-> outputMidi :: OutputDeviceID -> IO ()
-> outputMidi devId = do
->   (pChan, out, _stop) <- getOutDev devId
->   let loop = do
->         r <- peek pChan
->         case r of
->           Nothing     -> return ()
->           Just (t,m)  -> do
->             now <- getTimeNow
->             if t <= now 
->               then out (now, m) >> pop pChan >> loop
->               else return ()
->   loop
->   return ()
-
-
--------------------------------------------
- | Midi Output for a complete Midi track | 
--------------------------------------------
-
-When an entire Midi track is ready to be played, the playMidi function 
-may be more appropriate than deliverMidiEvent and outputMidi.
-
-playMidi will queue up the entire Midi track given to it and then close 
-the output device.
-
-> playMidi :: OutputDeviceID -> Midi -> IO ()
-> playMidi device midi@(Midi _ division _) = do
->   let track = toRealTime division (toAbsTime (head (tracks (toSingleTrack midi))))
->   out <- midiOutRealTime device
->   case out of
->     Nothing -> return ()
->     Just (out, stop) -> do
->       t0 <- getTimeNow 
->       finally (playTrack t0 0 out track) stop
->   where
->     playTrack t0 t' out [] = out (t0 + t', TrackEnd)
->     playTrack t0 t' out (e@(t, m) : s) = do
->       out (t0 + t, m) 
->       if isTrackEnd m 
->         then return ()
->         else playTrack t0 t out s
-
-
----------------------
- | midiOutRealTime | 
----------------------
-
-The following two functions are used to open a device for Midi output.  
-They should only be called when the device hasn't yet been opened, and 
-they both return a ``play'' function and a ``stop'' function.
-
-Currently, midiOutRealTime' is used for Midi output for inidividual 
-Midi events, and midiOutRealTime is used for Midi output for a complete 
-Midi track.
-
-DWC Notes:
-I'm not entirely sure how they both work yet.  midiOutRealTime' 
-actually looks pretty straightforward in that it just creates the process 
-and stop functions and adds this device to the outPort device list.  The 
-process function will look up the device in the outPort device list, and 
-if it finds it, it writes the message to it.  The stop function removes 
-the device from the outPort list and closes it.
-
-On the other hand, midiOutRealTime spawns a new thread and does some 
-concurrent stuff.  Really, it looks similar, but I don't know when to 
-use one and when to use the other.
-
-> midiOutRealTime' :: OutputDeviceID -> IO (Maybe ((Time, Message) -> IO (), IO ()))
-> midiOutRealTime' odid@(OutputDeviceID devId) = do
->   s <- openOutput devId 1  
->   case s of
->     Right e -> reportError "Unable to open output device in midiOutRealTime'" e >> return Nothing
->     Left s -> do
->       addPort outPort (odid, s)
->       return $ Just (process odid, finalize odid)
->   where
->     process odid (t, msg) = do
->       s <- lookupPort outPort odid
->       case s of
->         Nothing -> error ("midiOutRealTime': port " ++ show odid ++ " is not open for output")
->         Just s -> do
->           if isTrackEnd msg 
->               then return ()
->               else case midiEvent msg of
->                 Just m  -> writeMsg s t m
->                 Nothing -> return ()
->     writeMsg s t m = do
->               e <- writeShort s (PMEvent m (round (t * 1e3)))
->               case e of
->                 NoError -> return () 
->                 _ -> reportError "midiOutRealTime'" e
->     finalize odid = do
->       s <- lookupPort outPort odid
->       e <- maybe (return NoError) close s
->       case e of
->         NoError -> return () 
->         _ -> reportError "midiOutRealTime'" e
-
-
-> midiOutRealTime :: OutputDeviceID -> IO (Maybe ((Time, Message) -> IO (), IO ()))
-> midiOutRealTime odid@(OutputDeviceID devId) = do
->   s <- openOutput devId 1  
->   case s of
->     Right e -> reportError "outputMidi" e >> return Nothing
->     Left s -> do
->       ch <- atomically newTChan 
->       wait <- newEmptyMVar
->       fin <- newEmptyMVar
->       forkIO (pump s ch wait fin)
->       return $ Just (output s ch wait, stop ch fin)
->   where
->     stop ch fin = atomically (unGetTChan ch Nothing) >> takeMVar fin
->     output s ch wait evt@(_, m) = do
->       atomically $ writeTChan ch (Just evt)
->       if isTrackEnd m then takeMVar wait else return ()
->     pump s ch wait fin = loop
->       where
->         loop = do 
->           e <- atomically $ readTChan ch
->           case e of
->             Nothing -> close s >> putMVar fin ()
->             Just (t, msg) -> do
->               now <- getTimeNow
->               if (t > now + 5) 
->                 then atomically (unGetTChan ch e) >> threadDelay 10000 >> loop
->                 else do 
->                   done <- process t msg
->                   if done 
->                     then waitUntil (t + 1)
->                     else loop 
->           where
->             waitUntil t = do
->               now <- getTimeNow
->               if t > now 
->                 then do
->                   threadDelay $ min 10000 (round((t - now) * 1E6)) 
->                   empty <- atomically $ isEmptyTChan ch
->                   if empty 
->                     then waitUntil t
->                     else do
->                       e <- atomically $ readTChan ch
->                       case e of
->                         Nothing -> finishup 
->                         _ -> waitUntil t
->                 else finishup
->             finishup = putMVar wait () >> close s >> putMVar fin ()
->             process t msg = if isTrackEnd msg 
->               then return True 
->               else case midiEvent msg of
->                 Just m  -> writeMsg t m
->                 Nothing -> return False 
->             writeMsg t m = do
->               e <- writeShort s (PMEvent m (round (t * 1e3)))
->               case e of
->                 NoError -> return False 
->                 BufferOverflow -> putStrLn "overflow" >> threadDelay 10000 >> writeMsg t m
->                 _ -> reportError "outputMidi" e >> return True 
-
-
----------------------
- | MIDI Conversion | 
----------------------
-
-A conversion function from Codec.Midi Messages to PortMidi PMMsgs.
-
-> midiEvent :: Message -> Maybe PMMsg
-> midiEvent (NoteOff c p v)         = Just $ PMMsg (128 .|. (fromIntegral c .&. 0xF)) (fromIntegral p) (fromIntegral v)
-> midiEvent (NoteOn c p v)          = Just $ PMMsg (144 .|. (fromIntegral c .&. 0xF)) (fromIntegral p) (fromIntegral v)
-> midiEvent (KeyPressure c p pr)    = Just $ PMMsg (160 .|. (fromIntegral c .&. 0xF)) (fromIntegral p) (fromIntegral pr)
-> midiEvent (ControlChange c cn cv) = Just $ PMMsg (176 .|. (fromIntegral c .&. 0xF)) (fromIntegral cn) (fromIntegral cv)
-> midiEvent (ProgramChange c pn)    = Just $ PMMsg (192 .|. (fromIntegral c .&. 0xF)) (fromIntegral pn) 0
-> midiEvent (ChannelPressure c pr)  = Just $ PMMsg (208 .|. (fromIntegral c .&. 0xF)) (fromIntegral pr) 0
-> midiEvent (PitchWheel c pb)       = Just $ PMMsg (224 .|. (fromIntegral c .&. 0xF)) (fromIntegral lo) (fromIntegral hi)
->  where (hi,lo) = (pb `shiftR` 8, pb .&. 0xFF)
-> midiEvent _ = Nothing 
-
-
-A conversion function from PortMidi PMMsgs to Codec.Midi Messages.
-
-> msgToMidi :: PMMsg -> Maybe Message
-> msgToMidi (PMMsg m d1 d2) = 
->   let k = (m .&. 0xF0) `shiftR` 4
->       c = fromIntegral (m .&. 0x0F)
->   in case k of
->     0x8 -> Just $ NoteOff c (fromIntegral d1) (fromIntegral d2)
->     0x9 -> Just $ NoteOn  c (fromIntegral d1) (fromIntegral d2)
->     0xA -> Just $ KeyPressure c (fromIntegral d1) (fromIntegral d2)
->     0xB -> Just $ ControlChange c (fromIntegral d1) (fromIntegral d2)
->     0xC -> Just $ ProgramChange c (fromIntegral d1)
->     0xD -> Just $ ChannelPressure c (fromIntegral d1)
->     0xE -> Just $ PitchWheel c (fromIntegral (d1 + d2 `shiftL` 8))
->     0xF -> Nothing -- SysEx event not handled
->     _   -> Nothing
-
-
----------------------
- | Error Reporting | 
----------------------
-
-> reportError :: String -> PMError -> IO ()
-> reportError prompt e = do
->   err <- getErrorText e 
->   hPutStrLn stderr $ prompt ++ ": " ++  err
-
-
-
-
-
-----------------------
- | Unused Functions | 
-----------------------
-
-> -- Prints all DeviceInfo found by getAllDevices.
-> printAllDeviceInfo :: IO ()
-> printAllDeviceInfo = do
->   (indevs, outdevs) <- getAllDevices
->   mapM_ (print . snd) indevs
->   mapM_ (print . snd) outdevs
-
--- Given whether the device is an input device and the device name, 
--- returns the DeviceID.
-getDeviceId :: Bool -> String -> IO (Maybe DeviceID)
-getDeviceId isInput n = do
-  devs <- getAllDevices
-  return $ findIndex (\(_,d) -> name d == n && input d == isInput) devs
-
-> playTrackRealTime :: OutputDeviceID -> [(t, Message)] -> IO ()
-> playTrackRealTime device track = do
->   out <- midiOutRealTime device
->   case out of
->     Nothing -> return ()
->     Just (out, stop) -> finally (playTrack out track) stop
->   where
->     playTrack out [] = do
->       t <- getTimeNow
->       out (t, TrackEnd)
->     playTrack out (e@(_, m) : s) = do
->       t <- getTimeNow
->       out (t, m) 
->       if isTrackEnd m 
->         then return ()
->         else playTrack out s
-
-> {-
->     ticksPerBeat = case division of
->       TicksPerBeat n -> n
->       TicksPerSecond mode nticks -> (256 - mode - 128) * nticks `div` 2 
-> -}
-
-> {-
-> runTrack tpb = runTrack' 0 0 120                 -- 120 beat/s is the default tempo
->   where
->     runTrack' t t0 bps ((_, TempoChange tempo) : l) = 
->       let bps' = 1000000 `div` fromIntegral tempo  
->       in runTrack' t t0 bps' l
->     runTrack' t t0 bps ((t1, m) : l) = 
->       let t' = t + 1000 * fromIntegral (t1 - t0) `div` (tpb * bps)
->       in (t', m) : runTrack' t' t1 bps l
->     runTrack' _ _ _ [] = [] 
->
-> playTrack s ch t0 = playTrack' 0
->   where
->     playTrack' t [] = putStrLn "done" >> putMVar ch Nothing >> return (round (t * 1.0E3))
->     playTrack' _ ((t, e):es) = putMVar ch (Just io) >> playTrack' t es 
->       where 
->         io = case midiEvent e of
->           Just m  -> writeShort s (PMEvent m (t0 + round (t * 1.0E3)))
->           Nothing -> return NoError 
-> -}
-
-> recordMidi :: DeviceID -> (Track Time -> IO ()) -> IO ()
-> recordMidi device f = do
->   ch <- newChan
->   final <- midiInRealTime device (\e -> writeChan ch e >> return False)
->   case final of 
->     Nothing  -> return () 
->     Just fin -> do
->       track <- getChanContents ch
->       done <- newEmptyMVar 
->       forkIO (f track >> putMVar done ())  
->       putStrLn "Start recording, hit ENTER when you are done."
->       getLine
->       fin 
->       takeMVar done
->       return ()
-
-> midiInRealTime :: DeviceID -> ((Time, Message) -> IO Bool) -> IO (Maybe (IO ()))
-> midiInRealTime device callback = do
->   r <- openInput device 
->   case r of
->     Right e -> reportError "midiInRealTime" e >> return Nothing 
->     Left s -> do
->       fin <- newEmptyMVar
->       forkIO (loop Nothing s fin)
->       return (Just (putMVar fin () >> putMVar fin ()))
->   where
->     loop start s fin = do
->       done <- tryTakeMVar fin
->       t <- getTimeNow
->       case done of
->         Just _ -> close s >> callback (t, TrackEnd) >> takeMVar fin >> return ()
->         Nothing -> do
->           e <- readEvents s
->           case e of
->             Right e -> if e == NoError 
->               then threadDelay 1000 >> loop start s fin
->               else do
->                 reportError "midiInRealTime" e 
->                 callback (t, TrackEnd)
->                 return ()
->             Left l -> do
->               t <- getTimeNow
->               sendEvts start t l
->       where 
->         sendEvts start now [] = loop start s fin
->         sendEvts start now (e@(PMEvent m t):l) = do
->           let t0 = maybe t id start
->           case msgToMidi m of
->             Just m' -> do
->               done <- callback (now + fromIntegral (t - t0) / 1E3, m')
->               if done then close s >> return () else sendEvts (Just t0) now l
->             Nothing -> sendEvts (Just t0) now l
-
+
+> {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+> module Euterpea.IO.MIDI.MidiIO (
+>   getAllDevices, --isValidInputDevice, isValidOutputDevice, -- Used only by Euterpea.IO.MUI.MidiWidgets
+>   terminateMidi, initializeMidi, -- Used only by Euterpea.IO.MUI
+>   outputMidi, deliverMidiEvent, -- Used only by Euterpea.IO.MUI.MidiWidgets (particularly by midiOut)
+>   pollMidi, -- Used only by Euterpea.IO.MUI.MidiWidgets (particularly by midiIn)
+>   defaultOutput, defaultInput,
+>   playMidi, 
+>   MidiMessage (ANote, Std), 
+>   getTimeNow,
+>   DeviceInfo(..), InputDeviceID, OutputDeviceID, Message(..), Time,
+>   unsafeInputID, unsafeOutputID,
+> ) where
+
+> import Codec.Midi (Time, Channel, Key, Velocity, 
+>                    Message (..), Midi (..), Track, 
+>                    toRealTime, toAbsTime, toSingleTrack, isTrackEnd)
+> import Sound.PortMidi (DeviceInfo (..), getDeviceInfo, 
+>                        DeviceID, countDevices, time, 
+>                        getDefaultOutputDeviceID, getDefaultInputDeviceID, 
+>                        openInput, openOutput, readEvents, 
+>                        close, writeShort, getErrorText, terminate, initialize, 
+>                        PMError (NoError, BufferOverflow), PMStream, 
+>                        PMEvent (..), PMMsg (PMMsg))
+> import Control.Exception (finally)
+> import Control.Concurrent
+> import Control.Concurrent.STM.TChan
+> import Control.Monad.STM (atomically)
+> import Data.IORef
+
+> import Data.Bits (shiftR, shiftL, (.|.), (.&.))
+> import Data.List (findIndex)
+> import Data.Maybe (mapMaybe)
+> import qualified Data.Heap as Heap
+
+> import System.IO (hPutStrLn, stderr)
+> import System.IO.Unsafe (unsafePerformIO)
+> import Control.DeepSeq (NFData)
+
+
+----------------------------
+ | Midi Type declarations | 
+----------------------------
+
+> type MidiEvent = (Time, MidiMessage)
+
+> data MidiMessage = ANote { channel :: !Channel, key :: !Key,
+>                           velocity :: !Velocity, duration :: !Time }
+>                  | Std Message
+>   deriving Show
+
+> newtype InputDeviceID  = InputDeviceID  DeviceID
+>   deriving (Eq, Show, NFData)
+> newtype OutputDeviceID = OutputDeviceID DeviceID
+>   deriving (Eq, Show, NFData)
+
+> unsafeInputID :: Int -> InputDeviceID
+> unsafeInputID = InputDeviceID
+
+> unsafeOutputID :: Int -> OutputDeviceID
+> unsafeOutputID = OutputDeviceID
+
+----------
+ | Time | 
+----------
+
+Is this the time we want?  This comes from PortMidi, but there's also the 
+function FRP.UISF.SOE.timeGetTime which uses time data from GLFW.
+
+> getTimeNow :: IO Time 
+> getTimeNow = do
+>   t <- time
+>   return (fromIntegral t / 1000)
+
+
+----------------------
+ | Device Functions | 
+----------------------
+
+getAllDevices returns a list of all of the DeviceInfos found.
+It calls Port.Midi.getDeviceInfo over all device numbers
+
+> getAllDevices :: IO ([(InputDeviceID, DeviceInfo)], [(OutputDeviceID, DeviceInfo)])
+> getAllDevices = do
+>   n <- countDevices
+>   deviceInfos <- mapM getDeviceInfo [0..n-1]
+>   let devs = zip [0..n-1] deviceInfos
+>   return ([ (InputDeviceID  d, i) | (d,i) <- devs, input  i], 
+>           [ (OutputDeviceID d, i) | (d,i) <- devs, output i])
+
+
+isValidInputDevice and isValideOutputDevice check whether the given 
+devices are respectively valid for input or output.
+
+isValidInputDevice, isValidOutputDevice :: DeviceID -> IO Bool
+isValidInputDevice = isValidDevice input
+isValidOutputDevice = isValidDevice output
+isValidDevice :: (DeviceInfo -> Bool) -> DeviceID -> IO Bool
+isValidDevice pred i = do
+  n <- countDevices   
+  info <- getAllDevices
+  return $ 
+    i >= 0 && i < n && pred (snd $ info !! i)
+
+
+---------------------
+ | Default devices | 
+---------------------
+
+Rather than export the deviceIDs directly, these two functions allow 
+the caller to use the DeviceID without directly controlling it.
+
+They take a function (such as playMidi) and an auxiary argument and 
+apply them together with the default device.  If no default device 
+exists, an error is thrown.
+
+> defaultOutput :: (OutputDeviceID -> a -> IO b) -> a -> IO b
+> defaultOutput f a = do
+>   i <- getDefaultOutputDeviceID
+>   case i of
+>     Nothing -> error "No MIDI output device found"
+>     Just i  -> f (OutputDeviceID i) a
+> 
+> defaultInput :: (InputDeviceID -> a -> IO b) -> a -> IO b
+> defaultInput f a = do
+>   i <- getDefaultInputDeviceID
+>   case i of
+>     Nothing -> error "No MIDI input device found"
+>     Just i  -> f (InputDeviceID i) a
+
+
+-----------------------
+ | Priority Channels | 
+-----------------------
+
+The priority channel data type and a constructor for it will be used 
+by devices.  We define them here.
+
+> data PrioChannel a b = PrioChannel
+>     { get           :: IO (Heap.MinPrioHeap a b),
+>       push          :: a -> b -> IO (),
+>       pop           :: IO (a,b),
+>       peek          :: IO (Maybe (a,b)) }
+
+> makePriorityChannel :: IO (PrioChannel Time Message)
+> makePriorityChannel = do
+>   heapRef <- newIORef (Heap.empty :: Heap.MinPrioHeap Time Message)
+>   let get = readIORef heapRef
+>       push a b = modifyIORef heapRef (Heap.insert (a,b))
+>       pop = do
+>         h <- get
+>         let (a, h') = Heap.extractHead h
+>         modifyIORef heapRef (\_ -> h')
+>         return a
+>       peek = do
+>         h <- get
+>         if Heap.isEmpty h 
+>           then return Nothing 
+>           else return $ Just $ Heap.head h
+>         
+>   return $ PrioChannel get push pop peek
+
+
+------------------------
+ | Global Device Data | 
+------------------------
+
+We keep a mapping from DeviceID to the priority channel for keeping
+track of future MIDI messages, an output function to produce sound, 
+and a stop function.  This mapping is stored in the global ref 
+outDevMap, and it is accessed by getOutDev (which looks up info 
+and adds associations if necessary) and terminateMidi (which calls 
+the stop function on all elements and clears the mapping).
+
+outDevMap is the global mapping.
+
+> outDevMap :: IORef [(OutputDeviceID, 
+>                      (PrioChannel Time Message, -- priority channel
+>                       (Time, Message) -> IO (), -- sound output function
+>                       IO ()))]                  -- stop/terminate function
+> outDevMap = unsafePerformIO $ newIORef []
+
+
+outPort and inPort are global memory refs that contain a mapping of 
+DeviceID to Port Midi Streams.  They are modified with addPort (which 
+adds a new mapping to the list) and lookupPort (which, given a DeviceID, 
+returns the Port Midi Stream associated with it).
+
+> outPort :: IORef [(OutputDeviceID, PMStream)]
+> inPort  :: IORef [(InputDeviceID,  PMStream)]
+> outPort = unsafePerformIO (newIORef [])
+> inPort  = unsafePerformIO (newIORef [])
+
+> lookupPort :: (Eq deviceid) => IORef [(deviceid, PMStream)] -> deviceid -> IO (Maybe PMStream)
+> lookupPort p i = readIORef p >>= (return . lookup i)
+
+> addPort :: IORef [(deviceid, PMStream)] -> (deviceid, PMStream) -> IO ()
+> addPort p is = modifyIORef p (is:)
+
+
+--------------------------------------------------
+ | Global Device Initialization and Termination | 
+--------------------------------------------------
+
+initializeMidi just initializes PortMidi
+
+> initializeMidi :: IO ()
+> initializeMidi = do
+>   e <- initialize
+>   if e == NoError 
+>       then return () 
+>       else reportError "initializeMidi" e
+
+terminateMidi calls the stop function on all elements of outDevMap 
+and clears the mapping entirely.  It also clears outPort and inPort.
+
+> terminateMidi :: IO ()
+> terminateMidi = do
+>   inits <- readIORef outDevMap
+>   mapM_ (\(_, (_,_out,stop)) -> stop) inits
+>   terminate
+>   modifyIORef outDevMap (const [])
+>   writeIORef outPort []
+>   writeIORef inPort []
+
+
+-------------------
+ | Device Lookup | 
+-------------------
+
+getOutDev looks up info in outDevMap and adds associations if necessary.  
+It is accessed as a helper function for outputMidi and deliverMidiEvent.
+
+> getOutDev :: OutputDeviceID -> IO (PrioChannel Time Message, (Time, Message) -> IO (), IO ())
+> getOutDev devId = do
+>   inits <- readIORef outDevMap
+>   case lookup devId inits of
+>     Just f -> return f
+>     Nothing -> do
+>         x <- midiOutRealTime' devId -- Changes made by Donya Quick: this line used to pattern match against Just.
+>         pChan <- makePriorityChannel
+>         case x of Just (mout,stop) -> do -- Case statement added.
+>         				modifyIORef outDevMap ((devId,(pChan,mout,stop)):)
+>         				return (pChan,mout,stop)
+>                   Nothing -> return (pChan, const (return ()), return ()) -- Nothing case added
+
+
+----------------
+ | Midi Input | 
+----------------
+
+pollMidi take an input device and a callback function and polls the device 
+for midi events.  Any events are sent, along with the current time, to 
+the callback function.
+DWC NOTE: Why is the time even used?  All messages get the same time?
+
+> pollMidiCB :: InputDeviceID -> ((Time, [Message]) -> IO ()) -> IO ()
+> pollMidiCB idid@(InputDeviceID devId) callback = do
+>   s <- lookupPort inPort idid 
+>   case s of
+>     Nothing -> do
+>       r <- openInput devId 
+>       case r of
+>         Right e -> reportError "pollMidiCB" e
+>         Left s -> addPort inPort (idid, s) >> input s
+>     Just s -> input s 
+>   where
+>     input :: PMStream -> IO ()
+>     input s = do
+>       e <- readEvents s
+>       case e of
+>         Right e -> if e == NoError 
+>           then return () 
+>           else reportError "pollMidiCB" e
+>         Left l -> do
+>           now <- getTimeNow
+>           case mapMaybe (msgToMidi . message) l of
+>             [] -> return ()
+>             ms -> callback (now, ms)
+
+> pollMidi :: InputDeviceID -> IO (Maybe (Time, [Message]))
+> pollMidi idid@(InputDeviceID devId) = do
+>   s <- lookupPort inPort idid 
+>   case s of
+>     Nothing -> do
+>       r <- openInput devId 
+>       case r of
+>         Right e -> reportError "pollMIDI" e >> return Nothing
+>         Left s -> addPort inPort (idid, s) >> input s
+>     Just s -> input s 
+>   where
+>     input :: PMStream -> IO (Maybe (Time, [Message]))
+>     input s = do
+>       e <- readEvents s
+>       case e of
+>         Right e -> if e == NoError 
+>           then return Nothing
+>           else reportError "pollMIDI" e >> return Nothing
+>         Left l -> do
+>           now <- getTimeNow
+>           case mapMaybe (msgToMidi . message) l of
+>             [] -> return Nothing
+>             ms -> return $ Just (now, ms)
+
+
+---------------------------------------------
+ | Midi Output for inidividual Midi events | 
+---------------------------------------------
+
+The following two functions are for sending and playing individual 
+Midi events to devices.  Typically, usage will be to call outputMidi 
+to play anything that's ready to play and then send in the latest 
+messages with deliverMidiEvent.  Of course, if no new messages are 
+ready to be delivered, that step can be omitted.  Either way, 
+outputMidi should be called many times per second to assure that 
+all Midi messages are played approximately when scheduled.
+
+deliverMidiEvent sends the given MidiEvent to the given device.  If 
+the event is scheduled to happen ``now'', then it is immediately 
+played.  Otherwise, it is queued for later.
+
+> deliverMidiEvent :: OutputDeviceID -> MidiEvent -> IO ()
+> deliverMidiEvent devId (t,m) = do
+>   (pChan, out, _stop) <- getOutDev devId
+>   now <- getTimeNow
+>   let deliver t m = do
+>       if t == 0
+>         then out (now,m) 
+>         else push pChan (now+t) m
+>              
+>   case m of
+>     Std m -> deliver t m
+>     ANote c k v d -> do
+>         deliver t     (NoteOn c k v)
+>         deliver (t+d) (NoteOff c k v)
+
+
+outputMidi plays all midi events that are waiting in this device's 
+priority queue whose time to play has come.
+
+> outputMidi :: OutputDeviceID -> IO ()
+> outputMidi devId = do
+>   (pChan, out, _stop) <- getOutDev devId
+>   let loop = do
+>         r <- peek pChan
+>         case r of
+>           Nothing     -> return ()
+>           Just (t,m)  -> do
+>             now <- getTimeNow
+>             if t <= now 
+>               then out (now, m) >> pop pChan >> loop
+>               else return ()
+>   loop
+>   return ()
+
+
+-------------------------------------------
+ | Midi Output for a complete Midi track | 
+-------------------------------------------
+
+When an entire Midi track is ready to be played, the playMidi function 
+may be more appropriate than deliverMidiEvent and outputMidi.
+
+playMidi will queue up the entire Midi track given to it and then close 
+the output device.
+
+> playMidi :: OutputDeviceID -> Midi -> IO ()
+> playMidi device midi@(Midi _ division _) = do
+>   let track = toRealTime division (toAbsTime (head (tracks (toSingleTrack midi))))
+>   out <- midiOutRealTime device
+>   case out of
+>     Nothing -> return ()
+>     Just (out, stop) -> do
+>       t0 <- getTimeNow 
+>       finally (playTrack t0 0 out track) stop
+>   where
+>     playTrack t0 t' out [] = out (t0 + t', TrackEnd)
+>     playTrack t0 t' out (e@(t, m) : s) = do
+>       out (t0 + t, m) 
+>       if isTrackEnd m 
+>         then return ()
+>         else playTrack t0 t out s
+
+
+---------------------
+ | midiOutRealTime | 
+---------------------
+
+The following two functions are used to open a device for Midi output.  
+They should only be called when the device hasn't yet been opened, and 
+they both return a ``play'' function and a ``stop'' function.
+
+Currently, midiOutRealTime' is used for Midi output for inidividual 
+Midi events, and midiOutRealTime is used for Midi output for a complete 
+Midi track.
+
+DWC Notes:
+I'm not entirely sure how they both work yet.  midiOutRealTime' 
+actually looks pretty straightforward in that it just creates the process 
+and stop functions and adds this device to the outPort device list.  The 
+process function will look up the device in the outPort device list, and 
+if it finds it, it writes the message to it.  The stop function removes 
+the device from the outPort list and closes it.
+
+On the other hand, midiOutRealTime spawns a new thread and does some 
+concurrent stuff.  Really, it looks similar, but I don't know when to 
+use one and when to use the other.
+
+> midiOutRealTime' :: OutputDeviceID -> IO (Maybe ((Time, Message) -> IO (), IO ()))
+> midiOutRealTime' odid@(OutputDeviceID devId) = do
+>   s <- openOutput devId 1  
+>   case s of
+>     Right e -> reportError "Unable to open output device in midiOutRealTime'" e >> return Nothing
+>     Left s -> do
+>       addPort outPort (odid, s)
+>       return $ Just (process odid, finalize odid)
+>   where
+>     process odid (t, msg) = do
+>       s <- lookupPort outPort odid
+>       case s of
+>         Nothing -> error ("midiOutRealTime': port " ++ show odid ++ " is not open for output")
+>         Just s -> do
+>           if isTrackEnd msg 
+>               then return ()
+>               else case midiEvent msg of
+>                 Just m  -> writeMsg s t m
+>                 Nothing -> return ()
+>     writeMsg s t m = do
+>               e <- writeShort s (PMEvent m (round (t * 1e3)))
+>               case e of
+>                 NoError -> return () 
+>                 _ -> reportError "midiOutRealTime'" e
+>     finalize odid = do
+>       s <- lookupPort outPort odid
+>       e <- maybe (return NoError) close s
+>       case e of
+>         NoError -> return () 
+>         _ -> reportError "midiOutRealTime'" e
+
+
+> midiOutRealTime :: OutputDeviceID -> IO (Maybe ((Time, Message) -> IO (), IO ()))
+> midiOutRealTime odid@(OutputDeviceID devId) = do
+>   s <- openOutput devId 1  
+>   case s of
+>     Right e -> reportError "outputMidi" e >> return Nothing
+>     Left s -> do
+>       ch <- atomically newTChan 
+>       wait <- newEmptyMVar
+>       fin <- newEmptyMVar
+>       forkIO (pump s ch wait fin)
+>       return $ Just (output s ch wait, stop ch fin)
+>   where
+>     stop ch fin = atomically (unGetTChan ch Nothing) >> takeMVar fin
+>     output s ch wait evt@(_, m) = do
+>       atomically $ writeTChan ch (Just evt)
+>       if isTrackEnd m then takeMVar wait else return ()
+>     pump s ch wait fin = loop
+>       where
+>         loop = do 
+>           e <- atomically $ readTChan ch
+>           case e of
+>             Nothing -> close s >> putMVar fin ()
+>             Just (t, msg) -> do
+>               now <- getTimeNow
+>               if (t > now + 5) 
+>                 then atomically (unGetTChan ch e) >> threadDelay 10000 >> loop
+>                 else do 
+>                   done <- process t msg
+>                   if done 
+>                     then waitUntil (t + 1)
+>                     else loop 
+>           where
+>             waitUntil t = do
+>               now <- getTimeNow
+>               if t > now 
+>                 then do
+>                   threadDelay $ min 10000 (round((t - now) * 1E6)) 
+>                   empty <- atomically $ isEmptyTChan ch
+>                   if empty 
+>                     then waitUntil t
+>                     else do
+>                       e <- atomically $ readTChan ch
+>                       case e of
+>                         Nothing -> finishup 
+>                         _ -> waitUntil t
+>                 else finishup
+>             finishup = putMVar wait () >> close s >> putMVar fin ()
+>             process t msg = if isTrackEnd msg 
+>               then return True 
+>               else case midiEvent msg of
+>                 Just m  -> writeMsg t m
+>                 Nothing -> return False 
+>             writeMsg t m = do
+>               e <- writeShort s (PMEvent m (round (t * 1e3)))
+>               case e of
+>                 NoError -> return False 
+>                 BufferOverflow -> putStrLn "overflow" >> threadDelay 10000 >> writeMsg t m
+>                 _ -> reportError "outputMidi" e >> return True 
+
+
+---------------------
+ | MIDI Conversion | 
+---------------------
+
+A conversion function from Codec.Midi Messages to PortMidi PMMsgs.
+
+> midiEvent :: Message -> Maybe PMMsg
+> midiEvent (NoteOff c p v)         = Just $ PMMsg (128 .|. (fromIntegral c .&. 0xF)) (fromIntegral p) (fromIntegral v)
+> midiEvent (NoteOn c p v)          = Just $ PMMsg (144 .|. (fromIntegral c .&. 0xF)) (fromIntegral p) (fromIntegral v)
+> midiEvent (KeyPressure c p pr)    = Just $ PMMsg (160 .|. (fromIntegral c .&. 0xF)) (fromIntegral p) (fromIntegral pr)
+> midiEvent (ControlChange c cn cv) = Just $ PMMsg (176 .|. (fromIntegral c .&. 0xF)) (fromIntegral cn) (fromIntegral cv)
+> midiEvent (ProgramChange c pn)    = Just $ PMMsg (192 .|. (fromIntegral c .&. 0xF)) (fromIntegral pn) 0
+> midiEvent (ChannelPressure c pr)  = Just $ PMMsg (208 .|. (fromIntegral c .&. 0xF)) (fromIntegral pr) 0
+> midiEvent (PitchWheel c pb)       = Just $ PMMsg (224 .|. (fromIntegral c .&. 0xF)) (fromIntegral lo) (fromIntegral hi)
+>  where (hi,lo) = (pb `shiftR` 8, pb .&. 0xFF)
+> midiEvent _ = Nothing 
+
+
+A conversion function from PortMidi PMMsgs to Codec.Midi Messages.
+
+> msgToMidi :: PMMsg -> Maybe Message
+> msgToMidi (PMMsg m d1 d2) = 
+>   let k = (m .&. 0xF0) `shiftR` 4
+>       c = fromIntegral (m .&. 0x0F)
+>   in case k of
+>     0x8 -> Just $ NoteOff c (fromIntegral d1) (fromIntegral d2)
+>     0x9 -> Just $ NoteOn  c (fromIntegral d1) (fromIntegral d2)
+>     0xA -> Just $ KeyPressure c (fromIntegral d1) (fromIntegral d2)
+>     0xB -> Just $ ControlChange c (fromIntegral d1) (fromIntegral d2)
+>     0xC -> Just $ ProgramChange c (fromIntegral d1)
+>     0xD -> Just $ ChannelPressure c (fromIntegral d1)
+>     0xE -> Just $ PitchWheel c (fromIntegral (d1 + d2 `shiftL` 8))
+>     0xF -> Nothing -- SysEx event not handled
+>     _   -> Nothing
+
+
+---------------------
+ | Error Reporting | 
+---------------------
+
+> reportError :: String -> PMError -> IO ()
+> reportError prompt e = do
+>   err <- getErrorText e 
+>   hPutStrLn stderr $ prompt ++ ": " ++  err
+
+
+
+
+
+----------------------
+ | Unused Functions | 
+----------------------
+
+> -- Prints all DeviceInfo found by getAllDevices.
+> printAllDeviceInfo :: IO ()
+> printAllDeviceInfo = do
+>   (indevs, outdevs) <- getAllDevices
+>   mapM_ (print . snd) indevs
+>   mapM_ (print . snd) outdevs
+
+-- Given whether the device is an input device and the device name, 
+-- returns the DeviceID.
+getDeviceId :: Bool -> String -> IO (Maybe DeviceID)
+getDeviceId isInput n = do
+  devs <- getAllDevices
+  return $ findIndex (\(_,d) -> name d == n && input d == isInput) devs
+
+> playTrackRealTime :: OutputDeviceID -> [(t, Message)] -> IO ()
+> playTrackRealTime device track = do
+>   out <- midiOutRealTime device
+>   case out of
+>     Nothing -> return ()
+>     Just (out, stop) -> finally (playTrack out track) stop
+>   where
+>     playTrack out [] = do
+>       t <- getTimeNow
+>       out (t, TrackEnd)
+>     playTrack out (e@(_, m) : s) = do
+>       t <- getTimeNow
+>       out (t, m) 
+>       if isTrackEnd m 
+>         then return ()
+>         else playTrack out s
+
+> {-
+>     ticksPerBeat = case division of
+>       TicksPerBeat n -> n
+>       TicksPerSecond mode nticks -> (256 - mode - 128) * nticks `div` 2 
+> -}
+
+> {-
+> runTrack tpb = runTrack' 0 0 120                 -- 120 beat/s is the default tempo
+>   where
+>     runTrack' t t0 bps ((_, TempoChange tempo) : l) = 
+>       let bps' = 1000000 `div` fromIntegral tempo  
+>       in runTrack' t t0 bps' l
+>     runTrack' t t0 bps ((t1, m) : l) = 
+>       let t' = t + 1000 * fromIntegral (t1 - t0) `div` (tpb * bps)
+>       in (t', m) : runTrack' t' t1 bps l
+>     runTrack' _ _ _ [] = [] 
+>
+> playTrack s ch t0 = playTrack' 0
+>   where
+>     playTrack' t [] = putStrLn "done" >> putMVar ch Nothing >> return (round (t * 1.0E3))
+>     playTrack' _ ((t, e):es) = putMVar ch (Just io) >> playTrack' t es 
+>       where 
+>         io = case midiEvent e of
+>           Just m  -> writeShort s (PMEvent m (t0 + round (t * 1.0E3)))
+>           Nothing -> return NoError 
+> -}
+
+> recordMidi :: DeviceID -> (Track Time -> IO ()) -> IO ()
+> recordMidi device f = do
+>   ch <- newChan
+>   final <- midiInRealTime device (\e -> writeChan ch e >> return False)
+>   case final of 
+>     Nothing  -> return () 
+>     Just fin -> do
+>       track <- getChanContents ch
+>       done <- newEmptyMVar 
+>       forkIO (f track >> putMVar done ())  
+>       putStrLn "Start recording, hit ENTER when you are done."
+>       getLine
+>       fin 
+>       takeMVar done
+>       return ()
+
+> midiInRealTime :: DeviceID -> ((Time, Message) -> IO Bool) -> IO (Maybe (IO ()))
+> midiInRealTime device callback = do
+>   r <- openInput device 
+>   case r of
+>     Right e -> reportError "midiInRealTime" e >> return Nothing 
+>     Left s -> do
+>       fin <- newEmptyMVar
+>       forkIO (loop Nothing s fin)
+>       return (Just (putMVar fin () >> putMVar fin ()))
+>   where
+>     loop start s fin = do
+>       done <- tryTakeMVar fin
+>       t <- getTimeNow
+>       case done of
+>         Just _ -> close s >> callback (t, TrackEnd) >> takeMVar fin >> return ()
+>         Nothing -> do
+>           e <- readEvents s
+>           case e of
+>             Right e -> if e == NoError 
+>               then threadDelay 1000 >> loop start s fin
+>               else do
+>                 reportError "midiInRealTime" e 
+>                 callback (t, TrackEnd)
+>                 return ()
+>             Left l -> do
+>               t <- getTimeNow
+>               sendEvts start t l
+>       where 
+>         sendEvts start now [] = loop start s fin
+>         sendEvts start now (e@(PMEvent m t):l) = do
+>           let t0 = maybe t id start
+>           case msgToMidi m of
+>             Just m' -> do
+>               done <- callback (now + fromIntegral (t - t0) / 1E3, m')
+>               if done then close s >> return () else sendEvts (Just t0) now l
+>             Nothing -> sendEvts (Just t0) now l
+
diff --git a/License b/License
--- a/License
+++ b/License
@@ -1,20 +1,20 @@
-Copyright (c) 2008-2015 Euterpea authors
-
-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.
+Copyright (c) 2008-2015 Euterpea authors
+
+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.
diff --git a/ReadMe.txt b/ReadMe.txt
--- a/ReadMe.txt
+++ b/ReadMe.txt
@@ -1,38 +1,38 @@
-Version 2.0.0
-Last modified: 31-Dec-2015
- _____      _                             
-|  ___|    | |                            
-| |__ _   _| |_ ___ _ __ _ __   ___  __ _ 
-|  __| | | | __/ _ \ '__| '_ \ / _ \/ _` |
-| |__| |_| | ||  __/ |  | |_) |  __/ (_| |
-\____/\__,_|\__\___|_|  | .__/ \___|\__,_|
-                        | |               
-                        |_|               
-
-Authors:
-  Paul Hudak
-  Eric Cheng
-  Hai (Paul) Liu
-  Donya Quick 
-  Dan Winograd-Cort 
-
-Maintainers:
-  Donya Quick <donyaquick@gmail.com>
-
-Euterpea is a domain-specific language embedded in Haskell for 
-computer music research, education, and development, providing 
-both note-level and signal-level abstractions.  It is a descendant 
-of Haskore and HasSound, and is intended for both educational purposes 
-as well as serious computer music applications.  Euterpea is a 
-wide-spectrum DSL, suitable for high-level music representation, 
-algorithmic composition, and analysis; mid-level concepts such as 
-MIDI; and low-level audio processing, sound synthesis, and instrument 
-design.  
-
-See License for licensing information.
-
-Please send questions, comments, and bug reports to Donya Quick:
-donyaquick@gmail.com
-
-Installation instructions are available at:
+Version 2.0.0
+Last modified: 31-Dec-2015
+ _____      _                             
+|  ___|    | |                            
+| |__ _   _| |_ ___ _ __ _ __   ___  __ _ 
+|  __| | | | __/ _ \ '__| '_ \ / _ \/ _` |
+| |__| |_| | ||  __/ |  | |_) |  __/ (_| |
+\____/\__,_|\__\___|_|  | .__/ \___|\__,_|
+                        | |               
+                        |_|               
+
+Authors:
+  Paul Hudak
+  Eric Cheng
+  Hai (Paul) Liu
+  Donya Quick 
+  Dan Winograd-Cort 
+
+Maintainers:
+  Donya Quick <donyaquick@gmail.com>
+
+Euterpea is a domain-specific language embedded in Haskell for 
+computer music research, education, and development, providing 
+both note-level and signal-level abstractions.  It is a descendant 
+of Haskore and HasSound, and is intended for both educational purposes 
+as well as serious computer music applications.  Euterpea is a 
+wide-spectrum DSL, suitable for high-level music representation, 
+algorithmic composition, and analysis; mid-level concepts such as 
+MIDI; and low-level audio processing, sound synthesis, and instrument 
+design.  
+
+See License for licensing information.
+
+Please send questions, comments, and bug reports to Donya Quick:
+donyaquick@gmail.com
+
+Installation instructions are available at:
 http://www.euterpea.com
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,51 +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
+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
 -}
