Я могу издавать монофонические звуки, переключая один контакт ( с различной скоростью ), подключенный к пьезо-зуммеру.
Как я могу генерировать два смешанных аудиосигнала в программном обеспечении для создания полифонии?
Вот код, который я использую, чтобы сыграть простую мелодию.
#define F_CPU 8000000UL // 8MHz
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
// number of timer0 overflows/sec
#define INT_PER_SEC 31250
// Frequencies (in Hz) of notes
#define F_FSH_4 370
#define F_A_4 440
#define F_B_4 494
#define F_E_4 330
#define F_CSH_5 554
#define F_D_5 587
#define F_FSH_5 740
#define F_CSH_4 277
#define F_GSH_4 415
// number of timer0 overflows for notes
#define REST -1 // special case
#define FSH_4 INT_PER_SEC/F_FSH_4
#define A_4 INT_PER_SEC/F_A_4
#define B_4 INT_PER_SEC/F_B_4
#define E_4 INT_PER_SEC/F_E_4
#define CSH_5 INT_PER_SEC/F_CSH_5
#define D_5 INT_PER_SEC/F_D_5
#define FSH_5 INT_PER_SEC/F_FSH_5
#define CSH_4 INT_PER_SEC/F_CSH_4
#define GSH_4 INT_PER_SEC/F_GSH_4
#define SEMIQUAVER_TIME 60 // ms
#define BREATH_TIME 20 // ms
volatile uint32_t intrs = 0;
volatile int32_t curNote = REST;
// TIMER0 overflow
ISR(TIMER0_OVF_vect)
{
if (curNote == REST)
intrs = 0;
else
{
intrs++;
if (intrs >= curNote)
{
PORTD ^= _BV(PD4);
intrs = 0;
}
}
}
void play(int32_t note, uint32_t len)
{
int i;
curNote = note;
for (i = 0; i< len; i++)
_delay_ms(SEMIQUAVER_TIME);
curNote = REST;
_delay_ms(BREATH_TIME);
}
int main(void)
{
/* setup clock divider. Timer0 overflows on counting to 256.
* 8Mhz / 1 (CS0=1) = 8000000 increments/sec. Overflows every 256, so 31250
* overflow interrupts/sec */
TCCR0B |= _BV(CS00);
// enable overflow interrupts
TIMSK0 |= _BV(TOIE0);
// PD4 as output
DDRD = _BV(PD4);
TCNT0 = 0;
intrs = 0;
curNote = REST;
// enable interrupts
sei();
while (1)
{
// Axel F
play(FSH_4, 2);
play(REST, 2);
play(A_4, 3);
play(FSH_4, 2);
play(FSH_4, 1);
play(B_4, 2);
play(FSH_4, 2);
play(E_4, 2);
play(FSH_4, 2);
play(REST, 2);
play(CSH_5, 3);
play(FSH_4, 2);
play(FSH_4, 1);
play(D_5, 2);
play(CSH_5, 2);
play(A_4, 2);
play(FSH_4, 2);
play(CSH_5, 2);
play(FSH_5, 2);
play(FSH_4, 1);
play(E_4, 2);
play(E_4, 1);
play(CSH_4, 2);
play(GSH_4, 2);
play(FSH_4, 6);
play(REST, 12);
}
}
Ответы:
Один простой прием - использовать два контакта с ШИМ и привязать их к противоположным сторонам динамика. Затем модулируйте каждый вывод с разной скоростью, и вы сможете сыграть две ноты одновременно ... в основном, динамик смешивает их вместе для вас. Более двух заметок, и вам придется делать это в программном обеспечении, как уже упоминалось.
источник
Стандартный способ получения полифонии - прерывание с некоторой фиксированной частотой прерывания (чаще всего 8000 Гц или 44100 Гц), получение «высокого» (+1) или «низкого» (-1) (или чего-то промежуточного) от каждого источника звука. сложите все числа, чтобы получить общее количество, затем отправьте это общее число из ЦАП.
Как уже говорили здесь, с некоторой сообразительностью высокоскоростной ШИМ может заменить ЦАП.
Страница «Полифония микроконтроллера» содержит некоторые дополнительные сведения и советы.
источник
Я думаю, что этот старый добрый маленький камуфляж для ПК с DOS использовал настоящий полифонический звук через динамик ПК: Digger .
Я не знаю, как они это сделали, но вы можете скачать исходный код C с сайта.
источник
Это может помочь -> простой ШИМ ЦАП
источник
Вы можете просто добавить две прямоугольные волны и использовать быстрый pwm для вывода «аналогового» сигнала на динамик.
вот еще один другой метод, если вам нравится звук в игре, быстрый и грязный:
https://gitweb.bl0rg.net/cgi-bin/gitweb.cgi?p=arduinisten.git;a=blob;f=projekte/soundz/arpeggio/arpeggio.pde;h=6ceb64a57916c094e87e5983c07b5dd1b4623083;hb=HEAD
источник
Если вы используете программное обеспечение для определения времени ваших выступлений, возможно, самый простой подход - это генерировать два независимых потока данных и чередовать их. Этот подход может работать довольно хорошо, независимо от того, управляется ли выход динамика через вывод ввода-вывода или ЦАП. Например:
Выше приведен основной подход, который я использовал в музыкальной шкатулке на основе PIC в 1996 году (с использованием ассемблерного кода, а не C). Обратите внимание, что частота прерываний должна в 8 раз превышать эффективную частоту дискретизации, но каждое прерывание должно выполнять обработку только для одного голоса. Обратите внимание, что если фильтрация выходного сигнала хороша, этот подход даст эффективное разрешение ЦАП на 3 бита больше, чем при численном добавлении выборок и их выводе, но при этом генерируется много шума на частоте дискретизации и ее кратных. Таким образом, фильтрация даже важнее, чем могла бы быть в противном случае.источник
Раньше они делали это на старых игровых системах и во времена « колонок для ПК », но я не знаю как.
Первое предположение: подумайте о волне, которую вы в идеале создадите, затем представьте, что вы искажаете ее в сильно обрезанную квадратную форму, затем создайте эту квадратную форму, переключая выходной сигнал в подходящее время. Хотя было бы много интермодуляции .
Вторая мысль: можно ли значительно увеличить частоту генерации и вывода аналоговых сигналов в стиле ШИМ ?
источник
Как уже упоминалось, вы можете сделать это так же, как это делалось с динамиком ПК (который поддерживает только включение / выключение, опционально подключенное к ШИМ-контроллеру). По сути, я понимаю, что метод заключается в том, что вы включаете и выключаете динамик. достаточно быстрый, чтобы он никогда не включался и не выключался (немного похоже на то, как работает импульсный источник питания). В результате динамик постоянно перемещается между включением и выключением, генерируя аналоговый сигнал.
Единственное, что нужно, это то, что вам нужен настоящий динамик (я думаю, пьезо движется так быстро, что полностью включается и слишком быстро выключается), и вам нужно уметь переключать бит достаточно быстро. Я провел несколько экспериментов и получил максимальную скорость около 5 МГц, которая должна быть достаточной для аудиосигнала с частотой 11 025 Гц (возможно, лучшее качество, которое вы могли бы надеяться получить).
Конечно, 11025 Гц при 8-битной скорости составляет 11 килобайт в секунду, что намного быстрее, чем скорость последовательного порта. Это может позволить сохранить во флэш-памяти всего лишь одну-две секунды, так что вы в значительной степени ограничены воспроизведением звука на лету, при условии, что у вас будет достаточно свободного времени процессора, чтобы вертеть динамик!
Есть несколько других методов для достижения этой цели, и, похоже, уже есть реализация для Arduino описанного выше метода.
источник
Вы можете просто добавить потоки, как описано здесь:
http://www.vttoth.com/digimix.htm
источник
Воспроизведите звук A на мгновение, например, около 50 мс, затем звук B и переключайтесь назад и вперед. Идея состоит в том, чтобы переключаться быстрее, чем ухо может сказать, и это будет звучать так, будто оба играют одновременно.
источник
Я считаю, что есть библиотека тонов для Arduino, которая делает два тона. Вы должны быть в состоянии адаптировать код к чипу AVR, который вы используете. На arduino.cc также есть пара отличных потоков генерации сигналов.
Если вы решите добавить ЦАП, у меня есть пример генератора с числовым управлением на http://wiblocks.luciani.org/docs/app-notes/nb1a-nco.html Четыре независимых выходных канала. ЦАП с четырьмя ЦАП и справка стоят всего около 2 долларов или около того.
источник
Вот мой код для воспроизведения 2 мелодий одновременно. Извините, вы должны зарегистрироваться на уродов AVR, чтобы получить доступ.
источник