Skip to content

Commit

Permalink
Merge pull request #1 from nschloe/readme-fixes
Browse files Browse the repository at this point in the history
larger images
  • Loading branch information
nschloe authored Mar 26, 2020
2 parents 728fd10 + 736b88c commit 8673e66
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 23 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ jobs:
- uses: actions/checkout@v2
with:
lfs: true
- name: Install system dependencies
run: sudo apt install ffmpeg
- name: Test with tox
run: |
pip install tox
Expand Down
25 changes: 16 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# specky
<p align="center">
<a href="https://github.com/nschloe/specky"><img alt="specky" src="https://nschloe.github.io/specky/specky-logo.svg" width="50%"></a>
<p align="center">Delicious audio file spectrograms.</p>
</p>

[![gh-actions](https://img.shields.io/github/workflow/status/nschloe/specky/ci?style=flat-square)](https://github.com/nschloe/specky/actions?query=workflow%3Aci)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg?style=flat-square)](https://github.com/psf/black)
Expand All @@ -8,10 +11,14 @@
[![PyPi downloads](https://img.shields.io/pypi/dm/specky.svg?style=flat-square)](https://pypistats.org/packages/specky)

specky is a collection of easy-to-use Python and command-line tools for analyzing audio
files.
files. Install from [PyPi](https://pypi.org/project/specky/) with
```
pip install specky
```
and use with
```bash
specky-show filename.mp3 # shows the wave spectrum of the audio file
specky-check filename.mp3 # checks if the audio file is worse than it pretends to be
specky-show filename.mp3 # shows the wave spectrum of the audio file
specky-check {dirname or filename.mp3} # checks if the audio file is worse than it pretends to be
```
See `-h` for their respective command-line arguments.

Expand All @@ -24,13 +31,13 @@ Here is the `specky-show` output of a [sample
file](https://nschloe.github.io/specky/Yamaha-V50-Ride-Pattern-120bpm.wav) (only first
channel shown):

<img src="https://nschloe.github.io/specky/wav.png" width="70%"> | <img src="https://nschloe.github.io/specky/320.png" width="70%"> | <img src="https://nschloe.github.io/specky/256.png" width="70%">
<img src="https://nschloe.github.io/specky/wav.png" width="100%"> | <img src="https://nschloe.github.io/specky/320.png" width="100%"> | <img src="https://nschloe.github.io/specky/256.png" width="100%">
:-------------------:|:------------------:|:--------------:|
Full-quality WAV | 320 kbps MP3 | 256 kbps MP3 |
<img src="https://nschloe.github.io/specky/192.png" width="70%"> | <img src="https://nschloe.github.io/specky/128.png" width="70%"> | <img src="https://nschloe.github.io/specky/64.png" width="70%">
| 192 kbps MP3 | 128 kbps MP3 | 64 kbps MP3 |
<img src="https://nschloe.github.io/specky/96.png" width="70%"> | <img src="https://nschloe.github.io/specky/64.png" width="70%"> | <img src="https://nschloe.github.io/specky/32.png" width="70%">
| 96 kbps MP3 | 64 kbps MP3 | 32 kbps MP3 |
<img src="https://nschloe.github.io/specky/192.png" width="100%"> | <img src="https://nschloe.github.io/specky/128.png" width="100%"> | <img src="https://nschloe.github.io/specky/96.png" width="100%">
| 192 kbps MP3 | 128 kbps MP3 | 96 kbps MP3 |
<img src="https://nschloe.github.io/specky/64.png" width="100%"> | <img src="https://nschloe.github.io/specky/32.png" width="100%"> | <img src="https://nschloe.github.io/specky/16.png" width="100%">
| 64 kbps MP3 | 32 kbps MP3 | 16 kbps MP3 |


### License
Expand Down
3 changes: 2 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = specky
version = 0.1.0
version = 0.1.1
author = Nico Schlömer
email = [email protected]
description = Audio file spectral analysis
Expand Down Expand Up @@ -31,6 +31,7 @@ install_requires =
colorama
importlib_metadata
matplotlib
mutagen
numpy
pydub
scipy
Expand Down
44 changes: 34 additions & 10 deletions specky/_main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import glob
import os

import matplotlib.colors as colors
Expand All @@ -9,7 +10,14 @@
from scipy import signal


def show(filename, min_freq=1.0e-2, window_length_s=0.05, channel=None, outfile=None):
def show(
filename,
min_freq=1.0e-2,
num_windows=None,
num_frequencies=None,
channel=None,
outfile=None,
):
track = AudioSegment.from_file(filename)

out = numpy.array(track.get_array_of_samples()).reshape(-1, track.channels)
Expand All @@ -19,25 +27,28 @@ def show(filename, min_freq=1.0e-2, window_length_s=0.05, channel=None, outfile=
else:
channels = [channel - 1]

if window_length_s is None:
if num_windows is None:
nperseg = None
else:
nperseg = int(round(window_length_s * track.frame_rate))

# overlap = 0.5
# noverlap = int(round(overlap * window_length_samples))
nperseg = int(round(track.duration_seconds / num_windows * track.frame_rate))

for i, k in enumerate(channels):
# Perhaps one can downsample this.
# https://stackoverflow.com/q/60866162/353337
f, t, Sxx = signal.spectrogram(
out[:, k],
fs=track.frame_rate,
scaling="spectrum",
mode="magnitude",
# nperseg=window_length_samples
nperseg=nperseg,
# noverlap=noverlap
)

if num_frequencies is not None:
# ditch some of the frequencies
f_step = -(-f.shape[0] // num_frequencies)
f = f[::f_step]
Sxx = Sxx[::f_step]

# Make sure all values are positive for the log scaling
smallest_positive = numpy.min(Sxx[Sxx > 0])
Sxx[Sxx < smallest_positive] = smallest_positive
Expand All @@ -59,7 +70,18 @@ def show(filename, min_freq=1.0e-2, window_length_s=0.05, channel=None, outfile=
plt.savefig(outfile, transparent=True, bbox_inches="tight")


def check(filename, min_freq=1.0e-2, window_length_s=0.05, channel=0):
def check(path, **kwargs):
if os.path.isfile(path):
_check_file(path, **kwargs)
return

assert os.path.isdir(path)
for filename in glob.glob(path + "/**/*.mp3", recursive=True):
_check_file(filename, **kwargs)
return


def _check_file(filename, min_freq=1.0e-2, window_length_s=0.05, channel=0):
track = AudioSegment.from_file(filename)

out = numpy.array(track.get_array_of_samples()).reshape(-1, track.channels)
Expand Down Expand Up @@ -117,7 +139,9 @@ def check(filename, min_freq=1.0e-2, window_length_s=0.05, channel=0):
expected_max_freq = val

if f[k] > expected_max_freq:
print(f"{Fore.GREEN}{filename} seems good.{Style.RESET_ALL}")
print(
f"{Fore.GREEN}{filename} seems good [{bitrate} kbps].{Style.RESET_ALL}"
)
else:
print(
f"{Fore.RED}{filename} is MP3 [{bitrate} kbps], but has max frequency "
Expand Down
4 changes: 2 additions & 2 deletions specky/cli/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def check(argv=None):
# Parse command line arguments.
parser = _get_parser()
args = parser.parse_args(argv)
main_check(args.filename)
main_check(args.path)


def _get_parser():
Expand All @@ -19,7 +19,7 @@ def _get_parser():
formatter_class=argparse.RawTextHelpFormatter,
)

parser.add_argument("filename", type=str, help="audio file to analyze")
parser.add_argument("path", type=str, help="audio file or directory to analyze")

version_text = "\n".join(
[
Expand Down
24 changes: 23 additions & 1 deletion specky/cli/show.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ def show(argv=None):
# Parse command line arguments.
parser = _get_parser()
args = parser.parse_args(argv)
main_show(args.filename, channel=args.channel, outfile=args.outfile)
main_show(
args.filename,
channel=args.channel,
outfile=args.outfile,
num_windows=args.num_windows,
num_frequencies=args.num_frequencies,
)


def _get_parser():
Expand All @@ -29,6 +35,22 @@ def _get_parser():
help="only show one particular channel (default: show all channels)",
)

parser.add_argument(
"-w",
"--num-windows",
default=300,
type=int,
help="number of windows (x-axis resolution, default: 300)",
)

parser.add_argument(
"-f",
"--num-frequencies",
default=300,
type=int,
help="number of frequencies (y-axis resolution, default: 300)",
)

parser.add_argument(
"-o",
"--outfile",
Expand Down

0 comments on commit 8673e66

Please sign in to comment.