mirror of
https://github.com/chidiwilliams/buzz.git
synced 2026-03-17 16:10:08 +01:00
Will show average amplitude in the widget
This commit is contained in:
parent
c8b15d6beb
commit
9508103420
4 changed files with 42 additions and 9 deletions
|
|
@ -9,6 +9,9 @@ from PyQt6.QtCore import QObject, pyqtSignal
|
|||
class RecordingAmplitudeListener(QObject):
|
||||
stream: Optional[sounddevice.InputStream] = None
|
||||
amplitude_changed = pyqtSignal(float)
|
||||
average_amplitude_changed = pyqtSignal(float)
|
||||
|
||||
ACCUMULATION_SECONDS = 1
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
|
@ -17,6 +20,8 @@ class RecordingAmplitudeListener(QObject):
|
|||
):
|
||||
super().__init__(parent)
|
||||
self.input_device_index = input_device_index
|
||||
self.buffer = np.ndarray([], dtype=np.float32)
|
||||
self.accumulation_size = 0
|
||||
|
||||
def start_recording(self):
|
||||
try:
|
||||
|
|
@ -27,6 +32,7 @@ class RecordingAmplitudeListener(QObject):
|
|||
callback=self.stream_callback,
|
||||
)
|
||||
self.stream.start()
|
||||
self.accumulation_size = int(self.stream.samplerate * self.ACCUMULATION_SECONDS)
|
||||
except Exception as e:
|
||||
self.stop_recording()
|
||||
logging.exception("Failed to start audio stream on device %s: %s", self.input_device_index, e)
|
||||
|
|
@ -38,5 +44,9 @@ class RecordingAmplitudeListener(QObject):
|
|||
|
||||
def stream_callback(self, in_data: np.ndarray, frame_count, time_info, status):
|
||||
chunk = in_data.ravel()
|
||||
amplitude = np.sqrt(np.mean(chunk**2)) # root-mean-square
|
||||
self.amplitude_changed.emit(amplitude)
|
||||
self.amplitude_changed.emit(float(np.sqrt(np.mean(chunk**2))))
|
||||
|
||||
self.buffer = np.append(self.buffer, chunk)
|
||||
if self.buffer.size >= self.accumulation_size:
|
||||
self.average_amplitude_changed.emit(float(np.sqrt(np.mean(self.buffer**2))))
|
||||
self.buffer = np.ndarray([], dtype=np.float32)
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ class RecordingTranscriber(QObject):
|
|||
finished = pyqtSignal()
|
||||
error = pyqtSignal(str)
|
||||
amplitude_changed = pyqtSignal(float)
|
||||
average_amplitude_changed = pyqtSignal(float)
|
||||
is_running = False
|
||||
SAMPLE_RATE = whisper_audio.SAMPLE_RATE
|
||||
|
||||
|
|
@ -180,6 +181,7 @@ class RecordingTranscriber(QObject):
|
|||
self.mutex.release()
|
||||
|
||||
amplitude = self.amplitude(samples)
|
||||
self.average_amplitude_changed.emit(amplitude)
|
||||
|
||||
logging.debug(
|
||||
"Processing next frame, sample size = %s, queue size = %s, amplitude = %s",
|
||||
|
|
@ -188,7 +190,7 @@ class RecordingTranscriber(QObject):
|
|||
amplitude,
|
||||
)
|
||||
|
||||
if amplitude < 0.025:
|
||||
if amplitude < 0.0025:
|
||||
time.sleep(0.5)
|
||||
continue
|
||||
|
||||
|
|
@ -351,7 +353,7 @@ class RecordingTranscriber(QObject):
|
|||
# Try to enqueue the next block. If the queue is already full, drop the block.
|
||||
chunk: np.ndarray = in_data.ravel()
|
||||
|
||||
amplitude = float(np.sqrt(np.mean(chunk**2)))
|
||||
amplitude = self.amplitude(chunk)
|
||||
self.amplitude_changed.emit(amplitude)
|
||||
|
||||
with self.mutex:
|
||||
|
|
@ -360,7 +362,7 @@ class RecordingTranscriber(QObject):
|
|||
|
||||
@staticmethod
|
||||
def amplitude(arr: np.ndarray):
|
||||
return (abs(max(arr)) + abs(min(arr))) / 2
|
||||
return float(np.sqrt(np.mean(arr**2)))
|
||||
|
||||
def _drain_stderr(self):
|
||||
if self.process and self.process.stderr:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from typing import Optional
|
||||
|
||||
from PyQt6 import QtGui
|
||||
from PyQt6.QtCore import Qt
|
||||
from PyQt6.QtCore import Qt, QRect
|
||||
from PyQt6.QtGui import QColor, QPainter
|
||||
from PyQt6.QtWidgets import QWidget
|
||||
|
||||
|
|
@ -20,13 +20,16 @@ class AudioMeterWidget(QWidget):
|
|||
def __init__(self, parent: Optional[QWidget] = None):
|
||||
super().__init__(parent)
|
||||
self.setMinimumWidth(10)
|
||||
self.setFixedHeight(16)
|
||||
self.setFixedHeight(30)
|
||||
|
||||
self.BARS_HEIGHT = 14
|
||||
# Extra padding to fix layout
|
||||
self.PADDING_TOP = 3
|
||||
|
||||
self.current_amplitude = 0.0
|
||||
|
||||
self.average_amplitude = 0.0
|
||||
|
||||
self.MINIMUM_AMPLITUDE = 0.00005 # minimum amplitude to show the first bar
|
||||
self.AMPLITUDE_SCALE_FACTOR = 10 # scale the amplitudes such that 1/AMPLITUDE_SCALE_FACTOR will show all bars
|
||||
|
||||
|
|
@ -58,18 +61,23 @@ class AudioMeterWidget(QWidget):
|
|||
center_x - ((i + 1) * (self.BAR_MARGIN + self.BAR_WIDTH)),
|
||||
rect.top() + self.PADDING_TOP,
|
||||
self.BAR_WIDTH,
|
||||
rect.height() - self.PADDING_TOP,
|
||||
self.BARS_HEIGHT - self.PADDING_TOP,
|
||||
)
|
||||
# draw to right
|
||||
painter.drawRect(
|
||||
center_x + (self.BAR_MARGIN + (i * (self.BAR_MARGIN + self.BAR_WIDTH))),
|
||||
rect.top() + self.PADDING_TOP,
|
||||
self.BAR_WIDTH,
|
||||
rect.height() - self.PADDING_TOP,
|
||||
self.BARS_HEIGHT - self.PADDING_TOP,
|
||||
)
|
||||
|
||||
text_rect = QRect(rect.left(), self.BARS_HEIGHT, rect.width(), rect.height() - self.BARS_HEIGHT)
|
||||
painter.setPen(self.BAR_ACTIVE_COLOR)
|
||||
painter.drawText(text_rect, Qt.AlignmentFlag.AlignCenter, f"{self.average_amplitude:.4f}")
|
||||
|
||||
def reset_amplitude(self):
|
||||
self.current_amplitude = 0.0
|
||||
self.average_amplitude = 0.0
|
||||
self.repaint()
|
||||
|
||||
def update_amplitude(self, amplitude: float):
|
||||
|
|
@ -77,3 +85,7 @@ class AudioMeterWidget(QWidget):
|
|||
amplitude, self.current_amplitude * self.SMOOTHING_FACTOR
|
||||
)
|
||||
self.update()
|
||||
|
||||
def update_average_amplitude(self, amplitude: float):
|
||||
self.average_amplitude = amplitude
|
||||
self.update()
|
||||
|
|
|
|||
|
|
@ -509,6 +509,9 @@ class RecordingTranscriberWidget(QWidget):
|
|||
self.recording_amplitude_listener.amplitude_changed.connect(
|
||||
self.on_recording_amplitude_changed, Qt.ConnectionType.QueuedConnection
|
||||
)
|
||||
self.recording_amplitude_listener.average_amplitude_changed.connect(
|
||||
self.audio_meter_widget.update_average_amplitude, Qt.ConnectionType.QueuedConnection
|
||||
)
|
||||
self.recording_amplitude_listener.start_recording()
|
||||
|
||||
def on_record_button_clicked(self):
|
||||
|
|
@ -519,6 +522,9 @@ class RecordingTranscriberWidget(QWidget):
|
|||
self.recording_amplitude_listener.amplitude_changed.disconnect(
|
||||
self.on_recording_amplitude_changed
|
||||
)
|
||||
self.recording_amplitude_listener.average_amplitude_changed.disconnect(
|
||||
self.audio_meter_widget.update_average_amplitude
|
||||
)
|
||||
self.recording_amplitude_listener.stop_recording()
|
||||
self.recording_amplitude_listener = None
|
||||
self.audio_meter_widget.reset_amplitude()
|
||||
|
|
@ -587,6 +593,9 @@ class RecordingTranscriberWidget(QWidget):
|
|||
self.transcriber.amplitude_changed.connect(
|
||||
self.on_recording_amplitude_changed, Qt.ConnectionType.QueuedConnection
|
||||
)
|
||||
self.transcriber.average_amplitude_changed.connect(
|
||||
self.audio_meter_widget.update_average_amplitude, Qt.ConnectionType.QueuedConnection
|
||||
)
|
||||
|
||||
# Stop the separate amplitude listener to avoid two streams on the same device
|
||||
if self.recording_amplitude_listener is not None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue