### Installing Symusic Pre-Built Version (Bash) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md This command installs the `symusic` library using `pip` from pre-built wheels. It's the simplest way to get started, leveraging pre-compiled binaries for various OS and architectures. This method requires an active Python environment with `pip` installed. ```bash pip install symusic ``` -------------------------------- ### Installing Symusic From Git Repository (Bash) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md These commands clone the `symusic` repository recursively and then install the library directly from the local source directory. This method is typically used for active development or when specific branches/versions are needed. It also requires a C++20 compatible compiler. ```bash git clone --recursive git@github.com:Yikai-Liao/symusic.git pip install ./symusic ``` -------------------------------- ### Installing Symusic From PyPI Source (Bash) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md This command installs the `symusic` library by forcing `pip` to build it from the source distribution available on PyPI. This is useful when pre-built wheels are not suitable or for development purposes. It requires a compatible C++20 compiler (gcc >=11, clang >=15) to be available on the system. ```bash pip install --no-binary symusic symusic ``` -------------------------------- ### Installing symusic via pip Source: https://github.com/yikai-liao/symusic/blob/main/README.md This command installs the pre-compiled version of the symusic library from PyPI using pip. It's the simplest and recommended way to get started with symusic for most users. ```bash pip install symusic ``` -------------------------------- ### Installing Symusic with Conda GCC/G++ (Bash) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md This command sets environment variables `CC` and `CXX` to point to the `gcc` and `g++` compilers installed via `conda`, then proceeds to install `symusic` from source using `pip`. This ensures that `pip` uses the `conda`-managed compilers for building the library, addressing compiler compatibility issues on Linux without `sudo`. ```bash CC=/path_to_conda_root/envs/env_name/bin/gcc CXX=/path_to_conda_root/envs/env_name/bin/g++ pip install --no-binary symusic symusic ``` -------------------------------- ### Installing GCC/G++ with Conda on Linux (Bash) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md This command installs the `gcc` and `g++` compilers from the `conda-forge` channel using `conda`. This is a workaround for Linux users who lack `sudo` permissions to install system-wide compilers, providing the necessary C++20 compatible build tools for `symusic`. ```bash conda install conda-forge::gcc conda-forge::gxx ``` -------------------------------- ### Installing Symusic and MIDI Libraries Source: https://github.com/yikai-liao/symusic/blob/main/tutorial.ipynb This command installs the `symusic` library along with other common MIDI processing libraries (`mido`, `pretty_midi`, `miditoolkit`, `music21`) and `matplotlib` for plotting. These are essential dependencies for running the examples and benchmarks. ```Python # !pip install symusic mido pretty_midi miditoolkit music21 matplotlib ``` -------------------------------- ### Installing Pre-commit Hooks Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/development.md After installing the `pre-commit` tool, this command sets up the pre-commit script in the local Git repository. This enables the configured hooks to run automatically before each commit, enforcing code style and quality checks. ```bash pre-commit install ``` -------------------------------- ### Serializing Symusic Score with Pickle and Multiprocessing (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md This example demonstrates the pickling capability of `symusic.Score` objects, enabling fast serialization and deserialization. It also shows how to leverage Python's `multiprocessing` module with `symusic` objects, allowing parallel processing of scores (e.g., converting time units) due to their pickleability. This significantly accelerates batch operations on multiple scores. ```python from symusic import Score import pickle import multiprocessing as mp s = Score("xxx.mid") with open("out.pkl", "wb") as f: pickle.dump(s, f) with open("out.pkl", "rb") as f: s = pickle.load(f) with mp.Pool(4) as pool: print(pool.map(lambda x: x.to("second"), [s, s, s, s])) ``` -------------------------------- ### Downloading Example MIDI File Source: https://github.com/yikai-liao/symusic/blob/main/tutorial.ipynb This command downloads an example MIDI file named `mahler.mid` from a GitHub repository. This file is used throughout the documentation for demonstrating MIDI loading and processing functionalities. ```Python # !wget https://github.com/lzqlzzq/minimidi/raw/main/example/mahler.mid ``` -------------------------------- ### Installing Pre-commit Hook Manager Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/development.md This command installs `pre-commit`, a framework for managing and maintaining multi-language pre-commit hooks. It is used in the symusic project to automate code formatting and ensure consistent code style before commits. ```bash pip install pre-commit ``` -------------------------------- ### Manipulating Note Lists in Symusic (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md This snippet illustrates various methods available for `NoteList` containers in `symusic`, which behave similarly to Python lists but with added functionalities. It demonstrates checking for emptiness, retrieving start and end times, copying, sorting with custom keys, filtering, and adjusting note timings. These methods enable flexible manipulation of musical event data. ```python from symusic import Score notes = Score("xxx.mid").tracks[0].notes notes.empty() # return True if the note list is empty notes.start() # return the start time of the note list notes.end() # return the end time of the note list notes1 = notes.copy() # copy the note list # the default key is (time, duration, pitch) for notes, (time, duration) for pedals # for other events, the default key is "time" notes2 = notes.sort(reversed=False, inplace=False) # sort the notes notes3 = notes.sort(lambda x: x.velocity) # you could also customize the key, but it is slower notes4 = notes.filter(lambda x: x.pitch > 60, inplace=False) # filter the notes # adjust the time of the notes, the first list is the old time, the second list is the new time # the time unit of the two lists should be the same as the time unit of the note list # the semantic of adjust_time is the same as the method in pretty_midi notes5 = notes.adjust_time([0, 10, notes.end()], [0, 20, notes.end() / 2]) ``` -------------------------------- ### Loading Symusic Score from File (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md This snippet demonstrates how to load a musical score into a `symusic.Score` object from a file path. The `Score` constructor dynamically dispatches to `from_file`, inferring the format from the extension or allowing explicit specification via the `fmt` argument. It supports various formats like MIDI (`.mid`) and ABC (`.txt` with `fmt='abc'`). ```python from symusic import Score Score("xxx.mid") Score("xxx.txt", fmt="abc") Score.from_file("xxx.mid") Score.from_file("xxx.txt", fmt="abc") ``` -------------------------------- ### Installing Nanobind Dependency Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/development.md This command installs the `nanobind` library, which is the sole required dependency for the symusic project. It's recommended to use cpython <= 3.11 due to known memory leak issues with cpython 3.12 when detected by nanobind. ```bash pip install nanobind ``` -------------------------------- ### Accessing Track and Note Properties in Symusic (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md This snippet demonstrates how to access various properties and call methods on `Track` and `Note` objects within the `symusic` library. It covers basic attributes like `name`, `program`, `pitch`, `velocity`, and utility methods such as `start()`, `end()`, and `empty()`. These properties provide detailed information about the musical events. ```python s.tracks # list of tracks t = s.tracks[0] t.ttype # read-only property, the same as s.ttype t.name # track name t.program # program number t.is_drum # whether it's a drum track t.notes # list of notes t.controls # list of control changes t.pitch_bends # list of pitch bends t.pedals # list of pedals t.start() # return the start time of the track t.end() # return the end time of the track t.empty() # return True if the track is empty t.note_num() # return the number of notes in the track n = t.notes[0] n.ttype # read-only property, the same as s.ttype n.time # the NoteOn time or n.start n.start # the same as n.time n.duration # the duration of the note n.end # a read-only property, n.time + n.duration n.end_time() # a method that returns n.end n.pitch # the pitch of the note n.velocity # the velocity of the note n.empty() # duration <= 0 or velocity <= 0 ``` -------------------------------- ### Building and Installing symusic from Source (PyPI Source Distribution) Source: https://github.com/yikai-liao/symusic/blob/main/README.md This command installs symusic from its source distribution on PyPI, explicitly forcing a build from source rather than using a pre-compiled wheel. This is useful for specific build environments or when debugging build issues. ```bash pip install symusic --no-binary symusic ``` -------------------------------- ### Installing Symusic with Pip Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/introduction.md This command installs the Symusic library using pip, leveraging pre-built wheels for various operating systems, architectures, and Python versions. It is the easiest and recommended installation method for most users. ```bash pip install symusic ``` -------------------------------- ### Accessing Basic Symusic Score Properties (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md This snippet illustrates how to access fundamental properties and global event lists of a `symusic.Score` object. It covers retrieving the time unit type (`ttype`), ticks per quarter (`ticks_per_quarter` or `tpq`), and lists of global events like tempos, time signatures, key signatures, lyrics, and markers. Additionally, it shows methods to get the score's start/end times, check if it's empty, and count the number of notes, providing essential metadata for analysis. ```python from symusic import Score s = Score("xxx.mid") # ttype is a property of all the objects in symusic related to time s.ttype # the type of time unit, 'tick', 'quarter' or 'second' s.ticks_per_quarter # or s.tpq # Global Events s.tempos # list of tempo changes s.time_signatures # list of time signature changes s.key_signatures # list of key signature changes s.lyrics # list of lyrics s.markers # list of markers s.start() # return the start time of the score s.end() # return the end time of the score s.empty() # return True if the score is empty s.note_num() # return the number of notes in the score ``` -------------------------------- ### Visualizing Symusic Piano Roll with Matplotlib (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md This snippet provides an example of how to visualize a piano roll generated from a `symusic` `Track` using `matplotlib`. It demonstrates resampling the score, converting a track to a piano roll with specific modes and pitch range, and preparing it for plotting. This is a common step for analyzing musical data visually. ```python from symusic import Score from matplotlib import pyplot as plt s = Score("xxx.mid").resample(tpq=6, min_dur=1) track = s.tracks[0] pianoroll = track.pianoroll(modes=["onset", "frame"], pitch_range=[0, 128], encode_velocity=False) ``` -------------------------------- ### Installing Symusic to Python Environment Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/development.md This command installs the symusic package into the currently active Python environment directly from its source directory. Executing this in the project's root directory makes the package available for import and use within Python. ```bash pip install . ``` -------------------------------- ### Installing Symusic from Cloned Repository Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/introduction.md These commands clone the Symusic repository, including its submodules, and then install the library directly from the local source directory. This is typically used for development, contributing to the project, or accessing the very latest unreleased changes. ```bash git clone --recursive git@github.com:Yikai-Liao/symusic.git pip install ./symusic ``` -------------------------------- ### Synthesizing Audio from Symusic Score (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md This code block illustrates how to synthesize audio from a `symusic.Score` object into a WAV file. It covers initializing a `Synthesizer` with a SoundFont (builtin or custom), rendering the score to a NumPy array, and dumping the audio to a WAV file with specified sample rate and bit depth. ```Python from symusic import Score, Synthesizer, BuiltInSF3 ,dump_wav s = Score("xxx.mid") # You could choose a builtin soundfont # And the following one is the default soundfont if you don't specify it when creating a synthesizer sf_path = BuiltInSF3.MuseScoreGeneral().path(download=True) # sf3 and sf2 are both supported sf_path = "path/to/your/soundfont.sf3" synth = Synthesizer( sf_path = sf_path, # the path to the soundfont sample_rate = 44100, # the sample rate of the output wave, 44100 is the default value ) # audio is a 2D numpy array of float32, [channels, time] audio = synth.render(s, stereo=True) # stereo is True by default, which means you will get a stereo wave # you could also dump the wave to a file # use_int16 is True by default, which means the output wave is int16, otherwise float32 dump_wav("out.wav", audio, sample_rate=44100, use_int16=True) ``` -------------------------------- ### Building Symusic C++ Examples with CMake Source: https://github.com/yikai-liao/symusic/blob/main/CMakeLists.txt This section configures the build for various C++ examples of the Symusic library. It adds `nanobench` as a dependency and defines multiple executables, linking them against the `symusic` library and `nanobench` where required. This allows users to compile and run demonstration programs. ```CMake add_subdirectory(./3rdparty/nanobench EXCLUDE_FROM_ALL) add_executable(note_count examples/cpp/note_count.cpp) add_executable(dump examples/cpp/dump.cpp) add_executable(io_bench examples/cpp/io_bench.cpp) add_executable(synth examples/cpp/synth.cpp) add_executable(adjust_time examples/cpp/adjust_time.cpp) add_executable(process_midi_directory examples/cpp/process_midi_directory.cpp) target_link_libraries(note_count PRIVATE symusic) target_link_libraries(dump PRIVATE symusic) target_link_libraries(io_bench PRIVATE symusic nanobench) target_link_libraries(synth PUBLIC symusic) target_link_libraries(adjust_time PUBLIC symusic) target_link_libraries(process_midi_directory PRIVATE symusic) ``` -------------------------------- ### Full Example of Synthesizing and Saving Audio with Symusic in Python Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/api_reference/synthesizer.md This comprehensive example demonstrates the end-to-end process of loading a MIDI score, initializing the `Synthesizer` with a built-in SoundFont, rendering the score to audio, and saving the resulting `AudioData` to a WAV file. It also shows how to access the audio data as a NumPy array. ```python from symusic import Score, Synthesizer, BuiltInSF3, dump_wav # 1. Load a score score = Score("path/to/your/midi.mid") # 2. Initialize the synthesizer with a built-in SoundFont sf_path = BuiltInSF3.MuseScoreGeneral().path(download=True) synthesizer = Synthesizer(sf_path=sf_path, sample_rate=44100, quality=4) # 3. Render the score to audio audio_data = synthesizer.render(score, stereo=True) # 4. Save the audio to a WAV file dump_wav("output_audio.wav", audio_data) # 5. (Optional) Access audio data as a NumPy array import numpy as np audio_array = np.array(audio_data) print(f"Audio shape: {audio_array.shape}") print(f"Sample rate: {audio_data.sample_rate}") ``` -------------------------------- ### Installing Symusic from Source via PyPI Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/introduction.md This command installs Symusic from its source distribution available on PyPI, bypassing pre-built binaries. This method is used when pre-built wheels are not suitable or for specific build requirements, forcing a local compilation. ```bash pip install --no-binary symusic symusic ``` -------------------------------- ### Loading and Converting Symusic Score Time Units (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md This code illustrates how to specify the time unit (`tick`, `quarter`, `second`) when loading a `symusic.Score` or convert it afterward using the `.to()` method. The `ttype` argument in the constructor or the `.to()` method allows flexible time representation, with an optional `min_dur` for note duration during conversion. This is crucial for consistent time-based analysis or manipulation. ```python from symusic import Score, TimeUnit # you could specify the time unit when loading a score Score("xxx.mid", ttype=TimeUnit.quarter) Score("xxx.txt", fmt="abc", ttype='second') # or convert the time unit after loading # an additional argument `min_dur` is optional, which is the minimum duration of a note Score("xxx.mid", "quarter", ).to("tick", min_dur=1) Score("xxx.txt", fmt="abc").to(TimeUnit.second) ``` -------------------------------- ### Visualizing Piano Roll with Matplotlib (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md This snippet demonstrates how to visualize a piano roll by combining onset and frame data using Matplotlib. The `imshow` function displays the combined data as an image, and `show` renders the plot. ```Python plt.imshow(pianoroll[0] + pianoroll[1], aspect="auto") plt.show() ``` -------------------------------- ### Installing Python Test Dependencies Source: https://github.com/yikai-liao/symusic/blob/main/tests/README.md This command installs the necessary Python packages for running the SyMusic Python tests. It uses `pip` to install `pytest`, the testing framework, and `numpy`, a common dependency for numerical operations often used in music processing. ```bash pip install pytest numpy ``` -------------------------------- ### Building and Installing symusic from Source (Git Clone) Source: https://github.com/yikai-liao/symusic/blob/main/README.md These commands clone the symusic repository recursively and then install the library from the local source directory using pip. This method is used when building from source after cloning the repository, requiring CMake and C++ compilers. ```bash git clone --recursive https://github.com/Yikai-Liao/symusic pip install ./symusic ``` -------------------------------- ### Installing abcmidi Tools with CMake Source: https://github.com/yikai-liao/symusic/blob/main/CMakeLists.txt This snippet integrates the `abcmidi` third-party library and installs its `abc2midi` and `midi2abc` executables into the `symusic/bin` directory. It ensures that the necessary MIDI conversion tools are available after the build. ```CMake add_subdirectory(3rdparty/abcmidi) install(TARGETS abc2midi midi2abc DESTINATION symusic/bin) ``` -------------------------------- ### Installing Data Processing and Visualization Libraries - Bash Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/tutorials/index.md This command installs common Python libraries such as NumPy for numerical operations, Matplotlib for plotting, and SciPy for scientific computing. These libraries are often used in Symusic tutorials for data processing and visualization tasks, complementing Symusic's core functionality. ```Bash pip install numpy matplotlib scipy ``` -------------------------------- ### Installing GCC/G++ via Conda for Symusic Source Build Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/introduction.md These commands demonstrate how to install GCC and G++ compilers using Conda for users without sudo permissions on Linux. It then shows how to specify these Conda-installed compilers when installing Symusic from source, ensuring the correct C++20 compiler is used for compilation. ```bash conda install conda-forge::gcc conda-forge::gxx CC=/path_to_conda_root/envs/env_name/bin/gcc CXX=/path_to_conda_root/envs/env_name/bin/g++ pip install --no-binary symusic symusic ``` -------------------------------- ### Installing symusic with Memory Leak Warning Enabled Source: https://github.com/yikai-liao/symusic/blob/main/README.md This command installs symusic from a local source directory, enabling a memory leak warning during the build process via CMake. This feature, provided by nanobind, is primarily for debugging purposes during development. ```bash pip install -Ccmake.define.MEM_LEAK_WARNING=True ./symusic ``` -------------------------------- ### Dumping Symusic Score to MIDI/ABC File (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md This snippet shows how to save a `symusic.Score` object to a file using `dump_midi` for MIDI format or `dump_abc` for ABC format. Before dumping, the score is automatically converted to the `tick` time unit, which is the raw unit for MIDI files. Users should manually convert to `tick` with `min_dur` if specific note duration handling is required. ```python from symusic import Score s = Score("xxx.mid") s.dump_midi("out.mid") s.dump_abc("out.abc") ``` -------------------------------- ### Converting Symusic Objects to NumPy Arrays (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md This snippet demonstrates how `symusic` objects, specifically `tempos` and `notes`, can be efficiently converted to a Struct of Array (SOA) representation using NumPy arrays. It shows how to access individual arrays within the resulting dictionary and how to convert NumPy arrays back into `symusic` objects. This conversion is useful for high-performance numerical operations. ```python from symusic import Score import numpy as np from typing import Dict s = Score("xxx.mid") # get the numpy arrays tempos: Dict[str, np.ndarray] = s.tempos.numpy() notes: Dict[str, np.ndarray] = s.tracks[0].notes.numpy() # access the array in dict mspq = tempos["mspq"] # a 1D numpy array, dtype is int32. mspq for microsecond per quarter note start = notes["time"] # a 1D numpy array, the dtype is determined by the time unit(ttype) of the score # you could also convert the numpy arrays back to the list of objects from symusic import Note note_list1 = Note.from_numpy(**notes, ttype=s.ttype) note_list2 = Note.from_numpy( time=notes["time"], duration=notes["duration"], pitch=notes["pitch"], velocity=notes["velocity"], ttype=s.ttype ) # The note_list you get here is the same as s.tracks[0].notes ``` -------------------------------- ### Activating Conda Environment and Opening CLion Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/development.md This snippet demonstrates how to activate a specific Conda environment (`symusic-env`) and then launch CLion from the terminal. This ensures that the IDE detects the correct Python environment for development, which is crucial for projects using Python bindings like nanobind. ```bash conda activate symusic-env clion path/to/symusic ``` -------------------------------- ### Accessing Built-in SoundFonts in Symusic Python Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/tutorials/synthesis.md Illustrates how to access and download various built-in SoundFonts provided by Symusic using the `BuiltInSF3` class. It shows examples for MuseScore General, FluidR3 Mono, and FluidR3 GM, highlighting the `path(download=True)` method for obtaining the file path and ensuring download. ```Python from symusic import BuiltInSF3 # Available built-in SoundFonts sf_path = BuiltInSF3.MuseScoreGeneral().path(download=True) # MuseScore General (default) sf_path = BuiltInSF3.FluidR3Mono().path(download=True) # FluidR3 Mono sf_path = BuiltInSF3.FluidR3().path(download=True) # FluidR3 GM ``` -------------------------------- ### Manually Running All Pre-commit Hooks Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/development.md This command manually executes all configured pre-commit hooks on all files in the repository. It's useful for formatting code or checking for issues outside of the commit workflow, such as after generating a PYI file. ```bash pre-commit run --all-files ``` -------------------------------- ### Chaining Batch Operations (Symusic) Source: https://github.com/yikai-liao/symusic/blob/main/tutorial.ipynb This example illustrates method chaining for batch processing operations on a `symusic.Score` object. It shifts the entire score's time, pitch, and velocity, and then sorts the notes, all in a single chained call. ```Python score.shift_time(10) \ .shift_pitch(-6) \ .shift_velocity(-7) \ .sort() ``` -------------------------------- ### Loading MIDI File and Basic Score Info (Symusic) Source: https://github.com/yikai-liao/symusic/blob/main/tutorial.ipynb This snippet demonstrates how to load a MIDI file using `symusic.Score` and access basic information about the entire score, such as the total number of notes, and its start and end times. The time unit is a quarter note. ```Python from symusic import Score score = Score("mahler.mid") print("note_num: ", score.note_num()) print("start_time: ", score.start()) print("end_time: ", score.end()) ``` -------------------------------- ### Creating a MIDI Score Programmatically with Symusic in Python Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/examples/generation.md This snippet demonstrates how to programmatically construct a musical score using the Symusic library. It covers initializing a Score object with a specified ticks per quarter (tpq), adding tempo and time signature events, creating a new track, and populating it with individual Note objects to form a C major scale. Finally, the generated score is saved to a MIDI file. ```python from symusic import Score, Track, Note, Tempo, TimeSignature # Create an empty score with standard ticks per quarter score = Score(tpq=480) # Add tempo and time signature score.tempos.append(Tempo(time=0, qpm=120)) score.time_signatures.append(TimeSignature(time=0, numerator=4, denominator=4)) # Create a piano track piano_track = score.tracks.append_track(name="Generated Piano", program=0) # Generate a simple C major scale pitches = [60, 62, 64, 65, 67, 69, 71, 72] # MIDI pitches for C4 to C5 current_time = 0 quarter_note_duration = 480 # Since tpq=480 for pitch in pitches: note = Note( time=current_time, duration=quarter_note_duration, pitch=pitch, velocity=70 ) piano_track.notes.append(note) current_time += quarter_note_duration # Save the generated score score.dump_midi("generated_scale.mid") print("Generated C major scale saved to generated_scale.mid") ``` -------------------------------- ### Calculating Pitch Histogram with Symusic in Python Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/examples/analysis.md This snippet demonstrates how to load a MIDI file using Symusic, extract all note pitches, and then visualize their distribution as a histogram using Matplotlib and NumPy. It optionally filters out drum tracks to focus on melodic content. ```python from symusic import Score import numpy as np import matplotlib.pyplot as plt score = Score("path/to/file.mid") pitches = [] for track in score.tracks: # Optional: Filter for non-drum tracks if not track.is_drum: for note in track.notes: pitches.append(note.pitch) if pitches: plt.figure() plt.hist(pitches, bins=np.arange(129) - 0.5, density=True) plt.title("Pitch Distribution") plt.xlabel("MIDI Pitch") plt.ylabel("Probability") plt.xlim([-0.5, 127.5]) plt.show() else: print("No notes found.") ``` -------------------------------- ### Setting CMake Build Options for CLion Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/development.md These are CMake options to be set within CLion for building the symusic project. `-DBUILD_PY:BOOL=ON` enables the Python binding target, and `-DBUILD_TEST:BOOL=ON` includes test cases in the build. These flags are essential for a complete development build. ```text -DBUILD_TEST:BOOL=ON -DBUILD_PY:BOOL=ON ``` -------------------------------- ### Loading MIDI File - Symusic - Python Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/cook_book.md This snippet demonstrates how to load a MIDI file into a Symusic Score object. It shows examples of loading with default tick time units, as well as explicitly specifying 'quarter' or 'second' as the time unit for the score. ```python from symusic import Score # Load with default tick time unit score = Score("path/to/file.mid") # Load with quarter note time unit score = Score("path/to/file.mid", ttype="quarter") # Load with second time unit score = Score("path/to/file.mid", ttype="second") ``` -------------------------------- ### Defining Build Options for Symusic Project Source: https://github.com/yikai-liao/symusic/blob/main/CMakeLists.txt This section defines various build options for the Symusic project, allowing users to enable or disable features like Python bindings, examples, tests, link-time optimization (LTO), Intel VTune support, memory leak warnings, and code coverage. ```CMake option(BUILD_SYMUSIC_PY "Build the python binding of symusic" OFF) option(BUILD_SYMUSIC_EXAMPLE "Build the test target" OFF) option(BUILD_SYMUSIC_TEST "Build the test target" OFF) option(ENABLE_LTO "Enables link-time optimization, requires compiler support." ON) option(VTUNE "Compile Options for Intel VTune" Off) option(MEM_LEAK_WARNING "Enable memory leak warning" OFF) option(ENABLE_COVERAGE "Enable code coverage" OFF) ``` -------------------------------- ### Manipulating Symusic Scores in Python Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/examples/generation.md This snippet illustrates how to apply various transformations to an existing Symusic score. It demonstrates transposing the score's pitch using shift_pitch, doubling the tempo by iterating and modifying qpm values, and converting the score's time unit to 'quarter' before rhythmically shifting individual notes using shift_time_inplace to create a syncopated effect. Each modified score is then saved to a new MIDI file. ```python # Continuing from the previous example... # Transpose the generated scale up by a perfect fifth (7 semitones) transposed_score = score.shift_pitch(7) transposed_score.dump_midi("generated_g_major_scale.mid") # Create a version with double tempo double_tempo_score = score.copy() # Create a copy first for tempo in double_tempo_score.tempos: tempo.qpm *= 2.0 double_tempo_score.dump_midi("generated_scale_double_tempo.mid") # Create a version in quarter note time, shift rhythmically score_quarter = score.to("quarter") # Shift every other note later by an eighth note for i, note in enumerate(score_quarter.tracks[0].notes): if i % 2 == 1: note.shift_time_inplace(0.5) # 0.5 quarter notes = eighth note score_quarter.dump_midi("generated_scale_syncopated.mid") ``` -------------------------------- ### Accessing Individual Note Properties (Symusic) Source: https://github.com/yikai-liao/symusic/blob/main/tutorial.ipynb This snippet shows how to extract and print the properties of an individual note object from a `symusic` track. It displays the note's start time, duration, pitch, and velocity. ```Python note = score.tracks[0].notes[0] print("start:\t\t", note.start) print("duration:\t", note.duration) print("pitch:\t\t", note.pitch) print("velocity:\t", note.velocity) ``` -------------------------------- ### Configuring Python Bindings with Nanobind Source: https://github.com/yikai-liao/symusic/blob/main/CMakeLists.txt This conditional block sets up the Python bindings for Symusic using Nanobind if `BUILD_SYMUSIC_PY` is enabled. It finds the Python interpreter and development modules, includes the Nanobind subdirectory, defines a `core` Python module from C++ sources, links it to the `symusic` library, and configures its installation. ```CMake if(BUILD_SYMUSIC_PY) message("Building python binding.") find_package(Python REQUIRED COMPONENTS Interpreter Development.Module) # set symusic target to O3 and release mode because nanobind use minisize # execute_process( # COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir # OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE NB_DIR) # list(APPEND CMAKE_PREFIX_PATH "${NB_DIR}") # find_package(nanobind CONFIG REQUIRED) # show python executable path message(STATUS "Python_EXECUTABLE: ${Python_EXECUTABLE}") add_subdirectory(3rdparty/nanobind EXCLUDE_FROM_ALL) nanobind_add_module( core NB_STATIC STABLE_ABI LTO PROTECT_STACK NOSTRIP NB_DOMAIN symusic py_src/core.cpp py_src/py_utils.h py_src/bind_vector_copy.h ) target_link_libraries(core PRIVATE symusic) install(TARGETS core LIBRARY DESTINATION symusic) endif() ``` -------------------------------- ### Creating New Tracks - Symusic - Python Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/cook_book.md This snippet illustrates how to create a new empty Symusic Score and then add new tracks to it. It shows examples of adding both a regular instrument track (e.g., piano) and a drum track, specifying their name, program, and drum status. ```python # Create an empty score score = Score(tpq=480) # Add a piano track piano_track = score.tracks.append_track(name="Piano", program=0, is_drum=False) # Add a drum track drum_track = score.tracks.append_track(name="Drums", program=0, is_drum=True) ``` -------------------------------- ### Sorting Notes Inplace (Symusic) Source: https://github.com/yikai-liao/symusic/blob/main/tutorial.ipynb This code demonstrates the `sort()` method in `symusic`, which sorts notes within the score or a specific track inplace. It ensures notes are ordered by their start time, which can be crucial for certain processing tasks. ```Python # inplace operation print(score.sort()) print(score.tracks[0].sort()) ``` -------------------------------- ### Saving AudioData to WAV with dump_wav in Symusic (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/api_reference/utility.md This example demonstrates how to use the `dump_wav` function to save `AudioData` to WAV files. It shows how to initialize a `Score` and `Synthesizer`, render audio from a MIDI score, and then save the resulting audio in both standard 16-bit integer and higher-precision 32-bit float WAV formats. ```python from symusic import Score, Synthesizer, dump_wav, BuiltInSF3 score = Score("input.mid") synth = Synthesizer(BuiltInSF3.MuseScoreGeneral().path()) audio = synth.render(score) # Save as standard 16-bit WAV dump_wav("output_int16.wav", audio) # Save as 32-bit float WAV dump_wav("output_float32.wav", audio, use_int16=False) ``` -------------------------------- ### Integrating Symusic with Music Generation Algorithms in Python Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/examples/generation.md This snippet demonstrates how Symusic can serve as an output interface for external music generation algorithms. It provides a create_score_from_events function that takes a list of event tuples (e.g., 'note', 'tempo') and constructs a Symusic Score object. This function processes different event types, adds them to the score, and then sorts the score's events for proper playback, showcasing how to bridge algorithmic output with Symusic's data structures. ```python # Assume 'generated_events' is a list produced by your algorithm # Each element could be like: ("note", time, duration, pitch, velocity) # or ("tempo", time, qpm), etc. def create_score_from_events(generated_events, tpq=480): score = Score(tpq=tpq) # Assume single track for simplicity track = score.tracks.append_track(name="Generated Music") for event_data in generated_events: event_type = event_data[0] if event_type == "note": _, time, duration, pitch, velocity = event_data track.notes.append(Note(time, duration, pitch, velocity)) elif event_type == "tempo": _, time, qpm = event_data score.tempos.append(Tempo(time, qpm)) # ... handle other event types ... # It's good practice to sort events after adding them score.sort() return score # Example generated events (simple melody) generation_output = [ ("tempo", 0, 100), ("note", 0, 480, 60, 80), ("note", 480, 480, 62, 80), ("note", 960, 960, 64, 80), ("tempo", 1920, 80), ("note", 1920, 480, 62, 70), ("note", 2400, 480, 60, 70), ] generated_score = create_score_from_events(generation_output) generated_score.dump_midi("output_from_algorithm.mid") ``` -------------------------------- ### Adding MIDI Control Change Events with Symusic (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/cook_book.md This snippet demonstrates how to add `ControlChange` events to a `symusic` track. It shows examples for adding volume (controller 7), expression (controller 11), and sustain pedal (controller 64) events at specific times and values, allowing for dynamic control over instrument parameters. ```python from symusic import ControlChange # Add volume control (controller 7) track.controls.append(ControlChange(time=0, number=7, value=100)) # Add expression control (controller 11) track.controls.append(ControlChange(time=0, number=11, value=127)) # Add sustain pedal events (controller 64) track.controls.append(ControlChange(time=0, number=64, value=127)) track.controls.append(ControlChange(time=960, number=64, value=0)) ``` -------------------------------- ### Inspecting Symusic Score Contents in Python Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/tutorials/midi_operations.md This snippet illustrates how to access and inspect various properties and events within a loaded Symusic `Score` object. It demonstrates retrieving the number of tracks, total notes, score duration, iterating through tracks to get their names, programs, and drum status, accessing global tempo changes, and listing the first few notes of a specific track. ```python # Basic information print(f"Number of tracks: {score_tick.track_num()}") print(f"Total notes: {score_tick.note_num()}") print(f"Score duration (ticks): {score_tick.end() - score_tick.start()}") # Access tracks print("\nTracks:") for i, track in enumerate(score_tick.tracks): print(f" Track {i}: Name='{track.name}', Program={track.program}, IsDrum={track.is_drum}, Notes={track.note_num()}") # Access global events (e.g., tempos) print("\nTempo Changes:") for tempo in score_tick.tempos: print(f" Time={tempo.time}, QPM={tempo.qpm}") # Access notes in the first track first_track = score_tick.tracks[0] print("\nFirst 5 notes of Track 0:") for note in first_track.notes[:5]: print(f" Time={note.time}, Dur={note.duration}, Pitch={note.pitch}, Vel={note.velocity}") ``` -------------------------------- ### Adding MIDI Pedal Events with Symusic (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/cook_book.md This snippet demonstrates how to add `Pedal` events to a `symusic` track. It shows an example of adding a sustain pedal event with a specified start time and duration, which is useful for controlling sustain or other pedal-related effects. ```python from symusic import Pedal # Add sustain pedal with duration track.pedals.append(Pedal(time=0, duration=960)) ``` -------------------------------- ### Building C++ Tests with CMake Source: https://github.com/yikai-liao/symusic/blob/main/tests/README.md This snippet provides the bash commands to build the C++ test suite for SyMusic. It creates a build directory, navigates into it, configures the project with CMake to enable test building, and then compiles the project using `make`. ```bash mkdir -p build && cd build cmake .. -DBUILD_TESTS=ON make -j ``` -------------------------------- ### Synthesizing Audio with Symusic and SoundFonts (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/cook_book.md This snippet demonstrates how to load a MIDI score, initialize a `Synthesizer` with a built-in SoundFont, render the score into audio data, and save the output as a WAV file. It requires the `symusic` library and a SoundFont for audio generation. ```python from symusic import Score, Synthesizer, BuiltInSF3, dump_wav # Load a score score = Score("input.mid") # Create a synthesizer using a built-in SoundFont synthesizer = Synthesizer( sf_path=BuiltInSF3.MuseScoreGeneral().path(download=True), sample_rate=44100, quality=4 ) # Render the score to audio audio_data = synthesizer.render(score, stereo=True) # Save the audio to a WAV file dump_wav("output.wav", audio_data) ``` -------------------------------- ### Generating Piano Roll from Symusic Score (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/quick_start.md This snippet demonstrates how to convert a `symusic` `Score` or `Track` object into a piano roll, represented as a multi-dimensional NumPy array. It highlights the importance of resampling the score for size reduction and explains how to configure the piano roll's modes, pitch range, and velocity encoding. The output is a 3D or 4D NumPy array suitable for machine learning or analysis. ```python from symusic import Score s = Score("xxx.mid") # You'd better resample the score before converting it to the piano roll to reduce the size of it # tpq=6 means that the minimum time unit is 1/6 quarter note or 1/24 note # min_dur=1 means that the duration of a note is at least 1 time unit s_quantized = s.resample(tpq=6, min_dur=1) # 4D np array, [modes, tracks, pitch, time] s_pianoroll = s_quantized.pianoroll( # the modes of the piano roll, which determines the "modes dim" # only the following modes are supported: "onset", "frame", "offset" # you could determine the order by yourself modes=["onset", "frame", "offset"], # List[str] pitch_range=[0, 128], # the pitch range (half-open interval) of the piano roll, [0, 128) by default encode_velocity=True # make the pianoroll binary or filled with velocity ) # 3D np array, [modes, pitch, time] t_pianoroll = s_quantized.tracks[0].pianoroll( modes=["onset", "frame", "offset"], pitch_range=[0, 128], encode_velocity=True ) ``` -------------------------------- ### Initializing Symusic Synthesizer in Python Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/api_reference/synthesizer.md This snippet demonstrates how to initialize the `Synthesizer` class. It requires a SoundFont file path, an optional sample rate, and a quality setting. The `sf_path` can be a custom path or a built-in SoundFont from `symusic.BuiltInSF2` or `symusic.BuiltInSF3`. ```python from symusic import Synthesizer from pathlib import Path # Initialize with a SoundFont path synthesizer = Synthesizer( sf_path: str | Path, # Path to the .sf2 or .sf3 file sample_rate: int = 44100, # Desired sample rate in Hz quality: int = 0 # Synthesis quality (0-6, higher means better quality but slower) ) ``` -------------------------------- ### Performing Basic Audio Synthesis with Symusic in Python Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/tutorials/synthesis.md Demonstrates the fundamental steps to load a MIDI file, initialize the `Synthesizer` with a built-in SoundFont, render the score to an `AudioData` object, and save the resulting audio to a WAV file. It uses `BuiltInSF3.MuseScoreGeneral` as the SoundFont and sets a sample rate of 44100 Hz. ```Python from symusic import Score, Synthesizer, BuiltInSF3, dump_wav # Load a MIDI file score = Score("path/to/file.mid") # Create a synthesizer with default settings synthesizer = Synthesizer( sf_path=BuiltInSF3.MuseScoreGeneral().path(download=True), sample_rate=44100, quality=4 # Default quality setting ) # Render the score to audio (returns an AudioData object) audio_data = synthesizer.render(score, stereo=True) # Save the audio to a WAV file dump_wav("output.wav", audio_data) ``` -------------------------------- ### Configuring Symusic Synthesizer Parameters in Python Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/tutorials/synthesis.md Details the key parameters available when initializing the `Synthesizer` class in Symusic. It explains the purpose of `sf_path` (SoundFont file path), `sample_rate` (audio sample rate in Hz), and `quality` (synthesis quality setting from 0 to 6). ```Python synthesizer = Synthesizer( sf_path, # Path to the SoundFont file (string or Path) sample_rate, # Sample rate in Hz (default: 44100) quality # Synthesis quality (0-6, default: 0 in factory, 4 often good) ) ``` -------------------------------- ### Running All C++ Tests Source: https://github.com/yikai-liao/symusic/blob/main/tests/README.md This command executes the entire C++ test suite for SyMusic. It runs the compiled test executable located in the `build/tests/cpp/` directory, which will run all defined Catch2 test cases. ```bash ./tests/cpp/symusic_tests ``` -------------------------------- ### Creating a Note Event in Symusic (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/api_reference/events.md Initializes a musical note event with specified start time, duration, pitch, and velocity. The `ttype` parameter determines the time unit for the event, defaulting to 'tick'. ```python symusic.Note(time, duration, pitch, velocity, ttype="tick") ``` -------------------------------- ### Initializing Symusic Score Objects (Python) Source: https://github.com/yikai-liao/symusic/blob/main/docs/src/api_reference/score.md This snippet demonstrates how to create new `Score` instances using direct constructors. It covers creating an empty score with a specified ticks-per-quarter (TPQ) and time unit, loading a score from a file path (inferring or specifying format), and creating a deep copy of an existing score, optionally converting its time unit during the copy. ```python from symusic import Score, TimeUnit from pathlib import Path # Create an empty score with specified TPQ and time unit s = Score(tpq: int = 960, ttype: str | TimeUnit = "tick") # Load score from a file path # Format (fmt) is usually inferred from extension, can be 'midi' or 'abc' s = Score(path: str | Path, ttype: str | TimeUnit = "tick", fmt: str | None = None) # Copy constructor (creates a deep copy) s_copy = Score(other: Score, ttype: str | TimeUnit | None = None) # If ttype is provided, performs deep copy AND time unit conversion. # If ttype is None, keeps the original time unit. ```