fixed audio rendering

This commit is contained in:
2026-01-14 07:02:32 +11:00
parent 30835a506e
commit 2355520366
3 changed files with 66 additions and 14 deletions

3
src/project.py Normal file
View File

@@ -0,0 +1,3 @@
class Project:
def __init__(self):
pass

View File

@@ -9,7 +9,7 @@ from ui.widgets.project_settings import ProjectSettings
class AppUI(App):
def __init__(self):
super().__init__()
self.zoom_level = 0.1
self.zoom_level = 0.05
def compose(self) -> ComposeResult:
yield Sidebar()

View File

@@ -1,10 +1,10 @@
import librosa
import pyloudnorm as pyln
import numpy as np
import math
import random
from textual.containers import Vertical
from textual.widgets import Sparkline
from textual_plot import HiResMode, PlotWidget
from ui.widgets.chunk_types.chunk import Chunk
@@ -14,12 +14,15 @@ from ui.widgets.chunk_types.chunk import Chunk
class AudioChunk(Chunk):
DEFAULT_CSS = """
AudioChunk {
align: left middle;
Sparkline {
margin: 1;
PlotWidget {
height: 1fr;
.plot--axis {
color: transparent;
}
}
}
"""
def __init__(self, file_path: str, chunk_name: str = "Sample"):
@@ -28,7 +31,6 @@ class AudioChunk(Chunk):
self.file_path = file_path
self.audio, self.sample_rate = librosa.load(self.file_path, sr=None, mono=False)
self.num_channels = None
if len(self.audio.shape) == 1:
self.num_samples = self.audio.shape[0]
@@ -36,7 +38,6 @@ class AudioChunk(Chunk):
else:
self.num_samples = self.audio.shape[1]
self.num_channels = self.audio.shape[0]
self.notify(str(self.num_samples))
self.meter = pyln.Meter(self.sample_rate)
self.loudness_values = []
@@ -49,6 +50,50 @@ class AudioChunk(Chunk):
plot.margin_left = 0
plot.margin_bottom = 0
num_values = len(list(range(0, int(self.num_samples), int(self.sample_rate * 0.05))))
x = range(num_values)
y = []
if self.num_channels == 1:
# get rms
rms = librosa.feature.rms(y=self.audio)[0]
# split into N chunks
rms = np.array([
np.mean(chunk) if len(chunk) > 0 else 0.0
for chunk in np.array_split(rms, num_values)
])
# get the decibel values from that
y = list(librosa.amplitude_to_db(rms, ref=np.min))
else:
# get rms
rms = librosa.feature.rms(y=self.audio[int(plot.id[-1])])[0]
# split into N chunks
rms = np.array([
np.mean(chunk) if len(chunk) > 0 else 0.0
for chunk in np.array_split(rms, num_values)
])
# get the decibel values from that
y = librosa.amplitude_to_db(rms, ref=np.min)
plot.bar(
x,
y,
1.0,
bar_style=self.app.theme_variables["primary"],
hires_mode=HiResMode.HALFBLOCK
)
plot.set_xticks([])
plot.set_yticks([])
plot.set_ylimits(ymin=0)
def compose(self) -> ComposeResult:
@@ -57,19 +102,23 @@ class AudioChunk(Chunk):
# loop over each channel in the audio and display it seperately
for channel in range(self.num_channels):
samples = []
"""samples = []
for sample in range(0, self.num_samples, int(self.sample_rate*0.1)):
samples.append(self.audio[channel, sample])
samples.append(self.audio[channel, sample])"""
yield Sparkline(data=samples)
yield PlotWidget(allow_pan_and_zoom=False, id=f"channel-{channel}")
#yield Sparkline(data=samples)
else:
# just display the one channel
samples = []
"""samples = []
for sample in range(0, self.num_samples, int(self.sample_rate*0.1)):
samples.append(self.audio[sample])
samples.append(self.audio[sample])"""
yield Sparkline(data=samples)
yield PlotWidget(allow_pan_and_zoom=False)
#yield Sparkline(data=samples)