Академия гитарной электроники: Цифровой гитарный процессор - Академия гитарной электроники

Перейти к содержимому

  • 2 Страниц +
  • 1
  • 2
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

Цифровой гитарный процессор Обсуждение подробностей управления и общего дизайна

#1 Пользователь офлайн   Rst7 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 26 мая 2010 - 16:45

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

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

Собственно говоря, текущее состояние канала обработки таково:

  • Вход ->
  • регулируемый усилитель 0...+20дБ (дабы совместить максимальный уровень входного сигнала с макс. входным уровнем АЦП) ->
  • аналоговый вход VS1053 ->
  • АЦП ->
  • Подмешивание шума в дробную часть входного сигнала (может быть будет не нужно) ->
  • Устраниение постоянной составляющей обычным RC-фильтром ->
  • НЧ-фильтр с частотой среза 5.5кГц, он же добавляет пару бит к входному разрешению из-за дизеринга ->
  • Биквадратный фильтр предэквализации (управление - центральная частота, добротность (или полоса), усиление/затухание) ->
  • Регулятор гейна 0...+60..70дБ ->
  • Каскад ограничения (с регулировкой постоянной времени выпрямителя и регулировкой отношения четные/нечетные гармоники) ->
  • Устраниение постоянной составляющей обычным RC-фильтром ->
  • НЧ-фильтр с частотой среза 4.5кГц ->
  • Эквалайзер 19 полос (третьоктавный, диапазон 80...5000Гц) ->
  • Имитатор ограничения в выходном каскаде (тоже с возможностью регулировки четные/нечетные и постоянной времени) ->
  • Устраниение постоянной составляющей обычным RC-фильтром ->
  • НЧ-фильтр с частотой среза 4.5кГц ->
  • Преобразователь моно в стерео (пока в виде просто задержки в одном из каналов на несколько миллисекунд) ->
  • Стереоревербератор (пока не сделан, но сделаю) по мотивам multi-tap delay в Sound Forge ->
  • ЦАП ->
  • аналоговый выход VS1053 ->
  • собственно выход (в который, кстати, можно хоть прям уши воткнуть напрямую).

Еще можем влепить туда кваку (ибо это всего то один фильтр) и, например, еще какие-либо эффекты.

+небольшой бонус - дополнительный аналоговый вход (к сожалению, моно), который, например, можно подмешать к сигналу перед отправкой его в выходной ЦАП.

Рядом с VS1053 будет стоять проц общего назначения, работа которого будет заключаться в начальной загрузке софта в VS1053, работе интерфейса человек-машина, и плюс - поддержка внешних интерфейсов (пока планируется USB для компа и видимо MIDI для руления этим делом на ходу, в частности, я бы педаль экспрессии по MIDI прислонил).

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

Однако, кое-кто из моих знакомых возражает против такого подхода и хочет иметь возможность полноценного управления девайсом прямо с него. Вот я сейчас в глубоких раздумьях, как же строить это дело.
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
0

#2 Пользователь офлайн   Маклауд 

  • Злой модер
  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 26 мая 2010 - 17:27

19 полос - переболт. Может лучше параметрический на 2 полосы плюс срез вч и нч? По возможностям будут сравнимы, но параметрический в разы удобнее.
Чтобы с юзверем общаться, нужно повешать пару энкодеров. И тактовых кнопок по количеству параметров регулировки. Алгоритм такой - если надо добавить ВЧ, нажимаем кнопку "Срез ВЧ", затем крутим один энкодер, который будет отвечать за частоту среза, и второй, который будет собственно обрезать.
Кстати, стоит добавить экранчик от сименса сх65. Очень популярны, дёшевы, просты в обращении. Ну и где-то надо показывать пресеты, по возможности и АЧХ эквалайзера, другие данные.
Правда, у меня появляются подозрения, что проект будет непопулярен. Во-первых, из-за сложности. У меня тут драйвер к пружинному реверу либо даёт фузз, либо реалистично имитирует звук харлея, строит из себя прямоугольное тремоло или генерирует 500 кГц. А в схеме-то тл074 и лм386, проще фузз фэктори, который с первого раза завёлся...
И во-вторых, что если этот проц обзаведётся недостатками всех гитарных процов? Например разные гитары (даже самик страт за 1000 р и Лес Пол за $1000) звучат одинаково, причём независимо от положения ручек. И в миксе гитару не слышно, хотя когда все молчат она уши режет.
"...Металлисты - это самый развитой и передовой класс, и никто не может отрицать, что это и есть передовой отряд всего пролетариата." (В.И. Ленин, "Полное Собрание Сочинений", том 24)
0

#3 Пользователь офлайн   Rst7 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 26 мая 2010 - 18:08

Цитата

19 полос - переболт. Может лучше параметрический на 2 полосы плюс срез вч и нч? По возможностям будут сравнимы, но параметрический в разы удобнее.


Да как сказать. Есть некоторый кайф и в эквалайзере (для тонкой настройки). Я бы может сделал вот что - помимо эквалайзера добавил бы НЧ/ВЧ+2 параметрики. Практически ничего не стоит. Эквалайзер - только с компа крутить, а параметрику можно и вручную. Хотя опять же, ручек, получается, надо 3 - ибо есть частота, добротность, усиление. С другой стороны, любой узел можно будет этими тремя ручками крутить (практически).

Цитата

Кстати, стоит добавить экранчик от сименса сх65.


Нет уж. Это против моих профессиональных принципов. Обойдемся классическим вариантом ЧБ 128*64 за 15 долларов:
Изображение
(даташит)

Хотя, лучше уж вот таких:
Изображение
подробнее, и подсветочка на любой вкус

Так, а по интерфейсам есть предложения?

Цитата

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


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

Цитата

И во-вторых, что если этот проц обзаведётся недостатками всех гитарных процов?


Вот и постараемся не допустить.
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
0

#4 Пользователь офлайн   ericdriven 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 26 мая 2010 - 18:32

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

#5 Пользователь офлайн   Rst7 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 26 мая 2010 - 18:35

Цитата

думаю все же пара ручек не помешает


Ну я тоже склоняюсь к трем энкодерам и кнопкам выбора, чего эти энкодеры будут крутить. Это Маклауд хорошую идею подал, принимается.

PS Пойду поищу энкодеры подходящие.

Сообщение отредактировал Rst7: 26 мая 2010 - 18:36

"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
0

#6 Пользователь офлайн   ericdriven 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 01 июня 2010 - 12:56

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

PS. хотя чет гемора какогото придумал)) щас на чипдипе смотрю там можно найти разные энкодеры.
http://lib.chipdip.r...OC000054709.pdf вот например.

Сообщение отредактировал ericdriven: 01 июня 2010 - 13:05

0

#7 Пользователь офлайн   Rst7 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 01 июня 2010 - 13:07

Цитата

PS. хотя чет гемора какогото придумал))


Истинно так. Там красная цена - доллар :clapping:
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
0

#8 Пользователь офлайн   ericdriven 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 01 июня 2010 - 13:17

Пытался код скомпилить, что то он у меня ругался непомню уже на что, библиотечку вроде не мог какую то подключить, хотя в системе была она((
как продвигаются разработки, есть новые идеи??
0

#9 Пользователь офлайн   Rst7 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 01 июня 2010 - 13:38

Цитата

Пытался код скомпилить, что то он у меня ругался непомню уже на что, библиотечку вроде не мог какую то подключить, хотя в системе была она((


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

Цитата

как продвигаются разработки, есть новые идеи??


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

#10 Пользователь офлайн   ericdriven 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 01 июня 2010 - 13:50

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


PS. сейчас мысль появилась - если там будет USB то можно его использовать для 2х целей, сохранять пресеты в энергонезависимой памяти и можно примонстрячить декодер mp3\wav файлов и заливать на флягу минуса.

Сообщение отредактировал ericdriven: 01 июня 2010 - 14:22

0

#11 Пользователь офлайн   Rst7 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 01 июня 2010 - 15:44

Цитата

помоему неплохо подойдут bourns PEC12 какие нить


Дык их и заложил.

Цитата

если там будет USB


Там будет USB. Ибо по нынешним временам только так.

Цитата

можно примонстрячить декодер mp3\wav файлов и заливать на флягу минуса.


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

Цитата

а схемка как готова будет можно ее заполучить как то для испытательных целей?)


Можно конечно.
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
0

#12 Пользователь офлайн   ericdriven 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 11 июня 2010 - 13:23

как дело продвигается?? а то я с дипломом выпал из жизни))
0

#13 Пользователь офлайн   Rst7 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 11 июня 2010 - 15:47

Цитата

как дело продвигается??


Сей секунд - стоит. Ибо я в Киеве щас, закрываю вопросы по работе. А вот следующая неделя будет вполне в моем личном распоряжении, буду трудиться на благо этого проекта.
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
0

#14 Пользователь офлайн   Reystlin 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 12 июня 2010 - 09:52

http://easyelectronics.ru/enkoder-iz-perem...a.html#more-226
0

#15 Пользователь офлайн   Rst7 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 14 июня 2010 - 19:00

Reystlin, да ну нафиг. Они живые стоят столько-же, сколько резисторы. Ну может в полтора раза дороже.

Цитата

а схемка как готова будет можно ее заполучить как то для испытательных целей?)


Имеется в виду живое железо? Или схема именно железяки? Если железяки, то примерно вот такое получается:
Прикрепленное изображение: DTD.PNG

Пока только MIDI не пририсовал (лень рисовать компонент разъема DIN5 в плату).

Вот такая PCB выходит:
Прикрепленное изображение: DTD_COMP.PNGПрикрепленное изображение: DTD_SOLD.PNG

Сборочка:
Прикрепленное изображение: DTD_SB.PNG
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
1

#16 Пользователь офлайн   FeonKO 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 14 июня 2010 - 23:55

Rst7, Если акуратно, то можна спаять, если оооочень акуратно и нормальным паяльником... и то сложно чрезмерно. А вот как плату такую изготовить. Тем болие в домашних условиях... мжет сразу развести все на нормальной платке, пускай даже с СМД, но с нормальной толщиной дорожек, болие реальной для повторения, а вот микросхемки - тупо купить готовые заплатки под них... есть такие - продают частенько, тобиш там от этого заплатка уже нормальные выводы, с большими растояниями между дорожками, тобиш те которые легче паять. ИМХО.
0

#17 Пользователь офлайн   Rst7 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 15 июня 2010 - 00:31

Цитата

Если акуратно, то можна спаять, если оооочень акуратно и нормальным паяльником... и то сложно чрезмерно.


Поверьте, я такое паяю 25тиваттным паяльником 220тивольтовым. Классическим. Типоразмер 0805 - это фигня. И шаг 0.25мм/0.25мм - тоже.

Вот, например, полусобранная плата одного девайса (не из оперы гитарных примочек =) ):
Изображение

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

Если уж так страшно - могу дать исходник схемы в PCAD'е, можете развести под свои желания.

Сообщение отредактировал Rst7: 15 июня 2010 - 00:37

"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
1

#18 Пользователь офлайн   FeonKO 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 15 июня 2010 - 01:59

Rst7, Нет, я только про то говорил, что плату сложно сделать, поэтому и предложил вариант с разводкой таких элементов на уже готовых так сказать макетиках.
0

#19 Пользователь офлайн   Rst7 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 15 июня 2010 - 02:09

Цитата

предложил вариант с разводкой таких элементов на уже готовых так сказать макетиках


Не, это без меня =)
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
0

#20 Пользователь офлайн   Svet 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 15 июня 2010 - 11:33

Да ну - очень простая печатка. Лутом конечно сложновато, а вот с ФР в легкую. Единственное что я бы сделал - слегка пересмотрел ее на предмет метализации отверстий - вот это дома точно не сделаешь. А вот проволочки между слоями - это всегда пожалуйста.
2B OR NOT 2B = FF
http://svetguitars.com
0

#21 Пользователь офлайн   Rst7 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 15 июня 2010 - 12:02

Цитата

А вот проволочки между слоями - это всегда пожалуйста.


Проволочки - это, конечно, хорошо, но есть места, где их не особо воткнешь (под камнями). Можно, конечно, попробовать убрать переходы из-под микросхем, но, как-то у меня сложился уже способ дизайна плат (с точки зрения помехозащищенности и прочего), не хочется от него отступать.
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
0

#22 Пользователь офлайн   Svet 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 15 июня 2010 - 12:55

Rst7, а я вот под камнями заливку землей делаю, как в даташите прописано... Ну ладно, мелочи жизни... кому надо - переделает.
2B OR NOT 2B = FF
http://svetguitars.com
0

#23 Пользователь офлайн   Rst7 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 16 июня 2010 - 01:59

Цитата

а я вот под камнями заливку землей делаю, как в даташите прописано...


Тут тоже заливка. Главное - обеспечить одинаковый потенциал на земляных выводах. Ну и плюс пути тока.

Пока суть да дело, причесал немного код для большого брата (с точки зрения последующего портирования на DSP) и впилил ревер.

//---------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <winbase.h>
#include <string.h>
#include <math.h>

#pragma hdrstop

//---------------------------------------------------------------------------

typedef struct
{
  long Y;
  unsigned long TAU;
}HPF;

typedef struct
{
  long Y;
  unsigned long TAU;
}LPF;

typedef struct
{
  unsigned long GAIN;
  unsigned long ODDEVEN;
  LPF zero;
}SQ_DIST;

typedef struct
{
  signed long a0;
  signed long a1;
  signed long a2;
  signed long b1;
  signed long b2;
  signed long mem0;
  signed long mem1;
  signed long mem2;
  signed long mem3;
}BIQUAD;

typedef struct
{
  LPF filter;
  LPF filter_low;
  int fuse;
}ENV_DETECT;

signed long DebugSample;

static signed long LowPassFilter(signed long s, LPF *f)
{
  signed long long acc;
  acc=f->Y-s;
  acc*=f->TAU;
  if (acc>0)
  {
    acc+=0x8000;
    acc>>=16;
  }
  else
  {
    acc=-acc;
    acc+=0x8000;
    acc>>=16;
    acc=-acc;
  }
  acc=f->Y-acc;
  if (acc>0x7FFFFFFF) acc=0x7FFFFFFF;
  if (acc<-0x7FFFFFFF) acc=-0x7FFFFFFF;
  f->Y=acc;
  return acc;
}

static unsigned long int_sqrt(unsigned long v)
{
  unsigned int mask=0x00008000;
  unsigned int result=0;
  do
  {
    result|=mask;
    if (result*result>v) result&=~mask;
  }
  while(mask>>=1);
  return result;
}

static signed long HighPassFilter(signed long s, HPF *f)
{
  signed long long acc;
  acc=f->Y-s;
  acc*=f->TAU;
  if (acc>0)
  {
    acc+=0x8000;
    acc>>=16;
  }
  else
  {
    acc=-acc;
    acc+=0x8000;
    acc>>=16;
    acc=-acc;
  }
  acc=f->Y-acc;
  if (acc>0x7FFFFFFF) acc=0x7FFFFFFF;
  if (acc<-0x7FFFFFFF) acc=-0x7FFFFFFF;
  f->Y=acc;
  return s-f->Y;
}

static signed long SquareDist(signed long s, SQ_DIST *d)
{
  signed long long acc;
  signed long z;
  if (s>d->zero.Y)
  {
    //Пиковый детектор
    z=LowPassFilter(s*3,&d->zero);
  }
  else
  {
    z=LowPassFilter(s,&d->zero);
  }
  //DebugSample=z;
  acc=(signed long long)z*d->ODDEVEN;
  acc+=1ULL<<15;
  acc>>=16;
  acc+=s;
  if (acc> 0x7FFFFFFF) acc= 0x7FFFFFFF;
  if (acc<-0x7FFFFFFF) acc=-0x7FFFFFFF;
  acc=acc*d->GAIN;
  if (acc> 0x7FFFFFFF) acc= 0x7FFFFFFF;
  if (acc<-0x7FFFFFFF) acc=-0x7FFFFFFF;
  if (acc>=))
  {
    acc=0x7FFFFFFFULL-acc;
    acc=acc*acc;
    acc+=1ULL<<30;
    acc>>=31;
    /*acc=acc*acc;
    acc+=1ULL<<30;
    acc>>=31;*/
    acc=0x7FFFFFFFULL-acc;
  }
  else
  {
    acc=0x7FFFFFFFULL+acc;
    acc=acc*acc;
    acc+=1ULL<<30;
    acc>>=31;
    /*acc=acc*acc;
    acc+=1ULL<<30;
    acc>>=31;*/
    acc=acc-0x7FFFFFFFULL;
  }
  if (acc>0)
  {
    acc+=1ULL<<8;
    acc>>=9;
  }
  else
  {
    acc=-acc;
    acc+=1ULL<<8;
    acc>>=9;
    acc=-acc;
  }
  if (acc>0x7FFFFFFF) acc=0x7FFFFFFF;
  if (acc<-0x7FFFFFFF) acc=-0x7FFFFFFF;
  return acc;
}

static void SetBiQuad(double Fs, double Fc, double BW, double G, BIQUAD *f)
{
    double          k,
                    om,
                    x;
    double          fi;
    double a0,a1,a2,b1,b2;
    k = pow(10, G / 40);	/* relative gain */
    //BW = BW / (Fc - BW / 2);	/* bandwidth in octaves */
    printf("biquad: Fc=%g BW=%g\n",Fc,BW);
    om = 2 * M_PI * Fc / Fs;	/* normalized frequency in radians */
    fi = sinh(log(2) / 2 * BW * om / sin(om)) * sin(om);	/* stuff */
    x = 1 + fi / k;		/* b0 */
    a0 = (1 + fi * k) / x;
    a1 = -2 * cos(om) / x;
    a2 = (1 - fi * k) / x;
    b1 = -a1;
    b2 = -(1 - fi / k) / x;
    f->a0=16384.0*a0;
    f->a1=16384.0*a1;
    f->a2=16384.0*a2;
    f->b1=16384.0*b1;
    f->b2=16384.0*b2;
    printf("biquad: %g %g %g %g %g",a0,a1,a2,b1,b2);
    if (
      f->a0>0x7FFF || f->a0<-0x8000 ||
      f->a1>0x7FFF || f->a1<-0x8000 ||
      f->a2>0x7FFF || f->a2<-0x8000 ||
      f->b1>0x7FFF || f->b1<-0x8000 ||
      f->b2>0x7FFF || f->b2<-0x8000
    ) printf(" Overload!!!");
    printf("\n");
    //printf("biquad: %g %g %g %g %g\n",a0,a1,a2,b1,b2);
}

static void SetChebyshev(double Fs, double Fc, double ripple, int lowpass,
	       BIQUAD *f)
{
    double          x,
                    y,
                    z,
                    c,
                    v,
                    t,
                    r,
                    om,
                    m,
                    x0,
                    x1,
                    x2,
                    y1p,
                    y2,
                    k,
                    d,
                    tt,
                    tt2;
    double a0,a1,a2,b1,b2;
    // x=-cos(M_PI/4+M_PI/2);
    // y=sin(M_PI/4+M_PI/2);
    // c=-0.99915455413031497832540334286332;
    // v=0.041111761828599317357934264608497;
    c = -cos(M_PI / 4);
    v = sin(M_PI / 4);
    if (ripple > 0) {
	t = 100.0 / (100.0 - ripple);
	x = sqrt(t * t - 1);
	t = 1 / x;
	r = t + sqrt(t / x);
	y = 0.5 * log(r + 1);
	z = 0.5 * log(r - 1);
	t = exp(z);
	z = (t + 1 / t) / 2;
	t = exp(y);
	c *= (t - 1 / t) / 2 / z;
	v *= (t + 1 / t) / 2 / z;
    }
    tt = 2 * tan(0.5);
    tt2 = tt * tt;
    om = 2 * M_PI * Fc / Fs;
    m = c * c + v * v;
    d = 4 - 4 * c * tt + m * tt2;
    x0 = tt2 / d;
    x1 = x0 * 2;
    x2 = x0;
    y1p = (8 - 2 * m * tt2) / d;
    y2 = (-4 - 4 * c * tt - m * tt2) / d;
    if (lowpass)
	k = sin(0.5 - om / 2) / sin(0.5 + om / 2);
    else
	k = -cos(om / 2 + 0.5) / cos(om / 2 - 0.5);
    d = 1 + k * (y1p - y2 * k);
    a0 = (x0 - k * (x1 - x2 * k)) / d;
    // coeff[1]=(k*(-2*(x0+x2)+x1*k)+x1)/d;
    a1 = 2 * a0;
    a2 = a0;
    // coeff[2]=(k*(x0*k-x1)+x2)/d;
    b1 = (k * (2 + y1p * k - 2 * y2) + y1p) / d;
    b2 = (-k * (k + y1p) + y2) / d;
    if (!lowpass) {
	a1 = -a1;
	b1 = -b1;
    }
    f->a0=16384.0*a0;
    f->a1=16384.0*a1;
    f->a2=16384.0*a2;
    f->b1=16384.0*b1;
    f->b2=16384.0*b2;
    printf("cheb: %g %g %g %g %g",a0,a1,a2,b1,b2);
    if (
      f->a0>0x7FFF || f->a0<-0x8000 ||
      f->a1>0x7FFF || f->a1<-0x8000 ||
      f->a2>0x7FFF || f->a2<-0x8000 ||
      f->b1>0x7FFF || f->b1<-0x8000 ||
      f->b2>0x7FFF || f->b2<-0x8000
    ) printf(" Overload!!!");
    printf("\n");
}

static signed long BiQuad(signed long s, BIQUAD *q)
{
  signed long long acc;
  acc=(signed long long )s*q->a0;
  acc+=(signed long long )q->mem0*q->a1;
  acc+=(signed long long )q->mem1*q->a2;
  acc+=(signed long long )q->mem2*q->b1;
  acc+=(signed long long )q->mem3*q->b2;
  q->mem1=q->mem0;
  q->mem0=s;
  q->mem3=q->mem2;
  acc>>=14;
  if (acc>0x7FFFFF) acc=0x7FFFFF;
  if (acc<-0x7FFFFF) acc=-0x7FFFFF;
  return q->mem2=acc;
}

static signed long EnvDetector(signed long s, ENV_DETECT *d)
{
  int flag;
  signed long z;
  signed long z_low;
  if (s>d->filter_low.Y)
  {
    //Пиковый детектор
    //z_low=LowPassFilter(s,&d->filter_low);
    d->filter_low.Y=s;
    z_low=s;
  }
  else
  {
    z_low=LowPassFilter(256*3000,&d->filter_low);
  }
  z=LowPassFilter(z_low,&d->filter);
  flag=0;
  if (z_low>z)
  {
        LowPassFilter(z_low*10,&d->filter);
        flag=1;
  }
  if (!d->fuse && flag)
  {
        d->fuse=5000;
        return 256*16384; //Строб
  }
  if (flag)
  {
        d->fuse=5000;
  }
  if (d->fuse) d->fuse--;
  return 0;
}

signed long GainStage(signed long s, signed short G)
{
  signed long long acc;
  acc=(signed long long )s*G;
  acc>>=8;
  if (acc>0x7FFFFF) acc=0x7FFFFF;
  if (acc<-0x7FFFFF) acc=-0x7FFFFF;
  return acc;
}

signed long AttStage(signed long s, signed short G)
{
  signed long long acc;
  acc=(signed long long )s*G;
  acc>>=14;
  if (acc>0x7FFFFF) acc=0x7FFFFF;
  if (acc<-0x7FFFFF) acc=-0x7FFFFF;
  return acc;
}

signed short stereo_delay[16384];
#define stereo_delay_length (sizeof(stereo_delay)/sizeof(stereo_delay[0]))
int stereo_delay_p;

typedef struct
{
        unsigned short P0;
        signed short G0;
        unsigned short P1;
        signed short G1;
        unsigned short P2;
        signed short G2;
        unsigned short P3;
        signed short G3;
        unsigned short P4;
        signed short G4;
        unsigned short P5;
        signed short G5;
        unsigned short P6;
        signed short G6;
        unsigned short P7;
        signed short G7;
}DELAY_TAPS;

signed short MakeDelay(DELAY_TAPS *d)
{
  signed long long acc=0;
  signed short p;
  unsigned short b=stereo_delay_p;
  p=b-d->P0;if (p<0) p+=stereo_delay_length; acc+=(signed long long)stereo_delay[p]*d->G0;
  p=b-d->P1;if (p<0) p+=stereo_delay_length; acc+=(signed long long)stereo_delay[p]*d->G1;
  p=b-d->P2;if (p<0) p+=stereo_delay_length; acc+=(signed long long)stereo_delay[p]*d->G2;
  p=b-d->P3;if (p<0) p+=stereo_delay_length; acc+=(signed long long)stereo_delay[p]*d->G3;
  p=b-d->P4;if (p<0) p+=stereo_delay_length; acc+=(signed long long)stereo_delay[p]*d->G4;
  p=b-d->P5;if (p<0) p+=stereo_delay_length; acc+=(signed long long)stereo_delay[p]*d->G5;
  p=b-d->P6;if (p<0) p+=stereo_delay_length; acc+=(signed long long)stereo_delay[p]*d->G6;
  p=b-d->P7;if (p<0) p+=stereo_delay_length; acc+=(signed long long)stereo_delay[p]*d->G7;
  acc>>=14;
  if (acc>0x7FFF) acc=0x7FFF;
  if (acc<-0x7FFF) acc=-0x7FFF;
  return acc;
}

DELAY_TAPS Delay_L=
{
        0,       16384L*100L/100,
        17*44,  -16384L*0L/100,
        72*44,   16384L*20L/100,
        118*44,  16384L*0L/100,
        181*44, -16384L*12L/100,
        240*44,  16384L*0L/100,
        300*44, -16384L*6L/100,
        370*44,  16384L*0L/100
};

DELAY_TAPS Delay_R=
{
        10*44,   16384L*100L/100,
        27*44,  -16384L*30L/100,
        82*44,   16384L*0L/100,
        108*44,  16384L*15L/100,
        171*44, -16384L*0L/100,
        250*44,  16384L*10L/100,
        310*44, -16384L*0L/100,
        360*44,  16384L*4L/100
};

DELAY_TAPS Delay_FeedBack=
{
        12*44,   16384L*10L/100,
        29*44,  -16384L*9L/100,
        84*44,   16384L*6L/100,
        110*44,  16384L*5L/100,
        175*44, -16384L*4L/100,
        248*44,  16384L*3L/100,
        313*44, -16384L*2L/100,
        365*44,  16384L*1L/100
};

#pragma argsused
int main(int argc, char* argv[])
{
  static const char hdr1[]={
    0x52,0x49,0x46,0x46,0x00,0x00,0x00,0x00,0x57,0x41,0x56,0x45,0x66,0x6D,0x74,0x20,
    0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x44,0xAC,0x00,0x00,0x10,0xB1,0x02,0x00,
    0x04,0x00,0x10,0x00,0x64,0x61,0x74,0x61,0x00,0x00,0x00,0x00
  };


  HANDLE fin;
  HANDLE fout;
  signed short *inbuf;
  signed short *outbuf;
  unsigned long total_bytes;
  unsigned long br;
  unsigned long pos=0;
  unsigned long rpos=0;

  double preeq_G;
  signed short ipreeq_G;

  HPF dc_offset_remove={0,65536*50/7022};
  HPF dc_offset_remove1={0,65535*10/7022};
  HPF dc_offset_remove2={0,65535*10/7022};

  ENV_DETECT env1={{0,65535*1/7022},{0,65535*1/7022},0};

  BIQUAD input_filter={0,0,0,0,0,0,0,0,0};

  BIQUAD preeq_b={0,0,0,0,0,0,0,0};

  SQ_DIST dist1={256UL*3000,65536*100/100,{0,65535*40/7022}};

  SQ_DIST power_amp={256UL*1,65536*30/100,{0,65535*10/7022}};


  BIQUAD sand_remove={0,0,0,0,0,0,0,0,0};
  BIQUAD sand_remove2={0,0,0,0,0,0,0,0,0};

  BIQUAD out_eq[19];

  fout = CreateFile("out.wav",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, 0);
  WriteFile(fout,hdr1,sizeof(hdr1),&br,NULL);
  fin = CreateFile("in5.wav",GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
  SetFilePointer(fin,0x28,NULL,FILE_BEGIN);
  ReadFile(fin,&total_bytes,4,&br,NULL);
  inbuf=malloc(total_bytes);
  outbuf=malloc(total_bytes*2);
  ReadFile(fin,inbuf,total_bytes,&br,NULL);

  SetChebyshev(44100,5500,1,1,&input_filter);

  preeq_G=20;
  //SetBiQuad(44100,1600,3.3,preeq_G,&preeq_b);
  SetBiQuad(44100,900,4,preeq_G,&preeq_b);
  ipreeq_G=(int)(16384.0/pow(10, preeq_G / 20));

  SetChebyshev(44100,4500,1,1,&sand_remove);
  SetChebyshev(44100,4500,1,1,&sand_remove2);

  memset(out_eq,0,sizeof(out_eq));

#define bw_scale (0.5)
/*  SetBiQuad(44100,80,bw_scale,7.3,out_eq+0);
  SetBiQuad(44100,100,bw_scale,7,out_eq+1);
  SetBiQuad(44100,125,bw_scale,6.6,out_eq+2);
  SetBiQuad(44100,160,bw_scale,5.9,out_eq+3);
  SetBiQuad(44100,200,bw_scale,4.8,out_eq+4);
  SetBiQuad(44100,250,bw_scale,3.3,out_eq+5);
  SetBiQuad(44100,320,bw_scale,2.1,out_eq+6);
  SetBiQuad(44100,400,bw_scale,1.5,out_eq+7);
  SetBiQuad(44100,500,bw_scale,0.9,out_eq+8);
  SetBiQuad(44100,640,bw_scale,-2.9,out_eq+9);
  SetBiQuad(44100,800,bw_scale,-0.9,out_eq+10);
  SetBiQuad(44100,1000,bw_scale,0.7,out_eq+11);
  SetBiQuad(44100,1280,bw_scale,2,out_eq+12);
  SetBiQuad(44100,1600,bw_scale,4.5,out_eq+13);
  SetBiQuad(44100,2000,bw_scale,4.4,out_eq+14);
  SetBiQuad(44100,2560,bw_scale,5.3,out_eq+15);
  SetBiQuad(44100,3200,bw_scale,5.2,out_eq+16);
  SetBiQuad(44100,4000,bw_scale,6.2,out_eq+17);
  SetBiQuad(44100,5000,bw_scale,5,out_eq+18);*/

  SetBiQuad(44100,80,bw_scale,8.3,out_eq+0);
  SetBiQuad(44100,100,bw_scale,8,out_eq+1);
  SetBiQuad(44100,125,bw_scale,7.6,out_eq+2);
  SetBiQuad(44100,160,bw_scale,6.9,out_eq+3);
  SetBiQuad(44100,200,bw_scale,6.8,out_eq+4);
  SetBiQuad(44100,250,bw_scale,5.3,out_eq+5);
  SetBiQuad(44100,320,bw_scale,4.1,out_eq+6);
  SetBiQuad(44100,400,bw_scale,3.5,out_eq+7);
  SetBiQuad(44100,500,bw_scale,0.9,out_eq+8);
  SetBiQuad(44100,640,bw_scale,-1.9,out_eq+9);
  SetBiQuad(44100,800,bw_scale,-1.9,out_eq+10);
  SetBiQuad(44100,1000,bw_scale,3.7,out_eq+11);
  SetBiQuad(44100,1280,bw_scale,2,out_eq+12);
  SetBiQuad(44100,1600,bw_scale,5.5,out_eq+13);
  SetBiQuad(44100,2000,bw_scale,7.4,out_eq+14);
  SetBiQuad(44100,2560,bw_scale,7.3,out_eq+15);
  SetBiQuad(44100,3200,bw_scale,7.2,out_eq+16);
  SetBiQuad(44100,4000,bw_scale,7.2,out_eq+17);
  SetBiQuad(44100,5000,bw_scale,8,out_eq+18);

  while(pos<(total_bytes))
  {
     int i;
     int stereo_delay_rp;
     signed long L_sample;
     signed long R_sample;
     signed long sample=256UL*inbuf[rpos++];
     sample+=(rand()/(RAND_MAX/256));
     //Remove DC
     sample=HighPassFilter(sample,&dc_offset_remove);
     //Remove High Frequences
     sample=BiQuad(sample,&input_filter);
     //Detect Attack (for future usage)
     if (EnvDetector(sample,&env1))
     {
     	//Trigger
     }
     //Pre EQ
     sample=AttStage(sample,ipreeq_G);
     sample=BiQuad(sample,&preeq_b);
     //Distortion
     sample=SquareDist(sample,&dist1);
     sample=HighPassFilter(sample,&dc_offset_remove1);
     //Remove sand
     sample=BiQuad(sample,&sand_remove);
     //EQ
     sample=AttStage(sample,16384/8);
     for(i=0; i<sizeof(out_eq)/sizeof(BIQUAD); i++)
     {
          sample=BiQuad(sample,out_eq+i);
     }
     //Power Amp
     sample=SquareDist(sample,&power_amp);
     sample=HighPassFilter(sample,&dc_offset_remove2);
     //Remove sand
     sample=BiQuad(sample,&sand_remove2);
     //Generate stereo_delay
     if(1)
     {
       signed long acc=sample/128;
       acc+=MakeDelay(&Delay_FeedBack);
       if (acc>0x7FFF) acc=0x7FFF;
       if (acc<-0x7FFF) acc=-0x7FFF;
       stereo_delay[stereo_delay_p]=acc;
       L_sample=MakeDelay(&Delay_L);
       R_sample=MakeDelay(&Delay_R);
       stereo_delay_p++;
       if (stereo_delay_p>=stereo_delay_length) stereo_delay_p=0;
     }
     else
     {
        L_sample=sample/128;
        R_sample=sample/128;
     }
     //Write out
     outbuf[pos++]=L_sample;
     outbuf[pos++]=R_sample;
  }
  total_bytes*=2;
  WriteFile(fout,outbuf,total_bytes,&br,NULL);
  SetFilePointer(fout,0x28,NULL,FILE_BEGIN);
  WriteFile(fout,&total_bytes,4,&br,NULL);
  SetFilePointer(fout,0x04,NULL,FILE_BEGIN);
  total_bytes+=0x24;
  WriteFile(fout,&total_bytes,4,&br,NULL);
  CloseHandle(fout);
  CloseHandle(fin);
  free(inbuf);
  free(outbuf);
  return 0;
}
//---------------------------------------------------------------------------

"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
2

#24 Пользователь офлайн   xar 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 16 июня 2010 - 02:08

в платах с таким шагом главное не переходы... главное чтоб маска была, желательно качественная. недавно на работе дспшки с шагом 0.5 паял без маски. вот это веселуха однака...
Rst7, зачем тут код такой выкладывать? без комментов нормальных тем более. не поймет ведь ни кто )
0

#25 Пользователь офлайн   Rst7 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 16 июня 2010 - 03:01

Цитата

Rst7, зачем тут код такой выкладывать?


Может, кому интересно.

Цитата

без комментов нормальных тем более. не поймет ведь ни кто )


Ну у каждого свой взгляд на требуемую плотность комментариев. Уж всякую математику типа расчетов коэффициентов фильтров Чебышева я коментировать не буду, ибо со справочника код, считайте. А основной цикл вполне комментариями означен, что за чем. Ну и плюс я даю вполне вменяемые имена переменным и функциям.
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
1

#26 Пользователь офлайн   FeonKO 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 16 июня 2010 - 17:44

Rst7, Вот-вот... если посмотреть то из названия понятно что это... и основные уровнения.... они почти на всех компиляторах одинаково пишуться. А если сесть подумать то можна немного и поизминять, зделать например Дист, задав таким уровнением, которое не получиться зделать на аналоговых прибамбасах.

Снимаю шляпу перед автором.
0

#27 Пользователь офлайн   Rst7 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 16 июня 2010 - 19:34

Цитата

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


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

Опять же, надо помнить, что задачу точной эмуляции какого-либо известного усилителя или примочки я тут и не ставил. Нет смысла.
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
1

#28 Пользователь офлайн   FeonKO 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 20 июня 2010 - 18:27

Rst7, Хммм.. может я фигню спрошу... но всетаки, просто поставить условие вроди Иф. сигнал, или напряжение больше, заданого порога, тот что мы поставим валкодером, или как там угодно, то, значение функции приравнять этому же порогу... тоесть если превышает у нас просто получиться прямая линия (срезана шапка синусоиды) как только меньше ограничение уже не в силе. =)
0

#29 Пользователь офлайн   Rst7 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 20 июня 2010 - 19:57

Цитата

но всетаки, просто поставить условие вроди Иф.


С одной стороны? Или с двух? В любом случае, будет довольно мерзкий звук. Щас домой приеду, выложу пару семплов с таким топорным ограничением.
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
0

#30 Пользователь офлайн   Dr_Zlo 

  • Вставить ник
  • Цитировать
  • Раскрыть информацию

Отправлено 20 июня 2010 - 21:02

На мой скромный взгляд - прикольный фузз).
И не забывай, юный падаван, страх, гнев, и гитары FENDER ведут тебя к темной стороне силы...
0

Поделиться темой:


  • 2 Страниц +
  • 1
  • 2
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

4 человек читают эту тему
0 пользователей, 4 гостей, 0 скрытых пользователей

Спасибо админам и создателям форума, которые развивали ресурс вплоть до мая 2022 года: Kanistra, Nazarett, Satriani, Плохиш, Тяп !