WillieCubed commited on
Commit
38b0a66
0 Parent(s):

feat: Initial commit

Browse files

This creates a Gradio app that will let someone create sheet music out
of a given song.

.gitattributes ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Auto-convert line endings
2
+ * text=auto
3
+
4
+ # Blob stuffs
5
+ *.7z filter=lfs diff=lfs merge=lfs -text
6
+ *.arrow filter=lfs diff=lfs merge=lfs -text
7
+ *.bin filter=lfs diff=lfs merge=lfs -text
8
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
9
+ *.ftz filter=lfs diff=lfs merge=lfs -text
10
+ *.gz filter=lfs diff=lfs merge=lfs -text
11
+ *.h5 filter=lfs diff=lfs merge=lfs -text
12
+ *.joblib filter=lfs diff=lfs merge=lfs -text
13
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
14
+ *.model filter=lfs diff=lfs merge=lfs -text
15
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pt filter=lfs diff=lfs merge=lfs -text
21
+ *.pth filter=lfs diff=lfs merge=lfs -text
22
+ *.rar filter=lfs diff=lfs merge=lfs -text
23
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
24
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
25
+ *.tflite filter=lfs diff=lfs merge=lfs -text
26
+ *.tgz filter=lfs diff=lfs merge=lfs -text
27
+ *.wasm filter=lfs diff=lfs merge=lfs -text
28
+ *.xz filter=lfs diff=lfs merge=lfs -text
29
+ *.zip filter=lfs diff=lfs merge=lfs -text
30
+ *.zstandard filter=lfs diff=lfs merge=lfs -text
31
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # .gitignore courtesy of GitHub: https://github.com/github/gitignore/blob/main/Python.gitignore
2
+
3
+ # Byte-compiled / optimized / DLL files
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+
8
+ # C extensions
9
+ *.so
10
+
11
+ # Distribution / packaging
12
+ .Python
13
+ build/
14
+ develop-eggs/
15
+ dist/
16
+ downloads/
17
+ eggs/
18
+ .eggs/
19
+ lib/
20
+ lib64/
21
+ parts/
22
+ sdist/
23
+ var/
24
+ wheels/
25
+ share/python-wheels/
26
+ *.egg-info/
27
+ .installed.cfg
28
+ *.egg
29
+ MANIFEST
30
+
31
+ # PyInstaller
32
+ # Usually these files are written by a python script from a template
33
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
34
+ *.manifest
35
+ *.spec
36
+
37
+ # Installer logs
38
+ pip-log.txt
39
+ pip-delete-this-directory.txt
40
+
41
+ # Unit test / coverage reports
42
+ htmlcov/
43
+ .tox/
44
+ .nox/
45
+ .coverage
46
+ .coverage.*
47
+ .cache
48
+ nosetests.xml
49
+ coverage.xml
50
+ *.cover
51
+ *.py,cover
52
+ .hypothesis/
53
+ .pytest_cache/
54
+ cover/
55
+
56
+ # Translations
57
+ *.mo
58
+ *.pot
59
+
60
+ # Django stuff:
61
+ *.log
62
+ local_settings.py
63
+ db.sqlite3
64
+ db.sqlite3-journal
65
+
66
+ # Flask stuff:
67
+ instance/
68
+ .webassets-cache
69
+
70
+ # Scrapy stuff:
71
+ .scrapy
72
+
73
+ # Sphinx documentation
74
+ docs/_build/
75
+
76
+ # PyBuilder
77
+ .pybuilder/
78
+ target/
79
+
80
+ # Jupyter Notebook
81
+ .ipynb_checkpoints
82
+
83
+ # IPython
84
+ profile_default/
85
+ ipython_config.py
86
+
87
+ # pyenv
88
+ # For a library or package, you might want to ignore these files since the code is
89
+ # intended to run in multiple environments; otherwise, check them in:
90
+ # .python-version
91
+
92
+ # pipenv
93
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
94
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
95
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
96
+ # install all needed dependencies.
97
+ #Pipfile.lock
98
+
99
+ # poetry
100
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
101
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
102
+ # commonly ignored for libraries.
103
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
104
+ #poetry.lock
105
+
106
+ # pdm
107
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
108
+ #pdm.lock
109
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
110
+ # in version control.
111
+ # https://pdm.fming.dev/#use-with-ide
112
+ .pdm.toml
113
+
114
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
115
+ __pypackages__/
116
+
117
+ # Celery stuff
118
+ celerybeat-schedule
119
+ celerybeat.pid
120
+
121
+ # SageMath parsed files
122
+ *.sage.py
123
+
124
+ # Environments
125
+ .env
126
+ .venv
127
+ env/
128
+ venv/
129
+ ENV/
130
+ env.bak/
131
+ venv.bak/
132
+
133
+ # Spyder project settings
134
+ .spyderproject
135
+ .spyproject
136
+
137
+ # Rope project settings
138
+ .ropeproject
139
+
140
+ # mkdocs documentation
141
+ /site
142
+
143
+ # mypy
144
+ .mypy_cache/
145
+ .dmypy.json
146
+ dmypy.json
147
+
148
+ # Pyre type checker
149
+ .pyre/
150
+
151
+ # pytype static type analyzer
152
+ .pytype/
153
+
154
+ # Cython debug symbols
155
+ cython_debug/
156
+
157
+ # PyCharm
158
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
159
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
160
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
161
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
162
+ #.idea/
.vscode/launch.json ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+ {
8
+ "name": "Launch Demo",
9
+ "type": "python",
10
+ "request": "launch",
11
+ "module": "app",
12
+ "justMyCode": true
13
+ }
14
+ ]
15
+ }
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Willie Chalmers III
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.
README.md ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ # Hugging Face Spaces meta data
3
+ # See https://huggingface.co/docs/hub/spaces#reference
4
+ title: Song to Sheet
5
+ emoji: 🎼
6
+ colorFrom: gray
7
+ colorTo: blue
8
+ sdk: gradio
9
+ app_file: app.py
10
+ pinned: true
11
+ license: mit
12
+ ---
13
+
14
+ # Song to Sheet
15
+
16
+ _A tool to create sheet music out of songs._
17
+
18
+ ## About
19
+
20
+ ### Inspiration
21
+
22
+ I took an intro to deep learning class and was very unsatisfied with my
23
+ performance, so I made this in a bout of curiosity.
24
+
25
+ ### How to use
26
+
27
+ #### Casual Demo
28
+
29
+ Coming soon: a demo on Hugging Face Spaces!
30
+
31
+ #### Manual Installation
32
+
33
+ Prerequisites:
34
+
35
+ - Python 3.8 (really, anything above 3.6 will still work)
36
+ - pip (or another package manager if you know what you're doing)
37
+
38
+ If you're cloning from source, first install the dependencies:
39
+
40
+ ```bash
41
+ # Optional: Create and activate a virtual environment
42
+ python -m venv song-to-sheet
43
+ ./song-to-sheet/bin/activate # On windows: song-to-sheet\Scripts\activate
44
+
45
+ # Now install the dependencies
46
+ pip install -r requirements.txt
47
+ ```
48
+
49
+ After getting set up, run the `app.py` script:
50
+
51
+ ```bash
52
+ python app.py
53
+ ```
54
+
55
+ You can also run it standalone (on bash):
56
+
57
+ ```bash
58
+ ./app.py
59
+ ```
app.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ from typing import Tuple
4
+ import gradio as gr
5
+ import numpy as np
6
+
7
+ from song_to_sheet.generator import SheetMusicGenerator
8
+
9
+ INTRO_MESSAGE = """
10
+ # Song to Sheet
11
+
12
+ Upload a song file, and get sheet music of that song or MIDI.
13
+
14
+ When you upload your track, we'll analyze what instruments are in the song and
15
+ let you specify for which instruments we will generate the sheet music.
16
+
17
+ *Note: This demo is currently non-functional! Only the project structure*
18
+ *exists right now.*
19
+
20
+ """
21
+
22
+ OUTPUT_INFO = """
23
+ After the song has been analyzed, you can generate a MIDI and PDF conversion of
24
+ the song by clicking "Generate Sheet". The outputs will appear below!
25
+ """
26
+
27
+
28
+ generator = SheetMusicGenerator()
29
+
30
+
31
+ def process_input(inputs: Tuple[int, np.ndarray]):
32
+ _, raw_data = inputs
33
+ print(inputs)
34
+ print(raw_data.shape)
35
+ return generator.analyze_track(raw_data)
36
+
37
+
38
+ def get_final_outputs():
39
+ return generator.generate_midi(), generator.generate_pdf()
40
+
41
+
42
+ gr.Interface
43
+
44
+ demo = gr.Blocks()
45
+
46
+ with demo:
47
+ gr.Markdown(INTRO_MESSAGE)
48
+ with gr.Row().style(equal_height=False):
49
+ with gr.Column():
50
+ audio_in = gr.Audio(source="upload", label="Upload song")
51
+ analyze_music_button = gr.Button("Analyze song")
52
+ instruments_detected = gr.Label(label="Instrument Likelihoods")
53
+ generate_sheet_button = gr.Button("Generate Sheet")
54
+ with gr.Column():
55
+ gr.Markdown(OUTPUT_INFO)
56
+ with gr.Tabs():
57
+ with gr.TabItem("MIDI output"):
58
+ output_midi = gr.File(
59
+ label="Download MIDI output", type="binary")
60
+ with gr.TabItem("Sheet music"):
61
+ output_sheet = gr.File(
62
+ label="Downlaod sheet music", type="binary")
63
+
64
+ # TODO: Include song statistics
65
+
66
+ analyze_music_button.click(
67
+ fn=process_input,
68
+ inputs=[
69
+ audio_in
70
+ ],
71
+ outputs=[
72
+ instruments_detected,
73
+ ]
74
+ )
75
+ generate_sheet_button.click(
76
+ fn=get_final_outputs,
77
+ inputs=[],
78
+ outputs=[
79
+ output_midi,
80
+ output_sheet
81
+ ]
82
+ )
83
+
84
+ demo.launch()
data/references.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Project References
2
+
3
+ These are the things that helped in building this project.
4
+
5
+ ## Tools/Software
6
+
7
+ ## Web-based Guides, Tutorials
8
+
9
+ - [I built a sheet music transcriber](https://towardsdatascience.com/i-built-a-music-sheet-transcriber-heres-how-74708fe7c04c)
10
+
11
+ ## Research
12
+
13
+ ## Other
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ gradio
song_to_sheet/detector.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+ # TODO: Replace me with real process
4
+ TEST_OUTPUTS = {
5
+ 'piano': 0.95,
6
+ 'guitar': 0.7,
7
+ 'voice': 0.5,
8
+ 'other': 0.2,
9
+ }
10
+
11
+
12
+ def detect_instruments(audio_data: np.ndarray):
13
+ """Run inference on a model to detect instruments in the given audio data.
14
+
15
+ This assumes that the audio given is a song or can be decomposed into
16
+ discrete instruments.
17
+
18
+ Returns:
19
+ Dict[str, float]: predicted confidences of instruments present in the
20
+ track.
21
+ """
22
+ return TEST_OUTPUTS
song_to_sheet/generator.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tempfile
2
+ from pathlib import Path
3
+ from typing import Dict
4
+ import numpy as np
5
+
6
+ from song_to_sheet.detector import detect_instruments
7
+
8
+
9
+ class SheetMusicGenerator:
10
+ """A module that generates sheet music from sounds."""
11
+
12
+ def __init__(self, verbose=False):
13
+ """
14
+ Args:
15
+ verbose (bool): Whether to show detailed logging information.
16
+ """
17
+ self._song_data = None
18
+ self._verbose = verbose
19
+
20
+ def analyze_track(self, raw_data: np.ndarray) -> Dict[str, float]:
21
+ """Perform some preprocessing on the track and cache it in memory.
22
+
23
+ Args:
24
+ raw_data (ndarray): The encoded data from the track.
25
+
26
+ Returns:
27
+ Dict[str, float]:
28
+ """
29
+ self._song_data = raw_data
30
+ try:
31
+ instruments = self._detect_instruments(raw_data)
32
+ # TODO: Figure out how to handle multiple instruments of the same type
33
+ except:
34
+ pass
35
+
36
+ return instruments
37
+
38
+ def _detect_instruments(self, raw_data: np.ndarray):
39
+ """Return a list of instruments and their probalities of being in the track."""
40
+ # TODO: Detect if given track even is a song (maybe)
41
+ instruments = detect_instruments(raw_data)
42
+ return instruments
43
+
44
+ def generate_midi(self):
45
+ """Generate a MIDI file of the current song."""
46
+ file = tempfile.NamedTemporaryFile(
47
+ delete=False, prefix='transcribed_song_', suffix='.mid')
48
+ return file.name
49
+
50
+ def generate_pdf(self):
51
+ """Generate a PDF file with the sheet music of the current song."""
52
+ file = tempfile.NamedTemporaryFile(
53
+ delete=False, prefix='transcribed_song_', suffix='.pdf')
54
+ return file.name
55
+
56
+
57
+ class PDFGenerator:
58
+ """A module that generates PDFs of standard Western music notation."""