Mogę wydawać dźwięki monofoniczne, przełączając pojedynczy pin ( w różnym tempie ) podłączony do brzęczyka piezoelektrycznego.
Jak mogę wygenerować dwa zmiksowane sygnały audio w oprogramowaniu, aby stworzyć polifonię?
Oto kod, którego używam do grania prostej melodii.
#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);
}
}
Odpowiedzi:
Cóż, jedną łatwą sztuczką jest użycie dwóch pinów z PWM i przywiązanie ich do przeciwnych stron głośnika. Następnie moduluj każdy pin z inną prędkością i możesz grać dwie nuty jednocześnie ... w zasadzie głośnik miksuje je razem. Więcej niż dwie notatki i będziesz musiał to zrobić w oprogramowaniu, jak wspomniano.
źródło
Standardowym sposobem uzyskania polifonii jest przerywanie z określoną stałą częstotliwością przerywania (najczęściej 8000 Hz lub 44100 Hz), uzyskanie „wysokiego” (+1) lub „niskiego” (-1) (lub czegoś pośredniego) z każdego źródła dźwięku , dodaj wszystkie liczby, aby uzyskać sumę, a następnie wyślij tę liczbę do DAC.
Jak powiedzieli inni, przy odrobinie sprytu szybki PWM może zastąpić przetwornik cyfrowo-analogowy.
Strona „polifonia mikrokontrolera” zawiera więcej szczegółów i wskazówek.
źródło
Myślę, że ten stary, miły klejnot do gier DOS na PC wykorzystał prawdziwy dźwięk polifoniczny przez głośnik PC: Digger .
Nie wiem, jak to zrobili, ale możesz pobrać kod źródłowy C ze strony.
źródło
To może pomóc -> prosty przetwornik PWM
źródło
możesz po prostu dodać dwie fale prostokątne i użyć szybkiego pwm, aby wyprowadzić sygnał „analogowy” do głośnika.
oto jeszcze jedna metoda, jeśli lubisz dźwięk gry, szybki i brudny:
https://gitweb.bl0rg.net/cgi-bin/gitweb.cgi?p=arduinisten.git;a=blob;f=projekte/soundz/arpeggio/arpeggio.pde;h=6ceb64a57916c094e87e5983c07b5dd1b4623083ADhb=H
źródło
Jeśli korzystasz z oprogramowania do mierzenia czasu swoich mówców, najłatwiejszym sposobem jest prawdopodobnie wygenerowanie dwóch niezależnych strumieni danych i przełączanie między nimi. To podejście może działać całkiem dobrze, niezależnie od tego, czy wyjście głośnika jest kontrolowane przez pin I / O lub DAC. Na przykład:
Powyższe jest podstawowym podejściem, którego użyłem w pozytywce opartej na PIC w 1996 roku (używając kodu asemblera zamiast C). Zauważ, że częstotliwość przerwań musi być 8-krotna efektywna częstotliwość próbkowania, ale każde przerwanie musi przetworzyć tylko jeden głos. Zauważ, że jeśli filtrowanie wyjściowe jest dobre, to podejście zapewni 3-bitową efektywną rozdzielczość DAC niż dodawanie próbek numerycznie, a następnie ich wysyłanie, ale generuje dużo szumu przy częstotliwości próbkowania i jej wielokrotności. Filtrowanie jest zatem jeszcze ważniejsze niż byłoby inaczej.źródło
Robili to na starych systemach gier i w czasach „ głośników PC ”, ale nie wiem jak.
Najpierw zgadnij: pomyśl o fali, którą idealnie byś utworzył, a następnie wyobraź sobie, że zniekształcasz ją do mocno obciętego kwadratu, a następnie utwórz ten kwadratowy kształt, przełączając wyjście w odpowiednim momencie. Miałby jednak wiele intermodulacji .
Druga myśl: czy można znacznie zwiększyć częstotliwość oscylacji i wyjściowe sygnały analogowe w stylu PWM ?
źródło
Jak już wspomniano, można to zrobić w taki sam sposób, jak w przypadku głośnika komputerowego (który obsługuje tylko włączanie / wyłączanie opcjonalnie podłączone do kontrolera PWM). Zasadniczo rozumiem metodę polegającą na włączaniu i wyłączaniu głośnika wystarczająco szybko, aby nigdy nie był w pełni włączony lub wyłączony (trochę tak, jak działa zasilacz impulsowy). To sprawia, że głośnik ciągle się porusza między włączaniem i wyłączaniem, generując sygnał analogowy.
Jedyne problemy to to, że potrzebujesz prawdziwego głośnika (myślę, że piezo porusza się tak szybko, że osiąga pełne włączenie i wyłączenie zbyt szybko) i musisz być w stanie wystarczająco szybko przełączyć bit. Przeprowadziłem kilka eksperymentów i opracowałem maksymalną prędkość około 5 MHz, która powinna wystarczyć na sygnał audio 11,025 Hz (prawdopodobnie najlepszą jakość, jaką można uzyskać).
Oczywiście 11025Hz przy 8 bitach to 11 kilobajtów / sekundę, co jest znacznie szybsze niż prędkość portu szeregowego. Pozwoliłoby to na przechowanie w pamięci flash może drugiej lub dwóch wartości audio, więc jesteś prawie ograniczony do odtwarzania dźwięku generowanego w locie, pod warunkiem, że pozostawia to dość wolnego czasu procesora, aby skręcić głośnik!
Istnieje również kilka innych metod, aby to osiągnąć, i wygląda na to, że istnieje już implementacja dla Arduino metody opisanej powyżej.
źródło
Możesz po prostu dodać strumienie, jak opisano tutaj:
http://www.vttoth.com/digimix.htm
źródło
Odtwarzaj przez chwilę dźwięk A, na przykład może 50 ms, a następnie dźwięk B i przełączaj się tam iz powrotem. Chodzi o to, aby przełączać się szybciej niż ucho może to rozpoznać i będzie to brzmiało tak, jakby grało jednocześnie.
źródło
Uważam, że dla Arduino istnieje biblioteka brzmień, która wykonuje dwa dźwięki. Powinieneś być w stanie dostosować kod do używanego układu AVR. Na stronie arduino.cc znajduje się także kilka doskonałych wątków generujących fale
Jeśli zdecydujesz się na dodanie przetwornika cyfrowo-analogowego, mam przykład oscylatora sterowanego numerycznie pod adresem http://wiblocks.luciani.org/docs/app-notes/nb1a-nco.html Cztery niezależne kanały wyjściowe. Quad DAC i referencja to tylko około 2 USD.
źródło
Oto mój kod do grania 2 melodii jednocześnie. Niestety, musisz się zarejestrować u maniaków AVR, aby uzyskać dostęp.
źródło