audio-spectrogram 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,44 @@
1
+ # Copyright 2026 - 2026, Artur Drogunow and the Audio-Spectrogram contributors
2
+ # SPDX-License-Identifier: GPL-3.0-or-later
3
+
4
+ import sys
5
+
6
+ from PySide6.QtWidgets import QMainWindow, QVBoxLayout, QWidget
7
+
8
+ from audio_spectrogram import APP_TITLE, __version__
9
+
10
+ from .control_panel_widget import ControlPanelWidget
11
+ from .plot_widget import PlotWidget
12
+
13
+
14
+ class MainWindow(QMainWindow):
15
+ def __init__(self) -> None:
16
+ super().__init__()
17
+
18
+ # variables
19
+
20
+ # widgets
21
+ self.control_panel_widget = ControlPanelWidget()
22
+ self.plot_widget = PlotWidget()
23
+
24
+ # setup
25
+ self._setup_widgets()
26
+ self._setup_layout()
27
+ self._connect_signals()
28
+
29
+ def _setup_widgets(self) -> None:
30
+ title = (
31
+ f"{APP_TITLE} {__version__} "
32
+ f"(Python {sys.version_info[0]}.{sys.version_info[1]}.{sys.version_info[2]})"
33
+ )
34
+ self.setWindowTitle(title)
35
+
36
+ def _setup_layout(self) -> None:
37
+ central_widget = QWidget()
38
+ self.setCentralWidget(central_widget)
39
+ vbox = QVBoxLayout(central_widget)
40
+ vbox.addWidget(self.control_panel_widget, 0)
41
+ vbox.addWidget(self.plot_widget, 1)
42
+
43
+ def _connect_signals(self) -> None:
44
+ pass
@@ -0,0 +1,58 @@
1
+ # Copyright 2026 - 2026, Artur Drogunow and the Audio-Spectrogram contributors
2
+ # SPDX-License-Identifier: GPL-3.0-or-later
3
+
4
+ import pyqtgraph as pg
5
+ from PySide6.QtWidgets import QGroupBox, QVBoxLayout
6
+
7
+ pg.setConfigOption(opt="useNumba", value=True)
8
+
9
+
10
+ class PlotWidget(QGroupBox):
11
+ def __init__(self) -> None:
12
+ super().__init__("Signal Viewer")
13
+
14
+ # variables
15
+
16
+ # widgets
17
+ self.glw = pg.GraphicsLayoutWidget()
18
+ self.time_plot = self.glw.addPlot(row=0, col=0)
19
+ self.time_plot_item = pg.PlotCurveItem()
20
+ self.spec_plot = self.glw.addPlot(row=1, col=0)
21
+ self.spec_plot_item = pg.ImageItem(axisOrder="row-major", levels=[-90, 0])
22
+
23
+ # setup
24
+ self._setup_widgets()
25
+ self._setup_layout()
26
+ self._connect_signals()
27
+
28
+ def _setup_widgets(self) -> None:
29
+ # set line properties
30
+ self.time_plot_item.setClickable(False)
31
+ self.time_plot_item.setPen(pg.mkPen("coral", width=0.5))
32
+ self.time_plot_item.setSkipFiniteCheck(True)
33
+ self.time_plot_item.setSegmentedLineMode("on")
34
+
35
+ # horizontally align left axis
36
+ self.time_plot.getAxis("left").setWidth(40)
37
+ self.spec_plot.getAxis("left").setWidth(40)
38
+
39
+ # setup time plot
40
+ self.time_plot.setLabel("left", "Amplitude")
41
+ self.time_plot.setLabel("bottom", "Time", units="s")
42
+ self.time_plot.showGrid(x=True, y=True)
43
+ self.time_plot.addItem(self.time_plot_item)
44
+
45
+ # setup spectrum plot
46
+ self.spec_plot.setYRange(-100, 7100)
47
+ self.spec_plot.setLabel("left", "Frequency", units="Hz")
48
+ self.spec_plot.setLabel("bottom", "Time", units="s")
49
+ self.spec_plot.showGrid(x=False, y=False)
50
+ self.spec_plot_item.setColorMap(pg.colormap.get("magma"))
51
+ self.spec_plot.addItem(self.spec_plot_item)
52
+
53
+ def _setup_layout(self) -> None:
54
+ layout = QVBoxLayout(self)
55
+ layout.addWidget(self.glw)
56
+
57
+ def _connect_signals(self) -> None:
58
+ pass
@@ -0,0 +1,42 @@
1
+ # Copyright 2026 - 2026, Artur Drogunow and the Audio-Spectrogram contributors
2
+ # SPDX-License-Identifier: GPL-3.0-or-later
3
+
4
+ import typing
5
+
6
+ from PySide6.QtWidgets import (
7
+ QSpinBox,
8
+ QWidget,
9
+ )
10
+
11
+ DEFAULT_VALUE: typing.Final = 1024
12
+ MIN_VALUE: typing.Final = 64
13
+
14
+
15
+ class PowerOfTwoSpinBox(QSpinBox):
16
+ def __init__(self, parent: QWidget | None = None) -> None:
17
+ super().__init__(parent)
18
+
19
+ self.setReadOnly(True)
20
+ self.setRange(MIN_VALUE, 2**30)
21
+ self.setValue(1024) # default value
22
+
23
+ @typing.override
24
+ def stepBy(self, steps: int, /) -> None:
25
+ value: int = self.value()
26
+
27
+ for _ in range(abs(steps)):
28
+ if steps > 0:
29
+ value *= 2
30
+ else:
31
+ value = max(MIN_VALUE, value // 2)
32
+
33
+ self.setValue(value)
34
+
35
+ @typing.override
36
+ def stepEnabled(self, /) -> QSpinBox.StepEnabledFlag:
37
+ flags = QSpinBox.StepEnabledFlag.StepUpEnabled
38
+
39
+ if self.value() > MIN_VALUE:
40
+ flags |= QSpinBox.StepEnabledFlag.StepDownEnabled
41
+
42
+ return flags
@@ -0,0 +1,63 @@
1
+ # Copyright 2026 - 2026, Artur Drogunow and the Audio-Spectrogram contributors
2
+ # SPDX-License-Identifier: GPL-3.0-or-later
3
+
4
+ import datetime
5
+ import logging
6
+ from typing import Final
7
+
8
+ from platformdirs import user_log_path
9
+
10
+ from audio_spectrogram import APP_TITLE, LOGGER, PACKAGE_NAME
11
+
12
+ VERBOSITY_LEVEL_APP_DEBUG: Final = 1
13
+ VERBOSITY_LEVEL_ROOT_WARNING: Final = 1
14
+ VERBOSITY_LEVEL_ROOT_INFO: Final = 2
15
+ VERBOSITY_LEVEL_ROOT_DEBUG: Final = 3
16
+
17
+
18
+ def setup_logging(verbosity: int) -> None:
19
+ iso_date = datetime.datetime.now(tz=datetime.UTC).strftime("%Y-%m-%d")
20
+ logfile_path = user_log_path(PACKAGE_NAME, ensure_exists=True) / f"{iso_date}.log"
21
+
22
+ with logfile_path.open(mode="at") as file:
23
+ if file.tell() > 0:
24
+ file.write("\n\n")
25
+ file.writelines(
26
+ [
27
+ "*" * 80 + "\n",
28
+ f"Start {APP_TITLE}".center(80) + "\n",
29
+ "*" * 80 + "\n",
30
+ ]
31
+ )
32
+
33
+ # instantiate logging handlers
34
+ file_handler = logging.FileHandler(logfile_path)
35
+ stream_handler = logging.StreamHandler()
36
+
37
+ # configure formatting
38
+ formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
39
+ file_handler.setFormatter(formatter)
40
+ stream_handler.setFormatter(formatter)
41
+
42
+ # determine log levels for app (package_level) and dependencies (root_level)
43
+ package_level = logging.DEBUG if verbosity >= VERBOSITY_LEVEL_APP_DEBUG else logging.INFO
44
+ if verbosity >= VERBOSITY_LEVEL_ROOT_DEBUG:
45
+ root_level = logging.DEBUG
46
+ elif verbosity >= VERBOSITY_LEVEL_ROOT_INFO:
47
+ root_level = logging.INFO
48
+ elif verbosity >= VERBOSITY_LEVEL_ROOT_WARNING:
49
+ root_level = logging.WARNING
50
+ else:
51
+ root_level = logging.ERROR
52
+
53
+ # configure root logger
54
+ root_logger = logging.getLogger()
55
+ root_logger.handlers.clear()
56
+ root_logger.setLevel(root_level)
57
+ root_logger.addHandler(file_handler)
58
+ root_logger.addHandler(stream_handler)
59
+
60
+ # configure package logger
61
+ LOGGER.setLevel(package_level)
62
+ LOGGER.info("Root log level: %s", logging.getLevelName(root_level))
63
+ LOGGER.info("Package log level: %s", logging.getLevelName(package_level))
@@ -0,0 +1,48 @@
1
+ Metadata-Version: 2.4
2
+ Name: audio-spectrogram
3
+ Version: 0.1.0
4
+ Summary: Audio spectrogram app based on PySide6
5
+ Author-email: Artur Drogunow <Artur.Drogunow@zf.com>
6
+ License: GPL-3.0-or-later
7
+ Project-URL: Issues, https://github.com/zariiii9003/audio_spectrogram/issues
8
+ Project-URL: Source, https://github.com/zariiii9003/audio_spectrogram
9
+ Keywords: Audio,Microphone,FFT,STFT,Spectrogram,Sonogram
10
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
15
+ Classifier: Programming Language :: Python :: Implementation :: CPython
16
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
17
+ Requires-Python: >=3.12
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: numba==0.65.*
21
+ Requires-Dist: numpy==2.4.*
22
+ Requires-Dist: platformdirs==4.9.*
23
+ Requires-Dist: pyqtgraph==0.14.*
24
+ Requires-Dist: pyside6==6.11.*
25
+ Requires-Dist: rocket-fft==0.3.*
26
+ Dynamic: license-file
27
+
28
+ # Audio Spectrogram
29
+
30
+ [![PyPI - Version](https://img.shields.io/pypi/v/audio-spectrogram.svg)](https://pypi.org/project/audio-spectrogram)
31
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/audio-spectrogram.svg)](https://pypi.org/project/audio-spectrogram)
32
+
33
+ ## Introduction
34
+
35
+ *Audio Spectrogram* is a small python GUI application to analyze the frequency content of your microphone input.
36
+
37
+ <img src="https://raw.githubusercontent.com/zariiii9003/audio_spectrogram/refs/heads/master/doc/GUI.png" width="683" alt="GUI Screenshot" />
38
+
39
+ ## Usage
40
+
41
+ You can run it directly from your command line:
42
+ ```bash
43
+ uvx audio-spectrogram
44
+ ```
45
+ or
46
+ ```bash
47
+ pipx audio-spectrogram
48
+ ```
@@ -0,0 +1,21 @@
1
+ audio_spectrogram/__init__.py,sha256=5EDkWGwK2wElA1YUBkPjBbDX6MHrcKcLYSAUIxT6PhE,370
2
+ audio_spectrogram/__main__.py,sha256=Ss1Tm75zZmuX_pQqJuLa76nPwhUj7gBe-Mz5ObDssvs,910
3
+ audio_spectrogram/util.py,sha256=VuKBtd6rgnKkaDZx6t0wh1Ff-ZQywBLgkMqNMOzP4NE,2185
4
+ audio_spectrogram/app/__init__.py,sha256=-Og5GFBNZ-JabE4MKs8oKmad2KLKLljI_L8a_m_8CPY,123
5
+ audio_spectrogram/app/application.py,sha256=GuZSet7Im-bn_EWOQUXd9qzgrIwZbkkvhTNQYqtzYkQ,2818
6
+ audio_spectrogram/app/control_panel_handler.py,sha256=R1RpaZcrf_4VwOaXB4ouYnEGqbqYuiGeNaJAvH0bF00,6271
7
+ audio_spectrogram/app/plot_handler.py,sha256=HBYyzF_eF2PFSvQQOKuadFaOQtMROYwd1XOZRhkBDR0,3824
8
+ audio_spectrogram/app/qapplication.py,sha256=QO9oYPxgxZbdLS13qXS9VCuFr7gPbp0cAo4UyvAlLnc,606
9
+ audio_spectrogram/app/spectrogram.py,sha256=YBJMjsmU72UugLNRvXbdliqviJR4b7ivWyVJJwCQ6xM,2387
10
+ audio_spectrogram/app/widgets/__init__.py,sha256=-Og5GFBNZ-JabE4MKs8oKmad2KLKLljI_L8a_m_8CPY,123
11
+ audio_spectrogram/app/widgets/combobox.py,sha256=bOdtX3y8_oLMdlBMHKK19rKhwMmGe_4zQreDyY4E-b0,1246
12
+ audio_spectrogram/app/widgets/control_panel_widget.py,sha256=zCGpE-Qb57v5fvq9gDQftyRKJgHUAGNg35JCXSq-79I,4410
13
+ audio_spectrogram/app/widgets/main_window.py,sha256=AxlhEqKGiXXgUClBv77vVICb-o9_jJw0JRmyYY_j4lY,1228
14
+ audio_spectrogram/app/widgets/plot_widget.py,sha256=aQkKOEXKdfrW1wLKBN8qh3GTL7h11IpeP8ljxnvtVXI,1997
15
+ audio_spectrogram/app/widgets/power_of_two_spinbox.py,sha256=h97FCkDcCk_jXOk07o2138QQpQQNLAer_3RgL92qP30,1062
16
+ audio_spectrogram-0.1.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
17
+ audio_spectrogram-0.1.0.dist-info/METADATA,sha256=Zduygfxv-TWQkrndJcKa_kJxK1CGQU4FfrihWtAAYJE,1783
18
+ audio_spectrogram-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
19
+ audio_spectrogram-0.1.0.dist-info/entry_points.txt,sha256=dAZ0_Eq--lfWJ1yhxiybwPQwdUckQg4Bbkgyr2hkuZ0,145
20
+ audio_spectrogram-0.1.0.dist-info/top_level.txt,sha256=HcjNccVeBlauPVpuVzz1qMRDiYT3YKpyHMJH2s6_f1A,18
21
+ audio_spectrogram-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,5 @@
1
+ [console_scripts]
2
+ audio-spectrogram-console = audio_spectrogram.__main__:main
3
+
4
+ [gui_scripts]
5
+ audio-spectrogram = audio_spectrogram.__main__:main