Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: GlasgowEmbedded/glasgow
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1048640e6403
Choose a base ref
...
head repository: GlasgowEmbedded/glasgow
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: dee9eee6b94f
Choose a head ref
  • 1 commit
  • 1 file changed
  • 1 contributor

Commits on Apr 3, 2019

  1. applet.audio.yamaha_opl: flush command stream each 20 ms.

    Otherwise, the playback coroutine is starving the record coroutine.
    This doesn't seem entirely reliable--other options?
    whitequark committed Apr 3, 2019
    Copy the full SHA
    dee9eee View commit details
Showing with 13 additions and 2 deletions.
  1. +13 −2 software/glasgow/applet/audio/yamaha_opl/__init__.py
15 changes: 13 additions & 2 deletions software/glasgow/applet/audio/yamaha_opl/__init__.py
Original file line number Diff line number Diff line change
@@ -336,6 +336,11 @@ def __init__(self, interface, logger, instant_writes=True):
self._feature_level = 1
self._feature_warned = False

# To ensure a steady supply of commands and avoid starving the playback coroutine,
# flush each `flush_period` clocks.
self._clock_counter = 0
self.flush_period = 0

@abstractmethod
def get_vgm_clock_rate(self, vgm_reader):
pass
@@ -428,6 +433,8 @@ async def write_register(self, address, data, check_feature=True):
await self.lower.write([OP_WRITE|addr_high|0, addr_low, OP_WRITE|1, data])

async def wait_clocks(self, count):
self._clock_counter += count

if self._instant_writes:
old_phase_accum = self._phase_accum
self._phase_accum -= count
@@ -446,7 +453,10 @@ async def wait_clocks(self, count):
await self.lower.write([OP_WAIT, *struct.pack(">H", 65535)])
count -= 65535
await self.lower.write([OP_WAIT, *struct.pack(">H", count)])
await self.lower.flush()

if self._clock_counter >= self.flush_period:
self._clock_counter = 0
await self.lower.flush()

async def read_samples(self, count):
self._log("read %d samples", count)
@@ -617,6 +627,7 @@ async def serve_vgm(self, request):
raise ValueError("VGM file does not contain commands for any supported chip")
if clock_rate & 0xc0000000:
raise ValueError("VGM file uses unsupported chip configuration")
self._opx_iface.flush_period = clock_rate / 50 # each 20 ms

self._logger.info("web: %s: VGM is looped for %.2f/%.2f s",
digest, vgm_reader.loop_seconds, vgm_reader.total_seconds)
@@ -834,6 +845,7 @@ async def interact(self, device, args, opx_iface):
"supported chip")
if clock_rate & 0xc0000000:
raise GlasgowAppletError("VGM file uses unsupported chip configuration")
self._opx_iface.flush_period = clock_rate / 50 # each 20 ms

vgm_player = YamahaVGMStreamPlayer(vgm_reader, opx_iface, clock_rate)
self.logger.info("recording at sample rate %d Hz", 1 / vgm_player.sample_time)
@@ -851,7 +863,6 @@ async def write_pcm(input_queue):
write_fut = asyncio.ensure_future(write_pcm(input_queue))
done, pending = await asyncio.wait([play_fut, record_fut, write_fut],
return_when=asyncio.FIRST_EXCEPTION)
print(done, pending)
for fut in done:
await fut