Ynt: stm32 microcontroller ve wav file

Başlatan Karamel, 15 Ağustos 2015, 01:49:39

t2

#30
Sesi 8 bit kaydedip, cooledit goldwave gibi program ile 16 bite çevirip dinlersek pek fark duymayız

Örnekleme hızını 2 kata çıkarıp çözünürlüğü yarıya indirmek  algılanan kaliteyi  nasıl etkiler?
Galiba sesteki frekans bileşenlerine bağlıdır.

Telefon kalitesindeki sesi  yüksek çözünürlükte veya yüksek hızda örneklemek pek fark oluşturmayacağı için farketmiyormuş gerek yokmuş denebilir. Müzik sesi hatta bazı  enstürmanların sesi için durum farklı olur

Karamel

#31
Alıntı yapılan: Gökhan BEKEN - 15 Ağustos 2015, 21:56:24
Bir sorum var: x hz 16bit ses ile x*2 hz , 8 bit ses arasında kalite farkı var mıdır? Varsa hangisi daha kalitelidir?
Bunu dac'ın çözünürlük sıkıntısı için sordum, gerçi frekans artarsa işlemci daha fazla meşgul olacak ama merak ettim yinede.

hocam bu duruma gore degisiyor. yani goreceli. einstein in relativity theorysi gibi :P

mesaj birleştirme:: 16 Ağustos 2015, 01:32:26

hocam kaliteden kasit olarak neyi anladigimiza bagli bu durum.

OG hocamin paylastigi resimleri incelerseniz. frequence in fazla olmasinin detaylari iyi yakamalamaya yaradigini farkediyoruz. mesela 6000 hz olani bin celeyin ve aklinizda her noktanin uclarini birlestirin. sonuc karemsi birsey olacaktir. frequance arttikca signal gercek bir sinus signaline benzemis. yani frequence imiz arttikca x axies teki kalitemiz artiyor.

peki bit artince neler oluyor?

bu seferde 0-3.3 voltage arasini 256 adimda değilde 65536 adimda geziyoruz. buda y axis teki kalitemizi arttiriyor.



benim deneylerime gore. bit arttikca dip gurultusu azaldi. cunku soyle dusunelim. bir bitlik gurultu babinda degisim var. 0x80 ile 0x81 arasi 3.3/256 kadar. bu amplicator icin yuksek bir deger. kulagimiz bu degisimi hissediyor.

ama 16 bit olunca durum. 3.3/65536 kadar oluyor. buda digerinden 256 kat daha dusuk bir dip sesi demek.

frequance artincada sesin ayrintilari artiyor. mesela wav file imiz speech icersin. frequance dusukken adamin dediklerini iyi anlayamiyoruz. freance artincada OG hocamin resimlerinden faydalanarak bunu anlayabilirsiniz ki. ayrintilar cok belirgin oluveriyor.




mesaj birleştirme:: 16 Ağustos 2015, 01:50:43

suan ulasabildigim son nokta yi hocalarimla paylasmak istedim.

suan wav file i mukemmel bir sekilde okuyoruz caliyoruzda. ses bir sart saglanirsa mukemmel. o sart nedir bunu resimler uzerinden aciklamaliyim.



resimde bir music file var. uzantisinin ne oldugu bizi ilgilendirmiyor. hepsinin ic yapisi bu sekilde. originden yukariya yada asagiya dogru surekli hareket ediyor. originden usaklasmasi sesin volume unu belirliyor. mesela resimde uc noktalari sivri olan kisimlarda volume yuksek. mesela birisi orada microphone a parmagiyla pit pit diye vurmus olabilir. orta kisimlarda ses normal.

simdi ben Gokhan hocamdan dingdong kapi zili wav file ini convert etmesini istemistim. hocamin ilk konvert ettigi file sanirim kendi sesi idi. pc microphone u gibi birsey ile kaydedilmis. bu tarz kayitlar ile calisirsak. hata olsa bile hatayi anlamayabilirdik. cunku kayit. music gibi değil. bende hem kisa olsun. hemde hatamiz olunca bunu sesin farkliligindan anlayalim diye dingdong u hocama onerdim.

neyse. simdi bizim wav file imiz normal. yani yukaridaki gibi. ani ziplamalarimiz yok. pc de acinca bu peak lerin olmadigini anlayabiliyorum. peki peak lar olursa ne olur? ses oralarda cat pat diye patlar. yani oralarda bozulur.

simdi biz belli seviyeye kadar sesi peak yaptirmadan dac unit e atabiliyoruz. ama belirli bir seviyeden sonra dac tan 12 bitten daha fazla value degerinde bilgi cikmaya calisiyor. tabiki cikamiyorda. biz onu cat pat diye duyuyoruz.


resimin orta kismindaki normal yukselmelere bakalim. bizim file imiz resimdeki file in orta kismina benziyor. yani peak yok. ama biz normal olan bu sesi dac a duzgun aktaramadigimizdan peak ler olusuyor. peki buna sebep olan sey nedir?

biz 16 bit lik signed file i unsigned hale cevirip. duzgunce bunu 16 ya bolup 12 bitlik file elde edemiyoruz. dingdoonnnnnn kisminda volume yuksek oldugundan cizirtilari duyuyoruz. nggggggggg kisminda ve sonunda cizirti yok. pc de nasilsa speaker lardan da aynisi cikiyor. yani wav file in basinda cizirtilar duyuyoruz. ortasi ve sonunda duymuyoruz.

      while(1)
      {
          Ses_Cal = 0;
          Ses_Cal =  Wav[value + 1] + 128;
          Ses_Cal = Ses_Cal << 8;

          Ses_Cal = (Ses_Cal + Wav[value] + 128);

          
          Ses_Cal = (Ses_Cal) / 16;
          
          Line1 = Ses_Cal;
          
          Ses_Cal =  Wav[value + 3];
          Ses_Cal = Ses_Cal << 8;

          Ses_Cal = Ses_Cal + Wav[value + 2];

          Ses_Cal = (Ses_Cal+32767) / 16;
          
          Line2 = Ses_Cal;
          
          DAC1_Advanced_Ch1_Output(Line1, conf1);
          DAC1_Advanced_Ch2_Output(Line2, conf2);
          
          value++; value++; value++;  value++;  //

          Delay_us(19);
      }


16 ya değil. 32 ye boldum yine olmadi. 32767-32768-32769 denedim olmadi. zaten olmamasi normal. 32768 olmasi gerekir. 32767 yasarsam alttan - 1 olur. 32769 yarsamda ustten 65536 olur. bizim 65535 olmasi gerekli. yine bunlar peak a neden olur. signed. unsigned converting ini beceremedim. bu saatten sonra unsgined olarak decode edilmis bir wav file i tertemiz calabiliriz ama bizim isimiz deney yapmak oldugundan bu sorundan birseyler ogrenmeliyiz. simdi ben ogrenmek istiyorum. signed degiskeni unsigned haline bozmadan nasil ceviririm?

Karamel

#32
tamam. tezim dogruymus. biz suan icin. signed value yu unsigned form a duzgunce donusturemiyoruz. sesi 8 kat kistim. suan hic peak almadan calabiliyorum. quality excellent!  :P

simdi bir hocamin bana signed formdan neden unsigned form a duzgunce gecemedigimizi anlatmasini bekliyorum.

sorun burada:

          Ses_Cal = 0;
          Ses_Cal =  Wav[value + 1] + 128;
          Ses_Cal = Ses_Cal << 8;

          Ses_Cal = (Ses_Cal + Wav[value] + 128);

          
          Ses_Cal = (Ses_Cal) / 16;
          
          Line1 = Ses_Cal;




mesaj birleştirme:: 16 Ağustos 2015, 04:10:08

degiskenlerimizde boyle
unsigned long value;
unsigned long conf1;
unsigned long conf2;

unsigned int Ses_Cal = 0;


mesaj birleştirme:: 16 Ağustos 2015, 04:10:39

wav degiskenimizde boyle:

const unsigned char Wav[352846]={.........

OG

1KHz 1 alternans 16 bit bir ton ürettim (cooledit ile).


6000_16

Wav olarak kaydettim.
Wav dosyayı incelemek için Hex Workshop ile açtım.


Hex Workshop

Datayı export edip açıklamalar ekledim.

'' İlk 44 Byte header
52 49 46 46 32 00 00 00 57 41 56 
45 66 6D 74 20 10 00 00 00 01 00 
01 00 70 17 00 00 E0 2E 00 00 02 
00 10 00 64 61 74 61 0E 00 00 00

'' Örneklenen datalar (16 bit, signed, little endian) 
01 00  (          1) => 1. nokta 
B0 4C ( 19632) => 2. nokta 
B0 4C ( 19632) => 3. nokta  
00 00  (          0) => 4. nokta 
50 B3  (-19632) => 5. nokta 
51 B3  (-19631) => 6. nokta 
00 00   (          0) => 7. nokta         



Üretilen data signed, little endian olarak işlenmiş. Data üretirken, işlerken herhalde bunlara dikkat gerekir. t2' nin dediği DAC yapılanması konusunda da bu şartlara uyulmalı.

Bahsi gecen dosyalar ektedir.

FORUMU İLGİLENDİREN KONULARA ÖM İLE CEVAP VERİLMEZ.

Karamel

#34
hocam merhaba.

windows calculator u programmer moduna aldim.

4CB0 hex icin. 19632 ondalik sayi sina denk geliyor?

B350 hex icin. 45904 ondalik sayisina denk geliyor? burada bir yanlislik var.bu sayi icin - 19632 demissiniz? bunu nasil buluyoruz? sorun bu kisimda.


mesaj birleştirme:: 17 Ağustos 2015, 17:53:55

ben deneyi bir kac gun once yaptiydim.

minus ve positive value lari 8 kat kuculttum. o cizirti gitti. sorun signed value yu unsigned forma duzgunce cevirememek. bunu yanlis degisken tanimlamasi ilede yapiyor olabilirim. yada mesela char a yi unsiged char b ye unsigned halde gondereceksek.


b = a + 127; seklinde bir cozum. dogru olmuyor.

t2

#35
8'e bölmeye gerek yok. yanlış işlem.
8 kat kuculttme ile sorun çözülmüş gibi görünse de yanlış olmuş. Yanlışı yanlış ile düzeltmeye çalışmaktır.

işin doğrusu şu:

wav dosyadan okunan baytlar yer değişecek ! Sağ ile  sol
OG arkadaşın bildirdiği şekilde,
Wav dosyadaki  B0 4C (=19632) => 2. nokta  bu bilgi doğrudur.

Ancak hex calculatore  B0 4C yazarsak decimal olarak  19632 olmaz. 
4CB0  yazmak gerek.  4CB0  = 19632
Demek ki wav dosyadan 2 bayt okuyacağız. fakat  2bayt yer değişecek!

Sonra bu 2baytlık, signed integer datasına 32768 bias eklenecek, böylece wav data, kesin  pozitif olacak. (0..65535 arası )
Sonra 4 bit sağa kaydıracağız (yani /16) böylece data pozitif ve 12 bit olacak. daha sonra DACa uygulanacak.


Gökhan BEKEN

signed verilerin ilk biti zaten işaret oluyor. İlk bit 1 ise negatif, 0 ise pozitif.
Yalnız diğer bitler de terslenmiş oluyor, 0 olanları 1 gibi, 1 olanları 0 gibi düşünerek hesaplayıp, sonra en soldaki bitin durumuna göre negatif veya pozitif diyeceksin.
örneğin:
char sayi=0x80; // yani 0b10000000 => -128
char sayi=0xC0; // yani 0b11000000 => -64
char sayi=0xE0; // yani 0b11100000 => -32
char sayi=0xF0; // yani 0b11110000 => -16
char sayi=0xFF; // yani 0b11111111 => -1
char sayi=0x00; // yani 0b00000000 => 0


denemek için, hesap makinesinin programcı modundaki ayarlardan sayı türünü byte seç
Özel mesaj okumuyorum, lütfen göndermeyin.

LukeSkywalker

#37
t2 işi bitirmiş. Aynılarını yazıyordum sonradan mesajı gördüm.
value değişkenini signed olarak tanımla.

Karamel

#38
Alıntı yapılan: t2 - 17 Ağustos 2015, 18:09:39
8'e bölmeye gerek yok. yanlış işlem.
8 kat kuculttme ile sorun çözülmüş gibi görünse de yanlış olmuş. Yanlışı yanlış ile düzeltmeye çalışmaktır.

işin doğrusu şu:

wav dosyadan okunan baytlar yer değişecek ! Sağ ile  sol
OG arkadaşın bildirdiği şekilde,
Wav dosyadaki  B0 4C (=19632) => 2. nokta  bu bilgi doğrudur.

Ancak hex calculatore  B0 4C yazarsak decimal olarak  19632 olmaz. 
4CB0  yazmak gerek.  4CB0  = 19632
Demek ki wav dosyadan 2 bayt okuyacağız. fakat  2bayt yer değişecek!

Sonra bu 2baytlık, signed integer datasına 32768 bias eklenecek, böylecek wav data, kesin  pozitif olacak. (0..65535 arası )
Sonra 4 bit sağa kaydıracağız (yani /16) böylece data pozitif ve 12 bit olacak. daha sonra DACa uygulanacak.

iyide hocam ayni seyleri dene dene duruyorum.

yukarida anlattiklarinizinda deneyini yaptim. isler bir yerde karisiyor. bunu oscilloscope um ile yada debug ile goremeyince. labirete birakilmis fare gibi. surekli ayni yerlerde dolasip duruyorum.
          int Ses_Cal;

          Ses_Cal = 0;
          Ses_Cal =  Wav[value + 1];

          Ses_Cal = Ses_Cal << 8;

          Ses_Cal = (Ses_Cal + Wav[value]);
          
          Ses_Cal = Ses_Cal + 32768;
          
          Ses_Cal = (Ses_Cal) / 16;
          
          Line1 = Ses_Cal;



benim bu code larim ne yapiyor?

44 + 1 inci byte i okuyor. (msb) ve ses cal degiskenimizin icine yerlestiriyor.

daha sonra bunu 8 kere sola kaydiriyor. ve 44 uncu byte ile topluyor.

ses cal a 32768 i ekliyor.

bunu 12 bit e donusturmesi icin. 16 ya boluyor.

Line1 degiskeni digital analog converter in degiskeni.

DAC1_Advanced_Ch1_Output(Line1, conf1);


buda degerimizi analog olarak output ediyor.


yani sizin soyledikleriniz ile olanlar ayni ama. olmuyor iste. sesi 8 kat kisma nedenim. deney yapmakti. 8 kat kisinca oluyor tamam bu is bitti seklide bir deney değildi. 8 kat kisinca neden hersey normal mis gibi oluyor? cunku signed value belli degerleri(mesela atiyorum 10000 den yukarisi veya - 10000 den asagisi) asinca. bizim system duzgun calismiyor. orada bunu kanitladik.

Alıntı yapılan: LukeSkywalker - 17 Ağustos 2015, 18:29:30
t2 işi bitirmiş. Aynılarını yazıyordum sonradan mesajı gördüm.
value değişkenini signed olarak tanımla.

hocam value signed olsa ne degisecek ki? o array in degerini tutuyor? mesela

value = 44;

Ses_Cal =  Wav[value + 1]; // 45 inci byte i al?


mesaj birleştirme:: 17 Ağustos 2015, 18:56:40

burada signed ve unsigned konularini hoca anlatmis. sayilerin birbirlerini compliment etmesi gerekiyormus. bunun icin. en sol bit logic 1. diger bitlerin bit degerininde degisik olma sebebi. mesela +42 ile - 42 yi toplayinca 0 yapabilmesi. bunlari degistirmezsek toplayinca 0 yapamazmis. suan icin matematik diyorum. baskada birsey demiyorum ::)

https://www.youtube.com/watch?v=0MSmwdX5jlw

fatih6761

@Karamel bir de şunu denesen?
signed short Ses_Cal;
Ses_Cal = *(signed short *)(&Wav[value]);
Ses_Cal /= 16;
Ses_Cal += 2048;
Line1 = Ses_Cal;

Karamel

hocam Wav array icersindeki bilgiler 8 bitlik. fakat bunlarin byte yerlerini degistirip birbirine toplayinca 16 bit oluyorlar.

siz anladigim kadariyla burada Ses_Cal = *(signed short *)(&Wav[value]);   

Wav[value] array in icersini 16 bitlik olarak dusunmussunuz.

fatih6761

#41
Alıntı yapılan: Karamel - 17 Ağustos 2015, 19:01:25
hocam Wav array icersindeki bilgiler 8 bitlik. fakat bunlarin byte yerlerini degistirip birbirine toplayinca 16 bit oluyorlar.

siz anladigim kadariyla burada Ses_Cal = *(signed short *)(&Wav[value]);   

Wav[value] array in icersini 16 bitlik olarak dusunmussunuz.
@Karamel orada işaretçi aritmetiği var. Wav dosya içinde veriler Little Endian saklanıyorsa (ki muhtemelen öyle) derleyici o iki baytı zaten 16-bit lik veriymiş gibi değerlendirecek bu kodda.
Kodu açıklarsak:
& işareti ile Wav dizisinin value indisli elemanının adresi alınıyor. Adres alındığında artık verinin ne çeşit olduğu önemli değil sadece RAM adresi var. bunun önüne (signed short *) yazarak derleyiciye bak bu adreste 16-bitlik işaretli bir sayı saklıyorum diyoruz ki zaten aslında  Wav içinde bu şekilde saklanıyor. başına * koyarak derleyiciye bak bu adresteki 16-bitlik işaretli sayıyı bana oku diyoruz. Little Endian için byte sıralamasını derleyici bizim için yapıyor böylelikle.
Sen bir dene bakalım çalışırsa detaya gireriz :)

Not: Verinin hep 45. bayttan itibaren başladığını varsaymışsınız ama bu genel geçer bir kural değil. Format chunk'ında ExtraSize ile belirtilen kadar veri olabilieceği gibi değişik chunk'lar da mevcut. Bizzat 2-3 gün önce deneyimlediğimden biliyorum.
Bu soruna çözüm olarak da dosyanın başından 100 bayt okuyup "data" string'inin yerini buluyorum. Sonraki 4-bayt 32-bitlik veri boyutu oluyor. Geri kalanı da ses verisi oluyor.
Eğer 44-45 bayt kısmında 1-3-5-7... baytlık hata olursa verilerin tamamı bozulur. MSB-LSB karışır. Bundan da emin ol. Yani wav dosyayı hex editörle aç, data yazısını bul 4-bayt atla bundan sonrası ses verisidir.

LukeSkywalker

Value degiskenini signed yap, islemleri signed degiskenlerle yap, daca yukleyecegin degisken unsigned olsun.

Karamel

anladim hocam. :) ilk bos zamanimda c kitabi okuyayim. tek satirda bircok seyi halletmek bana cok cazip geldi ::)

hocam esrarengiz birsekilde short degilde int olarak cevirince calisiyor ama bir onceki gibi sorun. wav file in volumunun yukselen kisimlarinda cizirti var. buda bizim o kisimlari 12 bit e duzgunce ceviremedigimizi gosteriyor.

fatih6761

Alıntı yapılan: Karamel - 17 Ağustos 2015, 19:23:04
anladim hocam. :) ilk bos zamanimda c kitabi okuyayim. tek satirda bircok seyi halletmek bana cok cazip geldi ::)

hocam esrarengiz birsekilde short değilde int olarak cevirince calisiyor ama bir onceki gibi sorun. wav file in volumunun yukselen kisimlarinda cizirti var. buda bizim o kisimlari 12 bit e duzgunce ceviremedigimizi gosteriyor.
@Karamel Line1 değişkeninin unsigned olduğundan emin misin?
Ayrıca short olarak çalışması lazım int olarak çalışıyorsa bir sorun var demektir.
Wav dosyasını atabilir misin?