playbeats 0.1.1__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.
@@ -0,0 +1,29 @@
1
+ Metadata-Version: 2.4
2
+ Name: playbeats
3
+ Version: 0.1.1
4
+ Summary: Generate neural-network-powered beats from your terminal
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: pygame
8
+ Requires-Dist: torch
9
+ Requires-Dist: numpy
10
+
11
+ ### Installation
12
+
13
+ ```bash
14
+ pip install playbeats
15
+ ```
16
+
17
+ ### Usage
18
+
19
+ ```bash
20
+ playbeats --bpm=80 --energy=20
21
+ ```
22
+
23
+ - `--bpm` — Set the beat tempo.
24
+ - `--energy` — Set the beat energy.
25
+
26
+ ### Stop Playback
27
+
28
+ Press `Ctrl+C` to stop playback.
29
+
@@ -0,0 +1,19 @@
1
+ ### Installation
2
+
3
+ ```bash
4
+ pip install playbeats
5
+ ```
6
+
7
+ ### Usage
8
+
9
+ ```bash
10
+ playbeats --bpm=80 --energy=20
11
+ ```
12
+
13
+ - `--bpm` — Set the beat tempo.
14
+ - `--energy` — Set the beat energy.
15
+
16
+ ### Stop Playback
17
+
18
+ Press `Ctrl+C` to stop playback.
19
+
@@ -0,0 +1,29 @@
1
+ Metadata-Version: 2.4
2
+ Name: playbeats
3
+ Version: 0.1.1
4
+ Summary: Generate neural-network-powered beats from your terminal
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: pygame
8
+ Requires-Dist: torch
9
+ Requires-Dist: numpy
10
+
11
+ ### Installation
12
+
13
+ ```bash
14
+ pip install playbeats
15
+ ```
16
+
17
+ ### Usage
18
+
19
+ ```bash
20
+ playbeats --bpm=80 --energy=20
21
+ ```
22
+
23
+ - `--bpm` — Set the beat tempo.
24
+ - `--energy` — Set the beat energy.
25
+
26
+ ### Stop Playback
27
+
28
+ Press `Ctrl+C` to stop playback.
29
+
@@ -0,0 +1,26 @@
1
+ README.md
2
+ pyproject.toml
3
+ train.py
4
+ playbeats.egg-info/PKG-INFO
5
+ playbeats.egg-info/SOURCES.txt
6
+ playbeats.egg-info/dependency_links.txt
7
+ playbeats.egg-info/entry_points.txt
8
+ playbeats.egg-info/requires.txt
9
+ playbeats.egg-info/top_level.txt
10
+ src/__init__.py
11
+ src/main.py
12
+ src/assets/beat_generator.pth
13
+ src/assets/sounds/HIHAT.wav
14
+ src/assets/sounds/KICK.wav
15
+ src/assets/sounds/SAMPLE.wav
16
+ src/assets/sounds/SNARE.wav
17
+ src/assets/sounds/bass.wav
18
+ src/assets/sounds/bongo.wav
19
+ src/assets/sounds/clap.wav
20
+ src/assets/sounds/clap_fixed.wav
21
+ src/assets/sounds/closed-hihat.wav
22
+ src/assets/sounds/openhihat.wav
23
+ src/assets/sounds/tambourine.wav
24
+ src/assets/sounds/tom-high.wav
25
+ src/assets/sounds/tom-low.wav
26
+ src/assets/sounds/tom-mid.wav
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ playbeats = src.main:main
@@ -0,0 +1,3 @@
1
+ pygame
2
+ torch
3
+ numpy
@@ -0,0 +1,2 @@
1
+ src
2
+ train
@@ -0,0 +1,28 @@
1
+
2
+ [build-system]
3
+ requires = ["setuptools>=61"]
4
+ build-backend = "setuptools.build_meta"
5
+
6
+ [project]
7
+ name = "playbeats"
8
+ version = "0.1.1"
9
+ description = "Generate neural-network-powered beats from your terminal"
10
+ readme = "README.md"
11
+ requires-python = ">=3.10"
12
+ dependencies = [
13
+ "pygame",
14
+ "torch",
15
+ "numpy"
16
+ ]
17
+
18
+ [project.scripts]
19
+ playbeats = "src.main:main"
20
+
21
+ [tool.setuptools]
22
+ py-modules = ["train"]
23
+
24
+ [tool.setuptools.packages.find]
25
+ include = ["src*"]
26
+
27
+ [tool.setuptools.package-data]
28
+ src = ["assets/*.pth", "assets/sounds/*.wav"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,112 @@
1
+ import pygame
2
+ import time
3
+ from train import BeatGenerator
4
+ import torch
5
+ import random
6
+ import sys
7
+ import re
8
+
9
+ from pathlib import Path
10
+
11
+ ASSETS = Path(__file__).resolve().parent / "assets"
12
+
13
+ def shuffel(sounds:list):
14
+ for i in range(len(sounds) -1,0,-1):
15
+ j = random.randint(0,i)
16
+ sounds[i], sounds[j] = sounds[j], sounds[i]
17
+ return sounds
18
+
19
+
20
+ def main():
21
+
22
+ if len(sys.argv) < 3:
23
+ print("Error: Missing arguments.", file=sys.stderr)
24
+ print(f"Usage: playbeats {sys.argv[0]} bpm energy")
25
+ sys.exit(1)
26
+
27
+
28
+ match1 = re.search(r"\d+", sys.argv[1])
29
+
30
+ match2 = re.search(r"\d+", sys.argv[2])
31
+
32
+ if match1:
33
+ bpm = float(match1.group())
34
+ if match2:
35
+ energy = float(match2.group())
36
+
37
+ duration = float(random.randint(100,1000))
38
+
39
+ model = BeatGenerator()
40
+
41
+ state_dict = torch.load(
42
+ ASSETS / "beat_generator.pth",
43
+ map_location="cpu",
44
+ weights_only=True
45
+ )
46
+
47
+
48
+ model.load_state_dict(state_dict)
49
+
50
+ model.eval()
51
+
52
+ x = torch.tensor([[bpm, duration, 44100, energy]])
53
+
54
+ with torch.no_grad():
55
+ output = model(x)
56
+ beat = (torch.sigmoid(output) >= 0.5).int()
57
+
58
+ pygame.mixer.init()
59
+
60
+
61
+ sounds_dir = ASSETS / "sounds"
62
+
63
+ kick = pygame.mixer.Sound(str(sounds_dir / "KICK.wav"))
64
+ snare = pygame.mixer.Sound(str(sounds_dir / "SNARE.wav"))
65
+ sample = pygame.mixer.Sound(str(sounds_dir / "SAMPLE.wav"))
66
+ hihat = pygame.mixer.Sound(str(sounds_dir / "HIHAT.wav"))
67
+ bass = pygame.mixer.Sound(str(sounds_dir / "bass.wav"))
68
+ tom_mid = pygame.mixer.Sound(str(sounds_dir / "tom-mid.wav"))
69
+ tom_high = pygame.mixer.Sound(str(sounds_dir / "tom-high.wav"))
70
+ tom_low = pygame.mixer.Sound(str(sounds_dir / "tom-low.wav"))
71
+ closed_hithat = pygame.mixer.Sound(str(sounds_dir / "closed-hihat.wav"))
72
+ open_hihat = pygame.mixer.Sound(str(sounds_dir / "openhihat.wav"))
73
+ tambourine = pygame.mixer.Sound(str(sounds_dir / "tambourine.wav"))
74
+ bongo = pygame.mixer.Sound(str(sounds_dir / "bongo.wav"))
75
+ clap = pygame.mixer.Sound(str(sounds_dir / "clap.wav"))
76
+
77
+ instruments = [
78
+ bass,
79
+ snare,
80
+ tom_mid,
81
+ clap,
82
+ kick,
83
+ open_hihat,
84
+ closed_hithat,
85
+ tom_high,
86
+ hihat,
87
+ tambourine,
88
+ tom_low,
89
+ sample,
90
+ bongo,
91
+ ]
92
+
93
+ bpm = 120
94
+ beat_time = 60 / bpm
95
+
96
+ try:
97
+ while True:
98
+ for i in range(64):
99
+ for j in range(13):
100
+ if beat[0][i][j].item() == 1:
101
+ instruments = shuffel(instruments)
102
+ instruments[j].play()
103
+ time.sleep(beat_time)
104
+
105
+ except KeyboardInterrupt:
106
+ print("Beat playback stopped.")
107
+
108
+ finally:
109
+ pygame.mixer.quit()
110
+
111
+ if __name__ == "__main__":
112
+ main()
@@ -0,0 +1,109 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Untitled1.ipynb
3
+
4
+ Automatically generated by Colab.
5
+
6
+ Original file is located at
7
+ https://colab.research.google.com/drive/1EBzJZoQPsyh-XQYCCsFwpnd93PScSpSq
8
+ """
9
+
10
+ # from pathlib import Path
11
+ # import glob
12
+ # import json
13
+ import torch.nn as nn
14
+
15
+ # path = Path("/content/drive/MyDrive/training-data")
16
+
17
+ # training_data = glob.glob(str(path / "*.json"))
18
+
19
+ # training_tensors = []
20
+
21
+ # target_tensors = []
22
+
23
+ # for file in training_data:
24
+ # with open(file, "r") as f:
25
+ # data = json.load(f)
26
+
27
+ # metadata = data["metadata"]
28
+
29
+ # meta_data = [
30
+ # metadata["bpm"],
31
+ # metadata["duration"],
32
+ # metadata["sample_rate"],
33
+ # metadata["energy"]
34
+ # ]
35
+
36
+ # training_tensors.append(
37
+ # torch.tensor(meta_data, dtype=torch.float32)
38
+ # )
39
+
40
+ # target_tensors.append(
41
+ # torch.tensor(data["sequence"], dtype=torch.float32)
42
+ # )
43
+
44
+ # X = torch.stack(training_tensors)
45
+ # Y = torch.stack(target_tensors)
46
+
47
+ class BeatGenerator(nn.Module):
48
+ def __init__(self):
49
+ super().__init__()
50
+
51
+ self.network = nn.Sequential(
52
+ nn.Linear(4, 128),
53
+ nn.ReLU(),
54
+
55
+ nn.Linear(128, 256),
56
+ nn.ReLU(),
57
+
58
+ nn.Linear(256, 832)
59
+ )
60
+
61
+ def forward(self, x):
62
+ x = self.network(x)
63
+ x = x.reshape(-1, 64, 13)
64
+ return x
65
+
66
+ # model = BeatGenerator()
67
+
68
+ # positive = Y.sum()
69
+
70
+ # negative = Y.numel() - positive
71
+
72
+ # loss_fc = nn.BCEWithLogitsLoss(pos_weight=negative/positive)
73
+
74
+ # optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
75
+
76
+ # for epoch in range(20000):
77
+
78
+ # output = model(X)
79
+
80
+ # loss = loss_fc(output, Y)
81
+
82
+ # optimizer.zero_grad()
83
+
84
+ # loss.backward()
85
+
86
+ # optimizer.step()
87
+
88
+ # if (epoch + 1) % 100 == 0:
89
+ # print(f"Epoch {epoch + 1}, Loss: {loss.item():.4f}")
90
+
91
+
92
+ # torch.save(model.state_dict(), "beat_generator.pth")
93
+
94
+ # model = BeatGenerator()
95
+
96
+ # model.load_state_dict(
97
+ # torch.load("beat_generator.pth", map_location="cpu", weights_only=True)
98
+ # )
99
+
100
+ # model.eval()
101
+
102
+ # x = torch.tensor([[13230.0, 13235.89, 250.0, 0.12332411]])
103
+
104
+ # with torch.no_grad():
105
+ # output = model(x)
106
+ # beat = (torch.sigmoid(output) >= 0.5).int()
107
+
108
+ # print("Shape:", beat.shape)
109
+ # print(beat[0])