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

Player plików wav PCM na STM32

Samuraj 03 Sty 2015 11:29 4341 48
  • #1 03 Sty 2015 11:29
    Samuraj
    Poziom 35  

    Wiem iż temat był poruszany już parokrotnie i widziałem działające projekty lecz mam pytania z tym związane lecz nie znalazłem w nich odpowiedzi na nurtujące mnie pytania.
    Staram się odtworzyć pliki wav, bez kompresji - modulacja PCM. Znam pokrótce zasadę działania takiego odtwarzacza:
    1) odpalam timer zależny od częstotliwości pliku wav - znajdę ją w nagłówku pliku offset 24, 4 bajty.
    Timer ten będzie pobierał kolejne dane o karmił nimi generator PWM.
    2) konfiguruje drugi timer jako generator PWM. Dla stereo można utworzyć dwa takie generatory.
    I tu mam pytanie Dane którymi będę karmił ten generator to jest wypełnienie czy częstotliwość. Jeśli częstotliwość to jak przeliczyć dane z pliku na częstotliwość jaka ma być generowana.

    0 29
  • Oscyloskop cyfrowy Siglent SDS1104X
  • #2 03 Sty 2015 11:47
    piotrva
    Moderator na urlopie...

    Dane zawarte w pliku wav to wartości chwilowe sygnału, czyli odpowiadają one wypełnieniu sygnału PWM (co w połączeniu z filtrem, zwykle pasożytniczo powstającym w układzie, da nam wartość analogową).

    Częstotliwość PWM dobrze ustawić poza granicą słyszalności, ja osobiście korzystałem np. z ok. 60kHz

    0
  • Pomocny post
    #3 03 Sty 2015 11:54
    M. S.
    Poziom 34  

    Cytat:
    Dane którymi będę karmił ten generator to jest wypełnienie czy częstotliwość.


    Wypełnienie. Timer będzie generował przebieg o stałej częstotliwości

    Częstotliwość ta powinna być większa od częstotliwości słyszalnej.

    0
  • #4 03 Sty 2015 12:11
    Samuraj
    Poziom 35  

    Czy jeśli ustawie inną częstotliwość generatora PWM (mamy dwie jak widać) to czy muszę przeliczać dane z pliku :?:

    0
  • Pomocny post
    #6 03 Sty 2015 13:21
    atom1477
    Poziom 43  

    Nie mniej jednak najlepiej jak by ta częstotliwość była powiązana z częstotliwością próbkowania w pliku Wav.
    Czyli jak próbkowanie to 8kHz to PWM też powinien mieć 8kHz. Albo wielokrotności czyli 16, 24, 32kHz, itp.
    Co ciekawe użycie częstotliwości PWMa większych od 20kHz bez odpowiedniego filtru na wyjściu niewiele daje, i dalej słychać pisk 8kHz.
    Dopiero filtr dolnoprzepustowy o częstotliwości 4kHz (4kHz dla próbkowania 8kHz, dla innych ma być inny) usunie pisk.
    Przy innej częstotliwości PWMa, np. 9kHz, do PWMa będą trafiały próbki z częstotliwością 8kHz. A PWM ma 9kHz. Zatem odtworzy 7 próbek normalnie a ósmą dwa razy.
    I się pojawi pisk 1kHz.
    Dlatego najlepiej jak by PWM był zsynchronizowany z częstotliwością próbkowania w pliku Wav.
    Z tego też powodu nie widzę powodu stosowania dwóch Timerów do tego.
    Wystarczy jeden (ten od PWMa), np. 32kHz, który co 4 okresy PWMa będzie pobierał kolejną próbkę dźwięku.

    0
  • #7 03 Sty 2015 13:38
    Samuraj
    Poziom 35  

    Na szybko udało mi się uruchomić i usłyszeć jakieś dźwięki.
    na początek bez obsługi karty pamięci, próbkę dźwięku wrzuciłem na sztywno do tablicy. Niestety nie mam źródła tej próbki i nie mogę porównać tego co słyszę z oryginałem (znalazłem coś w internecie). A słyszę it's working oraz przydźwięk :(
    Na szybko też nie bawiłem się w ustawianie drugiego timera do wrzucania próbek dla PWM'a i wrzucam w pętli z delayem.

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Czy źródłem przydźwięku jest "zanieczyszczona" próbka dźwięku czy coś skopane w konfiguracji. W domu na spokojnie ustawie timer oraz wrzucę sprawdzony plik RAW.

    Dodano po pewnym czasie.

    Sample są czyste, powodem przydźwięku jest program. Jak go wyeliminować :?:

    0
  • #8 04 Sty 2015 01:27
    94075
    Użytkownik usunął konto  
  • Oscyloskop cyfrowy Siglent SDS1104X
  • #10 04 Sty 2015 10:06
    el2010tmp
    Poziom 25  

    Po co ta zabawa z PWM i PCM skoro na pokładzie masz podwójny DAC ?

    0
  • #11 04 Sty 2015 10:19
    Samuraj
    Poziom 35  

    Widziałem ten post lecz z niego nic nie wynika. Nie wiadomo czy autor rozwiązał problem. Algorytm mam podobny, oparty na 2 timerach. Jako filtr mam podłączone 2 kondensatory i rezystor.

    Player plików wav PCM na STM32

    Myślałem nad DAC który mam w procesorze lecz korzystam z gotowej płytki i piny z DAC są wykorzystane do sterowania wyświetlaczem LCD.

    0
  • #12 04 Sty 2015 10:38
    Badmaneq
    Poziom 23  

    Testowałem kod pokazany w tamtym temacie i jak napisałem błędem było ustalenie podstawy czasu dla PWM autor chciał odgrywać dźwięk 22,05 kHz, a ustawił częstotliwość na 732,42 Hz.
    Wystarczyło ospowiednio zwiększyć częstotliwość.
    Jeśli używasz połączeń, które pokazałeś na schemacie to zapewne dźwięk jest ledwo słyszalny ?

    0
  • #13 04 Sty 2015 10:47
    Samuraj
    Poziom 35  

    Szału nie ma lecz coś tam słychać. To akurat na ten moment nie jest problemem. Problemem jest przydźwięk. Jak widać w źródle ustawiałem różne częstotliwości PWM'a i nie wpływa to na jakoś odtwarzanego dźwięku.

    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    0
  • #14 04 Sty 2015 10:57
    Badmaneq
    Poziom 23  

    Hmm, może 31250Hz to nadal za mało, może filtr oparty na 1k i 10 nF jest zły dla tej częstotliwości (nie znam się na filtrach). Jak testowałem tamten kod to zwiększyłem częstotliwość do 187,5 kHz !
    Zresztą nie miałem na wyjściu PWM żadnego filtru. Oczywiście był kondesator 100 uF w celu uzyskania "drugiej połówki sinusoidy", a zanim wzmacniacz oparty na jakimś tam trazystorze.

    0
  • #15 04 Sty 2015 10:58
    94075
    Użytkownik usunął konto  
  • #16 04 Sty 2015 11:15
    Badmaneq
    Poziom 23  

    Samuraj napisał:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod



    Niech samplowaniem zajmie się lepiej przerwanie od timera i tak jak wspomniał Albert z odpowiednią częstotliwością.
    Próbki z jaką częstotliwością przygotowane ?

    0
  • #17 04 Sty 2015 11:29
    Samuraj
    Poziom 35  

    Nie napisałem iż powyższy kod był wczorajszym dziełem na szybko.
    Popracowałem trochę nad nim i wyszło mi coś takiego:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Procesor popędziłem na 72MHz. Ustawiłem wielokrotność generatora PWM w tym przypadku 4, karmieniem generatora PWM nie jest już pętla lecz drugi Timer a jego częstotliwość jest równa częstotliwości sampla.
    I jest lepiej, dźwięk jest czysty, lecz teraz słychać cykanie :(

    Czy powodem cykania jest to iż dane znajdują się w pamięci programu i długim czasem dostępu do niej :?:

    0
  • #18 04 Sty 2015 11:47
    Badmaneq
    Poziom 23  

    Nie znam SPL'a i nie wiem w jaki sposób jego funkcje zapisują do rejestrów, może dla obliczonej wielokrotności 2250 zapis powinien być taki TIM_TimeBaseStructure.TIM_Period = 2250 - 1, to samo może dotyczyć TIM_OCInitStructure.TIM_Pulse = 128 - 1
    Poza tym przy incjacji nie ustawiał bym wypełnienia, niech ma wartość 0. Rozumiem, że próbki przygotowane z częstotliwością 8000 Hz.

    0
  • #19 04 Sty 2015 11:52
    Samuraj
    Poziom 35  

    Badmaneq napisał:
    Rozumiem, że próbki przygotowane z częstotliwością 8000 Hz.


    Tak, próbka jest 8000 Hz.
    Zmiana
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    spowodowała iż cykanie, ćwierkanie jest wolniejsze. Jeśli to kogoś nakieruje to przez czas trwania sampla słychać je 3 razy. Poprzednio było wielokrotnie więcej.

    0
  • #20 04 Sty 2015 12:24
    Badmaneq
    Poziom 23  

    Sądzę, że jak to określiłeś ćwierkanie spowodowane jest błędem w programie, ponieważ na LPC1114 na znacznie wolniejszym zegarze 48 MHz odgrywana muzyka i to ze znacznie wolniejszego medium czyli karty SD poprzez interfejs SPI brzmiała przyzwoicie.

    Sugeruj się tym kodem:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    1. Podstawa czasu obliczona i przyjęta w ten sposób: próbki 8 bitowe, więc max. wartość 255, skoro taktowanie ustawione na 48 MHz, to PWM ustawiony na częstotliwość 48 MHZ / 256 = 187,5 kHz.
    2. Ma zerować licznik kiedy zawartość licznika zrówna się z wartością wpisaną do rejestru MR3.
    3. Przerwanie od innego timera dla Twoich próbek, czyli wywoływane co 8 kHZ, ma wpisać wartość próbki do rejestru MR3.

    0
  • #21 04 Sty 2015 13:29
    94075
    Użytkownik usunął konto  
  • #22 04 Sty 2015 15:20
    Samuraj
    Poziom 35  

    Krytyka byłą słuszna i pouczająca. Nie sądziłem że da się na jednym timerze lecz to raczej wynika z przyzwyczajenia do poprzedniej wiedzy czerpanej głównie na mikrokontrolerach AVR. Da się zrobić na jednym i to bez piszczenia, przydźwięku czy cykaniu. Gra trochę cicho ale to wina filtra.

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Dodano po chwili ..
    Fanfary były przedwczesne :(
    Cicho grało bo zwróciłem uwagę iż jeśli częstotliwość generatora mam * 4 to wypełnienie też powinno być * 4. Tak też zmieniłem funkcję:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    I pisk powrócił :(
    Proszę mądrych o dalsze wskazówki co jw tym kodzie est nie tak.

    0
  • #23 04 Sty 2015 15:37
    tmf
    Moderator Mikrokontrolery Projektowanie

    IMHO to trochę małoeleganckie rozwiązanie. Puszczasz timer z 4-krotnie wyższą częstotliwością, przy czym ładujesz nową wartość PWM co 4 przerwania timera. Ale przerwania masz z częstotliwością PWM... A wszystko po to, żeby zaoszczędzić timer, którego i tak nie wykorzystujesz... A na koniec - to wszystko można zrobić automatycznie przy pomocy timera i DMA.

    0
  • #24 04 Sty 2015 15:44
    Samuraj
    Poziom 35  

    Wiem że można korzystając z DMA. Jeszcze łatwiej było by dać jakiegoś VS1004 albo np. WM8731 lub jak ktoś zauważył powyżej skorzystać ze sprzętowego DAC'a.
    Ale mam co ma i muszę z tego skorzystać. Co do użycia jednego timera zdecydujcie się :)

    0
  • #25 04 Sty 2015 16:23
    94075
    Użytkownik usunął konto  
  • #26 04 Sty 2015 18:26
    tmf
    Moderator Mikrokontrolery Projektowanie

    @albertb - oczywiście nie chodzi o to, żeby wykorzystywać coś niepotrzebnie. Ale zgłaszanie kilku tys. przerwań/s jeśli tylko co 4-te jest istotne jest IMHO bez sensu. Już lepiej wykorzystać drugi timer, który generuje przerwanie zgodnie z samplerate odtwarzanego pliku i ładuje nowe dane do PWM. Oczywiście można to zrobićna jednym timerze. Z tym, że zawsze lepiej jeśli częstotlwość PWM leży poza pasmem akustycznym, w sumie im dalej tym lepiej. A to z kolei uniemożliwa wykorzystanie jednego timera.
    Chyba, że jak piszesz zgłaszamy tych przerwań 4-razy tyle i robimy np. aproksymację liniową pomiędzy samplami.
    @Samuraj - nie rozumiem, przecież DMA masz na pokładzie? Więc dlaczego ne możesz z niego skorzystać?

    0
  • #27 04 Sty 2015 18:43
    Samuraj
    Poziom 35  

    Nie korzystam z DMA gdyż sądzę iż na obecnym etapie można ten sam efekt uzyskać bez jego pomocy.

    Zrobiłem mało elegancko w pętli karmiąc PWM;a - piszczało #7
    Zmieniałem częstotliwość PWM'a bez rezultatu.
    Puściłem na 2 timerach - pojawiły się ćwierki #17
    Zrobiłem na 1 timerze - piskało #22
    Teraz DMA a rozwiązania dalej nie ma. AVR nie ma DMA i jakoś na nich wszystko śmiga bez ćwierków i pisków w tle.

    0
  • #28 04 Sty 2015 18:59
    tmf
    Moderator Mikrokontrolery Projektowanie

    Jeśli ci piszczy to znaczy, że podstawowa częstotliwość PWM leży w paśmie akustycznym i tego pisku żaden filtr ci nie usunie. Jeśli częstotliwość przeniesiesz wyżej to piszczeć nic nie ma prawa, bo byś tego nie usłyszał. Ty masz chyba 9*4 kHz, więc pisku nie ma prawa być. Nie wiem co to są ćwierki, ale jeśli dźwięk jest zniekształcony to albo samplerate nagranej próbki nie jest taki jak samplerate przy odtwarzaniu, albo próbkę masz skompresowaną PCM ze znakiem, a do PWM potrzebujesz liczbę bez znaku i wymagana jest konwersja, albo próbka jest ładowana nie wtedy kiedy potrzeba, czyli kłopot z synchronizacją wpisu do rejestru PWM.

    0
  • #29 04 Sty 2015 19:08
    Samuraj
    Poziom 35  

    Jutro zrobię przewód i nagram to co słyszę. Jak widać w poście 22 częstotliwość PWM'a ustawiona jest na 32kHz.

    0
  • #30 04 Sty 2015 19:11
    94075
    Użytkownik usunął konto