# Path: munin/provider/moodbar.py
# class MoodbarAudioFileProvider(MoodbarMoodFileProvider):
#     """Moodbar Provider for audio files.
# 
#     Takes a path to an arbitary audio file.
#     Will look for audio_file_path + '.mood' before computing it.
#     Resulting mood file will be stored in the same path.
#     """
#     def do_process(self, audio_file_path):
#         mood_file_path = audio_file_path + '.mood'
#         if not os.path.exists(mood_file_path):
#             if compute_moodbar_for_file(audio_file_path, mood_file_path):
#                 return None
#         return MoodbarMoodFileProvider.do_process(self, mood_file_path)
# 
# Path: munin/distance/moodbar.py
# class MoodbarDistance(DistanceFunction):
#     """Distance Function that compares two MoodbarDescriptions."""
#     def do_compute(self, lefts, rights):
#         """Compute the distance between two moodbar desc
# 
#         Only the first element in the individual lists is used.
# 
#         :param lefts: Packed left moodbar description.
#         :param rights: Packed right moodbar description.
#         """
#         if not (lefts and rights):
#             return 1.0
# 
#         distance = 1.0
#         ld, rd = lefts[0], rights[0]
#         distf = lambda v1, v2, m: 1.0 - sqrt(min(1.0, abs(v1 - v2) / m))
# 
#         for left_chan, right_chan in zip(ld.channels, rd.channels):
#             hist_diff = sum(abs(a - b) for a, b in zip(left_chan.histogram, right_chan.histogram))
#             distance -= 0.045 * (1.0 - hist_diff / (5 * 255))
#             distance -= 0.045 * distf(left_chan.diffsum, right_chan.diffsum, 50)
# 
#         distance -= 0.025 * distf(ld.average_max, rd.average_max, 255)
#         distance -= 0.025 * distf(ld.average_min, rd.average_min, 255)
#         distance -= 0.050 * distf(ld.blackness, rd.blackness, 50)
# 
#         lkeys, rkeys = ld.dominant_colors.keys(), rd.dominant_colors.keys()
#         if lkeys and rkeys:
#             distance -= 0.63 * (len(lkeys & rkeys) / max(len(lkeys), len(rkeys)))
# 
#         # Good distances are in the range 0.3 - 0.5 usually
#         # Therefore we handle lower values better.
#         # http://www.arndt-bruenner.de/mathe/scripts/regr.htm
#         # was used to calculate a polynom that scales these values.
#         # This function goes through the following points:
#         # 0      0
#         # 0,25   0,125
#         # 0,5    0,5
#         # 0,75   0,875
#         # 1      1
#         #
#         # The function is not 100% correct, so we clamp possible precision
#         # errors into [0, 1]
#         d2 = distance * distance
#         d3 = d2 * distance
#         return min(1.0, max(0, -2.666 * d3 + 4 * d2 - 0.3333 * distance))
# 
# Path: munin/helper.py
# class AudioFileWalker:
#     """File Iterator that yields all files with a specific ending.
#     """
#     def __init__(self, base_path, extensions=ALLOWED_FORMATS):
#         """There ist a list of default extensions in
#         ``munin.helpers.ALLOWED_FORMATS`` with the most common formats.
# 
#         This class implements ``__iter__``, so you just can start using it.
# 
#         :param base_path: Recursively seach files in this path.
#         :param extensions: An iterable of extensions that are allowed.
#         """
#         self._base_path = base_path
#         self._extension = set(extensions)
# 
#     def __iter__(self):
#         for root, _, files in os.walk(self._base_path):
#             for path in files:
#                 ending = path.split('.')[-1]
#                 if ending in self._extension:
#                     yield os.path.join(root, path)


import os
import sys
from itertools import combinations
from collections import deque
from concurrent.futures import ProcessPoolExecutor
from munin.provider.moodbar import MoodbarAudioFileProvider
from munin.distance.moodbar import MoodbarDistance
from munin.helper import AudioFileWalker
#!/usr/bin/env python
# encoding: utf-8

# Stdlib:


# Internal:


def compute_moodbar(full_path):
    try:
        root, path = os.path.dirname(full_path), os.path.basename(full_path)
        result = provider.process(full_path)
        if result:
            return (result, path, root)
    except Exception:
        pass
    return (None, path, root)


if __name__ == '__main__':
    if len(sys.argv) < 2:
        print('usage: {} path_to_music_dir'.format(sys.argv[0]))
        sys.exit(-1)

    provider = MoodbarAudioFileProvider()
    distance = MoodbarDistance(provider)

# Path: munin/provider/moodbar.py
# class MoodbarAudioFileProvider(MoodbarMoodFileProvider):
#     """Moodbar Provider for audio files.
# 
#     Takes a path to an arbitary audio file.
#     Will look for audio_file_path + '.mood' before computing it.
#     Resulting mood file will be stored in the same path.
#     """
#     def do_process(self, audio_file_path):
#         mood_file_path = audio_file_path + '.mood'
#         if not os.path.exists(mood_file_path):
#             if compute_moodbar_for_file(audio_file_path, mood_file_path):
#                 return None
#         return MoodbarMoodFileProvider.do_process(self, mood_file_path)
# 
# Path: munin/distance/moodbar.py
# class MoodbarDistance(DistanceFunction):
#     """Distance Function that compares two MoodbarDescriptions."""
#     def do_compute(self, lefts, rights):
#         """Compute the distance between two moodbar desc
# 
#         Only the first element in the individual lists is used.
# 
#         :param lefts: Packed left moodbar description.
#         :param rights: Packed right moodbar description.
#         """
#         if not (lefts and rights):
#             return 1.0
# 
#         distance = 1.0
#         ld, rd = lefts[0], rights[0]
#         distf = lambda v1, v2, m: 1.0 - sqrt(min(1.0, abs(v1 - v2) / m))
# 
#         for left_chan, right_chan in zip(ld.channels, rd.channels):
#             hist_diff = sum(abs(a - b) for a, b in zip(left_chan.histogram, right_chan.histogram))
#             distance -= 0.045 * (1.0 - hist_diff / (5 * 255))
#             distance -= 0.045 * distf(left_chan.diffsum, right_chan.diffsum, 50)
# 
#         distance -= 0.025 * distf(ld.average_max, rd.average_max, 255)
#         distance -= 0.025 * distf(ld.average_min, rd.average_min, 255)
#         distance -= 0.050 * distf(ld.blackness, rd.blackness, 50)
# 
#         lkeys, rkeys = ld.dominant_colors.keys(), rd.dominant_colors.keys()
#         if lkeys and rkeys:
#             distance -= 0.63 * (len(lkeys & rkeys) / max(len(lkeys), len(rkeys)))
# 
#         # Good distances are in the range 0.3 - 0.5 usually
#         # Therefore we handle lower values better.
#         # http://www.arndt-bruenner.de/mathe/scripts/regr.htm
#         # was used to calculate a polynom that scales these values.
#         # This function goes through the following points:
#         # 0      0
#         # 0,25   0,125
#         # 0,5    0,5
#         # 0,75   0,875
#         # 1      1
#         #
#         # The function is not 100% correct, so we clamp possible precision
#         # errors into [0, 1]
#         d2 = distance * distance
#         d3 = d2 * distance
#         return min(1.0, max(0, -2.666 * d3 + 4 * d2 - 0.3333 * distance))
# 
# Path: munin/helper.py
# class AudioFileWalker:
#     """File Iterator that yields all files with a specific ending.
#     """
#     def __init__(self, base_path, extensions=ALLOWED_FORMATS):
#         """There ist a list of default extensions in
#         ``munin.helpers.ALLOWED_FORMATS`` with the most common formats.
# 
#         This class implements ``__iter__``, so you just can start using it.
# 
#         :param base_path: Recursively seach files in this path.
#         :param extensions: An iterable of extensions that are allowed.
#         """
#         self._base_path = base_path
#         self._extension = set(extensions)
# 
#     def __iter__(self):
#         for root, _, files in os.walk(self._base_path):
#             for path in files:
#                 ending = path.split('.')[-1]
#                 if ending in self._extension:
#                     yield os.path.join(root, path)


# Path: munin/scripts/moodbar_walk.py
import os
import sys
from itertools import combinations
from collections import deque
from concurrent.futures import ProcessPoolExecutor
from munin.provider.moodbar import MoodbarAudioFileProvider
from munin.distance.moodbar import MoodbarDistance
from munin.helper import AudioFileWalker

#!/usr/bin/env python
# encoding: utf-8

# Stdlib:


# Internal:


def compute_moodbar(full_path):
    try:
        root, path = os.path.dirname(full_path), os.path.basename(full_path)
        result = provider.process(full_path)
        if result:
            return (result, path, root)
    except Exception:
        pass
    return (None, path, root)


if __name__ == '__main__':
    if len(sys.argv) < 2:
        print('usage: {} path_to_music_dir'.format(sys.argv[0]))
        sys.exit(-1)

    provider = MoodbarAudioFileProvider()
    distance = MoodbarDistance(provider)

    moodbar_files = list(AudioFileWalker(sys.argv[1]))