Elektroda.pl
Elektroda.pl
X
Szafy Rack
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Synth8 Unisonowy, 8mio kanałowy stereofoniczny syntezator 8miobitowy

bobeer 07 Cze 2013 00:09 7098 4
  • Synth8 Unisonowy, 8mio kanałowy stereofoniczny syntezator 8miobitowy Synth8 Unisonowy, 8mio kanałowy stereofoniczny syntezator 8miobitowy


    Mimo upływu lat w dalszym ciągu lubię od czasu do czasu odświeżyć sobie w pamięci elektroniczne brzmienia lat 80tych, kiedy to po raz pierwszy miałem okazję usłyszeć „syntetyczną” muzykę pochodzącą z wielkich drewnianych „szaf” (automaty arcade) lub trochę mniejszych plastikowych pudełek zwanych komputerami osobistymi. W tamtym czasie jeszcze nie miałem większego pojęcia o technice i sposobie kreowania dźwięków na drodze elektronicznej, ale to nie przeszkadzało w delektowaniu się przeróżnymi aranżacjami, wiele z nich do tej pory uważam za prawdziwe arcydzieła tak pod względem muzycznym jak i programistycznym (np. AGENTX2 Tim Follin wersja na ZX spectrum, nie C64 http://z80.i-demo.pl/Tim_Follin-Agent_X_2.mp3 ), ale nie o sztuce będzie tym razem.
    Po latach przyjemność z muzyki nie minęła, dodatkowo wiedzy o jej tworzeniu i przetwarzaniu trochę przybyło. Wcześniej lub później musiał więc nadejść czas na 'syntezę' zainteresowań ;) . Jako, że systemy oparte o AVR w międzyczasie udało mi się poznać nieco bliżej, niż te używane w starych 8bitowych komputerach, postanowiłem że sprawdzę jak będzie brzmiała muzyka wytworzona za pomocą takiego kontrolera, z wykorzystaniem jedynie jego własnych zasobów bez użycia dodatkowych przetworników lub filtrów. Jeszcze przed rozpoczęciem prac wyobrażałem sobie, że wyprodukowany z AVRa dźwięk będzie przypominał coś pomiędzy dokładnym i czystym brzmieniem sprzętowych generatorów jak AY38910 lub SID, a nieczystym bo mocno zniekształconym „pwmowym” – brzmieniem „jednobitowej” muzyki dochodzącej z beepera zx spectrum. Jak później się okazało wiele się nie pomyliłem, zapewne również z tego powodu, że pod kątem takich właśnie dźwięków syntezator został napisany (możliwie rozbudowana regulacja PWM). Pomimo 8 kanałów nigdy nie uzyskamy na synth8 prawdziwie „soczystych” brzmień, jak np. z SIDa MOS658x, z powodu braku jakichkolwiek filtrów, ograniczonej rozdzielczości regulacji rejestrów pwm, niskiej częstotliwości DDS i aliasingu, oraz innych niedoskonałości wynikających z programowej realizacji syntezy. (Jeśli mowa o SID, to pod koniec przygotowywania SYNTH8 natknąłem się na bardzo ciekawą stronę projektu emulatora SIDa właśnie na AVR / ARM.
    http://www.swinkels.tvtom.pl/swinsid/
    Przy okazji przypomniałem sobie budowę uświęconego wręcz generatora, i powody z jakich emulacja programowa tego „instrumentu” jest nieco problematyczna ;)

    Wracając jednak do tego niezwykle niepraktycznego projektu ;). Głównym jego celem jak już wspominałem było poznanie możliwości dźwiękowych procesora AVR, oraz próba oprogramowania w miarę wydajnego syntezatora o parametrach umożliwiających uzyskanie różnorodnych brzmień podobnych do tych z „ośmiobitowych czasów”. Na wstępie założyłem, że nie będzie odgrywania gotowych „sampli” tak jak ma to miejsce w 'modplayerze', na rzecz 256 bajtowych tablic fali, w których znajdują się podstawowe przebiegi - sinus kwadrat piła trójkąt i co kto sobie zechce jeszcze umieścić w romie, bo miejsca w M16 pozostało nieco, a po użyciu M32 niecowięcej ;) (Chociaż pod koniec aż mnie korciło bo pozostało sporo czasu procesora, a dorobienie „samplera” do odgrywania 8bitowych sampli stereo z karty nie było by żadnym problemem zakładając rezygnacje z używania SD do odczytywania pliku midi). Charakterystyczną cechą jest wykorzystywanie tych samych tablic do generowania kształtu sygnału, oraz modulacji obwiedni, częstotliwości itd. Syntezator posiada osiem niezależnych kanałów. Każdy z nich ma 32 8 bitowych rejestrów (wykorzystane 7) sterowanych komunikatami midi przez port szeregowy w standardzie MIDI 31.250 kbit.
    Takie rozwiązanie umożliwia generowanie przeróżnych efektów z użyciem minimalnej liczby danych wysyłanych do syntezatora, oraz użycie popularnych samplerów midi, żeby wydobyć z układu jak najszybciej jakie kolwiek dźwięki. ;)



    Krótko o programowaniu..

    Generator każdego kanału to DDS operujący na 16bitowym słowie które bezpośrednio przekłada się na częstotliwość. Nie będę tutaj opisywał zasady działania DDS, bo jest o tym mnogość informacji. Po pobraniu próbki z tablicy (można wybrać numer tablicy z rom lub ram) każdy kanał umożliwia dodatkowe operacje w celu wzbogacenia brzmienia surowego przebiegu. Pierwsza możliwość modyfikacji, to regulacja przesunięcia fazy pobierania próbek z tablicy ustalana w CC04. Następnym elementem jest PWM który umożliwia pominięcie próbek z WaveTable. Na miejsce próbki ładowana jest wartość z rejestru PWS1 (PhaseWidthSampel) - CC03. Następne urozmaicenie, to możliwość modulacji amplitudowej próbki generatora próbką z poprzedniego generatora. Wybór takiej opcji ustawia się bitem nr 1 rejestru CC00. Pomysł ten zaczerpnąłem z działania wcześniej wspomnianych sprzętowych generatorów, które w swojej konstrukcji posiadają właśnie taką możliwość, podobnie z generatorem szumu. Istnieje również możliwość „XORowania” wartości próbek dwóch generatorów bit.5 CC00 (jest to już mój oryginalny pomysł na który wpadłem przy pracy z MEGAwave). Ustawienie bitu 3 CC00 powoduje modulowanie obwiedni generatora prosto z generatora szumu. Bit.4 CC00 zmniejsza modulacje szumem o połowę. Bit 2 mnoży próbkę x2 co podnosi poziom sygnału oraz „ukwadratowia” przebiegi. Na końcu syntezy kanału znajduje się modulacja obwiedni i równoczesna regulacja amplitudy, umożliwiająca zmianę głośności, oraz umiejscowienie generatora na panoramie stereo. W kodzie można też odnaleźć fragment odpowiedzialny za synchronizowanie zmian amplitudy do zera fali (W praktyce do początku tablicy, ale najczęściej znajdują się tam próbki o najniższej wartości).
    Poniżej fragment programu dla generatora CH1 (ogólnie cały program jest napisany bardzo nieefektywnie rozmiarowo, każdy generator ma swój osobny powtarzający się kod, dodatkowo można natknąć się na nieco niekonsekwencji spowodowanej nieciągłością czasową pisania programu ;) ).

    Kod: asm
    Zaloguj się, aby zobaczyć kod

    W celu uzyskania zadowalającej jakości dźwięku przy wydajności umożliwiającej obsługę 8 kanałów okazało się konieczne napędzenie procesora z nieco większą niż zwykle częstotliwością. Pierwotnie było to 34.560Mhz, później zmniejszone do 32MHz. Wysoka częstotliwość zegara przekłada się na wyższą częstotliwość sprzętowego PWM procesora oraz mniejszy poziom szumów na wyjściu pseudo 16bitowego daca, przede wszystkim DDS wymaga jak najwyższego zegara w celu uniknięcia aliasingu dla wyższych częstotliwości. Synteza pracująca z 40kHz zegarem dostarcza akceptowalnej jakości sygnał do mniej więcej 2kHz.
    Generowany dźwięk jest pobierany z 4 portów PWM. Pierwszy dostarcza sygnału MSB drugi PWM dostarcza LSB. Sygnały zsumowane w odpowiednich proporcjach zapewniają pseudo 16 bitową rozdzielczość przy częstotliwości „nośnej” 125kHz. We wcześniejszej wersji z zegarem 34MHz częstotliwość odniesienia była uzyskiwana z preskalera przetwornika ADC, który dostarczał koniecznego do równej pracy programu sygnału upłynięcia 832 cykli zegarowych, co odpowiadało częstotliwości próbkowania oraz głównej pętli programu 41.53kHz (dla 25MHz=30,04kHz). Później częstotliwość odniesienia została uzyskiwana z jednego z timerów . (32MHz/(3X256)=41,666kHz SR). W programie zrezygnowałem z używania przerwań, również stos przed dopisaniem obsługi odczytu karty SD oraz przetwarzania pliku midi był nieużywany.
    Bloki przetwarzające są wywoływane poprzez odpowiedni podział czasu z wykorzystaniem rozkazu IJMP.
    Przykład podziału czasu procesora dla obsługi jednego kanału (1/8 głównej pętli):

    Code:
    ijmpvectors:   ;(8x16=128 wektorow)
    
          rjmp Usart_receive            ;midi read!
          rjmp CH1Umodulator         ;Universal modulator
          rjmp Ch1_ornamentator         
          rjmp Ch1FRQmodulator
          rjmp Ch1PITmodulator         ;PITch koniecznie cykl za FRQ
          rjmp Ch1ENVmodulator
          rjmp Ch1PORTAM
          rjmp Ch1BUFMOD            
          rjmp Usart_receive            ;midi read!
          rjmp nul               ;reserved
          rjmp nul
          rjmp deltatimer
          rjmp file
          rjmp file2
          rjmp nul
          rjmp Ch1BUFMOD
          ...

    Poglądowy opis poszczególnych bloków programu „syntezatora”

    1.ATMEGA_8CH_synth.asm - program główny, inicjalizacja rejestrów, zarządzanie pętlą główną, przydział czasu procesora na bloki syntezatora oraz synchronizacja z zegarem.
    2.table.inc- zawiera tablice fali, nuta/częstotliwość, ornamenty oraz inne tablice LUT.
    3.usart_midi.inc- Program odpowiedzialny, za cykliczne sprawdzanie i pobieranie odebranego bajtu z usart lub pliku (program wywoływany 1/8 czasu procesora – czas procesora umownie cały obieg programu dokoła pętli głównej mainloop, program usarata wykonywany jest zawsze w nieparzystym numerze cyklu timera dzielącego czas procesora-8 bitowy licznik w zależności od jego wartości wykonywane są programy usart_midi oraz modulators i reg_buf ).Program zawiera rozpoznawanie komunikatów midi, i odpowiednie ładowanie danych (częstotliwość -nuta, wartości kontrolerów CC) bezpośrednio lub pośrednio przez zmienne _buf do syntezatora lub programu modulatorów.
    4.synth.inc- Program zawierający syntezę DDS oraz dodatkowe obliczenia związane z modulacją amplitudy. Synth wykonuje się za każdym razem wywołania petli głównej. Warto tutaj zwrócić uwagę na „nie symetryczna” generacje fali (dobrze to widać na początku odtwarzania- składowa stała wędruje z 0V do ½ VCC, na końcu wraca na 0V), oraz ładowanie zbuforowanych wartości obwiedni podczas przejścia napięcia fali przez zero (faktyczne zero a nie ½) gdyż na próbkach bez znaku są prowadzone obliczenia.
    5.modulators.inc- Procedury związane z modulacja dźwięku/zmiana parametrów zmiennych ładowanych już bezpośrednio do synth. Znajdują się tutaj podprogramy odczytujące wartości z tablic oraz rejestrów i w zależności od czasu modyfikujące amplitudę lub częstotliwość dla danego kanału.
    6.ornamentators.inc- Program generujący charakterystyczne ornamenty dźwięku – modulowanie częstotliwości w równych odstępach czasu przesunięciami o zaprogramowaną liczbę półtonów. Ornamenty są odczytywane z osobnych tablic i mają długość 64B każdy. (W standardowej nomenklaturze muzycznej zwykło się nazywać takie ozdobniki arpeggio).
    7.univmod.inc- Program uniwersalnego modulatora. Modulator który można zaprogramować na zmienianie wartości dowolnego kontrolera CC w dowolnego kanału. Modulator korzysta z tych samych tablic w rom co reszta generatorów.
    8.portamento.inc- Program umożliwiający płynne przejścia między kolejnymi tonami. Działanie ze względu na komplikacje dopasowania do standardu odbiega nieco od rasowego portamento używanego w syntezatorach.
    9.reg_buf.inc- programy przepisujące zmienne buforowane w celu ograniczenia zakłóceń dźwięku podczas zmiany wartości parametrów związanych z obwiednią - VOL PAN PH PW PWS.
    *dodane po roku bo tyle sobie leżał syntezatorek w poczekalni, w międzyczasie doczekał się procedur obsługi karty SD i odczytu midi z pliku: *
    10.M816_SD.inc- obsługa karty SD z poziomu sprzętu, inicjalizacja, adresowanie itd.
    11.file_parser.inc- uproszczone odczytywanie nut midi z pliku (pomijane parametry związane z tempem).

    W skrócie o działaniu programu:
    Na początku sprawdzane jest, czy można zainicjować kartę SD. Jeśli tak, program szuka nagłówka MThd i uruchamia odczyt z karty SD (adresowanie 65536 bloków tylko). Jeśli brak karty, oczekuje na strumień danych poprzez usart. Dioda zaświeca się w przypadku wykrycia mniej niż 20 cykli pozostałych do sygnału synchronizacji- wskaźnik przeładowania procesora, przydatny podczas debuggingu i testu równomiernego rozłożenia czasu procesora na bloki modulatorów. Niektóre bloki syntezatora, jeśli użyte w wielu kanałach równocześnie mogą przedłużyć ponad normę czas wykonywania pętli programowej (np. portamento). Podczas prawidłowej pracy dioda powinna być zgaszona, ewentualnie sporadycznie sobie mrugnąć ;).

    Nieco o sprzęcie:
    Jak widać na schemacie projekt HW jest minimalistyczny, nie użyłem nawet kondensatorów na wyjściu pwm. Potencjometry służą do dokładnego „odważenia” bajtów MSB LSB pwmowego daca. Procesor powinien bez problemu działać przy 3.7V, szczerze mówiąc to u mnie większość czasu był zasilany 4.5V, również po włożeniu karty SD (nie udało się jej uszkodzić). Nie próbowałem używać generatora kwarcowego procesora, dostawał zegar z osobnego układu. Niestety 32MHz to szczyt możliwości stabilnej pracy dla M16, dla M32 sprawa wyglądała minimalnie gorzej w trakcie testów maksymalnego zegara przy jakim procesor jeszcze działa jakkolwiek poprawnie, ale myślę, że z 32MHz M32 poradzi sobie równie dobrze jak M16. Układ po zablokowaniu zasilania tantalami o niskim ESR umożliwia osiągnięcie odstępu sygnał szum na poziomie nie gorszym niż 60dB. Do wyjścia można podłączyć 32omowe słuchawki i głośność będzie w sam raz. W celu rejestracji „sampli” podłączyłem wyjście bezpośrednio z wejściem karty SB220 bez zauważalnych szkód w obrazie audio spowodowanych nieodfiltrowanym 125kHz pwm.

    Jak już wspomniałem przedstawiony projekt jest urządzeniem mało przydatnym, zamieszczonym głównie w celach edukacyjnych i archiwizacyjnych. Jedynym praktycznym zastosowaniem wydaje się możliwość odtwarzania muzyki bezpośrednio z karty SD i retransmisja strumienia midi na wyjściu TX procesora.

    W celu bardziej intuicyjnej analizy przepływu danych w programie spróbowałem sporządzić jakikolwiek schemat blokowy syntezatora. Mam nadzieje, że chociaż w części wyjaśnia zasadę działania programu oraz ilość czasu jaką procesor musi poświecić na poszczególne jego elementy.
    Zamieszczam też źródło całego programu, nieco rozlazłe, ale chciałem jak najbardziej oszczędzić na czasie, bo tego nigdy za wiele w takim przypadku. Podsumowując dołączam fragmenty audio kilku transkrypcji jako efekt końcowy całego projektu. Nie są one najlepszym „demo” wykorzystującym w pełni możliwości procesora, ale pozwalają na przybliżone zapoznanie się z jego możliwościami. Niestety używanie popularnych programów do edycji midi jest tu dość niewygodnie. Aby w pełni zapanować nad wszystkimi możliwościami generatorów należało by napisać osobny specjalizowany tracker umożliwiający szybki i odpowiednio dostosowany dostęp do rejestrów CC które są tu najczęściej wykorzystane w niestandardowy sposób.

    Zainteresowanym tematem życzę udanych eksperymentów dźwiękowych.


    Ponieważ nie mogłem załadować na elektrodę plików nie filmowych audio, załączam niżej spakowane zipem.

    Fajne! Ranking DIY
    Potrafisz napisać podobny artykuł? Wyślij do mnie a otrzymasz kartę SD 64GB.
    O autorze
    bobeer
    Poziom 28  
    Offline 
    Specjalizuje się w: elektronika
    bobeer napisał 1388 postów o ocenie 367, pomógł 56 razy. Mieszka w mieście Nowy Targ. Jest z nami od 2001 roku.
  • Szafy Rack
  • #2
    Gigantor
    Poziom 18  
    A jak ja mówie mojej kobiecie, że SID brzmi soczyście, to muszę za karę zmywać naczynia :/ Świetna robota! Jak na prostotę konstrukcji brzmi całkiem sensownie. Jak uzyskujesz tablice [256] z kolejnymi próbkami przebiegów? Mam swój sposób (generacja w edytorze audio -> zapis "raw data" 8 bit -> edycja jako plik tekstowy do postaci "tablicowej"), ale podejrzewam, że można jakoś prościej. I skąd nazwa "unisonowy"?
    Nawiasem jak przeczytałem opis projektu pomyślałem: jako demo powinien znaleźć się "One man and his droid" lub "Monty on the run" - no i nie zawiodłem się.
    Pozdrawiam!
  • Szafy Rack
  • #3
    bobeer
    Poziom 28  
    Już myślałem, że się nie doczekam żadnego komentarza, ale zdawałem sobie sprawę, że temat jest mocno „niszowy” i bardzo nie wiele osób zajmujących się elektroniką będzie chciało się wypowiadać w tej tematyce. Mówiąc szczerze, to nie pamiętam skąd wziąłem tablice. Większość pewnie pochodzi z innych projektów, albo z generatora online (gdzieś widziałem stronę która generowała tablice sinus dla zadanej długości i rozdzielczości), reszta dopisana ręcznie. Twój pomysł z edycją pliku audio w edytorze jest całkiem dobry, nie spotkałem się „po drodze” z niczym lepszym.

    Do "One man and his droid" o którym piszesz jest dostępny doskonale zrobiony plik midi, więc wypadało się nim zająć ;). Tak jak już wspomniałem jeżeli by użyć dostosowanego narzędzia edycyjnego, można uzyskać o wiele więcej ciekawych efektów. Nazwa unisonowy pochodzi z prostego faktu, że w jednym kanale midi nie uzyskamy więcej niż 1 dźwięk, a że synth8 składa się z 8miu kanałów to osobna rzecz. W każdym razie w łatwy sposób polifonii w nim się nie da zrobić np. podłączając keyboard bez rozbicia na więcej kanałów. Przez moment zastanawiałem się, czy nie zrobić właśnie obsługi wielodźwięku, ale wtedy syntezator nie przypominał by już sprzętowego generatora zorientowanego rejestrowo. Druga sprawa, to fakt, że już taki instrument jest zrobiony i „kolega” daje popis swoich i jego możliwości ;)
    http://www.youtube.com/watch?v=m1pchpDD5EU

    Pozdrawiam również :)
  • #4
    Gigantor
    Poziom 18  
    Niestety ludzie tworzący układy związane z syntezą dzwięku są na elektrodzie dość samotni, dlatego niewiele tego rodzaju układów tu zamieszczam. Sam popełniłem już (albo dopiero?) trzy syntezatory DDS i myślę, co z tym zrobić dalej. Na twoim miejscu zrobiłbym fotkę układu i wrzucił na główną - zadałeś sobie zbyt dużo trudu by taki kawał wiedzy (nie tam jakieś tłumaczenie z zachodniego portalu) został pogrzebany w "Artykułach" (jak zobacze na głównej Twój projekt, to wrzucę też własny, w kupie siła!)

    Pozdrawiam!

    edit
    Zapomniałem zapytać, jak generujesz szum.
  • #5
    bobeer
    Poziom 28  
    Projekt nie był zaplanowany jako DiY z powodu jego nieprzydatności (choć jak sobie przypomnę co czasem w diy się pojawia...), płytki nie fotografowałem, bo co będę się wygłupiał z kawałkiem uniwersalnej na dodatek z różnymi innymi układami które w tym przypadku nie są wykorzystane ? :). Zdaję sobie sprawę z ilości czasu, jakie poszły na ten projekt w imię nauki i wartości poznawczych, ale najprawdopodobniej nie będę już się więcej zajmował tym tematem (nie na AVR), stąd oddałem źródło i niech się młode pokolenie rozwija ;). Generator szumu to fragment kodu który znalazłem gdzieś w sieci. Jest w osobnym pliku .inc, zajmuje nie wiele czasu i jest zupełnie wystarczający w tym zastosowaniu. Wykonuje się z taką samą częstotliwością co dds umieszczając w 256 Bajtowej tablicy w RAM efekty swojego działania ale nie tylko. Używając Mega32 można by wykorzystać dodatkowy RAM i ładować tam również tablice przez midi za pomocą np. sysex ale to tylko podpowiedź gdyby ktoś chciał rozbudować program lub napisać coś podobnego. Podobnie z ROM dodatkowe 16kB na dodatkowe tablice do wykorzystania jako fale albo obwiednie. Synth8 nie jest idealną i do końca przemyślaną konstrukcją, bo nie pisałem go w celu codziennego użytkowania, jak wiele innych urządzeń których używam a ich kody są przeze mnie jak najlepiej dopracowane. Gdybym pisał od nowa ten syntezator, to dużo bym pozmieniał. Ale właśnie w takim celu został napisany, żeby mieć jakieś doświadczenie w tej dziedzinie :).

    Fakt, że mało ludzi zamieszcza projekty „syntezatorów” to nie powód żeby nie publikować takich projektów a wręcz przeciwnie, więc nie wiem na co jeszcze czekasz ;)