Как округлить разрыв между произвольными числами? - PullRequest
0 голосов
/ 01 ноября 2019

Я пытаюсь найти алгоритм, чтобы округлить разрыв между некоторыми полуслучайными числами так, чтобы, например, если были разрывы со значением закрытия, они были бы одинаковыми. например, если мы имеем «109 102 212 198 99 802» в качестве пробелов, они округляются до «100 100 200 200 100 800». Предположим, что все округленные пробелы будут иметь вид (2 ^ n) * (наименьший разрыв), где n - неотрицательное целое число. В приведенном выше примере промежутки равны 100 (наименьшему), 200, 400, 800.

1 Ответ

1 голос
/ 02 ноября 2019

На самом деле я хотел написать код, чтобы преобразовать песню в ноты. для этого я нашел интервалы между соседними заметками, а затем мне нужен алгоритм для округления этих интервалов. Я сделал это, и это работает хорошо, я думаю. Сначала я нашел значение основного разрыва, например, в «102 103 402 409 390 398 100 200 408», основной разрыв - что-то около 400 (в среднем 402 409 390 398 408), затем я положил его длительность как 1 и сравнилдругой с этим. на 102 длительность составит 0,25 и тд.

Отредактировано: Frist Я использовал несколько библиотек python для обработки файла .mp3 и поиска момента изменения частоты и его соответствующей продолжительности в миллисекундах. Поскольку эти времена не являются точными, мне нужно округлить их, чтобы я мог назначить им одну из нотаций примечаний.

def roundOff(diffs):
        global major_element, ref_offset, divide_flag, measured_time, measured_note
        major_element = findMajor(diffs)
        for element in diffs:
            divide_flag = False
            measured_time = 0
            measured_note = 0
            note_duration.append(noteFinder(element, ref_offset))
        return note_duration

Вышеприведенная функция получает пропуски в качестве входных данных и возвращает соответствующую длительность ноты. Я нашел основной разрыв следующим образом:

def findMajor(diffs):
    diffs_copy = diffs.copy()
    diffs_copy.sort()
    this = 0
    for element in diffs_copy:
        if isNear(element, this):
            temp_this = (this*elements_in_gap[this] + element)/(elements_in_gap[this] + 1)
            elements_in_gap[this] += 1
            elements_in_gap[temp_this] = elements_in_gap.pop(this)
            this = temp_this
        else:
            this = element
            elements_in_gap[this] = 1

    return max(elements_in_gap, key = element_in_gap.get)

Во-первых, он сортирует список пробелов и помещает 'this' в качестве репрезентативного значения разрыва, с которым мы хотим проверить других (начальное значение равно 0), вкаждый шаг, он проверяет, находится ли новый разрыв около 'this', затем изменяет 'this' и увеличивает количество разрывов в наборе 'this', но если он не рядом, замените 'this' на новый элемент и начальный номер нового 'this'(: |) в 1 и сделать то же самое. И, наконец, ключ возврата с наибольшим значением значения в качестве основного разрыва.

Функция isNear выглядит следующим образом:

def isNear(a, b):
    if a < b+b*tolerance and a > b-b*tolerance:
        return True
    return False

В этом случае целесообразно установить допуск равным 0,1. noteFinder находит примечание каждого разрыва относительно основного разрыва как 1 (ref_offset).

def noteFinder(diff_time, offset):
    global measured_time, measured_note, divide_flag, major_element
    if isNear(diff_time, measured_time):
        return measured_note
    else:
        if not divide_flag:
            if diff_time > measured_time:
                measured_time += offset*major_element
                measured_note += offset
                return noteFinder(diff_time, offset)
            else:
                offset /= 2
                measured_time -= offset*major_element
                measured_note -= offset
                divide_flag = True
                return noteFinder(diff_time, offset)
        else:
            offset /= 2
            if diff_time > measured_time:
                measured_time += offset*major_element
                measured_note += offset
                return noteFinder(diff_time, offset)
            else:
                measured_time -= offset*major_element
                measured_note -= offset
                return noteFinder(diff_time, offset)

Добавляет смещение к измеренной ноте и смещение * значение основного разрыва к измеренному времени на каждом шаге (сначаласмещение равно 1, как уже упоминалось), пока его значение разрыва не будет меньше измеренного времени, тогда он включит divid_flag, чтобы разделить смещение на 2 на каждом шаге, и попытается приблизиться к значению разрыва, а затем вернет записку meatured.

Это моя предложенная схема, если у вас есть лучшая, пожалуйста, дайте мне знать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...