Pliki WAVE

Zagadnienia związane z hardware i software
dawid
Raczkujący użytkownik 1
Raczkujący użytkownik 1
Posty: 9
Rejestracja: ndz 20 mar 2005, 17:37

Pliki WAVE

Postautor: dawid » pn 18 lip 2005, 22:55

Czy ktoś ma informacje na temat wartości amplitudy zapisanej muzyki w plikach wave. Chodzi mi o to że amplituda w plikach wave może mieć wartość do 1 volta, a nie wiem jak zapisywany jest sygnal a wartości większej nie 1 volt.

shg

Re: Pliki WAVE

Postautor: shg » pn 18 lip 2005, 23:24

dawid pisze:Chodzi mi o to że amplituda w plikach wave może mieć wartość do 1 volta

A nieprawda, skąd Ci się tam w ogóle wolty wzięły?
Amplituda zapisywana jest w postaci zwykłych liczb, a czy to będą wolty, ampery, czy prędkość ciągnika wyrażona w wiorstach na roboczogodzinę to już nikogo nie obchodzi.

Zapisane wartości mają różny zakres w zależności od zawartości takiego pliku i tak:
8 bit - od 0 do 255, dla sygnału audio poziomem odniesienia (0) jest wartość 128, wszystko poniżej jest ujemne, powyżej dodatnie.
16 bit - od 0 do 65535, poziom odniesienia - 32768.

to jakiemu napięciu odpowiada zapisana w pliku wartość zależy zarówno od urządzenia zapisującego, jak i odtwarzającego.
Możesz sobie zrobić tak, żeby przetwornik A/C zamieniał sygnały o wartości 1V na maksymalną wartość możliwą do zapisania w pliku tj. 255, czy 65535, dla napięcia 0V będzie odpowiednio 128 i 32768, a dla napięcia -1V będzie 1 i 1 (a nie zero, taki już urok liczb ze znakiem, że zazwyczj jest więcej ujemnych ;) )
A równie dobrze możesz zrobić tak, żeby maksymalnej zapisanej wartości odpowiadało napięcie 37534821V, wystarczy wstawić tylko tłumik (dzielnik) przed przetwornik A/C

To, co jest zapisane w WAVE, jest rzeczą względną i nie ma żadnej jednostki, określa tylko jaką część maksymalnego możliwego poziommu stanowi dana próbka.

A jak się jjuż tak uparłeś, to istnieje sposób na praktycznie bezstratne przekroczenie ograniczenia dla liczb całkowitych - doo zapisu wartości próbek z pliku stosuje się wtedy 32 bitowy format zmiennoprzecinkowy (IEEE, a numerka nie pamiętam, ale jest tylko jeden ;) ), zwany float, czy też single. Pozwala on na zapis wartości z dynamiką ok 760dB, co znacznie wykracza poza możliwości jakiegokolwiek sprzętu pomiarowego, czy grającego (typowy cholernie trudny do przeskoczenia próg to 140dB)

Pliki wave z danymi zmiennoprzecinkowymi zapisuje się w postaci znormalizowanej, tak źe maksymalna amplituda wynosi 1.0 (nie wolt, po prostu jeden). Oczywiście nic nie stoi na przeszkodzie, żeby zapisać tam wartości wyższe od 1.0, tylko, że aby oodtworzeć taki nieznormalizowany plik trzeba będzie najpierw wykonać jego normalizację (podzielić wszystkie próbki przez najwyższą występującą w pliku wartość)

PI

wave

Postautor: PI » wt 19 lip 2005, 0:02

Witam; piękny wykład. Podejrzewam jednak, ze może chodzić o cos innego (swoja drogą, czy ktos widział pliki analogowe i to w PC-cie???); ale... wejście analogowe (np. karty dzwiękowej) może być opisane tak - amplituda sygnału wejściowego nie może przekraczać 1V. I tu mogła powstac wątpliwość, co zrobić z większymi amplitudami??? Jeżeli tak, to po prostu nie nalezy do nich dopuścić - w źródle sygnału, który doprowadzamy do naszej "czarnej skrzynki"powinniśmy mieć jakiś wskaźnik wartości np. szczytowej i to by załatwiło sprawę - tak jak to jest w przeróżnych urzadzeniach wzmacniających, mikserskich itd, z których sygnał przesyłany jest do np. urzadzeń rejestrujących. Tam z góry ustala się największy dopuszczalny poziom sygnału (zazwyczaj z pewna rezerwą), aby nie przesterować urzadzenia końcowego. O wszelkiego rodzaju układach kompresji analogowej nie wspominam, bo tego wyjątkowo nie lubię ( nie lubię działania tych układów!!!).
Z róznymi wyrazami - PI

dawid
Raczkujący użytkownik 1
Raczkujący użytkownik 1
Posty: 9
Rejestracja: ndz 20 mar 2005, 17:37

pliki wave

Postautor: dawid » śr 20 lip 2005, 23:10

Dzienki za te odpowiedzi, troche mi ot rozjasnilo problem.
Co do jednostki volt. to poprostu mam programik co mi pokazuje amplitude pliku wave jako volty i tylko dlatego tak naisalem.

A co do normalizacji tych plikow to mi to troche nie wychodzi, bo jak podziele przez najwieksza mozliwa wartosc w pliku to zostaje bardzo mala wartosc. Jak ktos wie cos wiecec o normalizacji plikow wave to będę bardzo wdzieczny jak sie podzieli zemną tą wiedzą

PI

WAVE

Postautor: PI » śr 20 lip 2005, 23:37

Witam; mam wrażenie, że jednak potrzebny jest bardziej merytoryczny opis problemu, na razie bowiem obracamy sie w kręgu pewnych domniemań co do jego istoty. Czy chodzi o teoretyczne podstawy przetwarzania A/C, czy też mamy konkretne urzadzenie lub system i problem dotyczy parametrów sygnałów we/wy na poziomie analogowym.
Wielokrotnie spotykałem się tu i nie tylko z próbami przedstawiania problemów technicznych przy uzyciu pewnych dziwnych skrótów myslowych lub wręcz jakiegoś psudotechnicznego żargonu. Namawiam gorąco do rzeczowego i dokładnego opisu sprawy, bo to ułatwia odpwiedź i jak się domyślam, pozwala zaangazować się ludziom o ściśle okreslonej wiedzy.
PI

shg

Re: pliki wave

Postautor: shg » czw 21 lip 2005, 9:35

dawid pisze:A co do normalizacji tych plikow to mi to troche nie wychodzi, bo jak podziele przez najwieksza mozliwa wartosc w pliku to zostaje bardzo mala wartosc. Jak ktos wie cos wiecec o normalizacji plikow wave to będę bardzo wdzieczny jak sie podzieli zemną tą wiedzą


A no to zależy, co masz w pliku, bo ta normalizacja którą opisałem dotyczy WYŁĄCZNIE plików .wav z danymi zapisanymi jako float.
Jeżeli chcesz znormalizować plik powiedzmy szesnastobitowy, to trzeba go normalizować nie do 1.0, a do 32767 (2^16/2-1), bo taka jest największa wartość jaką możesz mieć zapisaną (dla 8 bitów będzie to 127).
I tu drogi są dwie, można to zrobić bardziej, lub mniej wydajnie, zależy od tego, jaki zakres danych chcesz znormalizować.
Bardziej wydajnie, ale trudniej:
Jeżeli chcesz znormalizować wartości nieprzekraczające zakresu (no Ty akurat nie chcesz ;) ), to wystarczy pomnożyć wszystkie próbki przez 32767, a potem podzielić przez maksymalną wartość. Koniecznie w tej kolejności, operację wykonujemy na jakimś 32-bitowym typie danych (zazwyczaj int, ale trzeba sprawdzić)
Jeżeli wartości są większe od przetwarzanego zakresy, to trzeba użyć arytmetyki np. 64-bitowej.
Mniej wydajnie, ale za to dużo prościej i uniwersalnie:
Wykonać wszystkie operacje jako zmiennoprzecinkowe.
Czyli szukamy największej wartości (max), potem liczymy 32767.0/max i przez tak otrzymaną wartość mnożymy każdą z próbek
Przykład w C:

Kod: Zaznacz cały

int probki[N]; /* tablica N próbek, jest int, ale to nie ważne ;) */
int max; /* maksymalna wartość znaleziona w próbkach */
float t; /* a przez to będziemy mnożyć */
int i; /* a to tylko taki indeks */

max = 0;
/* szukamy maksymalnej wartości */
for(i = 0; i<N; i++) {
  if (abs(probki[i]) > max) /* ma być wartość bezwzględna, bo ważne są oba limity, górny i dolny */
    max = abs(probki[i]);
}

/* teraz w max mamy największą wartość, albo 0, jeżeli wszystkie próbki były zerami */

if (max > 0) { /* jak max będzie zero, to nie ma co liczyć bo się wykrzaczy */
  t = 32767.0 / ((float) max); /* przez to będziemy mnożyć. zamiast 32767.0 możesz wstawić inną wartość, wtedy do niej będziesz normalizował */
/* i wszystkie próbki po kolei, operacje wykonujemy jako zmiennoprzecinkową (float), a wynik całkowity (int) */
  for(i = 0; i<N; i++)
    probki[i] = (int) (t * (float) probki[i]); /* a mnożenie jest dla tego, że jest szybsze od dzielenia */
}

dawid
Raczkujący użytkownik 1
Raczkujący użytkownik 1
Posty: 9
Rejestracja: ndz 20 mar 2005, 17:37

pliki wave

Postautor: dawid » czw 21 lip 2005, 22:59

Witam
Postaram się wyjasśnić dokladnie co mam zrobić

Mam napisać aplikację która składa się z trzech części
Pierwsza część to zgrywanie z gramofonu muzyki do pliku wave, to mi już dziala
Druga częśćto mam napisać programik który bedzie generatorem fali sinusoidalnej, prostokątnej i trojkatnej i ktory bedzie zapisywal tą wygenerowaną fale do pliku wave, to mi prawie dziala ,tylko tu mam problem taki ze nei wiem w jakich jednostkach podawać amplityde tej fali bo mam podobny programik co mi podaje amplitude w voltach (do 1 volt)a wy mi puszecie ze trza w dB, a to jest roznica bo jak bede podawal tak jak mi podeje moj przykladowy programik to poprostu wstawiam se wartosci od 0.001 do 1 z krokiem co 0.001 i mi to fale wmiare dobrze gerneruje, a jezeli to mam miec w decybelach to chyba trza zastosowac jakis wzor z logarytmem .
trzecia część jest najtrodniejsza bo mam sprawdzac czy w moim pliku zgranym z gramofonu znajduje sie fala wygenerowana w moim geberatorze fali. Mam porrównywaćte dwa pliki vav przy pomocy korelacji
i tu mam najwiekszy problem bo po takim porownaniu zostaja mi bardzo duze wartosci. wszystkie te porownania robie na float. a jezeli chce to wpisac ponownie do wave np. 8 bitowego to mi wpisuje jakies smieci bo. i tak samo jest na 16 bitach. Wiec pomyslalem ze moze trza zrobic normalizacje przed zapisem do tego pliku , bo jak to co mi wyszlo podzielilem sobie przez jakas liczbe ( i tu wstawiale sobie na chybil trafil bo nie wiedzialem jak sie taka normalizacje robi) to po wpisaniu do wave nie byly juz smieci tylko bylo slychac muzyke. A nie moge sobie wsawiac takich liczb an chybil trafil bo przy roznych rodzajach fali wychodza iine wyniki i co dla jednego dziala to dla drugiego sa smieci. Ale teraz sprobuje wstawić ten kod co dostalem to moze zadziala. A i te aplikacje pisze przy wykozystaniu DirectX(troche mu zmienilem bliblioteki ) I Visuala C++
Mam nadzieje ze wmiare wyjasnilem problem i oczywiscie wielkie dizenki za pomoc

dawid
Raczkujący użytkownik 1
Raczkujący użytkownik 1
Posty: 9
Rejestracja: ndz 20 mar 2005, 17:37

pliki wave

Postautor: dawid » czw 21 lip 2005, 23:15

jeszcze do wczesniejszej mojej wypowiedzi to Sory, nikt mi tu nie pisze ze amplitude w decybelach trzeba podawac, moje przejezycznie. poprostu napisalem tez do jakiejs firmy co sie zajmuja odszumianiem muzyki ( ta korelacja co ja robie to coś wlasnie w stylu odszumiania bo sobie moge usuwac rozne czestotliwosci z pliku) i tam mi napisali ze karty muzyczne maja dwa standardy zgrywania i te standardy sa w decybelach. a moj generatorek ma tak samo dzialac jakbym zgrywal te fale sinusoidalne z zewnatrz (np. z jakiegos zewnetrznego generatora) no i pasuje zeby jednostki sie zgadzaly

shg

Postautor: shg » pt 22 lip 2005, 0:59

No to jak masz sinusa do wava "zrzucić" to nie problem.

Przyjmijmy już ten Twój 1V jako maksimum, tzn. 1V będzie odpowiadała wartość typu float = 1.0

No ale w typowym .wav mamyy liczby całkowite z zakresu -128 do 127 (8 bit), albo -32768 do 32767 (16 bit). Napisałem, że wartości, są zarówno ujemne, jak i dodatnie, co nie jest do końca prawdą, w programie najczęściej w trakcie odczytu (albo zapisu) przeprowadza się konwersję, tak że program operuje na wartościach ze znakiem, bo łatwiej. W pliku zaś te wartości zapisane są jako liczby naturalne (bez znaku). Ale żeby nie stracić informacji o ujemnych wartościach cały sygnał przesuwany jest "w górę", tak, że najmniejsza możliwa wartość (ujemna) staje się zerem.
A więc dla ośmiu bitów mamy tak, że wartość -128 (minimum) zostaje zapisana w pliku jako 0, 0 zostanie zapisane jako 128, a 127 (maksimum) zostanie zapisane jako 255.
Żeby to osiągnąć, do każdej próbki należy dodać 128 (dla 8 bitów), lub 32768 (dla 16 bitów)

Sprawa numeros dos, to skalowanie.
Jak już napisałeś, chcesz, żeby amplituda wynosiła 1V, a więc Twój sygnał będzie się zmieniał w zakresie -1.0 do 1.0. Gdybyś takie wartości zapisał bezpośrednio do pliku, to dostaniesz bardzo cichy dźwięk z odstępem sygnał - szum równym 3dB. (niecałe 2 bity, a to i tak zależy od tego w jaki sposób dokonasz konwersji z typu zmiennoprzecinkowego na całkowity, bo może się okazać, że przez cały czas będziesz miał zero i tylko pojedyncze +/-1 tam gdzie wartość sinusa wynosi +/-1.0)
Więc trzeba ten sygnał przeskalować, po tej operacji amplituda sygnału będzie zajmowała cały dostępny przedział, czyli od -32768 do 32767 dla 16 bitów.
A jak? banalnie! wystarczy pomnożyć. :)

Gotowy generator (koncept):

Kod: Zaznacz cały

#include <math.h>

#define CZAS 1.0 /* czas w sekundach, czyli długość sampla */
#define FS 44100 /* częstotliwość próbkowania w Hz */
#define N ((int) (CZAS * FS)) /* ilość próbek */
#define FG 1000.0 /* częstotliwość Twojego "generatora" w Hz */
#define PI 3.141593 /* stosunek obwodu okręgu do jego średnicy :P */
#define PI2 (PI+PI) /* mówi samo za siebie */
#define SKALA 32767.0 /* maksymalna wartość (bezwzględna) jaka się znajdzie w tablicy */
/* Dane w tablicy będą miały zakres od -SKALA do +SKALA */
/* minimalna wartość (-32768) nigdy nie wystąpi, po takie przeskalowanie albo spowoduje asymetrię, albo doda składową stałą */
/* dla n bitów SKALA = 2 ^ (n - 1) - 1 */
#define ZERO 32768 /* poziom przesynięcia zera w pliku .wav */
/* dla n bitów ZERO = 2 ^ (n - 1) */

unsigned short sample[N]; /* tablica próbek, wartało by dynamiczną alokację zastosować */
/* chyba ten typ, na amidze na pewno to jest UWORD ma być 16 bit bez znaku*/

int main(void) {
int index; /* indeks w tablicy próbek */
float domega; /* przyrost fazy */
float omega = 0.0; /* aktualna wartość kąta */

/* no i to by było na tyle deklaracji */
/* teraz trzeba by przeliczyć, o ile będzie się zwiększał kąt (faza) dla każdej próbki w radianach ofkozz */
  domega = PI2 * FG / ((float) FS);

  for(index = 0; index<N; index++) {

/* liczymy sinusa, wynik mnożymy przez skalę i z zakresu -1.0 do +1.0 robi się -SKALA do +SKALA */
/* Potem dodajemy ZERO, czyli przesuwany sygnał tak, że wszystkie wartości są dodatnie) */

    sample[index] = (unsigned short) (sin(omega)*SKALA) + ZERO;

/* po każdej próbce zwiększamy wartość kąta */

    omega += domega;

/* poniższa operacja to korekcja kąta bardzo ważna dla dłuższych próbek, bo funkcje trygonometryczne tracą dokładność wraz ze wzrostem wartości argumentu, więc trzymamy go zawsze w zakresie 0.0-2*PI */
/* taka metoda i tak wprowadza błąd narastający z czasem. Właściwe było by zastosowanie np. akumulatora fazy ale jest to już trochę bardziej skomplikowane jeżeli chce się uzyskać dużą dokładność i dowolność wyboru częstotliwości */
/* to co jest tutaj w zupełności do Twoich zastosowań wystarczy */

    while(omega > PI2) {
      omega -= PI2;
    }
  }
 /* No i koniec :) w tablicy sample[] mamy wartości gotowe do zapisu do pliku */

  return 0;
}

A co do korelacji - to faktycznie duże wartości będą wychodzić, ale float powinien to wytrzymać. ;)
I pytanie, czy korelację liczysz na wartościach pobranych bezpośrednio z pliku, czy przeskalowujesz je na inny zakres?

dawid
Raczkujący użytkownik 1
Raczkujący użytkownik 1
Posty: 9
Rejestracja: ndz 20 mar 2005, 17:37

pliki wave

Postautor: dawid » pn 25 lip 2005, 15:08

shg napisal
I pytanie, czy korelację liczysz na wartościach pobranych bezpośrednio z pliku, czy przeskalowujesz je na inny zakres?



Tak wiec korelacje liczę na wartosciach pobranych bezpośrednio z pliku, a problem jest potem z wpisaniem tego spworotem, dlatego że float wytrzymuje wszystkie obliczenia zwiazane z korelacja, ale musze potem wpisac to spowrotem np. na 8 bitow jezeli plik wave bedzie mial 8 blitow na próbkę. I tu właśnie nie wiem co z tym zrobić bo jak napisalem wczesniej jak będą zaduże wartości to przy konwersji z float na 8 bitow to mi obcina dane i zostaja smieci.


Wróć do „Komputery, oprogramowanie i internet”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika. i 27 gości