Skip to content

Commit e121bc5

Browse files
committed
Get bpm from sound description if possible
1 parent 7e48c8e commit e121bc5

2 files changed

Lines changed: 41 additions & 2 deletions

File tree

freesound/audio_descriptor_settings.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@
5656
{
5757
"name": "bpm",
5858
"analyzer": "fs-essentia-extractor_v1",
59-
"get_func": lambda d, s: d["fs.bpm"],
59+
"get_func": lambda d, s: s.estimate_bpm_from_metadata() or d["fs.bpm"],
6060
},
6161
{
6262
"name": "bpm_confidence",
6363
"analyzer": "fs-essentia-extractor_v1",
64-
"get_func": lambda d, s: d["fs.bpm_confidence"],
64+
"get_func": lambda d, s: 1.0 if s.estimate_bpm_from_metadata() else d["fs.bpm_confidence"],
6565
},
6666
{
6767
"name": "brightness",

sounds/models.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import math
2626
import os
2727
import random
28+
import re
2829
import zlib
2930
from collections import Counter
3031
from urllib.parse import quote
@@ -1654,6 +1655,44 @@ def get_second_level_category_search_url(self):
16541655
else:
16551656
return None
16561657

1658+
def estimate_bpm_from_metadata(self, min_bpm=25, max_bpm=300):
1659+
"""
1660+
Estimate the bpm of a sound by looking at its description, tags and name.
1661+
:param min_bpm: minimum bpm
1662+
:param max_bpm: maximum bpm
1663+
:return: estimated bpm (int) or 0 if bpm could not be estimated
1664+
"""
1665+
bpm_candidates = list()
1666+
1667+
# Find sequences like 120bpm, bpm120, 120 bpm or bpm 120 in all fields
1668+
description = self.description.lower()
1669+
name = self.original_filename.lower()
1670+
tags = [t.lower() for t in self.get_sound_tags()]
1671+
for candidate in re.findall(r"\d+[\s]?bpm", description + " " + name + " " + " ".join(tags)) + re.findall(
1672+
r"bpm[\s]?\d+", description + " " + name + " " + " ".join(tags)
1673+
):
1674+
try:
1675+
bpm = int(candidate.replace("bpm", "").replace(" ", ""))
1676+
if min_bpm <= bpm <= max_bpm:
1677+
bpm_candidates.append(bpm)
1678+
except ValueError:
1679+
continue
1680+
1681+
# Find tags corresponding to single numbers and in a range
1682+
for tag in tags:
1683+
try:
1684+
bpm = int(tag)
1685+
if min_bpm <= bpm <= max_bpm:
1686+
bpm_candidates.append(bpm)
1687+
except ValueError:
1688+
continue
1689+
1690+
if not bpm_candidates:
1691+
return 0
1692+
1693+
# Return the most common candidate
1694+
return Counter(bpm_candidates).most_common(1)[0][0]
1695+
16571696
class Meta:
16581697
ordering = ("-created",)
16591698
indexes = [

0 commit comments

Comments
 (0)