Skip to content

3. Script I use

username116 edited this page Oct 1, 2024 · 68 revisions

Demo

Video with percentages

video2.mp4
Video with progress bar

video1.mp4
Results

9 / 13, flac
Tommy Guerrero  \  2018 - Road to knowhere  \  09. Slow roll

classic              3.0 %            (Genres Rosamerica)
dance                1.4 %
hip hop             17.4 %
jazz                 7.6 %
pop                 23.0 %
rhythm and blues    32.7 %
rock                13.4 %
speech               1.4 %

blues               27.4 %            (Genres Tzanetakis)
classic              0.5 %
country              1.2 %
disco                0.6 %
hip hop              4.5 %
jazz                 0.8 %
metal                0.5 %
pop                  1.5 %
reggae              52.0 %
rock                11.1 %

Electronic           1.0 %            (Genres FMA small)
Experimental         1.4 %
Folk                 2.3 %
Hip-Hop              1.1 %
Instrumental         4.4 %
International       75.9 %
Pop                  7.3 %
Rock                 6.3 %

Reggae - Dub                      25.9 %     (Genres Discogs400)
Reggae - Rocksteady               19.6 %
Funk-Soul - Afrobeat              17.5 %
Reggae - Reggae                   14.2 %
Jazz - Afrobeat                   12.9 %
Reggae - Ska                      12.4 %
Funk-Soul - Psychedelic           11.9 %
Jazz - Bossa Nova                  9.3 %
Rock - Ska                         7.3 %
Rock - Psychedelic Rock            7.3 %
Electronic - Downtempo             6.8 %
Folk World & Country - African     6.5 %
Funk-Soul - Funk                   6.4 %

Groupe 10  25 - 100%   Reggae - Dub
Groupe 11  22.5-100%   Reggae - Dub
Groupe 12  20 - 100%   Reggae - Dub
Groupe 13  17.5-100%   Reggae - Dub, Reggae - Rocksteady, Funk-Soul - Afrobeat
Groupe 14  15 - 100%   Reggae - Dub, Reggae - Rocksteady, Funk-Soul - Afrobeat
Groupe 15  12.5-100%   Reggae - Dub, Reggae - Rocksteady, Funk-Soul - Afrobeat, Reggae - Reggae, Jazz - Afrobeat
Groupe 16  10 - 100%   Reggae - Dub, Reggae - Rocksteady, Funk-Soul - Afrobeat, Reggae - Reggae, Jazz - Afrobeat, Reggae - Ska, Funk-Soul - Psychedelic
Groupe 17   7.5-100%   Reggae - Dub, Reggae - Rocksteady, Funk-Soul - Afrobeat, Reggae - Reggae, Jazz - Afrobeat, Reggae - Ska, Funk-Soul - Psychedelic, Jazz - Bossa Nova
Groupe 18   5 - 100%   Reggae - Dub, Reggae - Rocksteady, Funk-Soul - Afrobeat, Reggae - Reggae, Jazz - Afrobeat, Reggae - Ska, Funk-Soul - Psychedelic, Jazz - Bossa Nova, Rock - Ska, Rock - Psychedelic Rock, Electronic - Downtempo, Folk World & Country - African, Funk-Soul - Funk

not approachable    24.4 %
approachable        75.6 %
not engaging        33.8 %
engaging            66.2 %
valence              4.97
arousal              5.28
danceable           84.7 %
not danceable       15.3 %
aggressive           6.8 %
not aggressive      93.2 %
happy               66.3 %
non happy           33.7 %
non party           62.0 %
party               38.0 %
non relaxed         10.8 %
relaxed             89.2 %
non sad             80.4 %
sad                 19.6 %
acoustic            28.5 %
non acoustic        71.5 %
electronic          65.6 %
non electronic      34.4 %
instrumental        84.5 %
voice               15.5 %
female              43.6 %
male                56.4 %
bright              41.2 %
dark                58.8 %
tonal               81.3 %
atonal              18.7 %

bpm                156.3
key                   Am

Tags saved in file

Artist name           : Tommy Guerrero
Track title           : Slow roll
Album title           : Road to knowhere
Date                  : 2018
Es genre Rosamerica   : 3.0; 1.4; 17.4; 7.6; 23.0; 32.7; 13.4; 1.4                     (classic / dance / hip hop / jazz / pop / rhythm and blues / rock / speech)
Es genre Tzanetakis   : 27.4; 0.5; 1.2; 0.6; 4.5; 0.8; 0.5; 1.5; 52.0; 11.1            (blues / classic / country / disco / hip hop / jazz / metal / pop / reggae / rock)
Es genre FMA small    : 1.0; 1.4; 2.3; 1.1; 4.4; 75.9; 7.3; 6.3                        (Electronic / Experimental / Folk / Hip-Hop / Instrumental / International / Pop / Rock)
Es approachability    : 24.4; 75.6                                                     (not approachable / approachable)
Es engagement         : 33.8; 66.2                                                     (not engaging / engaging)
Es arousal/valence    : 4.97; 5.28                                                     (valence / arousal)
Es danceability       : 84.7; 15.3                                                     (danceable / not danceable)
Es mood aggressive    : 6.8; 93.2                                                      (aggressive / not aggressive)
Es mood happy         : 66.3; 33.7                                                     (happy / non happy)
Es mood party         : 62.0; 38.0                                                     (non party / party)
Es mood relaxed       : 10.8; 89.2                                                     (non relaxed / relaxed)
Es mood sad           : 80.4; 19.6                                                     (non sad / sad)
Es mood acoustic      : 28.5; 71.5                                                     (acoustic / non acoustic)
Es mood electronic    : 65.6; 34.4                                                     (electronic / non electronic)
Es voice/instrumental : 84.5; 15.5                                                     (instrumental / voice)
Es voice gender       : 43.6; 56.4                                                     (female / male)
Es timbre             : 41.2; 58.8                                                     (bright / dark)
Es tonal/atonal       : 81.3; 18.7                                                     (tonal / atonal)
Es key                : Am
Es bpm                : 156.3
Es Discogs 90-100 %   : 
Es Discogs 80-100 %   : 
Es Discogs 70-100 %   : 
Es Discogs 60-100 %   : 
Es Discogs 50-100 %   : 
Es Discogs 45-100 %   : 
Es Discogs 40-100 %   : 
Es Discogs 35-100 %   : 
Es Discogs 30-100 %   : 
Es Discogs 25-100 %   : Reggae - Dub
Es Discogs 22.5-100 % : Reggae - Dub
Es Discogs 20-100 %   : Reggae - Dub
Es Discogs 17.5-100 % : Reggae - Dub; Reggae - Rocksteady; Funk-Soul - Afrobeat
Es Discogs 15-100 %   : Reggae - Dub; Reggae - Rocksteady; Funk-Soul - Afrobeat
Es Discogs 12.5-100 % : Reggae - Dub; Reggae - Rocksteady; Funk-Soul - Afrobeat; Reggae - Reggae; Jazz - Afrobeat
Es Discogs 10-100 %   : Reggae - Dub; Reggae - Rocksteady; Funk-Soul - Afrobeat; Reggae - Reggae; Jazz - Afrobeat; Reggae - Ska; Funk-Soul - Psychedelic
Es Discogs 7.5-100 %  : Reggae - Dub; Reggae - Rocksteady; Funk-Soul - Afrobeat; Reggae - Reggae; Jazz - Afrobeat; Reggae - Ska; Funk-Soul - Psychedelic; Jazz - Bossa Nova
Es Discogs 5-100 %    : Reggae - Dub; Reggae - Rocksteady; Funk-Soul - Afrobeat; Reggae - Reggae; Jazz - Afrobeat; Reggae - Ska; Funk-Soul - Psychedelic; Jazz - Bossa Nova; Rock - Ska; Rock - Psychedelic Rock; Electronic - Downtempo; Folk World & Country - African; Funk-Soul - Funk

This is not the exact name of the tags, it's the foobar2000 Properties window.

CPU load

screenshot

The song Slow Roll can be listened to on Bandcamp. After a search, the closest tracks in my library are this one, then this one, with scores of 93.1 and 92.7.

Models

Feature extractors Models
Discogs-EffNet discogs-effnet-bs64
MSD-MusiCNN msd-musicnn
Classifiers Models
Genre Rosamerica genre_rosamerica-discogs-effnet
Genre Tzanetakis genre_tzanetakis-discogs-effnet
FMA Small fma_small-discogs-effnet
Genre Discogs400 genre_discogs400-discogs-effnet
Approachability approachability_2c-discogs-effnet
Engagement engagement_2c-discogs-effnet
Arousal/valence DEAM deam-msd-musicnn
Danceability danceability-discogs-effnet
Mood Aggressive mood_aggressive-discogs-effnet
Mood Happy mood_happy-discogs-effnet
Mood Party mood_party-discogs-effnet
Mood Relaxed mood_relaxed-discogs-effnet
Mood Sad mood_sad-discogs-effnet
Mood Acoustic mood_acoustic-discogs-effnet
Mood Electronic mood_electronic-discogs-effnet
Voice/instrumental voice_instrumental-discogs-effnet
Voice gender gender-discogs-effnet
Timbre timbre-discogs-effnet
Tonal/atonal tonal_atonal-discogs-effnet
Download links

https://essentia.upf.edu/models/feature-extractors/discogs-effnet/discogs-effnet-bs64-1.pb
https://essentia.upf.edu/models/feature-extractors/discogs-effnet/discogs-effnet-bs64-1.json
https://essentia.upf.edu/models/feature-extractors/musicnn/msd-musicnn-1.pb
https://essentia.upf.edu/models/feature-extractors/musicnn/msd-musicnn-1.json

https://essentia.upf.edu/models/classification-heads/genre_rosamerica/genre_rosamerica-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/genre_rosamerica/genre_rosamerica-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/genre_tzanetakis/genre_tzanetakis-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/genre_tzanetakis/genre_tzanetakis-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/fma_small/fma_small-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/fma_small/fma_small-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/genre_discogs400/genre_discogs400-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/genre_discogs400/genre_discogs400-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/approachability/approachability_2c-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/approachability/approachability_2c-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/engagement/engagement_2c-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/engagement/engagement_2c-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/deam/deam-msd-musicnn-2.pb
https://essentia.upf.edu/models/classification-heads/deam/deam-msd-musicnn-2.json
https://essentia.upf.edu/models/classification-heads/danceability/danceability-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/danceability/danceability-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/mood_aggressive/mood_aggressive-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/mood_aggressive/mood_aggressive-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/mood_happy/mood_happy-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/mood_happy/mood_happy-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/mood_party/mood_party-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/mood_party/mood_party-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/mood_relaxed/mood_relaxed-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/mood_relaxed/mood_relaxed-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/mood_sad/mood_sad-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/mood_sad/mood_sad-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/mood_acoustic/mood_acoustic-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/mood_acoustic/mood_acoustic-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/mood_electronic/mood_electronic-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/mood_electronic/mood_electronic-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/voice_instrumental/voice_instrumental-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/voice_instrumental/voice_instrumental-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/gender/gender-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/gender/gender-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/timbre/timbre-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/timbre/timbre-discogs-effnet-1.json
https://essentia.upf.edu/models/classification-heads/tonal_atonal/tonal_atonal-discogs-effnet-1.pb
https://essentia.upf.edu/models/classification-heads/tonal_atonal/tonal_atonal-discogs-effnet-1.json

https://essentia.upf.edu/extractors/essentia-extractors-v2.1_beta5-356-g673b6a14-win-i686/essentia_streaming_key.exe

About Discogs-EffNet.
About Genre Rosamerica.
About Genre Tzanetakis.
About FMA Small.

I dismissed Genre Dortmund and Moods Mirex by looking at their accuracies. I tried the Jamendo models, I didn't find them very accurate. I suspect the International class in FMA Small is very broad.

Script

I have two files, one called Liste.py and the other Tags Essentia.py, which can be placed wherever you want, but in the same folder.

Liste.py

# Caractères spéciaux :
# [^\x00-\x7f]
# [^\x00-\x7f!(’°ßçáéíóúàèùâêîôûäëïöüãñœ)]
# Chemin avec 261 caractères trop long
# r".{255,}",
# r"",

liste_de_fichiers = [

# r"",

r"E:\Musique\Tommy Guerrero\2018 - Road to knowhere\01. El camino negro.flac",
r"E:\Musique\Tommy Guerrero\2018 - Road to knowhere\02. White sands.flac",
r"E:\Musique\Tommy Guerrero\2018 - Road to knowhere\03. Highway hustle.flac",
r"E:\Musique\Tommy Guerrero\2018 - Road to knowhere\04. Los padres.flac",
r"E:\Musique\Tommy Guerrero\2018 - Road to knowhere\05. Headin west.flac",
r"E:\Musique\Tommy Guerrero\2018 - Road to knowhere\06. Silent miles.flac",
r"E:\Musique\Tommy Guerrero\2018 - Road to knowhere\07. Heat in the streets.flac",
r"E:\Musique\Tommy Guerrero\2018 - Road to knowhere\08. Sidewalk soul.flac",
r"E:\Musique\Tommy Guerrero\2018 - Road to knowhere\09. Slow roll.flac",
r"E:\Musique\Tommy Guerrero\2018 - Road to knowhere\10. Postcard home.flac",
r"E:\Musique\Tommy Guerrero\2018 - Road to knowhere\11. A distant closeness.flac",
r"E:\Musique\Tommy Guerrero\2018 - Road to knowhere\12. Where water once was.flac",
r"E:\Musique\Tommy Guerrero\2018 - Road to knowhere\13. The endless road.flac",

    ]
Tags Essentia.py

import os

# 0 = all messages are logged (default behavior)
# 1 = INFO messages are not printed
# 2 = INFO and WARNING messages are not printed
# 3 = INFO, WARNING, and ERROR messages are not printed
# os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

import essentia

# essentia.log.infoActive = False
# essentia.log.warningActive = False
# essentia.log.errorActive = False

import sys
import time
import json
import re
import subprocess
import mutagen
from mutagen.flac import FLAC
from unidecode import unidecode
# import requests
import msvcrt
from tqdm import tqdm
from time import localtime, strftime
# from colorama import Fore, Style
from essentia.standard import MonoLoader, TensorflowPredictEffnetDiscogs, TensorflowPredictMusiCNN, TensorflowPredict2D, RhythmExtractor2013

from Liste import liste_de_fichiers as liste_externe


option_affichage_barres_d_avencement = True
# option_affichage_barres_d_avencement = False

# option_affichage_des_classes = True
option_affichage_des_classes = False


with open('E:/Programmes/Essentia/Models/genre_rosamerica-discogs-effnet-1.json', 'r') as json_file_rosa:
    metadata_rosa = json.load(json_file_rosa)

with open('E:/Programmes/Essentia/Models/genre_tzanetakis-discogs-effnet-1.json', 'r') as json_file_tzan:
    metadata_tzan = json.load(json_file_tzan)

with open('E:/Programmes/Essentia/Models/fma_small-discogs-effnet-1.json', 'r') as json_file_fma:
    metadata_fma = json.load(json_file_fma)

with open('E:/Programmes/Essentia/Models/genre_discogs400-discogs-effnet-1.json', 'r') as json_file_discogs:
    metadata_discogs = json.load(json_file_discogs)

with open('E:/Programmes/Essentia/Models/approachability_2c-discogs-effnet-1.json', 'r') as json_file_appro:
    metadata_appro = json.load(json_file_appro)

with open('E:/Programmes/Essentia/Models/engagement_2c-discogs-effnet-1.json', 'r') as json_file_enga:
    metadata_enga = json.load(json_file_enga)

with open('E:/Programmes/Essentia/Models/deam-msd-musicnn-2.json', 'r') as json_file_ar_val:
    metadata_ar_val = json.load(json_file_ar_val)

with open('E:/Programmes/Essentia/Models/danceability-discogs-effnet-1.json', 'r') as json_file_danc:
    metadata_danc = json.load(json_file_danc)

with open('E:/Programmes/Essentia/Models/mood_aggressive-discogs-effnet-1.json', 'r') as json_file_aggr:
    metadata_aggr = json.load(json_file_aggr)

with open('E:/Programmes/Essentia/Models/mood_happy-discogs-effnet-1.json', 'r') as json_file_happy:
    metadata_happy = json.load(json_file_happy)

with open('E:/Programmes/Essentia/Models/mood_party-discogs-effnet-1.json', 'r') as json_file_party:
    metadata_party = json.load(json_file_party)

with open('E:/Programmes/Essentia/Models/mood_relaxed-discogs-effnet-1.json', 'r') as json_file_relax:
    metadata_relax = json.load(json_file_relax)

with open('E:/Programmes/Essentia/Models/mood_sad-discogs-effnet-1.json', 'r') as json_file_sad:
    metadata_sad = json.load(json_file_sad)

with open('E:/Programmes/Essentia/Models/mood_acoustic-discogs-effnet-1.json', 'r') as json_file_acou:
    metadata_acou = json.load(json_file_acou)

with open('E:/Programmes/Essentia/Models/mood_electronic-discogs-effnet-1.json', 'r') as json_file_elec:
    metadata_elec = json.load(json_file_elec)

with open('E:/Programmes/Essentia/Models/voice_instrumental-discogs-effnet-1.json', 'r') as json_file_vo_inst:
    metadata_vo_inst = json.load(json_file_vo_inst)

with open('E:/Programmes/Essentia/Models/gender-discogs-effnet-1.json', 'r') as json_file_vo_gend:
    metadata_vo_gend = json.load(json_file_vo_gend)

with open('E:/Programmes/Essentia/Models/timbre-discogs-effnet-1.json', 'r') as json_file_timbre:
    metadata_timbre = json.load(json_file_timbre)

with open('E:/Programmes/Essentia/Models/tonal_atonal-discogs-effnet-1.json', 'r') as json_file_to_aton:
    metadata_to_aton = json.load(json_file_to_aton)



liste_interne = []
liste_de_dossiers = []
liste_de_fichiers_pour_compteur = []
compteur_fichiers_seuls = 0
compteur_fichiers_dans_les_dossiers = 0


for chemin in liste_externe:
    if chemin.lower().endswith(('.flac', '.mp3')):
        liste_interne.append(chemin)
        compteur_fichiers_seuls = compteur_fichiers_seuls + 1
    else:
        if not chemin.lower().endswith(('.flac', '.mp3', '.wma', '.m4a', '.ogg', '.mp4', '.aac', '.ape', '.wav', '.mpc', '.cue', '.log', '.txt', '.nfo', '.jpg', '.png')):
            liste_de_dossiers.append(chemin)
            for root, dirs, files in os.walk(chemin):
                for file in files:
                    if file.lower().endswith(('.flac', '.mp3')):
                        liste_interne.append(os.path.join(root, file))


total_liste_interne = len(liste_interne)
nombre_de_dossiers = len(liste_de_dossiers)
compteur_fichiers_dans_les_dossiers = total_liste_interne - compteur_fichiers_seuls


if nombre_de_dossiers > 0 :
    print()
    if nombre_de_dossiers == 1 :
        print(f'1 dossier avec {compteur_fichiers_dans_les_dossiers} fichiers :')
    else:
        if nombre_de_dossiers > 1 :
            print(f'{nombre_de_dossiers} dossiers avec {compteur_fichiers_dans_les_dossiers} fichiers :')
    print()
    for dossier in liste_de_dossiers:
        chemin_dossier_message = re.sub(r'.+\\(.+)\\(.+)\\(.+)$', r'\1  \  \2  \  \3', dossier)
        print(chemin_dossier_message)
        if ( liste_de_dossiers.index(dossier) + 1 ) < nombre_de_dossiers :
            print()

    if compteur_fichiers_seuls > 0 :
        print()
        if compteur_fichiers_seuls == 1 :
            print(f'et 1 fichier')
        else:
            if compteur_fichiers_seuls > 1 :
                print(f'et {compteur_fichiers_seuls} fichiers')

if ( nombre_de_dossiers == 0 ) and ( compteur_fichiers_seuls > 0 ) :
    print()
    if compteur_fichiers_seuls == 1 :
        print(f'1 fichier') 
    else:
        if compteur_fichiers_seuls > 1 :
            print(f'{compteur_fichiers_seuls} fichiers')


# print()
# print(strftime("%Y-%m-%d %H:%M:%S", localtime()))
print()


try:

    for fichier in liste_interne:

        if fichier.lower().endswith(('.flac', '.mp3')):

            index_du_fichier = liste_interne.index(fichier) + 1

            fichier = fichier.replace("\\","/")

            chemin_fichier_message = re.sub(r'.+/(.+)/(.+)/(.+)\.(flac|mp3)$', r'\1  \  \2  \  \3', fichier)
            extension = re.sub(r'.+\.(flac|mp3)$', r'\1', fichier)

            # heure = strftime("%H:%M:%S", localtime())

            if option_affichage_barres_d_avencement is False :
                print(f'{index_du_fichier} / {total_liste_interne}, {extension}')
                print(f'{chemin_fichier_message}')

            if option_affichage_barres_d_avencement is True :
                p_bar_total = tqdm(range(total_liste_interne), bar_format= ' {n_fmt:>5} / {total_fmt:<5} {bar:10}  {unit}', ascii = "░▒█", unit = f'{extension:<4}    {chemin_fichier_message}' )      # {heure}     {percentage:>3.0f} %
                p_bar_total.n = index_du_fichier
                p_bar_total.close()

                print()
                p_bar = tqdm(range(29), bar_format= '               {bar:30}     {unit}', ascii = "░▒█", unit = "MonoLoader", leave=False)
                p_bar.n = 0.5
                p_bar.refresh()


            audio = " "
            audio = MonoLoader(filename=fichier, sampleRate=16000, resampleQuality=0)()           # https://essentia.upf.edu/reference/std_MonoLoader.html

            if option_affichage_barres_d_avencement is True:
                p_bar.n = 4
                p_bar.unit = "Genre Rosamerica"
                p_bar.refresh()





            # === Genre Rosamerica ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Genre Rosamerica :")
                for classe in metadata_rosa['classes']:
                    print(classe)

            résultat_rosa = []

            embedding_model_rosa = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_rosa = embedding_model_rosa(audio)

            model_rosa = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/genre_rosamerica-discogs-effnet-1.pb", output="model/Softmax")
            predictions_rosa = model_rosa(embeddings_rosa)

            for label, probability in zip(metadata_rosa['classes'], predictions_rosa.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)
                label = label.replace("cla", "classic")
                label = label.replace("dan", "dance")
                label = label.replace("hip", "hip hop")
                label = label.replace("jaz", "jazz")
                label = label.replace("pop", "pop")
                label = label.replace("rhy", "rhythm and blues")
                label = label.replace("roc", "rock")
                label = label.replace("spe", "speech")
                résultat_rosa.append(probability)                
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')

            embedding_model_rosa = " "
            embeddings_rosa = " "
            model_rosa = " "
            predictions_rosa = " "

            if option_affichage_barres_d_avencement is True:
                p_bar.n = 5
                p_bar.unit = "Genre Tzanetakis"
                p_bar.refresh()





            # === Genre Tzanetakis ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Genre Tzanetakis :")
                for classe in metadata_tzan['classes']:
                    print(classe)

            résultat_tzan = []

            embedding_model_tzan = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_tzan = embedding_model_tzan(audio)

            model_tzan = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/genre_tzanetakis-discogs-effnet-1.pb", output="model/Softmax")
            predictions_tzan = model_tzan(embeddings_tzan)

            for label, probability in zip(metadata_tzan['classes'], predictions_tzan.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)
                label = label.replace("blu", "blues")
                label = label.replace("cla", "classic")
                label = label.replace("cou", "country")
                label = label.replace("dis", "disco")
                label = label.replace("hip", "hip hop")
                label = label.replace("jaz", "jazz")
                label = label.replace("met", "metal")
                label = label.replace("pop", "pop")
                label = label.replace("reg", "reggae")
                label = label.replace("roc", "rock")
                résultat_tzan.append(probability)                
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')

            embedding_model_tzan = " "
            embeddings_tzan = " "
            model_tzan = " "
            predictions_tzan = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 6
                p_bar.unit = "Genre FMA small"
                p_bar.refresh()





            # === Genre FMA small ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Genre FMA small :")
                for classe in metadata_fma['classes']:
                    print(classe)

            résultat_fma = []

            embedding_model_fma = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_fma = embedding_model_fma(audio)

            model_fma = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/fma_small-discogs-effnet-1.pb")
            predictions_fma = model_fma(embeddings_fma)

            for label, probability in zip(metadata_fma['classes'], predictions_fma.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)
                résultat_fma.append(probability)                
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')

            embedding_model_fma = " "
            embeddings_fma = " "
            model_fma = " "
            predictions_fma = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 7
                p_bar.unit = "Genre Discogs400"
                p_bar.refresh()





            # === Genre Discogs400 ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Genre Discogs400 :")
                for classe in metadata_discogs['classes']:
                    print(classe)

            liste_affichage_discogs = []
            largeur_colonne = " "
            résultat_ordre_discogs = []
            résultat_ordre_décr_discogs = []
            group_01_discogs, group_02_discogs, group_03_discogs, group_04_discogs, group_05_discogs, group_06_discogs, group_07_discogs, group_08_discogs, group_09_discogs, group_10_discogs, group_11_discogs, group_12_discogs, group_13_discogs, group_14_discogs, group_15_discogs, group_16_discogs, group_17_discogs, group_18_discogs = ([] for i in range(18))

            embedding_model_discogs = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_discogs = embedding_model_discogs(audio)

            model_discogs = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/genre_discogs400-discogs-effnet-1.pb", input="serving_default_model_Placeholder", output="PartitionedCall:0")
            predictions_discogs = model_discogs(embeddings_discogs)

            résultat_ordre_discogs = list(zip(metadata_discogs['classes'], predictions_discogs.mean(axis=0)))

            résultat_ordre_décr_discogs = sorted(résultat_ordre_discogs, key=lambda x: x[1], reverse=True)

            for label, probability in résultat_ordre_décr_discogs:
                probability = 100 * (probability)
                label = label.replace("Funk / Soul---", "Funk-Soul - ")
                label = label.replace(",", "")                      # "Folk, World, & Country"
                label = label.replace("/", "-")
                label = label.replace("---", " - ")
                label = unidecode(label)

                if 90   <= probability <= 100:
                    group_01_discogs.append(label)
                if 80   <= probability <= 100:
                    group_02_discogs.append(label)
                if 70   <= probability <= 100:
                    group_03_discogs.append(label)
                if 60   <= probability <= 100:
                    group_04_discogs.append(label)
                if 50   <= probability <= 100:
                    group_05_discogs.append(label)
                if 45   <= probability <= 100:
                    group_06_discogs.append(label)
                if 40   <= probability <= 100:
                    group_07_discogs.append(label)
                if 35   <= probability <= 100:
                    group_08_discogs.append(label)
                if 30   <= probability <= 100:
                    group_09_discogs.append(label)
                if 25   <= probability <= 100:
                    group_10_discogs.append(label)
                if 22.5 <= probability <= 100:
                    group_11_discogs.append(label)
                if 20   <= probability <= 100:
                    group_12_discogs.append(label)
                if 17.5 <= probability <= 100:
                    group_13_discogs.append(label)
                if 15   <= probability <= 100:
                    group_14_discogs.append(label)
                if 12.5 <= probability <= 100:
                    group_15_discogs.append(label)
                if 10   <= probability <= 100:
                    group_16_discogs.append(label)
                if 7.5  <= probability <= 100:
                    group_17_discogs.append(label)
                if 5    <= probability <= 100:
                    group_18_discogs.append(label)
                    # print(f'{label:<44} {probability:>5.1f} %')
                    liste_affichage_discogs.append((label, probability))

            if option_affichage_barres_d_avencement is False :
                largeur_colonne = max(len(ligne[0]) for ligne in liste_affichage_discogs) + 2      # padding
                for label, probability in liste_affichage_discogs:
                    print(f'{label:<{largeur_colonne}} {probability:>5.1f} %')

                if group_01_discogs:
                    print(f'Groupe 1   90 - 100%   {', '.join(group_01_discogs)}')
                if group_02_discogs:
                    print(f'Groupe 2   80 - 100%   {', '.join(group_02_discogs)}')
                if group_03_discogs:
                    print(f'Groupe 3   70 - 100%   {', '.join(group_03_discogs)}')
                if group_04_discogs:
                    print(f'Groupe 4   60 - 100%   {', '.join(group_04_discogs)}')
                if group_05_discogs:
                    print(f'Groupe 5   50 - 100%   {', '.join(group_05_discogs)}')
                if group_06_discogs:
                    print(f'Groupe 6   45 - 100%   {', '.join(group_06_discogs)}')
                if group_07_discogs:
                    print(f'Groupe 7   40 - 100%   {', '.join(group_07_discogs)}')
                if group_08_discogs:
                    print(f'Groupe 8   35 - 100%   {', '.join(group_08_discogs)}')
                if group_09_discogs:
                    print(f'Groupe 9   30 - 100%   {', '.join(group_09_discogs)}')
                if group_10_discogs:
                    print(f'Groupe 10  25 - 100%   {', '.join(group_10_discogs)}')
                if group_11_discogs:
                    print(f'Groupe 11  22.5-100%   {', '.join(group_11_discogs)}')
                if group_12_discogs:
                    print(f'Groupe 12  20 - 100%   {', '.join(group_12_discogs)}')
                if group_13_discogs:
                    print(f'Groupe 13  17.5-100%   {', '.join(group_13_discogs)}')
                if group_14_discogs:
                    print(f'Groupe 14  15 - 100%   {', '.join(group_14_discogs)}')
                if group_15_discogs:
                    print(f'Groupe 15  12.5-100%   {', '.join(group_15_discogs)}')
                if group_16_discogs:
                    print(f'Groupe 16  10 - 100%   {', '.join(group_16_discogs)}')
                if group_17_discogs:
                    print(f'Groupe 17   7.5-100%   {', '.join(group_17_discogs)}')
                if group_18_discogs:
                    print(f'Groupe 18   5 - 100%   {', '.join(group_18_discogs)}')

            embedding_model_discogs = " "
            embeddings_discogs = " "
            model_discogs = " "
            predictions_discogs = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 8
                p_bar.unit = "Approachability"
                p_bar.refresh()





            # === Approachability ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Approachability :")
                for classe in metadata_appro['classes']:
                    print(classe)

            résultat_appro = []

            embedding_model_appro = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_appro = embedding_model_appro(audio)

            model_appro = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/approachability_2c-discogs-effnet-1.pb", output="model/Softmax")
            predictions_appro = model_appro(embeddings_appro)

            for label, probability in zip(metadata_appro['classes'], predictions_appro.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)
                résultat_appro.append(probability)                
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')
                    

            embedding_model_appro = " "
            embeddings_appro = " "
            model_appro = " "
            predictions_appro = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 9
                p_bar.unit = "Engagement"
                p_bar.refresh()





            # === Engagement ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Engagement :")
                for classe in metadata_enga['classes']:
                    print(classe)

            résultat_enga = []

            embedding_model_enga = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_enga = embedding_model_enga(audio)

            model_enga = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/engagement_2c-discogs-effnet-1.pb", output="model/Softmax")
            predictions_enga = model_enga(embeddings_enga)

            for label, probability in zip(metadata_enga['classes'], predictions_enga.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)
                résultat_enga.append(probability)                
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')
                    

            embedding_model_enga = " "
            embeddings_enga = " "
            model_enga = " "
            predictions_enga = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 10
                p_bar.unit = "Arousal/valence DEAM"
                p_bar.refresh()





            # === Arousal/valence DEAM ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Arousal/valence DEAM :")
                for classe in metadata_ar_val['classes']:
                    print(classe)

            résultat_ar_val = []

            embedding_model_ar_val = TensorflowPredictMusiCNN(graphFilename="E:/Programmes/Essentia/Models/msd-musicnn-1.pb", output="model/dense/BiasAdd")
            embeddings_ar_val = embedding_model_ar_val(audio)

            model_ar_val = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/deam-msd-musicnn-2.pb", output="model/Identity")
            predictions_ar_val = model_ar_val(embeddings_ar_val)

            for label, probability in zip(metadata_ar_val['classes'], predictions_ar_val.mean(axis=0)):
                # probability = 100 * (probability)
                probability = "{:.2f}".format(probability)
                résultat_ar_val.append(probability)                
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<19} {probability:>5}')

            embedding_model_ar_val = " "
            embeddings_ar_val = " "
            model_ar_val = " "
            predictions_ar_val = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 11
                p_bar.unit = "Danceability"
                p_bar.refresh()





            # === Danceability ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Danceability :")
                for classe in metadata_danc['classes']:
                    print(classe)

            résultat_danc = []

            embedding_model_danc = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_danc = embedding_model_danc(audio)

            model_danc = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/danceability-discogs-effnet-1.pb", output="model/Softmax")
            predictions_danc = model_danc(embeddings_danc)

            for label, probability in zip(metadata_danc['classes'], predictions_danc.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)
                label = label.replace("_", " ")
                résultat_danc.append(probability)                
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')

            embedding_model_danc = " "
            embeddings_danc = " "
            model_danc = " "
            predictions_danc = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 12
                p_bar.unit = "Mood Aggressive"
                p_bar.refresh()





            # === Mood Aggressive ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Mood Aggressive :")
                for classe in metadata_aggr['classes']:
                    print(classe)

            résultat_aggr = []

            embedding_model_aggr = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_aggr = embedding_model_aggr(audio)

            model_aggr = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/mood_aggressive-discogs-effnet-1.pb", output="model/Softmax")
            predictions_aggr = model_aggr(embeddings_aggr)

            for label, probability in zip(metadata_aggr['classes'], predictions_aggr.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)
                label = label.replace("_", " ")
                résultat_aggr.append(probability)                
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')

            embedding_model_aggr = " "
            embeddings_aggr = " "
            model_aggr = " "
            predictions_aggr = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 13
                p_bar.unit = "Mood Happy"
                p_bar.refresh()





            # === Mood Happy ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Mood Happy :")
                for classe in metadata_happy['classes']:
                    print(classe)

            résultat_happy = []

            embedding_model_happy = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_happy = embedding_model_happy(audio)

            model_happy = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/mood_happy-discogs-effnet-1.pb", output="model/Softmax")
            predictions_happy = model_happy(embeddings_happy)

            for label, probability in zip(metadata_happy['classes'], predictions_happy.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)
                label = label.replace("_", " ")
                résultat_happy.append(probability)                
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')

            embedding_model_happy = " "
            embeddings_happy = " "
            model_happy = " "
            predictions_happy = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 14
                p_bar.unit = "Mood Party"
                p_bar.refresh()





            # === Mood Party ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Mood Party :")
                for classe in metadata_party['classes']:
                    print(classe)

            résultat_party = []

            embedding_model_party = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_party = embedding_model_party(audio)

            model_party = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/mood_party-discogs-effnet-1.pb", output="model/Softmax")
            predictions_party = model_party(embeddings_party)

            for label, probability in zip(metadata_party['classes'], predictions_party.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)
                label = label.replace("_", " ")
                résultat_party.append(probability)                
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')

            embedding_model_party = " "
            embeddings_party = " "
            model_party = " "
            predictions_party = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 15
                p_bar.unit = "Mood Relaxed"
                p_bar.refresh()





            # === Mood Relaxed ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Mood Relaxed :")
                for classe in metadata_relax['classes']:
                    print(classe)

            résultat_relax = []

            embedding_model_relax = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_relax = embedding_model_relax(audio)

            model_relax = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/mood_relaxed-discogs-effnet-1.pb", output="model/Softmax")
            predictions_relax = model_relax(embeddings_relax)

            for label, probability in zip(metadata_relax['classes'], predictions_relax.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)
                label = label.replace("_", " ")
                résultat_relax.append(probability)                
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')

            embedding_model_relax = " "
            embeddings_relax = " "
            model_relax = " "
            predictions_relax = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 16
                p_bar.unit = "Mood Sad"
                p_bar.refresh()





            # === Mood Sad ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Mood Sad :")
                for classe in metadata_sad['classes']:
                    print(classe)

            résultat_sad = []

            embedding_model_sad = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_sad = embedding_model_sad(audio)

            model_sad = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/mood_sad-discogs-effnet-1.pb", output="model/Softmax")
            predictions_sad = model_sad(embeddings_sad)

            for label, probability in zip(metadata_sad['classes'], predictions_sad.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)
                label = label.replace("_", " ")
                résultat_sad.append(probability)                
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')

            embedding_model_sad = " "
            embeddings_sad = " "
            model_sad = " "
            predictions_sad = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 17
                p_bar.unit = "Mood Acoustic"
                p_bar.refresh()





            # === Mood Acoustic ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Mood Acoustic :")
                for classe in metadata_acou['classes']:
                    print(classe)

            résultat_acou = []

            embedding_model_acou = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_acou = embedding_model_acou(audio)

            model_acou = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/mood_acoustic-discogs-effnet-1.pb", output="model/Softmax")
            predictions_acou = model_acou(embeddings_acou)

            for label, probability in zip(metadata_acou['classes'], predictions_acou.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)
                label = label.replace("_", " ")
                résultat_acou.append(probability)                
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')

            embedding_model_acou = " "
            embeddings_acou = " "
            model_acou = " "
            predictions_acou = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 18
                p_bar.unit = "Mood Electronic"
                p_bar.refresh()





            # === Mood Electronic ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Mood Electronic :")
                for classe in metadata_elec['classes']:
                    print(classe)

            résultat_elec = []

            embedding_model_elec = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_elec = embedding_model_elec(audio)

            model_elec = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/mood_electronic-discogs-effnet-1.pb", output="model/Softmax")
            predictions_elec = model_elec(embeddings_elec)

            for label, probability in zip(metadata_elec['classes'], predictions_elec.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)
                label = label.replace("_", " ")
                résultat_elec.append(probability)                
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')

            embedding_model_elec = " "
            embeddings_elec = " "
            model_elec = " "
            predictions_elec = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 19
                p_bar.unit = "Voice/instrumental"
                p_bar.refresh()





            # === Voice/instrumental ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Voice/instrumental :")
                for classe in metadata_vo_inst['classes']:
                    print(classe)

            résultat_vo_inst = []

            embedding_model_vo_inst = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_vo_inst = embedding_model_vo_inst(audio)

            model_vo_inst = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/voice_instrumental-discogs-effnet-1.pb", output="model/Softmax")
            predictions_vo_inst = model_vo_inst(embeddings_vo_inst)

            for label, probability in zip(metadata_vo_inst['classes'], predictions_vo_inst.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)                
                résultat_vo_inst.append(probability)
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')

            embedding_model_vo_inst = " "
            embeddings_vo_inst = " "
            model_vo_inst = " "
            predictions_vo_inst = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 20
                p_bar.unit = "Voice gender"
                p_bar.refresh()





            # === Voice gender ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Voice gender :")
                for classe in metadata_vo_gend['classes']:
                    print(classe)

            résultat_vo_gend = []

            embedding_model_vo_gend = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_vo_gend = embedding_model_vo_gend(audio)

            model_vo_gend = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/gender-discogs-effnet-1.pb", output="model/Softmax")
            predictions_vo_gend = model_vo_gend(embeddings_vo_gend)

            for label, probability in zip(metadata_vo_gend['classes'], predictions_vo_gend.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)                
                résultat_vo_gend.append(probability)
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')
                

            embedding_model_vo_gend = " "
            embeddings_vo_gend = " "
            model_vo_gend = " "
            predictions_vo_gend = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 21
                p_bar.unit = "Timbre"
                p_bar.refresh()





            # === Timbre ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Timbre :")
                for classe in metadata_timbre['classes']:
                    print(classe)

            résultat_timbre = []

            embedding_model_timbre = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_timbre = embedding_model_timbre(audio)

            model_timbre = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/timbre-discogs-effnet-1.pb", output="model/Softmax")
            predictions_timbre = model_timbre(embeddings_timbre)

            for label, probability in zip(metadata_timbre['classes'], predictions_timbre.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)
                résultat_timbre.append(probability)
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')

                

            embedding_model_timbre = " "
            embeddings_timbre = " "
            model_timbre = " "
            predictions_timbre = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 22
                p_bar.unit = "Tonal/atonal"
                p_bar.refresh()





            # === Tonal/atonal ===

            if option_affichage_des_classes is True :
                print()
                print("Classes Tonal/atonal :")
                for classe in metadata_to_aton['classes']:
                    print(classe)

            résultat_to_aton = []

            embedding_model_to_aton = TensorflowPredictEffnetDiscogs(graphFilename="E:/Programmes/Essentia/Models/discogs-effnet-bs64-1.pb", output="PartitionedCall:1")
            embeddings_to_aton = embedding_model_to_aton(audio)

            model_to_aton = TensorflowPredict2D(graphFilename="E:/Programmes/Essentia/Models/tonal_atonal-discogs-effnet-1.pb", output="model/Softmax")
            predictions_to_aton = model_to_aton(embeddings_to_aton)

            for label, probability in zip(metadata_to_aton['classes'], predictions_to_aton.mean(axis=0)):
                probability = 100 * (probability)
                probability = "{:.1f}".format(probability)
                résultat_to_aton.append(probability)
                if option_affichage_barres_d_avencement is False :
                    print(f'{label:<18} {probability:>5} %')

            embedding_model_to_aton = " "
            embeddings_to_aton = " "
            model_to_aton = " "
            predictions_to_aton = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 23
                p_bar.unit = "BPM"
                p_bar.refresh()




            audio = " "



            # === BPM ===

            bpm = " "
            beats = " "

            audio_bpm = MonoLoader(filename=fichier)()
            
            rhythm_extractor = RhythmExtractor2013(method="multifeature")          # https://essentia.upf.edu/tutorial_rhythm_beatdetection.html
            bpm, beats, _, _, _ = rhythm_extractor(audio_bpm)

            bpm = "{:.1f}".format(bpm)

            if option_affichage_barres_d_avencement is False :
                print(f'{"bpm":<17} {bpm:>6}')
            
            audio_bpm = " "

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 25
                p_bar.unit = "Key"
                p_bar.refresh()





            # === Key ===

            sortie_streaming_key = " "
            note = " "

            sortie_streaming_key = subprocess.check_output(["E:/Programmes/Essentia/Extracteurs/essentia_streaming_key.exe", fichier, "."], universal_newlines=True)

            note = re.search(r"key:\s+(\w.+)$", sortie_streaming_key).group(1)
            note = note.replace("major", "")          #  note.group()   note.strip()
            note = note.replace("minor", "m")
            note = note.replace(" ", "")

            if option_affichage_barres_d_avencement is False :
                print(f'{"key":<18} {note:>5}')

            if option_affichage_barres_d_avencement is True :
                p_bar.n = 28
                p_bar.unit = "Écrire tag"
                p_bar.refresh()







            time.sleep(1)

            tag_audio = " "

            if fichier.lower().endswith('.flac'):

                tag_audio = FLAC(fichier)

                tag_audio["ES:GENRE_ROSAMERICA"]     = résultat_rosa           # Genre Rosamerica
                tag_audio["ES:GENRE_TZANETAKIS"]     = résultat_tzan           # Genre Tzanetakis
                tag_audio["ES:GENRE_FMA_SMALL"]      = résultat_fma            # Genre FMA small
                tag_audio["ES:DISCOGS_G01"]          = group_01_discogs        # Discogs 90 - 100 %
                tag_audio["ES:DISCOGS_G02"]          = group_02_discogs        # Discogs 80 - 100 %
                tag_audio["ES:DISCOGS_G03"]          = group_03_discogs        # Discogs 70 - 100 %
                tag_audio["ES:DISCOGS_G04"]          = group_04_discogs        # Discogs 60 - 100 %
                tag_audio["ES:DISCOGS_G05"]          = group_05_discogs        # Discogs 50 - 100 %
                tag_audio["ES:DISCOGS_G06"]          = group_06_discogs        # Discogs 45 - 100 %
                tag_audio["ES:DISCOGS_G07"]          = group_07_discogs        # Discogs 40 - 100 %
                tag_audio["ES:DISCOGS_G08"]          = group_08_discogs        # Discogs 35 - 100 %
                tag_audio["ES:DISCOGS_G09"]          = group_09_discogs        # Discogs 30 - 100 %
                tag_audio["ES:DISCOGS_G10"]          = group_10_discogs        # Discogs 25 - 100 %
                tag_audio["ES:DISCOGS_G11"]          = group_11_discogs        # Discogs 22.5-100 %
                tag_audio["ES:DISCOGS_G12"]          = group_12_discogs        # Discogs 20 - 100 %
                tag_audio["ES:DISCOGS_G13"]          = group_13_discogs        # Discogs 17.5-100 %
                tag_audio["ES:DISCOGS_G14"]          = group_14_discogs        # Discogs 15 - 100 %
                tag_audio["ES:DISCOGS_G15"]          = group_15_discogs        # Discogs 12.5-100 %
                tag_audio["ES:DISCOGS_G16"]          = group_16_discogs        # Discogs 10 - 100 %
                tag_audio["ES:DISCOGS_G17"]          = group_17_discogs        # Discogs  7.5-100 %
                tag_audio["ES:DISCOGS_G18"]          = group_18_discogs        # Discogs  5 - 100 %
                tag_audio["ES:APPROACHABILITY"]      = résultat_appro          # Approachability
                tag_audio["ES:ENGAGEMENT"]           = résultat_enga           # Engagement
                tag_audio["ES:AROUSAL_VALENCE_DEAM"] = résultat_ar_val         # Arousal/valence DEAM
                tag_audio["ES:DANCEABILITY"]         = résultat_danc           # Danceability
                tag_audio["ES:MOOD_AGGRESSIVE"]      = résultat_aggr           # Mood Aggressive
                tag_audio["ES:MOOD_HAPPY"]           = résultat_happy          # Mood Happy
                tag_audio["ES:MOOD_PARTY"]           = résultat_party          # Mood Party
                tag_audio["ES:MOOD_RELAXED"]         = résultat_relax          # Mood Relaxed
                tag_audio["ES:MOOD_SAD"]             = résultat_sad            # Mood Sad
                tag_audio["ES:MOOD_ACOUSTIC"]        = résultat_acou           # Mood Acoustic
                tag_audio["ES:MOOD_ELECTRONIC"]      = résultat_elec           # Mood Electronic
                tag_audio["ES:VOICE_INSTRUMENTAL"]   = résultat_vo_inst        # Voice/instrumental
                tag_audio["ES:VOICE_GENDER"]         = résultat_vo_gend        # Voice gender
                tag_audio["ES:TIMBRE"]               = résultat_timbre         # Timbre
                tag_audio["ES:TONAL_ATONAL"]         = résultat_to_aton        # Tonal/atonal
                tag_audio["ES:KEY"]                  = note
                tag_audio["ES:BPM"]                  = bpm

                tag_audio.pprint()
                tag_audio.save()


            if fichier.lower().endswith('.mp3'):
                import mutagen.mp3
                from mutagen import id3
                from mutagen.id3 import ID3

                tag_audio = ID3(fichier)

                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:GENRE_ROSAMERICA",     text = résultat_rosa ))        # Genre Rosamerica
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:GENRE_TZANETAKIS",     text = résultat_tzan ))        # Genre Tzanetakis
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:GENRE_FMA_SMALL",      text = résultat_fma ))         # Genre FMA small
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G01",          text = group_01_discogs ))     # Discogs 90 - 100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G02",          text = group_02_discogs ))     # Discogs 80 - 100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G03",          text = group_03_discogs ))     # Discogs 70 - 100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G04",          text = group_04_discogs ))     # Discogs 60 - 100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G05",          text = group_05_discogs ))     # Discogs 50 - 100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G06",          text = group_06_discogs ))     # Discogs 45 - 100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G07",          text = group_07_discogs ))     # Discogs 40 - 100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G08",          text = group_08_discogs ))     # Discogs 35 - 100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G09",          text = group_09_discogs ))     # Discogs 30 - 100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G10",          text = group_10_discogs ))     # Discogs 25 - 100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G11",          text = group_11_discogs ))     # Discogs 22.5-100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G12",          text = group_12_discogs ))     # Discogs 20 - 100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G13",          text = group_13_discogs ))     # Discogs 17.5-100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G14",          text = group_14_discogs ))     # Discogs 15 - 100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G15",          text = group_15_discogs ))     # Discogs 12.5-100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G16",          text = group_16_discogs ))     # Discogs 10 - 100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G17",          text = group_17_discogs ))     # Discogs  7.5-100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DISCOGS_G18",          text = group_18_discogs ))     # Discogs  5 - 100 %
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:APPROACHABILITY",      text = résultat_appro ))       # Approachability
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:ENGAGEMENT",           text = résultat_enga ))        # Engagement
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:AROUSAL_VALENCE_DEAM", text = résultat_ar_val ))      # Arousal/valence DEAM
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:DANCEABILITY",         text = résultat_danc ))        # Danceability
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:MOOD_AGGRESSIVE",      text = résultat_aggr ))        # Mood Aggressive
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:MOOD_HAPPY",           text = résultat_happy ))       # Mood Happy
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:MOOD_PARTY",           text = résultat_party ))       # Mood Party
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:MOOD_RELAXED",         text = résultat_relax ))       # Mood Relaxed
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:MOOD_SAD",             text = résultat_sad ))         # Mood Sad
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:MOOD_ACOUSTIC",        text = résultat_acou ))        # Mood Acoustic
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:MOOD_ELECTRONIC",      text = résultat_elec ))        # Mood Electronic
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:VOICE_INSTRUMENTAL",   text = résultat_vo_inst ))     # Voice/instrumental
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:VOICE_GENDER",         text = résultat_vo_gend ))     # Voice gender
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:TIMBRE",               text = résultat_timbre ))      # Timbre
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:TONAL_ATONAL",         text = résultat_to_aton ))     # Tonal/atonal
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:KEY",                  text = note ))
                tag_audio.add(id3.TXXX(encoding = 3, desc = "ES:BPM",                  text = bpm ))

                tag_audio.pprint()
                tag_audio.save()


            if option_affichage_barres_d_avencement is True :
                p_bar.n = 29
                p_bar.unit = "Presser une touche pour interrompre"        # ou attendre 2.5 secondes
                # p_bar.unit = Style.BRIGHT + Fore.BLUE + "Presser une touche pour interrompre"
                p_bar.colour = "blue"
                p_bar.refresh()

            if option_affichage_barres_d_avencement is False :
                print("Presser une touche pour interrompre")
                print()

            timeout = 2.5
            inp = None
            startTime = time.time()

            while True:
                if msvcrt.kbhit():
                    if option_affichage_barres_d_avencement is True :                                      
                        p_bar.unit = " "
                        p_bar.refresh()
                        p_bar.close()
                    inp = msvcrt.getch()
                    # touche = str(inp)
                    # touche = touche.replace("b'","'").replace("'","").upper()
                    # touche = touche.replace(" ","Espace").replace("\\R","Entrée").replace("\\X1","Echap")
                    # print()
                    # print(f'Touche pressée: {touche}')
                    print()
                    print(f'Interruption')
                    # print()
                    os.system("py -m pyclean .")
                    print()
                    print(f'Dernier fichier fait :')     # .{extension}
                    print()
                    print(f'{chemin_fichier_message}')
                    print()
                    print()
                    print()
                    sys.exit()
                    # break
                elif time.time() - startTime > timeout:
                    if option_affichage_barres_d_avencement is True :
                        p_bar.unit = " "
                        p_bar.refresh()
                        p_bar.close()
                    break


    # print()
    # print(strftime("%Y-%m-%d %H:%M:%S", localtime()))
    
    print( )
    # os.system("py -m pyclean -v .")
    os.system("py -m pyclean .")

    print( )
    print("Fin du script")
    print( )


# except:

except KeyboardInterrupt:
    print()
    print()
    print(f'Interruption clavier')
    # print()
    os.system("py -m pyclean .")
    print()
    print(f'Fichier en cours, non fait :')     # .{extension}
    print()
    print(f'{chemin_fichier_message}')
    print()
    print()
    print()

except Exception:
    # requests.post("https://ntfy.hostux.net/essentia_ng5At2ds",
    #     headers = { "Title"    : "Erreur script Essentia",
    #                 "Priority" : "4",
    #                 "Tags"     : "snake, triangular_flag_on_post" },
    #     data    = f"{index_du_fichier} / {total_liste_interne}\n{re.sub(r'  \\  ', '\n', chemin_fichier_message)}".encode(encoding='utf-8'))
    print()
    print()
    print(f'Interruption exceptionnelle')
    os.system("py -m pyclean .")
    print()
    print(f'Fichier en cours, non fait :')
    print()
    print(f'{chemin_fichier_message}')
    print()
    print()
    print()

The same code in this gist, to see the line numbers.

Replace all paths E:/Programmes/Essentia/Models/ in the script with the path to the folder where the .pb and .json files are located. Replace backslashes \ with slashes / in your path.
There is also the path to the Key extractor, line 1060.

I've never done Python before, so this script can probably be improved.

Python packages

  • mutagen: to write tags to audio files (PyPI)

    py -m pip install mutagen
    
  • pyclean (optional): to clean up __pycache__ folders. It's only cosmetic.
    If you don't use pyclean, lines 1212, 1235, 1249 and 1267 need to be commented out.

    py -m pip install pyclean
    
  • requests (optional): to send a notification to a cell phone when an error occurs

    py -m pip install requests
    
  • tqdm: to display progress bars

    py -m pip install tqdm
    
  • Unidecode: to replace special or accented characters. I don't remember exactly why I did this, maybe it's not necessary.

    What Unidecode does

    Discogs400 labels:

    before after
    Electronic---Musique Concrète Electronic---Musique Concrete
    Folk, World, & Country---Laïkó Folk, World, & Country---Laiko
    Folk, World, & Country---Raï Folk, World, & Country---Rai
    Folk, World, & Country---Séga Folk, World, & Country---Sega
    Folk, World, & Country---Éntekhno Folk, World, & Country---Entekhno
    Latin---Baião Latin---Baiao
    Latin---Forró Latin---Forro
    Latin---Guaguancó Latin---Guaguanco
    Latin---Norteño Latin---Norteno
    Pop---Kayōkyoku Pop---Kayokyoku
    Rock---Yé-Yé Rock---Ye-Ye

    If you don't use Unidecode, lines 22 and 361 need to be commented out. And see if it works.

    py -m pip install Unidecode
    

Settings

Search-by-Distance-SMP

Open the SMP panel properties, look for the property sbd0.Tags used for scoring (near the end) and replace the value with the following on a single line.
(to open panel properties with DUI: Shift + Win + right-click on the SMP panel, or Enable layout editing mode, then right-click on the SMP panel)

Custom tags settings, formatted

{

"genre"                 :{"weight": 0,   "tf": ["GENRE"],                            "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["string", "multiple", "graph"]},
"style"                 :{"weight": 0,   "tf": ["STYLE"],                            "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["string", "multiple", "graph"]},
"dynGenre"              :{"weight": 15,  "tf": [],                                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["number", "single", "virtual", "absRange"],                "range": 1  },
"mood"                  :{"weight": 0,   "tf": ["MOOD"],                             "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["string", "multiple", "combinations"],                     "combs": 6  },
"key"                   :{"weight": 0,   "tf": ["KEY"],                              "baseScore": 0, "scoringDistribution": "LOGARITHMIC", "type": ["string", "single", "keyMix", "keyRange"],                 "range": 8  },
"bpm"                   :{"weight": 0,   "tf": ["BPM"],                              "baseScore": 0, "scoringDistribution": "NORMAL",      "type": ["number", "single", "percentRange"],                       "range": 50 },
"date"                  :{"weight": 0,   "tf": ["$year(%DATE%)"],                    "baseScore": 0, "scoringDistribution": "NORMAL",      "type": ["number", "single", "absRange"],                           "range": 500},
"composer"              :{"weight": 0,   "tf": ["COMPOSER"],                         "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["string", "multiple"]},
"artistRegion"          :{"weight": 0,   "tf": ["LOCALE LAST.FM"],                   "baseScore": 0, "scoringDistribution": "LOGISTIC",    "type": ["string", "single", "virtual", "absRange", "tfRemap"],     "range": 5  },
"genreStyleRegion"      :{"weight": 0,   "tf": [],                                   "baseScore": 0, "scoringDistribution": "LOGISTIC",    "type": ["string", "single", "virtual", "absRange"],                "range": 5  },
"related"               :{"weight": 0,   "tf": ["RELATED"],                          "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["string", "multiple", "virtual", "tfRemap", "bNegative"]},
"unrelated"             :{"weight": 0,   "tf": ["UNRELATED"],                        "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["string", "multiple", "virtual", "tfRemap", "bNegative"]},

"Key es"                :{"weight": 1,   "tf": ["ES:KEY"],                           "baseScore": 0, "scoringDistribution": "LOGARITHMIC", "type": ["string", "single", "keyMix", "keyRange"],                 "range": 8  },
"Bpm es"                :{"weight": 1,   "tf": ["ES:BPM"],                           "baseScore": 0, "scoringDistribution": "NORMAL",      "type": ["number", "single", "percentRange"],                       "range": 150},

"Rosa Classic"          :{"weight": 4,   "tf": ["$meta(ES:GENRE_ROSAMERICA,0)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Rosa Dance"            :{"weight": 4,   "tf": ["$meta(ES:GENRE_ROSAMERICA,1)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Rosa Hip hop"          :{"weight": 4,   "tf": ["$meta(ES:GENRE_ROSAMERICA,2)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Rosa Jazz"             :{"weight": 4,   "tf": ["$meta(ES:GENRE_ROSAMERICA,3)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Rosa Pop"              :{"weight": 4,   "tf": ["$meta(ES:GENRE_ROSAMERICA,4)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Rosa Rhythm and blues" :{"weight": 4,   "tf": ["$meta(ES:GENRE_ROSAMERICA,5)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Rosa Rock"             :{"weight": 4,   "tf": ["$meta(ES:GENRE_ROSAMERICA,6)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Rosa Speech"           :{"weight": 4,   "tf": ["$meta(ES:GENRE_ROSAMERICA,7)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Tzan Blues"            :{"weight": 4,   "tf": ["$meta(ES:GENRE_TZANETAKIS,0)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Tzan Classic"          :{"weight": 4,   "tf": ["$meta(ES:GENRE_TZANETAKIS,1)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Tzan Country"          :{"weight": 4,   "tf": ["$meta(ES:GENRE_TZANETAKIS,2)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Tzan Disco"            :{"weight": 4,   "tf": ["$meta(ES:GENRE_TZANETAKIS,3)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Tzan Hip hop"          :{"weight": 4,   "tf": ["$meta(ES:GENRE_TZANETAKIS,4)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Tzan Jazz"             :{"weight": 4,   "tf": ["$meta(ES:GENRE_TZANETAKIS,5)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Tzan Metal"            :{"weight": 4,   "tf": ["$meta(ES:GENRE_TZANETAKIS,6)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Tzan Pop"              :{"weight": 4,   "tf": ["$meta(ES:GENRE_TZANETAKIS,7)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Tzan Reggae"           :{"weight": 4,   "tf": ["$meta(ES:GENRE_TZANETAKIS,8)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Tzan Rock"             :{"weight": 4,   "tf": ["$meta(ES:GENRE_TZANETAKIS,9)"],     "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Fma Electronic"        :{"weight": 4,   "tf": ["$meta(ES:GENRE_FMA_SMALL,0)"],      "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Fma Experimental"      :{"weight": 4,   "tf": ["$meta(ES:GENRE_FMA_SMALL,1)"],      "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Fma Folk"              :{"weight": 4,   "tf": ["$meta(ES:GENRE_FMA_SMALL,2)"],      "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Fma Hip-hop"           :{"weight": 4,   "tf": ["$meta(ES:GENRE_FMA_SMALL,3)"],      "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Fma Instrumental"      :{"weight": 4,   "tf": ["$meta(ES:GENRE_FMA_SMALL,4)"],      "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Fma International"     :{"weight": 4,   "tf": ["$meta(ES:GENRE_FMA_SMALL,5)"],      "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Fma Pop"               :{"weight": 4,   "tf": ["$meta(ES:GENRE_FMA_SMALL,6)"],      "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Fma Rock"              :{"weight": 4,   "tf": ["$meta(ES:GENRE_FMA_SMALL,7)"],      "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},

"Discogs 90-100 %"      :{"weight": 4,   "tf": ["ES:DISCOGS_G01"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 80-100 %"      :{"weight": 4,   "tf": ["ES:DISCOGS_G02"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 70-100 %"      :{"weight": 4,   "tf": ["ES:DISCOGS_G03"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 60-100 %"      :{"weight": 4,   "tf": ["ES:DISCOGS_G04"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 50-100 %"      :{"weight": 4,   "tf": ["ES:DISCOGS_G05"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 45-100 %"      :{"weight": 2,   "tf": ["ES:DISCOGS_G06"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 40-100 %"      :{"weight": 2,   "tf": ["ES:DISCOGS_G07"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 35-100 %"      :{"weight": 2,   "tf": ["ES:DISCOGS_G08"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 30-100 %"      :{"weight": 2,   "tf": ["ES:DISCOGS_G09"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 25-100 %"      :{"weight": 2,   "tf": ["ES:DISCOGS_G10"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 22.5-100 %"    :{"weight": 1,   "tf": ["ES:DISCOGS_G11"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 20-100 %"      :{"weight": 1,   "tf": ["ES:DISCOGS_G12"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 17.5-100 %"    :{"weight": 1,   "tf": ["ES:DISCOGS_G13"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 15-100 %"      :{"weight": 1,   "tf": ["ES:DISCOGS_G14"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 12.5-100 %"    :{"weight": 1,   "tf": ["ES:DISCOGS_G15"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 10-100 %"      :{"weight": 1,   "tf": ["ES:DISCOGS_G16"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 7.5-100 %"     :{"weight": 1,   "tf": ["ES:DISCOGS_G17"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},
"Discogs 5-100 %"       :{"weight": 1,   "tf": ["ES:DISCOGS_G18"],                   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["multiple","string"]},

"Not approachable"      :{"weight": 4,   "tf": ["$meta(ES:APPROACHABILITY,0)"],      "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Approachable"          :{"weight": 4,   "tf": ["$meta(ES:APPROACHABILITY,1)"],      "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Not engaging"          :{"weight": 4,   "tf": ["$meta(ES:ENGAGEMENT,0)"],           "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Engaging"              :{"weight": 4,   "tf": ["$meta(ES:ENGAGEMENT,1)"],           "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Valence"               :{"weight": 4,   "tf": ["$meta(ES:AROUSAL_VALENCE_DEAM,0)"], "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":9  },
"Arousal"               :{"weight": 4,   "tf": ["$meta(ES:AROUSAL_VALENCE_DEAM,1)"], "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":9  },
"Danceable"             :{"weight": 4,   "tf": ["$meta(ES:DANCEABILITY,0)"],         "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Not danceable"         :{"weight": 4,   "tf": ["$meta(ES:DANCEABILITY,1)"],         "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Aggressive"            :{"weight": 4,   "tf": ["$meta(ES:MOOD_AGGRESSIVE,0)"],      "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Not aggressive"        :{"weight": 4,   "tf": ["$meta(ES:MOOD_AGGRESSIVE,1)"],      "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Happy"                 :{"weight": 4,   "tf": ["$meta(ES:MOOD_HAPPY,0)"],           "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Non happy"             :{"weight": 4,   "tf": ["$meta(ES:MOOD_HAPPY,1)"],           "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Non party"             :{"weight": 4,   "tf": ["$meta(ES:MOOD_PARTY,0)"],           "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Party"                 :{"weight": 4,   "tf": ["$meta(ES:MOOD_PARTY,1)"],           "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Non relaxed"           :{"weight": 4,   "tf": ["$meta(ES:MOOD_RELAXED,0)"],         "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Relaxed"               :{"weight": 4,   "tf": ["$meta(ES:MOOD_RELAXED,1)"],         "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Non sad"               :{"weight": 4,   "tf": ["$meta(ES:MOOD_SAD,0)"],             "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Sad"                   :{"weight": 4,   "tf": ["$meta(ES:MOOD_SAD,1)"],             "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Acoustic"              :{"weight": 4,   "tf": ["$meta(ES:MOOD_ACOUSTIC,0)"],        "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Non acoustic"          :{"weight": 4,   "tf": ["$meta(ES:MOOD_ACOUSTIC,1)"],        "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Electronic"            :{"weight": 4,   "tf": ["$meta(ES:MOOD_ELECTRONIC,0)"],      "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Non electronic"        :{"weight": 4,   "tf": ["$meta(ES:MOOD_ELECTRONIC,1)"],      "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Instrumental"          :{"weight": 4,   "tf": ["$meta(ES:VOICE_INSTRUMENTAL,0)"],   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Voice"                 :{"weight": 4,   "tf": ["$meta(ES:VOICE_INSTRUMENTAL,1)"],   "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Female"                :{"weight": 4,   "tf": ["$meta(ES:VOICE_GENDER,0)"],         "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Male"                  :{"weight": 4,   "tf": ["$meta(ES:VOICE_GENDER,1)"],         "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Bright"                :{"weight": 3,   "tf": ["$meta(ES:TIMBRE,0)"],               "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Dark"                  :{"weight": 3,   "tf": ["$meta(ES:TIMBRE,1)"],               "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Tonal"                 :{"weight": 4,   "tf": ["$meta(ES:TONAL_ATONAL,0)"],         "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100},
"Atonal"                :{"weight": 4,   "tf": ["$meta(ES:TONAL_ATONAL,1)"],         "baseScore": 0, "scoringDistribution": "LINEAR",      "type": ["single","number","absRange"],     "range":100}

}
Custom tags settings, on one line

{"genre":{"weight":0,"tf":["GENRE"],"baseScore":0,"scoringDistribution":"LINEAR","type":["string","multiple","graph"]},"style":{"weight":0,"tf":["STYLE"],"baseScore":0,"scoringDistribution":"LINEAR","type":["string","multiple","graph"]},"dynGenre":{"weight":15,"tf":[],"baseScore":0,"scoringDistribution":"LINEAR","type":["number","single","virtual","absRange"],"range":1},"mood":{"weight":0,"tf":["MOOD"],"baseScore":0,"scoringDistribution":"LINEAR","type":["string","multiple","combinations"],"combs":6},"key":{"weight":0,"tf":["KEY"],"baseScore":0,"scoringDistribution":"LOGARITHMIC","type":["string","single","keyMix","keyRange"],"range":8},"bpm":{"weight":0,"tf":["BPM"],"baseScore":0,"scoringDistribution":"NORMAL","type":["number","single","percentRange"],"range":50},"date":{"weight":0,"tf":["$year(%DATE%)"],"baseScore":0,"scoringDistribution":"NORMAL","type":["number","single","absRange"],"range":500},"composer":{"weight":0,"tf":["COMPOSER"],"baseScore":0,"scoringDistribution":"LINEAR","type":["string","multiple"]},"artistRegion":{"weight":0,"tf":["LOCALE LAST.FM"],"baseScore":0,"scoringDistribution":"LOGISTIC","type":["string","single","virtual","absRange","tfRemap"],"range":5},"genreStyleRegion":{"weight":0,"tf":[],"baseScore":0,"scoringDistribution":"LOGISTIC","type":["string","single","virtual","absRange"],"range":5},"related":{"weight":0,"tf":["RELATED"],"baseScore":0,"scoringDistribution":"LINEAR","type":["string","multiple","virtual","tfRemap","bNegative"]},"unrelated":{"weight":0,"tf":["UNRELATED"],"baseScore":0,"scoringDistribution":"LINEAR","type":["string","multiple","virtual","tfRemap","bNegative"]},"Key es":{"weight":1,"tf":["ES:KEY"],"baseScore":0,"scoringDistribution":"LOGARITHMIC","type":["string","single","keyMix","keyRange"],"range":8},"Bpm es":{"weight":1,"tf":["ES:BPM"],"baseScore":0,"scoringDistribution":"NORMAL","type":["number","single","percentRange"],"range":150},"Rosa Classic":{"weight":4,"tf":["$meta(ES:GENRE_ROSAMERICA,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Rosa Dance":{"weight":4,"tf":["$meta(ES:GENRE_ROSAMERICA,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Rosa Hip hop":{"weight":4,"tf":["$meta(ES:GENRE_ROSAMERICA,2)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Rosa Jazz":{"weight":4,"tf":["$meta(ES:GENRE_ROSAMERICA,3)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Rosa Pop":{"weight":4,"tf":["$meta(ES:GENRE_ROSAMERICA,4)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Rosa Rhythm and blues":{"weight":4,"tf":["$meta(ES:GENRE_ROSAMERICA,5)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Rosa Rock":{"weight":4,"tf":["$meta(ES:GENRE_ROSAMERICA,6)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Rosa Speech":{"weight":4,"tf":["$meta(ES:GENRE_ROSAMERICA,7)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Tzan Blues":{"weight":4,"tf":["$meta(ES:GENRE_TZANETAKIS,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Tzan Classic":{"weight":4,"tf":["$meta(ES:GENRE_TZANETAKIS,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Tzan Country":{"weight":4,"tf":["$meta(ES:GENRE_TZANETAKIS,2)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Tzan Disco":{"weight":4,"tf":["$meta(ES:GENRE_TZANETAKIS,3)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Tzan Hip hop":{"weight":4,"tf":["$meta(ES:GENRE_TZANETAKIS,4)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Tzan Jazz":{"weight":4,"tf":["$meta(ES:GENRE_TZANETAKIS,5)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Tzan Metal":{"weight":4,"tf":["$meta(ES:GENRE_TZANETAKIS,6)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Tzan Pop":{"weight":4,"tf":["$meta(ES:GENRE_TZANETAKIS,7)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Tzan Reggae":{"weight":4,"tf":["$meta(ES:GENRE_TZANETAKIS,8)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Tzan Rock":{"weight":4,"tf":["$meta(ES:GENRE_TZANETAKIS,9)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Fma Electronic":{"weight":4,"tf":["$meta(ES:GENRE_FMA_SMALL,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Fma Experimental":{"weight":4,"tf":["$meta(ES:GENRE_FMA_SMALL,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Fma Folk":{"weight":4,"tf":["$meta(ES:GENRE_FMA_SMALL,2)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Fma Hip-hop":{"weight":4,"tf":["$meta(ES:GENRE_FMA_SMALL,3)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Fma Instrumental":{"weight":4,"tf":["$meta(ES:GENRE_FMA_SMALL,4)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Fma International":{"weight":4,"tf":["$meta(ES:GENRE_FMA_SMALL,5)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Fma Pop":{"weight":4,"tf":["$meta(ES:GENRE_FMA_SMALL,6)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Fma Rock":{"weight":4,"tf":["$meta(ES:GENRE_FMA_SMALL,7)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Discogs 90-100 %":{"weight":4,"tf":["ES:DISCOGS_G01"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 80-100 %":{"weight":4,"tf":["ES:DISCOGS_G02"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 70-100 %":{"weight":4,"tf":["ES:DISCOGS_G03"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 60-100 %":{"weight":4,"tf":["ES:DISCOGS_G04"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 50-100 %":{"weight":4,"tf":["ES:DISCOGS_G05"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 45-100 %":{"weight":2,"tf":["ES:DISCOGS_G06"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 40-100 %":{"weight":2,"tf":["ES:DISCOGS_G07"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 35-100 %":{"weight":2,"tf":["ES:DISCOGS_G08"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 30-100 %":{"weight":2,"tf":["ES:DISCOGS_G09"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 25-100 %":{"weight":2,"tf":["ES:DISCOGS_G10"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 22.5-100 %":{"weight":1,"tf":["ES:DISCOGS_G11"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 20-100 %":{"weight":1,"tf":["ES:DISCOGS_G12"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 17.5-100 %":{"weight":1,"tf":["ES:DISCOGS_G13"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 15-100 %":{"weight":1,"tf":["ES:DISCOGS_G14"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 12.5-100 %":{"weight":1,"tf":["ES:DISCOGS_G15"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 10-100 %":{"weight":1,"tf":["ES:DISCOGS_G16"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 7.5-100 %":{"weight":1,"tf":["ES:DISCOGS_G17"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Discogs 5-100 %":{"weight":1,"tf":["ES:DISCOGS_G18"],"baseScore":0,"scoringDistribution":"LINEAR","type":["multiple","string"]},"Not approachable":{"weight":4,"tf":["$meta(ES:APPROACHABILITY,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Approachable":{"weight":4,"tf":["$meta(ES:APPROACHABILITY,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Not engaging":{"weight":4,"tf":["$meta(ES:ENGAGEMENT,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Engaging":{"weight":4,"tf":["$meta(ES:ENGAGEMENT,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Valence":{"weight":4,"tf":["$meta(ES:AROUSAL_VALENCE_DEAM,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":9},"Arousal":{"weight":4,"tf":["$meta(ES:AROUSAL_VALENCE_DEAM,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":9},"Danceable":{"weight":4,"tf":["$meta(ES:DANCEABILITY,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Not danceable":{"weight":4,"tf":["$meta(ES:DANCEABILITY,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Aggressive":{"weight":4,"tf":["$meta(ES:MOOD_AGGRESSIVE,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Not aggressive":{"weight":4,"tf":["$meta(ES:MOOD_AGGRESSIVE,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Happy":{"weight":4,"tf":["$meta(ES:MOOD_HAPPY,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Non happy":{"weight":4,"tf":["$meta(ES:MOOD_HAPPY,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Non party":{"weight":4,"tf":["$meta(ES:MOOD_PARTY,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Party":{"weight":4,"tf":["$meta(ES:MOOD_PARTY,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Non relaxed":{"weight":4,"tf":["$meta(ES:MOOD_RELAXED,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Relaxed":{"weight":4,"tf":["$meta(ES:MOOD_RELAXED,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Non sad":{"weight":4,"tf":["$meta(ES:MOOD_SAD,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Sad":{"weight":4,"tf":["$meta(ES:MOOD_SAD,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Acoustic":{"weight":4,"tf":["$meta(ES:MOOD_ACOUSTIC,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Non acoustic":{"weight":4,"tf":["$meta(ES:MOOD_ACOUSTIC,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Electronic":{"weight":4,"tf":["$meta(ES:MOOD_ELECTRONIC,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Non electronic":{"weight":4,"tf":["$meta(ES:MOOD_ELECTRONIC,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Instrumental":{"weight":4,"tf":["$meta(ES:VOICE_INSTRUMENTAL,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Voice":{"weight":4,"tf":["$meta(ES:VOICE_INSTRUMENTAL,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Female":{"weight":4,"tf":["$meta(ES:VOICE_GENDER,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Male":{"weight":4,"tf":["$meta(ES:VOICE_GENDER,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Bright":{"weight":3,"tf":["$meta(ES:TIMBRE,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Dark":{"weight":3,"tf":["$meta(ES:TIMBRE,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Tonal":{"weight":4,"tf":["$meta(ES:TONAL_ATONAL,0)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100},"Atonal":{"weight":4,"tf":["$meta(ES:TONAL_ATONAL,1)"],"baseScore":0,"scoringDistribution":"LINEAR","type":["single","number","absRange"],"range":100}}

If you use these settings without making any changes, use the Weight method.

To put everything on a single line, I use this extension with VS Codium. Otherwise, there must be tools on the Internet to do this.

foobar2000

I use the Text Tools component to copy a list of tracks, formatted with the pattern r"%path%",, with a keyboard shortcut. Then I manually paste this list into the file Liste.py.

Optional: For a customized display of the foobar2000 Properties window, the advanced setting: Display > Properties dialog > Standard fields . To be added to the existing setting.

Standard fields, formatted

Es genre Rosamerica   = ES:GENRE_ROSAMERICA;
Es genre Tzanetakis   = ES:GENRE_TZANETAKIS;
Es genre FMA small    = ES:GENRE_FMA_SMALL;
Es approachability    = ES:APPROACHABILITY;
Es engagement         = ES:ENGAGEMENT;
Es arousal/valence    = ES:AROUSAL_VALENCE_DEAM;
Es danceability       = ES:DANCEABILITY;
Es mood aggressive    = ES:MOOD_AGGRESSIVE;
Es mood happy         = ES:MOOD_HAPPY;
Es mood party         = ES:MOOD_PARTY;
Es mood relaxed       = ES:MOOD_RELAXED;
Es mood sad           = ES:MOOD_SAD;
Es mood acoustic      = ES:MOOD_ACOUSTIC;
Es mood electronic    = ES:MOOD_ELECTRONIC;
Es voice/instrumental = ES:VOICE_INSTRUMENTAL;
Es voice gender       = ES:VOICE_GENDER;
Es timbre             = ES:TIMBRE;
Es tonal/atonal       = ES:TONAL_ATONAL;
Es key                = ES:KEY;
Es bpm                = ES:BPM;
Es Discogs 90-100 %   = ES:DISCOGS_G01;
Es Discogs 80-100 %   = ES:DISCOGS_G02;
Es Discogs 70-100 %   = ES:DISCOGS_G03;
Es Discogs 60-100 %   = ES:DISCOGS_G04;
Es Discogs 50-100 %   = ES:DISCOGS_G05;
Es Discogs 45-100 %   = ES:DISCOGS_G06;
Es Discogs 40-100 %   = ES:DISCOGS_G07;
Es Discogs 35-100 %   = ES:DISCOGS_G08;
Es Discogs 30-100 %   = ES:DISCOGS_G09;
Es Discogs 25-100 %   = ES:DISCOGS_G10;
Es Discogs 22.5-100 % = ES:DISCOGS_G11;
Es Discogs 20-100 %   = ES:DISCOGS_G12;
Es Discogs 17.5-100 % = ES:DISCOGS_G13;
Es Discogs 15-100 %   = ES:DISCOGS_G14;
Es Discogs 12.5-100 % = ES:DISCOGS_G15;
Es Discogs 10-100 %   = ES:DISCOGS_G16;
Es Discogs 7.5-100 %  = ES:DISCOGS_G17;
Es Discogs 5-100 %    = ES:DISCOGS_G18;
Standard fields, on one line

Es genre Rosamerica=ES:GENRE_ROSAMERICA;Es genre Tzanetakis=ES:GENRE_TZANETAKIS;Es genre FMA small=ES:GENRE_FMA_SMALL;Es approachability=ES:APPROACHABILITY;Es engagement=ES:ENGAGEMENT;Es arousal/valence=ES:AROUSAL_VALENCE_DEAM;Es danceability=ES:DANCEABILITY;Es mood aggressive=ES:MOOD_AGGRESSIVE;Es mood happy=ES:MOOD_HAPPY;Es mood party=ES:MOOD_PARTY;Es mood relaxed=ES:MOOD_RELAXED;Es mood sad=ES:MOOD_SAD;Es mood acoustic=ES:MOOD_ACOUSTIC;Es mood electronic=ES:MOOD_ELECTRONIC;Es voice/instrumental=ES:VOICE_INSTRUMENTAL;Es voice gender=ES:VOICE_GENDER;Es timbre=ES:TIMBRE;Es tonal/atonal=ES:TONAL_ATONAL;Es key=ES:KEY;Es bpm=ES:BPM;Es Discogs 90-100 %=ES:DISCOGS_G01;Es Discogs 80-100 %=ES:DISCOGS_G02;Es Discogs 70-100 %=ES:DISCOGS_G03;Es Discogs 60-100 %=ES:DISCOGS_G04;Es Discogs 50-100 %=ES:DISCOGS_G05;Es Discogs 45-100 %=ES:DISCOGS_G06;Es Discogs 40-100 %=ES:DISCOGS_G07;Es Discogs 35-100 %=ES:DISCOGS_G08;Es Discogs 30-100 %=ES:DISCOGS_G09;Es Discogs 25-100 %=ES:DISCOGS_G10;Es Discogs 22.5-100 %=ES:DISCOGS_G11;Es Discogs 20-100 %=ES:DISCOGS_G12;Es Discogs 17.5-100 %=ES:DISCOGS_G13;Es Discogs 15-100 %=ES:DISCOGS_G14;Es Discogs 12.5-100 %=ES:DISCOGS_G15;Es Discogs 10-100 %=ES:DISCOGS_G16;Es Discogs 7.5-100 %=ES:DISCOGS_G17;Es Discogs 5-100 %=ES:DISCOGS_G18;

Optional: To keep tags multi-value if touched in foobar2000, the advanced setting: Display > Properties dialog > Multivalue fields . To be added to the existing setting.

Multivalue fields, formatted

ES:GENRE_ROSAMERICA;
ES:GENRE_TZANETAKIS;
ES:GENRE_FMA_SMALL;
ES:APPROACHABILITY;
ES:ENGAGEMENT;
ES:AROUSAL_VALENCE_DEAM;
ES:DANCEABILITY;
ES:MOOD_AGGRESSIVE;
ES:MOOD_HAPPY;
ES:MOOD_PARTY;
ES:MOOD_RELAXED;
ES:MOOD_SAD;
ES:MOOD_ACOUSTIC;
ES:MOOD_ELECTRONIC;
ES:VOICE_INSTRUMENTAL;
ES:VOICE_GENDER;
ES:TIMBRE;
ES:TONAL_ATONAL;
ES:DISCOGS_G01;
ES:DISCOGS_G02;
ES:DISCOGS_G03;
ES:DISCOGS_G04;
ES:DISCOGS_G05;
ES:DISCOGS_G06;
ES:DISCOGS_G07;
ES:DISCOGS_G08;
ES:DISCOGS_G09;
ES:DISCOGS_G10;
ES:DISCOGS_G11;
ES:DISCOGS_G12;
ES:DISCOGS_G13;
ES:DISCOGS_G14;
ES:DISCOGS_G15;
ES:DISCOGS_G16;
ES:DISCOGS_G17;
ES:DISCOGS_G18;
Multivalue fields, on one line

ES:GENRE_ROSAMERICA;ES:GENRE_TZANETAKIS;ES:GENRE_FMA_SMALL;ES:APPROACHABILITY;ES:ENGAGEMENT;ES:AROUSAL_VALENCE_DEAM;ES:DANCEABILITY;ES:MOOD_AGGRESSIVE;ES:MOOD_HAPPY;ES:MOOD_PARTY;ES:MOOD_RELAXED;ES:MOOD_SAD;ES:MOOD_ACOUSTIC;ES:MOOD_ELECTRONIC;ES:VOICE_INSTRUMENTAL;ES:VOICE_GENDER;ES:TIMBRE;ES:TONAL_ATONAL;ES:DISCOGS_G01;ES:DISCOGS_G02;ES:DISCOGS_G03;ES:DISCOGS_G04;ES:DISCOGS_G05;ES:DISCOGS_G06;ES:DISCOGS_G07;ES:DISCOGS_G08;ES:DISCOGS_G09;ES:DISCOGS_G10;ES:DISCOGS_G11;ES:DISCOGS_G12;ES:DISCOGS_G13;ES:DISCOGS_G14;ES:DISCOGS_G15;ES:DISCOGS_G16;ES:DISCOGS_G17;ES:DISCOGS_G18;

Use

Interrupt

At the end of each song, there is a 2.5 seconds delay during which the script can be stopped by pressing any key on the keyboard.
At any time, the script can be paused by pressing the pause key on the keyboard.
At any time, the script can be interrupted by pressing Ctrl + C.

Hide information messages

You can uncomment lines 7, 11 and 12 to hide information messages.

Options

To choose between displaying progress bars or percentages, comment either line 33 or line 34.

The option on lines 36-37 is not very useful. It's used to display the list of classes like this:

List of classes

Classes Genre Rosamerica :
cla
dan
hip
jaz
pop
rhy
roc
spe

Classes Genre Tzanetakis :
blu
cla
cou
dis
hip
jaz
met
pop
reg
roc

Classes Genre FMA small :
Electronic
Experimental
Folk
Hip-Hop
Instrumental
International
Pop
Rock

Classes Genre Discogs400 :
Blues---Boogie Woogie
Blues---Chicago Blues
Blues---Country Blues
Blues---Delta Blues
Blues---Electric Blues
Blues---Harmonica Blues
Blues---Jump Blues
Blues---Louisiana Blues
Blues---Modern Electric Blues
Blues---Piano Blues
Blues---Rhythm & Blues
Blues---Texas Blues
Brass & Military---Brass Band
Brass & Military---Marches
Brass & Military---Military
Children's---Educational
Children's---Nursery Rhymes
Children's---Story
Classical---Baroque
Classical---Choral
Classical---Classical
Classical---Contemporary
Classical---Impressionist
Classical---Medieval
Classical---Modern
Classical---Neo-Classical
Classical---Neo-Romantic
Classical---Opera
Classical---Post-Modern
Classical---Renaissance
Classical---Romantic
Electronic---Abstract
Electronic---Acid
Electronic---Acid House
Electronic---Acid Jazz
Electronic---Ambient
Electronic---Bassline
Electronic---Beatdown
Electronic---Berlin-School
Electronic---Big Beat
Electronic---Bleep
Electronic---Breakbeat
Electronic---Breakcore
Electronic---Breaks
Electronic---Broken Beat
Electronic---Chillwave
Electronic---Chiptune
Electronic---Dance-pop
Electronic---Dark Ambient
Electronic---Darkwave
Electronic---Deep House
Electronic---Deep Techno
Electronic---Disco
Electronic---Disco Polo
Electronic---Donk
Electronic---Downtempo
Electronic---Drone
Electronic---Drum n Bass
Electronic---Dub
Electronic---Dub Techno
Electronic---Dubstep
Electronic---Dungeon Synth
Electronic---EBM
Electronic---Electro
Electronic---Electro House
Electronic---Electroclash
Electronic---Euro House
Electronic---Euro-Disco
Electronic---Eurobeat
Electronic---Eurodance
Electronic---Experimental
Electronic---Freestyle
Electronic---Future Jazz
Electronic---Gabber
Electronic---Garage House
Electronic---Ghetto
Electronic---Ghetto House
Electronic---Glitch
Electronic---Goa Trance
Electronic---Grime
Electronic---Halftime
Electronic---Hands Up
Electronic---Happy Hardcore
Electronic---Hard House
Electronic---Hard Techno
Electronic---Hard Trance
Electronic---Hardcore
Electronic---Hardstyle
Electronic---Hi NRG
Electronic---Hip Hop
Electronic---Hip-House
Electronic---House
Electronic---IDM
Electronic---Illbient
Electronic---Industrial
Electronic---Italo House
Electronic---Italo-Disco
Electronic---Italodance
Electronic---Jazzdance
Electronic---Juke
Electronic---Jumpstyle
Electronic---Jungle
Electronic---Latin
Electronic---Leftfield
Electronic---Makina
Electronic---Minimal
Electronic---Minimal Techno
Electronic---Modern Classical
Electronic---Musique Concrète
Electronic---Neofolk
Electronic---New Age
Electronic---New Beat
Electronic---New Wave
Electronic---Noise
Electronic---Nu-Disco
Electronic---Power Electronics
Electronic---Progressive Breaks
Electronic---Progressive House
Electronic---Progressive Trance
Electronic---Psy-Trance
Electronic---Rhythmic Noise
Electronic---Schranz
Electronic---Sound Collage
Electronic---Speed Garage
Electronic---Speedcore
Electronic---Synth-pop
Electronic---Synthwave
Electronic---Tech House
Electronic---Tech Trance
Electronic---Techno
Electronic---Trance
Electronic---Tribal
Electronic---Tribal House
Electronic---Trip Hop
Electronic---Tropical House
Electronic---UK Garage
Electronic---Vaporwave
Folk, World, & Country---African
Folk, World, & Country---Bluegrass
Folk, World, & Country---Cajun
Folk, World, & Country---Canzone Napoletana
Folk, World, & Country---Catalan Music
Folk, World, & Country---Celtic
Folk, World, & Country---Country
Folk, World, & Country---Fado
Folk, World, & Country---Flamenco
Folk, World, & Country---Folk
Folk, World, & Country---Gospel
Folk, World, & Country---Highlife
Folk, World, & Country---Hillbilly
Folk, World, & Country---Hindustani
Folk, World, & Country---Honky Tonk
Folk, World, & Country---Indian Classical
Folk, World, & Country---Laïkó
Folk, World, & Country---Nordic
Folk, World, & Country---Pacific
Folk, World, & Country---Polka
Folk, World, & Country---Raï
Folk, World, & Country---Romani
Folk, World, & Country---Soukous
Folk, World, & Country---Séga
Folk, World, & Country---Volksmusik
Folk, World, & Country---Zouk
Folk, World, & Country---Éntekhno
Funk / Soul---Afrobeat
Funk / Soul---Boogie
Funk / Soul---Contemporary R&B
Funk / Soul---Disco
Funk / Soul---Free Funk
Funk / Soul---Funk
Funk / Soul---Gospel
Funk / Soul---Neo Soul
Funk / Soul---New Jack Swing
Funk / Soul---P.Funk
Funk / Soul---Psychedelic
Funk / Soul---Rhythm & Blues
Funk / Soul---Soul
Funk / Soul---Swingbeat
Funk / Soul---UK Street Soul
Hip Hop---Bass Music
Hip Hop---Boom Bap
Hip Hop---Bounce
Hip Hop---Britcore
Hip Hop---Cloud Rap
Hip Hop---Conscious
Hip Hop---Crunk
Hip Hop---Cut-up/DJ
Hip Hop---DJ Battle Tool
Hip Hop---Electro
Hip Hop---G-Funk
Hip Hop---Gangsta
Hip Hop---Grime
Hip Hop---Hardcore Hip-Hop
Hip Hop---Horrorcore
Hip Hop---Instrumental
Hip Hop---Jazzy Hip-Hop
Hip Hop---Miami Bass
Hip Hop---Pop Rap
Hip Hop---Ragga HipHop
Hip Hop---RnB/Swing
Hip Hop---Screw
Hip Hop---Thug Rap
Hip Hop---Trap
Hip Hop---Trip Hop
Hip Hop---Turntablism
Jazz---Afro-Cuban Jazz
Jazz---Afrobeat
Jazz---Avant-garde Jazz
Jazz---Big Band
Jazz---Bop
Jazz---Bossa Nova
Jazz---Contemporary Jazz
Jazz---Cool Jazz
Jazz---Dixieland
Jazz---Easy Listening
Jazz---Free Improvisation
Jazz---Free Jazz
Jazz---Fusion
Jazz---Gypsy Jazz
Jazz---Hard Bop
Jazz---Jazz-Funk
Jazz---Jazz-Rock
Jazz---Latin Jazz
Jazz---Modal
Jazz---Post Bop
Jazz---Ragtime
Jazz---Smooth Jazz
Jazz---Soul-Jazz
Jazz---Space-Age
Jazz---Swing
Latin---Afro-Cuban
Latin---Baião
Latin---Batucada
Latin---Beguine
Latin---Bolero
Latin---Boogaloo
Latin---Bossanova
Latin---Cha-Cha
Latin---Charanga
Latin---Compas
Latin---Cubano
Latin---Cumbia
Latin---Descarga
Latin---Forró
Latin---Guaguancó
Latin---Guajira
Latin---Guaracha
Latin---MPB
Latin---Mambo
Latin---Mariachi
Latin---Merengue
Latin---Norteño
Latin---Nueva Cancion
Latin---Pachanga
Latin---Porro
Latin---Ranchera
Latin---Reggaeton
Latin---Rumba
Latin---Salsa
Latin---Samba
Latin---Son
Latin---Son Montuno
Latin---Tango
Latin---Tejano
Latin---Vallenato
Non-Music---Audiobook
Non-Music---Comedy
Non-Music---Dialogue
Non-Music---Education
Non-Music---Field Recording
Non-Music---Interview
Non-Music---Monolog
Non-Music---Poetry
Non-Music---Political
Non-Music---Promotional
Non-Music---Radioplay
Non-Music---Religious
Non-Music---Spoken Word
Pop---Ballad
Pop---Bollywood
Pop---Bubblegum
Pop---Chanson
Pop---City Pop
Pop---Europop
Pop---Indie Pop
Pop---J-pop
Pop---K-pop
Pop---Kayōkyoku
Pop---Light Music
Pop---Music Hall
Pop---Novelty
Pop---Parody
Pop---Schlager
Pop---Vocal
Reggae---Calypso
Reggae---Dancehall
Reggae---Dub
Reggae---Lovers Rock
Reggae---Ragga
Reggae---Reggae
Reggae---Reggae-Pop
Reggae---Rocksteady
Reggae---Roots Reggae
Reggae---Ska
Reggae---Soca
Rock---AOR
Rock---Acid Rock
Rock---Acoustic
Rock---Alternative Rock
Rock---Arena Rock
Rock---Art Rock
Rock---Atmospheric Black Metal
Rock---Avantgarde
Rock---Beat
Rock---Black Metal
Rock---Blues Rock
Rock---Brit Pop
Rock---Classic Rock
Rock---Coldwave
Rock---Country Rock
Rock---Crust
Rock---Death Metal
Rock---Deathcore
Rock---Deathrock
Rock---Depressive Black Metal
Rock---Doo Wop
Rock---Doom Metal
Rock---Dream Pop
Rock---Emo
Rock---Ethereal
Rock---Experimental
Rock---Folk Metal
Rock---Folk Rock
Rock---Funeral Doom Metal
Rock---Funk Metal
Rock---Garage Rock
Rock---Glam
Rock---Goregrind
Rock---Goth Rock
Rock---Gothic Metal
Rock---Grindcore
Rock---Grunge
Rock---Hard Rock
Rock---Hardcore
Rock---Heavy Metal
Rock---Indie Rock
Rock---Industrial
Rock---Krautrock
Rock---Lo-Fi
Rock---Lounge
Rock---Math Rock
Rock---Melodic Death Metal
Rock---Melodic Hardcore
Rock---Metalcore
Rock---Mod
Rock---Neofolk
Rock---New Wave
Rock---No Wave
Rock---Noise
Rock---Noisecore
Rock---Nu Metal
Rock---Oi
Rock---Parody
Rock---Pop Punk
Rock---Pop Rock
Rock---Pornogrind
Rock---Post Rock
Rock---Post-Hardcore
Rock---Post-Metal
Rock---Post-Punk
Rock---Power Metal
Rock---Power Pop
Rock---Power Violence
Rock---Prog Rock
Rock---Progressive Metal
Rock---Psychedelic Rock
Rock---Psychobilly
Rock---Pub Rock
Rock---Punk
Rock---Rock & Roll
Rock---Rockabilly
Rock---Shoegaze
Rock---Ska
Rock---Sludge Metal
Rock---Soft Rock
Rock---Southern Rock
Rock---Space Rock
Rock---Speed Metal
Rock---Stoner Rock
Rock---Surf
Rock---Symphonic Rock
Rock---Technical Death Metal
Rock---Thrash
Rock---Twist
Rock---Viking Metal
Rock---Yé-Yé
Stage & Screen---Musical
Stage & Screen---Score
Stage & Screen---Soundtrack
Stage & Screen---Theme

Classes Approachability :
not approachable
approachable

Classes Engagement :
not engaging
engaging

Classes Arousal/valence DEAM :
valence
arousal

Classes Danceability :
danceable
not_danceable

Classes Mood Aggressive :
aggressive
not_aggressive

Classes Mood Happy :
happy
non_happy

Classes Mood Party :
non_party
party

Classes Mood Relaxed :
non_relaxed
relaxed

Classes Mood Sad :
non_sad
sad

Classes Mood Acoustic :
acoustic
non_acoustic

Classes Mood Electronic :
electronic
non_electronic

Classes Voice/instrumental :
instrumental
voice

Classes Voice gender :
female
male

Classes Timbre :
bright
dark

Classes Tonal/atonal :
tonal
atonal

And you also need to hide/comment the results display, it's badly done. Lines 36-37, 204-208, 249-253 etc. can therefore be deleted.

The little progress bar on the left, for total progress, is on lines 180-182. You can hide it: remove {bar:10}, if I remember correctly. You can add the time and/or a percentage: take what's in the comment at the end of the line. For the time, you also need to uncomment line 173.

Use the Liste.py file

In theory, you can add folders to this list (e.g. r"E:\path\to\folder",). The script will find all flac and mp3 files inside these folders and sub-folders. But I haven't used this method much, so I'm not sure it's foolproof. I've often used long lists of single files, copied with Text Tools in foobar. It's easier to resume if there's an interruption.

Errors can occur if there are special characters, or particular accented characters, in the path. Errors can also occur if the file path length is too long. This is due to the use of the .exe extractor for Keys in sub-process.
That's why there are regular expressions in comments at the beginning of the Liste.py file. I use them with VS Codium. I do not claim that they are exact or complete. Before tagging my library, I had to rename a few files.

Phone notification

If you want to send a notification to your cell phone when there is an error, the requests package is required. Uncomment lines 23 and 1259-1263. This works with Ntfy. Here it's a different server. Topic names are public, so modify the address with a personal topic name that cannot be guessed easily. You need to install the application on your phone.

Comments

Save time when analyzing

In the first step, the track is resampled to 16kHz. You can set the quality of the resampling (resampleQuality=0, line 191). I've chosen the best quality, but it takes longer. In the code examples, the setting is 4, which is faster. I don't know if this changes the results... I compare the Mood Happy result of the example at the top of this page with the one at the bottom of the previous page, it's the same file: 0.1% difference, with roundings.

There are pauses in the script that can be removed: 1 second before writing tags to files (line 1081), and 2.5 seconds at the end of each song, where you can stop by pressing a key (lines 1193-1227).

You can choose another method to obtain the Key. essentia_streaming_key.exe is quite slow (lines 1057-1065).

Save time when searching in foobar

I have a search time between 6 and 6.5 s, with 17k tagged tracks, and a 7 year old i5 processor.

I was looking for as much precision as possible, if the search time remained acceptable with my library. Initially, essentia gives a probability with a number between 0 and 1 with many decimals. I chose to use percentages with one decimal place. Perhaps less precise rounding will speed up the search.

Some tags are duplicates. Often these are opposite results, e.g. happy 95.8 non_happy 4.2. So a lot of calculations are done twice for the same result. Sometimes I've seen a discrepancy, I don't remember which tag. So I kept these complementary tags, but it seems a bit exaggerated. I think removing those 14 complementary tags would save a lot of time and the difference in results would be small.

Keys and BPM

Methods I've seen:

Methods for Keys

Methods for BPM

For the Keys, I've tried all these methods with several tracks, with varying results. I'm unable to say which is the best, or which are the right settings. I took the essentia_streaming_key.exe extractor, but I have no idea if it's the best choice.

I just saw MusicExtractor. I haven't tried it.

Discogs results

I did something experimental with the Discogs400 results.
Problem: this model gives predictions on 400 genres/styles, but Spider Monkey Panel doesn't accept 400 custom tag slots (see note).
EDIT : I just discovered that we can load the 400 custom tag slots with a recipe. I'll have to try that.

We could keep only the genre with the highest percentage. Or the first 3 genres. Or only the genres above a threshold, e.g. all genres above 20%. But by doing this, you could put a genre at 87% and the same one at 21% on the same level.
So I made slices: 100 - 90 - 80 - 70 - etc. Then, in Search-by-Distance-SMP, I compare the slices.
I keep only the genres above 5%.
There are many more genres with low values, between 5 and 20%. To have more precision with these low values, I made thinner slices at the end.
I also copy the genre in all the lower slices. If I have a genre at 23%, that means it's also present in every slice between 5 and 23%. So it makes a pyramid.

However, you can't set a weight of less than 1 for custom tag slots ("Value must be an INT POSITIVE"). So I tried to balance things out by increasing the weight of the other models.

note: I tried. When I paste something into the property sbd0.Tags used for scoring, it only keeps the first 30 000 characters. So I can't. When I press Ok, it displays an error because the json is badly closed. You can try it yourself with these tags.
Otherwise, with the values below 5% (i.e. the vast majority) at 0, or empty, perhaps it would have been feasible?

Code for models not on the website

I found the code for models Rosamerica and Tzanetakis here and here.

For the FMA Small model, I generated the code from a script here, adding the model name to this list (line 334).

Memory

I had errors with very long tracks (20 min and +). The memory was full. So I reset things when they are no longer useful, on the lines 233-236, 280-283 etc. And now it works.

Changelog

There was a small update on a model. I haven't changed my settings.

Changelog

Link

## 2024-05-02

### Changed
- Fix class label order for tonal/atonal classifiers.
Clone this wiki locally