Code-Beispiel
Audio: WAV-Datei erstellen
Bei der Veröffentlichung meines WAVEPRESSOR hier im Portal bin ich gebeten worden, etwas zum Thema WAV-Dateien zu veröffentlichen. Dem Wunsch komme ich sehr gerne nach.
Im erstes Beispiel geht es um den Dateiaufbau und den Inhalt einer Mono-Datei.
Es wird eine kurze Audiodatei mit Testtönen erstellt. Abhören anschliessend bitte mit dem Media-Player, anschauen zum Beispiel mit Audacity.
Allgemeine Erklärung:
Eine Kette von Zahlenwerten bilden die Wellenform ab.
Bei einer Samplerate von 44,1 kHz (Audio-CD) sind das dann 44100 Zahlenwerte je Sekunde (Mono) und 88200 Zahlenwerte je Sekunde (Stereo).
Jede Zahl hat 16 Bit (2 Byte).
Bei der Analyse beliebiger anderer WAV-Dateien wird man feststellen, dass es einige unterschiedliche Varianten gibt.
Die anderen Varianten betreffen den Dateiaufbau, zum Beispiel zusätzliche Informationen, und die Audioqualität.
Um Verwirrung zu vermeiden, bleibt es hier bei der einfachsten Variante.
WINDOWTITLE "WAVE-Datei By J.Härpfer"
SCREEN 14
color 0,7
cls
'DIM für die Audiodatei-Paramteter
dim as short RestlaengeFormatChunk
dim as short FormatTag
dim as ushort Kanaele
dim as ULONGINT Samplerate
dim as ULONGINT BytesJeSek
dim as ushort Block
dim as ushort Bits
'DIM für den Programmablauf
dim as integer Freq,Free_FileNr
dim as single Verst,Hoehedaempf
dim as integer ii,uu,oo,Tonfrequenz
dim as uinteger Dateigroesse
dim as string Txt,Start_Chunks,Dateiname,Stille,Null2
'Erste Datei mit 44 kHz Samplerate:
RestlaengeFormatChunk=16'fester Wert bei "unkompliziertem" WAV
FormatTag=1
'das entspricht der PCM-Codierung
Kanaele=1
' 1=mono 2=stereo
Samplerate=44100
'44 kHz ist bei Audio-CDs üblich
'bedeutet: 44100 Zahlen je Sekunde (signed short) (MKSHORT)
Bits=16
'16-Bit-Audio (oder 2 Byte je dargestelltem Punkt auf der Audiowelle)
BytesJeSek=Samplerate*Kanaele*(Bits/8)
' "2" weil wir 16Bit Quantisierung nehmen
Block=Kanaele*(Bits/8)
print
print " Erzeuge eine Audiodatei."
print
print " 16 bit, Mono, Testsignale."
print
print
Free_FileNr=freefile
Dateiname="ISO_Waves_mono_"+str$(Samplerate)+".wav"
print
print " ";Dateiname
print:print
open Dateiname for output as Free_FileNr
'Der Anfang einer WAV-Datei entält die technischen Angaben
'An den beiden Stellen "xxxx" wird später noch je ein Zahlenwert eingetragen
'folgende MKSHORT sind nur korrekt, sofern der Wert unter 32767 liegt :-)
'... und bei 16 Bit Quantisierung
'
Start_Chunks="RIFFxxxxWAVEfmt "+mki(RestlaengeFormatChunk)+mkshort(FormatTag)
Start_Chunks+=mkshort(Kanaele)+mki(Samplerate)+mki(Samplerate*Block)+mkshort(Block)
Start_Chunks+=mkshort(Bits)+"dataxxxx"
print #Free_FileNr, Start_Chunks;
'Einen Punkt auf der Nulllinie definieren
Null2=mkshort(0)
'Erzeuge ein kurzes Stück Audiodatei, Stille, eine halbe Sekunde
Stille=""
for ii = 1 to Samplerate/2:Stille+=Null2:next ii
'Das geht mit dem String-Befehl auch eleganter, aber ich lasse es hier so.
'Setzte READ-Lesezeiger auf das Label iso_freq
restore iso_freq
Sprungmarke2:
'Schreibe das Stück in die Audiodatei
print #Free_FileNr, Stille;'Stille
'Lies die nächste Tonfrequenz,
'mit der ein kurzes Stück Audiodatei erstellt werden soll
read Tonfrequenz'Hz
if Tonfrequenz=0 then goto Sprungmarke3
Txt=""
verst=0
if Tonfrequenz>2600 then Hoehedaempf=(1-(Tonfrequenz-2600)/25000) else Hoehedaempf=1
'Erzeuge jetzt ein Stück Audiodatei (Txt)
for ii = 1 to Samplerate' 1 Sekunde lang
'Erzeuge Sinuswellen bei ca 70% der Maximallautstärke (32767*0.7 = ca. 22900)
uu=int(Hoehedaempf*verst*22900*sin(ii*Tonfrequenz/Samplerate*3.14159*2))
Txt+=mkshort(uu)
'Für Stereo: Txt+=mkshort(uu)+mkshort(uu)
' und (oben) Kanaele=2 (oben)
'Den Anfang des Stücks einblenden:
if ii<Samplerate/20 and verst<.95 then verst+=50/Samplerate
'Das Ende des Stücks ausblenden
if ii>Samplerate*.6 then verst-=5/Samplerate
if verst<0 then verst=0
if verst>1 then verst=1
next ii
'Schreibe die 1 Sekunde Audio in die Datei
print #Free_FileNr, Txt;
goto Sprungmarke2
Sprungmarke3:
'Datei beenden
close Free_FileNr
sleep 40
'Abschliessende Arbeiten
Free_FileNr=freefile
open Dateiname for binary as Free_FileNr
Dateigroesse=LOF(Free_FileNr)
'Der nachfolgend verwendete MKI-Befehl geht nur bis ca. 2 GByte
PUT #Free_FileNr,5,MKI$(Dateigroesse-8)
PUT #Free_FileNr,41,MKI$(Dateigroesse-44)
close Free_FileNr
print
print " Fertig. Beliebige Taste ..."
sleep
END
ISO_freq:
Data 40,63,100,160,250,400,630,1000,1600,2500,4000,6300,10000,16000,0
Zusätzliche Informationen und Funktionen |
|
|