Skip to content

jizhang495/wavemusic

Repository files navigation

WaveMusic

Writing music audio files using sine, square, triangular and sawtooth wave

C++ Implementation

Architecture of the C++ implementation




                                  main()
                             ┌──────────────────────────┐
                             │                          │
                             │   Write WAV              │
                             │   header                 │
               sigen.cpp     │                          │
                             │     │                    │
┌──────────────────────────┐ │     ▼                    │
│                          │ │                          │
│ play()       Generate    │ │   Parse        parse()   │
│              signals   ◄─┼─┼── score                  │
│                          │ │                          │
│                 │        │ │     │                    │
│                 ▼        │ │     │                    │
│                          │ │     │                    │
│ filter()     A/R filter  │ │     │                    │
│                          │ │     │                    │
│                 │        │ │     │                    │
│                 ▼        │ │     ▼                    │
│                          │ │                          │
│ lowpass()    Low pass  ──┼─┼─► Write                  │
│              filter      │ │   notes                  │
│                          │ │                          │
└──────────────────────────┘ │     │                    │
                             │     ▼                    │
                             │                          │
                             │   Insert data size       │
                             │   in WAV header          │
                             │                          │
                             │     │                    │
                             │     ▼                    │
                             │                          │
                             │   Playback               │
                             │   with                   │
                             │   system Call            │
                             │                          │
                             └──────────────────────────┘

To use the C++ version:

make simple
./simple sheets/<title>.wmusic

for debug mode:

make refresh DEBUG=1
./simple sheets/<title>.wmusic

Python Implementation

The wave module in the Python standard library provides a convenient interface to the WAV sound format. References: https://docs.python.org/3/library/wave.html https://www.tutorialspoint.com/read-and-write-wav-files-using-python-wave

On Linux

(Note: WSL may need extra configuration to display GUI and play sound.)

To incorporate the C++ code as a backend, use pybind11:

sudo apt install python3-dev g++ cmake pybind11-dev
uv run setup.py build_ext --inplace

where uv is recommended for dependency management.

To run the python script:

uv run main.py

or

uv run main.py gui

To use command-line interface:

uv run main.py cli

To generate WAV from score:

uv run main.py sheets/<title>.wmusic

To build a standalone app:

uv run pyinstaller main.py --onefile 
# pyinstaller main.py --onefile --clean --noconsole --icon=icon.ico

On Windows

Use MSYS2 MINGW x64 terminal:

pacman -Syu
# Close terminal, reopen it (again in MinGW 64-bit)
pacman -Syu

To use inside VScode: In VScode, open Settings, search for 'terminal.integrated.profiles.windows' - Edit in settings.json - add:

"terminal.integrated.profiles.windows": {
  "MSYS2 MinGW 64-bit": {
    "path": "C:\\msys64\\usr\\bin\\bash.exe",
    "args": ["--login", "-i"],
    "env": {
      "MSYSTEM": "MINGW64",
      "CHERE_INVOKING": "1"
    }
  }
},
"terminal.integrated.defaultProfile.windows": "MSYS2 MinGW 64-bit"

Restart VScode, open terminal.

pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-python-pip mingw-w64-x86_64-pybind11 git
g++ --version
python --version
cmake --version

Set up .venv and dependencies (uv can be tricky in MSYS2 Mingw)

python -m venv .venv
source .venv/bin/activate
pip install --upgrade -r requirements.txt
python setup.py build_ext --inplace

To run the python script:

python main.py

To build a standalone app:

pyinstaller main.py --onefile 
# pyinstaller main.py --onefile --clean --noconsole --icon=icon.ico

Python TODO list:

  • time different implementations main_cpp.py, main_list.py, main_np.py and compare with C++
  • write tests
  • add docs
  • use C++ code as a backend
  • add waveforms.py to store functions for each waveform
  • add Entry with up/down for transpose
  • use () to pass frequecies or chords
  • add bpm and sample rate selection
  • use numpy for faster performance
  • the functions can be added to produce complex timber and polyphony
  • add loudness: ff, f, fp, p, pp
  • add dynamics: cresc, dim
  • add timber
  • GUI (maybe try webapp next? Electrojs?)
  • add polyphony (fugue)
  • live waveform plotting matplotlib like oscilloscope
  • playsound on the go with Enter (plays the line just completed)
  • threading, running playsound at background (already okay with vlc open)

C++ TODO list:

  • consistent note length
  • functional REPL
  • triangle wave generation
  • polyphony doesn't sound out of tune anymore?
  • saw and square waves sounds bad, add LPF to soften it

Using uv for Python dependency management

Installing uv:

curl -LsSf https://astral.sh/uv/install.sh | sh

Syncing Python version, .venv, dependencies (optional command):

uv sync

Using .venv (optional command, as it should be automatic):

source ./venv/Scripts/activate

Syncing and running project:

uv run main.py

Linting with ruff:

uvx ruff check .
uvx ruff format

Other useful commands:

Creating 'pyproject.toml' and '.python-version:

uv init

Adding package dependencies to 'pyproject.toml':

uv add <package>

Adding package dependencies from 'requirements.txt' to 'pyproject.toml':

uv add -r requirements.txt

Adding ruff and pytest as development dependencies:

uv add ruff --dev
uv add pytest --dev

Generating 'requirements.txt' from a UV lock file:

uv export -o requirements.txt

About

Writing music audio files using sine, square, triangular and sawtooth waves

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •