|
| 1 | +# SPDX-FileCopyrightText: Copyright (C) ARDUINO SRL (http://www.arduino.cc) |
| 2 | +# |
| 3 | +# SPDX-License-Identifier: MPL-2.0 |
| 4 | + |
| 5 | +from dataclasses import dataclass, field |
| 6 | +from .effects import SoundEffect |
| 7 | + |
| 8 | + |
| 9 | +@dataclass |
| 10 | +class MusicComposition: |
| 11 | + """ |
| 12 | + A structured representation of a musical composition for SoundGenerator. |
| 13 | +
|
| 14 | + This class encapsulates all the parameters needed to play a polyphonic composition, |
| 15 | + making it easy to save, load, and share musical sequences. |
| 16 | +
|
| 17 | + Attributes: |
| 18 | + composition (list[list[tuple[str, float]]]): Polyphonic sequence as a list of tracks. |
| 19 | + Each track is a list of tuples (note, duration). |
| 20 | + Duration is in note fractions (1/4 = quarter note, 1/8 = eighth note). |
| 21 | + Example: [[("C4", 0.25), ("E4", 0.25)], [("G4", 0.5)]] |
| 22 | + bpm (int): Tempo in beats per minute. Default: 120. |
| 23 | + waveform (str): Wave form type ("sine", "square", "triangle", "sawtooth"). Default: "sine". |
| 24 | + volume (float): Master volume level (0.0 to 1.0). Default: 0.8. |
| 25 | + effects (list): List of SoundEffect instances to apply. Default: [SoundEffect.adsr()]. |
| 26 | +
|
| 27 | + Example: |
| 28 | + ```python |
| 29 | + from arduino.app_bricks.sound_generator import MusicComposition, SoundGenerator, SoundEffect |
| 30 | +
|
| 31 | + # Create a composition |
| 32 | + comp = MusicComposition( |
| 33 | + composition=[ |
| 34 | + [("C4", 0.25), ("E4", 0.25), ("G4", 0.25)], # Track 1 |
| 35 | + [("REST", 0.25), ("C5", 0.5)], # Track 2 |
| 36 | + ], |
| 37 | + bpm=120, |
| 38 | + waveform="square", |
| 39 | + volume=0.8, |
| 40 | + effects=[SoundEffect.adsr(), SoundEffect.tremolo(depth=0.5, rate=5.0)], |
| 41 | + ) |
| 42 | +
|
| 43 | + # Configure and play with SoundGenerator |
| 44 | + gen = SoundGenerator() |
| 45 | + gen.start() |
| 46 | + gen.play_composition(comp, block=True) |
| 47 | +
|
| 48 | + # Alternatively, set parameters manually and play |
| 49 | + gen = SoundGenerator() |
| 50 | + gen.start() |
| 51 | + gen.set_bpm(comp.bpm) |
| 52 | + gen.set_wave_form(comp.waveform) |
| 53 | + gen.set_master_volume(comp.volume) |
| 54 | + gen.set_effects(comp.effects) |
| 55 | + gen.play_polyphonic(comp.composition, volume=comp.volume, block=True) |
| 56 | + ``` |
| 57 | + """ |
| 58 | + |
| 59 | + composition: list[list[tuple[str, float]]] |
| 60 | + bpm: int = 120 |
| 61 | + waveform: str = "sine" |
| 62 | + volume: float = 0.8 |
| 63 | + effects: list = field(default_factory=lambda: [SoundEffect.adsr()]) |
0 commit comments