diff --git a/src/project.py b/src/project.py new file mode 100644 index 0000000..c9ce23d --- /dev/null +++ b/src/project.py @@ -0,0 +1,3 @@ +class Project: + def __init__(self): + pass \ No newline at end of file diff --git a/src/ui/app.py b/src/ui/app.py index 8e29267..7217aa0 100644 --- a/src/ui/app.py +++ b/src/ui/app.py @@ -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() diff --git a/src/ui/widgets/chunk_types/audio.py b/src/ui/widgets/chunk_types/audio.py index 8806b1c..ac65715 100644 --- a/src/ui/widgets/chunk_types/audio.py +++ b/src/ui/widgets/chunk_types/audio.py @@ -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,11 +14,14 @@ 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; + } + } - } """ @@ -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 = [] @@ -48,6 +49,50 @@ class AudioChunk(Chunk): plot.margin_top = 0 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) \ No newline at end of file + yield PlotWidget(allow_pan_and_zoom=False) + + #yield Sparkline(data=samples) \ No newline at end of file