CreativePython 0.1.0__tar.gz → 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. creativepython-0.1.2/MANIFEST.in +5 -0
  2. creativepython-0.1.2/PKG-INFO +151 -0
  3. creativepython-0.1.2/README.md +102 -0
  4. {creativepython-0.1.0 → creativepython-0.1.2}/pyproject.toml +11 -7
  5. creativepython-0.1.2/src/CreativePython/_creativepythonSetup.py +134 -0
  6. creativepython-0.1.2/src/CreativePython/_soundfont.py +72 -0
  7. creativepython-0.1.2/src/CreativePython/examples/.DS_Store +0 -0
  8. creativepython-0.1.2/src/CreativePython/examples/ArvoPart.CantusInMemoriam.py +76 -0
  9. creativepython-0.1.2/src/CreativePython/examples/ConcretPH_Xenakis.py +41 -0
  10. creativepython-0.1.2/src/CreativePython/examples/DeepPurple.SmokeOnTheWater.py +67 -0
  11. creativepython-0.1.2/src/CreativePython/examples/JS_Bach.Canon.TriasHarmonica.BWV1072.py +77 -0
  12. creativepython-0.1.2/src/CreativePython/examples/JS_Bach.Canon_1.GoldbergGround.BWV1087.py +39 -0
  13. creativepython-0.1.2/src/CreativePython/examples/Mozart.MusikalischesWurfelspiel.py +101 -0
  14. creativepython-0.1.2/src/CreativePython/examples/PierreCage.StructuresPourDeuxChances.py +47 -0
  15. creativepython-0.1.2/src/CreativePython/examples/RGB_Display.py +73 -0
  16. creativepython-0.1.2/src/CreativePython/examples/TerryRiley.InC.py +34 -0
  17. creativepython-0.1.2/src/CreativePython/examples/arpeggiator1.py +30 -0
  18. creativepython-0.1.2/src/CreativePython/examples/arpeggiator2.py +32 -0
  19. creativepython-0.1.2/src/CreativePython/examples/autumnLeaves.py +77 -0
  20. creativepython-0.1.2/src/CreativePython/examples/axelF.py +26 -0
  21. creativepython-0.1.2/src/CreativePython/examples/biosignals.txt +3555 -0
  22. creativepython-0.1.2/src/CreativePython/examples/boids.py +267 -0
  23. creativepython-0.1.2/src/CreativePython/examples/brownianMelody.py +47 -0
  24. creativepython-0.1.2/src/CreativePython/examples/changesByTupac.py +23 -0
  25. creativepython-0.1.2/src/CreativePython/examples/clementine.py +140 -0
  26. creativepython-0.1.2/src/CreativePython/examples/continuousPitchInstrumentAudio.py +54 -0
  27. creativepython-0.1.2/src/CreativePython/examples/drumExample.py +22 -0
  28. creativepython-0.1.2/src/CreativePython/examples/drumMachinePattern1.py +50 -0
  29. creativepython-0.1.2/src/CreativePython/examples/drumsComeAlive.py +87 -0
  30. creativepython-0.1.2/src/CreativePython/examples/fibonacci.py +19 -0
  31. creativepython-0.1.2/src/CreativePython/examples/findPitchOctave.py +14 -0
  32. creativepython-0.1.2/src/CreativePython/examples/furElise.py +27 -0
  33. creativepython-0.1.2/src/CreativePython/examples/generativeMusic.py +47 -0
  34. creativepython-0.1.2/src/CreativePython/examples/goldenTree.py +55 -0
  35. creativepython-0.1.2/src/CreativePython/examples/guidoWordMusic.py +70 -0
  36. creativepython-0.1.2/src/CreativePython/examples/harmonicesMundi.py +67 -0
  37. creativepython-0.1.2/src/CreativePython/examples/harmonicesMundiRevisisted.py +65 -0
  38. creativepython-0.1.2/src/CreativePython/examples/harmonographLateral.py +47 -0
  39. creativepython-0.1.2/src/CreativePython/examples/harmonographRotary.py +70 -0
  40. creativepython-0.1.2/src/CreativePython/examples/iPianoBlackDown.png +0 -0
  41. creativepython-0.1.2/src/CreativePython/examples/iPianoOctave.png +0 -0
  42. creativepython-0.1.2/src/CreativePython/examples/iPianoParallel.py +73 -0
  43. creativepython-0.1.2/src/CreativePython/examples/iPianoSimple.py +86 -0
  44. creativepython-0.1.2/src/CreativePython/examples/iPianoWhiteCenterDown.png +0 -0
  45. creativepython-0.1.2/src/CreativePython/examples/iPianoWhiteLeftDown.png +0 -0
  46. creativepython-0.1.2/src/CreativePython/examples/iPianoWhiteRightDown.png +0 -0
  47. creativepython-0.1.2/src/CreativePython/examples/midiIn1.py +14 -0
  48. creativepython-0.1.2/src/CreativePython/examples/midiIn2.py +13 -0
  49. creativepython-0.1.2/src/CreativePython/examples/midiIn3.py +25 -0
  50. creativepython-0.1.2/src/CreativePython/examples/midiOut.a.py +12 -0
  51. creativepython-0.1.2/src/CreativePython/examples/midiOut.b.py +14 -0
  52. creativepython-0.1.2/src/CreativePython/examples/midiSynthesizer.py +34 -0
  53. creativepython-0.1.2/src/CreativePython/examples/midiSynthesizer2.py +55 -0
  54. creativepython-0.1.2/src/CreativePython/examples/moondog-bird_slament.wav +0 -0
  55. creativepython-0.1.2/src/CreativePython/examples/musicalSphere.py +178 -0
  56. creativepython-0.1.2/src/CreativePython/examples/note.py +55 -0
  57. creativepython-0.1.2/src/CreativePython/examples/octoplus.py +56 -0
  58. creativepython-0.1.2/src/CreativePython/examples/oscIn1.py +13 -0
  59. creativepython-0.1.2/src/CreativePython/examples/oscIn2.py +19 -0
  60. creativepython-0.1.2/src/CreativePython/examples/pentatonicMelody.py +33 -0
  61. creativepython-0.1.2/src/CreativePython/examples/pianoPhase.py +28 -0
  62. creativepython-0.1.2/src/CreativePython/examples/pianoRollGenerator.py +43 -0
  63. creativepython-0.1.2/src/CreativePython/examples/playNote.py +7 -0
  64. creativepython-0.1.2/src/CreativePython/examples/proteinMusic.py +59 -0
  65. creativepython-0.1.2/src/CreativePython/examples/randomCircles.py +36 -0
  66. creativepython-0.1.2/src/CreativePython/examples/randomCirclesThroughMidiInput.py +52 -0
  67. creativepython-0.1.2/src/CreativePython/examples/randomCirclesTimed.py +67 -0
  68. creativepython-0.1.2/src/CreativePython/examples/retrograde.a.py +22 -0
  69. creativepython-0.1.2/src/CreativePython/examples/retrograde.b.py +36 -0
  70. creativepython-0.1.2/src/CreativePython/examples/retrograde.c.py +41 -0
  71. creativepython-0.1.2/src/CreativePython/examples/rowYourBoat.py +61 -0
  72. creativepython-0.1.2/src/CreativePython/examples/scaleTutor.py +27 -0
  73. creativepython-0.1.2/src/CreativePython/examples/sierpinskiTriangle.py +52 -0
  74. creativepython-0.1.2/src/CreativePython/examples/simpleButtonInstrument.py +34 -0
  75. creativepython-0.1.2/src/CreativePython/examples/simpleCircleInstrument.py +70 -0
  76. creativepython-0.1.2/src/CreativePython/examples/sineMelody.py +23 -0
  77. creativepython-0.1.2/src/CreativePython/examples/sineMelodyPlus.py +28 -0
  78. creativepython-0.1.2/src/CreativePython/examples/sliderControl.py +66 -0
  79. creativepython-0.1.2/src/CreativePython/examples/sonifyBiosignals.py +79 -0
  80. creativepython-0.1.2/src/CreativePython/examples/sonifyImage.py +109 -0
  81. creativepython-0.1.2/src/CreativePython/examples/soundscapeLoutrakiSunset.jpg +0 -0
  82. creativepython-0.1.2/src/CreativePython/examples/stringQuartet.py +36 -0
  83. creativepython-0.1.2/src/CreativePython/examples/textMusic.py +62 -0
  84. creativepython-0.1.2/src/CreativePython/examples/theWayItIs.py +33 -0
  85. creativepython-0.1.2/src/CreativePython/examples/themeAndVariations.py +64 -0
  86. creativepython-0.1.2/src/CreativePython/examples/throwingDice.py +37 -0
  87. creativepython-0.1.2/src/CreativePython/examples/windChimes.py +56 -0
  88. creativepython-0.1.2/src/CreativePython/examples/zipfMetrics.py +81 -0
  89. creativepython-0.1.2/src/CreativePython/resources/.DS_Store +0 -0
  90. creativepython-0.1.2/src/CreativePython/resources/550973__luizguilherme_a__clean-guitarr-riff.mp3 +0 -0
  91. creativepython-0.1.2/src/CreativePython/resources/chopper.jpg +0 -0
  92. creativepython-0.1.2/src/CreativePython/resources/de-brazzas-monkey.jpg +0 -0
  93. creativepython-0.1.2/src/CreativePython.egg-info/PKG-INFO +151 -0
  94. creativepython-0.1.2/src/CreativePython.egg-info/SOURCES.txt +108 -0
  95. {creativepython-0.1.0 → creativepython-0.1.2}/src/CreativePython.egg-info/requires.txt +0 -3
  96. {creativepython-0.1.0 → creativepython-0.1.2}/src/CreativePython.egg-info/top_level.txt +1 -3
  97. {creativepython-0.1.0 → creativepython-0.1.2}/src/gui.py +116 -98
  98. creativepython-0.1.2/src/iannix.py +455 -0
  99. {creativepython-0.1.0 → creativepython-0.1.2}/src/image.py +18 -2
  100. creativepython-0.1.2/src/markov.py +543 -0
  101. {creativepython-0.1.0 → creativepython-0.1.2}/src/midi.py +179 -130
  102. {creativepython-0.1.0 → creativepython-0.1.2}/src/music.py +172 -137
  103. {creativepython-0.1.0 → creativepython-0.1.2}/src/osc.py +18 -6
  104. {creativepython-0.1.0 → creativepython-0.1.2}/src/timer.py +12 -11
  105. {creativepython-0.1.0 → creativepython-0.1.2}/src/zipf.py +170 -178
  106. creativepython-0.1.0/MANIFEST.in +0 -1
  107. creativepython-0.1.0/PKG-INFO +0 -189
  108. creativepython-0.1.0/README.md +0 -137
  109. creativepython-0.1.0/src/CreativePython.egg-info/PKG-INFO +0 -189
  110. creativepython-0.1.0/src/CreativePython.egg-info/SOURCES.txt +0 -22
  111. creativepython-0.1.0/src/CreativePython.egg-info/entry_points.txt +0 -3
  112. creativepython-0.1.0/src/creativepython_setup.py +0 -85
  113. creativepython-0.1.0/src/iannix.py +0 -383
  114. creativepython-0.1.0/src/markov.py +0 -263
  115. {creativepython-0.1.0 → creativepython-0.1.2}/LICENSE +0 -0
  116. {creativepython-0.1.0 → creativepython-0.1.2}/setup.cfg +0 -0
  117. {creativepython-0.1.0/src → creativepython-0.1.2/src/CreativePython}/__init__.py +0 -0
  118. {creativepython-0.1.0 → creativepython-0.1.2}/src/CreativePython.egg-info/dependency_links.txt +0 -0
  119. {creativepython-0.1.0 → creativepython-0.1.2}/src/_RealtimeAudioPlayer.py +0 -0
@@ -0,0 +1,5 @@
1
+ recursive-include src/CreativePython/resources *
2
+ recursive-include src/CreativePython/examples *
3
+ recursive-include src/CreativePython/scripts *
4
+ recursive-exclude */.DS_Store
5
+ recursive-exclude */__pycache__/*
@@ -0,0 +1,151 @@
1
+ Metadata-Version: 2.4
2
+ Name: CreativePython
3
+ Version: 0.1.2
4
+ Summary: A Python-based software environment for developing algorithmic art projects.
5
+ Author-email: "Dr. Bill Manaris" <manaris@cofc.edu>, Taj Ballinger <ballingertj@g.cofc.edu>, Trevor Ritchie <ritchiets@g.cofc.edu>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2025 Dr. Bill Manaris
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://jythonmusic.me
29
+ Keywords: music,audio,midi,learning,algorithmic art,algoart
30
+ Classifier: Programming Language :: Python :: 3
31
+ Classifier: Operating System :: OS Independent
32
+ Classifier: License :: OSI Approved :: MIT License
33
+ Requires-Python: >=3.9
34
+ Description-Content-Type: text/markdown
35
+ License-File: LICENSE
36
+ Requires-Dist: tinysoundfont>=0.3.6
37
+ Requires-Dist: osc4py3>=1.0.8
38
+ Requires-Dist: mido>=1.3.3
39
+ Requires-Dist: PySide6>=6.9.1
40
+ Requires-Dist: sounddevice>=0.5.2
41
+ Requires-Dist: soundfile>=0.13.1
42
+ Requires-Dist: tqdm>=4.67.1
43
+ Requires-Dist: pooch>=1.8
44
+ Requires-Dist: pypianoroll>=1.0
45
+ Provides-Extra: dev
46
+ Requires-Dist: build; extra == "dev"
47
+ Requires-Dist: twine; extra == "dev"
48
+ Dynamic: license-file
49
+
50
+ # CreativePython
51
+
52
+ CreativePython is a Python-based software environment for learning and developing algorithmic art projects. It mirrors the [JythonMusic API](https://jythonmusic.me/api-reference/), and is powered by [PySide6](https://wiki.qt.io/Qt_for_Python) and [portaudio](http://portaudio.com/).
53
+
54
+ CreativePython is distributed under the MIT License.
55
+
56
+ - [Homepage](https://jythonmusic.me/)
57
+ - [Download All Examples [ZIP]](https://www.dropbox.com/scl/fo/rvc8m8pt4m0281qn0t4oi/AO2Y0W2qOrOcurlQmLa7M54?rlkey=0sf80bmov135tc85dk9k7ats6&dl=1)
58
+
59
+ This package is still under development.
60
+
61
+ # Beginner Installation (IDLE)
62
+
63
+ 1. Download and install the latest version of [Python](https://www.python.org/downloads/).
64
+
65
+ 2. Download the [CreativePython Setup Script](https://www.dropbox.com/scl/fi/253bvfqsf0ij3rmza88q5/_creativepythonSetup.py?rlkey=iu4y4u8pujltgfx6kbjmodu9m&dl=1).
66
+
67
+ 3. Open `creativePythonSetup.py` with IDLE, Python's Integrated Development Learning Environment.
68
+
69
+ 4. From the IDLE toolbar, select `Run`, then `Run Module`.
70
+
71
+ 5. CreativePython will check for its requirements on your system, download any missing requirements, and install its libraries.
72
+
73
+ 6. When you see `[CreativePython Setup]: CreativePython installed successfully.`, you're all done! You're ready to start using CreativePython.
74
+
75
+ **NOTE**: You can use the setup script in any Python3 environment - not just IDLE!
76
+
77
+ # Custom Installation
78
+
79
+ ## Windows
80
+
81
+ Install CreativePython using `pip`:
82
+
83
+ ```
84
+ python -m pip install CreativePython
85
+ ```
86
+
87
+ ## MacOS
88
+
89
+ Use [Homebrew](https://brew.sh/) to install the prerequisite [portaudio](http://portaudio.com/) library, then install CreativePython using `pip`:
90
+
91
+ ```
92
+ brew install portaudio
93
+ pip install CreativePython
94
+ ```
95
+
96
+ ## Linux
97
+
98
+ Use apt, or your preferred package manager, to install the prerequisite [portaudio](http://portaudio.com/) library, then install CreativePython using `pip`:
99
+
100
+ ```
101
+ sudo apt-get portaudio
102
+ pip install CreativePython
103
+ ```
104
+
105
+ # Using CreativePython
106
+
107
+ ## Importing Libraries
108
+
109
+ CreativePython's core modules are the `music`, `gui`, `image`, `timer`, `osc`, and `midi` libraries. You can import these libraries into your python code using:
110
+
111
+ ```
112
+ import music
113
+ from music import *
114
+ from music import Note, Play, C4, HN
115
+ ```
116
+
117
+ Or a similar statement. CreativePython includes a number of useful constants, so we recommend using wildcard imports like `from music import *`.
118
+
119
+ **NOTE**: The first time you import `music`, CreativePython will ask permission to download a high-quality soundfont (FluidR3 G2-2.sf2) for you. You should only have to do this once.
120
+
121
+ ## Running CreativePython programs
122
+
123
+ CreativePython is designed for use in Python's Interactive Mode. To use Interactive Mode, enter a command like:
124
+
125
+ ```
126
+ python -i <filename>.py
127
+ ```
128
+
129
+ ## Example
130
+
131
+ Download [playNote.py](https://www.dropbox.com/scl/fi/z6rkjy4xnofmg0t899se3/playNote.py?rlkey=o3t8c91ne6agj2lqf2aupl8m5&dl=1):
132
+
133
+ ```
134
+ # playNote.py
135
+ # Demonstrates how to play a single note.
136
+
137
+ from music import * # import music library
138
+
139
+ note = Note(C4, HN) # create a middle C half note
140
+ Play.midi(note) # and play it!
141
+ ```
142
+
143
+ In a terminal, run the code in interactive mode:
144
+
145
+ ```
146
+ python -i playNote.py
147
+ ```
148
+
149
+ If this is the first time you've used CreativePython, it will ask to download a soundfont.
150
+
151
+ After you do, you should hear a single C4 half-note.
@@ -0,0 +1,102 @@
1
+ # CreativePython
2
+
3
+ CreativePython is a Python-based software environment for learning and developing algorithmic art projects. It mirrors the [JythonMusic API](https://jythonmusic.me/api-reference/), and is powered by [PySide6](https://wiki.qt.io/Qt_for_Python) and [portaudio](http://portaudio.com/).
4
+
5
+ CreativePython is distributed under the MIT License.
6
+
7
+ - [Homepage](https://jythonmusic.me/)
8
+ - [Download All Examples [ZIP]](https://www.dropbox.com/scl/fo/rvc8m8pt4m0281qn0t4oi/AO2Y0W2qOrOcurlQmLa7M54?rlkey=0sf80bmov135tc85dk9k7ats6&dl=1)
9
+
10
+ This package is still under development.
11
+
12
+ # Beginner Installation (IDLE)
13
+
14
+ 1. Download and install the latest version of [Python](https://www.python.org/downloads/).
15
+
16
+ 2. Download the [CreativePython Setup Script](https://www.dropbox.com/scl/fi/253bvfqsf0ij3rmza88q5/_creativepythonSetup.py?rlkey=iu4y4u8pujltgfx6kbjmodu9m&dl=1).
17
+
18
+ 3. Open `creativePythonSetup.py` with IDLE, Python's Integrated Development Learning Environment.
19
+
20
+ 4. From the IDLE toolbar, select `Run`, then `Run Module`.
21
+
22
+ 5. CreativePython will check for its requirements on your system, download any missing requirements, and install its libraries.
23
+
24
+ 6. When you see `[CreativePython Setup]: CreativePython installed successfully.`, you're all done! You're ready to start using CreativePython.
25
+
26
+ **NOTE**: You can use the setup script in any Python3 environment - not just IDLE!
27
+
28
+ # Custom Installation
29
+
30
+ ## Windows
31
+
32
+ Install CreativePython using `pip`:
33
+
34
+ ```
35
+ python -m pip install CreativePython
36
+ ```
37
+
38
+ ## MacOS
39
+
40
+ Use [Homebrew](https://brew.sh/) to install the prerequisite [portaudio](http://portaudio.com/) library, then install CreativePython using `pip`:
41
+
42
+ ```
43
+ brew install portaudio
44
+ pip install CreativePython
45
+ ```
46
+
47
+ ## Linux
48
+
49
+ Use apt, or your preferred package manager, to install the prerequisite [portaudio](http://portaudio.com/) library, then install CreativePython using `pip`:
50
+
51
+ ```
52
+ sudo apt-get portaudio
53
+ pip install CreativePython
54
+ ```
55
+
56
+ # Using CreativePython
57
+
58
+ ## Importing Libraries
59
+
60
+ CreativePython's core modules are the `music`, `gui`, `image`, `timer`, `osc`, and `midi` libraries. You can import these libraries into your python code using:
61
+
62
+ ```
63
+ import music
64
+ from music import *
65
+ from music import Note, Play, C4, HN
66
+ ```
67
+
68
+ Or a similar statement. CreativePython includes a number of useful constants, so we recommend using wildcard imports like `from music import *`.
69
+
70
+ **NOTE**: The first time you import `music`, CreativePython will ask permission to download a high-quality soundfont (FluidR3 G2-2.sf2) for you. You should only have to do this once.
71
+
72
+ ## Running CreativePython programs
73
+
74
+ CreativePython is designed for use in Python's Interactive Mode. To use Interactive Mode, enter a command like:
75
+
76
+ ```
77
+ python -i <filename>.py
78
+ ```
79
+
80
+ ## Example
81
+
82
+ Download [playNote.py](https://www.dropbox.com/scl/fi/z6rkjy4xnofmg0t899se3/playNote.py?rlkey=o3t8c91ne6agj2lqf2aupl8m5&dl=1):
83
+
84
+ ```
85
+ # playNote.py
86
+ # Demonstrates how to play a single note.
87
+
88
+ from music import * # import music library
89
+
90
+ note = Note(C4, HN) # create a middle C half note
91
+ Play.midi(note) # and play it!
92
+ ```
93
+
94
+ In a terminal, run the code in interactive mode:
95
+
96
+ ```
97
+ python -i playNote.py
98
+ ```
99
+
100
+ If this is the first time you've used CreativePython, it will ask to download a soundfont.
101
+
102
+ After you do, you should hear a single C4 half-note.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "CreativePython"
7
- version = "0.1.0"
7
+ version = "0.1.2"
8
8
  description = "A Python-based software environment for developing algorithmic art projects."
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -24,23 +24,27 @@ dependencies = [
24
24
  "tinysoundfont>=0.3.6",
25
25
  "osc4py3>=1.0.8",
26
26
  "mido>=1.3.3",
27
- "numpy>=2.3.2",
28
- "pyaudio>=0.2.14",
29
27
  "PySide6>=6.9.1",
30
28
  "sounddevice>=0.5.2",
31
29
  "soundfile>=0.13.1",
32
30
  "tqdm>=4.67.1",
33
31
  "pooch>=1.8",
34
- "platformdirs>=4.2",
35
32
  "pypianoroll>=1.0"
36
33
  ]
37
34
 
38
35
  [project.urls]
39
36
  Homepage = "https://jythonmusic.me"
40
37
 
41
- [project.scripts]
42
- cp-setup = "creativepython_setup:run"
43
- cp-test = "creativepython_setup:playNote"
38
+ [tool.setuptools.package-data]
39
+ CreativePython = [
40
+ "examples/*",
41
+ "scripts/*",
42
+ "resources/*",
43
+ # "bin/windows/*",
44
+ # "bin/macos/*",
45
+ # "licenses/*",
46
+ # "wheels/*.whl"
47
+ ]
44
48
 
45
49
  [project.optional-dependencies]
46
50
  dev = ["build", "twine"]
@@ -0,0 +1,134 @@
1
+ # creativePythonSetup.py
2
+ # This script installs CreativePython, and any missing system requirements
3
+ # MacOS: Portaudio (installed via Homebrew)
4
+ # Win64: None
5
+ # Linux: None
6
+
7
+ import os, platform, shutil, subprocess
8
+ import sys, pathlib
9
+
10
+ debug = True
11
+ LOG_PATH = str(pathlib.Path.home() / "Desktop" / "creativepython-install.log")
12
+
13
+ class SetupError(Exception):
14
+ pass
15
+
16
+ def _print(text):
17
+ print(f"[CreativePython Setup]: {text}")
18
+
19
+ def _run(cmd, env=os.environ, log=None, check=True):
20
+ if debug: _print(f"Running: {' '.join(cmd)}")
21
+ result = subprocess.run(
22
+ cmd,
23
+ check=False,
24
+ text=True,
25
+ stdout=subprocess.PIPE,
26
+ stderr=subprocess.PIPE,
27
+ env=env
28
+ )
29
+
30
+ if log:
31
+ log.write(f"\n$ {' '.join(cmd)}\n")
32
+ if result.stdout: log.write(result.stdout)
33
+ if result.stderr: log.write(f"\n[stderr]\n{result.stderr}")
34
+ if check and result.returncode != 0:
35
+ raise SetupError(f"Command failed: {' '.join(cmd)} (exit {result.returncode})")
36
+
37
+ return result
38
+
39
+
40
+ def _findHomebrew():
41
+ if debug: _print("Looking for Homebrew...")
42
+ brew = shutil.which("brew") # check if brew is on PATH
43
+
44
+ if not brew:
45
+ if debug: _print("Didn't find Homebrew, checking other locations...")
46
+ # brew not on PATH, so check common install locations
47
+ commonBins = ["/opt/homebrew/bin/brew", "/usr/local/bin/brew"]
48
+ i = 0
49
+ while not brew and i < len(commonBins):
50
+ if os.path.exists(commonBins[i]): # bin is installed, so add it to PATH
51
+ os.environ["PATH"] = commonBins[i] + os.pathsep + os.environ.get("PATH", "")
52
+ brew = commonBins[i]
53
+ i = i + 1
54
+
55
+ if debug:
56
+ if brew: _print(f"Homebrew found at {brew}")
57
+ else: _print("Failed to find Homebrew...")
58
+
59
+ return brew
60
+
61
+
62
+ def _installHomebrew():
63
+ if debug: _print("Installing Homebrew...")
64
+ env = dict(os.environ)
65
+ env["NONINTERACTIVE"] = "1"
66
+
67
+ _run('/bin/bash', '-c', '"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', env=env) # install homebrew
68
+
69
+ brew = _findHomebrew() # and verify installation
70
+ if not brew:
71
+ raise SetupError("Homebrew installation failed. Ensure you have internet access and try again.")
72
+
73
+ if debug: _print("Homebrew installed successfully.")
74
+ return brew
75
+
76
+
77
+ def _isBrewPackageInstalled(package, brew=None):
78
+ if debug: _print(f"Looking for {package}...")
79
+ if not brew: brew = _findHomebrew()
80
+
81
+ isInstalled = subprocess.run(
82
+ [brew, "list", "--versions", package],
83
+ stdout=subprocess.DEVNULL,
84
+ stderr=subprocess.DEVNULL
85
+ ).returncode == 0
86
+
87
+ if debug:
88
+ if isInstalled: _print(f"{package} found.")
89
+ else: _print(f"Failed to find {package}...")
90
+
91
+ return isInstalled
92
+
93
+
94
+ def _installBrewPackage(package, brew=None):
95
+ if debug: _print(f"Installing {package}...")
96
+ if not brew: brew = _findHomebrew()
97
+
98
+ _run([brew, 'update']) # update Homebrew...
99
+ _run([brew, 'install', package]) # ... and install package
100
+
101
+ if not _isBrewPackageInstalled(package): # verify installation
102
+ raise SetupError(f"{package} installation failed. Ensure you have internet access and try again.")
103
+
104
+ if debug: _print(f"{package} installed successfully.")
105
+
106
+
107
+ def _installCreativePython():
108
+ if debug: _print(f"Installing CreativePython... (log: {LOG_PATH})")
109
+
110
+ with open(LOG_PATH, "w", encoding="utf-8", errors="replace") as log:
111
+ # find the python interpreter location
112
+ py = sys.executable.replace("pythonw.exe", "python.exe")
113
+
114
+ _run([py, '-m', 'pip', 'install', '--upgrade', 'pip', 'setuptools', 'wheel'], log=log, check=False)
115
+ _run([py, '-m', 'pip', 'install', '--user', 'CreativePython'], log=log)
116
+
117
+ if debug: _print("CreativePython installed successfully.")
118
+
119
+ import music # import music to trigger soundfont download
120
+
121
+
122
+
123
+ if __name__ == "__main__":
124
+
125
+ if platform.system() == "Darwin": # check for MacOS...
126
+ brew = _findHomebrew()
127
+ if not brew: # ... check for Homebrew...
128
+ brew = _installHomebrew() # ... no, so install it
129
+
130
+ if not _isBrewPackageInstalled("portaudio", brew): # next, check for portaudio ...
131
+ _installBrewPackage("portaudio", brew) # ... no, so install it
132
+
133
+ # now, requirements have been met
134
+ _installCreativePython()
@@ -0,0 +1,72 @@
1
+ from pathlib import Path
2
+ from platformdirs import user_data_dir
3
+ from pooch import retrieve
4
+ import os
5
+
6
+ APP = "CreativePython"
7
+ ORG = "CofC"
8
+
9
+ SOUNDFONT_NAME = "default.sf2"
10
+ CACHE_DIR = Path(user_data_dir(APP, ORG)) / "SoundFonts"
11
+ SOUNDFONT_PATH = CACHE_DIR / SOUNDFONT_NAME
12
+
13
+ SF2_URL = "https://www.dropbox.com/s/xixtvox70lna6m2/FluidR3%20GM2-2.SF2?dl=1"
14
+ SF2_SHA256 = "2ae766ab5c5deb6f7fffacd6316ec9f3699998cce821df3163e7b10a78a64066"
15
+
16
+ ##### SOUNDFONTS #####
17
+
18
+ def _findSoundfont(candidate=None):
19
+ """
20
+ Finds a soundfont 'default.sf2' and returns its location.
21
+ 'candidate' can be another path containing the soundfont.
22
+ """
23
+ candidates = []
24
+ soundfontPath = None
25
+
26
+ # path as argument?
27
+ if candidate:
28
+ candidates.append(Path(candidate))
29
+
30
+ # path as environment variable?
31
+ env = os.getenv("CREATIVEPYTHON_SOUNDFONT")
32
+ if env:
33
+ candidates.append(Path(env))
34
+
35
+ # default soundfont location
36
+ candidates+= [SOUNDFONT_PATH, Path.home() / "SoundFonts" / SOUNDFONT_NAME]
37
+
38
+ # find first valid candidate
39
+ i = 0
40
+ while soundfontPath is None and i < len(candidates):
41
+ c = candidates[i]
42
+ if c and c.exists():
43
+ soundfontPath = str(c)
44
+
45
+ return soundfontPath
46
+
47
+
48
+ def _downloadSoundfont(destination=SOUNDFONT_PATH):
49
+ """
50
+ Downloads FluidR3 GM2-2 to given destination as 'default.sf2'
51
+ """
52
+ # create parent directory
53
+ destination.parent.mkdir(parents=True, exist_ok=True)
54
+ # download soundfont
55
+ path = retrieve(
56
+ url=SF2_URL,
57
+ known_hash=f"sha256:{SF2_SHA256}",
58
+ progressbar=True,
59
+ fname=destination.name,
60
+ path=str(destination.parent)
61
+ )
62
+ return path
63
+
64
+
65
+ def _installSoundfont():
66
+ soundfontPath = _findSoundfont()
67
+ if not soundfontPath:
68
+ print(f"[CreativePython Setup]: Downloading MIDI Soundfont...")
69
+ _soundfontPath = _downloadSoundfont()
70
+ print(f"[CreativePython Setup]: Soundfont downloaded to {_soundfontPath}")
71
+
72
+ return _soundfontPath
@@ -0,0 +1,76 @@
1
+ # ArvoPart.CantusInMemoriam.py
2
+ #
3
+ # Recreates a variation of Arvo Part's "Cantus in Memoriam Benjamin
4
+ # Britten" (1977) for string orchestra and bell, using Mod functions.
5
+
6
+ from music import *
7
+
8
+ # musical parameters
9
+ repetitions = 2 # length of piece
10
+ tempo = 112 # tempo of piece
11
+ bar = WN+HN # length of a measure
12
+
13
+ # create musical data structure
14
+ cantusScore = Score("Cantus in Memoriam Benjamin Britten", tempo)
15
+
16
+ bellPart = Part(TUBULAR_BELLS, 0)
17
+ violinPart = Part(VIOLIN, 1)
18
+
19
+ # bell
20
+ bellPitches = [REST, A4, REST, REST, A4, REST, REST, A4]
21
+ bellDurations = [bar/2, bar/2, bar, bar/2, bar/2, bar, bar/2, bar/2]
22
+
23
+ bellPhrase = Phrase(0.0)
24
+ bellPhrase.addNoteList(bellPitches, bellDurations)
25
+ bellPart.addPhrase(bellPhrase)
26
+
27
+ # violin - define descending aeolian scale and rhythms
28
+ pitches = [A5, G5, F5, E5, D5, C5, B4, A4]
29
+ durations = [HN, QN, HN, QN, HN, QN, HN, QN]
30
+
31
+ # violin 1
32
+ violin1Phrase = Phrase(bar * 6.5) # start after 6 and 1/2 measures
33
+ violin1Phrase.addNoteList(pitches, durations)
34
+
35
+ # violin 2
36
+ violin2Phrase = violin1Phrase.copy()
37
+ violin2Phrase.setStartTime(bar * 7.0) # start after 7 measures
38
+ Mod.elongate(violin2Phrase, 2.0) # double durations
39
+ Mod.transpose(violin2Phrase, -12) # an octave lower
40
+
41
+ # violin 3
42
+ violin3Phrase = violin2Phrase.copy()
43
+ violin3Phrase.setStartTime(bar * 8.0) # start after 8 measures
44
+ Mod.elongate(violin3Phrase, 2.0) # double durations
45
+ Mod.transpose(violin3Phrase, -12) # an octave lower
46
+
47
+ # violin 4
48
+ violin4Phrase = violin3Phrase.copy()
49
+ violin4Phrase.setStartTime(bar * 10.0) # start after 10 measures
50
+ Mod.elongate(violin4Phrase, 2.0) # double durations
51
+ Mod.transpose(violin4Phrase, -12) # an octave lower
52
+
53
+ # repeat phrases enough times
54
+ Mod.repeat(violin1Phrase, 8 * repetitions)
55
+ Mod.repeat(violin2Phrase, 4 * repetitions)
56
+ Mod.repeat(violin3Phrase, 2 * repetitions)
57
+ Mod.repeat(violin4Phrase, repetitions)
58
+
59
+ # violin part
60
+ violinPart.addPhrase(violin1Phrase)
61
+ violinPart.addPhrase(violin2Phrase)
62
+ violinPart.addPhrase(violin3Phrase)
63
+ violinPart.addPhrase(violin4Phrase)
64
+
65
+ # score
66
+ cantusScore.addPart(bellPart)
67
+ cantusScore.addPart(violinPart)
68
+
69
+ # fade in, and fade out
70
+ Mod.fadeIn(cantusScore, WN)
71
+ Mod.fadeOut(cantusScore, WN * 12)
72
+
73
+ # view, play, and write
74
+ View.sketch(cantusScore)
75
+ Play.midi(cantusScore)
76
+ Write.midi (cantusScore, "ArvoPart.CantusInMemoriam.mid")
@@ -0,0 +1,41 @@
1
+ # ConcretPH_Xenakis.py
2
+ #
3
+ # A short example which generates a random cloud texture
4
+ # inspired by Iannis Xenakis's 'Concret PH' composition
5
+ #
6
+ # see http://en.wikipedia.org/wiki/Concret_PH
7
+
8
+ from music import *
9
+ from random import *
10
+
11
+ # constants for controlling musical parameters
12
+ cloudWidth = 64 # length of piece (in quarter notes)
13
+ cloudDensity = 23.44 # how dense the cloud may be
14
+ particleDuration = 0.2 # how long each sound particle may be
15
+ numParticles = int(cloudDensity * cloudWidth) # how many particles
16
+
17
+ part = Part(BREATHNOISE)
18
+
19
+ # make particles (notes) and add them to cloud (part)
20
+ for i in range(numParticles):
21
+
22
+ # create note with random attributes
23
+ pitch = randint(0, 127) # pick from 0 to 127
24
+ duration = random() * particleDuration # 0 to particleDuration
25
+ dynamic = randint(0, 127) # pick from silent to loud
26
+ panning = random() # pick from left to right
27
+ note = Note(pitch, duration, dynamic, panning) # create note
28
+
29
+ # now, place it somewhere in the cloud (time continuum)
30
+ startTime = random() * cloudWidth # pick from 0 to end of piece
31
+ phrase = Phrase(startTime) # create phrase with this start time
32
+ phrase.addNote(note) # add the above note
33
+ part.addPhrase(phrase) # and add both to the part
34
+ # now, all notes have been created
35
+
36
+ # add some elegance to the end
37
+ Mod.fadeOut(part, 20)
38
+
39
+ View.show(part)
40
+ Play.midi(part)
41
+ Write.midi(part, "ConcretPh.mid")