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 ADDED
Binary file
vl8/__init__.py ADDED
File without changes
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
+ ![vl8 logo](https://raw.githubusercontent.com/rec/vl8/master/vl8.png)
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,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.34.2)
2
+ Generator: uv 0.9.28
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
@@ -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.
@@ -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
-
@@ -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')