unitracker-player 0.2.0__tar.gz → 0.3.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.
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/PKG-INFO +2 -1
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/README.md +1 -0
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/pyproject.toml +1 -1
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/src/unitracker_player/player.py +18 -20
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/src/unitracker_player.egg-info/PKG-INFO +2 -1
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/tests/test_player.py +11 -0
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/LICENSE +0 -0
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/setup.cfg +0 -0
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/src/unitracker_player/__init__.py +0 -0
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/src/unitracker_player/cli.py +0 -0
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/src/unitracker_player/document.py +0 -0
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/src/unitracker_player/expr.py +0 -0
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/src/unitracker_player/modulation.py +0 -0
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/src/unitracker_player.egg-info/SOURCES.txt +0 -0
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/src/unitracker_player.egg-info/dependency_links.txt +0 -0
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/src/unitracker_player.egg-info/entry_points.txt +0 -0
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/src/unitracker_player.egg-info/requires.txt +0 -0
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/src/unitracker_player.egg-info/top_level.txt +0 -0
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/tests/test_cli.py +0 -0
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/tests/test_document.py +0 -0
- {unitracker_player-0.2.0 → unitracker_player-0.3.0}/tests/test_modulation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: unitracker-player
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Plays canonical unitracker documents to SID register state per tick
|
|
5
5
|
Author: Josh Bailey
|
|
6
6
|
License: Apache License
|
|
@@ -247,6 +247,7 @@ frames = play(text, ticks=3000) # a looping song needs ticks
|
|
|
247
247
|
song = load(text) # parse and compile once; play(song, ...) reuses it
|
|
248
248
|
player = Player(song)
|
|
249
249
|
regs = player.step() # the 25 registers after one tick; None once the song ends
|
|
250
|
+
player.regs # the register file the last tick wrote, one store per register
|
|
250
251
|
```
|
|
251
252
|
|
|
252
253
|
`read(text)` returns the document as plain dataclasses. A text outside the grammar raises
|
|
@@ -22,6 +22,7 @@ frames = play(text, ticks=3000) # a looping song needs ticks
|
|
|
22
22
|
song = load(text) # parse and compile once; play(song, ...) reuses it
|
|
23
23
|
player = Player(song)
|
|
24
24
|
regs = player.step() # the 25 registers after one tick; None once the song ends
|
|
25
|
+
player.regs # the register file the last tick wrote, one store per register
|
|
25
26
|
```
|
|
26
27
|
|
|
27
28
|
`read(text)` returns the document as plain dataclasses. A text outside the grammar raises
|
|
@@ -364,11 +364,13 @@ class _Voice:
|
|
|
364
364
|
|
|
365
365
|
class Player:
|
|
366
366
|
"""Plays a Song one tick at a time; ``step()`` returns the registers at the end of the
|
|
367
|
-
tick, or None once the song has ended.
|
|
367
|
+
tick, or None once the song has ended. ``regs`` is the register file the last tick wrote,
|
|
368
|
+
each register by its own statement, so a line tracer sees one store per register."""
|
|
368
369
|
|
|
369
370
|
def __init__(self, song: Song):
|
|
370
371
|
self.song = song
|
|
371
372
|
self.tick = 0
|
|
373
|
+
self.regs = [0] * REGISTERS
|
|
372
374
|
self.voices = [_Voice() for _ in range(song.voices)]
|
|
373
375
|
self.cut = self.res = self.route = self.mode = self.vol = 0
|
|
374
376
|
self.cut_prog = self.cut_cmd = None
|
|
@@ -436,26 +438,22 @@ class Player:
|
|
|
436
438
|
return self.registers()
|
|
437
439
|
|
|
438
440
|
def registers(self) -> list:
|
|
439
|
-
"""The 25 register values
|
|
440
|
-
regs =
|
|
441
|
+
"""The 25 register values, written to ``regs``."""
|
|
442
|
+
regs = self.regs
|
|
441
443
|
for v, voice in enumerate(self.voices):
|
|
442
|
-
|
|
443
|
-
regs[
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
regs[
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
self.res << 4 | self.route,
|
|
456
|
-
self.mode | self.vol,
|
|
457
|
-
]
|
|
458
|
-
return regs
|
|
444
|
+
at = 7 * v
|
|
445
|
+
regs[at] = voice.freq & 0xFF
|
|
446
|
+
regs[at + 1] = voice.freq >> 8
|
|
447
|
+
regs[at + 2] = voice.pw & 0xFF
|
|
448
|
+
regs[at + 3] = voice.pw >> 8
|
|
449
|
+
regs[at + 4] = ((voice.ctrl ^ voice.mask) & 0xFE) | (voice.ctrl & voice.gate & 1)
|
|
450
|
+
regs[at + 5] = voice.ad
|
|
451
|
+
regs[at + 6] = voice.sr
|
|
452
|
+
regs[21] = self.cut & 7
|
|
453
|
+
regs[22] = self.cut >> 3
|
|
454
|
+
regs[23] = self.res << 4 | self.route
|
|
455
|
+
regs[24] = self.mode | self.vol
|
|
456
|
+
return list(regs)
|
|
459
457
|
|
|
460
458
|
def _start(self, v: int, kind: int, prog: CProgram | None, t: int):
|
|
461
459
|
running = prog is not None and bool(prog.rows)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: unitracker-player
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Plays canonical unitracker documents to SID register state per tick
|
|
5
5
|
Author: Josh Bailey
|
|
6
6
|
License: Apache License
|
|
@@ -247,6 +247,7 @@ frames = play(text, ticks=3000) # a looping song needs ticks
|
|
|
247
247
|
song = load(text) # parse and compile once; play(song, ...) reuses it
|
|
248
248
|
player = Player(song)
|
|
249
249
|
regs = player.step() # the 25 registers after one tick; None once the song ends
|
|
250
|
+
player.regs # the register file the last tick wrote, one store per register
|
|
250
251
|
```
|
|
251
252
|
|
|
252
253
|
`read(text)` returns the document as plain dataclasses. A text outside the grammar raises
|
|
@@ -479,6 +479,17 @@ def test_the_player_steps_until_the_song_ends():
|
|
|
479
479
|
assert regs[24] is None and player.step() is None
|
|
480
480
|
|
|
481
481
|
|
|
482
|
+
def test_regs_is_the_register_file_each_tick_rewrites():
|
|
483
|
+
"""`Player.regs` holds the last tick's registers; each step returns a copy of it."""
|
|
484
|
+
player = Player(load(doc()))
|
|
485
|
+
first = player.step()
|
|
486
|
+
assert first == player.regs and first is not player.regs
|
|
487
|
+
player.voices[0].ad = 0x5A
|
|
488
|
+
after = player.registers()
|
|
489
|
+
assert [i for i, (x, y) in enumerate(zip(first, after)) if x != y] == [5]
|
|
490
|
+
assert after[5] == player.regs[5] == 0x5A and first[5] == 9
|
|
491
|
+
|
|
492
|
+
|
|
482
493
|
def _twice(text: str) -> str:
|
|
483
494
|
return text.replace(" ins:\n", " ins:\n i1: {ad: 1}\n", 1)
|
|
484
495
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unitracker_player-0.2.0 → unitracker_player-0.3.0}/src/unitracker_player.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{unitracker_player-0.2.0 → unitracker_player-0.3.0}/src/unitracker_player.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{unitracker_player-0.2.0 → unitracker_player-0.3.0}/src/unitracker_player.egg-info/requires.txt
RENAMED
|
File without changes
|
{unitracker_player-0.2.0 → unitracker_player-0.3.0}/src/unitracker_player.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|