lazarus i bass.dll - rysowanie wykresu waveform

lazarus i bass.dll - rysowanie wykresu waveform
Z1
  • Rejestracja:ponad 11 lat
  • Ostatnio:około 6 lat
  • Postów:4
0

Witam.

Napisałem w Lazarusie w oparciu o bass.dll prosty odtwarzacz plików wav.
W trakcie odgrywania plików odtwarzacz realizuje bieżące wizualizacje FFT lub waveform.
Wszystko działa tak jak trzeba ale ...
teraz chciałbym dodatkowo po "otwarciu" wav

Kopiuj
channel := BASS_StreamCreateFile(False, filename, 0, 0, 0 {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF});

narysować jego kompletny wykres waveform.

Próbuję, w pętli for, pobierać z wav paczki danych korzystając z funkcji

Kopiuj
BASS_ChannelSetPosition(channel, pozycja, BASS_POS_BYTE);
BASS_ChannelGetData(channel, @WaveData, 2048);

i niestety w zmiennej WaveData ciągle mam te same stałe ale "przypadkowe" wartości.

Natomiast jeśli dam

Kopiuj
BASS_ChannelPlay(channel, true);

i "ręcznie" pobieram z wav bieżące dane przez

Kopiuj
BASS_ChannelGetData(channel, @WaveData, 2048);

to wszystko mi działa ok.

Wydumałem więc, że bass.dll nie udostępnia tych danych jeśli wav nie jest odgrywany.
Czyżby tak było ?
czy też źle się do tego zabrałem.

Proszę o wskazówki i wyrozumiałość,
jestem programistą amatorem :)

dodanie znaczników <code class="delphi"> - fp

edytowany 1x, ostatnio: flowCRANE
olesio
  • Rejestracja:około 17 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Szczecin
  • Postów:4191
0

Nigdy tak z bassem nie musiałem kombinować. Ale jeśli nie ma przykładu w examples na rysowanie waveform. Ponieważ na inne bajery jak wykresy przy odtwarzaniu od dawna był przykład w WinAPI. To ja bym pokombinował raczej tak jak wedlug opisu na: http://www.un4seen.com/doc/#bass/BASS_ChannelGetData.html - bo Ty przekazujesz rozmiar luzem podają jakąś wielkość. A tutaj raczej trzeba operować na wymienionych na powyższej stronie stałych. Z których jak widzę z pliku nagłówkowego do bass, żadna nie ma wartości 2048 raczej. Być może stąd te przypadkowe dane.

Nie widzę też żadnego wspomnienia, że można pobierać te dane tylko przy odtwarzaniu. Jeżeli uzyskane Handle jest prawidłowe to myślę, że to powinno się udac. Jednak, w bass.dll nie jestem ekspertem i nigdy nie pisałem z użyciem tej dllki aż tak zaawasnowanych rzeczy, bo zwykle interesowało mnie tylko odtworzenie plików, ewentualnie ładowanie bass.dll z zasobów exeka, a ostatnio proste wyświetlenie danych o module muzycznym. Także ktoś może coś jeszcze Tobie lepszego i konkretniejszego tutaj doradzi.

EDIT: a nie przepraszam, jednak można podać konkretną ilośc bajtów. Teraz doczytałem. Ale spróbuj jeszcze ze stałymi może. Ja póki co nic lepszego nie wymyślę.


Pozdrawiam.
edytowany 3x, ostatnio: olesio
Z1
  • Rejestracja:ponad 11 lat
  • Ostatnio:około 6 lat
  • Postów:4
0

Witam ponownie.

Oczywiście okazało się, że da się pobrać te dane.
Otworzyłem dodatkowo plik tylko do pobrania danych

Kopiuj
chanwav := BASS_StreamCreateFile(False, f, 0, 0, BASS_STREAM_DECODE {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF});

Istotna jest flaga BASS_STREAM_DECODE.

Potem już funkcje pozycjonowania i pobierania

Kopiuj
BASS_ChannelSetPosition(chanwav, pozycja, BASS_POS_BYTE);
BASS_ChannelGetData(chanwav, @WaveData, 2048);

działają tak jak należy.

Teraz mam kolejne pytanie,
jak uśrednić dane z kilku/kilkudziesięciu tysięcy pobranych bajtów przypadające na 1 piksel wykresu (oś X) aby wyglądało to tak jak na wykresach waveform ?
Próbowałem wyliczać średnią, wyznaczać maksimum, ale efekt jest marny :(
Jakaś funkcja matematyczna ?

olesio
  • Rejestracja:około 17 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Szczecin
  • Postów:4191
0

Niestety nie umiem Ci pomóc w tym. Z matmy byłem, jestem i zawsze będę totalny lama/noga/baran. Już się z tym pogodziłem. Jedyne co mogę doradzić to przeanalizowanie sobie przykładów w podkatalogach SampleVis oraz spectrum w paczce z bass.dll, dokumentacją i przykładami w kilku językach.


Pozdrawiam.
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 12 godzin
1

jak uśrednić dane z kilku/kilkudziesięciu tysięcy pobranych bajtów przypadające na 1 piksel wykresu (oś X) aby wyglądało to tak jak na wykresach waveform ?
Weź wartość maksymalną i minimalną z danego odcinka, i narysuj krechę pionową od min do max.
Pamiętaj, że sample są ze znakiem, więc zero masz po środku.

edytowany 1x, ostatnio: Azarien
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 13 godzin
  • Lokalizacja:Tuchów
  • Postów:12171
0

Lub obliczaj na zmianę min i max i rysuj co krok krechę od poprzedniej do nowej wartości.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
Z1
  • Rejestracja:ponad 11 lat
  • Ostatnio:około 6 lat
  • Postów:4
0

Znalazłem dwie metody kalkulacji, może się to komuś przyda.

Pierwsza RMS.

Kopiuj
float RMS = 0;
for (int a = 0; a < BlockSize; a++)
{
   RMS += samples[a] * samples[s]; 
}
RMS = sqrt(RMS / BlockSize);

Druga Min/Max.

Kopiuj
float Max = - 1000000;
float Min = 1000000;
for (int a = 0; a < BlockSize; a++)
{
   if (samples[a] > Max) Max = samples[a];
   if (samples[a] < Min) Min = samples[a];
}

Pierwszą już wypróbowałem, efekt jest taki sobie.
Zabieram się za drugą :)

flowCRANE
W tej pierwszej metodzie brakuje deklaracji zmiennej/parametru s, więc w sumie połowę wiadomo; Chyba że to literówka i miało być a zamiast s, ale to byłby zwykły kwadrat - nic skomplikowanego :P
flowCRANE
Druga zaś to zwykły min-max, o którym wspominał @Azarien i powinna dawać dobre wyniki;

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.