Я по образованию и роду занятий не музыкант,
но немного увлекаюсь теорией музыки
и это увлечение в итоге привело к тому,
что я написал программульку, синтезатор с чистым строем.
Информация тут:
Исходные тексты тут:
Буду признателен, если кто-то, кто интересуется чистым строем,
попробует эту программку и выскажет предложения или замечания.
Программа написана для того,
чтобы попробовать "на вкус" чистый строй.
При отсутствии "настоящего" синтезатора может
вполне подойти для несложного аккомпанемента пению :)
Написана для ОС Linux, проверялась в Debian и Ubuntu.
P.S. Извиняюсь, если разместил тему не в том разделе,
ничего более подходящего не нашел.
23.02.2012, 18:38
xjiss
Re: Синтезатор с чистым строем
... ндас, ЧСХ, народ безмолвствует...
ладно, попробуем с другой стороны зайти.
специально "написал" и сыграл "Реквием по РТС".
(48000 Hz, stereo, s16 little endian)
ну? )) есть кто живой?
24.02.2012, 03:01
DJ Хруст
Re: Синтезатор с чистым строем
Уважаемый xjiss, наверное, проблема в том, что здесь мало линуксоидов.
24.02.2012, 09:33
xjiss
Re: Синтезатор с чистым строем
Да, наверное. Ну да и ладненько.
10.03.2012, 23:53
Toman
Re: Синтезатор с чистым строем
Думаю, мне будет очень интересно почитать исходники. Возможно, это почти то самое, что я давно ищу. Потому как я как раз пробовал найти хотя бы онлайновые синтезаторы для некоторых строев, однако ничего хорошего не нашёл. Возможно, если повезёт, удастся переделать этот синтезатор для работы в каких-нибудь персидских ладах. Или просто в 53-РДО, или ещё какие-нибудь РДО, чтобы просто поиграться и посравнивать их на слух между собой. В своё время, лет уже 10 назад (ой, блин, неужели это уже целых 10 лет прошло...) я начинал было писать игрульки, издающие (и даже записывающие) какие-то звуки, и даже, хе-хе, показывал и рассказывал одному цивильному товарищу, как это делается (в качестве источника хватило хороших комментариев в заголовках от OSS, кажется), но... это было во времена ещё OSS'ного интерфейса звукового устройства, а очень вскоре он стал как-то неактуален, сменившись на ALSA, и всё на этом застопорилось. В то время как попытки понять, как то же самое делать в ALSA, кончились ничем, т.к. такого же понятного руководства, как в заголовках OSS, я что-то не нашёл среди аналогичных заголовков. А потом на несколько лет (примерно до 2009) вообще вышел из рядов пользователей Линукс. Может быть, почитав Ваши исходники, мне, наконец, удастся что-то понять :) Да ещё тут программа с нитями - в своих тогдашних почти-школьных программах я до нитей не доходил, всё делал последовательно в единственной. Короче, надеюсь, такая сравнительно небольшая программа, которую и части которой, в отличие от больших, можно обозреть взглядом одного человека - почти самое то что надо, чтобы посмотреть, как более-менее цивильно делается то, что я хотел и пытался сделать нецивильно тогда. В общем, большое спасибо: уже из того, что я успел прочитать в исходниках за первые 10-15 минут, я почерпнул много интересного и полезного для себя, при своём самом начальном уровне. Уже давненько я ничего на C не писал вообще - наверное, как раз те самые лет 10 после тех первых попыток, т.к. по работе-то всё перл да перл обычно...
11.03.2012, 11:00
xjiss
Re: Синтезатор с чистым строем
Цитата:
Сообщение от Toman
Или просто в 53-РДО, или ещё какие-нибудь РДО, чтобы просто поиграться и посравнивать их на слух между собой.
Думаю, с точки зрения кодинга - не проблема.
Проблема вот где
:)
Цитата:
Сообщение от Toman
В то время как попытки понять, как то же самое делать в ALSA, кончились ничем,
Ну, освоить хоть немного ALSA было одной из целей написания
программки.
Цитата:
Сообщение от Toman
Да ещё тут программа с нитями
Есть еще вариант с callback.
(это один из ранних)
Он мне больше нравится,
но, к сожалению, он не работает с Pulse Audio
из-за причудливых архитектурных взаимотоношений
этой ALSA с Pulse Audio.
Цитата:
Сообщение от Toman
В общем, большое спасибо: уже из того, что я успел прочитать в исходниках за первые 10-15 минут, я почерпнул много интересного и полезного для себя, при своём самом начальном уровне.
Ок, жду замечаний и всё такое.
Большая проблема - тембр.
Я его "делал" тупо перебирая различные формы сигнала.
Сейчас там используется гауссиана (на первом полупериоде колебания),
второй оставлен нулём. Звучит относительно сносно, но глуховато.
11.03.2012, 12:03
Dmitrii
Re: Синтезатор с чистым строем
Цитата:
Сообщение от xjiss
Проблема вот где
Нет, это не проблема.
11.03.2012, 13:55
xjiss
Re: Синтезатор с чистым строем
Цитата:
Сообщение от Dmitrii
Нет, это не проблема.
Имеется ввиду, что при генерации звука при помощи звуковой карты
нельзя сгенерировать, к примеру, пилу/менандр/etc с каким
угодно периодом (и, соответственно, с какой угодно частотой).
Период всегда будет кратен 1/F, где F - частота, на которой работает звучка.
Считать это проблемой или нет - это другой вопрос.
Если JI - то это как раз не проблема. )
А если темперации - тогда да, какбы проблема,
поскольку не получится абсолютно точно выдержать
интервалы. Хотя.. по мне это тем более не проблема )
11.03.2012, 16:35
Toman
Re: Синтезатор с чистым строем
Цитата:
Сообщение от xjiss
Период всегда будет кратен 1/F, где F - частота, на которой работает звучка.
Это только если задаться целью уложить период сигнала обязательно в целое число отсчётов. Да, может быть, так оно проще, и занимает меньше всего памяти для хранения пресинтезированного образца, насколько это возможно. И требует минимум процессорного времени на вычисление отсчётов в этих пресинтезирванных образцах. Но с другой стороны, когда речь идёт о таких частотах, где на период звука приходится десяток-другой отсчётов, а то и меньше - в общем-то не проблема пресинтезировать не один период такого звука, а достаточно много. Если мы для каждой ноты (считая, что каждая нота синтезируется отдельным генератором) будем синтезировать, скажем, столько периодов, сколько укладывается в 1 секунду, то мы можем в области сколь угодно высоких частот (вплоть до принципиального предела по частоте дискретизации) синтезировать частоты с шагом по крайней мере 1 Гц. А при желании - и с большей точностью, если синтезируемый период не делать равным точно 1 с, а немножко укорачивать или удлинять согласно нашим потребностям.
И вообще, всё это относится только к работе с пресинтезированным звуком. На лету же синтезировать можно звук вообще любой частоты - с такой точностью, какую позволяют сами вычисления на компьютере.
Разумеется, на высоких частотах при таком синтезе значения отсчётов будут как-то меняться с каждым периодом звука (а повторяться только с каждым синтезируемым периодом). Поэтому частоты вроде F/2 на самом деле очень проблематичны: из-за наличия всего лишь 2 отсчётов в периоде мы не можем двигать её по фазе, т.к. при этом будет фактически падать вплоть до нуля амплитуда. А значит, будут возникать сильные биения. Более-менее сносно работает синтез с нецелым числом отсчётов на период при числе отсчётов на период ближе к 3 (пусть даже немножко меньше) и более - это довольно близко аналогично той причине, по которой трёхфазные (или с бОльшим числом фаз) асинхронные электродвигатели лучше однофазных (которые даже не могут без посторонней помощи пуститься в определённую нужную сторону). Поэтому, собственно, реальная "рабочая" часть частотного диапазона ЦАПей и АЦПей должна довольно сильно не дотягиваться до F/2. Более-менее реалистичная оценка - это F/3 с небольшим. Ну т.е. для частоты дискретизации 48 кГц можно более-менее дотягиваться где-то до 16-18 кГц, а выше лезть уже не стоит. При этом необходимо при синтезе звука с высокими частотами (а значит, малым числом отсчётов на период) подразумевать, что значения отсчётов не должны быть мгновенными значениями используемой функции в данной точке, а должны быть средними за весь тот кусок функции, который они "представляют". Если это дело нарушить, то в самом деле будем иметь артефакты в виде биений с частотой f-F/n. А при точных значениях f=F/n, хотя и не будет биений, но тембр звука будет тем или иным образом искажаться, отклоняясь от запланированного.
11.03.2012, 17:12
xjiss
Re: Синтезатор с чистым строем
Цитата:
Сообщение от Toman
Это только если задаться целью уложить период сигнала обязательно в целое число отсчётов.
эээ... а как звучка может выдать _нецелое_ число отсчетов?....
Цитата:
Сообщение от Toman
И вообще, всё это относится только к работе с пресинтезированным звуком. На лету же синтезировать можно звук вообще любой частоты - с такой точностью, какую позволяют сами вычисления на компьютере.
Во-первых, честно говоря, не вижу разницы между real-time (на лету) и "заранее".
Во-вторых, не понимаю, как можно сгенерировать *дискретный по времени* сигнал любой частоты.
Давайте на тупом примере. Пусть у нас сигнал - меандр.
И пусть звучка работает на 48 кгц, то есть длительность одного сэмла
примерно 20 мксек (чуть больше, не важно).
Какую самую высокую частоту меандра можно получить?
Один сэмпл - типа 10000, второй - минус 10000.
То есть минимальный период - 40 мксек.
Соотвестсвенно, макс. частота - F/2
Следующий период - 3*20 = 60 мксек., частота - F/3
Ну и тд, чем больше, тем больше возможностей
для изменения скважности меандрика.
Но, пардон, как можно сгенерировать меандр с периодом
в 2.5 периода дикретизации?!?
Или в 100 с половиной?
---
Может, вы Фурьёвое преобразование имеете ввиду?
Так оно само по себе в дискретном виде неточно.
Скажем, если синус раскладывать, то одна гармоника
получится тогда и только тогда, когда будет взято целое
число периодов этого синуса.
11.03.2012, 20:12
Toman
Re: Синтезатор с чистым строем
Цитата:
Сообщение от xjiss
эээ... а как звучка может выдать _нецелое_ число отсчетов?....
Выдаст-то она целое число. Но период колебания не обязан быть целым. Грубо говоря, допустим, мы берём 1200 отсчётов (целое число) и укладываем туда 119 звуковых колебаний (можно было бы и 118,6543 уложить - нецелое число колебаний - но тогда будут проблемы со стыковкой, которая обязана происходить на нулевом уровне - если только специально плавно не уменьшать амплитуду до нуля перед окончанием сигнала). Имеем колебания с периодом 1200/119 отсчётов Просто по расположению отсчётов в периоде колебания и по величинам отсчётов периоды колебания не будут совпадать друг с другом. Но в силу обязательной фильтрации сигнала слышимой разницы это всё равно не даст (если сами отсчёты рассчитаны грамотно, как описано выше, по возможности близко к среднему, а не по мгновенным значениям).
Цитата:
Во-первых, честно говоря, не вижу разницы между real-time (на лету) и "заранее".
Разница в том, что, если считаешь сигнал на лету, и в т.ч. вычисляешь заново каждый отсчёт, то по вычислительной нагрузке совершенно никакой разницы, равно ли значение фазы нулю или какому-то другому значению, и равен ли период колебаний целому числу отсчётов. В любом случае ты честно вычисляешь каждый отсчёт из заданной начальной фазы, амплитуды, времени/номера отсчёта и выбранной функции для колебаний. От того, что величины отсчётов будут повторяться в точности на каждом периоде колебаний, нисколько не легче, т.к. ты их всё равно честно считаешь по-новой. И вырубить звук даже резко имеешь полное право в любой момент, когда значение отсчёта достаточно близко к нулю, чтобы не вызвать серьёзного щелчка (а ещё лучше - просто плавно, пусть и быстро, задавить синтезируемый звук по амплитуде - благо, нагрузки по вычислению это здесь не прибавит).
Ваша проблема вокруг целого числа отсчётов возникает именно при необходимости использовать предсинтезированные сэмплы, которые не могут пересчитываться и даже просто масштабироваться по амплитуде для плавного включения-выключения без щелчков. И поэтому обязаны быть на концах выровнены до нулевого уровня. И вот этот нулевой уровень, если мы его назначаем для начала периода колебаний, приводит к необходимости уложить целое число колебаний (и не обязательно единицу, как по Вашему тексту, а просто целое) в целое число отсчётов (потому что нецелое число отсчётов звуковуха выдать действительно не может), чтобы на концах иметь эти самые нули.
Цитата:
Пусть у нас сигнал - меандр.
Какую самую высокую частоту меандра можно получить?
Один сэмпл - типа 10000, второй - минус 10000.
То есть минимальный период - 40 мксек.
Соотвестсвенно, макс. частота - F/2
Но понимаете, в чём тут подвох: говорить о том, что мы хотим синтезировать меандр, мы могли бы только в том случае, если бы у нас были шансы вывести на аналоговый выход не только наш основной тон (синусоиду), но и какой-то хотя бы минимальный набор гармоник, которые, собственно, сделали бы наш сигнал приблизительно похожим на меандр. Но на частоте F/2, да что там, даже на F/3, например - у нас таких шансов и близко нет. Ближайшая же нечётная гармоника, 3-я, уже составляет частоту соотв. 3/2 F или F, и безусловно срезается выходным фильтром, т.к. всё, что выходит при цифроаналоговом преобразовании на таких частотах, рассматривается только как куча артефактов и мусора. Поэтому мы на таких частотах можем хотеть синтезировать только синусоиду :) И если выходной фильтр хороший, то что-то на синусоиду похожее и получится. Если плохой - то будет некий грязный тон на этой самой частоте. Даже если оно будет похоже на меандр, человек этого не услышит: не то что третья, а даже вторая и первая (основной тон) гармоники в данном случае находятся вне области слышимых частот. Впрочем, можно взять частоту дискретизации хоть 8 кГц, тогда у сигнала с частотой 4 кГц и при отсутствии выходного фильтра хотя бы 3-я гармоника 12 кГц попадёт в область слышимых частот (и 5-я 20 кГц - в область слышимых для некоторых людей, в основном только детей и подростков), и разница с синусоидой на слух таки будет. Но это именно если убрать положенный по штату фильтр, обязанный срезать слишком высокие частоты.
Цитата:
Но, пардон, как можно сгенерировать меандр с периодом
в 2.5 периода дикретизации?!?
И мы опять не можем хотеть на такой частоте никакого меандра! Потому что опять же все гармоники кроме первой (основного тона) будут заведомо срезаны выходным фильтром. Поэтому спокойно берём, например, 5 отсчётов, и кладём на них 2 периода колебаний, получаем искомое.
Цитата:
Или в 100 с половиной?
Аналогично: кладём на 201 отсчёт 2 периода колебаний. Т.е. если у нас есть возможность использовать не единственный период колебаний, возможная точность приближения к нужной нам частоте улучшается. Чем больше периодов, тем больше улучшается.
Цитата:
Может, вы Фурьёвое преобразование имеете ввиду?
Вообще-то не хотелось его касаться, но можно хотя бы и через него зайти.
Цитата:
Так оно само по себе в дискретном виде неточно.
Скажем, если синус раскладывать, то одна гармоника
получится тогда и только тогда, когда будет взято целое
число периодов этого синуса.
Ну вот, и тут, в том же Фурье, сами же говорите, достаточно именно целого числа периодов, а вовсе не обязательно единицы. Хотя в общем и непонятно, при чём тут Фурье, но и синтез по гармоникам, разумеется, возможен таким образом, как частный случай для периодических функций вообще, если целое число периодов ляжет на целое число отсчётов. А если у нас есть возможность аккуратно задавить в ноль начало и конец звука, то даже число периодов не обязано быть целым для любых практических целей, в т.ч. для музыки.
11.03.2012, 20:41
Toman
Re: Синтезатор с чистым строем
А воообще, то, что описано по ссылке, это по сути основано на "У-тональности" (U-tonality), т.е. выбор тонов из набора "унтертонов" некоего (не обязательно реально существующего) базового производящего тона. Оно же на некоторых сайтах микротоналистов или любителей альтернативных настроек называется "равномерное деление струны". Т.е. это принцип, в некотором смысле обратный используемому при построении натуральной (О-тональной, т.е. основанной на обертонах) гаммы. При этом оказывается, что минорное трезвучие, например, является фактически У-тональным эквивалентом мажорного трезвучия, относящегося к О-тональному "миру".
У меня есть некоторые предположения о том, что У-тональные гаммы в принципе кое-где генерируются в природе (ну, точнее, не то чтобы прямо в природе, но не по специальному на то устремлению музыканта или создателя муз. инструмента) - а именно, я предполагаю, что именно по какой-то У-тональной гамме, возможно, расположены звуки, издаваемые "поющими поездами" на свежеотшлифованных рельсах.
11.03.2012, 22:15
xjiss
Re: Синтезатор с чистым строем
Цитата:
Сообщение от Toman
Аналогично: кладём на 201 отсчёт 2 периода колебаний. Т.е. если у нас есть возможность использовать не единственный период колебаний, возможная точность приближения к нужной нам частоте улучшается. Чем больше периодов, тем больше улучшается.
Если я один период не могу точно задать, то я и два не могу задать )
Как мы будем укладывать период в 100.5 отсчётов на 201 отсчёт?
Полупериод у нас будет 50 с четвертью, этого мы сделать не можем.
На 201-ом отсчёте нам надо уложить 2 периода.
Полупериоды у нас есть целое число периодов дискретизации
и никак иначе.
Пусть первый полупериод будет 50 тактов,
второй ну пусть тоже 50. Пусть третий опять 50.
Тогда 4-ый будет длится 51 период дискретизации.
И получится у вас не 2 периода меандра с периодом 100.5,
а два периода ДВУХ РАЗНЫХ меандров, склейка из двух меандров (по разику)
с разными частотами. Так что моя пока не согласная. ))
11.03.2012, 22:50
xjiss
Re: Синтезатор с чистым строем
Цитата:
Сообщение от Toman
Просто по расположению отсчётов в периоде колебания и по величинам отсчётов периоды колебания не будут совпадать друг с другом.
Вот-вот-вот. Тогда и о периоде (строгом повторении во времени) речи быть не может.
Тем-то и хорош чистый строй, что на компе он делается математически точно
(с заранее известными исключениями). Вы глядели же в сорцы, там для периода тоники
выбрано 720 (соответствует 66.(6)Hz при 48kHz). Ну так если мы возьмем для соль 720*(2/3),
мы получим опять же целый период звука в 480 периодов дискретизации.
И этот период будет соблюдаться
с точностью до глюков кварца, которым звучка тактируется,
то есть практически мы поимеем акустически чистую квинту.
И это (чистота строя) вообще никак не зависит от формы сигнала.
В проге у меня не синус и не меандр, но это по совсем другим
соображениям - для многих комбинаций нот наимененьшее общее
кратное получается столь большим, что аккорд может звучать
по 30 сек и то и похлеще.
Впрочем, голый синус звучит уж совсем тускло,
а меандр - слишком жестоко для ушей.
Плюс проблемы производительности - долгий аккорд он и генерируется
дольше, поэтому можем поиметь underrun - ALSA уже готова принять
от нас следующую порцию звука, а мы всё еще копошимся с расчетами.
Поэтому эти долгие аккорды я генерю относительно небольшими кусками.
Но тут мы напарываемся на другую проблему - щелчки.
Они возникают или не возникают в зависимости от того,
в какой момент были отжаты кнопки - если попали на момент,
когда уровень сигнала был высокий, он обрывается, потом начинается
с нуля - вот и щелчок.
Поэтому у меня большая часть периода - вообще 0)
Но до конца от шелчков избавится всё равно не получилось.
Такая вот печаль )
12.03.2012, 14:02
Toman
Re: Синтезатор с чистым строем
Цитата:
Сообщение от xjiss
Если я один период не могу точно задать, то я и два не могу задать )
Как мы будем укладывать период в 100.5 отсчётов на 201 отсчёт?
Полупериод у нас будет 50 с четвертью, этого мы сделать не можем.
Полупериоды у нас есть целое число периодов дискретизации
и никак иначе.
Вот я всё не понимаю, для чего такая точность-то? Час от часу не легче, теперь уже не только период, но полупериод зачем-то стало надо, чтобы был целым числом отсчётов. И поэтому вы зачем-то предлагаете делать полупериоды разной длины. Если синтезатор предназначен для людей (а не летучих мышей или просто мышей, которые слышат в несколько раз более высокие частоты, чем люди), то даже в вашем экстремальном случае меандра никто не услышит разницы между случаем, когда +1 сменяется на -1 прямо в соседнем отсчёте, и когда он сменяется через один отсчёт (через нулевой, например - тогда можно считать положение границы смещённым ровно на половину отсчёта, или какой-то ненулевой - тогда это м.б. смещение границы на четверть отсчёта или ещё на сколько-то). Например, при выводе изображений на экран представляете себе, что такое антиалиасинг, что такое оверсемплинг? Какой смысл выравнивать, например, величину какого-то изображения по пикселам, если или пикселы столь малы, или пользователь отошёл от экрана (или намеренно аппаратно размыл изображение) так, что в принципе не видит отдельных пикселов? На наших современных мониторах, правда, до этого ещё далеко (если смотреть на него с более-менее общепринятого расстояния), но вот если бы пиксел был величиной не 0,25 мм, а, скажем, 2,5..3 раза меньше - 0,08..0,1 мм - то отдельные пикселы реально были бы не видны. Вот со звуком при современных частотах дискретизации (48 кГц, или даже старый стандарт 44,1 кГц) это уже так.
А поскольку при изображении какого-либо более-менее практически осмысленного звука (в частности, который могут осилить обычные динамики) смена полярности сигнала в пределах 1-2 отсчётов и подавно не нужна, то даже этой теоретически заметной (только на спец.динамиках, и только для летучей мыши, и, возможно, при внесении специальных изменений в выходной фильтр) разницы между прохождением границы периода (или полупериода) не будет. Если же рассчитывать на работу с летучими мышами, то тут опять же не надо изобретать что-то особенное, а просто использовать бОльшие частоты дискретизации и звуковую карту с соответствующим фильтром, который не будет резать нужные нам (или, точнее, мышам) частоты.
По всем этим причинам, я не вижу вообще никаких проблем сделать хоть период, хоть полупериод длиной хоть 100,5, хоть 50,25, хоть сколько угодно отсчётов (точность тут ограничивается сочетанием частоты дискретизации и плотности ступеней оцифровки по амплитуде (напр., практическое число бит в отсчёте), но это ограничение, опять же намного превосходит любые практические надобности).
12.03.2012, 15:20
xjiss
Re: Синтезатор с чистым строем
Цитата:
Сообщение от Toman
Вот я всё не понимаю, для чего такая точность-то?
Час от часу не легче, теперь уже не только период, но полупериод
зачем-то стало надо, чтобы был целым числом отсчётов.
Дело не в том, что "надо", а в том, что по-другому
при цифровом синтезе просто не получается.
Цитата:
Сообщение от Toman
И поэтому вы
зачем-то предлагаете делать полупериоды разной длины.
Да это не я предлагаю, я просто подробно расписал,
что получится, если попытаться уложить два колебания
с реальным периодом в 100.5 тактов дискретизации
на 201 этих тактов.
Ну вы просто представьте (ну или не представьте,
а сделайте), что вы заполняете массив цифирками.
Всего у вас в массиве 201 элемент.
Пусть верхняя полка меандра - это +1, а нижняя - -1.
Какие отсчеты вы сделаете равными +1, а какие равными -1?
Тут как ни крути, получится что-то вроде того, что,
первые 50 отсчетов будут +1, потом 50 -1, потом еще 50 снова
+1 и оставшиеся 51 -1.
Ну не делится 201 на 4 нацело, не делится! :)
Что мы имеем в итоге?
Вместо 2 колебаний с периодом в 100.5 тактов
мы имеем одно колебание (1 его период) с периодом
100 тактов и второе - с периодом 101.
Но никак не два по 100.5!!!
Иными словами, невозможно сгенерить меандр с периодом,
равным нецелому числу тактов дискретизации.
Вместо этого у вас получится чередование колебаний
по 100 и по 101-му такту.
Я не веду речи про то, что там будет после ЦАПы,
фильтров, усилителей и т.д. Это уже совсем другая
история. Я также ничего не говорю про то, что мы будем
слышать. Я всего лишь говорю, что на этапе "рисования"
звука (то есть заполнения массива отсчетов циферками)
ну просто никак не сделать так, чтобы ... гхы,
запополамить один отсчет ). Ну цифра же! Время - дискретно,
его "квант" - период дискретизации. Не можно сделать так,
чтобы пол-периода дискретизации было одно значение уровня сигнала,
а другие пол-периода - другое.
Насчёт точности.
Еще раз - комп позволяет идеально (с точностью до стабильности работы кварца)
сделать то, что называется "чистым строем".
Если же брать темперированные строи, сделать их на компе
идеально точно не получится, поскольку отношения частот
в таких строях - иррациональные, а у нас тут, понимаешь,
период никак не может быть нецелым.
Разумеется, идеальная точность на практике не особа и нужна,
я не спорю.
Но для чистого строя-то это возможно!!!
Так почему бы и нет?...
Цитата:
Сообщение от Toman
Если синтезатор
предназначен для людей (а не летучих мышей или просто мышей, которые
слышат в несколько раз более высокие частоты, чем люди), то даже в вашем
экстремальном случае меандра никто не услышит разницы между случаем,
когда +1 сменяется на -1 прямо в соседнем отсчёте, и когда он сменяется
через один отсчёт (через нулевой, например - тогда можно считать
положение границы смещённым ровно на половину отсчёта, или какой-то
ненулевой - тогда это м.б. смещение границы на четверть отсчёта или ещё
на сколько-то)
Ого. Даже вот как. На четверть периода дискретизации...
Ну вот как вы будете укладывать наши 2 меандрических
колебания с реальным периодом в 100.5 тактов в 201 этих тактов,
чтобы "сместить" чего-то там на "четверть отсчёта"?!?!?
Покажите массив, заполненный цифирками?... Тут неважно, сколько
вы периодов меандра возьмете. У Вас на первом же,
НА ПЕРВОМ ЖЕ периоде получится не 100.5, а 100, 99 или 101 ,)
Так ведь?..
Про "экстремальный" случай меандра.
Ну, во-первых, ничего экстремального в этом нету,
в любом triple oscillator оно есть :)
Я взял для примера меандр только потому,
что на нём сразу видно, что период может
быть только k*T, где k - натуральное число,
T - период дискретизации.
С другими формами сигналов - ровно та же история,
просто, например, для синуса это какбы не бросается в глаза,
надо на каждый отсчетик в отдельности посмотреть, чтобы
увидеть, что период то у нас получился вовсе и не такой,
какой задумывали.
Цитата:
Сообщение от Toman
По всем этим причинам, я не вижу вообще никаких проблем сделать хоть
период, хоть полупериод длиной хоть 100,5, хоть 50,25, хоть сколько
угодно отсчётов (точность тут ограничивается сочетанием частоты
дискретизации и плотности ступеней оцифровки по амплитуде (напр.,
практическое число бит в отсчёте), но это ограничение, опять же намного
превосходит любые практические надобности).
Окей.
С Вас массив размеров в 201 отсчет, заполненный +1 и -1 так,
чтобы получилось два колебания меандра, причем оба длительностью
ровнехонько в 100.5 ячеек массива ,)
12.03.2012, 16:30
Toman
Re: Синтезатор с чистым строем
Цитата:
Сообщение от xjiss
Дело не в том, что "надо", а в том, что по-другому
при цифровом синтезе просто не получается.
Это лично у вас не получается, а так, вообще, у всех получается, с той точностью, которую человек вообще в состоянии воспринять. Я не понимаю, зачем нужно идти на такие жертвы, вполне заметные на слух, вплоть до почти что единственной строго фиксированной высоты, от которой можно построить желаемый строй, или каких-то бешеных (не регулируемых исполнителем, фактически) продолжительностей звучания аккордов, ради каких-то сугубо формальных вещей, которые никто на слух не почувствует. Ну не пересчитывает никто на слух отсчёты в периоде колебаний динамика, понимаете...
Цитата:
С Вас массив размеров в 201 отсчет, заполненный +1 и -1 так,
чтобы получилось два колебания меандра, причем оба длительностью
ровнехонько в 100.5 ячеек массива ,)
Да вроде у нас ажно 65535 возможных значений (если пунктуально брать только имеющие симметричные относительно нуля, т.е. не считать -32768). Зачем ограничивать себя при этом только двумя числами? Даже, как минимум, между +1 и -1 есть ноль, если на то пошло.
12.03.2012, 18:42
xjiss
Re: Синтезатор с чистым строем
Цитата:
Сообщение от Toman
Это лично у вас не получается, а так, вообще, у всех получается, с той
точностью, которую человек вообще в состоянии воспринять. Я не понимаю,
зачем нужно идти на такие жертвы, вполне заметные на слух, вплоть до
почти что единственной строго фиксированной высоты, от которой можно
построить желаемый строй,
Вы программульку-то попробовали, кстати?
Вот возьмите, замените в ней период тоники
с 720 на, скажем, 727. И вы очень даже услышите,
что весь строй разъехался.
Господи, о каких "жертвах" вы говорите?
Я всего-то хотел написать прожку,
которая будет играть в чистом строе.
Чтобы ежели квинта - так чтобы 3/2 и никак иначе!
Ежели кварта - вынь да положь 4/3 и никак иначе!
Ежели б.терция - чтоб 5/4 и никак иначе!
И вот такой строй на компе-то как раз можно сделать
абсолютно точно! Так почему бы не сделать? :)
Но самый низкий тон тут не может быть произвольным.
720 тактов дискретизации - наиболее оптимальный выбор.
Вы поменяйте, поменяйте в проге-то...
Или вы хотите устроить дискашшн на тему
"Just Intonation vs. Equal Temperament"?
Ну уж нет, увольте! :) Преимущества и того, и другого всем,
кто интересовался, уже лет как 200 известны.
12TET уже изъежжен вдоль и поперек, тут больше нечего
делать. А дальше-то что? Будем продолжать тесниться
в 12-ти полутонах в октаве? Искать более хорошие
приближения терций, используя не 12, а 53 нотки в октаве?
Тогда 53TET сразу заполучает жуткий недостаток,
за который ругают чистый строй - а именно, слишком
дофигища кнопочек в октаве. Так раз так, то почему
бы не вернуться к чистому строю? Кнопок в октаве опять
же много, но зато не надо изголяться над терциями и т.п.
Они по определению будут такими как надо.
На этом диспут на тему "Just Intonation vs. Equal Temperament"
закончен. :)
Цитата:
Сообщение от Toman
или каких-то бешеных (не регулируемых
исполнителем, фактически) продолжительностей звучания аккордов
Вы, наверное, не совсем меня поняли.
Так было в одной из самых ранних версий программы,
щас в этом плане всё в порядке. Да Вы попробуйте наконец же! :)
Цитата:
Сообщение от Toman
ради каких-то сугубо формальных вещей, которые никто на слух не почувствует.
Ну не пересчитывает никто на слух отсчёты в периоде колебаний динамика,
понимаете...
Разумеется.
Зато все очень хорошо слышат биения, например...
Цитата:
Сообщение от Toman
Да вроде у нас ажно 65535 возможных значений (если пунктуально брать
только имеющие симметричные относительно нуля, т.е. не считать -32768.
Зачем ограничивать себя при этом только двумя числами? Даже, как
минимум, между +1 и -1 есть ноль, если на то пошло.
Так я жеж про меандр толкую жеж!
Как с меандром разберемся, пойдём дальше,
пилой, например, займёмся.
Про обыкновенный простой тривиальный меандр.
Под +1 и -1 имел ввиду значения сигнала
на верхней и ниэней полках меандра, соответственно.
Не нравится плюс-минус 1? Ок, ок, давайте возьмем
плюс-минус 16384.
Итак, повторяю, чего мне от Вас хочется.
Покажите мне 201 (двести один) отсчёт, в которые уложены
2 прямоугольных колебания периодом 100.5 тактов дискретизации
Какие именно из этих 201-го отсчёта будут равны 16384,
а какие - -16384?
Если взять бумажку в клеточку (одна клеточка = период дискретизации)
и нарисовать эти 2 колебания на 201-ой клеточке, то вы всё сразу
увидите! Но только специально напоминаю - короче одной клеточки
какое-то значение сигнала длится не может. Так ведь, да?
Ну вот когда вы всё это нарисуете, то сразу же и увидите,
что первые 50 отсчетов у вас будут 16384, затем 50 отсчетов
по -16384, затем опять 50 по 16384 и наконец, оставшиеся 51
снова -16384.
Если на эту картинку пристально посмотреть, то опять же
можно легко увидеть, что у получилось у нас не два колебания
(прямоугольных) с периодом 100.5 тактов дискретизации,
а одно с периодом 100 и второе - с периодом 101.
Ы?
Из чего явственно следует, что состряпать меандр с периодом
100.5 тактов дискретизации - невозможно. Просто тупо в силу
того, что имеется некий минмальный промежуток времени,
в течение которого сигнал на выходе ЦАПы - постоянный.
А Вы упорно утверждаете, что возможно.
Ну так покажите мне наконец-то уже отсчёты в количестве 201-го,
в которые Вы уложили 2 периода прямоугольного колебания
такого, что его "реальный" период - 100.5 тактов дискретизации.
Уже третий раз ведь прошу...
12.03.2012, 22:23
xjiss
Re: Синтезатор с чистым строем
Кстати, насчет чего там ухо различает или не различает.
Не поленился сделать 2 файлика.
1
Меандр с периодом 100 тактов звучки (50/50)
2
Чередование меандров по 100 (50/50) тактов и по 101-му (50/51)
Разница на слух есть.
12.03.2012, 23:22
Toman
Re: Синтезатор с чистым строем
Цитата:
Сообщение от xjiss
Вы программульку-то попробовали, кстати?
Ещё нет - пока только читаю сорцы, чтобы понять, что там и как. И офигеваю... То есть, с точки зрения чисто технической - всё вроде нормально. Т.е. программа (по крайней мере у вас на компьютере) работает, звук синтезирует и выводит на нужной частоте - это хорошо. Но вот способ, которым этот звук синтезируется - это просто атас. Причём там есть странные вещи, даже если исходить из вашего постулата о необходимости точной периодичности с точностью до конкретных отсчётов и цифр у каждого индивидуального сигнала. Но про эти моменты - немножко позже.
Цитата:
Вот возьмите, замените в ней период тоники
с 720 на, скажем, 727. И вы очень даже услышите,
что весь строй разъехался.
Ну, с вашей целочисленной арифметикой - конечно, разъедется. Вы же фактически аппроксимируете любую ноту унтертонами частоты дискретизации. Не то чтобы этот подход был чем-то принципиально плох - но для его использования надо не на компьютере это делать, а строить аналоговый синтезатор или даже электромеханический орган. Собственно, они (электромеханические органы), НЯП, примерно таким образом и строились. Ну или если бы была возможность с удобством произвольно перестраивать частоту дискретизации на звуковой карте. Но ведь такой возможности нет, поэтому такая манера работы с цифровым звуком является нештатной. Потому как звуковые карты создавались для работы со звуком любых частот в пределах оговоренного спектра, и всё в ней (в аппаратной части, в том числе) рассчитано именно на это.
Цитата:
И вот такой строй на компе-то как раз можно сделать
абсолютно точно! Так почему бы не сделать? :)
И опять вопрос: зачем вам именно абсолютно точно? Чем не устраивает результат, который на слух никак не будет отличим от абсолютно точного (но при этом может быть настроен на любой тон, а не только от 720 отсчётов)?
Цитата:
Но самый низкий тон тут не может быть произвольным.
720 тактов дискретизации - наиболее оптимальный выбор.
Вы поменяйте, поменяйте в проге-то...
А почему бы целочисленный период не поменять на нецелочисленный? Разумеется, не просто так поменять тип переменной, а соответствующим образом переделав всю схему синтеза звука.
Цитата:
Или вы хотите устроить дискашшн на тему
"Just Intonation vs. Equal Temperament"?
Вот уж чего мне совершенно неинтересно делать - так это на такую тему ругаться. Тем более, что, чтобы начать ругаться, мне пришлось бы долго чесать репу, и придумывать, какую бы из сторон тут занять. Меня вообще-то интересуют разные строи, хотя бы просто с точки зрения побаловаться. Чистый - в том числе. И непосредственно унтертоновый как таковой - тоже интересует (отдельные ступени которого (точно подходящие по соотношению частот) вы фактически используете для построения чистого страя). Но вот делать принципиально неперестраиваемый софтовый синтезатор под чистый или под унтертоновый строй - это уже какая-то жесть. Но я бы это (целочисленность и неперестраиваемость) ещё понял, если бы там действительно были предвычисленные (один раз, при запуске программы) периоды, которые бы просто включались/выключались (прибавлялись к общему звуку или игнорировались) по клавишам. Тогда да, целочисленность нужна, т.к. просто так сложить по значениям можно только выровненные по времени отсчёты. Но у вас же при каждом новом сочетании звуков (ноте или аккорде) всё это вычисляется заново. Непонятно, зачем - можно же было бы действительно заранее вычислить все ноты по-отдельности, и во время игры уже только складывать их. Сложить N готовых целых чисел (по числу нот в текущем аккорде) как бы побыстрее будет, чем N же раз вычислять 5000*(exp(-(x*x)/period)) (т.е., на минутку, 2 умножения, 1 деление и одна экспонента, пусть она даже при компиляции и не становится настоящим вызовом функции, а "выписывается" прямо на месте в машинном коде - всё равно эта экспонента - дело довольно тяжёлое вычислительно), а потом всё равно ещё преобразование плавающего в целое, и, наконец, сложение. Вот вы сколько лишней вычислительной работы делаете по каждому нажатию клавиши. Если бы вы её не делали, а всё предвычисляли - я бы ещё понял, повторюсь, целочисленные ограничения. Но при таком раскладе, когда по каждому нажатию столько раз пересчитывается всё заново, можно было бы уже расслабиться, и честно вычислять вообще каждый отсчёт (без повторного использования буфера, то есть). Всё равно же вычислительные затраты вас, как видно, не сильно беспокоят 8)
Цитата:
Вы, наверное, не совсем меня поняли.
Так было в одной из самых ранних версий программы,
щас в этом плане всё в порядке. Да Вы попробуйте наконец же! :)
А выдавать сигнал с постоянной составляющей (не просто с постоянной, а вообще все ненулевые отсчёты одного знака) - это как вообще, нормально так? По-моему, это, мягко говоря, совсем не здорово. И если так делать, то оно и неудивительно, что будут щелчки. Постоянное напряжение, наряду с просто очень низкими частотами, конечно, фильтруется звуковой картой, но низкочастотный "щелчок" (тут уж лучше сказать "толчок", наверное, в силу низкой частоты) - как раз в районе частоты среза этого фильтра - вам обеспечен как при начале, так и при конце звучания любой ноты, даже если она состыковалась с тишиной по нулю, т.е. без высокочастотного щелчка.
Так что пробовать я буду, пожалуй, только когда придумаю, как разрулить хотя бы вот этот момент с постоянной составляющей, как минимум.
Цитата:
Разумеется.
Зато все очень хорошо слышат биения, например...
Боитесь, вам точности типа double, например, не хватит, чтобы никто не услышал биений, что обязательно нужно рациональную дробь из настоящих целых чисел (в виде реальных физических отсчётов на звуковой карте) сооружать? Я уверен, что такие опасения напрасны, причём с очень-очень большим запасом.
Цитата:
Итак, повторяю, чего мне от Вас хочется.
Покажите мне 201 (двести один) отсчёт, в которые уложены
2 прямоугольных колебания периодом 100.5 тактов дискретизации
Какие именно из этих 201-го отсчёта будут равны 16384,
а какие - -16384?
Я ещё раз повторю: звуковые карты создавались для работы с произвольным звуком путём приближения, а не для асбстрактных меандров и т.п. И там стоит выходной фильтр, который вам уже в аналоговой выходной линии (намеренно!!! специально для этого и стоит!) переход от 16384 к -16384 размажет на время, соответствующее этак почти что паре отсчётов. Поэтому ограничиваться этими двумя числами совершенно неинтересно и физически бессмысленно. Вы можете совершенно спокойно использовать кусочек, например, вида ( 16384, 0, -16384), или ( 16384, 6492, -16384), или с любым другим числом в промежутке между. Это есть, с точки зрения конструкции звуковой карты, штатный способ приближения для меандра, у которого теоретический момент перехода не попадает точно между отсчётами. Первая картинка, с нулём - это случай, когда теоретический переход попал точно посередине соостветствующего отсчёта. Второй вариант - это когда не посередине, а где-то в стороне. В частности, для того случая, который вы приводите для примера, полупериод занимает 50.25 отсчётов. Если мы изначально начнём полупериод выровненным по началу первого отсчёта, то будем иметь 50 отсчётов значением +16384, потом отсчёт, у которого 1/4 приходится на значение +16384, а 3/4 - на -16384. Нехитрой арифметикой получаем из этого, что значение этого, 51-го, отсчёта, будет равно -8192 (в данном случае даже не пришлось округлять до целого, ну а в произвольном случае было бы округление - т.е. ошибка плюс-минус 1/2 "ступеньки" при скачке на 32768 в данном случае - т.е. сущая чешуя). Следующий полупериод такой же длины - 50.25 отсчётов. Из которых 0.75 отсчёта у нас уже есть, поэтому мы делаем 49 отсчётов с уровнем -16384, а дальше идёт отсчёт, делящийся ровно пополам между плюсом и минусом, и потому имеющий значение 0. Дальше всё происходит симметрично: ещё 49 отсчётов с уровнем +16384, потом 1 отсчёт с уровнем +8192, потом 50 отсчётов с уровнем -16384. И дальше пошёл новый (целочисленный, в данном случае) период, начинаясь ровно с +16384. Итак, считаем отсчёты: 50+1+49+1+49+1+50=201. Два периода в 201 отсчёт уложены, причём и оба периода равны друг другу, и все полупериоды тоже равны друг другу. Да, наверное, с вашей точки зрения это не есть меандр, потому что использованы 3 каких-то "левых" промежуточных значения. С практической же точки зрения, после того, как фильтр отутюжит все "правильные" переходы, вместе с "неправильными", какой-то заметной разницы между "правильными" и "неправильными" не останется. На месте "правильного" будет, допустим (если взять аналоговый сигнал и попробовать оцифровать обратно), что-то вроде 16000, 12000, -12000, -16000. А на месте "неправильного" (того, который посередине) - что-то вроде 16000, 15000, 0, -15000, -16000. А никакой чёткой ступеньки уже не будет всё равно, как ни старайся - так что напрягаться на эту тему просто нет практического смысла.
Цитата:
Но только специально напоминаю - короче одной клеточки
какое-то значение сигнала длится не может. Так ведь, да?
Ну вот вы видели, как я делил один отсчёт между разными полками меандра - хоть поровну, хоть по четверинкам, хоть как придётся. Типичный АЦП, скажем, получив на вход сигнал, фронт которого не попал точно между отсчётам, поступил бы в точности так же. И если мы имеем право записывать звуки или иные аналоговые сигналы из реального мира при помощи таких АЦП, то и при синтезе искуственного сигнала совершенно естественно эмулировать поведение того же АЦП. Я просто не вижу практической проблемы на этом месте. Именно для этого частоты дискретизации звуковых карт (или каких-нибудь сигнальных процессоров) и повышают - чтобы превысить "разрешающую способность (по времени)" уха человека, и спокойно антиалиасить и размазывать (в т.ч. аппаратно) любые скачки, а вовсе не для того, чтобы у кого-то волшебный период в 720 отсчётов в области инфразвуков не оказывался :)
13.03.2012, 05:29
Toman
Re: Синтезатор с чистым строем
Цитата:
Сообщение от xjiss
Чередование меандров по 100 (50/50) тактов и по 101-му (50/51)
Разница на слух есть.
Я вот не слышу особо, кстати. Ну т.е. по спектру понимаю, что примерно "должен" слышать - некий темброво богатый звук на октаву ниже целевого. Но его громкость столь мала, видимо, что целевым звуком маскируется напрочь. По крайней мере, через мои домашние колонки, и при моём личном относительном восприятии силы звуков разной высоты. Может быть, для кого-то это и не так.
...Попробовал модифицировать второй вариант именно так, как описал выше. Если посмотреть на спектр результата - то спектра все лишние гармоники почти исчезли, однако, конечно, вылезают наверху. Но это чисто цифровой анализ, т.е. он не совсем отражает спектр того аналогового сигнала, который выходит. Вероятно, если соответствующим образом ещё чуть сгладить оставшиеся острые фронты, от этих гармоник останутся вовсе жалкие следы (правда, и "правильные" гармоники тоже уйдут в верху спектра - но выше 14-15 кГц я в общем-то вряд ли чего слышу, а если кому эта разница принципиальна - повышайте частоту дискретизации).
...Наконец, собрал и попробовал программу в действии. Во-первых, самое главное - у меня она тоже работает, и это хорошо, ура. Попробовал придумать какую-нибудь другую форму волны - но чтобы была симметричной относительно нуля (вообще говоря, меня интересует симметричность только в смысле того, чтоб постоянной составляющей не было, чётность/нечётность функции роли не играет, но я не делал её специально какой-то "художественно кривой", а просто собрал из трёх синусов, но не простых синусов, а в трёх разных степенях - 1-й, 3-й и 5-й, и, соответственно, взятых от соответствующей же степени координаты):
Код:
float a, s5, s3, s1, x;
//...
x = (2.0*(float)phase/(float)period-1.0);
s5 = sin(M_PI*(x*x*x*x*x+1));
s3 = sin(M_PI*(x*x*x+1));
s1 = sin(M_PI*(x+1));
a = 2200*s5*s5*s5*s5*s5+2200*s3*s3*s3+600*s1;
sample += a;
Тембр, конечно, другой, но в принципе тоже возможный вариант. В каких-то регистрах кажется пожёстче звучащим, в каких-то других - наоборот, помягче. А постоянного смещения, надеюсь, теперь нет.
А вот про собственно строй позволю себе таки немножко поругаться. Попробовал сыграть небольшую простенькую фразу, которую когда-то сочинил ещё в школьные годы (на фоно). Тем более, что тембр (оба варианта) практически идеально подходит для того, как изначально задумывалась фраза (пианино было лишь неизбежной на то время заменой, за неимением даже синтезатора, не говоря уж об ансамбле из 3-5 духовых вроде практис-чантеров или крумхорнов). Фраза вся на белых клавишах, причём использует все 7 нот, т.е., вероятнее всего, тональность там "наша". Но тут же нарываюсь на кривущие терцию и квинту (звучащие там как гармонические интервалы) от ре. Потом обнаруживаю ещё по ощущениям довольно кривую при движении по мелодии секунду ля-си. Ну т.е. это достаточно серьёзная проблема. Так что при попытках использовать чистый строй или что-то близкое множество клавиш для разных случаев - неизбежны, имхо. Причём поставить эти клавиши на клавиатуре даже в принципе можно было бы - если отказаться от части "черноклавишных" нот, неактуалных для конкретного произведения.
Другая проблема (в случае данной фразы - даже бОльшая, чем кривые интервалы) - сыграть эту фразу в виде, похожем на то, как оно играется на фоно (или как это должен был бы играть ансамбль) - невозможно, потому что нужные аккорды с октавным удвоением попадают под запрет, приходится урезать практически до двухголосного, что звучит намного хуже...
13.03.2012, 15:11
xjiss
Re: Синтезатор с чистым строем
Toman, прежде всего, большое спасибо за критику.
В качестве, так сказать, оправдания, скажу, что
я ни в коей мере не спец по синтезу звука;
кроме того, программу я писал в новогодние каникулы,
пару недель, в состоянии хронического алкогольного
отравления средней степени тяжести :)))
Цитата:
Сообщение от Toman
Ещё нет - пока только читаю сорцы, чтобы понять, что там и как. И
офигеваю... То есть, с точки зрения чисто технической - всё вроде
нормально. Т.е. программа (по крайней мере у вас на компьютере)
работает, звук синтезирует и выводит на нужной частоте - это хорошо.
Реально она проверялась на 4-х различных компах
1) какой-то ноутбук, которого я не видел, с Ubuntu
(из-за этой Ubuntu, кстати, я и отказался от варианта
с функцией обратного вызова - он не работает с Pulse Audio,
который в той Убунте по умолчанию ставится; перешел на вариант
с 2-мя нитями)
2) относительно старый PC с Debian Lenny
3) относительно новый PC с Debian Squeeze
4) древняя кастрюля (P-какой-то 400 MHz) с Debian Squeeze
Звучки везде вроде как встроенные, Intel.
Цитата:
Сообщение от Toman
Но вот способ, которым этот звук синтезируется - это просто атас. Причём
там есть странные вещи, даже если исходить из вашего постулата о
необходимости точной периодичности с точностью до конкретных отсчётов и
цифр у каждого индивидуального сигнала. Но про эти моменты - немножко
позже.
Ок, буду весьма признателен.
На остальное отвечу в следующем/следующих сообщениях.
13.03.2012, 15:55
xjiss
Re: Синтезатор с чистым строем
Цитата:
Сообщение от Toman
Ну, с вашей целочисленной арифметикой - конечно, разъедется. Вы же
фактически аппроксимируете любую ноту унтертонами частоты дискретизации.
Ну можно и так сказать, наверное.
Только не "аппроксимирую", а "использую".
Там ничего никуда не аппроксимируется, там все абсолютно точно.
Период самого низкого тона задан (720),
а дальше от него танцуем - например, 720*(4/5) = 576,
чистая б.терция (ми) и т.п. Некоторые тоны в верхних октавах
получаются нечистыми, но тут уж ничего не поделаешь.
Цитата:
Сообщение от Toman
И опять вопрос: зачем вам именно абсолютно точно?
1)
Мне это нужно ПО ОПРЕДЕЛЕНИЮ ЧИСТОГО СТРОЯ. ПО ОПРЕДЕЛЕНИЮ.
Программа как называется? :)
Just Intonation Synthesizer.
Для этого и нужно абсолютно точно, чтобы контент соответствовал
названию.
2)
Для чистого строя это МОЖНО сделать.
Если бы мне взбрендило использовать 12TET, тогда
да - начихал бы я тогда на точное соблюдение интервалов.
Цитата:
Сообщение от Toman
А почему бы целочисленный период не поменять на нецелочисленный?
Разумеется, не просто так поменять тип переменной, а соответствующим
образом переделав всю схему синтеза звука.
Брр, какой еще тип переменной?
Индекс массива - он был, есть и будет целым.
Вы про тип, используемый для отсчетов?
Он тут вообще ни причем, мы ведем речи про периоды
и про частоты, то есть точность по времени, а не по уровню
сигнала.
Цитата:
Сообщение от Toman
Вот уж чего мне совершенно неинтересно делать - так это на такую тему
ругаться.
Фух... это хорошо! )
Цитата:
Сообщение от Toman
Но у вас же при каждом новом сочетании
звуков (ноте или аккорде) всё это вычисляется заново. Непонятно, зачем -
можно же было бы действительно заранее вычислить все ноты
по-отдельности, и во время игры уже только складывать их.
Разумеется, если нагенерить заранее, то нагрузка на проц
во время игры весьма резко снизится. Мысль такая, разумеется,
была. Сейчас уже не могу сказать точно, почему не стал
так делать. Видимо, не хотел память жрать бегамайтами.
Или просто было лень переделывать.
Ну, или такое вот дополнение к этому "аргументу".
Допустим, когда-нибудь я сделаю переключалку тембров
(какбы инструментов). Тогда мне надо будет для каждого тона
каждого тембра заранее нагенерить сигнальчиков.
Ну, вобщем, всё как обычно - компромисс
экономим процессорное время-жрём память. ))
А, да, где-то в учебниках по ALSA есть пример,
где синус генерируется при разной организации программы -
так вот они там делают это на лету. Может, оттуда
я это содрал.
Цитата:
Сообщение от Toman
А выдавать сигнал с постоянной составляющей (не просто с постоянной, а
вообще все ненулевые отсчёты одного знака) - это как вообще, нормально
так? По-моему, это, мягко говоря, совсем не здорово.
Я объясню. Я дня два-три возился с подбором формы сигнала
(ну, чтобы от звука уши не рвало). В конце концов сделал
гауссиану, на первом полупериоде - "вверх", на втором полупериоде -
"вниз". Понравилось. Убрал второй полупериод - еще больше понравилось.
Так и оставил однополярный сигнал. Можно его, конечно, двинуть вниз,
но это же думать надо, насколько )))
А щелчков-то как раз при этом меньше,
так как все ноты и почти все аккорды
оканчиваются нулём.
Цитата:
Сообщение от Toman
Боитесь, вам точности типа double, например, не хватит, чтобы никто не
услышал биений, что обязательно нужно рациональную дробь из настоящих
целых чисел (в виде реальных физических отсчётов на звуковой карте)
сооружать? Я уверен, что такие опасения напрасны, причём с очень-очень
большим запасом.
Причем тут точность для значений отсчетов?
Не причом тут она вообще.
Цитата:
Сообщение от Toman
Я ещё раз повторю: звуковые карты создавались для работы с произвольным
звуком путём приближения, а не для асбстрактных меандров и т.п. И там
стоит выходной фильтр, который вам уже в аналоговой выходной линии
(намеренно!!! специально для этого и стоит!) переход от 16384 к -16384
размажет на время, соответствующее этак почти что паре отсчётов.
Разумеется, диффузор динамика переходит из одного положения в другое
не за нулевое время. И про фильтр всё правильно. Идеальный
меандр - ну да, это абстракция, в реальности всегда есть переходные
процессы конечной длительности.
Но! Соотношения периодов-то это же не исправит!
Или я чего-то где-то сильно не догоняю...
13.03.2012, 16:29
xjiss
Re: Синтезатор с чистым строем
Цитата:
Сообщение от Toman
Если мы изначально начнём полупериод выровненным по началу
первого отсчёта, то будем иметь 50 отсчётов значением +16384, потом
отсчёт, у которого 1/4 приходится на значение +16384, а 3/4 - на -16384.
....
Вроде понял. То есть Вы учитываете работу фильтра;
если слегка схитрить, введя как бы промежуточные
отсчеты, то на выходе поимеем сигнал с периодом
100.5 тактов дискретизации ну или что-то весьма
похожее.
Я-то изначально имел ввиду "идеальный" меандр
и при этом без учета того, что там делают ЦАП, фильтры,
усилители, колонки/наушники, воздух и уши;
иными словами, я смотрел на это дело просто как на вопрос
заполнения массива числами - есссна, в таком виде
решения просто нет и не может быть.
С "хитростями", учитывающими физические реалии - да.
Цитата:
Сообщение от Toman
скачки, а вовсе не для того, чтобы у кого-то волшебный период в 720
отсчётов в области инфразвуков не оказывался
:) Так с таким волшебным периодом мне не надо "хитрить"! :)
Там всё само собой как надо получается для любой формы
сигнала, все периоды (частоты) соотносятся так, как
положено по определению чистого строя.
13.03.2012, 17:49
xjiss
Re: Синтезатор с чистым строем
Цитата:
Сообщение от Toman
Наконец, собрал и попробовал программу в действии. Во-первых, самое
главное - у меня она тоже работает, и это хорошо, ура.
Это радует, но не удивляет - там только xlib и alsa используются,
чтоб как можно ближе к телу, так сказать, было.
Ну и posix threads, но с этим вроде как уж давно проблем нет.
13.03.2012, 18:15
xjiss
Re: Синтезатор с чистым строем
Цитата:
Сообщение от Toman
А вот про собственно строй позволю себе таки немножко поругаться.
А давайте! :)
Цитата:
Сообщение от Toman
Попробовал сыграть небольшую простенькую фразу.
Фраза вся на белых клавишах, причём
использует все 7 нот, т.е., вероятнее всего, тональность там "наша". Но
тут же нарываюсь на кривущие терцию и квинту (звучащие там как
гармонические интервалы) от ре.
Всё правильно.
Квинта ре-ля в диатонике чистого строя от до - кривая.
Равно как и малая терция ре-фа.
Но там же есть тон ре-минус (клавиши s, 2, 9).
С этой второй "ре" терция ре-фа и квинта ре-ля - акустически чистые.
Цитата:
Сообщение от Toman
Потом обнаруживаю ещё по ощущениям
довольно кривую при движении по мелодии секунду ля-си.
Куда хочется "си" двинуть - вверх?
Цитата:
Сообщение от Toman
Ну т.е. это
достаточно серьёзная проблема.
Ага, и ей уже лет этак 2 тыщи как минимум ,)
Цитата:
Сообщение от Toman
Так что при попытках использовать чистый
строй или что-то близкое множество клавиш для разных случаев -
неизбежны, имхо.
Как бы это сказать... Эти все так называемые "проблемы" чистого строя
на самом деле не являются проблемами именно строя как такового.
Он то сам по себе как раз, что надо.
Это проблемы конструкции/изготовления/техники игры для определённой части
музыкальных инструментов - а именно, тех инструментов,
где строй фиксирован (струнные клавишные, орган, флейты и тп).
Для вокала/струнных смычковых нет никакой проблемы,
интонируй куда хочешь, выстраивый себе на здоровье
чистые квинты-терции от чего угодно.
Цитата:
Сообщение от Toman
Другая проблема (в случае данной фразы - даже бОльшая, чем кривые
интервалы) - сыграть эту фразу в виде, похожем на то, как оно играется
на фоно (или как это должен был бы играть ансамбль) - невозможно, потому
что нужные аккорды с октавным удвоением попадают под запрет, приходится
урезать практически до двухголосного, что звучит намного хуже...
Ох, с этим, я, к сожалению, ничего не могу поделать.
Так работает софтинка микроконтроллера клавиатурок.
Причем я вообще не понимаю логики, так сказать.
Например, 4-х звучный аккорд (n-y-i-p) "работает",
4-х звучный аккорд (b-t-u-o) тоже работает,
а вот фа (v-r-y-i) уже фигвам.
До мажор (i-p-]) - тоже не играет.
Какими соображениями руководствовались разработчики клавиатуры -
для меня это есть загадка великая.
13.03.2012, 19:16
xjiss
Re: Синтезатор с чистым строем
По поводу загрузки CPU при расчетах волны на лету
(имею ввиду эту свою гауссиану на первом полупериоде).
На уже упомянутой древней кастрюле с чипсетом i810
и процом Celeron (Mendocino), работающим на частоте 400 MHz,
наблюдается следующая картина.
Если "играть кулаком", то максимум, что занаблюдалось - 50%.
На некоторых аццких звукосочетаниях в 5-6-7 тонов - до 60%.
То есть даже для древнего железа еще есть запасик.
Я к тому, что, может и нет резону считать сигналы для всех нот
и для всех тембров (инструментов) заранее...
Как думаете?
14.03.2012, 03:15
Toman
Re: Синтезатор с чистым строем
Цитата:
Сообщение от xjiss
Я к тому, что, может и нет резону считать сигналы для всех нот
и для всех тембров (инструментов) заранее...
Как думаете?
Немножко подумал, и решил, что считать заранее ...всё-таки в любом случае лучше, чем считать на лету. Причём, даже в обоих случаях - и для целочисленного периода колебаний (если это всё-таки имеет какое-то концептуальное значение), и для нецелочисленного (что для получения на практике сигнала, неотличимого на слух от нужного, вполне годится тоже, но даёт возможность получить сколько угодно нот в октаве, а значит, работать, в принципе, хоть в самом лучшем для каждого конкретного произведения "гибридном" строе (ну, то есть, мелодию ведём по тем интервалам, которые выгодны именно для ведения мелодии (а это - пифагоров тон, полуторатон, кварта, квинта и т.д.), в то время как гармонию для неё делаем терциями чистого строя, по возможности - по крайней мере, если речь идёт о простых мажорных или минорных трезвучиях) ). Т.е. то, чего жёстко заданный 12-ступенный строй, разумеется, не позволяет, из-за чего я на него и ругаюсь. Ну и, разумеется, возможность настраиваться в любые частоты.
Если по-прежнему делать только целочисленные периоды - то тогда имеет смысл рассчитать сразу (при запуске программы или при загрузке/смене тембра) ровно по одному периоду колебания для каждой ноты (каждого тембра). Поскольку нот у вас сейчас порядка 30, а средняя длина периода, наверное, порядка 300 отсчётов или менее, памяти на 1 тембр понадобится около 9 тыс. отсчётов, или 18 кб. Ну, допустим, можно предположить, что даже добавится ещё 12 нот (если перевести основу на октаву ниже, на 1440 отсчётов), ну, станет под 50 кб. Всё равно ни о каких страшных мегабайтах речи не идёт. Можно спокойно держать в таком виде хоть десяток-другой тембров одновременно. А вот во время игры, особенно если в хорошем темпе, да с одновременно включёнными несколькими регистрами, например, да тяжёлыми аккордами и т.д., процессорной мощности это сэкономит прилично. Да и загрузка процессора 50% - это, имхо, для такого синтезатора многовато. И вообще, почему бы не посчитать сэмплы заранее, если в данных тепличных условиях (целочисленный период) это не просто, а очень просто. До того, как я заглянул в код, я был вообще уверен, что всё заранее и считается, т.к. это было бы наиболее естественным объяснением для использования строго целочисленного периода.
Соответственно, что происходит дальше, как я это себе представляю... Дальше мы делаем буфер или "цепочку" из нескольких буферов (тут уж надо мне разобраться подробнее с тем, как происходит вывод звука при помощи данной библиотеки, как всё это синхронизируется и т.д., чтобы прикинуть, сколько именно нужно буферов и как им работать). Разумеется, память под буфер выделяется тоже заранее (а то, может, дажи и просто объявляется статически), и во время игры не меняется. Ибо такое постоянное выделение-освобождение динамической памяти под буферы со звуком во время игры, имхо, суть что-то чрезвычайно неправильное и нежелательное. При сравнительно лёгких условиях оно может работать нормально, но чуть что... В общем, работать с динамической памятью в цикле работы со звуком - это значит активно нарываться на проблемы. Так что делаем буфер/буферы некоторого фиксированного размера исходя из величины latency, которую мы хотим с точки зрения исполнителя /с которой вынуждены мириться из-за условий и ограничений, налагаемых ОС. Дальше, по ходу вывода звука в эти буферы, так же, как оно и сделано сейчас, у каждой из активных нот растёт, с регулярным возвратом на ноль, приписанная ей фаза, и из суммы взятых значений из предвычисленных сэмплов этих нот получается значение очередного отсчёта, ну и цикл идёт дальше. Таким образом, у нас нет никакой необходимости вычислять общий период для аккорда, а каждая нота может продолжать непрерывно звучать независимо от начала или конца звучания других нот. Для того, чтобы избежать щелчков, либо выключение (равно как и включение) нот допускается только при прохождении уровня сигнала близко от нуля (т.е. вместо нынешней единственной переменной по активным нотам делаем две - "запрос на включение/выключение" и реальную активность, или просто сэмплы делать такими, чтобы у них этот ноль был в самом начале/конце периода, и довыводить даже "неактивную" ноту до окончания её текущего периода). Либо сделать ещё более хитро, и включать/убирать звучание не моментально, а умножая сэмпл во время переходов на какой-то ряд величин (тоже предвычисленных, если хочется красивой кривой, или рассчитываемых на ходу по какой-то сравнительно лёгкой функции - напр. если это простая прямая линия), введя для этого дела ещё одну переменную для каждой ноты - "фазу" по кривой нарастания-спадания, с некоторой выделенной точкой, на которой коэффициент заведомо равен 1, и умножение не производится, равно как и начальной точкой, в которой он равен 0, и опять же умножение не производится, а нота просто игнорируется при сборке значения для записи в буфер, ну и соотв. переменная "активности" ноты в этом варианте будет просто управлять движением по этому "кругу" нарастания-спадания. Умножение, конечно, добавляет процессорного времени, но всё же это полегче, чем полномасштабное вычисление отсчёта. Если предполагается когда-нибудь использовать варьирование уровня звука (напр. если научить программу играть по MIDI управлению или что-то в этом роде), то умножение, видимо, всё равно неизбежно, уже для всего времени, пока ноты звучат.
Или же можно как бы скомбинировать идею выравнивания по началу-концу периодов, и идею делать профилированную атаку и спадание. И сделать практически "по-взрослому": предвычислить не только 1 период середины звучания, но и атаку и спадание звука. Так, разумеется, вычислять, чтобы сэмплы мягко стыковались по концам в порядке атака-середина-спадание (собственно, сэмпл может представлять собой единый массив, просто с указанием того участка, который представляет собой период продолжающегося звучания, и внутри которого программе надо будет крутиться, пока для ноты указано "активна"). Конечно, настоящие "взрослые" атака и спадание звука должны занимать как минимум несколько периодов колебаний (а "игрушечные" делать мало смысла, т.к. это не будет на слух лучше первого метода или того, что есть в программе уже сейчас), поэтому необходимая для хранения память возрастёт. Но поскольку, как мы видели, объём этой памяти для одного тембра и 30 нот, в общем-то, совсем не страшный, вполне можно себе позволить увеличить раз в 10-20, ради того, чтобы сделать красивую атаку и затухание (во время которых, в отличие от второго варианта, с умножением на число, можно не просто плавно менять громкость, а довольно сильно менять и тембровый состав, что делает более реалистичной в особенности атаку).
В общем, имхо, честное вычисление на лету имеет смысл только для таких эффектов, которые выходят за рамки эмуляции органного звука - т.е. широкое и непрерывное варьирование не только громкости звука, но и продолжительности и характера атаки в зависимости от силы звука, непрерывное бесступенчатое варьирование тембра звука, непрерывное глиссандо. В общем, такие вещи, которые вряд ли имеют смысл для игры через компьютерную клавиатуру (или даже простейшую MIDI клавиатуру без всяких серьёзных функций и датчиков). Для эмуляции же органного звука, который даже и по громкости-то не меняется - имхо, оптимальный и наиболее общий именно такой путь - предвычисленные сэмплы с более или менее скромными атакой и затуханием и с указанными границами периода внутри для продолжающегося звука (вот этот-то внутренний период и обязан подчиняться чистому строю). При этом как частный случай, конечно, внутренний период может занимать весь сэмпл, т.е. автоматически сводиться в точности к первому варианту, без атаки или затухания, а просто с выравниванием начала-конца звучания по началу сэмпла. Вот как-то так, пожалуй...
14.03.2012, 06:09
Toman
Re: Синтезатор с чистым строем
А теперь - о том, что и как меняется, если мы уходим от целочисленного периода к произвольным частотам. Вообще-то и здесь нет жёсткой необходимости вычислять на лету. Можно тоже предвычислить сигнал. Но только помня, что, поскольку теперь "фаза" будет с каждым отсчётом (выводимым, т.е. с "системной" частотой дискретизации) возрастать не на единицу, а на какую-то нецелую величину, повторения значений по отсчётам не будет. Поэтому предвычисляем мы период, разумеется, в виде целого числа отсчётов (нецелым количество отсчётов в массиве, разумеется, быть не может), но с частотой дискретизации, отличной от той, на которой будет происходить вывод звука. Соответственно, каждый отсчёт вывода будет попадать по фазе не точно на какой-то отсчёт нашего сэмпла, а между. И вот тут возможны варианты, и зависит это в первую очередь от избранного нами числа отсчётов на период (это может быть абсолютно любое целое число). Например, если это небольшое число (например, ради экономии памяти), то, чтобы избежать сильных искажений, необходима будет интерполяция - хотя бы линейная между соседними отсчётами - фактически, то самое, что я демонстрировал в качестве "хитрости" с меандром (хотя возможны теоретически и другие варианты интерполяции). А можно поступить и проще: предвычислить сигнал, подробив его очень мелко, т.е. на длинном массиве. Т.е. сделать что-то вроде оверсэмплинга. И тогда можно просто тупо брать отсчёт, ближайший к значению фазы (нецелому) для данного отсчёта вывода - интерполяция как бы уже сделана за нас, с какой-то, заведомо достаточной для практики, точностью.
Разумеется, необходимая для сэмпла память в разы возрастает при таком оверсэмплинге, равно как и время на вычисление. Но это на самом деле компенсируется (порой, с избытком даже) тем, что, в отличие от подхода со строгим совпадением частоты дискретизации для вычисления (с целым периодом, разумеется) и частоты дискретизации вывода, здесь нет необходимости предвычислять и хранить сэмплы для каждой ноты. В простейшем случае - т.е. для того, чтобы всего лишь воспроизвести ситуацию, имеющуюся в программе сейчас, с единственной функцией на все ноты - достаточно вообще посчитать единственный период. Например, тыщ на 8 отсчётов посчитать (а при желании - да хоть на 80 тыс., только это, пожалуй, вовсе уж избыточно) период, потом, при выборе частоты дискретизации вывода, на этапе общения с системой, посчитать для каждой ноты, скольким "внутренним" отсчётам будет равен отсчёт вывода (плавающее число), т.е. на сколько продвигать "фазу" ноты с каждым отсчётом. И т.о. для каждой ноты хранить фактически только "фазу", т.е. текущее положение на общем на все ноты сэмпле, да этот самый коэффициент, на сколько сдвигаться с каждым выводимым отсчётом. Здесь тоже возможен вариант с предвычисленными атакой и затуханием, конечно. Ну а если хочется делать более серьёзный тембр, "адаптирующийся" к частоте тона, то можно сделать несколько "образцовых" тембров - скажем, штучки по 1-3 на октаву. И простейшим, хоть линейным, образом интерполировать потом результирующий отсчёт из двух соседних образцовых тембров. (Конечно, чтобы это гладко сработало, эти образцовые тембры должны быть достаточно хорошо согласованы по фазам участвующих там гармоник или элементарных форм сигнала, из которых оно там синтезируется, чтобы они в промежутке между "опорными" нотам не глушили сами себя, оказавшись в противофазе, или под 90 градусов, или типа того).
Цитата:
Причем тут точность для значений отсчетов?
Как видите, это я не столько про значения отсчётов (хотя и их можно сделать плавающими, при желании, или просто увеличить число бит, т.е. перейти на 32-битные отсчёты хотя бы, для снижения накапливающихся при суммировании многих нот ошибок дискретизации - но это, во всяком случае, не первой важности вопрос на данном этапе), а про точность нецелого смещения каждой ноты ("генератора") по "фазе" при выводе каждого отсчёта. Разумеется, у плавающих типов есть своя точность, и из-за этого в итоге реальные частоты считаемых таким образом звуков будут, строго говоря, не совпадать точно с желаемыми, и от этого чистота строя будет, строго говоря, нарушена. Но, насколько я знаю, реальный счёт плавающих чисел на современных компах идёт как минимум в double, так что что-то ниже double для "фазы" использовать нет смысла. Исходно собственная точность этого типа близка к 16 десятичным знакам. К сожалению, правда, при прибавлении к фазе смещения из-за разности порядков самой фазы и смещения точность уменьшится на столько же порядков. Скажем, для частоты тона 12 Гц (беру как бы худший случай, с точки зрения относительной точности - самое большое количество смещений на период) на частоте дискретизации 48 кГц соотношение составит примерно 4000 - т.е. почти ровно 12 двоичных порядков (12 двоичных цифр долой из 53, имеющихся в типе double) или примерно 3,6 десятичных порядков. Т.е. оставшаяся точность (отдельной операции сложения) составит 41 двоичную цифру, или примерно 12,3 десятичных цифр. На самом деле, впрочем, ошибки округления будут падать в разные стороны, распределяясь достаточно равномерно, скорее всего, так что на самом деле суммарно по периоду точность будет несколько лучше, но, опять же, допустим, в качестве худшего случая, что все округления будут давать именно максимальную ошибку, и всякий раз в одну сторону. Т.е. точность соответствия частоты заданной будет в худшем случае 12,3 десятичных знаков, а в абсолютном значении порядка 10-11 Гц.
Или, скажем, для частоты 400 Гц - теряем примерно 7 двоичных или 2,1 десятичных порядков, т.е. точность 46 двоичных или 13,8 десятичных знаков, а в абсолютном значении точность выдерживания частоты в худшем случае опять же порядка 10-11 Гц. Т.е. возможный (и то, это в худшем случае, практически нереальном, имхо!) период биений из-за ошибок плавающей арифметики можно было бы ожидать порядка 5*1010 секунд, т.е. порядка 1500 лет. Имхо, такой точности соответствия частот друг другу всё же должно быть достаточно, чтобы считать строй в соответствующим заданному для любых практических целей :)
14.03.2012, 07:28
Toman
Re: Синтезатор с чистым строем
Цитата:
Сообщение от xjiss
Всё правильно.
Квинта ре-ля в диатонике чистого строя от до - кривая.
Равно как и малая терция ре-фа.
Но там же есть тон ре-минус (клавиши s, 2, 9).
С этой второй "ре" терция ре-фа и квинта ре-ля - акустически чистые.
Хмм... Сам я как-то не догадался там искать другую ре, т.к. все остальные ноты в "верхних" рядах суть "черноклавишные", и я как-то просто не ждал там варианта ре. А про наличие в таблице в исходниках значения 10/9 честно забыл :)
Но тут тоже свои проблемы с его использованием. Во-первых, получающийся мелодический интервал 10/9 (который, в результате, имеет место и в басу, и в среднем голосе, и, естественно, в квинте, которая в верхнем голосе) воспринимается как довольно сильно несоответствующий ситуации. Во-вторых, кроме ре, фа и ля, которые по строю в таком аккорде соответствуют, во фразе участвует соль, которая теперь образует нам кривую кварту... Можно, конечно, на время звучания этой соль переходить на "основное" ре, а потом, когда пойдёт ля, вернуться на ре-минус. Но это не решает проблемы мелодически неприятно суженного интервала. Так что для адекватной игры второго "колена" фразы от ре больше бы подошёл повышенный вариант ля (ну и, по вкусу, также повышенный вариант фа - если хочется именно чистую терцию). Что происходит в третьем "колене" фразы, и какие ноты там были бы наиболее уместны - я пока не анализировал, т.к. там картина, пожалуй, сложнее (работают бас и середина ми, и в верхнем голосе и ля, си, до, ре). Но на слух, там как раз всё как надо. И даже мелодический ход на 10/9 секунду в этом случае воспринимается почему-то спокойнее.
Да, внезапно обнаружилось, что, кроме как в самой верхней октаве, "бьют" квинты ми-си и фа-до - хотя чисто с точки зрения строя, не должны. Т.е. это уже технические глюки какие-то, непонятно откуда берущиеся.
Цитата:
Куда хочется "си" двинуть - вверх?
Хм... Я вообще не уверен, что именно си. Дело в том, что "кривым" на самом деле мне показалось сочетание этой секунды с предыдущей соль-ля. Потому что они там разные, а в тот момент хотелось скорее одинаковых. А уж куда что двигать хотелось, и вовсе неопределённый вопрос. Может быть, двигать хотелось вообще соль. Но, во всяком случае, неравенство мелодических секунд как-то ощущается, и в некоторых случаях это ощущение неприятно. А в других случаях вроде и ничего - вот, как c ре на ми в этой моей фразе, который воспринимается нормально. М.б. потому что там что-то вроде минора перед этим, и зауженная секунда воспринимается как-то уместнее. А когда ноты в голом виде, или, допустим, с ля минора на си переходить... Нет, чёткого ответа всё равно не дам, это надо было бы попробовать посравнивать разные варианты, если бы они были - тогда бы можно было что-то понять. Я всё-таки не такой спец по настройкам, и не скрипач или какой ещё спец по интонированию, чтобы так сразу сказать "я бы сыграл вот так-то, настолько-то ниже/выше", не попробовав это сам в реальности.
Цитата:
Как бы это сказать... Эти все так называемые "проблемы" чистого строя
на самом деле не являются проблемами именно строя как такового.
Он то сам по себе как раз, что надо.
Это проблемы конструкции/изготовления/техники игры для определённой части
музыкальных инструментов - а именно, тех инструментов,
где строй фиксирован (струнные клавишные, орган, флейты и тп).
...Флейта, кстати, позволяет подстраивать интонацию в довольно широких пределах.
Ну так вот вы же делаете что? Инструмент как раз. И у него, в его нынешнем виде, эта проблема стоит просто в полный рост. Хотя на софтовом синтезаторе как раз наоборот можно было бы делать такие вещи как автоопределение терций и квинт в аккордах и автоматический выбор чистой интонации в этом случае относительно тоники. Для мелодии тут уже можно было бы разный строй брать, по вкусу - хоть пифагоров вообще как таковой (а для мелодий вроде пентатоники всякой и иже с ними он, вероятно, должен быть предпочтителен).
Цитата:
Ох, с этим, я, к сожалению, ничего не могу поделать.
Так работает софтинка микроконтроллера клавиатурок.
Причем я вообще не понимаю логики, так сказать.
Значит, надо искать какие-то другие варианты. Например, попробовать освоить подключение программы к MIDI интерфейсу - чтобы иметь возможность использовать нормальные MIDI клавиатуры.
Цитата:
До мажор (i-p-]) - тоже не играет.
Был на работе, там тоже скомпилировал прогу (бинарник из дома там не подошёл бы - дома-то 64-битная система, на работе 32-битная). Так на тамошней клавиатуре как раз до мажор этот верхний играет (дома у меня не играет). Зато там не играет, например, тот самый "кривой" ре минор (который с "основным" ре).
14.03.2012, 17:29
xjiss
Re: Синтезатор с чистым строем
Цитата:
Да, внезапно обнаружилось, что, кроме как в самой верхней октаве, "бьют" квинты ми-си и фа-до - хотя чисто с точки зрения строя, не должны. Т.е. это уже технические глюки какие-то, непонятно откуда берущиеся.
Хм. Может, это эффект восприятия, связанный с тембром?
С гауссианой звук как бы слегка булькающий, чтоли...
Если на чистом синусе попробовать?..
14.03.2012, 17:32
xjiss
Re: Синтезатор с чистым строем
Цитата:
Флейта, кстати, позволяет подстраивать интонацию в довольно широких пределах.
Я в курсе:
(если не лазали по сайтику)
На остальное попозжа отвечу, подумать надо.
14.03.2012, 18:44
xjiss
Re: Синтезатор с чистым строем
Цитата:
Сообщение от Toman
Немножко подумал, и решил, что считать заранее ...всё-таки в любом
случае лучше, чем считать на лету.
В принципе, я тоже к такой мысли склоняюсь.
С мегабайтами - это да, это я не подумавши ляпнул.
Так и не вспомнил, с чего я решил рассчитывать "на лету".
Кстати, тонов не порядка 30, а ровно 46;
если из терминала запускать, оно пишет в него:
Код:
./xjiss
NTONES = 46
Цитата:
Сообщение от Toman
Причём, даже в обоих случаях - и для
целочисленного периода колебаний (если это всё-таки имеет какое-то
концептуальное значение)
Ну, я уже сказал, что вся "концептуальность" заключается в
определении чистого строя и в выборе надлежащего периода
самого низкого тона. Тогда все интервалы автоматом соблюдаются
идеально без всяких ухищрений навроде того, что Вы привели
в примере с меандром.
Мне думается, что такие вот "маленькие хитрости" - это слишком мутно.
Для разных форм сигналов нужно будет мутить по-своему.
Не программа получится, а черт знает что... :)
Вообщем, затея двигать строй вверх-вниз мне кажется
не очень хорошей.
Цитата:
Сообщение от Toman
такое постоянное выделение-освобождение динамической памяти под буферы со звуком во время
игры, имхо, суть что-то чрезвычайно неправильное и нежелательное.
Тут я согласен.
Опять же не помню, какие тараканы заставили меня сделать именно так.
Щас есть мысль сделать буфер на 1-2-3-4-5 секунд звучания
и генерить в него. Мысль появилась тогда, когда я захотел
сделать реверберацию (надо просто добавлять ослабленные отсчеты
в "будущее"). Но силов и времени на implementation пока не хватило... :)
Цитата:
Сообщение от Toman
Таким образом, у нас нет
никакой необходимости вычислять общий период для аккорда, а каждая нота
может продолжать непрерывно звучать независимо от начала или конца
звучания других нот.
Пока не осознал, надо подумать. Чувствую, что тут рациональное зерно есть.
Цитата:
Сообщение от Toman
сделать красивую атаку и затухание
Я немного думал на эту тему; в принципе, сделать этот
envelope не особо сложно, надо просто считать периоды,
ну и множить/делить на соотв. коэффициент в зависимости от номера
периода. Опять же, не хватило запалу, чтоб реализовать.
Цитата:
Сообщение от Toman
В общем, такие вещи, которые вряд ли имеют смысл для игры
через компьютерную клавиатуру (или даже простейшую MIDI клавиатуру без
всяких серьёзных функций и датчиков).
Эт да, на компьютерной клаве играть - занятие своеобразное.
Насчет MIDI-клавы никаких планов не было и нет,
мне было прикольно разобраться с тем, как отрабатывать
одновременно нажатые клавиши именно на комп. клаве,
чтобы можно было по этой самой клаве фигачить :)
По типу того, как это можно делать в FL Studio (для форточек)
и в линуксовом аналоге LMMS.
Я из-за этого даже примерно месяц гитару в руки не брал :)
И вот тут я просто обязан выразить искреннюю благодарность
за интерес к поделке и особенно за дельные замечания.
Если хотя бы один человек проявил интерес - это уже здорово!
Как будет время и желание, постараюсь хорошенько обдумать
всё, что Вы написали и перепилить программу так или иначе.
14.03.2012, 18:54
xjiss
Re: Синтезатор с чистым строем
Цитата:
Сообщение от Toman
Но, во всяком случае, неравенство мелодических секунд как-то ощущается, и в некоторых случаях это ощущение неприятно. А в других случаях вроде и ничего - вот, как c ре на ми в этой моей фразе, который воспринимается нормально
А можно фразу послушать?
14.03.2012, 19:12
Toman
Re: Синтезатор с чистым строем
Цитата:
Сообщение от xjiss
Хм. Может, это эффект восприятия, связанный с тембром?
С гауссианой звук как бы слегка булькающий, чтоли...
Если на чистом синусе попробовать?..
Нет, с тембром это связано быть никак не может. Тем более, что это происходит как на вашем, так и на любом из моих тембров (основанных на сочетаниях 1, 3, 5 степеней синуса от 1, 3, 5 степеней координаты). Т.е. там зависимость скорее именно от высоты нот. Причём, скажем, сейчас, на работе, я вижу уже другое: при том же тембре ми-си совсем не бьёт, в то время как фа-до немножко бьёт (хотя намного менее выраженно, чем биение их обоих на домашнем компе). Т.е. это уже, возможно, какие-то аппаратные зависимости. То есть, более точно сказать, не совсем аппаратные, а, скорее всего, разные драйверы у разных карт (в обоих случаях карты встроенные, но они на работе и дома разные), которые выдают разные параметры. Плюс, наверное, всё-таки что-то некорректное во взаимодействии с ALSA. Вот, например, чего я не понял: вы получаете оттуда ( sound.c ) параметры "буфер" и "период" (я пока не в курсе, что это именно означает, но, наверное, всё-таки что-то важное, да?) в локальные переменные функции sound_init(), даже печатаете их на стандартый вывод (я, грешен, стандартный вывод ещё не перенаправлял в файл, и соотв. не смотрел, что прога туда пишет при соответствующих условиях... хотя вообще для этих целей, имхо, более правильно использовать стандартный вывод для ошибок, который stderr, он же номер 2, а не "основной" стандтартный вывод). После чего эти значения никак в программе не используются, и просто пропадают с выходом из оной функции. М.б., тут дело как раз в том, что для каких-то аккордов получаются такие размеры буфера, которые потом устраивают какой-то конфликт с какими-то драйверами карт, когда дело доходит до собственно осуществления вывода, в то время как для других аккордов конкретный размер буфера другой, и всё оказывается нормально... В общем, пока у меня подозрения в каком-то таком направлении...
14.03.2012, 19:41
Toman
Re: Синтезатор с чистым строем
Цитата:
Сообщение от xjiss
Ну, я уже сказал, что вся "концептуальность" заключается в
определении чистого строя и в выборе надлежащего периода
самого низкого тона. Тогда все интервалы автоматом соблюдаются
идеально без всяких ухищрений навроде того, что Вы привели
в примере с меандром.
Мне думается, что такие вот "маленькие хитрости" - это слишком мутно.
Для разных форм сигналов нужно будет мутить по-своему.
Не программа получится, а черт знает что... :)
Да нет, это совершенно общий и стандартный алгоритм для любых форм сигнала - в т.ч. записанных из реального мира звуков произвольного вида. При более-менее гладкой форме сигнала ошибки минимальны. Строгий меандр (наряду с пилой) - это один из тех самых худших случаев, при которой величина сопутствующих ошибок дискретизации в любом случае максимальна. Таких сигналов в цифре надо в любом случае избегать. Потому что даже если они выглядят в цифрах вроде бы аккуратненько и красиво, корректно выведены они быть не могут. В своё время, опять же, 10-12 лет назад, заинтересовавшись темой, я пошёл в книжный и купил книгу о работе со звуком с точки зрения программиста (автор Тим Кинтцель, издание в русском переводе 2000 года, НЯП). Значительную часть книги составляет, увы, не совсем относящаяся к делу словесная и кодовая шелуха, связанная с приверженностью автора к C++ и ООП. Но в части собственно работы с "цифрой" там он пишет дельные вещи. И, в частности, в самом начале он как раз приводит пример, что для того же прямоугольного сигнала, чтобы он реально звучал чище всего и содержал меньше искажений и мусора, он должен аппроксимироваться в цифровом виде вовсе не ровными полочками, а таким образом, чтобы были срезаны гармоники, слишком близкие к F/2. Т.е. с той ещё "колбаснёй" перед и после острого фронта. Т.е. сигналы, содержащие острые фронты, в принципе сложны для правильного синтеза в пригодном к выводу виде. Это вообще отдельная проблема, и она как минимум на порядок сложнее того довольно нехитрого алгоритма, что вы называете хитростями. Проще всего просто не нарываться на неё, избегая синтеза таких форм сигнала, по крайней мере, "непосредственным" образом. А с приличными сигналами без острых фронтов и (в меньшей степени, но всё же) острых "изломов" всё это работает общим образом без каких-то специфических мер.
Цитата:
Я немного думал на эту тему; в принципе, сделать этот
envelope не особо сложно, надо просто считать периоды,
ну и множить/делить на соотв. коэффициент в зависимости от номера
периода. Опять же, не хватило запалу, чтоб реализовать.
Нет, так не годится. Даже если резкая смена амплитуды будет происходить по нулю сигнала, изменение её рывками будет звучать на слух неприятно, и (с точки зрения акустики и спектров) порождать всплески шума, следующие с вашим периодом синтеза. Так что амплитуду менять надо обязательно плавно, а значит, обсчитывать каждый отсчёт со своим множителем, а не общим на весь период...
14.03.2012, 20:46
xjiss
Re: Синтезатор с чистым строем
Я у себя послушал, вроде как нет биений в квинтах ми-си и фа-до.
Кривая квинта ре-ля сразу слышна.
Цитата:
Сообщение от Toman
Нет, с тембром это связано быть никак не может. Тем более, что это
происходит как на вашем, так и на любом из моих тембров (основанных на
сочетаниях 1, 3, 5 степеней синуса от 1, 3, 5 степеней координаты).
Т.е. там зависимость скорее именно от высоты нот. Причём, скажем,
сейчас, на работе, я вижу уже другое: при том же тембре ми-си совсем
не бьёт, в то время как фа-до немножко бьёт (хотя намного менее
выраженно, чем биение их обоих на домашнем компе).
Чудяса...
А вы еще предлагаете похимичить с периодами тонов, некратными
периодам дискретизации. )))
Цитата:
Сообщение от Toman
Плюс, наверное, всё-таки что-то некорректное во взаимодействии с ALSA. Вот, например,
чего я не понял: вы получаете оттуда ( sound.c ) параметры "буфер" и
"период" (я пока не в курсе, что это именно означает, но, наверное,
всё-таки что-то важное, да?)
1) Что может быть некорректного в тупом write()?
(
Замечание - функция записи в девайс возвращается
не тогда, когда весь звук уже проигран, а раньше...
возврат из snd_pcm_writei() происходит тогда,
когда ALSA прожевала порцию и отправила в дело.
Сопсна, это и позволяет считать на лету...
Расчет длится меньше, чем проигрывание.
)
2) С параметрами "размер буфера" и "период" я и сам не особо разобрался.
Особенно с "период" - ваще не понимаю, чо это такое.
Я подобрал LATENCY таким образом, чтобы на моём древнем железе
ошибка "разорванная труба" не возникала слишком уж часто
(при включенной записи всё-таки иногда возникает, в итоге срыв звука).
Как я понял, broken pipe означает underrun, то есть приложение
не успело, извиняюсь, запихнуть очередную порцию данных.
Если заметили - прога пишет звук всегда; если кнопки не нажаты,
гонит нули (кстати, загрузка проца при этом - порядка 1-2%)
Цитата:
Сообщение от Toman
в локальные переменные функции
sound_init(), даже печатаете их на стандартый вывод (я, грешен,
стандартный вывод ещё не перенаправлял в файл, и соотв. не смотрел, что
прога туда пишет при соответствующих условиях
Да Вы просто из консольки запускайте, йошкин кодЪ :)))
А не мышиными кликами с "раб. стола" )))
stdout, stderr - тут не принципиально.
14.03.2012, 21:06
Toman
Re: Синтезатор с чистым строем
Цитата:
Сообщение от xjiss
А можно фразу послушать?
Вот (записано на данном синтезаторе, но с моим тембром (смесь из синусов 1, 3 и 5 степеней, с преобладанием 5-й степени, НЯП), с "кривым" ре минором (на "основной" ре) ):
На самом деле, основной (первый вариант фразы, как оно было придумано изначально) - это который звучит вторым. Тот же, который звучит первым - это такой "зацикленный" вариант, который может идти в качестве фона или в качестве вставки для перехода во что-то ещё.
15.03.2012, 10:50
xjiss
Re: Синтезатор с чистым строем
В продолжение темы про уложение 2-х периодов колебания в 201 отсчет.
Период в 100 отсчетов соответствует частоте звука 480 Hz.
Период в 101 отсчет соответствует частоте звука 475.248 Hz.
Разница - почти 5 Герц.
Допустим, что Ваш меандр с хитринкой действительно даст
период в 100.5 тактов дискретизации и, соответственно,
частоту звука 472.906 Hz.
А как Вы будете изображать, скажем, 478 Hz?
Период для этой частоты - 100.418.
У Вас опять получатся полочки по 49 или 50 отсчетов
и 3 промежуточных значения. Единственное, что Вы сможете
изменить, это значения этих промежуточных отсчетов.
И Вы хотите сказать, что от величины этих отсчётов
будет зависеть частота меандра на выходе звуковой карты?
Что-то терзают меня смутные сомнения....
15.03.2012, 10:54
xjiss
Re: Синтезатор с чистым строем
Фразу послушал. Красиво.
Кстати, почему то мой любимый mplayer играет только первую секунду.
Слушал в audacity.