Improve PCM audio by reducing framesize (so that latency is 0.01s) and adding a call...
authorNick Downing <nick@ndcode.org>
Sun, 22 May 2022 06:37:20 +0000 (16:37 +1000)
committerNick Downing <nick@ndcode.org>
Sun, 22 May 2022 06:37:20 +0000 (16:37 +1000)
apple_io.py

index 11bb7f5..7b97b69 100644 (file)
@@ -9,7 +9,7 @@ import time
 import tty
 
 PCM_RATE = 44100
-PCM_PERIODSIZE = 44100
+PCM_PERIODSIZE = 441
 
 # see https://www.tinaja.com/ebooks/tearing_rework.pdf
 ZP_WNDLFT = 0x20 # Left side of scroll window
@@ -209,7 +209,6 @@ mem = {
 }
 gr_color = 0
 gr_mem = [[0 for j in range(40)] for i in range(40)]
-pcm = None
 
 def init():
   global termios_attr, pcm
@@ -221,15 +220,6 @@ def init():
     # auto wrap off, hide cursor, reset attributes
     write('\x1b[?7l\x1b[?25l\x1b[0m')
 
-  if beep_style == BEEP_STYLE_ALSA:
-    pcm = alsaaudio.PCM(
-      device = 'default',
-      channels = 1,
-      rate = PCM_RATE,
-      format = alsaaudio.PCM_FORMAT_U8,
-      periodsize = PCM_PERIODSIZE
-    )
-
 def deinit():
   global termios_attr
 
@@ -357,20 +347,27 @@ def tone(freq, dur): # Hz, s
   if beep_style == BEEP_STYLE_VT100:
     write(f'\x1b[10;{round(freq):d}]\x1b[11;{round(dur * 1e3):d}]\a')
   elif beep_style == BEEP_STYLE_ALSA:
+    samples = math.floor(dur * PCM_RATE)
+    samples_last = (samples + PCM_PERIODSIZE - 1) % PCM_PERIODSIZE + 1
     buf = bytes(
       [
         0xff if math.floor(2 * freq * i / PCM_RATE) & 1 else 0
-        for i in range(math.floor(dur * PCM_RATE))
-      ]
+        for i in range(samples)
+      ] +
+      [0] * (PCM_PERIODSIZE - samples_last)
+    )
+
+    pcm = alsaaudio.PCM(
+      device = 'default',
+      channels = 1,
+      rate = PCM_RATE,
+      format = alsaaudio.PCM_FORMAT_U8,
+      periodsize = PCM_PERIODSIZE
     )
-    u = time.monotonic() + dur
     i = 0
     while i < len(buf):
       i += pcm.write(buf[i:])
-    t = time.monotonic()
-    while t < u:
-      time.sleep(u - t)
-      t = time.monotonic()
+    pcm.close()
   else: 
     assert False