Ранее экспериментировал с синтезом звука на AVR. По итогу сделал музыкальную шкатулку на ATTiny2313, где задействовал два таймера Т0 и Т1 в режиме СТС для вывода основной мелодии и бас-партии. Динамик, соответственно, смешивал все это хозяйство. Получилось неплохо.
Продолжая эту историю, заинтересовался, как технически суммируются прямоугольные импульсы? И можно ли обойтись в принципе одной ногой таймера в коде для вывода двух (и более нот) одновременно? Примерно, как на картинке ниже:
Наглядный пример:
Буду благодарен за разъяснения и направление, куда копать дальше!
Re: Суммирование прямоугольных сигналов
Добавлено: Вт июл 11, 2023 21:50:04
КРАМ
[uquote="kas1830",url="/forum/viewtopic.php?p=4444709#p4444709"]как технически суммируются прямоугольные импульсы?[/uquote]
Так же, как и непрямоугольные и не импульсы - аналоговым сумматором. Простейший - резистивный. Можно сделать сумматор на ОУ.
Re: Суммирование прямоугольных сигналов
Добавлено: Вт июл 11, 2023 22:06:27
veso74
Для тонов с частотами в сотые доли герца нужна другая вычислительная мощность и ресурс. С AVR и указанным способом будет всего каких-то два тона. Рассмотрите как идею напр. NCO генератор, или два внешних генератора DDS. Будет легче.
Re: Суммирование прямоугольных сигналов
Добавлено: Ср июл 12, 2023 09:36:34
Jack_A
[uquote="veso74",url="/forum/viewtopic.php?p=4444727#p4444727"]Для тонов с частотами в сотые доли герца[/uquote]
Сотые доли Герца можно сгенерировать на самом медленном оборудовании, даже на реле Ну если период - десятки секунд - это даже арифмометр "Феликс" осилит Но музыку в диапазоне инфразвука оценит разве что осьминог. СпойлерУ нас НИИ сдавало тему - простейшая цикловая схема управления роботом. Для демонстрации подобрали и подключили к выходам несколько пускателей разных габаритов. При срабатывнии они издавали щелчок разной тональности - зависит от массы якоря. Программа исполняла "Чижик-пыжик"
------------------------
Как-то в институте на скучной лекции я взялся посчитать - с какой частотой я получаю стипендию. Оказалоь 3,8 * 10^-7 Гц
Re: Суммирование прямоугольных сигналов
Добавлено: Ср июл 12, 2023 10:44:00
veso74
Видимо переводчик БГ-РУ неправильно перевел мысль, но вы поняли. Я писал для 261,63 и 277,18 Hz.
Re: Суммирование прямоугольных сигналов
Добавлено: Ср июл 12, 2023 14:16:19
kas1830
Товарищи, спасибо всем, кто уже откликнулся.
В крайности уходить не стоит. Перефразирую вопрос проще: как на МК сгенерить одновременное звучание двух и более нот разной частоты? Типа аккорда. Какие есть технические варианты?
Re: Суммирование прямоугольных сигналов
Добавлено: Ср июл 12, 2023 17:42:38
Starichok51
kas1830, тебе уже ответили - сложить сигналы обычным сумматором.
...в памяти прописывается массив, отражающий форму элементарного сигнала, а затем делается выборка, сложение с выборкой другой(-ими) ноты, одновременно звучащей, и результирующий код (8 и более бит) подается на R2R, ЦАП, или ШИМ.
Как раз то, что я ищу. У меня записан массив нот в памяти.
Поделитесь пжл примером кода, если у кого есть, как производится сложение выборок, чтобы выводить полифонию
Re: Суммирование прямоугольных сигналов
Добавлено: Чт июл 13, 2023 10:20:25
Starichok51
кроме массива нот нужен массив частот этих нот. и складываются частоты, а не ноты.
Добавлено after 10 minutes 30 seconds:
для лучшего понимания прочитай эту статью https://www.radiokot.ru/circuit/digital/game/51/
а также запусти поиск по фразе "синтез мелодий на AVR", и найдешь уйму информации по синтезу мелодий.
Re: Суммирование прямоугольных сигналов
Добавлено: Чт июл 13, 2023 10:55:39
Engineer_Keen
Для складывания двух и более звуков, если используется AVR и ШИМ 8-10 бит, достаточно их все тупо сложить (с учетом знака) и при выходе за пределы разрядности тупо ограничить, т.е. если сумма для 8 бит>255, то результат будет 255, если меньше 0, то 0.
Да, при сложении может произойти искажение (перегрузка), ее можно обойти, заранее поделив громкость на количество одновременно складываемых звуков, но в этом скорее всего не будет необходимости, учитывая условия.
Re: Суммирование прямоугольных сигналов
Добавлено: Чт июл 13, 2023 11:13:55
kas1830
Спасибо за ответ.
[uquote="Engineer_Keen",url="/forum/viewtopic.php?p=4445419#p4445419"]...если используется AVR и ШИМ 8-10 бит[/uquote]
Тут у меня как раз не ШИМ, а СТС режим. Будет аналогично или есть особенности?
[uquote="kas1830",url="/forum/viewtopic.php?p=4445437#p4445437"]Тут у меня как раз не ШИМ, а СТС режим. Будет аналогично или
есть особенности?[/uquote]
Э погодите-ка, тут есть варианты...
Если вы генирируете звук при помощи сложения разных меандров, т.е. используете режим CTC для задания частот именно самих звуковых волн и ЭТИ волны надо микшировать, то действительно, это проще сделать внешним смесителем. Кстати, можно использовать один железный таймер, а частоты меандров синтезировать программно, используя вариант ниже.
А вот если режим CTC нужен для задания частоты квантования и по этой частоте вы бы через ШИМ выводили семплы, то суммировать их можно методом, который я описал выше.
Кстати, и для задачи частоты квантования и для ШИМ (даже стерео) можно использовать всего ОДИН таймер, причем частоту квантования можно задавать в широких пределах, в том числе близкую к стандартным 11-22-44кГц. Для этого таймер настраивается в режим CTС со сравнением с ICR, в ICR заносится нужное для заданной частоты квантования значение. А семплы нормируются с учетом этого значения и выводятся в OCRA и OCRB в прерывании по переполнению.
Re: Суммирование прямоугольных сигналов
Добавлено: Чт июл 13, 2023 12:10:22
Asmodey
В некоторых моделях PIC микроконтроллеров присутствует периферийный модуль DATA SIGNAL MODULATOR. Возможно подойдет для поставленных топикстартером целей.
Re: Суммирование прямоугольных сигналов
Добавлено: Чт июл 13, 2023 12:48:11
veso74
Или с тремя NCO генераторами (напр. PIC18F25Q43), но отклоняемся от темы.
Re: Суммирование прямоугольных сигналов
Добавлено: Чт июл 13, 2023 15:14:45
BOB51
Модулятор и в старших АВРках есть...
Re: Суммирование прямоугольных сигналов
Добавлено: Чт июл 13, 2023 22:27:40
Asmodey
Ну так то в старших, а у PIC в копеечных младших имеются.
Re: Суммирование прямоугольных сигналов
Добавлено: Чт июл 13, 2023 22:50:32
kas1830
Э погодите-ка, тут есть варианты...
Если вы генерируете звук при помощи сложения разных меандров, т.е. используете режим CTC для задания частот именно самих звуковых волн и ЭТИ волны надо микшировать, то действительно, это проще сделать внешним смесителем. Кстати, можно использовать один железный таймер, а частоты меандров синтезировать программно, используя вариант ниже.
А вот если режим CTC нужен для задания частоты квантования и по этой частоте вы бы через ШИМ выводили семплы, то суммировать их можно методом, который я описал выше.
Спасибо, а можно поподробнее (или пример)? Пока непонятно. что с чем складывать.
У меня два таймера Т0 и Т1 тикают независимо в режиме СТС, далее в прерывании каждый дергает свою ногу, с частотой, заданной регистром сравнения.
Динамик соединен с двумя выводами МК и делает всю работу по смешению за меня.
Re: Суммирование прямоугольных сигналов
Добавлено: Пт июл 14, 2023 11:24:33
Engineer_Keen
Ну вот так, например...
Код для суммирования 4х меандров (2 отключил чтобы понятнее сумма выглядела). Тактовая для Mega88 - 8МГц, частота семплов 22кГц, использован один 16 разрядный таймер, и одно его прерывание, 20 байт ОЗУ, и 270 флеша, загрузка контроллера ~45%. Спойлер
;программа сложения 4х прямоугольных сигналов с произвольными частотами
.include "m88def.inc" ;определения для Mega88
.include "MacroAVR.asm" ;макросы для упрощения кода
.equ F_CPU=8000000 ;частота контроллера
.equ SND_SAMPLE_FREQ =22050 ;частота выборок
.equ SND_OCR_VALUE =F_CPU/SND_SAMPLE_FREQ ;расчет значения для режима CTC
.equ SND_MID_VALUE =SND_OCR_VALUE/2 ;половина выходного сигнала
.equ NUMBER_OF_SIGNALS =4 ;количество смешиваемых сигналов
.equ FREQ0 =261 ;C4 ;частоты сигналов
.equ FREQ1 =311 ;D#4
.equ FREQ2 =110 ;A2
.equ FREQ3 =61 ;B1
.equ DIV0 =SND_SAMPLE_FREQ/FREQ0/2 ;расчет делителей
.equ DIV1 =SND_SAMPLE_FREQ/FREQ1/2 ;для частоты каждого сигнала
.equ DIV2 =SND_SAMPLE_FREQ/FREQ2/2
.equ DIV3 =SND_SAMPLE_FREQ/FREQ3/2
.def ZERO =R2 ;для ускорения арифметики
.def STR =R3 ;для ускорения вх/вых в прерывание
;структура данных для одного сигнала
.equ PH_OFFSET =0 ;фаза
.equ DIV_OFFSET =2 ;делитель
.equ OUT_OFFSET =4 ;значение на выходе
.equ SIGNAL_SIZE =2+2+1 ;ее размер
.dseg ;сегмент данных
SIG: .byte SIGNAL_SIZE*NUMBER_OF_SIGNALS ;данных сигналов
.cseg ;сегмент кода
.org 0
RJMP RESET
.org OVF1addr
RJMP SAMPLE_OUT ;прерывание для расчета и вывода семпла
DIVS:
.dw DIV0,DIV3,0,0 ;рассчитанная таблица частот сигналов (0-отключено для наглядности)
; .dw DIV0,DIV1,DIV2,DIV3
RESET: SETSTACK ;установка стека
OUTI CLKPR,(1<<CLKPCE) ;сброс делителя тактовой
STS CLKPR,ZERO
OUTI DDRC,(1<<PC4)|(1<<PC3)|(1<<PC2)|(1<<PC1)|(1<<PC0);тестовые выходы
OUTI TCCR1A,(1<<COM1A1)|(1<<WGM11)|(0<<WGM10) ;настройка таймера CTC, TOP=ICR
OUTI TCCR1B,(1<<WGM12)|(1<<WGM13)|(1<<CS10)
OUTI ICR1H,High(SND_OCR_VALUE) ;период квантования
OUTI ICR1L,Low(SND_OCR_VALUE)
OUTI OCR1AH,High(SND_MID_VALUE) ;в ШИМ - половина уровня
OUTI OCR1AL,Low(SND_MID_VALUE)
LDS R16,TIMSK1 ;вкл. прерывания OVF1
ORI R16,(1<<TOIE1)
STS TIMSK1,R16
SBI DDRB,PB1 ;включить вывод ШИМ
SETZ DIVS*2 ;копирование таблицы из флеша
SETY SIG ;в структуру сигнала
LDI R17,NUMBER_OF_SIGNALS
DLOOP: LPM XL,Z+ ;чтение делителя
LPM XH,Z+
STD Y+PH_OFFSET+0,XH ;запись начального значения фазы
STD Y+PH_OFFSET+1,XL
STD Y+DIV_OFFSET+0,XH ;и это же значение в делитель
STD Y+DIV_OFFSET+1,XL
STD Y+OUT_OFFSET,ZERO ;значение функции изначально=0
ADIW YL,SIGNAL_SIZE ;переход к следюущему
DJNZ R17,DLOOP
SEI ;вкл. глобальных прерываний
LOOP: SETX SIG+OUT_OFFSET ;основной цикл
LDI R17,NUMBER_OF_SIGNALS ;просто вывод
CLR R18 ;значения функций на выходы
OLOOP: LD R16,X ;для наглядности
BST R16,7
BLD R18,4
LSR R18
ADIW XL,SIGNAL_SIZE
DJNZ R17,OLOOP
IN R16,PORTC
ANDI R16,0xF0
OR R16,R18
OUT PORTC,R16
RJMP LOOP
;процедура вывода семпла
SAMPLE_OUT:
SBI PORTC,PC4 ;вывод загрузки контроллера процедурой
IN STR,SREG ;сохранение SREG и регистров
PUSH R17
PUSH R16
PUSHX
PUSHY
PUSHZ
LDI ZL,0x08 ;начальное значение суммы сигналов
LDI R17,NUMBER_OF_SIGNALS
SETY SIG ;установка на структуру первого сигнала
SLOOP: LDD XH,Y+PH_OFFSET+0 ;чтение фазы
LDD XL,Y+PH_OFFSET+1
CP XL,ZERO
CPC XH,ZERO
BREQ SKIP ;если 0, про сигнал не обрабатывать
LDD R16,Y+OUT_OFFSET ;чтение значения на выходе
SBIW XL,1 ;уменьшаем фазу
BRNE NO_INVERT ;если не 0, переход к сохранению
COM R16 ;если 0, инвертируем выход
STD Y+OUT_OFFSET,R16 ;сохраняем значение на выходе
LDD XH,Y+DIV_OFFSET+0 ;перезагружаем значение фазы
LDD XL,Y+DIV_OFFSET+1
NO_INVERT:
STD Y+PH_OFFSET+0,XH ;сохраняем фазу
STD Y+PH_OFFSET+1,XL
SBRC R16,7 ;суммируем значения на выходах
INC ZL
SBRS R16,7
DEC ZL
SKIP: ADIW YL,SIGNAL_SIZE ;переход к следующему
DJNZ R17,SLOOP
CJNE ZL,0x08,NO_HALF ;проверка суммы значений и преобразование в ШИМ
SETZ SND_MID_VALUE ;если сумма=0, выводим половину в ШИМ
RJMP OCR_SET
NO_HALF:CJLO ZL,0x08,OUT_MIN ;если сумма<0, выводим в ШИМ 0
SETZ SND_OCR_VALUE-1 ;если сумма>0, выводим в ШИМ максимальное значение
RJMP OCR_SET
OUT_MIN:SETZ 0
OCR_SET:
STS OCR1AH,ZH ;вывод в регистры ШИМ
STS OCR1AL,ZL
POPZ ;восстановление регистров
POPY
POPX
POP R16
POP R17
OUT SREG,STR
CBI PORTC,PC4
RETI
Результат. Зеленый (после RC-цепочки) = желтый+синий. Нижний осциллограф - ШИМ, и загрузка контроллера.
Спойлер
PS: О, зацените игрушку
всего 146 байт флеша и 14 ОЗУ, работает от встроенного RC на 8МГц, 7 кнопок, можно все сразу нажать, будет 7 меандров на выходе и еще 66% процессорного времени свободно. Можно прикрутить читалку нот по таймеру и готова музыкальная шкатулка