soundkit 1.0.0__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.
- soundkit-1.0.0/LICENSE +21 -0
- soundkit-1.0.0/PKG-INFO +538 -0
- soundkit-1.0.0/README.md +509 -0
- soundkit-1.0.0/pyproject.toml +37 -0
- soundkit-1.0.0/setup.cfg +4 -0
- soundkit-1.0.0/src/soundkit/__init__.py +31 -0
- soundkit-1.0.0/src/soundkit/constants.py +35 -0
- soundkit-1.0.0/src/soundkit/core/__init__.py +5 -0
- soundkit-1.0.0/src/soundkit/core/chords.py +69 -0
- soundkit-1.0.0/src/soundkit/core/notes.py +145 -0
- soundkit-1.0.0/src/soundkit/core/scales.py +60 -0
- soundkit-1.0.0/src/soundkit/exceptions.py +23 -0
- soundkit-1.0.0/src/soundkit/utils/__init__.py +11 -0
- soundkit-1.0.0/src/soundkit/utils/converters.py +45 -0
- soundkit-1.0.0/src/soundkit/utils/validators.py +38 -0
- soundkit-1.0.0/src/soundkit.egg-info/PKG-INFO +538 -0
- soundkit-1.0.0/src/soundkit.egg-info/SOURCES.txt +21 -0
- soundkit-1.0.0/src/soundkit.egg-info/dependency_links.txt +1 -0
- soundkit-1.0.0/src/soundkit.egg-info/top_level.txt +1 -0
- soundkit-1.0.0/tests/test_chords.py +101 -0
- soundkit-1.0.0/tests/test_notes.py +156 -0
- soundkit-1.0.0/tests/test_scales.py +110 -0
- soundkit-1.0.0/tests/test_utils.py +156 -0
soundkit-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Quabynah Davis
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
soundkit-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: soundkit
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A comprehensive Python framework for musical note processing, MIDI manipulation and music theory operations
|
|
5
|
+
Author-email: Quabynah Davis <exceldavisville@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/davisdeveloper/soundkit
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/davisdeveloper/soundkit/issues
|
|
9
|
+
Project-URL: Documentation, https://github.com/davisdeveloper/soundkit#readme
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Education
|
|
13
|
+
Classifier: Intended Audience :: Other Audience
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Topic :: Multimedia :: Sound/Audio
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Classifier: Topic :: Education
|
|
25
|
+
Requires-Python: >=3.7
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
|
|
30
|
+
# SoundKit
|
|
31
|
+
|
|
32
|
+
**A Comprehensive Python Framework for Musical Note Processing, MIDI Manipulation and Music Theory Operations**
|
|
33
|
+
|
|
34
|
+
SoundKit is a powerful Python framework designed for musicians, developers, and audio engineers working with musical notes, MIDI data, and music theory. It provides intuitive APIs for note conversion, chord generation, scale creation, and comprehensive music theory operations.
|
|
35
|
+
|
|
36
|
+
## Features
|
|
37
|
+
|
|
38
|
+
- 🎵 **Note Conversion**: Convert between note names, MIDI numbers, and frequencies
|
|
39
|
+
- 🎹 **Chord Generation**: Create chords with various types and inversions
|
|
40
|
+
- 🎼 **Scale Generation**: Generate musical scales with multiple octaves
|
|
41
|
+
- 🔍 **Validation**: Comprehensive input validation and error handling
|
|
42
|
+
- 📊 **Utilities**: Advanced conversion tools and music theory utilities
|
|
43
|
+
- 🎯 **Music Theory**: Built-in music theory operations and constants
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install soundkit
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Quick Start
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
import soundkit as sk
|
|
55
|
+
|
|
56
|
+
# Basic note conversion
|
|
57
|
+
print(sk.notes.midiKey("C4")) # 60
|
|
58
|
+
print(sk.notes.midiFreq("A4")) # 440.0
|
|
59
|
+
|
|
60
|
+
# Create chords
|
|
61
|
+
c_major = sk.chords.get_chord_notes("C", "maj", 4)
|
|
62
|
+
print(c_major) # [60, 64, 67]
|
|
63
|
+
|
|
64
|
+
# Generate scales
|
|
65
|
+
c_major_scale = sk.scales.get_scale_notes("C", "major", 4, 2)
|
|
66
|
+
print(c_major_scale) # [60, 62, 64, 65, 67, 69, 71, 72, 74, 76, 77, 79, 81, 83]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Core Modules
|
|
70
|
+
|
|
71
|
+
### Notes Module
|
|
72
|
+
|
|
73
|
+
The `notes` module handles all note-related conversions and operations.
|
|
74
|
+
|
|
75
|
+
#### Basic Note Conversion
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
import soundkit as sk
|
|
79
|
+
|
|
80
|
+
# Convert note name to MIDI number
|
|
81
|
+
midi_number = sk.notes.midiKey("C4") # 60
|
|
82
|
+
midi_number = sk.notes.midiKey("A4") # 69
|
|
83
|
+
midi_number = sk.notes.midiKey("Gb3") # 54
|
|
84
|
+
|
|
85
|
+
# Convert note name to frequency
|
|
86
|
+
frequency = sk.notes.midiFreq("A4") # 440.0
|
|
87
|
+
frequency = sk.notes.midiFreq("C4") # 261.63
|
|
88
|
+
frequency = sk.notes.midiFreq("C4", round_digits=4) # 261.6256
|
|
89
|
+
|
|
90
|
+
# Convert frequency to MIDI number
|
|
91
|
+
midi_number = sk.notes.freqToMidi(440.0) # 69
|
|
92
|
+
midi_number = sk.notes.freqToMidi(261.63) # 60
|
|
93
|
+
|
|
94
|
+
# Convert MIDI number to note name
|
|
95
|
+
note_name = sk.notes.midiToNoteName(60) # "C4"
|
|
96
|
+
note_name = sk.notes.midiToNoteName(69) # "A4"
|
|
97
|
+
note_name = sk.notes.midiToNoteName(60, use_sharps=False) # "C4" (no effect for C)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### Supported Note Formats
|
|
101
|
+
|
|
102
|
+
SoundKit supports various note naming conventions:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
# Sharp notes
|
|
106
|
+
sk.notes.midiKey("C#4") # 61
|
|
107
|
+
sk.notes.midiKey("D#4") # 63
|
|
108
|
+
sk.notes.midiKey("F#4") # 66
|
|
109
|
+
|
|
110
|
+
# Flat notes
|
|
111
|
+
sk.notes.midiKey("Db4") # 61
|
|
112
|
+
sk.notes.midiKey("Eb4") # 63
|
|
113
|
+
sk.notes.midiKey("Gb4") # 66
|
|
114
|
+
|
|
115
|
+
# Mixed notation
|
|
116
|
+
sk.notes.midiKey("C4") # 60
|
|
117
|
+
sk.notes.midiKey("C#4") # 61
|
|
118
|
+
sk.notes.midiKey("Db4") # 61 (same as C#4)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
#### Batch Processing
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
import soundkit as sk
|
|
125
|
+
|
|
126
|
+
# Process multiple notes at once
|
|
127
|
+
notes = ["C4", "E4", "G4", "A4", "B4"]
|
|
128
|
+
|
|
129
|
+
# Convert to MIDI numbers
|
|
130
|
+
midi_numbers = sk.notes.notes_to_midi(notes)
|
|
131
|
+
print(midi_numbers) # [60, 64, 67, 69, 71]
|
|
132
|
+
|
|
133
|
+
# Convert to frequencies
|
|
134
|
+
frequencies = sk.notes.notes_to_frequencies(notes)
|
|
135
|
+
print(frequencies) # [261.63, 329.63, 392.0, 440.0, 493.88]
|
|
136
|
+
|
|
137
|
+
# With custom concert pitch
|
|
138
|
+
frequencies = sk.notes.notes_to_frequencies(notes, concert_pitch=442.0)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
#### Validation
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
import soundkit as sk
|
|
145
|
+
|
|
146
|
+
# Check if note is valid
|
|
147
|
+
is_valid = sk.notes.is_valid_midi_range("C4") # True
|
|
148
|
+
is_valid = sk.notes.is_valid_midi_range("C11") # False
|
|
149
|
+
|
|
150
|
+
# Handle invalid notes gracefully
|
|
151
|
+
try:
|
|
152
|
+
sk.notes.midiKey("H4") # Invalid note
|
|
153
|
+
except sk.InvalidNoteError as e:
|
|
154
|
+
print(f"Error: {e}")
|
|
155
|
+
|
|
156
|
+
try:
|
|
157
|
+
sk.notes.midiKey("C11") # Invalid octave
|
|
158
|
+
except sk.InvalidOctaveError as e:
|
|
159
|
+
print(f"Error: {e}")
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Chords Module
|
|
163
|
+
|
|
164
|
+
The `chords` module provides chord generation and manipulation.
|
|
165
|
+
|
|
166
|
+
#### Basic Chord Generation
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
import soundkit as sk
|
|
170
|
+
|
|
171
|
+
# Generate chord notes
|
|
172
|
+
c_major = sk.chords.get_chord_notes("C", "maj", 4)
|
|
173
|
+
print(c_major) # [60, 64, 67]
|
|
174
|
+
|
|
175
|
+
d_minor = sk.chords.get_chord_notes("D", "min", 4)
|
|
176
|
+
print(d_minor) # [62, 65, 69]
|
|
177
|
+
|
|
178
|
+
g_seventh = sk.chords.get_chord_notes("G", "7", 4)
|
|
179
|
+
print(g_seventh) # [67, 71, 74, 77]
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
#### Available Chord Types
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
import soundkit as sk
|
|
186
|
+
|
|
187
|
+
# Get all available chord types
|
|
188
|
+
chord_types = sk.chords.get_chord_names()
|
|
189
|
+
print(chord_types)
|
|
190
|
+
# ['maj', 'major', 'min', 'minor', 'dim', 'diminished', 'aug', 'augmented',
|
|
191
|
+
# '7', 'dominant7', 'maj7', 'major7', 'min7', 'minor7', 'dim7', 'diminished7',
|
|
192
|
+
# 'half_dim7', 'm7b5', 'sus2', 'sus4', '9', 'maj9']
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
#### Chord Inversions
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
import soundkit as sk
|
|
199
|
+
|
|
200
|
+
# Root position
|
|
201
|
+
c_major_root = sk.chords.get_chord_notes("C", "maj", 4, inversion=0)
|
|
202
|
+
print(c_major_root) # [60, 64, 67]
|
|
203
|
+
|
|
204
|
+
# First inversion
|
|
205
|
+
c_major_first = sk.chords.get_chord_notes("C", "maj", 4, inversion=1)
|
|
206
|
+
print(c_major_first) # [64, 67, 72]
|
|
207
|
+
|
|
208
|
+
# Second inversion
|
|
209
|
+
c_major_second = sk.chords.get_chord_notes("C", "maj", 4, inversion=2)
|
|
210
|
+
print(c_major_second) # [67, 72, 76]
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### Chord Frequencies
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
import soundkit as sk
|
|
217
|
+
|
|
218
|
+
# Get chord frequencies
|
|
219
|
+
c_major_freq = sk.chords.get_chord_frequencies("C", "maj", 4)
|
|
220
|
+
print(c_major_freq) # [261.63, 329.63, 392.0]
|
|
221
|
+
|
|
222
|
+
# With custom rounding
|
|
223
|
+
c_major_freq = sk.chords.get_chord_frequencies("C", "maj", 4, round_digits=4)
|
|
224
|
+
print(c_major_freq) # [261.6256, 329.6276, 392.0]
|
|
225
|
+
|
|
226
|
+
# With inversion
|
|
227
|
+
c_major_first_freq = sk.chords.get_chord_frequencies("C", "maj", 4, inversion=1)
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Scales Module
|
|
231
|
+
|
|
232
|
+
The `scales` module provides scale generation and music theory operations.
|
|
233
|
+
|
|
234
|
+
#### Basic Scale Generation
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
import soundkit as sk
|
|
238
|
+
|
|
239
|
+
# Generate scale notes
|
|
240
|
+
c_major = sk.scales.get_scale_notes("C", "major", 4)
|
|
241
|
+
print(c_major) # [60, 62, 64, 65, 67, 69, 71]
|
|
242
|
+
|
|
243
|
+
a_minor = sk.scales.get_scale_notes("A", "minor", 4)
|
|
244
|
+
print(a_minor) # [69, 71, 72, 74, 76, 77, 79]
|
|
245
|
+
|
|
246
|
+
# Multiple octaves
|
|
247
|
+
c_major_2octaves = sk.scales.get_scale_notes("C", "major", 4, 2)
|
|
248
|
+
print(c_major_2octaves) # [60, 62, 64, 65, 67, 69, 71, 72, 74, 76, 77, 79, 81, 83]
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
#### Available Scale Types
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
import soundkit as sk
|
|
255
|
+
|
|
256
|
+
# Get all available scale types
|
|
257
|
+
scale_types = sk.scales.get_scale_names()
|
|
258
|
+
print(scale_types)
|
|
259
|
+
# ['major', 'minor', 'natural_minor', 'harmonic_minor', 'melodic_minor',
|
|
260
|
+
# 'pentatonic_major', 'pentatonic_minor', 'blues', 'dorian', 'phrygian',
|
|
261
|
+
# 'lydian', 'mixolydian', 'locrian', 'whole_tone']
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### Scale Frequencies
|
|
265
|
+
|
|
266
|
+
```python
|
|
267
|
+
import soundkit as sk
|
|
268
|
+
|
|
269
|
+
# Get scale frequencies
|
|
270
|
+
c_major_freq = sk.scales.get_scale_frequencies("C", "major", 4)
|
|
271
|
+
print(c_major_freq) # [261.63, 293.66, 329.63, 349.23, 392.0, 440.0, 493.88]
|
|
272
|
+
|
|
273
|
+
# Multiple octaves with custom rounding
|
|
274
|
+
c_major_2oct_freq = sk.scales.get_scale_frequencies("C", "major", 4, 2, round_digits=1)
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
#### Modes and Special Scales
|
|
278
|
+
|
|
279
|
+
```python
|
|
280
|
+
import soundkit as sk
|
|
281
|
+
|
|
282
|
+
# Modes
|
|
283
|
+
d_dorian = sk.scales.get_scale_notes("D", "dorian", 4)
|
|
284
|
+
print(d_dorian) # [62, 64, 65, 67, 69, 71, 72]
|
|
285
|
+
|
|
286
|
+
# Pentatonic scales
|
|
287
|
+
c_pentatonic_major = sk.scales.get_scale_notes("C", "pentatonic_major", 4)
|
|
288
|
+
print(c_pentatonic_major) # [60, 62, 64, 67, 69]
|
|
289
|
+
|
|
290
|
+
a_pentatonic_minor = sk.scales.get_scale_notes("A", "pentatonic_minor", 4)
|
|
291
|
+
print(a_pentatonic_minor) # [69, 72, 74, 76, 79]
|
|
292
|
+
|
|
293
|
+
# Blues scale
|
|
294
|
+
c_blues = sk.scales.get_scale_notes("C", "blues", 4)
|
|
295
|
+
print(c_blues) # [60, 63, 65, 66, 67, 70]
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Utils Module
|
|
299
|
+
|
|
300
|
+
The `utils` module provides validation and conversion utilities.
|
|
301
|
+
|
|
302
|
+
#### Validators
|
|
303
|
+
|
|
304
|
+
```python
|
|
305
|
+
import soundkit as sk
|
|
306
|
+
|
|
307
|
+
# Note validation
|
|
308
|
+
is_valid = sk.validators.validate_note_name("C4") # True
|
|
309
|
+
is_valid = sk.validators.validate_note_name("H4") # False
|
|
310
|
+
is_valid = sk.validators.validate_note_name("C#4") # True
|
|
311
|
+
is_valid = sk.validators.validate_note_name("Db4") # True
|
|
312
|
+
|
|
313
|
+
# MIDI range validation
|
|
314
|
+
is_valid = sk.validators.validate_midi_range(60) # True
|
|
315
|
+
is_valid = sk.validators.validate_midi_range(128) # False
|
|
316
|
+
|
|
317
|
+
# Frequency validation
|
|
318
|
+
is_valid = sk.validators.validate_frequency(440.0) # True
|
|
319
|
+
is_valid = sk.validators.validate_frequency(-10.0) # False
|
|
320
|
+
|
|
321
|
+
# Octave validation
|
|
322
|
+
is_valid = sk.validators.validate_octave(4) # True
|
|
323
|
+
is_valid = sk.validators.validate_octave(11) # False
|
|
324
|
+
|
|
325
|
+
# Note normalization
|
|
326
|
+
normalized = sk.validators.normalize_note_name("c#4") # "C#4"
|
|
327
|
+
normalized = sk.validators.normalize_note_name("db4") # "DB4"
|
|
328
|
+
normalized = sk.validators.normalize_note_name("C ♯4") # "C#4"
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
#### Converters
|
|
332
|
+
|
|
333
|
+
```python
|
|
334
|
+
import soundkit as sk
|
|
335
|
+
|
|
336
|
+
# Frequency to cents
|
|
337
|
+
cents = sk.converters.frequency_to_cents(440, 444) # ~15.67
|
|
338
|
+
cents = sk.converters.frequency_to_cents(440, 880) # 1200.0
|
|
339
|
+
|
|
340
|
+
# Cents to ratio
|
|
341
|
+
ratio = sk.converters.cents_to_ratio(100) # ~1.05946
|
|
342
|
+
ratio = sk.converters.cents_to_ratio(1200) # 2.0
|
|
343
|
+
|
|
344
|
+
# Ratio conversions
|
|
345
|
+
ratio = sk.converters.semitones_to_ratio(12) # 2.0
|
|
346
|
+
semitones = sk.converters.ratio_to_semitones(2.0) # 12.0
|
|
347
|
+
|
|
348
|
+
# Frequency normalization
|
|
349
|
+
normalized = sk.converters.normalize_frequency(441.0) # ~440.0
|
|
350
|
+
normalized = sk.converters.normalize_frequency(445.0, reference=442.0)
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Constants
|
|
354
|
+
|
|
355
|
+
SoundKit provides useful musical constants:
|
|
356
|
+
|
|
357
|
+
```python
|
|
358
|
+
import soundkit as sk
|
|
359
|
+
|
|
360
|
+
# Standard concert pitch
|
|
361
|
+
print(sk.CONCERT_PITCH) # 440.0
|
|
362
|
+
|
|
363
|
+
# MIDI range
|
|
364
|
+
print(sk.MIDI_RANGE) # (0, 127)
|
|
365
|
+
|
|
366
|
+
# Reference frequencies
|
|
367
|
+
print(sk.REFERENCE_FREQUENCIES["A4"]) # 440.0
|
|
368
|
+
print(sk.REFERENCE_FREQUENCIES["C4"]) # 261.63
|
|
369
|
+
|
|
370
|
+
# Use constants in your calculations
|
|
371
|
+
custom_freq = sk.notes.midiFreq("A4", concert_pitch=442.0)
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## Error Handling
|
|
375
|
+
|
|
376
|
+
SoundKit provides comprehensive error handling with custom exceptions:
|
|
377
|
+
|
|
378
|
+
```python
|
|
379
|
+
import soundkit as sk
|
|
380
|
+
|
|
381
|
+
try:
|
|
382
|
+
# Invalid note name
|
|
383
|
+
sk.notes.midiKey("H4")
|
|
384
|
+
except sk.InvalidNoteError as e:
|
|
385
|
+
print(f"Invalid note: {e}")
|
|
386
|
+
|
|
387
|
+
try:
|
|
388
|
+
# Invalid octave
|
|
389
|
+
sk.notes.midiKey("C11")
|
|
390
|
+
except sk.InvalidOctaveError as e:
|
|
391
|
+
print(f"Invalid octave: {e}")
|
|
392
|
+
|
|
393
|
+
try:
|
|
394
|
+
# Invalid frequency
|
|
395
|
+
sk.notes.freqToMidi(-100)
|
|
396
|
+
except sk.InvalidFrequencyError as e:
|
|
397
|
+
print(f"Invalid frequency: {e}")
|
|
398
|
+
|
|
399
|
+
try:
|
|
400
|
+
# Invalid chord type
|
|
401
|
+
sk.chords.get_chord_notes("C", "invalid_type", 4)
|
|
402
|
+
except sk.InvalidChordError as e:
|
|
403
|
+
print(f"Invalid chord: {e}")
|
|
404
|
+
|
|
405
|
+
try:
|
|
406
|
+
# Invalid scale type
|
|
407
|
+
sk.scales.get_scale_notes("C", "invalid_scale", 4)
|
|
408
|
+
except sk.InvalidScaleError as e:
|
|
409
|
+
print(f"Invalid scale: {e}")
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
## Advanced Examples
|
|
413
|
+
|
|
414
|
+
### Music Theory Application
|
|
415
|
+
|
|
416
|
+
```python
|
|
417
|
+
import soundkit as sk
|
|
418
|
+
|
|
419
|
+
def analyze_progression(progression):
|
|
420
|
+
"""Analyze a chord progression"""
|
|
421
|
+
for chord in progression:
|
|
422
|
+
root, quality = chord
|
|
423
|
+
notes = sk.chords.get_chord_notes(root, quality, 4)
|
|
424
|
+
frequencies = sk.chords.get_chord_frequencies(root, quality, 4)
|
|
425
|
+
print(f"{root}{quality}: {notes} -> {frequencies}Hz")
|
|
426
|
+
|
|
427
|
+
# Analyze a II-V-I progression
|
|
428
|
+
progression = [("D", "min7"), ("G", "7"), ("C", "maj7")]
|
|
429
|
+
analyze_progression(progression)
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Scale Visualization
|
|
433
|
+
|
|
434
|
+
```python
|
|
435
|
+
import soundkit as sk
|
|
436
|
+
|
|
437
|
+
def print_scale_intervals(root_note, scale_type, octave=4):
|
|
438
|
+
"""Print scale with note names and frequencies"""
|
|
439
|
+
midi_notes = sk.scales.get_scale_notes(root_note, scale_type, octave)
|
|
440
|
+
|
|
441
|
+
print(f"{root_note} {scale_type} scale:")
|
|
442
|
+
for midi in midi_notes:
|
|
443
|
+
note_name = sk.notes.midiToNoteName(midi)
|
|
444
|
+
frequency = sk.notes.midiFreq(note_name)
|
|
445
|
+
print(f" {note_name}: {frequency}Hz")
|
|
446
|
+
|
|
447
|
+
print_scale_intervals("C", "major")
|
|
448
|
+
print_scale_intervals("A", "harmonic_minor")
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Tuning Analysis
|
|
452
|
+
|
|
453
|
+
```python
|
|
454
|
+
import soundkit as sk
|
|
455
|
+
|
|
456
|
+
def compare_tunings(note_name, reference_pitches):
|
|
457
|
+
"""Compare frequencies across different tuning standards"""
|
|
458
|
+
print(f"Note: {note_name}")
|
|
459
|
+
for name, pitch in reference_pitches.items():
|
|
460
|
+
freq = sk.notes.midiFreq(note_name, concert_pitch=pitch)
|
|
461
|
+
print(f" {name} (A4={pitch}Hz): {freq}Hz")
|
|
462
|
+
|
|
463
|
+
tunings = {
|
|
464
|
+
"Modern Standard": 440.0,
|
|
465
|
+
"Baroque": 415.0,
|
|
466
|
+
"Classical": 430.0,
|
|
467
|
+
"Modern High": 442.0
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
compare_tunings("A4", tunings)
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
## API Reference
|
|
474
|
+
|
|
475
|
+
### Notes Module
|
|
476
|
+
|
|
477
|
+
- `midiKey(note_name: str) -> int`: Convert note name to MIDI number
|
|
478
|
+
- `midiFreq(note_name: str, round_digits: int = 2, concert_pitch: float = 440.0) -> float`: Convert note name to frequency
|
|
479
|
+
- `freqToMidi(frequency: float, concert_pitch: float = 440.0) -> int`: Convert frequency to MIDI number
|
|
480
|
+
- `midiToNoteName(midi_number: int, use_sharps: bool = True) -> str`: Convert MIDI number to note name
|
|
481
|
+
- `is_valid_midi_range(note_name: str) -> bool`: Check if note is within MIDI range
|
|
482
|
+
- `notes_to_midi(note_list: List[str]) -> List[Union[int, str]]`: Convert list of notes to MIDI numbers
|
|
483
|
+
- `notes_to_frequencies(note_list: List[str], round_digits: int = 2, concert_pitch: float = 440.0) -> List[Union[float, str]]`: Convert list of notes to frequencies
|
|
484
|
+
|
|
485
|
+
### Chords Module
|
|
486
|
+
|
|
487
|
+
- `get_chord_notes(chord_root: str, chord_type: str = 'maj', octave: int = 4, inversion: int = 0) -> List[int]`: Get MIDI notes for a chord
|
|
488
|
+
- `get_chord_frequencies(chord_root: str, chord_type: str = 'maj', octave: int = 4, round_digits: int = 2, inversion: int = 0) -> List[float]`: Get frequencies for a chord
|
|
489
|
+
- `get_chord_names() -> List[str]`: Get available chord types
|
|
490
|
+
|
|
491
|
+
### Scales Module
|
|
492
|
+
|
|
493
|
+
- `get_scale_notes(scale_root: str, scale_type: str = 'major', octave: int = 4, num_octaves: int = 1) -> List[int]`: Get MIDI notes for a scale
|
|
494
|
+
- `get_scale_frequencies(scale_root: str, scale_type: str = 'major', octave: int = 4, num_octaves: int = 1, round_digits: int = 2) -> List[float]`: Get frequencies for a scale
|
|
495
|
+
- `get_scale_names() -> List[str]`: Get available scale types
|
|
496
|
+
|
|
497
|
+
### Utils Module
|
|
498
|
+
|
|
499
|
+
#### Validators
|
|
500
|
+
|
|
501
|
+
- `validate_note_name(note_name: str) -> bool`: Validate note name format
|
|
502
|
+
- `validate_midi_range(midi_number: int) -> bool`: Validate MIDI number range
|
|
503
|
+
- `validate_frequency(frequency: float) -> bool`: Validate frequency value
|
|
504
|
+
- `validate_octave(octave: int) -> bool`: Validate octave range
|
|
505
|
+
- `normalize_note_name(note_name: str) -> str`: Normalize note name format
|
|
506
|
+
|
|
507
|
+
#### Converters
|
|
508
|
+
|
|
509
|
+
- `frequency_to_cents(freq1: float, freq2: float) -> float`: Convert frequency ratio to cents
|
|
510
|
+
- `cents_to_ratio(cents: float) -> float`: Convert cents to frequency ratio
|
|
511
|
+
- `ratio_to_cents(ratio: float) -> float`: Convert frequency ratio to cents
|
|
512
|
+
- `semitones_to_ratio(semitones: float) -> float`: Convert semitones to frequency ratio
|
|
513
|
+
- `ratio_to_semitones(ratio: float) -> float`: Convert frequency ratio to semitones
|
|
514
|
+
- `normalize_frequency(frequency: float, reference: float = 440.0) -> float`: Normalize frequency to nearest reference
|
|
515
|
+
|
|
516
|
+
## Contributing
|
|
517
|
+
|
|
518
|
+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
519
|
+
|
|
520
|
+
## License
|
|
521
|
+
|
|
522
|
+
SoundKit is released under the MIT License. See [LICENSE](LICENSE) for details.
|
|
523
|
+
|
|
524
|
+
## Support
|
|
525
|
+
|
|
526
|
+
For bug reports, feature requests, or questions:
|
|
527
|
+
|
|
528
|
+
- Create an issue on [GitHub](https://github.com/yourusername/soundkit/issues)
|
|
529
|
+
|
|
530
|
+
- Email: <exceldavisville@gmail.com>
|
|
531
|
+
|
|
532
|
+
## Version History
|
|
533
|
+
|
|
534
|
+
- **1.0.0**: Initial release with core note, chord, and scale functionality
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
538
|
+
SoundKit is developed and maintained by Quabynah Davis.
|