kopia lustrzana https://github.com/erdewit/HiFiScan
Add playing over left, right or both channels, fixes #10
rodzic
a17f14c6fc
commit
d0c9f9a1bf
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
Ładowanie…
Reference in New Issue