Void & Alcota
Alcota Alcota
Привет, запустила небольшой скрипт, который сопоставляет разложение на простые множители с микротональными интервалами — вроде генератора гамм, основанного на логике. У тебя есть код, который превращает твои собственные паттерны в звук?
Void Void
Конечно, есть простой способ превратить числовую последовательность в звуковую волну – сопоставить каждое число с частотой и сложить синусоиды. Вот минимальный пример, который берёт список простых чисел, преобразует каждое в частоту (используя простое масштабирование) и воспроизводит короткий тон для каждого. Потребуются numpy и sounddevice; если их нет, сначала установи их. import numpy as np, sounddevice as sd # Пример последовательности – первые несколько простых чисел primes = [2,3,5,7,11,13] # Преобразуем каждое простое число в частоту (Гц). # Здесь мы используем базовую частоту 220 Гц и удваиваем её для каждого простого числа. frequencies = [220 * p for p in primes] duration = 0.3 # секунды на ноту sample_rate = 44100 # выборки в секунду def note(freq, dur): t = np.linspace(0, dur, int(sample_rate*dur), endpoint=False) return 0.3 * np.sin(2*np.pi*freq*t) # Собираем полную волну, объединяя ноты wave = np.concatenate([note(f, duration) for f in frequencies]) # Воспроизводим её sd.play(wave, sample_rate) sd.wait()
Alcota Alcota
Здорово, но этот твой вариант с прямыми 220х простыми числами упустит все микротональные нюансы, которые мне нравятся. Может, попробуешь изменить масштабирование, чтобы попасть в сетку 17-тоновой равномерной темперации, а не использовать чистые октавы? И добавь небольшой ADSR-конверт, чтобы эти синусоидальные всплески не звучали как лазерные разрезы. Продолжай экспериментировать, пусть простые числа будут основой, а микротоны – сутью.
Void Void
Понял, переделаю масштабирование, чтобы каждый тон попадал на ступень в 17-ступенчатой равномерной системе (E17), и добавлю небольшой ADSR-конверт, чтобы сгладить резкость. Вот обновленный фрагмент: import numpy as np, sounddevice as sd # Базовая частота для первой ступени E17 (до в 17-ступенчатой) base = 220.0 steps = 17 # Генерируем таблицу соответствия: 1 ступень = 2^(1/ступени) ratio = 2**(1/steps) # Первые несколько простых чисел, как основа primes = [2,3,5,7,11,13] # Отображаем каждое простое число на микротональную ступень, возводя в степень frequencies = [base * (ratio ** (p-1)) for p in primes] duration = 0.25 # секунды на ноту sr = 44100 def adsr(freq, dur, attack=0.01, decay=0.05, sustain=0.8, release=0.05): t = np.linspace(0, dur, int(sr*dur), endpoint=False) env = np.ones_like(t) # attack a = int(attack*sr) env[:a] = np.linspace(0, 1, a) # decay d = int(decay*sr) env[a:a+d] = np.linspace(1, sustain, d) # sustain s = int((dur-attack-decay-release)*sr) env[a+d:a+d+s] = sustain # release r = int(release*sr) env[-r:] = np.linspace(sustain, 0, r) return 0.3 * np.sin(2*np.pi*freq*t) * env wave = np.concatenate([adsr(f, duration) for f in frequencies]) sd.play(wave, sr) sd.wait()
Alcota Alcota
Переход с линейной октавы к настоящей E17 – впечатляет, кривая ADSR выглядит аккуратно, хотя в сегменте са sustain иногда может не хватить пространства, если нота очень короткая. Попробуй немного ограничить release, чтобы он не выходил за пределы буфера. И ещё, подумай добавить немного де-тюнинга на каждый основной шаг – у простых чисел своя внутренняя напряжённость, которую идеально микротональное деление не передаёт полностью. Следи за первыми нотами, они будут самыми низкими, и могут заклинить, если слишком сильно давить на басовую частоту в 220 Гц. И помни: иногда незаконченный мотив – это всего лишь подсказка для следующей импровизации.