Add playing over left, right or both channels, fixes #10

pull/14/head
Ewald de Wit 2022-09-25 12:00:26 +02:00
rodzic a17f14c6fc
commit d0c9f9a1bf
2 zmienionych plików z 22 dodań i 9 usunięć

Wyświetl plik

@ -54,10 +54,15 @@ class App(qt.QMainWindow):
if self.paused or lo >= hi or secs <= 0 or not ampl: if self.paused or lo >= hi or secs <= 0 or not ampl:
await asyncio.sleep(0.1) await asyncio.sleep(0.1)
continue continue
ch = self.channelsBox.currentIndex()
analyzer = hifi.Analyzer(lo, hi, secs, audio.rate, ampl, analyzer = hifi.Analyzer(lo, hi, secs, audio.rate, ampl,
self.calibration, self.target) self.calibration, self.target)
audio.play(analyzer.chirp) sound = analyzer.chirp
if ch:
silence = np.zeros_like(sound)
sound = [sound, silence] if ch == 1 else [silence, sound]
audio.play(sound)
async for recording in audio.record(): async for recording in audio.record():
if self.paused: if self.paused:
audio.cancelPlay() audio.cancelPlay()
@ -199,6 +204,8 @@ class App(qt.QMainWindow):
value=1.0, step=0.1, bounds=[0.1, 30], suffix='s') value=1.0, step=0.1, bounds=[0.1, 30], suffix='s')
self.ampl = pg.SpinBox( self.ampl = pg.SpinBox(
value=40, step=1, bounds=[0, 100], suffix='%') value=40, step=1, bounds=[0, 100], suffix='%')
self.channelsBox = qt.QComboBox()
self.channelsBox.addItems(['Stereo', 'Left', 'Right'])
self.spectrumSmoothing = pg.SpinBox( self.spectrumSmoothing = pg.SpinBox(
value=15, step=1, bounds=[0, 30]) value=15, step=1, bounds=[0, 30])
self.spectrumSmoothing.sigValueChanging.connect(self.plot) self.spectrumSmoothing.sigValueChanging.connect(self.plot)
@ -216,6 +223,7 @@ class App(qt.QMainWindow):
hbox.addSpacing(32) hbox.addSpacing(32)
hbox.addWidget(qt.QLabel('Amplitude: ')) hbox.addWidget(qt.QLabel('Amplitude: '))
hbox.addWidget(self.ampl) hbox.addWidget(self.ampl)
hbox.addWidget(self.channelsBox)
hbox.addSpacing(32) hbox.addSpacing(32)
hbox.addWidget(qt.QLabel('Smoothing: ')) hbox.addWidget(qt.QLabel('Smoothing: '))
hbox.addWidget(self.spectrumSmoothing) hbox.addWidget(self.spectrumSmoothing)

Wyświetl plik

@ -5,6 +5,7 @@ from typing import AsyncIterator, Deque
import eventkit as ev import eventkit as ev
import numpy as np import numpy as np
import numpy.typing as npt
import sounddevice as sd import sounddevice as sd
@ -21,7 +22,7 @@ class Audio:
self.recorded = ev.Event() self.recorded = ev.Event()
self.playQ: Deque[PlayItem] = deque() self.playQ: Deque[PlayItem] = deque()
self.stream = sd.Stream( self.stream = sd.Stream(
channels=1, channels=2,
callback=self._onStream) callback=self._onStream)
self.stream.start() self.stream.start()
self.rate = self.stream.samplerate self.rate = self.stream.samplerate
@ -42,16 +43,19 @@ class Audio:
idx = 0 idx = 0
while self.playQ and idx < frames: while self.playQ and idx < frames:
playItem = self.playQ[0] playItem = self.playQ[0]
chunk = playItem.pop(frames - idx) chunk = playItem.pop(frames - idx).T
idx2 = idx + chunk.size idx2 = idx + len(chunk)
out_data[idx:idx2, 0] = chunk out_data[idx:idx2, :] = chunk
idx = idx2 idx = idx2
if not playItem.remaining(): if not playItem.remaining():
self.playQ.popleft() self.playQ.popleft()
self.recorded.emit_threadsafe(in_data.copy()) self.recorded.emit_threadsafe(in_data.copy().T)
def play(self, sound: np.ndarray): def play(self, sound: npt.ArrayLike):
"""Add a sound to the play queue.""" """Add a sound to the play queue."""
sound = np.asarray(sound)
if len(sound.shape) == 1:
sound = np.vstack([sound, sound])
self.playQ.append(PlayItem(sound)) self.playQ.append(PlayItem(sound))
def cancelPlay(self): def cancelPlay(self):
@ -69,7 +73,8 @@ class Audio:
""" """
recording = array.array('f') recording = array.array('f')
return self.recorded.map( return self.recorded.map(
recording.extend).constant(recording).aiter(skip_to_last=True) lambda rec: recording.extend(0.5 * (rec[0] + rec[1]))) \
.constant(recording).aiter(skip_to_last=True)
@dataclass @dataclass
@ -82,6 +87,6 @@ class PlayItem:
def pop(self, num: int) -> np.ndarray: def pop(self, num: int) -> np.ndarray:
idx = self.index + min(num, self.remaining()) idx = self.index + min(num, self.remaining())
chunk = self.sound[self.index:idx] chunk = self.sound[:, self.index:idx]
self.index = idx self.index = idx
return chunk return chunk