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

[Atmega328][C][PWM] - Odtwarzanie .wav z karty SD

10 Wrz 2013 11:42 3009 13
  • Poziom 7  
    Cześć,
    Próbuję odtworzyć plik .wav z karty SD wykorzystując PWM ale nie do końca mi to wychodzi. Dźwięk jest w okropnej jakości, muzykę ledwo da się rozpoznać, strasznie charczy, ale jeśli się wsłucham to jakoś tekst wokalu wychwycę:D

    O to kawałek kodu odpowiedzialnego za odtwarzanie:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Wydaję mi się, że wina leży gdzieś w Timerze.

    Kawałek schematu:
    [Atmega328][C][PWM] - Odtwarzanie .wav z karty SD

    Pozdrawiam
  • Pomocny post
    Poziom 20  
    Nie ładuj bufora w przerwaniu, ustaw flagę i w pętli głównej czytaj z karty.
  • Poziom 7  
    d.d napisał:
    Nie ładuj bufora w przerwaniu, ustaw flagę i w pętli głównej czytaj z karty.

    Rzeczywiście, poprawiło to jakość dzwięku ale dalej mam problem ponieważ muzyka gra wolniej niż powinna. Wav ma 8000khz jak ustawić przerwania pod tego wava? Czy na 8Mhz procka wycisnę z jakiegoś wava więcej niż 8000khz?
  • Pomocny post
    Poziom 39  
    sansik napisał:
    Czy na 8Mhz procka wycisnę z jakiegoś wava więcej niż 8000khz?
    Sam sobie odpowiedziałeś na pytanie...
    Gdyby "procek" nic poza tym nie robił i cała operacje odczytania i wyemitowania "próbki" trwała jeden takt, to wtedy odpowiedź brzmiała by :tak, wyciągniesz 8000kHz - czyli 8MHz.
    Ale wiesz przecież, że tak nie jest.

    Chyba - że pomyliłeś 8000kHz z 8000Hz.
  • Poziom 7  
    mickpr napisał:
    sansik napisał:
    Czy na 8Mhz procka wycisnę z jakiegoś wava więcej niż 8000khz?
    Sam sobie odpowiedziałeś na pytanie...
    Gdyby "procek" nic poza tym nie robił i cała operacje odczytania i wyemitowania "próbki" trwała jeden takt, to wtedy odpowiedź brzmiała by :tak, wyciągniesz 8000kHz - czyli 8MHz.
    Ale wiesz przecież, że tak nie jest.

    Chyba - że pomyliłeś 8000kHz z 8000Hz.


    Przepraszam, rzeczywiście chodziło mi o 8000Hz :oops:
    Nie mam pojęcia jak ustawić timer aby odtwarzać wava który ma 8000Hz(lub więcej). Mógłby ktoś mnie nakierować jak na to patrzeć?
  • Poziom 39  
    Wywoływanie tej funkcji:
    Kod: c
    Zaloguj się, aby zobaczyć kod
    ....
    w przerwaniu to kardynalny błąd. To on powoduje owe "złe odtwarzanie".
    Przerwanie powinno być jak najkrótsze. Możesz w nim wystawiać kolejne próbki z bufora, ale nie ładować bufor z karty SD!

    Błędny (żeby nie powiedzieć chory) jest też pomysł zwalniania przerwania!
    Nie masz kalkulatora aby ustawić żądane próbkowanie? http://www.et06.dk/atmega_timers/
  • Poziom 7  
    mickpr napisał:
    Poza (jakże słusznymi) konkluzjami kolegi d.d, oglądam sobie ten kod i ...
    Kod: c
    Zaloguj się, aby zobaczyć kod
    zastanawiam się - czemu ma służyć to "IF"?

    W zależności z której tablicy(iChooseBuff) korzysta teraz przerwanie to z tej bierze informacje. Jeśli osiągnie koniec tablicy to pętla główna ładuje nowe info do tablicy nr 1, a przerwanie w tym czasie zczytuje info z drugiej tablicy, i na odwrót. Możliwe, że jest to przerost formy nad treścią, ale gdzieś wyczytałem, że w ten sposób nie pojawi się żadna dodatkowa przerwa(na zczytywanie nowego info do tablicy) w działaniu przerwania.

    mickpr napisał:

    Dodatkowo wywoływanie tej funkcji:
    Kod: c
    Zaloguj się, aby zobaczyć kod
    ....
    w przerwaniu to kardynalny błąd. To on powoduje owe "złe odtwarzanie".
    Przerwanie powinno być jak najkrótsze. Możesz w nim wystawiać kolejne próbki z bufora, ale nie ładować bufor z karty SD!

    Wywoływanie funkcji Music_Read_Next wrzuciłem już do pętli głównej.

    główna pętla:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    a przerwanie wygląda teraz tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Ta konfiguracja poprawiła o wiele jakość odtwarzania, ale teraz tylko jak skonfigurować przerwanie aby normalnie odtwarzało .wav 8000Hz przy 8MHz procek?
  • Pomocny post
    Poziom 39  
    sansik napisał:
    Ta konfiguracja poprawiła o wiele jakość odtwarzania, ale teraz tylko jak skonfigurować przerwanie aby normalnie odtwarzało .wav 8000Hz przy 8MHz procek?
    W tym celu podałem ci link do kalkulatora (jednego z wielu).
    Zaglądając do datasheet-a będziesz mógł ustawić taką częstotliwość próbkowania (wywoływania przerwania) - jaka ci się podoba.
    Oczywiście w ramach rozsądku.
  • Pomocny post
    Poziom 18  
    http://elm-chan.org/works/sd8p/report.html
    Na tej stronce jest sporo wiedzy na temat obsługi karty SD oraz na temat generowania dźwięku przy użyciu PWM. Zbudowałem na podstawie tej strony odtwarzacz wma i działa. Jakość dźwięku może nie powala, ale.....jako urządzenie do zapowiedzi głosowej idealne. Dźwięk jest zrozumiały na poziomie bardzo dobrym.
    W razie pytań do programu służę pomocą.
  • Pomocny post
    Poziom 19  
    Poczytaj ten temat link Link tu masz trochę informacji

    Należy pamiętać że częstotliwość kwarcu jest ściśle powiązana z częstotliwościa PWM a to dalej powiązane jest w częstotliwościa wystawiania próbek z pliku, ale
    to nie to samo co częstotliwość PWM, to zmiana wartości wypełnienia PWM co określony czas np 8kHz wartością pobraną z pliku. ( w Twoim przypadku 8kHz)

    kwarc 16MHz można uzyskać zgodność z plikani o próbkowaniu 32khz / 16khz / 8 khz / 4khz
    dla kwarcu 11,0952MHz uzyskujemy 22,05kHz / 11,025KHz / 5,5125kHz

    a wynika to z matematyki = częstotliwosc liczymy dla 8 bit pwm fosc/510 dla prescale =1
    czyli dla 16MHz / 510 = 31,37kHz / dzielnik (2) = 15,68kHz blisko 16kHz

    Wzór dla prawidłowego wyliczenia częstotliwości kwarcu to (uwaga na jednostki!!!)
    dla dzielnika przez R=2 programowego Fosc(MHz= Fprób(kHz) * (0,51 * R)

    dla próbki 16kHz * (0,51 * 2) = 16,32MHz taki powinien być prawidłowy kwarc, ale przyjmujemy przybliżenie i zastosowano popularny kwarc 16MHz.

    Dla kwarcu 24MHz uzyskamy częstotliwość PWM 24 / 510 = 47,0588kHz czyli używając prograwowego dzielnika 2, 3 lub 4 uzyskamy odpowiednio
    23,52 kHz, 15,58 kHz i 11,76 kHz
  • Pomocny post
    Poziom 32  
    By uzyskać wysokiej jakości dźwięk 8 bitowy możesz użyć programu ( SoX ) i poniższej linii:
    Code:
    sox --buffer 131072 -S -V "%1" -c 1 -b 8 "%1.u8" highpass 10 rate -v -s -I 44100 gain -n -0.5 dither -f high-shibata -p 8


    W tej chwili to chyba najlepsze co można osiągnąć w domowych warunkach jeśli chodzi o jakość dźwięku na 8 bitach - przypuszczam ze uzyskasz dynamikę zbliżoną do 16 bitów bez większych problemów. Prędkość odtwarzania próbek jest ustawiona na 44100 i można ja lekko modyfikować (w granicach ok +- 800 - 1000Hz - zmiana parametru "rate -v -s -I 44100").

    --
    W wypadku 8 bitowych uC bardziej opłaca się użyć wysokiej jakości próbek 8 bitowych niż konwertować 16 bitowe próbki w locie - po prostu mały 8 bitowy uC nie poradzi sobie z poprawnym (wysoka jakość) skonwertowaniem 16 bitów (konieczność użycia ditheringu i noise shapingu) - stosując prędkości próbkowania powyżej 48000Hz - powiedzmy rzędu 55 - 80kHz jesteśmy w stanie korzystając z właściwie przygotowanych próbek bez problemu uzyskać dynamikę przekraczającą 20 bitów dla sygnałów akustycznych.

    W wypadku szybkich uC 8 bit wydaje się możliwe zastosowanie programowych technik (Delta Sigma) w połączeniu z sprzętowym PWM o ograniczonej rozdzielczości (np 8 bit) w celu uzyskania wyższej rozdzielczości (np 16 - 20 bitów oczywiście kosztem prędkości próbkowania co nie jest jednak problemem dla niektórych aplikacji np oświetlenie LED) - pomocna może być poniższa nota aplikacyjna:

    SLYT076
  • Poziom 7  
    Udało mi się odtworzyć .wav 22050Hz. Jest bardzo fajnie, muzyczka gra w bardzo fajnej jakości, ALE... słyszę cały czas szum(pierdzenie), który jest jakby nałożony dodatkowo w muzyczce, taki odrębny szum. Jak go wyeliminować?

    Aktualnie kod odpowiedzialny za odtwarzanie przedstawia się tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    A schemat jest ten sam jak w 1-szym poście.

    Pozdrawiam
  • Poziom 32  
    sansik napisał:
    Udało mi się odtworzyć .wav 22050Hz. Jest bardzo fajnie, muzyczka gra w bardzo fajnej jakości, ALE... słyszę cały czas szum(pierdzenie), który jest jakby nałożony dodatkowo w muzyczce, taki odrębny szum. Jak go wyeliminować?


    Powodem może być program (np. wypadają ci próbki), powodem może być nieskuteczna filtracja dolnoprzepustowa (w wypadku PWM wymagania odnośnie filtru dolnoprzepustowego są naprawdę bardzo duże), problemem mogą być zakłócenia przenoszone przez zasilanie (jakość sygnału będzie tak dobra jak jakość zasilania).
  • Pomocny post
    Poziom 19  
    Przyczyna jest w tych linijkach

    Kod: c
    Zaloguj się, aby zobaczyć kod


    w przerwaniu robisz | i do tego dzielenie przez 1024 ???!!! wiesz ile takie operacje trwają??? Chcesz 16 bitów wystawiać do PWM 8bitowego??? to robi się inaczej a jak to powiem później.

    Tak jak podałem w linku do postu powyżej (chyba nie przeczytałeś) to podam jeszcze raz:

    W przerwaniu timera masz tylko ładować do PWMa bajt z bufora wskazywany przez wskaźnik, nic więcej nie robisz w przerwaniu, a już na pewno nie czasowożerne procedury, tam tylko flagi. Ma to być jak najbardziej proste i krótkie czasowo, reszta w programie głównym.

    Do tego źle zadeklarowałeś wskaźniki, dlaczego integer???!!! Pomyśl ile czasu zajmuje operacja na takiej zmiennej?

    Flagi deklaruj jako 8bit
    Kod: c
    Zaloguj się, aby zobaczyć kod
    mają być bajtowe bo obsługa warunków na prostej zmiennej jest krótka.
    Wygeneruj sobie dwa programy, jeden prosta operacja na int (2 bajty) drugi program na char (1 bajt) i zobacz co robi procesor i ile cykli maszynowych zajmuje wykonanie obu programów to zrozumiesz!?

    Dlaczego deklarujesz bufory o rozmiarze 400??? Używaj bufora 64 128 lub 256 i na takich operuj, upraszcza to operacje procesorowi i Tobie przy pisaniu programu, to jest 8 bitowy procesor. Tam gdzie nie musisz używać 16 bitów rób wszystko na 8 bitach, zmienne 8bitów, wskazniki 8bitowe itp.
    Użyj bufora 256 i wskaźnika 8 bitowego
    Kod: c
    Zaloguj się, aby zobaczyć kod

    unikniesz przekroczenia tablicy
    Cytat:
    Trzeba też pamiętać, że jeżeli zdefiniujemy tablicę n elementową i spróbujemy zapisać coś pod indeksem równym lub większym n to kompilator nie zgłosi błędu, ale skutkować to może nieprawidłowym działaniem programu.