vl8 0.2.0__py3-none-any.whl → 0.3.0__py3-none-any.whl
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.
- vl8/.DS_Store +0 -0
- vl8/__init__.py +0 -0
- vl8/adaptor/__init__.py +0 -0
- vl8/dsp/__init__.py +0 -0
- vl8/dsp/fix_gaps.py +49 -0
- vl8/processor/__init__.py +0 -0
- vl8/processor/catenate.py +62 -0
- vl8-0.3.0.dist-info/METADATA +51 -0
- vl8-0.3.0.dist-info/RECORD +10 -0
- {vl8-0.2.0.dist-info → vl8-0.3.0.dist-info}/WHEEL +1 -2
- vl8-0.2.0.dist-info/LICENSE +0 -21
- vl8-0.2.0.dist-info/METADATA +0 -29
- vl8-0.2.0.dist-info/RECORD +0 -6
- vl8-0.2.0.dist-info/top_level.txt +0 -1
- vl8.py +0 -81
vl8/.DS_Store
ADDED
|
Binary file
|
vl8/__init__.py
ADDED
|
File without changes
|
vl8/adaptor/__init__.py
ADDED
|
File without changes
|
vl8/dsp/__init__.py
ADDED
|
File without changes
|
vl8/dsp/fix_gaps.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import math
|
|
2
|
+
from typing import List, Optional, Union
|
|
3
|
+
|
|
4
|
+
import xmod
|
|
5
|
+
|
|
6
|
+
from old.vl8.util import error
|
|
7
|
+
|
|
8
|
+
Number = Union[int, float]
|
|
9
|
+
Gaps = Union[Number, List[Number]]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@xmod
|
|
13
|
+
def fix_gaps(
|
|
14
|
+
durations: List[int],
|
|
15
|
+
gaps: Gaps,
|
|
16
|
+
pre: float = 0,
|
|
17
|
+
post: float = 0,
|
|
18
|
+
sample_rate: Optional[int] = None,
|
|
19
|
+
):
|
|
20
|
+
# TODO: fix_gaps should learn about durations amd ration
|
|
21
|
+
if pre < 0 or post < 0:
|
|
22
|
+
raise ValueError("pre and post cannot be negative")
|
|
23
|
+
|
|
24
|
+
if not isinstance(gaps, list):
|
|
25
|
+
gaps = [gaps]
|
|
26
|
+
elif not gaps:
|
|
27
|
+
raise ValueError("gap must be a non-empty list or an integer")
|
|
28
|
+
|
|
29
|
+
n = len(durations)
|
|
30
|
+
scale = math.ceil(n / len(gaps))
|
|
31
|
+
gaps = [pre] + (gaps * scale)[: n - 1] + [post]
|
|
32
|
+
|
|
33
|
+
if sample_rate:
|
|
34
|
+
gaps = [g * sample_rate for g in gaps]
|
|
35
|
+
|
|
36
|
+
gaps = [round(g) for g in gaps]
|
|
37
|
+
|
|
38
|
+
# Fix any fade gaps that are too long.
|
|
39
|
+
for i, gap in enumerate(gaps):
|
|
40
|
+
if i > 0:
|
|
41
|
+
gap = max(gap, -durations[i - 1])
|
|
42
|
+
if i < n:
|
|
43
|
+
gap = max(gap, -durations[i])
|
|
44
|
+
if gaps[i] != gap:
|
|
45
|
+
error(f"Gap {i}: {gap} was longer than the sample!")
|
|
46
|
+
gaps[i] = gap
|
|
47
|
+
|
|
48
|
+
assert len(gaps) == n + 1
|
|
49
|
+
return gaps
|
|
File without changes
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from old.vl8.dsp import curve_cache
|
|
4
|
+
from old.vl8.function.creator import Creator
|
|
5
|
+
from vl8.dsp import fix_gaps
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class Catenate(Creator):
|
|
10
|
+
curve: curve_cache.Curve = None
|
|
11
|
+
gap: fix_gaps.Gaps = 0
|
|
12
|
+
pre: int = 0
|
|
13
|
+
post: int = 0
|
|
14
|
+
|
|
15
|
+
def _prepare(self, src):
|
|
16
|
+
durations = [s.shape[1] for s in src]
|
|
17
|
+
self.gaps = fix_gaps(
|
|
18
|
+
durations, self.gap, self.pre, self.post, src[0].sample_rate
|
|
19
|
+
)
|
|
20
|
+
return sum(durations) + sum(self.gaps)
|
|
21
|
+
|
|
22
|
+
def _call(self, arr, *src):
|
|
23
|
+
"""
|
|
24
|
+
gap: None, a number of seconds or a list of seconds
|
|
25
|
+
if a gap is negative, it's a fade
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
fader = curve_cache(self.curve, arr.dtype)
|
|
29
|
+
|
|
30
|
+
begin = end = 0
|
|
31
|
+
for i, s in enumerate(src):
|
|
32
|
+
begin = end + self.gaps[i]
|
|
33
|
+
end = begin + s.shape[-1]
|
|
34
|
+
fade_in, fade_out = -self.gaps[i], -self.gaps[i + 1]
|
|
35
|
+
|
|
36
|
+
b, e = begin, end
|
|
37
|
+
if fade_in > 0:
|
|
38
|
+
delta = fader(0, 1, fade_in) * s[:, :fade_in]
|
|
39
|
+
arr[:, b : b + fade_in] += delta
|
|
40
|
+
b += fade_in
|
|
41
|
+
|
|
42
|
+
if fade_out > 0:
|
|
43
|
+
delta = fader(1, 0, fade_out) * s[:, -fade_out:]
|
|
44
|
+
arr[:, e - fade_out : e] += delta
|
|
45
|
+
e -= fade_out
|
|
46
|
+
|
|
47
|
+
arr[:, b:e] += s[:, b - begin : e - end or None]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
"""
|
|
51
|
+
# Should be elsewhere in a task
|
|
52
|
+
|
|
53
|
+
overlap: None or any floating point numbers, referenced to the longest item.
|
|
54
|
+
|
|
55
|
+
These next comments shoul
|
|
56
|
+
|
|
57
|
+
0 means: all start together
|
|
58
|
+
0.5 means: middles of all songs are at same time
|
|
59
|
+
1 means: all end together
|
|
60
|
+
|
|
61
|
+
Negative numbers and numbers bigger than one are possible!
|
|
62
|
+
"""
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vl8
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: 🔉 Perturbed audio 🔉
|
|
5
|
+
Author: Tom Ritchford
|
|
6
|
+
Author-email: Tom Ritchford <tom@swirly.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
14
|
+
Requires-Dist: abbrev>=1.0.1,<2
|
|
15
|
+
Requires-Dist: graycode>=1.0.5,<2
|
|
16
|
+
Requires-Dist: more-itertools>=9.0.0,<10
|
|
17
|
+
Requires-Dist: numpy>=1.24.1,<2
|
|
18
|
+
Requires-Dist: pydub>=0.25.1,<0.26
|
|
19
|
+
Requires-Dist: pyyaml>=6.0,<7
|
|
20
|
+
Requires-Dist: runs>=1.1.0,<2
|
|
21
|
+
Requires-Dist: soundfile>=0.11.0,<0.12
|
|
22
|
+
Requires-Dist: stroll>=1.1.0,<2
|
|
23
|
+
Requires-Dist: tdir>=1.4.1,<2
|
|
24
|
+
Requires-Dist: toml>=0.10.2,<0.11
|
|
25
|
+
Requires-Dist: typeguard>=2.13.3,<3
|
|
26
|
+
Requires-Dist: wavemap>=2.0.1,<3
|
|
27
|
+
Requires-Dist: xmod>=1.3.2,<2
|
|
28
|
+
Requires-Python: >=3.10
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# 🔉 vl8: Create derivative works that might not be copyright violations 🔉
|
|
32
|
+
|
|
33
|
+

|
|
34
|
+
|
|
35
|
+
Update: this is still in development - I got sidetracked by paying work.
|
|
36
|
+
Most of this is working, it just needs to be packaged!
|
|
37
|
+
|
|
38
|
+
------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
A command line tool and Python library that (will soon be) like a Swiss
|
|
41
|
+
Army Knife for audio.
|
|
42
|
+
|
|
43
|
+
- Create a myriad of mashups of your favorite audio effortlessly.
|
|
44
|
+
- Script mundane tasks like editing, scaling and stretching,
|
|
45
|
+
envelopes, playlists and more.
|
|
46
|
+
- Handle very large audio files using memory mapping, or very large
|
|
47
|
+
numbers of audio files using scripting.
|
|
48
|
+
- Write your own scripts for mashups or editing, or your own plug-ins,
|
|
49
|
+
and share them.
|
|
50
|
+
- Uses widely compatible, highly performant numpy arrays to represent
|
|
51
|
+
audio files within Python.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
vl8/.DS_Store,sha256=_TBPvn1BKjmozZm-cBCle4EVW9oGlInMnj157oc6s0Q,6148
|
|
2
|
+
vl8/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
vl8/adaptor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
vl8/dsp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
vl8/dsp/fix_gaps.py,sha256=GUh6m19TZxpcfp2qlc7gr94gr-fJFfyaTdaXO1ciq3c,1191
|
|
6
|
+
vl8/processor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
vl8/processor/catenate.py,sha256=US0xS9OZs_Qxc3wFnvJRaNLDOzXwdx2Xisu_FdFYfj4,1678
|
|
8
|
+
vl8-0.3.0.dist-info/WHEEL,sha256=fAguSjoiATBe7TNBkJwOjyL1Tt4wwiaQGtNtjRPNMQA,80
|
|
9
|
+
vl8-0.3.0.dist-info/METADATA,sha256=KVdkls5k8m-nTq-AVXJn-IG9fQVrhNMtRG427KnXLy8,1935
|
|
10
|
+
vl8-0.3.0.dist-info/RECORD,,
|
vl8-0.2.0.dist-info/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2020 Tom Ritchford
|
|
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.
|
vl8-0.2.0.dist-info/METADATA
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: vl8
|
|
3
|
-
Version: 0.2.0
|
|
4
|
-
Summary: 🔉 vl8: Sort audio granularly 🔉
|
|
5
|
-
Home-page: https://github.com/rec/vl8
|
|
6
|
-
Author: Tom Ritchford
|
|
7
|
-
Author-email: tom@swirly.com
|
|
8
|
-
License: MIT
|
|
9
|
-
Keywords: audio
|
|
10
|
-
Platform: UNKNOWN
|
|
11
|
-
Classifier: Development Status :: 3 - Alpha
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
-
Classifier: Intended Audience :: Developers
|
|
17
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
-
Requires-Dist: aubio
|
|
19
|
-
Requires-Dist: numpy
|
|
20
|
-
Requires-Dist: pydub
|
|
21
|
-
Requires-Dist: runs
|
|
22
|
-
Requires-Dist: stroll
|
|
23
|
-
|
|
24
|
-
🔉 vl8: Create derivative works that might not be copyright violations 🔉
|
|
25
|
-
----------------------------------------------------------------------------
|
|
26
|
-
|
|
27
|
-
This is a tool to create derivative works of pieces of music.
|
|
28
|
-
|
|
29
|
-
|
vl8-0.2.0.dist-info/RECORD
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
vl8.py,sha256=ywuzsvxvfjBSqJxDjeO6Jta8zKfUZt9HzNHueFl0iSE,2108
|
|
2
|
-
vl8-0.2.0.dist-info/LICENSE,sha256=2H3TTsBJEVDu73RHBbYDXTPRFsypRLOplkjh_AwfOi8,1070
|
|
3
|
-
vl8-0.2.0.dist-info/METADATA,sha256=tUZzNbvm1SIp5cqxnPh8m3wixKIWeEypoCN9DiK2LCo,894
|
|
4
|
-
vl8-0.2.0.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
|
|
5
|
-
vl8-0.2.0.dist-info/top_level.txt,sha256=UsypfRs_Ha0bvxtcJdtiBjkcAe883jDlT7CE70_97Yk,4
|
|
6
|
-
vl8-0.2.0.dist-info/RECORD,,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
vl8
|
vl8.py
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
🏃 Run one or more commands 🏃
|
|
3
|
-
------------------------------------------------------------------
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
# import stroll
|
|
8
|
-
from dataclasses import dataclass
|
|
9
|
-
import numpy as np
|
|
10
|
-
import util
|
|
11
|
-
|
|
12
|
-
__all__ = 'vl8'
|
|
13
|
-
__version__ = '0.2.0'
|
|
14
|
-
INFILE = '/data/vl8/full.wav'
|
|
15
|
-
MAX_FRAME = 4096
|
|
16
|
-
SAMPLERATE = 44100
|
|
17
|
-
GRAIN_SIZE = SAMPLERATE // 10
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def mean_square(granule):
|
|
21
|
-
return np.mean(granule * granule)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@dataclass
|
|
25
|
-
class Granulator:
|
|
26
|
-
filename: str
|
|
27
|
-
grain_size: int = GRAIN_SIZE
|
|
28
|
-
sort: bool = True
|
|
29
|
-
duration: int = 0
|
|
30
|
-
|
|
31
|
-
def __post_init__(self):
|
|
32
|
-
assert not (self.grain_size % 2)
|
|
33
|
-
self.buffer = util.read(self.filename, self.grain_size, self.duration)
|
|
34
|
-
self.duration = self.buffer.shape[1]
|
|
35
|
-
|
|
36
|
-
def run(self, function, outfile):
|
|
37
|
-
results = self.for_each_granule(function)
|
|
38
|
-
results.sort(1)
|
|
39
|
-
print('writing', outfile)
|
|
40
|
-
util.write(outfile, self.combine(results))
|
|
41
|
-
|
|
42
|
-
def for_each_granule(self, function):
|
|
43
|
-
half = self.grain_size // 2
|
|
44
|
-
granules = self.duration // half
|
|
45
|
-
granules = round(granules)
|
|
46
|
-
|
|
47
|
-
results = util.empty(granules).transpose()
|
|
48
|
-
for i in range(granules):
|
|
49
|
-
begin = half * i
|
|
50
|
-
end = begin + self.grain_size
|
|
51
|
-
value = function(self.buffer[:, begin:end])
|
|
52
|
-
results[i] = float(i), value
|
|
53
|
-
|
|
54
|
-
return results
|
|
55
|
-
|
|
56
|
-
def combine(self, results):
|
|
57
|
-
half = self.grain_size // 2
|
|
58
|
-
buf = self.buffer
|
|
59
|
-
out = util.zeros(buf.shape[1] + half)
|
|
60
|
-
|
|
61
|
-
fade_in = np.linspace(0, 1, half, dtype=util.FLOAT)
|
|
62
|
-
fade_out = np.flip(fade_in)
|
|
63
|
-
|
|
64
|
-
for out_index, (in_index, value) in enumerate(results):
|
|
65
|
-
i = round(in_index) * half
|
|
66
|
-
o = out_index * half
|
|
67
|
-
out[:, o : o + half] += buf[:, i : i + half] * fade_in
|
|
68
|
-
|
|
69
|
-
i += half
|
|
70
|
-
o += half
|
|
71
|
-
out[:, o : o + half] += buf[:, i : i + half] * fade_out
|
|
72
|
-
|
|
73
|
-
return out
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if __name__ == '__main__':
|
|
77
|
-
print('Reading', INFILE)
|
|
78
|
-
generator = Granulator(INFILE)
|
|
79
|
-
|
|
80
|
-
print('Running mean_square')
|
|
81
|
-
generator.run(mean_square, '/data/vl8/mean_square.wav')
|