Случайны выбор дневника Раскрыть/свернуть полный список возможностей


Найдено 4468 сообщений
Cообщения с меткой

алгоритмы - Самое интересное в блогах

Следующие 30  »
rss_rss_hh_new

Что такое творчество

Понедельник, 25 Июля 2016 г. 16:04 (ссылка)

Главное в статье для неосиляторов: творчество — это постановка новых проблем, задач, их решение, а так же создание новых способов (алгоритмов) решения уже решённых задач. В посте будет рассматриваться модель творчества, компиляция материалов нескольких авторов. Для умеренных осиляторов презентация. Остальных приглашаю в статью.







Много думал насчёт того, в каком хабе опубликовать. Если есть более подходящий, прошу написать мне название.



Я пишу эту статью сюда не только потому, что часто слышал: «программирование/дизайн/управление проектами — творческая профессия» и уверен, что тема интересна здешним программистам, дизайнерам, верстальщикам, управленцам и т.д. Кроме этого, здешняя аудитория сможет помочь мне улучшить модель, поделившись примерами, указав на ошибки и неизвестные мне материалы по теме.



Началось всё с эмоций. Я вроде как музыкант и вроде как занимаюсь творчеством. Однако было ощущение, что ни я, ни куча снобствующих музыкантов, поэтов, художников и т.д. на деле ничего в общество не привносят, совсем ничего. Кроме того, творческими людьми, талантамИ, гениями называли и людей искусства, и изобретателей, и учёных, и философов. И методы с основными подходами в этих направлениях разные, по многим параметрам противоположные, как и результаты.



Я начал копаться вместе с ещё несколькими интересующимися в этой теме. После того, как перечитал несколько книг, кучу статей, в том числе с замечательного портала vikent.ru, поговорил с умными людьми, я убедился, что в теме творчества, искусства, одарёности и талантливости куча мифов, часть из которых давно опровергнуты фактами, и люди продолжают им верить. Но главное — люди очень по-разному понимают, что такое талант, творчество и т.д. Мне кажется, что наши труды могут помочь разобраться в этом бардаке.



Люди понимают под творчеством и талантом разные вещи



Под творчеством могут подразумеваться минимум 4 вещи:




  1. Художественная деятельность, искусство.

  2. Результат этой деятельности («вот моё творчество» — песни, картины и т.д.)

  3. Процесс создания принципиально новых материальных и нематериальных ценностей

  4. Результат этого процесса (по аналогии с 2)



Первые два — следствие из 3го и 4го, они появились из мнения, что любое художественное произведение (сделанное профессионалом, по крайней мере) те самые ценности привносит в общество. Однако такое явление, как «попса» опровергает это. Поэтому мы остановились на 3-ем определении, для 4-го понятия выбрали термин «творческий результат». Или «результат творчества»



Под талантом тоже понимают обычно несколько вещей:




  1. Одарённость (способность быстро осваивать знания, умения, навыки в определённой области)

  2. Умение регулярно делать что-то хорошо (иначе знания, умения, навыки; профессионализм)

  3. Способность делать что-то оригинально, либо делать то, чего никто до этого не делал



Для первых двух понятий термины уже есть. Кроме того, они не подразумевают того самого результата. Можно ведь хорошо делать попсу и забивать гвозди, но того же творческого результата там нет. А вот третье термина не имеет и как раз подразумевает некую новизну. Правда, настолько в людях сильно сидит «талант=одарённость» (даже Ожегов так расшифровывает), что возможно, придётся отказаться от этого термина и использовать «способность к творчеству».



Что такое принципиально новые материальные и нематериальные ценности



Вопрос был сложный, так как к таковым относятся как произведения искусства, так и различные изобретения и открытия. И как их свести к чему-то единому?



Талант, творчество и т.д. проявляются в деятельности. Любую деятельность можно рассматривать как решение задач. Базовые типы задач:




  • мышление (что думать по поводу поступившей информации, как воспринимать/понимать)

  • отношение (какую эмоцию испытывать по этому поводу)

  • движение (что конкретно с этим делать и как)



Любую деятельность можно разложить на алгоритм этих базовых операций. Любую задачу можно раскладывать на подзадачи, пока не спустимся на этот базовый уровень.



Многие задачи можно решать с помощью разных алгоритмов, разных последовательностей базовых операций. Или, более простым языком, способов.



Мы постоянно решаем огромное количество задач. Для экономии ресурсов и энергии большинство задач решаются с помощью автоматических, фиксированных способов. Стереотипов, шаблонов, паттернов. Многие люди, похоже, на протяжении многих лет, а то и всей жизни решают так вообще все возникающие задачи.



Шаблон человек вырабатывает сам или получает извне. Вспомните библиотеки функций, классов. Вы просто используете алгоритм, который кто-то давно создал. Пишете название, параметры, получаете результат. Гугл сделал модным решение многих, не только программистких задач, с помощью Ctrl+V Ctrl+C. Посмотреть в интернете и сделать так же, не вдаваясь в суть.



Но иногда случается, что человек отказывается от шаблона. Либо возникла новая для человека, предприятия, а то и вообще мира, задача, и шаблон не работает вообще, либо результат выполнения шаблона не удовлетворителен по каким-то причинам. Некоторые люди способны перестроить этот шаблон либо вообще создать новый способ решения задачи.



Вот это создание нового способа, нового алгоритма, мы и будем считать творческим результатом.



Как оценить уровень творческого результата (нового алгоритма)?



Для этого можно использовать диаграмму Викентьева-Джефферсона (творческая эффективность):





То есть новизна и польза только для себя — это тоже творчество, только низкого уровня. Возможен результат с разными показателями полезности и новизны. Скажем, новизна на уровне страны, а польза только для города.



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



Чего-то не хватает



К искусству, философии, да и науке такое подходит не всегда. Известны случаи, когда они решали прикладные задачи (лаундж — отличная музыка для того, чтобы человек не чувствовал себя неуютно в чупермаркете). Известны случаи, когда они эти новые задачи ставили. И вот тут мы перешли к определению задачи. Что такое задача?



На Википедии нашлось хорошее и краткое определение: «Зада

https://habrahabr.ru/post/304456/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Самообучение шахматной программы

Четверг, 21 Июля 2016 г. 20:23 (ссылка)

Здравствуй, Хабр!



В статье, опубликованной на Хабре в прошлом году, мы решали задачу определения математически обоснованных стоимостей шахматных фигур. С помощью регрессионного анализа партий, сыгранных компьютерами и людьми, нам удалось получить шкалу ценности «юнитов», во многом совпадающую с традиционными значениями, известными из книг и практического опыта.



К сожалению, непосредственная подстановка скорректированных значений для фигур не усилила программу автора — во всяком случае, больше, чем в рамках статистической погрешности. Применение же исходного метода «в лоб» к другим параметрам оценочной функции давало несколько абсурдные результаты, алгоритм оптимизации явно нуждался в некоторой доработке. Тем временем, автор решил, что очередной релиз его движка станет заключительным в длинной серии версий, берущих своё начало в коде десятилетней давности. Была выпущена версия GreKo 2015, и дальнейшие изменения в ближайшем будущем не планировались.



Картинка для привлечения внимания



Всем интересующихся тем, что было дальше — после просмотра картинки для привлечения внимания добро пожаловать под кат.



Мотивацией к внезапному продолжению работы и, в конечном итоге, появлению этой статьи, послужили два события. Одно из них прогремело на весь мир по каналам массовой информации — это матч в Го корейского топ-игрока Ли Седоля с программой Google AlphaGo.







Разработчики из Google DeepMind сумели эффективно объединить две мощные техники — поиск в дереве методом Монте-Карло и глубокое обучение с использованием нейросетей. Получившийся симбиоз привёл к феноменальным результатам в виде победы над двумя профессиональными игроками в Го (Ли Седолем и Фан Хуэем) с общим счётом 9 — 1. Детали реализации AlphaGo широко обсуждались, в том числе и на Хабре, поэтому сейчас останавливаться на них не будем.



Второе событие, не столь широко разрекламированное, и замеченное в основном энтузиастами шахматного программирования — появление программы Giraffe. Её автор, Matthew Lai, активно использовал идеи машинного обучения, в частности, всё те же глубокие нейросети. В отличие от традиционных движков, в которых оценочная функция содержит ряд заранее предопределённых признаков позиции, Giraffe на этапе обучения самостоятельно извлекает эти признаки из учебного материала. Фактически, была заявлена цель автоматического вывода «шахматного знания» в том виде, в котором его излагают в учебниках.



Кроме оценочной функции, нейронные сети в Giraffe использовались и для параметризации поиска по дереву, что также наводит на мысли о некоторых параллелях с AlphaGo.



Определённые успехи программа продемонстрировала, достигнув с нуля за несколько дней обучения силы международного мастера. Но, к сожалению, интереснейший исследовательский проект был преждевременно завершён… в связи с переходом Matthew Lai на работу в команду Google DeepMind!



Так или иначе, информационная волна, возникшая в связи с AlphaGo и Giraffe, побудила автора данной статьи ещё раз вернуться к коду своего движка и попытаться всё-таки усилить его игру методами столь популярного ныне машинного обучения.



Алгоритм





Возможно, кого-то это разочарует, но в описываемом проекте не будет ни многослойных нейронных сетей, ни автоматического детектирования ключевых признаков позиции, ни метода Монте-Карло. Случайный поиск по дереву в шахматах практически не требуется в силу ограниченности задачи, а хорошо работающие факторы оценки шахматной позиции известны ещё со времён «Каиссы». Кроме того, автору было интересно насколько можно усилить игру программы в рамках достаточно минималистичного их набора, который реализован в GreKo.



Базовым методом был выбран алгоритм настройки оценочной функции, который предложил шведский исследователь и разработчик Peter "Osterlund, автор сильной программы Texel. Выигрышными сторонами этого метода, по словам его создателя, являются:




  • Возможность одновременно оптимизировать до нескольких сотен параметров оценочной функции.

  • Отсутствие необходимости в источнике «внешнего знания» в виде экспертных оценок позиций — нужны только тексты и результаты партий.

  • Корректная работа с сильно коррелированными признаками — не требуется никакая предварительная подготовка вроде их ортогонализации.





Пусть

https://habrahabr.ru/post/305604/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

[Из песочницы] Синтезатор речи «для роботов» с нуля

Понедельник, 18 Июля 2016 г. 18:28 (ссылка)

image



Давным-давно посетила меня идея создать синтезатор речи с «голосом робота», как, например, в песне Die Roboter группы Kraftwerk. Поиски информации по «голосу робота» привели к историческому факту, что подобное звучание синтетической речи характерно для вокодеров, которые используются для сжатия речи (2400 — 9600 бит/c). Голос человека, синтезированный вокодером, отдает металлическим звучанием и становится похожим на тот самый «голос робота». Музыкантам понравился данный эффект искажения речи, и они стали активно его использовать в своем творчестве.



Поиски информации по реализации вокодера вывели меня на книгу «Теория и применение цифровой обработки сигналов», где расписано почти все, что необходимо для создания собственного синтезатора речи на основе вокодера.



Небольшое замечание касательно выбора способа реализации синтеза речи



Конечно, можно было бы и не париться с созданием вокодера, а просто сделать базу заранее записанных звуков всех фонем и проигрывать их в соответствии с текстом. Данный способ мне не был интересен, поэтому я решил сделать синтезатор речи именно с синтезом всех звуков, как согласных, так и гласных. Вокодер для этих целей был выбран потому, что его проще обучить, чем формантный синтезатор речи, хотя звучание в обоих случаях было бы именно то, которое мне нужно. К тому же, синтезирование звуков, возможно, позволит реализовать синтезатор речи на базе микроконтроллера stm32 без внешней памяти! Вопрос тут скорее в том, хватит ли скорости работы МК.



Под спойлером представлен результат обработки речи вокодером





Краткая теория работы вокодера



Самая основная часть вокодера — это гребенка полосовых фильтров. Именно она формирует спектр синтетической речи или, наоборот, определяет уровни спектра естественной человеческой речи в приемной части устройства. Как передающая, так и принимающая часть вокодера содержит гребенку полосовых фильтров.



Принимающая человеческую речь часть вокодера также определяет, помимо спектра звука, является ли звук шумовым, или у него есть тон. Для тона определяется его период. Сигналы с выходов полосовых фильтров детектируются, пропускаются через ФНЧ и используются в дальнейшем в качестве коэффициентов для модуляции сигналов на полосовых фильтрах синтезирующей части вокодера.



Синтезирующая часть вокодера содержит генератор шума и тона (читай: генератор случайной числовой последовательности на основе сдвигового регистра и генератора меандра), а также переключатель между этими двумя генераторами. Сигнал от одного из двух генераторов подается на вход гребенки полосовых фильтров. Для каждого фильтра на входе сигнал от генератора тона или шума модулируется соответствующим коэффициентом. И наконец, с выхода всех фильтров суммируем сигнал и получаем синтезированную речь.



Если кто не понял мое описание работы вокодера, вот блок-схема:



image



Не все так просто



Чтобы вокодер хоть как-то понятно звучал, нужно выполнить пару требований к его полосовым фильтрам. Нет времени объяснять, просто поверье, что нужно использовать БИХ фильтры Бесселя (пруфы на 749 странице). Также, нужно распределить спектр речи неравномерно по фильтрам, особенно если у нас их немного (в моей реализации вокодера их всего 16 штук). Есть еще одна прелюбопытнейшая вещь, с которой вы можете ознакомиться все в той же книжке. А именно, представим, что сначала мы пропускаем сигнал от генератора тона или шума через гребенку фильтров, затем с выхода каждого фильтра ограничиваем сигнал двумя уровнями -1 и +1 и затем модулируем сигналы и снова пропускаем каждый сигнал через такой же фильтр, как ранее. По идее, такая схема не должна давать ощутимой разницы в синтезируемой речи. Тем не менее, такой прием выравнивания спектра существенно улучшает синтетическую речь вокодера. Почему так, лучше прочесть в книжке. Ну а тем, кому лень читать, скажу кратко: это из-за флуктуаций речи человека. На картинке снизу представлена блок-схема «улучшения» вокодера.



image



Что же касательно того, как распределить частоты между фильтрами… Основные частоты человеческой речи находятся в диапазоне примерно до 4-5 кГц (очень примерно). Я взял предел в 4 кГц и, используя психофизическую единицу измерения высоты звука «мел», распределил равномерно, правда не по герцам, а по мелам.



Что дает такой способ синтеза речи?



Если коэффициенты модуляции полосовых фильтров «смещать» по номеру фильтра, можно получить из женского голоса мужской. И это несмотря на то, что диапазоны фильтров (в моей реализации вокодера) в частотной области распределены не равномерно.



Также можно менять интонацию речи, можно вообще все менять. Единственный минус остается отстойное низкое качество речи.



Прослушать то, как меняется женская речь в мужскую, можно тут:



женский голос без изменений (монотонный)

мужской голос из женского (монотонный)

А если мужской голос сделать еще более мужским?

очень мужской голос (монотонный)



Немного кода



Весь код я пока выкладывать не буду (так как еще не дописал синтезатор речи — будет вторая статья). Ниже представлен код для определения высоты основного тона (также можно определить, тон или шум). Для этого измеряется энтропия сигнала, энтропия сигнала после ФНЧ на 600 Гц (в частотной области тона), а также число правильных совпадений в определителе периода тона.



Код определения высоты основного тона.
#include 
#include

/*
speesy_Entropy_f - возвращает энтропию сигнала (функция не моя)
speesy_GetBasicTone - получить высоту основного тона
speesy_GetAllCoincidence - число совпадений в функции определения высоты основного тона
speesy_GetBasicToneEntropy - энтропия сигнала в области высоты основного тона
speesy_SetFreqMeander - установить частоту меандра
speesy_Meander - возвращает сигнал меандра

*/

#define SPEESY_SAMPLE_FREQ8 8000
#define SPEESY_SAMPLE_FREQ16 16000
#define SPEESY_SAMPLE_FREQ SPEESY_SAMPLE_FREQ16

#define SPEESY_MEANDER_MAX 100
#define FOR_FLOAT_EPSILON 1.19209e-007

static float speesy_all_coincidence = 0; //число правильных совпадений в определителе периода основного тона
static float speesy_fliter600_Entropy = 1.0;

static float speesy_meander_period = 0.01;//для генератора меандра

float speesy_Entropy_f(const float* source, unsigned long int start, unsigned long int finish, unsigned char binsCount, float minRaw, float maxRaw) {
float entropy = 0;
float binSize = fabs(maxRaw - minRaw) / (float)binsCount;
//FOR_FLOAT_EPSILON == numeric_limits::epsilon()
if (fabs(binSize) < FOR_FLOAT_EPSILON) {
return 0;
}
//float* p = new float[binsCount];
float p[256];
for (unsigned char i = 0; i < binsCount; i++) {
p[i] = 0.0;
}

// Calculate probabilities
unsigned char index;
float value;
for (unsigned long int i = start; i <= finish; i++) {
value = source[i]; //for 8-bit data
index = floor((value - minRaw) / binSize);

if (index >= binsCount) {
index = binsCount - 1;
}

p[index] += 1.0;
}

unsigned char Normalize_size = finish - start + 1;
for (unsigned char i = 0; i < binsCount; i++) {
p[i] /= Normalize_size;
}

for (unsigned char i = 0; i < binsCount; i++) {
if (p[i] > FOR_FLOAT_EPSILON) {
entropy += p[i] * log2(p[i]);
}
}

entropy = -entropy;
return entropy;
}


float speesy_GetBasicTone(float source) {
static float matrix[6][6] ={0,0,0,0,0,0,
0,0,0,0,0,0,
0,0,0,0,0,0,
0,0,0,0,0,0,
0,0,0,0,0,0,
0,0,0,0,0,0};
const float max_detector_p = 0.0255;
const float min_detector_p = 0.0016;
static float detector_p[6] = {min_detector_p};
static float detector_old_p[6] = {min_detector_p};
static float detector_t[6] = {0};
static float detector_tay[6] = {0.016};
static float detector_t_end = 0;
//static float detector_beta[6] = {0};
static float detector_value[6] = {0};
float f_data = 0;
//char detector_p_t0_f = 0;
static float sig_old = 0;
static char sig_p = 0;
static char sig_m = 0;
static unsigned short tim160 = 0;
float detector_m1;
float detector_m2;
float detector_m3;
float detector_m4;
float detector_m5;
float detector_m6;
int detector_data = 0;
static float detector_old_m1;
static float detector_old_m4 = 0;
static char speesy_tone_i = 0;
static char speesy_tone_x = 0;
static char speesy_tone_y = 0;
static char speesy_tone_inter = 0;
//char n_coincidence[4] ={0};
char n_coincidence_matrix[6][4] ={0};
static float out_t;
#if SPEESY_SAMPLE_FREQ == SPEESY_SAMPLE_FREQ8
static float source_data[16] = {0};
const int max_source_data = 16;
const float p_conts = 0.000125;
#endif // SPEESY_SAMPLE_FREQ

#if SPEESY_SAMPLE_FREQ == SPEESY_SAMPLE_FREQ16
static float source_data[32] = {0};
const int max_source_data = 32;
const float p_conts = 0.0000625;
#endif // SPEESY_SAMPLE_FREQ

/*************Filter 600 Hz**********************/
#if SPEESY_SAMPLE_FREQ == SPEESY_SAMPLE_FREQ8
const float filter600_ACoef1[5] = {
0.00161978575856732190,
0.00647914303426928760,
0.00971871455140393280,
0.00647914303426928760,
0.00161978575856732190
};

const float filter600_BCoef1[4] = {
-2.63228606617055720000,
2.68865140959361830000,
-1.25580694576241330000,
0.22536111137571077000
};
#endif // SPEESY_SAMPLE_FREQ
#if SPEESY_SAMPLE_FREQ == SPEESY_SAMPLE_FREQ16
const float filter600_ACoef1[5] = {
0.00013538805748957640,
0.00054155222995830559,
0.00081232834493745844,
0.00054155222995830559,
0.00013538805748957640
};

const float filter600_BCoef1[4] = {
-3.29078386336302660000,
4.09122986596582550000,
-2.27618508727807440000,
0.47792443748067198000
};
#endif // SPEESY_SAMPLE_FREQ

static float filter600_y[5] = {0}; //output samples
static float filter600_x[5] = {0}; //input samples
static float out_filter600[240] = {0};
short out_i = 0;

filter600_x[4] = filter600_x[3];
filter600_y[4] = filter600_y[3];
filter600_x[3] = filter600_x[2];
filter600_y[3] = filter600_y[2];
filter600_x[2] = filter600_x[1];
filter600_y[2] = filter600_y[1];
filter600_x[1] = filter600_x[0];
filter600_y[1] = filter600_y[0];

filter600_x[0] = source;

filter600_y[0] = filter600_ACoef1[0] * filter600_x[0];
filter600_y[0] += filter600_ACoef1[1] * filter600_x[1] - filter600_BCoef1[0] * filter600_y[1];
filter600_y[0] += filter600_ACoef1[2] * filter600_x[2] - filter600_BCoef1[1] * filter600_y[2];
filter600_y[0] += filter600_ACoef1[3] * filter600_x[3] - filter600_BCoef1[2] * filter600_y[3];
filter600_y[0] += filter600_ACoef1[4] * filter600_x[4] - filter600_BCoef1[3] * filter600_y[4];
/***************End Filter 600 Hz*********************/
for (out_i = 239;out_i>0; out_i--) {
out_filter600[out_i] = out_filter600[out_i - 1];
}
out_filter600[0] = filter600_y[0];

if (tim160 < 160) {tim160 = tim160 + 1;}
else {
tim160 = 0;
speesy_fliter600_Entropy = speesy_Entropy_f(out_filter600,0,159,255,-32768,32768);
speesy_fliter600_Entropy = speesy_Entropy_f(out_filter600,160,239,255,-32768,32768);
}



detector_m1 = 0;
detector_m2 = 0;
detector_m3 = 0;
detector_m4 = 0;
detector_m5 = 0;
detector_m6 = 0;

//printf("\nSpeesy max_source_data = %d\n",max_source_data);



if (filter600_y[0] >= 0) {
if (filter600_y[0] > sig_old) {sig_p = 1;}
else {
if (sig_p == 1) {
sig_p = 0;
detector_m1 = filter600_y[0];
if (detector_m1 > detector_old_m1) {
detector_m3 = detector_m1 - detector_old_m1;
} else detector_m3 = 0;
detector_m2 = detector_m1 + detector_old_m4;
detector_old_m1 = detector_m1;
}
}
sig_old = filter600_y[0];
} else {
if ((-filter600_y[0]) > sig_old) {sig_m = 1;}
else {
if (sig_m == 1) {
sig_m = 0;
detector_m4 = -filter600_y[0];
if (detector_m4 > detector_old_m4) {
detector_m6 = detector_m4 - detector_old_m4;
} else detector_m6 = 0;
detector_m5 = detector_m4 + detector_old_m1;
detector_old_m4 = detector_m4;
}
}
sig_old = -filter600_y[0];
}

/*****************************************************/

//ИОН6
if (detector_t[5] > detector_tay[5]) { //если время больше tay
f_data = detector_value[5]*(exp(-(detector_t[5] - detector_tay[5])/(detector_p[5]/0.695))); //экспоненциальный разряд
if (detector_m6 > f_data) { //больше уровня
detector_value[5] = detector_m6; //обновляем уровень
detector_p[5] = (detector_t[5] + detector_p[5])/2; //среднее значение периода
if (detector_p[5] > max_detector_p) detector_p[5] = max_detector_p;
if (detector_p[5] < min_detector_p) detector_p[5] = min_detector_p;
detector_tay[5] = 0.4*detector_p[5]; //новое тау
detector_t[5] = 0;
//detector_p_t0_f = 1;
matrix[5][2] = matrix[5][1];
matrix[5][1] = matrix[5][0];
matrix[5][0] = detector_p[5];
} else {
detector_t[5] = detector_t[5] + p_conts; //инкремент времени
}
} else {
detector_t[5] = detector_t[5] + p_conts;
}
//ИОН5
if (detector_t[4] > detector_tay[4]) { //если время больше tay
f_data = detector_value[4]*(exp(-(detector_t[4] - detector_tay[4])/(detector_p[4]/0.695))); //экспоненциальный разряд
if (detector_m5 > f_data) { //больше уровня
detector_value[4] = detector_m5; //обновляем уровень
detector_p[4] = (detector_t[4] + detector_p[4])/2; //среднее значение периода
if (detector_p[4] > max_detector_p) detector_p[4] = max_detector_p;
if (detector_p[4] < min_detector_p) detector_p[4] = min_detector_p;
detector_tay[4] = 0.4*detector_p[4]; //новое тау
detector_t[4] = 0;
//detector_p_t0_f = 1;
matrix[4][2] = matrix[4][1];
matrix[4][1] = matrix[4][0];
matrix[4][0] = detector_p[4];
} else {
detector_t[4] = detector_t[4] + p_conts; //инкремент времени
}
} else {
detector_t[4] = detector_t[4] + p_conts;
}
//ИОН4
if (detector_t[3] > detector_tay[3]) { //если время больше tay
f_data = detector_value[3]*(exp(-(detector_t[3] - detector_tay[3])/(detector_p[3]/0.695))); //экспоненциальный разряд
if (detector_m4 > f_data) { //больше уровня
detector_value[3] = detector_m4; //обновляем уровень
detector_p[3] = (detector_t[3] + detector_p[3])/2; //среднее значение периода
if (detector_p[3] > max_detector_p) detector_p[3] = max_detector_p;
if (detector_p[3] < min_detector_p) detector_p[3] = min_detector_p;
detector_tay[3] = 0.4*detector_p[3]; //новое тау
detector_t[3] = 0;
//detector_p_t0_f = 1;
matrix[3][2] = matrix[3][1];
matrix[3][1] = matrix[3][0];
matrix[3][0] = detector_p[3];
} else {
detector_t[3] = detector_t[3] + p_conts; //инкремент времени
}
} else {
detector_t[3] = detector_t[3] + p_conts;
}
//ИОН3
if (detector_t[2] > detector_tay[2]) { //если время больше tay
f_data = detector_value[2]*(exp(-(detector_t[2] - detector_tay[2])/(detector_p[2]/0.695))); //экспоненциальный разряд
if (detector_m3 > f_data) { //больше уровня
detector_value[2] = detector_m3; //обновляем уровень
detector_p[2] = (detector_t[2] + detector_p[2])/2; //среднее значение периода
if (detector_p[2] > max_detector_p) detector_p[2] = max_detector_p;
if (detector_p[2] < min_detector_p) detector_p[2] = min_detector_p;
detector_tay[2] = 0.4*detector_p[2]; //новое тау
detector_t[2] = 0;
//detector_p_t0_f = 1;
matrix[2][2] = matrix[2][1];
matrix[2][1] = matrix[2][0];
matrix[2][0] = detector_p[2];
} else {
detector_t[2] = detector_t[2] + p_conts; //инкремент времени
}
} else {
detector_t[2] = detector_t[2] + p_conts;
}
//ИОН2
if (detector_t[1] > detector_tay[1]) { //если время больше tay
f_data = detector_value[1]*(exp(-(detector_t[1] - detector_tay[1])/(detector_p[1]/0.695))); //экспоненциальный разряд
if (detector_m2 > f_data) { //больше уровня
detector_value[1] = detector_m2; //обновляем уровень
detector_p[1] = (detector_t[1] + detector_p[1])/2; //среднее значение периода
if (detector_p[1] > max_detector_p) detector_p[1] = max_detector_p;
if (detector_p[1] < min_detector_p) detector_p[1] = min_detector_p;
detector_tay[1] = 0.4*detector_p[1]; //новое тау
detector_t[1] = 0;
//detector_p_t0_f = 1;
matrix[1][2] = matrix[1][1];
matrix[1][1] = matrix[1][0];
matrix[1][0] = detector_p[1];
} else {
detector_t[1] = detector_t[1] + p_conts; //инкремент времени
}
} else {
detector_t[1] = detector_t[1] + p_conts;
}
//ИОН1
if (detector_t[0] > detector_tay[0]) { //если время больше tay
f_data = detector_value[0]*(exp(-(detector_t[0] - detector_tay[0])/(detector_p[0]/0.695))); //экспоненциальный разряд
if (detector_m1 > f_data) { //больше уровня
detector_value[0] = detector_m1; //обновляем уровень
detector_p[0] = (detector_t[0] + detector_p[0])/2; //среднее значение периода
if (detector_p[0] > max_detector_p) detector_p[0] = max_detector_p;
if (detector_p[0] < min_detector_p) detector_p[0] = min_detector_p;
detector_tay[0] = 0.4*detector_p[0]; //новое тау
detector_t[0] = 0;
//detector_p_t0_f = 1;
matrix[0][2] = matrix[0][1];
matrix[0][1] = matrix[0][0];
matrix[0][0] = detector_p[0];
} else {
detector_t[0] = detector_t[0] + p_conts; //инкремент времени
}
} else {
detector_t[0] = detector_t[0] + p_conts;
}
/************************************************************************/
if (detector_t_end == 0) {
for (speesy_tone_x = 0;speesy_tone_x<6;speesy_tone_x++) {
matrix[speesy_tone_x][3] = matrix[speesy_tone_x][0] + matrix[speesy_tone_x][1];
matrix[speesy_tone_x][4] = matrix[speesy_tone_x][1] + matrix[speesy_tone_x][2];
matrix[speesy_tone_x][5] = matrix[speesy_tone_x][1] + matrix[speesy_tone_x][2] + matrix[speesy_tone_x][0];
}
for (speesy_tone_inter = 0; speesy_tone_inter<4;speesy_tone_inter++) {
n_coincidence_matrix[0][speesy_tone_inter] = 0;
n_coincidence_matrix[1][speesy_tone_inter] = 0;
n_coincidence_matrix[2][speesy_tone_inter] = 0;
n_coincidence_matrix[3][speesy_tone_inter] = 0;
n_coincidence_matrix[4][speesy_tone_inter] = 0;
n_coincidence_matrix[5][speesy_tone_inter] = 0;
for (speesy_tone_x = 0;speesy_tone_x<6;speesy_tone_x++) {
for (speesy_tone_y = 0;speesy_tone_y<6;speesy_tone_y++) {
//printf("\nValue_matrix %f",matrix[speesy_tone_x][speesy_tone_y]);
//printf("\nmatrix %f",(float)matrix[speesy_tone_x][speesy_tone_y]);
for (speesy_tone_i = 0;speesy_tone_i<6;speesy_tone_i++) {
//printf("\nmatrix %f",(float)matrix[speesy_tone_x][speesy_tone_y]);
//printf("\nspeesy_tone_i %d",speesy_tone_i);
//printf("\nsr matrix %f",(float)matrix[speesy_tone_i][0]);
if (((speesy_tone_y != 0)&(speesy_tone_x!=speesy_tone_i))|(speesy_tone_y > 0))
if ((matrix[speesy_tone_i][0] >= 0.0016)&(matrix[speesy_tone_i][0] <= 0.0031)) {
f_data = 0.0001*((float)speesy_tone_inter + 1.0);
if ((((float)matrix[speesy_tone_i][0] + (float)f_data) >= (float)matrix[speesy_tone_x][speesy_tone_y])&
(((float)matrix[speesy_tone_i][0] - (float)f_data) <= (float)matrix[speesy_tone_x][speesy_tone_y])) {
n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] = n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] + 1;
//printf("\ncoincidence 0.0016 - 0.0031");
}
} else
if ((matrix[speesy_tone_i][0] > 0.0031)&(matrix[speesy_tone_i][0] <= 0.0063)) {
f_data = 0.0002*((float)speesy_tone_inter + 1.0);
if ((((float)matrix[speesy_tone_i][0] + (float)f_data) >= (float)matrix[speesy_tone_x][speesy_tone_y])&
(((float)matrix[speesy_tone_i][0] - (float)f_data) <= (float)matrix[speesy_tone_x][speesy_tone_y])) {
n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] = n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] + 1;
//printf("\ncoincidence 0.0031 - 0.0063");
}
} else
if ((matrix[speesy_tone_i][0] > 0.0063)&(matrix[speesy_tone_i][0] <= 0.0127)) {
f_data = 0.0004*((float)speesy_tone_inter + 1.0);
if ((((float)matrix[speesy_tone_i][0] + (float)f_data) >= (float)matrix[speesy_tone_x][speesy_tone_y])&
(((float)matrix[speesy_tone_i][0] - (float)f_data) <= (float)matrix[speesy_tone_x][speesy_tone_y])) {
n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] = n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] + 1;
//printf("\ncoincidence 0.0063 - 0.0127");
}
} else
if ((matrix[speesy_tone_i][0] > 0.0127)&(matrix[speesy_tone_i][0] <= 0.0255)) {
f_data = 0.0008*((float)speesy_tone_inter + 1.0);
if (((matrix[speesy_tone_i][0] + f_data) >= matrix[speesy_tone_x][speesy_tone_y])&
((matrix[speesy_tone_i][0] - f_data) <= matrix[speesy_tone_x][speesy_tone_y])) {
n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] = n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] + 1;
//printf("\ncoincidence 0.0127 - 0.0255");
}
} else {
//printf("\nNO coincidence");
}
//printf("\ncoincidence %d",n_coincidence_matrix[speesy_tone_i][speesy_tone_inter]);
} //end for

} //end for

for (speesy_tone_inter = 0; speesy_tone_inter<4;speesy_tone_inter++) {
for (speesy_tone_i = 0;speesy_tone_i<6;speesy_tone_i++) {
//printf("\nDo mat_ton %d",(int)n_coincidence_matrix[speesy_tone_i][speesy_tone_inter]);
}
}

if (speesy_tone_inter == 0) {
for (speesy_tone_i = 0;speesy_tone_i<6;speesy_tone_i++) {
if (n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] >= 1) {
n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] -= 1;
} else {
n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] = 0;
}

}
} else
if (speesy_tone_inter == 1) {
for (speesy_tone_i = 0;speesy_tone_i<6;speesy_tone_i++) {
if (n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] >= 2) {
n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] -= 2;
} else {
n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] = 0;
}
}
} else
if (speesy_tone_inter == 2) {
for (speesy_tone_i = 0;speesy_tone_i<6;speesy_tone_i++) {
if (n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] >= 5) {
n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] -= 5;
} else {
n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] = 0;
}
}
} else
if (speesy_tone_inter == 3) {
for (speesy_tone_i = 0;speesy_tone_i<6;speesy_tone_i++) {
if (n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] >= 7) {
n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] -= 7;
} else {
n_coincidence_matrix[speesy_tone_i][speesy_tone_inter] = 0;
}
}
}

} //end for

} //end for () for inter

out_t = 0;
speesy_tone_x = 0;
for (speesy_tone_inter = 0; speesy_tone_inter<4;speesy_tone_inter++) {
for (speesy_tone_i = 0;speesy_tone_i<6;speesy_tone_i++) {
//printf("\n mat_ton %d",(int)n_coincidence_matrix[speesy_tone_i][speesy_tone_inter]);
if (speesy_tone_x < n_coincidence_matrix[speesy_tone_i][speesy_tone_inter]) {
speesy_tone_x = n_coincidence_matrix[speesy_tone_i][speesy_tone_inter];
out_t = matrix[speesy_tone_i][0];
}
}
}
speesy_all_coincidence = speesy_tone_x;
} // end if

detector_t_end = detector_t_end + p_conts;
if (detector_t_end > 0.01) detector_t_end = 0;
return out_t;
}

float speesy_GetAllCoincidence(void) {
return speesy_all_coincidence;
}

float speesy_GetBasicToneEntropy(void) {
return speesy_fliter600_Entropy;
}



void speesy_SetFreqMeander(float freq) {
if (freq > 0) {
speesy_meander_period = (1.0/freq)/2;
}
}

signed char speesy_Meander(void) {
static float tim = 0;
static signed char out = SPEESY_MEANDER_MAX;
if (tim < speesy_meander_period) {
tim = tim + 0.0000625;
} else {
tim = 0;
out = -out;
}
return out;
}







А так же код гребенки полосовых фильтров.

#define SPEESY_NCOEF 4
#define SPEESY_MAXCAN 16

#define SPEESY_SAMPLE_FREQ8 8000
#define SPEESY_SAMPLE_FREQ16 16000
#define SPEESY_SAMPLE_FREQ SPEESY_SAMPLE_FREQ16


#if SPEESY_SAMPLE_FREQ == SPEESY_SAMPLE_FREQ16

//const float speesy_gain_correction_factor[16] = {1};


//for 0-88 Hz
const float ACoef1[SPEESY_NCOEF+1] = {
0.00000010368236408362,
0.00000041472945633450,
0.00000062209418450175,
0.00000041472945633450,
0.00000010368236408362
};

const float BCoef1[SPEESY_NCOEF] = {
-3.89262720221970990000,
5.68304206565440850000,
-3.68807460061232460000,
0.89766108913372833000
};

//for 88-188 Hz ---
const float ACoef2[SPEESY_NCOEF+1] = {
0.00046664702180067459,
0.00000000000000000000,
-0.00093329404360134919,
0.00000000000000000000,
0.00046664702180067459
};

const float BCoef2[SPEESY_NCOEF] = {
-3.92772838537582160000,
5.78986681239677910000,
-3.79636811635581890000,
0.93423598091247251000
};

//for 188-300 Hz
const float ACoef3[SPEESY_NCOEF+1] = {
0.00068858979234044106,
0.00000000000000000000,
-0.00137717958468088210,
0.00000000000000000000,
0.00068858979234044106
};

const float BCoef3[SPEESY_NCOEF] = {
-3.90771680345434060000,
5.74278248379999570000,
-3.76163133600848760000,
0.92663841158343707000
};
//for 300-426 Hz
const float ACoef4[SPEESY_NCOEF+1] = {
0.00088886359477686550,
0.00000000000000000000,
-0.00177772718955373100,
0.00000000000000000000,
0.00088886359477686550
};

const float BCoef4[SPEESY_NCOEF] = {
-3.87697578244056950000,
5.67379106513293690000,
-3.71429576416733910000,
0.91785164973031175000
};

//for 426-569 Hz
const float ACoef5[SPEESY_NCOEF+1] = {
0.00089752885269638212,
0.00000000000000000000,
-0.00179505770539276420,
0.00000000000000000000,
0.00089752885269638212
};

const float BCoef5[SPEESY_NCOEF] = {
-3.83152224876138180000,
5.57511629406004070000,
-3.64956251837243120000,
0.90729235654450602000
};

//for 569-729 Hz
const float ACoef6[SPEESY_NCOEF+1] = {
0.00117165116363920890,
0.00000000000000000000,
-0.00234330232727841770,
0.00000000000000000000,
0.00117165116363920890
};

const float BCoef6[SPEESY_NCOEF] = {
-3.76921491262598970000,
5.44568593950509160000,
-3.56948525439078870000,
0.89685259841470821000
};

//for 729-910 Hz
const float ACoef7[SPEESY_NCOEF+1] = {
0.00148423763165421900,
0.00000000000000000000,
-0.00296847526330843790,
0.00000000000000000000,
0.00148423763165421900
};

const float BCoef7[SPEESY_NCOEF] = {
-3.68252961240084180000,
5.27062615397503010000,
-3.46252708324253880000,
0.88411914122102575000
};

//for 910-1113 Hz
const float ACoef8[SPEESY_NCOEF+1] = {
0.00200280660037213200,
0.00000000000000000000,
-0.00400561320074426400,
0.00000000000000000000,
0.00200280660037213200
};

const float BCoef8[SPEESY_NCOEF] = {
-3.56693687706466770000,
5.04696879760847760000,
-3.32877844509510410000,
0.87096927786413736000
};

//for 1113-1343 Hz
const float ACoef9[SPEESY_NCOEF+1] = {
0.00211587349387137120,
0.00000000000000000000,
-0.00423174698774274240,
0.00000000000000000000,
0.00211587349387137120
};

const float BCoef9[SPEESY_NCOEF] = {
-3.41224013209053600000,
4.75975212198515950000,
-3.15521200191456290000,
0.85509175287783645000
};

//for 1343-1601 Hz
const float ACoef10[SPEESY_NCOEF+1] = {
0.00297423038464923910,
0.00000000000000000000,
-0.00594846076929847830,
0.00000000000000000000,
0.00297423038464923910
};

const float BCoef10[SPEESY_NCOEF] = {
-3.21142823810671900000,
4.40933217825630660000,
-2.94127038526055400000,
0.83892403143238325000
};

//for 1601-1892 Hz
const float ACoef11[SPEESY_NCOEF+1] = {
0.00355749937553949790,
0.00000000000000000000,
-0.00711499875107899590,
0.00000000000000000000,
0.00355749937553949790
};

const float BCoef11[SPEESY_NCOEF] = {
-2.95205117909921370000,
3.98864705820180850000,
-2.67338596187190400000,
0.82024999905406459000
};

//for 1892-2219 Hz
const float ACoef12[SPEESY_NCOEF+1] = {
0.00647978043392210490,
0.00000000000000000000,
-0.01295956086784421000,
0.00000000000000000000,
0.00647978043392210490
};

const float BCoef12[SPEESY_NCOEF] = {
-2.62319693441575370000,
3.50739946700623410000,
-2.34648117429591170000,
0.80033689362210914000
};

//for 2219-2588 Hz
const float ACoef13[SPEESY_NCOEF+1] = {
0.00856598928083165260,
0.00000000000000000000,
-0.01713197856166330500,
0.00000000000000000000,
0.00856598928083165260
};

const float BCoef13[SPEESY_NCOEF] = {
-2.21114034361129000000,
2.98277240977037210000,
-1.94961151450908200000,
0.77769319296960093000
};

//for 2588-3004 Hz
const float ACoef14[SPEESY_NCOEF+1] = {
0.02526264992554181800,
0.00000000000000000000,
-0.05052529985108363700,
0.00000000000000000000,
0.02526264992554181800
};

const float BCoef14[SPEESY_NCOEF] = {
-1.70416700060032110000,
2.45684840140417120000,
-1.47852699918255030000,
0.75308204601400430000
};

//for 3004-3472 Hz
const float ACoef15[SPEESY_NCOEF+1] = {
0.03942139343875778600,
0.00000000000000000000,
-0.07884278687751557200,
0.00000000000000000000,
0.03942139343875778600
};

const float BCoef15[SPEESY_NCOEF] = {
-1.09464887950984990000,
1.99774885820253490000,
-0.93284437413716226000,
0.72671843772403244000
};

//for 3472-4000 Hz
const float ACoef16[SPEESY_NCOEF+1] = {
0.11014553344131538000,
0.00000000000000000000,
-0.22029106688263075000,
0.00000000000000000000,
0.11014553344131538000
};

const float BCoef16[SPEESY_NCOEF] = {
-0.38091397871674004000,
1.69738617536193790000,
-0.31794271360590415000,
0.69738617534660274000
};

#endif // SPEESY_SAMPLE_FREQ


static float speesy_y1[SPEESY_NCOEF+1];
static float speesy_x1[SPEESY_NCOEF+1];
static float speesy_y2[SPEESY_NCOEF+1];
static float speesy_x2[SPEESY_NCOEF+1];
static float speesy_y3[SPEESY_NCOEF+1];
static float speesy_x3[SPEESY_NCOEF+1];
static float speesy_y4[SPEESY_NCOEF+1];
static float speesy_x4[SPEESY_NCOEF+1];
static float speesy_y5[SPEESY_NCOEF+1];
static float speesy_x5[SPEESY_NCOEF+1];
static float speesy_y6[SPEESY_NCOEF+1];
static float speesy_x6[SPEESY_NCOEF+1];
static float speesy_y7[SPEESY_NCOEF+1];
static float speesy_x7[SPEESY_NCOEF+1];
static float speesy_y8[SPEESY_NCOEF+1];
static float speesy_x8[SPEESY_NCOEF+1];
static float speesy_y9[SPEESY_NCOEF+1];
static float speesy_x9[SPEESY_NCOEF+1];
static float speesy_y10[SPEESY_NCOEF+1];
static float speesy_x10[SPEESY_NCOEF+1];
static float speesy_y11[SPEESY_NCOEF+1];
static float speesy_x11[SPEESY_NCOEF+1];
static float speesy_y12[SPEESY_NCOEF+1];
static float speesy_x12[SPEESY_NCOEF+1];
static float speesy_y13[SPEESY_NCOEF+1];
static float speesy_x13[SPEESY_NCOEF+1];
static float speesy_y14[SPEESY_NCOEF+1];
static float speesy_x14[SPEESY_NCOEF+1];
static float speesy_y15[SPEESY_NCOEF+1];
static float speesy_x15[SPEESY_NCOEF+1];
static float speesy_y16[SPEESY_NCOEF+1];
static float speesy_x16[SPEESY_NCOEF+1];

static float speesy_cannel[SPEESY_MAXCAN] ={0};
static float speesy_value[SPEESY_MAXCAN] ={0};
static int speesy_i = 0;

const float speesy_gain_correction_factor[16] = {0.95,0.79,0.66,0.66,0.8,0.79,0.8,0.74,0.85,0.79,0.834,0.57,0.54,0.23,0.18,0.082};

void speesy_set_cannel(float * cannel) {
for (speesy_i = 0; speesy_i < SPEESY_MAXCAN; speesy_i++) {
speesy_value[speesy_i] = cannel[speesy_i];
}
}

void speesy_get_value(float * value) {
for (speesy_i = 0; speesy_i < SPEESY_MAXCAN; speesy_i++) {
value[speesy_i] = speesy_cannel[speesy_i] * speesy_gain_correction_factor[speesy_i];
}
}

void speesy_update_filter(float NewSample) {
/*************1***********/
speesy_x1[4] = speesy_x1[3];
speesy_y1[4] = speesy_y1[3];
speesy_x1[3] = speesy_x1[2];
speesy_y1[3] = speesy_y1[2];
speesy_x1[2] = speesy_x1[1];
speesy_y1[2] = speesy_y1[1];
speesy_x1[1] = speesy_x1[0];
speesy_y1[1] = speesy_y1[0];

speesy_x1[0] = speesy_value[0]*NewSample;

speesy_y1[0] = ACoef1[0] * speesy_x1[0];
speesy_y1[0] += ACoef1[1] * speesy_x1[1] - BCoef1[0] * speesy_y1[1];
speesy_y1[0] += ACoef1[2] * speesy_x1[2] - BCoef1[1] * speesy_y1[2];
speesy_y1[0] += ACoef1[3] * speesy_x1[3] - BCoef1[2] * speesy_y1[3];
speesy_y1[0] += ACoef1[4] * speesy_x1[4] - BCoef1[3] * speesy_y1[4];
speesy_cannel[0] = speesy_y1[0];
/*************************/
/*************2***********/
speesy_x2[4] = speesy_x2[3];
speesy_y2[4] = speesy_y2[3];
speesy_x2[3] = speesy_x2[2];
speesy_y2[3] = speesy_y2[2];
speesy_x2[2] = speesy_x2[1];
speesy_y2[2] = speesy_y2[1];
speesy_x2[1] = speesy_x2[0];
speesy_y2[1] = speesy_y2[0];

speesy_x2[0] = speesy_value[1]*NewSample;

speesy_y2[0] = ACoef2[0] * speesy_x2[0];
speesy_y2[0] += ACoef2[1] * speesy_x2[1] - BCoef2[0] * speesy_y2[1];
speesy_y2[0] += ACoef2[2] * speesy_x2[2] - BCoef2[1] * speesy_y2[2];
speesy_y2[0] += ACoef2[3] * speesy_x2[3] - BCoef2[2] * speesy_y2[3];
speesy_y2[0] += ACoef2[4] * speesy_x2[4] - BCoef2[3] * speesy_y2[4];
speesy_cannel[1] = speesy_y2[0];
/*************************/
/*************3***********/
speesy_x3[4] = speesy_x3[3];
speesy_y3[4] = speesy_y3[3];
speesy_x3[3] = speesy_x3[2];
speesy_y3[3] = speesy_y3[2];
speesy_x3[2] = speesy_x3[1];
speesy_y3[2] = speesy_y3[1];
speesy_x3[1] = speesy_x3[0];
speesy_y3[1] = speesy_y3[0];

speesy_x3[0] = speesy_value[2]*NewSample;

speesy_y3[0] = ACoef3[0] * speesy_x3[0];
speesy_y3[0] += ACoef3[1] * speesy_x3[1] - BCoef3[0] * speesy_y3[1];
speesy_y3[0] += ACoef3[2] * speesy_x3[2] - BCoef3[1] * speesy_y3[2];
speesy_y3[0] += ACoef3[3] * speesy_x3[3] - BCoef3[2] * speesy_y3[3];
speesy_y3[0] += ACoef3[4] * speesy_x3[4] - BCoef3[3] * speesy_y3[4];
speesy_cannel[2] = speesy_y3[0];
/*************************/
/*************4***********/
speesy_x4[4] = speesy_x4[3];
speesy_y4[4] = speesy_y4[3];
speesy_x4[3] = speesy_x4[2];
speesy_y4[3] = speesy_y4[2];
speesy_x4[2] = speesy_x4[1];
speesy_y4[2] = speesy_y4[1];
speesy_x4[1] = speesy_x4[0];
speesy_y4[1] = speesy_y4[0];

speesy_x4[0] = speesy_value[3]*NewSample;

speesy_y4[0] = ACoef4[0] * speesy_x4[0];
speesy_y4[0] += ACoef4[1] * speesy_x4[1] - BCoef4[0] * speesy_y4[1];
speesy_y4[0] += ACoef4[2] * speesy_x4[2] - BCoef4[1] * speesy_y4[2];
speesy_y4[0] += ACoef4[3] * speesy_x4[3] - BCoef4[2] * speesy_y4[3];
speesy_y4[0] += ACoef4[4] * speesy_x4[4] - BCoef4[3] * speesy_y4[4];
speesy_cannel[3] = speesy_y4[0];
/*************************/
/*************5***********/
speesy_x5[4] = speesy_x5[3];
speesy_y5[4] = speesy_y5[3];
speesy_x5[3] = speesy_x5[2];
speesy_y5[3] = speesy_y5[2];
speesy_x5[2] = speesy_x5[1];
speesy_y5[2] = speesy_y5[1];
speesy_x5[1] = speesy_x5[0];
speesy_y5[1] = speesy_y5[0];

speesy_x5[0] = speesy_value[4]*NewSample;

speesy_y5[0] = ACoef5[0] * speesy_x5[0];
speesy_y5[0] += ACoef5[1] * speesy_x5[1] - BCoef5[0] * speesy_y5[1];
speesy_y5[0] += ACoef5[2] * speesy_x5[2] - BCoef5[1] * speesy_y5[2];
speesy_y5[0] += ACoef5[3] * speesy_x5[3] - BCoef5[2] * speesy_y5[3];
speesy_y5[0] += ACoef5[4] * speesy_x5[4] - BCoef5[3] * speesy_y5[4];
speesy_cannel[4] = speesy_y5[0];
/*************************/
/*************6***********/
speesy_x6[4] = speesy_x6[3];
speesy_y6[4] = speesy_y6[3];
speesy_x6[3] = speesy_x6[2];
speesy_y6[3] = speesy_y6[2];
speesy_x6[2] = speesy_x6[1];
speesy_y6[2] = speesy_y6[1];
speesy_x6[1] = speesy_x6[0];
speesy_y6[1] = speesy_y6[0];

speesy_x6[0] = speesy_value[5]*NewSample;

speesy_y6[0] = ACoef6[0] * speesy_x6[0];
speesy_y6[0] += ACoef6[1] * speesy_x6[1] - BCoef6[0] * speesy_y6[1];
speesy_y6[0] += ACoef6[2] * speesy_x6[2] - BCoef6[1] * speesy_y6[2];
speesy_y6[0] += ACoef6[3] * speesy_x6[3] - BCoef6[2] * speesy_y6[3];
speesy_y6[0] += ACoef6[4] * speesy_x6[4] - BCoef6[3] * speesy_y6[4];
speesy_cannel[5] = speesy_y6[0];
/*************************/
/*************7***********/
speesy_x7[4] = speesy_x7[3];
speesy_y7[4] = speesy_y7[3];
speesy_x7[3] = speesy_x7[2];
speesy_y7[3] = speesy_y7[2];
speesy_x7[2] = speesy_x7[1];
speesy_y7[2] = speesy_y7[1];
speesy_x7[1] = speesy_x7[0];
speesy_y7[1] = speesy_y7[0];

speesy_x7[0] = speesy_value[6]*NewSample;

speesy_y7[0] = ACoef7[0] * speesy_x7[0];
speesy_y7[0] += ACoef7[1] * speesy_x7[1] - BCoef7[0] * speesy_y7[1];
speesy_y7[0] += ACoef7[2] * speesy_x7[2] - BCoef7[1] * speesy_y7[2];
speesy_y7[0] += ACoef7[3] * speesy_x7[3] - BCoef7[2] * speesy_y7[3];
speesy_y7[0] += ACoef7[4] * speesy_x7[4] - BCoef7[3] * speesy_y7[4];
speesy_cannel[6] = speesy_y7[0];
/*************************/
/*************8***********/
speesy_x8[4] = speesy_x8[3];
speesy_y8[4] = speesy_y8[3];
speesy_x8[3] = speesy_x8[2];
speesy_y8[3] = speesy_y8[2];
speesy_x8[2] = speesy_x8[1];
speesy_y8[2] = speesy_y8[1];
speesy_x8[1] = speesy_x8[0];
speesy_y8[1] = speesy_y8[0];

speesy_x8[0] = speesy_value[7]*NewSample;

speesy_y8[0] = ACoef8[0] * speesy_x8[0];
speesy_y8[0] += ACoef8[1] * speesy_x8[1] - BCoef8[0] * speesy_y8[1];
speesy_y8[0] += ACoef8[2] * speesy_x8[2] - BCoef8[1] * speesy_y8[2];
speesy_y8[0] += ACoef8[3] * speesy_x8[3] - BCoef8[2] * speesy_y8[3];
speesy_y8[0] += ACoef8[4] * speesy_x8[4] - BCoef8[3] * speesy_y8[4];
speesy_cannel[7] = speesy_y8[0];
/*************************/
/*************9***********/
speesy_x9[4] = speesy_x9[3];
speesy_y9[4] = speesy_y9[3];
speesy_x9[3] = speesy_x9[2];
speesy_y9[3] = speesy_y9[2];
speesy_x9[2] = speesy_x9[1];
speesy_y9[2] = speesy_y9[1];
speesy_x9[1] = speesy_x9[0];
speesy_y9[1] = speesy_y9[0];

speesy_x9[0] = speesy_value[8]*NewSample;

speesy_y9[0] = ACoef9[0] * speesy_x9[0];
speesy_y9[0] += ACoef9[1] * speesy_x9[1] - BCoef9[0] * speesy_y9[1];
speesy_y9[0] += ACoef9[2] * speesy_x9[2] - BCoef9[1] * speesy_y9[2];
speesy_y9[0] += ACoef9[3] * speesy_x9[3] - BCoef9[2] * speesy_y9[3];
speesy_y9[0] += ACoef9[4] * speesy_x9[4] - BCoef9[3] * speesy_y9[4];
speesy_cannel[8] = speesy_y9[0];
/*************************/
/*************10***********/
speesy_x10[4] = speesy_x10[3];
speesy_y10[4] = speesy_y10[3];
speesy_x10[3] = speesy_x10[2];
speesy_y10[3] = speesy_y10[2];
speesy_x10[2] = speesy_x10[1];
speesy_y10[2] = speesy_y10[1];
speesy_x10[1] = speesy_x10[0];
speesy_y10[1] = speesy_y10[0];

speesy_x10[0] = speesy_value[9]*NewSample;

speesy_y10[0] = ACoef10[0] * speesy_x10[0];
speesy_y10[0] += ACoef10[1] * speesy_x10[1] - BCoef10[0] * speesy_y10[1];
speesy_y10[0] += ACoef10[2] * speesy_x10[2] - BCoef10[1] * speesy_y10[2];
speesy_y10[0] += ACoef10[3] * speesy_x10[3] - BCoef10[2] * speesy_y10[3];
speesy_y10[0] += ACoef10[4] * speesy_x10[4] - BCoef10[3] * speesy_y10[4];
speesy_cannel[9] = speesy_y10[0];
/*************************/
/*************11***********/
speesy_x11[4] = speesy_x11[3];
speesy_y11[4] = speesy_y11[3];
speesy_x11[3] = speesy_x11[2];
speesy_y11[3] = speesy_y11[2];
speesy_x11[2] = speesy_x11[1];
speesy_y11[2] = speesy_y11[1];
speesy_x11[1] = speesy_x11[0];
speesy_y11[1] = speesy_y11[0];

speesy_x11[0] = speesy_value[10]*NewSample;

speesy_y11[0] = ACoef11[0] * speesy_x11[0];
speesy_y11[0] += ACoef11[1] * speesy_x11[1] - BCoef11[0] * speesy_y11[1];
speesy_y11[0] += ACoef11[2] * speesy_x11[2] - BCoef11[1] * speesy_y11[2];
speesy_y11[0] += ACoef11[3] * speesy_x11[3] - BCoef11[2] * speesy_y11[3];
speesy_y11[0] += ACoef11[4] * speesy_x11[4] - BCoef11[3] * speesy_y11[4];
speesy_cannel[10] = speesy_y11[0];
/*************************/
/*************12***********/
speesy_x12[4] = speesy_x12[3];
speesy_y12[4] = speesy_y12[3];
speesy_x12[3] = speesy_x12[2];
speesy_y12[3] = speesy_y12[2];
speesy_x12[2] = speesy_x12[1];
speesy_y12[2] = speesy_y12[1];
speesy_x12[1] = speesy_x12[0];
speesy_y12[1] = speesy_y12[0];

speesy_x12[0] = speesy_value[11]*NewSample;

speesy_y12[0] = ACoef12[0] * speesy_x12[0];
speesy_y12[0] += ACoef12[1] * speesy_x12[1] - BCoef12[0] * speesy_y12[1];
speesy_y12[0] += ACoef12[2] * speesy_x12[2] - BCoef12[1] * speesy_y12[2];
speesy_y12[0] += ACoef12[3] * speesy_x12[3] - BCoef12[2] * speesy_y12[3];
speesy_y12[0] += ACoef12[4] * speesy_x12[4] - BCoef12[3] * speesy_y12[4];
speesy_cannel[11] = speesy_y12[0];
/*************************/
/*************13***********/
speesy_x13[4] = speesy_x13[3];
speesy_y13[4] = speesy_y13[3];
speesy_x13[3] = speesy_x13[2];
speesy_y13[3] = speesy_y13[2];
speesy_x13[2] = speesy_x13[1];
speesy_y13[2] = speesy_y13[1];
speesy_x13[1] = speesy_x13[0];
speesy_y13[1] = speesy_y13[0];

speesy_x13[0] = speesy_value[12]*NewSample;

speesy_y13[0] = ACoef13[0] * speesy_x13[0];
speesy_y13[0] += ACoef13[1] * speesy_x13[1] - BCoef13[0] * speesy_y13[1];
speesy_y13[0] += ACoef13[2] * speesy_x13[2] - BCoef13[1] * speesy_y13[2];
speesy_y13[0] += ACoef13[3] * speesy_x13[3] - BCoef13[2] * speesy_y13[3];
speesy_y13[0] += ACoef13[4] * speesy_x13[4] - BCoef13[3] * speesy_y13[4];
speesy_cannel[12] = speesy_y13[0];
/*************************/
/*************14***********/
speesy_x14[4] = speesy_x14[3];
speesy_y14[4] = speesy_y14[3];
speesy_x14[3] = speesy_x14[2];
speesy_y14[3] = speesy_y14[2];
speesy_x14[2] = speesy_x14[1];
speesy_y14[2] = speesy_y14[1];
speesy_x14[1] = speesy_x14[0];
speesy_y14[1] = speesy_y14[0];

speesy_x14[0] = speesy_value[13]*NewSample;

speesy_y14[0] = ACoef14[0] * speesy_x14[0];
speesy_y14[0] += ACoef14[1] * speesy_x14[1] - BCoef14[0] * speesy_y14[1];
speesy_y14[0] += ACoef14[2] * speesy_x14[2] - BCoef14[1] * speesy_y14[2];
speesy_y14[0] += ACoef14[3] * speesy_x14[3] - BCoef14[2] * speesy_y14[3];
speesy_y14[0] += ACoef14[4] * speesy_x14[4] - BCoef14[3] * speesy_y14[4];
speesy_cannel[13] = speesy_y14[0];
/*************************/
/*************15***********/
speesy_x15[4] = speesy_x15[3];
speesy_y15[4] = speesy_y15[3];
speesy_x15[3] = speesy_x15[2];
speesy_y15[3] = speesy_y15[2];
speesy_x15[2] = speesy_x15[1];
speesy_y15[2] = speesy_y15[1];
speesy_x15[1] = speesy_x15[0];
speesy_y15[1] = speesy_y15[0];

speesy_x15[0] = speesy_value[14]*NewSample;

speesy_y15[0] = ACoef15[0] * speesy_x15[0];
speesy_y15[0] += ACoef15[1] * speesy_x15[1] - BCoef15[0] * speesy_y15[1];
speesy_y15[0] += ACoef15[2] * speesy_x15[2] - BCoef15[1] * speesy_y15[2];
speesy_y15[0] += ACoef15[3] * speesy_x15[3] - BCoef15[2] * speesy_y15[3];
speesy_y15[0] += ACoef15[4] * speesy_x15[4] - BCoef15[3] * speesy_y15[4];
speesy_cannel[14] = speesy_y15[0];
/*************************/
/*************16***********/
speesy_x16[4] = speesy_x16[3];
speesy_y16[4] = speesy_y16[3];
speesy_x16[3] = speesy_x16[2];
speesy_y16[3] = speesy_y16[2];
speesy_x16[2] = speesy_x16[1];
speesy_y16[2] = speesy_y16[1];
speesy_x16[1] = speesy_x16[0];
speesy_y16[1] = speesy_y16[0];

speesy_x16[0] = speesy_value[15]*NewSample;

speesy_y16[0] = ACoef16[0] * speesy_x16[0];
speesy_y16[0] += ACoef16[1] * speesy_x16[1] - BCoef16[0] * speesy_y16[1];
speesy_y16[0] += ACoef16[2] * speesy_x16[2] - BCoef16[1] * speesy_y16[2];
speesy_y16[0] += ACoef16[3] * speesy_x16[3] - BCoef16[2] * speesy_y16[3];
speesy_y16[0] += ACoef16[4] * speesy_x16[4] - BCoef16[3] * speesy_y16[4];
speesy_cannel[15] = speesy_y16[0];
/*************************/
}







P.S. Называться синтезатор речи будет Speesy (от слов speech и synthesizer).
Original source: habrahabr.ru.

https://habrahabr.ru/post/305868/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
Stasy_Ka

Все виды разбора по русскому языку

Суббота, 16 Июля 2016 г. 15:25 (ссылка)

Это цитата сообщения Svetlana-sima Оригинальное сообщение

Все виды разбора по русскому языку








1.

razbor-1 (533x700, 346Kb)



Читать далее...
Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Последние новости о развитии C++

Среда, 13 Июля 2016 г. 19:19 (ссылка)

Недавно в финском городе Оулу завершилась встреча международной рабочей группы WG21 по стандартизации C++, в которой впервые официально участвовали сотрудники Яндекса. На ней утвердили черновой вариант C++17 со множеством новых классов, методов и полезных нововведений языка.







Во время поездки мы обедали с Бьярне Страуструпом, катались в лифте с Гербом Саттером, жали руку Беману Дейвсу, выходили «подышать воздухом» с Винцентом Боте, обсуждали онлайн-игры с Гором Нишановым, были на приёме в мэрии Оулу и общались с мэром. А ещё мы вместе со всеми с 8:30 до 17:30 работали над новым стандартом C++, зачастую собираясь в 20:00 чтобы ещё четыре часика поработать и успеть добавить пару хороших вещей.



Теперь мы готовы поделиться с вами «вкусностями» нового стандарта. Всех желающих поглядеть на многопоточные алгоритмы, новые контейнеры, необычные возможности старых контейнеров, «синтаксический сахар» нового чудесного C++, прошу под кат.



if constexpr (condition)



В C++17 появилась возможность на этапе компиляции выполнять if:



template 
auto rget(const std::pair& p) {
if constexpr (I == 0) {
return p.second;
} else {
return p.first;
}
}


При этом неактиваная ветка ветвления не влияет на определение возвращаемого значения. Другими словами, данный пример скомпилируется и:


  • при вызове rget<0>( std::pair{} ) тип возвращаемого значения будет short;

  • при вызове rget<1>( std::pair{} ) тип возвращаемого значения будет char*.



T& container::emplace_back(Args&&...)



Методы emplace_back(Args&&...) для sequence контейнеров теперь возвращают ссылку на созданый элемент:

// C++11
some_vector.emplace_back();
some_vector.back().do_something();

// C++17
some_vector.emplace_back().do_something();


std::variant



Позвольте представить: std::variant — union, который помнит что хранит.

std::variant v;
v = "Hello word";
assert(std::get(v) == "Hello word");
v = 17 * 42;
assert(std::get<0>(v) == 17 * 42);


Дизайн основан на boost::variant, но при этом убраны все известные недочёты последнего:




  • std::variant никогда не аллоцирует память для собственных нужд;

  • множество методов std::variant являются constexpr, так что его можно использовать в constexpr выражениях;

  • std::variant умеет делать emplace;

  • к хранимому значению можно обращаться по индексу или по типу — кому как больше нравится;

  • std::variant не нуждается в boost::static_visitor;

  • std::variant не умеет рекурсивно держать в себе себя (например функционал наподобие `boost::make_recursive_variant>::type` убран).



Многопоточные алгоритмы



Практически все алгоритмы из заголовочного файла были продублированы в виде версий, принимающих ExecutionPolicy. Теперь, например, можно выполнять алгоритмы многопоточно:

std::vector v;
v.reserve(100500 * 1024);
some_function_that_fills_vector(v);

// Многопоточная сортировка данных
std::sort(std::execution::par, v.begin(), v.end());


Осторожно: если внутри алгоритма, принимающего ExecutionPolicy, вы кидаете исключение и не ловите его, то программа завершится с вызовом std::terminate():

std::sort(std::execution::par, v.begin(), v.end(), [](auto left, auto right) {
if (left==right)
throw std::logic_error("Equal values are not expected"); // вызовет std::terminate()

return left < right;
});




Доступ к нодам контейнера



Давайте напишем многопоточную очередь с приоритетом. Класс очереди должен уметь потокобезопасно сохранять в себе множество значений с помощью метода push и потокобезопасно выдавать значения в определенном порядке с помощью метода pop():






// C++11
void push(std::multiset&& items) {
std::unique_lock lock(values_mutex_);
for (auto&& val : items) {
// аллоцирует память, может кидать исключения
values_.insert(val);
}

cond_.notify_one();
}

value_type pop() {
std::unique_lock lock(values_mutex_);
while (values_.empty()) {
cond_.wait(lock);
}

// аллоцирет память, может кидать исключения
value_type ret = *values_.begin();
// деаллоцирует память
values_.erase(values_.begin());

return ret;
}
// C++17
void push(std::multiset&& items) {
std::unique_lock lock(values_mutex_);

// не аллоцирует память, не кидает исключения.
// работает намного быстрее (см. #2)
values_.merge(std::move(items));

cond_.notify_one();
}

value_type pop() {
std::unique_lock lock(values_mutex_);
while (values_.empty()) {
cond_.wait(lock);
}

// не аллоцирет память и не кидает исключения (см. #2)
auto node = values_.extract(values_.begin());
lock.unlock();

// извлекаем значение из ноды multiset'а
return std::move(node.value());
}


В C++17 многие контейнеры обзавелись возможностью передавать свои внутренние структуры для хранения данных наружу, обмениваться ими друг с другом без дополнительных копирований и аллокаций. Именно это происходит в методе pop() в примере:

// Извлекаем из rbtree контейнера его 'ноду' (tree-node)
auto node = values_.extract(values_.begin());

// Теперь values_ не содрежит в себе первого элемента, этот элемент полностью переехал в node
// values_mutex_ синхронизирует доступ к values_. раз мы вынули из этого контейнера
// интересующую нас ноду, для дальнейшей работы с нодой нет необходимости держать блокировку.
lock.unlock();

// Наружу нам необходимо вернуть только элемент, а не всю ноду. Делаем std::move элемента из ноды.
return std::move(node.value());

// здесь вызовется деструктор для ноды


Таким образом наша многопоточная очередь в C++17 стала:


  • более производительной — за счёт уменьшения количества динамических аллокаций и уменьшения времени, которое программа проводит в критической секции;

  • более безопасной — за счёт уменьшения количества мест, кидающих исключения, и за счет меньшего количества аллокаций;

  • менее требовательной к памяти.



Автоматическое определение шаблонных параметров для классов



В черновик C++17 добавили автоматическое определение шаблонных параметров для шаблонных классов. Это значит, что простые шаблонные классы, конструктор которых явно использует шаблонный параметр, теперь автоматически определяют свой тип:


















Было Стало
std::pair p(17, 42.0);
std::pair p(17, 42.0);
std::lock_guard lck(mut_);
std::lock_guard lck(mut_);
std::lock_guard lck(mut_);
auto lck = std::lock_guard(mut_);


std::string_view



Продолжаем эксурс в дивный мир C++17. Давайте посмотрим на следующую C++11 функцию, печатающую сообщение на экран:

// C++11
#include
void get_vendor_from_id(const std::string& id) { // аллоцирует память, если большой массив символов передан на вход вместо std::string
std::cout <<
id.substr(0, id.find_last_of(':')); // аллоцирует память при создании больших подстрок
}

// TODO: дописать get_vendor_from_id(const char* id) чтобы избавиться от динамической аллокации памяти


В C++17 можно написать лучше:

// C++17
#include
void get_vendor_from_id(std::string_view id) { // не аллоцирует память, работает с `const char*`, `char*`, `const std::string&` и т.д.
std::cout <<
id.substr(0, id.find_last_of(':')); // не аллоцирует память для подстрок
}


std::basic_string_view или std::string_view — это класс, не владеющий строкой, но хранящий указатель на начало строки и её размер. Класс пришел в стандарт из Boost, где он назывался boost::basic_string_ref или boost::string_ref.



std::string_view уже давно обосновался в черновиках C++17, однако именно на последнем собрании было решено исправить его взимодействие с std::string. Теперь файл может не подключать файл , за счет чего использование std::string_view становится более легковесным и компиляция программы происходит немного быстрее.



Рекомендации:


  • используйте единственную функцию, принимающую string_view, вместо перегруженных функций, принимающих const std::string&, const char* и т.д.;

  • передавайте string_view по копии (нет необходимости писать `const string_view& id`, достаточно просто `string_view id`).



Осторожно: string_view не гарантирует, что строчка, которая в нем хранится, оканчивается на символ '\0', так что не стоит использовать функции наподобие string_view::data() в местах, где необходимо передавать нуль-терминированные строчки.



if (init; condition)



Давайте рассмотрим следующий пример функции с критической секцией:

// C++11
void foo() {
// ...
{
std::lock_guard lock(m);
if (!container.empty()) {
// do something
}
}
// ...
}


Многим людям такая конструкция не нравилась, пустые скобки выглядят не очень красиво. Поэтому в C++17 решено было сделать всё красивее:

// C++17
void foo() {
// ...
if (std::lock_guard lock(m); !container.empty()) {
// do something
}
// ...
}


В приведенном выше примере переменная lock будет существовать до закрывающей фигурной скобки оператора if.



Structured bindings



std::set s;
// ...

auto [it, ok] = s.insert(42);
// Теперь it — интегратор на вставленный элемент; ok - bool переменная с результатом.
if (!ok) {
throw std::logic_error("42 is already in set");
}
s.insert(it, 43);
// ...


Structured bindings работает не только с std::pair или std::tuple, а с любыми структурами:

struct my_struct { std::string s; int i; };
my_struct my_function();
// ...

auto [str, integer] = my_function();


А ещё...



В C++17 так же есть:


  • синтаксис наподобие template struct my_class{ /*… */ };

  • filesystem — классы и функции для кросплатформенной работы с файловой системой;

  • std::to_chars/std::from_chars — методы для очень быстрых преобразований чисел в строки и строк в числа с использованием C локали;

  • std::has_unique_object_representations — type_trait, помогающий определять «уникальную-представимость» типа в бинарном виде;

  • new для типов с alignment большим, чем стандартный;

  • inline для переменных — если в разных единицах трансляции присутствует переменная с внешней линковкой с одним и тем же именем, то оставить и использовать только одну переменную (без inline будет ошибка линковки);

  • std::not_fn коректно работающий с operator() const&, operator() && и т.д.;

  • зафиксирован порядок выполнения некоторых операций. Например, если есть выражение, содержащее =, то сначала выполнится его правая часть, потом — левая;

  • гарантированный copy elision;

  • огромное количество математических функций;

  • std::string::data(), возвращающий неконстантый char* (УРА!);

  • constexpr для итераторов, std::array и вспомогательных функций (моя фишечка :);

  • явная пометка старья типа std::iterator, std::is_literal_type, std::allocator, std::get_temporary_buffer и т.д. как deprecated;

  • удаление функций, принимающих аллокаторы из std::function;

  • std::any — класс для хранения любых значений;

  • std::optional — класс, хранящий определенное значение, либо флаг, что значения нет;

  • fallthrough, nodiscard, maybe_unused;

  • constexpr лямбды;

  • лямбды с [this]( /*… */ ){ /*… */ };

  • полиморфные алокаторы — type-erased алокаторы, отличное решение, чтобы передавать свои алокаторы в чужие библиотеки;

  • lock_guard, работающий сразу со множеством мьютексов;

  • многое другое.





Напоследок



На конференции C++Siberia в августе мы постараемся рассказать о новинках С++ с большим количеством примеров, объяснить, почему именно такой дизайн был выбран, ответим на ваши вопросы и упомянем множество других мелочей, которые невозможно поместить в статью.



Расскажите о чём бы вам было интересно почитать
















































Проголосовало 11 человек. Воздержалось 3 человека.





Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.


Original source: habrahabr.ru.

https://habrahabr.ru/post/304510/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Гильоши

Вторник, 12 Июля 2016 г. 13:29 (ссылка)

Гильоши — это характерные узоры на деньгах и ценных бумагах. Они красивы, и сочетают в себе одновременно заметную сложность с внутренней простотой — когда кажется, что ты вот-вот уловишь принцип, но он каждый раз от тебя ускользает. Возможно, именно это и есть определение красоты.



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



Само название происходит от фамилии французского инженера Гилльо (Guillot), о котором не осталось никаких сведений. Не исключено, что это вообще чисто мифическая фигура.



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



Примерно в середине XIX века кому-то пришла в голову идея приспособить такой станок для генерации сложных узоров на типографской пластинке. Скорее всего, это были американцы, поскольку на их деньгах гильоши появились раньше всего — на выпуске 1862 года, и очень быстро стали одним из главных элементов дизайна.



image



Постепенно их заимствовали почти все развитые страны — кроме Франции, которая придерживалась исключительно живописной манеры рисования банкнот, не отвлекаясь на механические штучки.



На российских деньгах гильоши первый раз были напечатаны в выпуске 1892 года.

image



Если рассматривать сами узоры на деньгах разных стран, то можно заметить, что, несмотря на общий принцип, они довольно сильно различаются. Отсюда можно сделать вывод, что каждый разрабатывал соответствующие станки самостоятельно. Заметна и корреляция — чем развитее страна, тем ее гильоши сделаны лучше. Для примера достаточно посмотреть на румынские деньги времен Чаушеску, где для гильошировочной машины, похоже, использовались детали от трактора.



image



Создание гильошей было сложным делом — настолько сложным, что этим занимались отдельные люди, имевшие особую профессию гильошировщика. По некоторым сведениям можно понять, что гильошировщики рисовали гильош по эскизу художника — это видно из приводимого примера наброска и готовой банкноты в 1 червонец 1926 года. Не удивлюсь, если они это делали путем механической подгонки деталей, а то и вообще перебирали машину заново.









Сейчас гильоши из моды вышли, поскольку они могут противостоять только рисованию денег руками — попробуй чернилами вычертить все эти мелкие кривые. При использовании оптического копирования они бесполезны — сканеру все равно, что считывать: узоры или портреты. Так что на современных банкнотах гильошей обычно уже нет или они скромно торчат где-нибудь в углу как дань традиции.



Вычислить алгоритм для рисования гильошей крайне сложно — хотя на вид они кажутся достаточно простыми. Во многих источниках пишут, что это всего лишь усложненная версия спирографа с несколькими колесами, но я в этом сильно сомневаюсь. Многоколесный спирограф несложно повторить на компьютере, но получающиеся узоры во-первых, нисколько гильоши не напоминают, а во-вторых, их невозможно подогнать к заранее заданным контурам.



Ясно, что гильош — это семейство синусоид, сдвинутых по фазе относительно друг друга, и искажающихся в зависимости от внешних контуров так, чтобы не переходить их границы. Это очевидно — но совсем не очевидно, как именно математически контуры на синусоиды влияют.



На самом деле принцип построения узоров довольно прост, но несколько странноват. Они считаются по точкам, причем простых алгебраических операций над тремя кривыми (внутренним, внешним контуром и синусоидой, стелящейся между ними) недостаточно — нужно еще решать уравнения, чтобы определить пересечение линии и кривой.



Собственно, в каждой точке мы ставим точку синусоиды, но каждый раз разной — как бы модулированной текущим состоянием ограничивающих контуров.



Как именно необходимые вычисления выполнялись на механических станках, выше моего понимания.



Итак, принцип рисования. Мы начнем с горизонтального гильоша, потому что он проще. Внимание на экран.







Зеленым цветом выделены контуры, ограничивающие наш гильош. Будем считать их нижним и верхним и рассчитаем значение точки гильоша в абсциссе t.



Прежде всего найдем точки PB и PT — точки контуров при t. Заодно высчитаем в этом месте векторы направления кривых.



Теперь найдем некую среднюю точку Mid между нижним и верхним контуром. Именно от нее будет отсчитываться рисование нашей красивой кривой. Мы можем взять просто точку, среднюю между PB и PT, а можем еще умножить ее на некий коэффициент 0..1, показывающий, в какой пропорции следует учитывать нижний и верхний контур. Тогда мы сможем чуть смещать гильош вверх-вниз между контурами, чтобы добиться более красивых фигур.



Высчитаем в этой точке вектор направления как средний между векторами в точках PB и PT. Найдем для него перпендикуляр.



Посчитаем значение самой обыкновенной синусоиды в точке t (в предположении, что она начинается в точке 0,0 и движется вдоль оси ординат вправо).



Теперь исказим эту синусоиду следующим образом: перенесем текущее значение ее аргумента (t,0) в точку Mid, ее осью X сделаем «средний вектор», а осью Y, соответственно, перпендикуляр к нему. Тогда ее текущая точка окажется в точке RP.



Осталось только смодулировать амплитуду этой синусоиды. Посчитаем расстояние Mid--IP, то есть расстояние от средней точки до первой точки пересечения перпендикуляра с контуром. Какой контур брать, верхний или нижний, мы определим по значению исходной синусоиды — находится она выше оси ординат или ниже. На рисунке изображен случай, когда значение эталонной синусоиды больше нуля и мы используем верхний контур.



Теперь масштабируем Mid--RP, считая расстояние Mid--IP единицей, и отложим это значение вдоль новой оси ординат, т.е. по перпендикуляру. Мы получим точку GP — она и будет искомой точкой гильоша.



Перейдем к программированию. Вот программа рисования горизонтального гильоша на языке Asymptote:



import graph;
import wave;

size(1000,1000);
xaxis(ticks=Ticks);
yaxis(ticks=Ticks);

defaultpen(2);

var zero = (0,0);

typedef pair pairf(real x);

///////////////////////////////////////////

// Единичный вектор, перпендикулярный к вектору (0,0)--v
pair orthogonal(pair v)
{
return unit((-v.y,v.x));
}

// Точка и направление кривой в точке с координатами x,path(x)
pair[] pt_and_dir(path p, real x)
{
var t = times(p,x)[0];
return new pair[]{point(p,t), dir(p,t)};
}

// Функция, рассчитывающая точку гильоша в точке с абсциссой t
pairf between(path top, path bottom, real topk=0.5, real phase, real omega)
{
return new pair(real t)
{
// Точка и направление верхнего и нижнего контура
var pdt = pt_and_dir(top,t);
var pdb = pt_and_dir(bottom,t);

// "Средняя" точка как смесь из верхней и нижней
var mid = topk*pdt[0] + (1-topk)*pdb[0];
// Выведем для наглядности среднюю точку
draw(mid,gray);
// Вектор, перпендикулярный смеси направлений верхней и нижней точки
var ort = orthogonal(topk*pdt[1] + (1-topk)*pdb[1]);

// Точка на обычной синусоиде, которую мы сейчас будем модулировать
var f = sin(phase+omega*t);

// Вектор, в сторону которого модуляция отклонит точку
var rp = rotate(degrees(atan2(ort.y,ort.x)-pi/2),zero) * (0,f);

// Рассчитываем точку пересечения перпендикулярного вектора с одним из контуров
// Для этого узнаём все точки пересечения и берем из них ближайшую
var ipath = rp.y >= 0 ? top : bottom;
var inter = intersections(ipath,mid,mid+ort);
var interp = sequence(new pair(int i) {return point(ipath,inter[i]); }, inter.length);
interp = sort(interp, new bool(pair a, pair b) {return abs(mid.x-a.x) < abs(mid.x-b.x); });
var ip = interp[0];

// Узнаем расстояние от "средней точки" до точки пересечения перпендикулярного вектора с контуром
var r = sqrt((mid.x-ip.x)*(mid.x-ip.x)+(mid.y-ip.y)*(mid.y-ip.y));

// Модулируем синусоиду
return mid+r*rp;
};
}

// Рисуем гильош несколько раз со сдвигом
void repeat(int n, path top, path bottom, real topk, real freq)
{
var step = 2pi/n;
for (var i: sequence(0,n))
{
draw(graph(between(top,bottom, topk, i*step, freq), 0,8, 500));
}
}

// Верхний контур - просто что-то типа синусоиды
path top = shift(0,0.3)*(4*make_wave(1.4, (+1,+0.7),(+1,-0.7) ));

// Нижний - прямая
path bottom = (0,0)--(8,0);

draw(top, blue);
draw(bottom, blue);

// укладываем между ними 9 "синусоид" с частотой 11, проходящих точно посередине между верхним и нижним контуром
repeat(9, top, bottom, 0.5, 11);




А вот результат ее работы. Изящно.







С круговыми гильошами — как раз теми, что обычно фигурируют на деньгах — дело усложняется. Принцип остается тем же, но…



1. Вместо декартовых координат приходится работать в полярных

2. Кривые становятся капризными и начинают себя плохо вести. При более-менее сложных контурах в некоторых точках возникает ситуация, когда перпендикуляр вовсе не пересекается с нужным контуром. Очевидно, в таких случаях и требуется многолетний опыт гильошировщика.



Итак, программа. Обратите внимание, что в ней контуры по аналогии с предыдущей программой называются верхним и нижним, хотя реально они внешние и внутренние.



import graph;
import wave;

size(1000,1000);

xaxis(ticks=Ticks);
yaxis(ticks=Ticks);

defaultpen(5);

var zero = (0,0);

typedef pair pairf(real x);
typedef pair[] pairaf(real t);

///////////////////////////////////////////

// Определение перпендикулярного вектора
pair orthogonal(pair v)
{
return unit((-v.y,v.x));
}

// Пересчет полярных координат в декартовые
pair cart(real a, real r)
{
return (r*cos(a), r*sin(a));
}

// Нормализованный угол по вектору-направлению
real atan2p(pair v)
{
var a = atan2(v.y,v.x);
return a<0 ? a+2pi : a;
}

// Расстояние между двумя точками
real distance(pair a, pair b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

// Точка и вектор направления на пути p при полярном угле a
pair[] pt_and_dir(path p, real a)
{
var ii = intersections(p,zero--cart(a,100));
if (ii.length==0)
{
write(p);
write(a);
}
var t = ii[0];
return new pair[]{point(p,t[0]), dir(p,t[0])};
}

// Вычисление точек гильоша, если имеется функция midpoint, рассчитывающая координаты и направление в средней точке
pairf between(path top, path bottom, pairaf midpoint, real phase, real omega)
{
return new pair(real t)
{
var b = midpoint(t);
var mid = b[0];
draw(mid,green);
var mid_dir = b[1];
var f = sin(phase+omega*t);

var angle = (degrees(atan2p(mid_dir))+180) % 360;

var rp = rotate(angle,zero) * (0,f);

//На какой контур смотрит вектор нашей точки синусоиды - на верхний или нижний?
var ipath = distance(mid+rp,zero) > distance(mid,zero) ? top : bottom;

// Найдем точки пересечения перпендикуляра с контуром
var inter = intersections(ipath,mid,mid+rp);

// Вот тут-то и засада. Пересечений с контуром может вообще не быть. Выводим тогда линию противного цвета,
// чтобы это было сразу заметно
if (inter.length==0)
{
draw(mid--mid+rp,magenta,Arrow);
return mid;
}

// Отсортируем точки пересечения и найдем самую ближнюю
var interp = sequence(new pair(int i) {return point(ipath,inter[i]); }, inter.length);
interp = sort(interp, new bool(pair a, pair b) {return distance(mid,a) < distance(mid,b); });
var ip = interp[0];

var r = distance(mid,ip);
return mid + r*rp;
};
}

// Вычисление точек гильоша, если задан средний путь
pairf between(path top, path bottom, path base, real phase, real omega)
{
pairaf mf = new pair[](real t) { return pt_and_dir(base, t); };
return between(top, bottom, mf, phase, omega);
}

// Вычисление точек гильоша, если дан коэффициент смешивания верхнего и нижнего контуров
pairf between(path top, path bottom, real topk=0.5, real phase, real omega)
{
pairaf midpoint = new pair[](real t)
{
var pdt = pt_and_dir(top,t);
var pdb = pt_and_dir(bottom,t);
var mid = topk*pdt[0] + (1-topk)*pdb[0];
var mid_dir = topk*pdt[1] + (1-topk)*pdb[1];
return new pair[]{mid, mid_dir};
};
return between(top, bottom, midpoint, phase, omega);
}

// Рисование гильоша с вычислением средней линии (как в программе с горизонтальным гильошем)
void repeat(int n, path top, path bottom, real topk, real freq)
{
var step = 2pi/n;
for (var i: sequence(0,n-1))
{
draw(graph(between(top,bottom, topk, i*step, freq), 0, 2pi, 500));
}
}

// Вариант - средняя линия не вычисляется, а задается отдельным путем
void repeat(int n, path top, path bottom, path base, real freq)
{
var step = 2pi/n;
for (var i: sequence(0,n-1))
{
draw(graph(between(top,bottom,base, i*step, freq), 0, 2pi, 500));
}
}

// Контуры - внешний и внутренний. Чтобы не возиться с вычислением их координат, я просто обвел их в векторном редакторе,
// сохранил как SVG и извлек из текста описание пути
path top = (458.43,237.715)..controls (468.922,264.461) and (481.563,290.133)..(466.797,322.145)
..controls (438.688,358.184) and (392.762,345.094)..(362.438,351.945)
..controls (354.488,353.742) and (350.508,354.398)..(342.07,358.234)
..controls (338.023,360.074) and (333.797,358.609)..(329.125,358.598)
..controls (324.457,358.582) and (319.348,360.02)..(315.824,363.094)
..controls (306.16,371.52) and (294.707,387.746)..(278.176,400.949)
..controls (261.645,414.152) and (250.875,417.965)..(236.914,417.996)
..controls (222.957,418.023) and (213.074,414.152)..(196.543,400.949)
..controls (180.012,387.746) and (168.559,371.52)..(158.895,363.094)
..controls (155.371,360.02) and (150.262,358.582)..(145.594,358.598)
..controls (140.922,358.609) and (136.695,360.074)..(132.648,358.234)
..controls (124.211,354.398) and (120.23,353.742)..(112.281,351.945)
..controls (81.957,345.094) and (36.0313,358.184)..(7.92188,322.145)
..controls (-6.84375,290.133) and (5.79688,264.461)..(16.2891,237.715)
..controls (19.1992,230.289) and (11.7227,218.836)..(11.7227,209.773)
..controls (11.7227,200.711) and (19.1992,188.906)..(16.2891,181.48)
..controls (5.79688,154.734) and (-6.84375,129.063)..(7.92188,97.0508)
..controls (36.0313,61.0078) and (81.957,74.0977)..(112.281,67.2461)
..controls (120.23,65.4531) and (124.211,64.7969)..(132.648,60.9609)
..controls (136.695,59.1211) and (140.922,60.582)..(145.594,60.5977)
..controls (150.262,60.6094) and (155.371,59.1719)..(158.895,56.1016)
..controls (168.559,47.6719) and (180.012,31.4492)..(196.543,18.2461)
..controls (213.074,5.03906) and (222.957,1.16797)..(236.914,1.19922)
..controls (250.875,1.22656) and (261.645,5.03906)..(278.176,18.2461)
..controls (294.707,31.4492) and (306.16,47.6719)..(315.824,56.1016)
..controls (319.348,59.1719) and (324.457,60.6094)..(329.125,60.5977)
..controls (333.797,60.582) and (338.023,59.1211)..(342.07,60.9609)
..controls (350.508,64.7969) and (354.488,65.4531)..(362.438,67.2461)
..controls (392.762,74.0977) and (438.688,61.0078)..(466.797,97.0508)
..controls (481.563,129.063) and (468.922,154.734)..(458.43,181.48)
..controls (455.52,188.906) and (462.996,200.238)..(463.055,209.359)
..controls (463.113,218.48) and (455.52,230.289)..(458.43,237.715)
--cycle;

path bottom = (435.121,232.246)..controls (424.465,250.848) and (436.73,269.879)..(418,294.242)
..controls (399.266,318.602) and (368.48,321.363)..(355.004,331.102)
..controls (341.531,340.84) and (349.316,349.461)..(338.301,353.699)
..controls (327.289,357.934) and (311.055,338.211)..(297.848,342.762)
..controls (277.797,349.668) and (257.313,362.477)..(235.926,362.551)
..controls (214.543,362.629) and (196.012,350.156)..(175.961,343.25)
..controls (162.75,338.699) and (146.52,358.422)..(135.504,354.188)
..controls (124.492,349.949) and (132.277,341.328)..(118.805,331.59)
..controls (105.328,321.852) and (74.5391,319.09)..(55.8086,294.73)
..controls (37.0742,270.367) and (49.3438,251.336)..(38.6875,232.734)
..controls (33.918,224.414) and (17.0078,213.824)..(17.0078,209.363)
..controls (17.0078,204.902) and (33.9258,194.051)..(38.6953,185.727)
..controls (49.3555,167.129) and (37.082,148.094)..(55.8242,123.734)
..controls (74.5625,99.375) and (105.359,96.6094)..(118.84,86.875)
..controls (132.32,77.1367) and (124.531,68.5117)..(135.547,64.2773)
..controls (146.566,60.043) and (162.805,79.7617)..(176.016,75.2148)
..controls (196.078,68.3086) and (214.613,55.832)..(236.008,55.9102)
..controls (257.398,55.9883) and (277.891,68.7969)..(297.953,75.7031)
..controls (311.164,80.2539) and (327.402,60.5313)..(338.418,64.7656)
..controls (349.438,69.0039) and (341.648,77.625)..(355.129,87.3633)
..controls (368.609,97.0977) and (399.406,99.8633)..(418.145,124.223)
..controls (436.887,148.586) and (424.613,167.617)..(435.273,186.219)
..controls (440.043,194.539) and (456.961,205.215)..(456.926,209.535)
..controls (456.887,213.859) and (439.891,223.926)..(435.121,232.246)
--cycle;

// Подгоняем под масштаб нашего рисунка
top = scale(1/10)*top;
bottom = scale(1/10)*bottom;

// И смещаем контуры из центра координат в левый верхний квадрант
var min = min(top);
var max = max(top);
top=shift(-(max.x-min.x)/2, -(max.y-min.y)/2)*top;

min = min(bottom);
max = max(bottom);
bottom=shift(-(max.x-min.x)/2-min.x, -(max.y-min.y)/2-min.y)*bottom;

draw(top, blue);
draw(bottom, blue);

// Пускаем 4 синусоиды
repeat(4, top, bottom, 0.5, 18);


Результат — нечто похожее на розетку с купона в 25 белорусских рублей 1992 года. Можно сделать еще похожей, если самому аккуратно нарисовать среднюю линию (см. второй рисунок).















Некоторые линии на нашем рисунке получились с зазубринами — это из-за недостатка точности вычислений. В какой-то степени их можно исправить, поставив в операторе draw расчет не 500, а 10000 точек.



Что можно еще придумать с гильошами?



Во-первых, если внимательно посмотреть на белорусскую версию, то заметно, что тамошние узоры еще меняют свою частоту — они становятся то гуще, то реже. Как учитывать частоту в моей программе — я так и не придумал.



Во-вторых, гильоши прямо-таки напрашиваются быть сохраненными в виде кривых Безье — они очень хорошо ими аппроксимируются. Но для этого надо понимать, как они себя ведут — где у них вершины, где точки перегиба. Вычислять это из набора точек как-то глупо, а как подойти к вопросу математически, например, посчитав производную, — непонятно.



Если у многоуважаемой публики есть на этот счет какие-то соображения, прошу делиться.



P.S. Рисунки в статье отмасштабированы, чтобы не портить общий вид страницы. Вы можете открыть их отдельно и рассмотреть с лучшим разрешением.
Original source: habrahabr.ru.

https://habrahabr.ru/post/305354/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество

Следующие 30  »

<алгоритмы - Самое интересное в блогах

Страницы: [1] 2 3 ..
.. 10

LiveInternet.Ru Ссылки: на главную|почта|знакомства|одноклассники|фото|открытки|тесты|чат
О проекте: помощь|контакты|разместить рекламу|версия для pda