Kirjautuminen

Haku

Tehtävät

Koodit: VB6: Wav-aaltoa

Kirjoittaja: sooda

Kirjoitettu: 11.07.2004 – 11.07.2004

Tagit: ääni, koodi näytille, vinkki

Kiinnostuin WAVin formaatista koska sain uudet kajarit. Aattelin tehdä testausohjelman niille :D
WAVia on montaa eri vormaattia, mutta kivoin on "canonical wave format" eli joku perushomma (http://www.lightlink.com/tjweber/StripWav/Canon.html sain tiedot formaatista).
En jaksa tota headerin formaattia selittää tässä koska kaikki varmaan osaa englantia ainaki sen verran että osaa ton sivun lukea. Tässä käytetään PCM (Pulse Code Modulation) -koodausta. Mulla ei ole mitään tarkkaa hajua miten toi toimii, mutta sain sellaisen käsityksen että se selitetään helpoimmin näin: filussa on joko tavuja tai integerlukuja peräkkäin (siis siellä missä on äänidata). Jokainen näistä antaa ämyrille infon että tunge kartiota n paljon eteenpäin, eli täysi arvo on että kajari on sama kun siihen tungettaisiin tasavirtaa sen verran kuin se kestää. Minimiarvo on sitten sama toisinpäin eli käännetään virtalähteen piuhat toisteppäi :). (Niille jotka ei tiedä: kaiutin toimii siten että siinä on kartio joka liikkuu edestakaisin tuottaen ääntä.) Neliöaallon tapauksessa kahta arvoa heilutellaan edestakaisin tyyliin 255-0-255-0 jolloin kartio pomppii edestakaisin ja syntyy ääntä. Toivottavasti joku osaa selittää paremmin :)

Noh ite vinkissä on kivoja sovellettavia funkkareita jotka tekee neliö- tai siniaaltoa ja soittaa sen. Siniaallosta tein kivan hommelin(SiniAaltoLiuku) jolla saa lineaarisen siniaallon x Hz:stä y:hyn. Neliöaaltoon en jaksanut tehdä kun se kuulostaa niin rumalta :)

Ainiin: noi hommelit jotka vääntää hertsiarvosta sen mikä filuun ängetään on tejeeziltä. Kiitos tejeez. (olisin iteki kyllä googletuksen jälkeen löytänyt mutta tejeez ehti eka.)

Private Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
Private Sub NeliöAalto(Taajuus, Pituus, Voimakkuus)

    On Error Resume Next 'jos vaikka wav.wav olisi käytössä jo.
    lenkku = Pituus * 44100 'koko filun pituus, käytetään samplerate 44100:aa.
    Kill "wav.wav"
    Open "wav.wav" For Binary As #1
    Put #1, , "RIFF" 'RIFF formaattia on waveissa.
    Put #1, , CLng(28 + lenkku) 'filun pituus - 8
    Put #1, , "WAVEfmt " 'wave ja fmt hommeli
    Put #1, , CLng(16) 'fmt header pituus
    Put #1, , CInt(1) '1 meinaa että pcm formaatti.
    Put #1, , CInt(1) 'kanavat, 1 = mono. Stereota ei tässä tarvita
    Put #1, , CLng(44100) 'samplerate
    Put #1, , CLng(44100) 'bps
    Put #1, , CInt(1) 'kertoo yhden samplen pituuden
    Put #1, , CInt(8) 'bitps
    Put #1, , "data" 'kertoo että data alkaa tästä
    Put #1, , CLng(lenkku) 'datan pituus
    ÄäniPituus = 22050 \ Taajuus  'lasketaan taajuushommeli, tästä kiitokset tejeezille (olisin pienen miettimisen jälkeen varmaan itekin kyllä keksinyt).
    'ääni tehdään kahta tavua heiluttelemalla, mitä erilaisemmat sitä isompi volyymi.
    ÄäniEka = 127 + Voimakkuus / 100 * 128
    ÄäniToka = 128 - Voimakkuus / 100 * 128
    'tehdään äänet
    'neliöaalto on tyyliin: tavu 255, tavu 0, tavu 255, tavu 0, ... tai tavu 255, tavu 255, tavu 0, tavu 0, ...
    For i = 1 To lenkku
        ÄäniKohta = ÄäniKohta + 1
        If ÄäniKohta > ÄäniPituus Then ÄäniJuttu = 1 - ÄäniJuttu: ÄäniKohta = 0
        If ÄäniJuttu Then Put #1, , CByte(ÄäniToka) Else Put #1, , CByte(ÄäniEka)
    Next
    Close 'filu sulki
    sndPlaySound App.Path & "\wav.wav", 1 'soita se

End Sub

Private Sub SiniAalto(Taajuus, Pituus, Voimakkuus)

    On Error Resume Next 'jos vaikka wav.wav olisi käytössä jo.
    lenkku = Pituus * 44100 'koko filun pituus, käytetään samplerate 44100:aa.
    Kill "wav.wav"
    Open "wav.wav" For Binary As #1
    Put #1, , "RIFF" 'RIFF formaattia on waveissa.
    Put #1, , CLng(28 + lenkku) 'filun pituus - 8
    Put #1, , "WAVEfmt " 'wave ja fmt hommeli
    Put #1, , CLng(16) 'fmt header pituus
    Put #1, , CInt(1) '1 meinaa että pcm formaatti.
    Put #1, , CInt(1) 'kanavat, 1 = mono. Stereota ei tässä tarvita
    Put #1, , CLng(44100) 'samplerate
    Put #1, , CLng(44100) 'bps
    Put #1, , CInt(1) 'kertoo yhden samplen pituuden
    Put #1, , CInt(8) 'bitps
    Put #1, , "data" 'kertoo että data alkaa tästä
    Put #1, , CLng(lenkku) 'datan pituus
    'tehdään äänet
    VolKerroin = Voimakkuus / 100 * 127 'äänenvoimakkuus
    For i = 1 To lenkku
        Put #1, , CByte(128 + Sin(Taajuus / 44100 * i * 2 * 3.14159265358979) * VolKerroin) 'tämänkin kaavan tejeez kekkasi ennen mua.
    Next
    Close 'filu sulki
    sndPlaySound App.Path & "\wav.wav", 1 'soita se

End Sub

Private Sub SiniAaltoLiuku(AlkuTaajuus, LoppuTaajuus, Pituus, Voimakkuus)

    On Error Resume Next 'jos vaikka wav.wav olisi käytössä jo.
    lenkku = Pituus * 44100 'koko filun pituus, käytetään samplerate 44100:aa.
    Kill "wav.wav"
    Open "wav.wav" For Binary As #1
    Put #1, , "RIFF" 'RIFF formaattia on waveissa.
    Put #1, , CLng(28 + lenkku) 'filun pituus - 8
    Put #1, , "WAVEfmt " 'wave ja fmt hommeli
    Put #1, , CLng(16) 'fmt header pituus
    Put #1, , CInt(1) '1 meinaa että pcm formaatti.
    Put #1, , CInt(1) 'kanavat, 1 = mono. Stereota ei tässä tarvita
    Put #1, , CLng(44100) 'samplerate
    Put #1, , CLng(44100) 'bps
    Put #1, , CInt(1) 'kertoo yhden samplen pituuden
    Put #1, , CInt(8) 'bitps
    Put #1, , "data" 'kertoo että data alkaa tästä
    Put #1, , CLng(lenkku) 'datan pituus
    'tehdään äänet
    VolKerroin = Voimakkuus / 100 * 127 'äänenvoimakkuus
    For i = 1 To lenkku
        Taajuus = AlkuTaajuus + i / lenkku * (LoppuTaajuus - AlkuTaajuus) 'taajuus alun ja lopun väliltä
        Put #1, , CByte(128 + Sin(Taajuus / 44100 * i * 2 * 3.14159265358979) * VolKerroin)
    Next
    Close 'filu sulki
    sndPlaySound App.Path & "\wav.wav", 1 'soita se

End Sub

Kommentit

hunajavohveli [11.07.2004 20:55:22]

#

Vau, tolla saa aikaan hienoja ääniä. :D Pitääpä joskus itsekin perehtyä tuohon API-funktioon.

rndprogy [11.07.2004 22:09:57]

#

Mitään ei tapahdu?

peki [11.07.2004 23:06:34]

#

Kivoja ääniä. Voisit ehkä lisätä vielä lisää efektejä?

rndprogy [11.07.2004 23:44:29]

#

Sainki toimimaan.

sooda [12.07.2004 10:37:28]

#

peki: voithan ite tehdä ihan mitä haluat kun nyt näet miten homma toimii.

Antti Laaksonen [12.07.2004 17:54:57]

#

Yksi asia askarruttaa vielä minua. Miten taajuudet pitää ilmoittaa, jos haluaa saada useamman äänen kuulumaan yhtä aikaa?

thefox [12.07.2004 23:51:11]

#

Antti: en nyt ihan tainnut tajuta kysymystäsi, mutta miksaus (kahden äänen yhdistäminen) tapahtuu yksinkertaisesti lisäämällä signaalit yhteen. Eli jos sinulla on pulssiaallon senhetkinen näyte (sample) muuttujassa a ja siniaallon näyte muuttujassa b, miksaat nuo yhteen yksinkertaisesti laskemalla c = a + b. Tällöin tunkemalla c-muuttujaa tiedostoon (tai ulos suoraan äänikortille) tulevat molemmat äänet yhtäaikaa.

Tietysti kannattaa huolehtia tarvittavista normalisoinneista, eli tuossa tapauksessa kannatanee jakaa signaali kahdella lisäysoperaation jälkeen ettei signaali klippaa.

User137 [13.07.2004 09:04:59]

#

Melko hyvältä ja yksinkertaiselta koodilta näyttää. Pistää vaan silmään yksi asia:
For i = 0 To lenkku

Tuo kirjoittaa wav-tiedostoon yhden ylimääräisen tavun! Eipä se tietty kiintolevyä pahemmin rassaa, mutta jos tuota käytetään pohjana tulevissa ohjelmissa niin... :P

sooda [13.07.2004 12:01:51]

#

lainaus:

Melko hyvältä ja yksinkertaiselta koodilta näyttää. Pistää vaan silmään yksi asia:
For i = 0 To lenkku

Tuo kirjoittaa wav-tiedostoon yhden ylimääräisen tavun! Eipä se tietty kiintolevyä pahemmin rassaa, mutta jos tuota käytetään pohjana tulevissa ohjelmissa niin... :P

Kiitti kun huomautit, korjattu =)

nomic [13.07.2004 13:39:26]

#

loistava! itse jo olen miettinyt jonkin aikaa että mites homma toimii, tai siis sen olen tiennyt miten wavi rakennetaan (esim tekstitiedostossa) mutta enpä ole osannut tehdä tämmöistä lelua joka sitten näpertää kaiken kunnolla :) loistava, ja tuosta klippaamisesta sen verran niin homman voi säätää vaikkapa kanava-sliden sekä pieni yksinkertainen kompressori joka määrittelee että monella jaetaan luku jotta ei klippaisi, siihen voi vaikkapa tunkea maksimi-rajan tyyliin:

if äänenluku > maksimiraja - jotain then
 käytä kompressoria
end iffii ;)

thefox [29.07.2004 01:24:20]

#

Ei siihen mitään kompressoria kannata kyllä lähteä tunkemaan :)

Lumi-ukkeli [16.02.2005 21:00:49]

#

Oisko exeä?

Meitzi [28.10.2006 14:18:00]

#

En tiedä miksi halusit nimenomaan tehdä WAV tiedoston ensin ja soittaa sitte vasta sen. Aika helppoa olisi vain tehdä ääni muistiin ja soittaa se. Sillätavalla olisi helppoa sitten tehdä mixsaushohjelma jolla säädetään korkekuskia ym.. useampia ääniä yhteen jne.

Kirjoita kommentti

Muista lukea kirjoitusohjeet.
Tietoa sivustosta