-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into python-built-in-functions
- Loading branch information
Showing
149 changed files
with
16,903 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Build a Guitar Synthesizer: Play Musical Tablature in Python | ||
|
||
This folder contains the source code and resources for the Real Python tutorial [Build a Guitar Synthesizer: Play Musical Tablature in Python](https://realpython.com/python-guitar-synthesizer/). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Digitar | ||
|
||
A digital guitar and a tablature player. | ||
|
||
## Installation | ||
|
||
Install the project along with its dependencies into a virtual environment managed by Poetry: | ||
|
||
```sh | ||
$ poetry install | ||
``` | ||
|
||
## Usage | ||
|
||
Activate the project's virtual environment: | ||
|
||
```sh | ||
$ poetry shell | ||
``` | ||
|
||
Change directory to the `demo/` subfolder and run the sample scripts: | ||
|
||
```sh | ||
(digitar-py3.12) $ cd demo/ | ||
(digitar-py3.12) $ python play_chorus.py | ||
(digitar-py3.12) $ python play_diablo.py | ||
``` | ||
|
||
Read the tablature from the custom YAML file format: | ||
|
||
```sh | ||
$ play-tab tabs/doom.yaml | ||
Saved file /home/user/digital-guitar/demo/doom.mp3 | ||
|
||
$ play-tab tabs/foggy-mountain-breakdown.yaml -o foggy.mp3 | ||
Saved file /home/user/digital-guitar/demo/foggy.mp3 | ||
``` |
21 changes: 21 additions & 0 deletions
21
python-guitar-synthesizer/source_code_final/demo/ir/ATTRIBUTION.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Impulse Responses | ||
|
||
1. Acoustic Guitar | ||
- File: `Tay816 M251 SB1.wav` | ||
- URL: https://worshiptutorials.com/product/acoustic-ir-sample-pack/ | ||
|
||
2. Banjo | ||
- File: `IR_5_string_banjo_dazzo_IR44k.wav` | ||
- URL: https://acousticir.free.fr/spip.php | ||
|
||
3. Bass Guitar | ||
- File: `Holy Grail C800 SB1.wav` | ||
- https://worshiptutorials.com/product/acoustic-ir-sample-pack/ | ||
|
||
4. Electric Guitar | ||
- File: `Rocksta Reactions Mesa Traditional D6 D 0 -18 -36.wav` | ||
- URL: https://www.soundwoofer.se/blog/about/top-20-list/ | ||
|
||
5. Ukulele | ||
- File: `AtlasV2.wav` | ||
- URL: https://liveukulele.com/lessons/plug-in/impulse-response-tutorial/ |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+159 KB
python-guitar-synthesizer/source_code_final/demo/mp3/01_monophonic.mp3
Binary file not shown.
Binary file added
BIN
+139 KB
python-guitar-synthesizer/source_code_final/demo/mp3/02_polyphonic.mp3
Binary file not shown.
Binary file added
BIN
+196 KB
python-guitar-synthesizer/source_code_final/demo/mp3/03_polyphonic.mp3
Binary file not shown.
Binary file added
BIN
+401 KB
python-guitar-synthesizer/source_code_final/demo/mp3/04_acoustic_guitar.mp3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
70 changes: 70 additions & 0 deletions
70
python-guitar-synthesizer/source_code_final/demo/play_chorus.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
from itertools import cycle | ||
from typing import Iterator | ||
|
||
from digitar.chord import Chord | ||
from digitar.instrument import PluckedStringInstrument, StringTuning | ||
from digitar.processing import normalize | ||
from digitar.stroke import Velocity | ||
from digitar.synthesis import Synthesizer | ||
from digitar.temporal import Time, Timeline | ||
from digitar.track import AudioTrack | ||
from pedalboard import Convolution, Gain, LowShelfFilter, Pedalboard, Reverb | ||
from pedalboard.io import AudioFile | ||
|
||
|
||
def main() -> None: | ||
ukulele = PluckedStringInstrument( | ||
tuning=StringTuning.from_notes("A4", "E4", "C4", "G4"), | ||
vibration=Time(seconds=5.0), | ||
damping=0.498, | ||
) | ||
synthesizer = Synthesizer(ukulele) | ||
audio_track = AudioTrack(synthesizer.sampling_rate) | ||
timeline = Timeline() | ||
for interval, chord, stroke in strumming_pattern(): | ||
audio_samples = synthesizer.strum_strings(chord, stroke) | ||
audio_track.add_at(timeline.instant, audio_samples) | ||
timeline >> interval | ||
effects = Pedalboard( | ||
[ | ||
Reverb(), | ||
Convolution(impulse_response_filename="ir/ukulele.wav", mix=0.95), | ||
LowShelfFilter(cutoff_frequency_hz=440, gain_db=10, q=1), | ||
Gain(gain_db=15), | ||
] | ||
) | ||
samples = effects(audio_track.samples, audio_track.sampling_rate) | ||
with AudioFile("chorus.mp3", "w", audio_track.sampling_rate) as file: | ||
file.write(normalize(samples)) | ||
|
||
|
||
def strumming_pattern() -> Iterator[tuple[float, Chord, Velocity]]: | ||
chords = ( | ||
Chord.from_numbers(0, 0, 0, 3), | ||
Chord.from_numbers(0, 2, 3, 2), | ||
Chord.from_numbers(2, 0, 0, 0), | ||
Chord.from_numbers(2, 0, 1, 0), | ||
) | ||
|
||
fast = Time.from_milliseconds(10) | ||
slow = Time.from_milliseconds(25) | ||
|
||
strokes = [ | ||
Velocity.down(slow), | ||
Velocity.down(slow), | ||
Velocity.up(slow), | ||
Velocity.up(fast), | ||
Velocity.down(fast), | ||
Velocity.up(slow), | ||
] | ||
|
||
interval = cycle([0.65, 0.45, 0.75, 0.2, 0.4, 0.25]) | ||
|
||
for chord in chords: | ||
for _ in range(2): # Repeat each chord twice | ||
for stroke in strokes: | ||
yield next(interval), chord, stroke | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
Oops, something went wrong.