breakdig 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. breakdig-0.1.0/CHANGELOG.md +35 -0
  2. breakdig-0.1.0/LICENSE +21 -0
  3. breakdig-0.1.0/MANIFEST.in +3 -0
  4. breakdig-0.1.0/PKG-INFO +379 -0
  5. breakdig-0.1.0/README.md +341 -0
  6. breakdig-0.1.0/breakdig/__init__.py +3 -0
  7. breakdig-0.1.0/breakdig/__main__.py +3 -0
  8. breakdig-0.1.0/breakdig/audio.py +107 -0
  9. breakdig-0.1.0/breakdig/beats.py +62 -0
  10. breakdig-0.1.0/breakdig/cli.py +343 -0
  11. breakdig-0.1.0/breakdig/db.py +240 -0
  12. breakdig-0.1.0/breakdig/export.py +349 -0
  13. breakdig-0.1.0/breakdig/indexer.py +371 -0
  14. breakdig-0.1.0/breakdig/isolate.py +46 -0
  15. breakdig-0.1.0/breakdig/profile.py +69 -0
  16. breakdig-0.1.0/breakdig/query.py +288 -0
  17. breakdig-0.1.0/breakdig/scan.py +146 -0
  18. breakdig-0.1.0/breakdig/separate.py +68 -0
  19. breakdig-0.1.0/breakdig/web/__init__.py +0 -0
  20. breakdig-0.1.0/breakdig/web/app.py +224 -0
  21. breakdig-0.1.0/breakdig/web/static/index.html +485 -0
  22. breakdig-0.1.0/breakdig.egg-info/PKG-INFO +379 -0
  23. breakdig-0.1.0/breakdig.egg-info/SOURCES.txt +35 -0
  24. breakdig-0.1.0/breakdig.egg-info/dependency_links.txt +1 -0
  25. breakdig-0.1.0/breakdig.egg-info/entry_points.txt +2 -0
  26. breakdig-0.1.0/breakdig.egg-info/requires.txt +15 -0
  27. breakdig-0.1.0/breakdig.egg-info/top_level.txt +1 -0
  28. breakdig-0.1.0/pyproject.toml +68 -0
  29. breakdig-0.1.0/setup.cfg +4 -0
  30. breakdig-0.1.0/tests/conftest.py +92 -0
  31. breakdig-0.1.0/tests/fixtures/make_fixture.py +118 -0
  32. breakdig-0.1.0/tests/test_cli.py +223 -0
  33. breakdig-0.1.0/tests/test_export.py +393 -0
  34. breakdig-0.1.0/tests/test_gpu.py +72 -0
  35. breakdig-0.1.0/tests/test_pipeline.py +607 -0
  36. breakdig-0.1.0/tests/test_query.py +225 -0
  37. breakdig-0.1.0/tests/test_web.py +229 -0
@@ -0,0 +1,35 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 (2026-09-29)
4
+
5
+ First release.
6
+
7
+ - `breakdig index` separates each track into drums, bass, vocals and other with Demucs
8
+ (htdemucs_ft through audio-separator), finds downbeats with beat_this, and stores
9
+ per-bar stem levels in a local SQLite index. Resumable and idempotent; the same audio
10
+ in another format or at another path is recognised and not separated twice, and a
11
+ retagged, moved or renamed file keeps its analysis. `--exclude` skips files and folders
12
+ by name, and a second run on the same index stops rather than racing the first. Reads
13
+ MP3, FLAC, WAV, AIFF, M4A, AAC, OGG, Opus and WMA.
14
+ - `breakdig find` lists bar-exact sections by what is playing: drums only, vocals only,
15
+ bass and drums only, anything with no drums, and so on. Filters for length, tempo and
16
+ words in the tags or path; sorted by how clean the section is, and `--cleaner-than`
17
+ sets a floor.
18
+ `--silence-db` loosens the silence rule when separation bleed hides sections you can hear.
19
+ - `breakdig export` cuts sections from the original file at the bar lines, snapped to
20
+ the quietest point within 2 ms, as tagged WAV. `--sp404` writes 16-bit 48 kHz files named
21
+ BRK_0001.WAV with an index.csv, and `--sp404 sx` writes 44.1 kHz for the SX, A and
22
+ original 404. Exporting again overwrites or skips what is there, even
23
+ after the library moves, and relists clips from an export that was cut off.
24
+ - `breakdig export --keep drums` (or `drums,bass`, and so on) exports only those stems:
25
+ each section is separated again with a few seconds either side and put back at the
26
+ source sample rate, so the drums can be taken out of bars where a bassline or pad plays
27
+ over them.
28
+ - Exported WAVs have a cue point on every beat.
29
+ - `breakdig ui` opens a local web UI to filter, audition and export sections. Previews loop
30
+ with no gap, ticked rows are kept across searches, and the filters, volume and loop
31
+ setting are remembered. Each row shows a small grid of the four stems' levels per bar,
32
+ and a keep menu previews and exports just the stems you pick.
33
+ - `breakdig stats` shows what is indexed, what failed and why, and indexing speed.
34
+ - `python -m breakdig` works as well as the `breakdig` command.
35
+ - `find --json` includes each section's beat times and per-bar stem levels.
breakdig-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Booyaka101
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.
@@ -0,0 +1,3 @@
1
+ include CHANGELOG.md
2
+ recursive-include tests *.py
3
+ global-exclude __pycache__ *.py[co]
@@ -0,0 +1,379 @@
1
+ Metadata-Version: 2.4
2
+ Name: breakdig
3
+ Version: 0.1.0
4
+ Summary: Find bar-exact drum breaks, acapellas and other sections in your own music library, using GPU stem separation and downbeat tracking.
5
+ Author: Booyaka101
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Booyaka101/breakdig
8
+ Project-URL: Issues, https://github.com/Booyaka101/breakdig/issues
9
+ Project-URL: Changelog, https://github.com/Booyaka101/breakdig/blob/main/CHANGELOG.md
10
+ Keywords: drum breaks,sampling,stem separation,demucs,downbeat,beat tracking,sp-404,crate digging
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Environment :: Web Environment
14
+ Classifier: Intended Audience :: End Users/Desktop
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: audio-separator[gpu]>=0.47
24
+ Requires-Dist: audioread>=2.1.9
25
+ Requires-Dist: beat-this>=1.1
26
+ Requires-Dist: numpy>=2
27
+ Requires-Dist: soundfile>=0.12
28
+ Requires-Dist: soxr>=0.3
29
+ Requires-Dist: mutagen>=1.47
30
+ Requires-Dist: fastapi>=0.115
31
+ Requires-Dist: starlette>=0.39
32
+ Requires-Dist: uvicorn>=0.36
33
+ Requires-Dist: tqdm>=4.66
34
+ Provides-Extra: test
35
+ Requires-Dist: pytest>=8; extra == "test"
36
+ Requires-Dist: httpx>=0.27; extra == "test"
37
+ Dynamic: license-file
38
+
39
+ # breakdig
40
+
41
+ Find the drum breaks, acapellas and other bare sections in your own music, cut to the bar.
42
+
43
+ breakdig runs every track in a folder through Demucs source separation and a downbeat
44
+ tracker, then keeps a small index of how loud the drums, bass, vocals and everything else
45
+ are in each bar. After that you can ask for "drums only, at least 2 bars, 85 to 100 BPM" and
46
+ get back exact bar ranges you can audition and export from the original files.
47
+
48
+ Everything runs locally. Nothing is uploaded anywhere.
49
+
50
+ ![breakdig UI](https://raw.githubusercontent.com/Booyaka101/breakdig/main/docs/demo.gif)
51
+
52
+ ## Install
53
+
54
+ You need Python 3.11, ffmpeg on PATH, and for reasonable speed an NVIDIA GPU. On Windows:
55
+
56
+ ```
57
+ winget install Python.Python.3.11
58
+ winget install Gyan.FFmpeg
59
+ ```
60
+
61
+ On Windows the simplest route is the zip. Download `breakdig-0.1.0-windows.zip` from the
62
+ GitHub release, unzip it somewhere permanent, and run `install.bat`. It makes a virtual
63
+ environment next to itself, installs breakdig into it, and swaps in the CUDA build of
64
+ PyTorch if `nvidia-smi` is present. It prints the full path to `breakdig.bat` to use
65
+ afterwards; add the folder to PATH to type just `breakdig`.
66
+
67
+ Or with pip:
68
+
69
+ ```
70
+ py -3.11 -m venv .venv
71
+ .venv\Scripts\activate
72
+ pip install breakdig
73
+ pip install --force-reinstall --no-deps torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu130
74
+ ```
75
+
76
+ The last line matters. On Windows, pip resolves torch to the CPU-only build, and separation
77
+ on the CPU is 10 to 30 times slower. The cu130 wheels need NVIDIA driver 580 or newer; with
78
+ an older driver use `cu126` in the URL instead. breakdig prints a warning when it is running
79
+ without CUDA.
80
+
81
+ The first `breakdig index` downloads two models: htdemucs_ft (322 MB) into
82
+ `%LOCALAPPDATA%\breakdig\models`, and the beat_this checkpoint (81 MB) into the PyTorch hub
83
+ cache at `%USERPROFILE%\.cache\torch\hub\checkpoints`. If the Demucs download is cut short,
84
+ the run stops and deletes the partial file, and the next run downloads it again.
85
+
86
+ ## Quick start
87
+
88
+ Index a folder. This is the slow part and it only happens once per track:
89
+
90
+ ```
91
+ > breakdig index D:\Music\Breaks
92
+ Scanning 14 files...
93
+ 0 already indexed, 14 to do. Index: C:\Users\you\AppData\Local\breakdig
94
+ Done in 189s: 14 ok.
95
+ Separated tracks took 13.5s each on average.
96
+ ```
97
+
98
+ Run it again and it only looks at what is new. Ctrl+C is safe at any point; the next run
99
+ carries on from the track it was working on. A second `index` run on the same index while
100
+ one is going stops straight away and says so.
101
+
102
+ ```
103
+ > breakdig index D:\Music\Breaks
104
+ Scanning 14 files...
105
+ 14 already indexed, 0 to do. Index: C:\Users\you\AppData\Local\breakdig
106
+ Done in 0s: nothing new.
107
+ ```
108
+
109
+ Find sections. With no options, `find` looks for drums alone:
110
+
111
+ ```
112
+ > breakdig find
113
+ ID ARTIST - TITLE BARS START END BPM CLEAN
114
+ -----------------------------------------------------------------------------------------------
115
+ 13:107-108 Bebop - Fidget Kaos 2 3:15.724 3:19.403 130.2 -34.0
116
+ 14:165-166 Innyu - For The Hell Of It 2 5:07.525 5:11.300 127.7 -30.4
117
+
118
+ 2 section(s). CLEAN is the loudest unwanted stem minus the target, in dB; lower is cleaner.
119
+ ```
120
+
121
+ `--silence-db 25` loosens the silence rule (see below) and finds a little more:
122
+
123
+ ```
124
+ > breakdig find --silence-db 25
125
+ ID ARTIST - TITLE BARS START END BPM CLEAN
126
+ -----------------------------------------------------------------------------------------------
127
+ 13:107-109 Bebop - Fidget Kaos 3 3:15.724 3:21.264 130.0 -29.8
128
+ 14:164-166 Innyu - For The Hell Of It 3 5:05.649 5:11.300 127.7 -26.5
129
+ 14:7-8 Innyu - For The Hell Of It 2 0:11.273 0:15.062 127.8 -26.4
130
+
131
+ 3 section(s). CLEAN is the loudest unwanted stem minus the target, in dB; lower is cleaner.
132
+ ```
133
+
134
+ ```
135
+ > breakdig find --no drums --limit 5
136
+ ID ARTIST - TITLE BARS START END BPM CLEAN
137
+ -----------------------------------------------------------------------------------------------
138
+ 7:25-28 Igor Leontyev - Remote District 4 0:16.358 0:21.674 183.1 -55.7
139
+ 10:1-16 Zipp - Coffee Break 16 0:01.526 0:33.507 60.3 -55.5
140
+ 2:56-57 Dog On Springs - Footloose (feat. Paul Whit~ 2 1:31.346 1:34.819 137.3 -55.3
141
+ 7:4-6 Igor Leontyev - Remote District 3 0:03.016 0:06.369 182.8 -54.9
142
+ 2:43-45 Dog On Springs - Footloose (feat. Paul Whit~ 3 1:09.037 1:14.137 142.3 -52.3
143
+
144
+ 5 section(s). CLEAN is the loudest unwanted stem minus the target, in dB; lower is cleaner.
145
+ ```
146
+
147
+ Export everything a `find` would list by giving the same filters to `export`, or pick
148
+ sections by ID with `--pick 13:107-109 14:7-8` (the other filters are ignored then):
149
+
150
+ ```
151
+ > breakdig export --silence-db 25 --out D:\Samples\breaks
152
+ wrote D:\Samples\breaks\Bebop - Fidget Kaos - 3 bars - 130 BPM - 03.16.wav
153
+ wrote D:\Samples\breaks\Innyu - For The Hell Of It - 3 bars - 128 BPM - 05.06.wav
154
+ wrote D:\Samples\breaks\Innyu - For The Hell Of It - 2 bars - 128 BPM - 00.11.wav
155
+
156
+ 3 file(s) in D:\Samples\breaks
157
+ ```
158
+
159
+ Or do all of it in the browser:
160
+
161
+ ```
162
+ > breakdig ui
163
+ breakdig UI on http://127.0.0.1:8765 (Ctrl+C to stop)
164
+ ```
165
+
166
+ ## What you can search for
167
+
168
+ `--only` names the stems that play alone, and everything else has to be silent.
169
+ `--no` names the stems that have to be silent, and at least one of the others has to play.
170
+ Stems are `drums`, `bass`, `vocals` and `other` (everything else: keys, guitars, pads, samples).
171
+
172
+ | You want | Use |
173
+ | --- | --- |
174
+ | Drum breaks | `--only drums` (the default) |
175
+ | Acapellas | `--only vocals` |
176
+ | Bass and drums | `--only bass,drums` |
177
+ | Anything without drums | `--no drums` |
178
+ | Instrumentals | `--no vocals` |
179
+
180
+ Other filters: `--min-bars N` (default 2), `--bpm 90` or `--bpm 85-100`, `--search "words"`
181
+ (every word has to appear in the artist, title, album or path), `--cleaner-than -25` (only sections at least that
182
+ clean), `--sort clean|bars|bpm|artist`, `--limit N`, `--skip-seams`, and `--json` for
183
+ scripting.
184
+
185
+ ## How a bar is judged
186
+
187
+ For every bar, breakdig has the mean level in dB of each separated stem and of the mix.
188
+
189
+ - A stem is active in a bar if it is no more than 12 dB below the mix.
190
+ - A stem is silent if it is more than 30 dB below the loudest active stem in that bar,
191
+ or below -90 dBFS.
192
+ Silent wins over active, so a bar of digital silence has nothing active in it.
193
+ - A bar where a stem is neither is a grey zone and never matches. That is deliberate: it is
194
+ what keeps a break with a quiet bassline under it out of "drums only".
195
+ - Consecutive matching bars become a section, and a section has to be at least `--min-bars`
196
+ long.
197
+ - CLEAN is the loudest stem that should be silent minus the target stem, taken from the
198
+ dirtiest bar in the section. -40 is very clean, -15 means you will probably hear something
199
+ else in there. Results are sorted by it.
200
+ - BPM is 60 divided by the median beat interval inside the section, so tempo drift is
201
+ handled per section. Bars come from detected downbeats, so 3/4 and changing meters work.
202
+ The bar after the last downbeat counts too, if the music carries on for a full bar past it.
203
+
204
+ The 30 dB is `--silence-db` (and "Silence dB" in the UI). Demucs leaves 20 to 35 dB of bleed
205
+ between stems on real records, so at 30 plenty of breaks you can clearly hear on the record
206
+ will not match. Dropping it to 25 or 20 finds more at the cost of some bleed. The table's
207
+ CLEAN column tells you how much.
208
+
209
+ ## Exports
210
+
211
+ Clips are cut from the original file, not from the separated stems, at the bar lines. Each
212
+ edge is moved to the quietest point within 2 ms, which gets rid of most clicks; a loud bass
213
+ note held across the bar line can still leave a faint one. Files are WAV at the source
214
+ sample rate: 16-bit from 8- and 16-bit sources, 24-bit from everything else,
215
+ including MP3 and AAC, which decode to more than 16 bits. A lossy file from a loud master
216
+ often decodes past full scale, and those clips are written as 32-bit float so the transients
217
+ are not clipped. They are tagged with artist, title with the bar range, album and BPM, and a
218
+ comment holds the source path, times and content key. Exporting the same section again
219
+ overwrites its file, even after the library has moved or the track was retagged.
220
+ Names follow `{artist} - {title} - {bars} bars - {bpm} BPM - {mm.ss}.wav`, with characters
221
+ Windows cannot handle replaced by `_` and the name capped at 120 characters. If another
222
+ section would get the same name, it becomes `... (2).wav`.
223
+
224
+ Every clip also has a cue point on each beat, labelled `beat 1`, `beat 2` and so on, in the
225
+ WAV's standard `cue ` chunk. Editors that read WAV cue points show them as markers to chop
226
+ at. Plenty of software ignores them, which does no harm.
227
+
228
+ `--keep drums` (or the keep menu in the UI) exports only some stems instead of the mix. Each
229
+ section is separated again with three seconds either side, so its edges come out clean,
230
+ and the kept stems are put back at the source sample rate. That turns a near miss into a
231
+ usable break: search `--no vocals`, look at the Stems column in the UI to see where the
232
+ drums are, and export those rows with `--keep drums`. `--keep drums,bass` and the rest work
233
+ the same way. The result is only as good as Demucs, so listen before you trust it. The name
234
+ gets the stems before the bar count (`... - drums - 4 bars - ...`), and the isolated clip
235
+ and the full-mix clip of the same bars are separate files.
236
+
237
+ `--sp404` (or SP-404 MKII in the UI's format menu) writes 16-bit 48 kHz files named
238
+ `BRK_0001.WAV`, `BRK_0002.WAV` and so on, plus an `index.csv` that maps each file back to its
239
+ source. `--sp404 sx` (SP-404 SX / A in the UI) does the same at 44.1 kHz for the SX, the A
240
+ and the original 404:
241
+
242
+ ```
243
+ file,artist,title,bars,bpm,start,end,source,stems
244
+ BRK_0001.WAV,Bebop,Fidget Kaos,3,130.0,195.724,201.264,D:\Music\Breaks\SOSLP008\SOSLP008_01_BEBOP_DONT_BELIEVE_THE_HYPE-Fidget_Kaos.mp3,
245
+ BRK_0002.WAV,Innyu,For The Hell Of It,3,127.7,305.649,311.300,D:\Music\Breaks\SOSLP008\SOSLP008_02_INNYU_DONT_BELIEVE_THE_HYPE-For_The_Hell_Of_It.mp3,
246
+ BRK_0003.WAV,Innyu,For The Hell Of It,2,127.8,11.273,15.062,D:\Music\Breaks\SOSLP008\SOSLP008_02_INNYU_DONT_BELIEVE_THE_HYPE-For_The_Hell_Of_It.mp3,drums
247
+ ```
248
+
249
+ Exporting into the same SP-404 folder again skips sections that are already there and
250
+ numbers new ones after the highest number in the folder or the csv, so a number is never
251
+ reused. Delete a BRK file and that section is exported again under a new number. Clips that
252
+ would go past full scale are turned down to fit instead of being clipped. Editing
253
+ `index.csv` in Excel is fine, including extra columns of your own and semicolon-separated
254
+ saves, but close it before exporting again. A folder that already has clips at one rate
255
+ refuses the other, so one card never ends up with both.
256
+
257
+ ## The web UI
258
+
259
+ `breakdig ui` serves on http://127.0.0.1:8765 and opens your browser. Pick stems, set the
260
+ filters and press Find. The play button loads just that section and loops it with no gap
261
+ at the loop point, so you hear how it will loop in a sampler. Space plays or stops the
262
+ selected row and the arrow keys move through the list. Tick rows and press Export to
263
+ write them to the folder at the bottom, then use "reveal" to open the file in Explorer.
264
+ Ticked rows stay ticked when you sort or search again, so one export can collect sections
265
+ from several searches; "clear" unticks them all, and an export unticks what it handled. The
266
+ filters, volume and loop setting are remembered for next time.
267
+
268
+ The Stems column draws each bar of a section as four small cells, drums, bass, vocals and
269
+ other from top to bottom, brighter the louder that stem is against the mix. The keep menu
270
+ next to Export does what `--keep` does, for previews as well as exports, so you can hear the
271
+ drums on their own before you write them out.
272
+
273
+ `--port` picks another port and `--no-browser` skips opening a tab. Previews are cached in
274
+ the index folder, up to about 500 MB, and the oldest go first.
275
+
276
+ It only listens on localhost. `--host 0.0.0.0` works but prints a warning, because anyone
277
+ who can reach the port can browse your index and write exports anywhere you can.
278
+
279
+ ## Configuration
280
+
281
+ | Setting | Default | |
282
+ | --- | --- | --- |
283
+ | `--home` or `BREAKDIG_HOME` | `%LOCALAPPDATA%\breakdig` | Index folder: `index.sqlite`, per-track profiles, `index.log`, the UI's clip cache |
284
+ | `BREAKDIG_MODELS` | `%LOCALAPPDATA%\breakdig\models` | Separation models, shared by every index |
285
+ | `index --model` | `htdemucs_ft.yaml` | Any audio-separator Demucs model |
286
+ | `index --shifts` | 1 | Demucs random shifts; 2 is slightly cleaner and twice as slow |
287
+ | `index --retry-failed` | off | Try files that failed last time again |
288
+ | `index --exclude GLOB` | none | Skip files and folders whose name matches, e.g. `"*.removed.*"` or `stems`. Repeatable |
289
+
290
+ `--home` goes before or after the command: `breakdig --home D:\breakdig-index find`. For
291
+ anything but `index`, a `--home` folder with no index in it is an error rather than an empty
292
+ result, so a typo does not look like an empty index.
293
+
294
+ ## Speed
295
+
296
+ Measured on an RTX 4090 with the default model:
297
+
298
+ - 64 tracks, 2.5 hours of audio: 11.3 s per track, 12.6x realtime (`breakdig stats`).
299
+ - A 50-track folder, 1.8 hours of audio, indexed unattended: 9.4 s per separated track.
300
+ - A 21-minute MP3: 89 s.
301
+ - Exporting with `--keep`: the first clip takes about 9 s, most of it loading the model, and
302
+ after that about 6x realtime. Eight sections, 7.5 minutes of audio in all, took 78 s.
303
+ - Re-running on an indexed folder: a second or two. Files whose size and modified time have
304
+ not changed are not read at all, and neither are unchanged byte-for-byte copies.
305
+
306
+ The index is small: about 25 KB per minute of audio, so 90 KB or so for a typical track.
307
+
308
+ ## Files it handles and skips
309
+
310
+ MP3, FLAC, WAV, AIFF, M4A (AAC or ALAC), AAC, OGG Vorbis, Opus and WMA. Mono, 8-bit, 24-bit,
311
+ float and odd sample rates are fine. The same audio at two paths or in two formats is only
312
+ separated once; the copy is recorded as a duplicate and takes over if the original is deleted.
313
+ An original on a drive that is not plugged in counts as still there.
314
+ The exception is a raw .aac file, which does not record its encoder delay, next to the same
315
+ track in another format. A file that moves or is renamed keeps its index entry, and so does one
316
+ you retag. One you trim or edit is analysed again.
317
+
318
+ Skipped, logged, and listed by `breakdig stats --failures`: files that will not decode,
319
+ DRM-protected iTunes files (.m4p), and tracks with fewer than 8 downbeats (`no_grid`; mostly
320
+ speech, ambient and very short files).
321
+
322
+ Vinyl rips with crackle can go through [grooveclean](https://github.com/Booyaka101/grooveclean)
323
+ first. Its batch mode writes a `.removed` difference file next to each cleaned side, which
324
+ has enough of a beat to get indexed, so leave those out:
325
+ `breakdig index D:\Rips\cleaned --exclude "*.removed.*"`.
326
+
327
+ Files over 20 minutes are separated in 10-minute chunks. A section that crosses a chunk
328
+ boundary is marked `seam` because the separation can glitch there; `--skip-seams` drops
329
+ them.
330
+
331
+ ## Limitations
332
+
333
+ - On most commercial records the drums are almost never truly alone for two bars. Expect a
334
+ handful of hits per album at the default setting, and use `--silence-db 25` and
335
+ `--min-bars 1` to see near misses, or `--keep drums` to take the drums out of busier bars.
336
+ - Downbeat tracking can be wrong on rubato, very old recordings and music with no clear
337
+ pulse. Bars far off a track's usual length are ignored rather than exported as nonsense.
338
+ - Separation quality is Demucs quality. Sections are judged on separated stems but cut from
339
+ the original mix, so what you export is exactly what was on the record, unless you ask
340
+ for `--keep`.
341
+ - Tested on Windows 11 with Python 3.11. It should run on Linux; macOS will only have the
342
+ CPU, which is slow.
343
+
344
+ ## Development
345
+
346
+ ```
347
+ py -3.11 -m venv .venv
348
+ .venv\Scripts\pip install -e .[test]
349
+ .venv\Scripts\python -m pytest -q
350
+ ```
351
+
352
+ The `gpu` tests run real Demucs separation and are skipped without CUDA. Set
353
+ `BREAKDIG_MODELS` to reuse a model folder between runs. CI runs everything else on Windows
354
+ and Linux with the CPU build of torch.
355
+
356
+ ## Releasing
357
+
358
+ ```
359
+ python -m build
360
+ python packaging\make_windows_zip.py
361
+ twine upload dist\breakdig-0.1.0-py3-none-any.whl dist\breakdig-0.1.0.tar.gz
362
+ ```
363
+
364
+ `make_windows_zip.py` writes `dist\breakdig-0.1.0-windows.zip` for the GitHub release.
365
+
366
+ ## Credits
367
+
368
+ The demo uses Creative Commons music from the Internet Archive: "Retrovision" (MIXG032,
369
+ CC BY-NC 3.0) with tracks by Zipp, Dog On Springs, Astat, Fedorov Mark, VAD and Igor
370
+ Leontyev, and "Dont Believe The Hype" (SOSLP008, CC BY-NC-ND 2.5 IT) with tracks by Bebop and
371
+ Innyu.
372
+
373
+ Separation is [Demucs](https://github.com/facebookresearch/demucs) through
374
+ [audio-separator](https://github.com/nomadkaraoke/python-audio-separator). Downbeats come
375
+ from [beat_this](https://github.com/CPJKU/beat_this).
376
+
377
+ ## License
378
+
379
+ MIT