Ля, ля бемоль. Создание звука фортепьяно

Дмитрий Маштаков
   Математическое программирование звука фортепьяно.

   статья чуть устарела, более современное описание алгоритма тут -
   http://www.proza.ru/2017/04/01/260

   Синтез электронного музыкального звука интересен не только своей прагматичной целью, он интересен и в более глубоком плане - и в плане исследования принципиальных возможностей создания звука программными средствами, и в плане исследования особенностей восприятия звука. Но и прагматичная цель передо мною стояла - приведённая здесь http://www.proza.ru/2015/04/18/1425 функция изготовления звука, хотя и вполне удовлетворяла меня звучанием своего результата, но звучание это было всё же отлично от "натурального" звука ф-но, особенно в среднем диапазоне - первая, и малая октавы.
   И, ещё раз повторю, возникла задача чисто исследовательская - что "звучит не так", по каким параметрам звук, при всех моих стараниях, отличается от натурального, и как это различие преодолеть наиболее простым способом?

  Всё оказалось интересным, и об этом я сейчас расскажу.
  Прежде всего о тембре звучания. Синусоида звучит, сами знаете как -"Пиии...", однотонно и однообразно. А фортепьяно - "Ля, ля, ля...", совсем другой оттенок.
 Однако можно попытаться добавить обертонов или деформировать каким либо образом кривую звука. Чтобы было яснее, расскажу конкретнее.

НЕМНОГО МАТЕМАТИКИ И ПРОГРАММИРОВАНИЯ

   Никакой синус от Х в программе на самом деле не вычисляется. Вместо этого отслеживается движение по Х от нуля до двух. Делается это движение шагами  DX=2*F/VEL, где F - частота тона, а VEL - скорость раздачи, равная 32000 сэмпла в секунду, или 44100 сэмпла в секунду. Короче говоря, делаем 1 шаг, вычисляем амплитуду, записываем 1 сэмпл в WAV файл. При таком программном подходе фаза колебания располагается не между нулём и числом 2*Пи, а между нулём и числом 2 (см.Примечание в самом низу этого текста).
   Как только при очередном шаге Х становится большим 2-х, значение это оператором Х=Х-2 возвращается в начало периода. Это понятно. Что же вычисляется?

  Находим предварительно Z=2*X-1  для первого полупериода (если X<1),
или Z=2*(X-1)-1, если Х находится во втором полупериоде. В обоих случаях мы получаем переменную Z в интервале (-1,1). В этом интервале и происходят все вычисления:
   Y=1-Z*Z - уже есть горбик параболы "рожками вниз", но, если хотим, то продолжим дальше, и получим почти точную форму косинусоиды: Y =(Y*3+Y^2)/4.
Нам понадобится ещё функция более остренькая. чем синусоида, вот такая:
Y2=Y^6 - шестая степень от только что полученной функции Y.
  Для чего нам понадобилась такая функция? А для того что, если сложить наши функции таким образом: Yтр = Y + 0.8*Y2, то мы получим хороший равнобедренный треугольник со сглаженной вершинкой.
  Все эти функции ещё и наклонять можно, умножая на линейную функцию Z:
Y(z)наклонное = Y(z)*(1+K*z).
  Для второго полупериода вычисленная амплитуда, естественно, берётся с обратным знаком. Кроме того есть возможность проходить второй полупериод не только в прямом, но и в обратном направлении - для этого перед вычислением амплитуд второго полупериода нужно сменить знак z: Z=-Z.

Казалось бы возможностей много.
  Но звук "Ля, ля, ля..." не получается, как я не старался. Получается "Ви", если обострить вершинку. "Во", если выгнуть в одну сторону, и точно такое же "Во", если выгнуть в другую сторону. Глухо звучит. Чему я научился, так это сделать так, чтобы звук зазвенел, точнее - стал звонче. Для этого оказалось нужным, чтобы одна половина периода и другая половина периода проходились с разными скоростями (с разными шагами, при сохранении суммарного числа шагов). Делается это так:

 IF X<1 THEN
     DXM=DX/(1+AZ0)
         ELSE
     DXM=DX/(1-AZ0)
 END IF

  как видно,  вычисляется модернизированный шаг  DXM, немного более узкий для первого полупериода, если параметр AZ0 немного больше нуля, при этом первый полупериод растягивается по времени. Амплитуда звука затем корректируется - если шаг укорачивается, то амплитуда уменьшается, и наоборот (площади полупериодов остаются одинаковыми, и дисбаланса среднего давления не происходит). Оптимальным с точки зрения восприятия звука в первой октаве оказалось значение AZ0=0.12
  При бОльших значениях звон становился чересчур резким. Но всё равно, желанного тембра не получилось. Получилось "Вя"

КАК ВЫГЛЯДИТ НАТУРАЛЬНЫЙ ЗВУК

  Уважаемые читатели, прошу прощения, я вас утомил, но математики больше не будет. Мы обратимся к исследованию записей натурального звука.
Вот он - на рисунке наверху, звук рояля, нота Ля второй октавы. На чёрной записи пониже видно, из какой части звука вырезка сделана. В других местах - никаких видимых отличий, только по амплитуде. Ну и что? - скажите Вы. Синусоида.
  Как бы не так! Звучит-то "Ля...", причём при проигрывании с любого места. А синусоида: "Пиии", ну "Вя", в лучшем случае.
  Но исследовал я звук октавой ниже - Ля бемоль, поскольку он имел более характерную и интересную форму. Проводил я исследования в Автокаде, поскольку в нём можно измерять расстояния. Я и измерял. В миллиметрах, но нас интересуют относительные величины.
  Что оказалось? Действительно, первый (верхний) полупериод шире второго в соотношении 1.308. Более того, если отталкиваться от ожидаемого вида обострённой синусоиды, то вершина треугольника оказывается смещённой вправо (в сторону запаздывания). При этом фронт треугольника нарастает не столь резко. Естественно, звук звучит мягче! Интересно, что нижняя половина полупериода показывает хоть небольшую, но противоположную тенденцию с укорочением фронта. Оказывается, в этом тоже есть резон, но об этом позже. Пока скажем, что тенденция растягивания фронта на более широком полупериоде превалирует в зрительном восприятии. Но каковО оно на слух? И как создать подобный синтетический звук?
Также просто, как мы с вами только что это делали - слегка менять шаг не только по полупериодам, но и по четвертям периода звукового колебания:

 IF X<1 THEN
    V=DX/(1+AZ0) : IF X<.5 THEN DXM=V/(1+PA) ELSE DXM=V/(1-PA)
         ELSE
    V=DX/(1-AZ0) : IF X<1.5 THEN DXM=V/(1+PB) ELSE DXM=V/(1-PB)
  END IF

И вот, я взял параметры AZ0=0.12, PA=0.27, PB=-0.1 и треугольничек Yтр(z) для расчёта амплитуд, и получил звук "Ля...", ничем на слух не отличимый от натурального, с двумя исключениями - нет противного стука клавиши, и нет обертонов в стадии нарастания звука, которая демонстрирует их наличие, см. чёрный рисунок снизу. Стук клавиши я в звук возвращать не собираюсь, а обертоны в начало звука я поместил. Без них звук возникает не столь ярко.

ОТКУДА БЕРЁТСЯ СИПЕНИЕ

  Но прежде чем говорить об обертонах, давайте, закончим с нижней частью колебания - со вторым, укороченным полупериодом.
  Всё прекрасно, сказал я, но хочу звук ещё улучшить - зачем крутой фронт в нижний половине? И поменял PB=-0.1 на PB=+0.1
  Думаете, получилось лучше? Как бы не так. Звук стал действительно, ещё помягче, но на фоне этого помягчения появился призвук "Ся...". Понимаете? "Ля...", и ещё "Ся..." слышится! Откуда сипение? После такой замены параметра появился чересчур длинный линейный участок - спад 1-го полупериода поддерживался фронтом 2-го полупериода. А чрезмерный линейный участок, это всегда сипение - разложение в ряд Фурье даёт на нём многочисленные высокие обертоны. Которые и сипят.
  Этого и следовало бы ожидать. Как рояль устроен? Он устроен оптимально! Совершенствовался веками. И нам, переходя к обертонам, самое время ознакомиться с геометрией его устройства.

ОБЕРТОНЫ И УСТРОЙСТВО ФОРТЕПЬЯНО

  Фото раскрытого рояля, вид сверху, такого, чтобы были видны колки и молоточки, я не нашёл, но нашел пианино Ricco & Son, где всё хорошо было видно. Меня интересовало положение молоточков на струнах. Расстояния от верхних колков до молоточков всюду уменьшалось по мере уменьшения длины струн. Точка удара приходилась при этом на от 1/7 до 1/10 части струны. Чаще всего  на 1/9.
  Граничные условия процесса колебания струны заданы колками. Конечно, дека гудит, но ничего вразумительного об этом гуде мы предположить не можем. Потому считаем точки крепления струны неподвижными.
  Удар молоточка локально прогибает струну, с этого-то всё и начинается.
  Струны фортепьяно очень жёсткие, прогибаются они даже при очень сильном и коротком ударе не под форму молоточка. Но будем считать, что в месте удара исходный для колебания прогиб максимален. Пусть это будет горбик, подобный горбику синусоиды, спадающий до нуля на верхнем колке и ноль - за пределами 2/9 части струны то есть на 7/9 её части. Кстати, у щипкового инструмента - клавесина, струны тоньше. Если предположить для клавесина ту же точку начального зацепа, что и для удара у фортепьяно, то за начальное отклонение струны можно взять сильно разнобокую треугольного вида функцию с максимумом в месте зацепа и длинами сторон 1/9 и 8/9 от длины струны. С этими данными мы и будем вычислять коэффициенты Фурье для амплитуд начала колебания обертонов.
  Результат вычисления показан на рисунке справа.
  Да, сказал я, беден клавесин на обертоны. Зато рояль каков! У рояля струны жёсткие - успокоили в интернете, таких сильных обертонов у него на наблюдается, они очень быстро спадают и перераспределяют свою амплитуду. После чего затухают, но не столь быстро. Но меня интересовала яркость первого момента - видите, обертоны 4, 5, может быть 6, если не слишком затухнет и составит конкуренцию своим младшим соседям. Вот на диаграмме нарастания звука, в самом её начале, мне кажется, я эти обертоны и вижу. Потом они заметно портят вершинки основного колебания.
   У меня в программе есть места для 3-х штатных обертонов. Одно место занято обострением вершинки (созданием треугольника). Два других места я отдал обертонам 4 и 5, приписав им начальную амплитуду 0.2, относительно единицы основного колебания. На диаграмму натурального звука ориентировался.
  И зазвучало. Зазвучало хорошо, даже без перестройки параметров. В  4-х октавах - в большой (в ней есть средства сделать звук поярче), малой и первой (в них делать ничего не нужно), и во второй (очень ярко звучит, но разве это плохо, притупить звук всегда можно - уменьшив обостряющую верхушечку треугольника). И всему этому придаёт особую красоту медленное (53 периода) вибрато, которое можно создавать периодическим изменением параметра AZ0. Это предусмотрено в программе.
 
ПЛАНЫ НА БУДУЩЕЕ

  Есть и ещё различные возможности оттенения звука в других диапазонах и в целом. Сделан ревербератор, создающий эхо резонатора указанных размеров, или эхо вблизи заданной резонансной частоты. Всё это интересно будет попробовать. И есть же другие инструменты, кроме рояля. Программа оказалась богатой на возможности, хотя и простой. Удачной, поскольку богатые возможности и простота обычно трудно совместимые вещи.
  В синтезе звука имеются различные подходы и направления, и я о них знаю, но делаю то, что умею, и что мне ближе.

Помимо ссылки, данной выше, привожу ещё ссылки на предыдущие статьи по близким темам:
http://www.proza.ru/2015/04/18/1425 - Математическое программирование звука
http://www.proza.ru/2015/04/11/1943 - Как устроен WAV файл. Запись сэмплов
http://www.proza.ru/2015/04/02/1593 - Пианино на клавишах компьютера
http://www.proza.ru/2015/04/02/1578 - Гармония звуков

Спасибо за внимание.
_____________
Примечание. В настоящее время алгоритм получения величины X несколько другой.
  При первом обращении к звуковой функции время T устанавливается в ноль, и находятся шаг по времени DT=1/VEL, и период звукового колебания TT=1/F.
  А затем, при каждом обращении к функции, выполняется цепочка операторов -
     T=T+DT : X=T/TT : NT=INT(X) : X=(X-NT)*2
в результате X определяется как удвоенная дробная часть отношения T/TT.