Dr.Godfried-Willem RAES
Kursus Experimentele Muziek: Boekdeel 1: Algoritmische kompositie & Kursus Akoestiek
Hogeschool Gent : School of Arts
<Terug naar inhoudstafel kursus> |
1157
Wave naar Spektrum en Spektrum naar Wave konversie
Hierbij geven we bronkode waarin Fourier transforms geimplementeerd zijn (zie tekst terzake). De hier gegeven procedures zijn terug te vinden in de Basic library <HarmLib> , module HARM_AKU die de studenten ter beschikking staat als onderdeel van <GMT> (library: g_lib.dll)
1.- Wave naar Spectrum
Gegeven een golfvorm, hier in de vorm van een genormaliseerd array Samp!() bestaande uit n sample waarden, dan kan de kode voor een procedure die daarvan het spektrum berekent, eruit zien alsvolgt:
SUB DFT (Samp!(), Sp!())
size% = (UBOUND(Samp!)) + 1: ' dit moet een macht van 2 zijn indien een FFT algoritme wordt toegepast.
REDIM Sp!(0 TO UBOUND(Samp!))
kfaktor! = Pi2 / size% : ' Pi2 is een konstante = 2 * Pi
i% = 0
DO
kt! = kfaktor! * i%
Rl! = 0
Im! = 0
FOR x% = 0 TO size% - 1
g! = (kt! * x%)
a! = Samp!(x%) / size%
IF a! THEN
Rl! = Rl! + (a! * COS(g!))
Im! = Im! - (a! * SIN(g!))
END IF
NEXT x%
pw! = (Rl! * Rl!) + (Im! * Im!): ' sum of squares
IF pw! THEN Sp!(i%) = 2 * SQR(pw!)
i% = i% + 1
LOOP UNTIL i% >= size% / 2:
' de tweede helft van het array laten we blanko. Het is het spiegelbeeld van de eerste helft.
END SUB
Merk op dat net zoals de tijd in het sample-array lineair loopt, ook de frekwentie een lineaire distributie heeft in het geretourneerde spektrum. Dit heeft voor gevolg dat de resolutie in de lage spektraalbandjes voor ons logaritmisch oor veel geringer is dan voor de hoge. Funkties voor omzetting naar logaritmische en meer bepaald chromatische spektraalbandjes zijn opgenomen in onze <Harmony Library>. Merk op dat in deze procedure geen enkele vorm van windowing wordt toegepast. In zo'n geval spreken we van een rechthoekig venster (rectangular window). In de praktijk is de voorafgaandelijke toepassing van een geschikt venster wenselijk, vooral wanneer het aangeboden sample niet begint en eindigt met een 0 waarde.
2.- Spectrum naar Wave
In de hiernavolgende procedure gebeurt precies het omgekeerde. Data uit het frequentiedomein (een spektrum, gegeven als een array Sp!()) worden omgezet in een reeks samples met overeenkomstige spektrale samenstelling. De tijd waarover het spektrum loopt wordt beschouwd als gelijk aan 1, tevens de nominale duur voor Smp!(). Bij gebruik van een andere tijdschaal, moeten coefficienten proportioneel toegepast worden.
SUB InvDFT (Sp!(), Smp!())
size% = UBOUND(Sp!) + 1
REDIM Smp!(0 TO UBOUND(Sp!))
kfaktor! = Pi2 / size%
i% = 0
DO
kt! = kfaktor! * i%
Rl! = 0
x% = 0
DO
g! = (kt! * x%)
a! = Sp!(x%)
IF a! > 0 THEN
a! = SQR(a!)
Rl! = Rl! + (a! * SIN(g!)): ' alleen reele waarden
END IF
x% = x% + 1
LOOP UNTIL x% >= size% / 2: ' de helft is voldoende
IF Rl! THEN
Smp!(i%) = Rl!
END IF
i% = i% + 1: ' dit is de teller voor de frekwentiebandjes
LOOP UNTIL i% > size% - 1
END SUB
3.- Vensters
Omdat het gebruik van een rechthoekig venster -waarbij er erg diskontinue overgangen kunnen zijn bij het begin en einde van de data- steeds aanleiding geeft tot het ontstaan van aliasfrekwenties en artefakten die de Sin(x)/x wet volgen, verdient het aanbeveling het input array voor de wave naar spektrum transformatie eerst door een vensterfunktie te halen.
Het snelst -maar niet ideaal- werkt het driehoeksvenster, dat er in kode uitziet alsvolgt:
SUB TriangleWindow (Shape!())
size% = UBOUND(Shape!)
HalfSize% = size% / 2
increment! = 1 / HalfSize%
faktor! = 0
FOR i% = 0 TO HalfSize%
Shape!(i%) = Shape!(i%) * faktor!
Shape!(size% - i%) = Shape!(size% - i%) * faktor!
faktor! = faktor! + increment!
NEXT i%
END SUB
Veel mooier zijn de rezultaten wanneer een zgn. 'Hanning' venster wordt gebruikt. Dit venster is gesteund op een klokkurve gebaseerd op een COS funktie. De snelle procedure (de cosinus moet maar over een enkel kwadrant berekend worden) daarvoor ziet eruit alsvolgt:
SUB HanningWindow (Shape!())
size% = UBOUND(Shape!)
hoekincrement! = Pi2 / size% :' Pi2 en Pi zijn gedeklareerde konstanten
hoek! = Pi
HalfSize% = size% / 2
QuartSize% = size% / 4
i% = 0
DO
faktor1! = (COS(hoek!) + 1) / 2
faktor2! = 1 - faktor1!
Shape!(i%) = Shape!(i%) * faktor1!
Shape!(size% - i%) = Shape!(size% - i%) * faktor1!
Shape!(HalfSize% - i%) = Shape!(HalfSize% - i%) * faktor2!
Shape!(HalfSize% + i%) = Shape!(HalfSize% + i%) * faktor2!
i% = i% + 1
hoek! = hoek! + hoekincrement!
LOOP UNTIL i% = QuartSize%
' now we missed only Shape!(QuartSize%)
faktor1! = (COS(hoek!) + 1) / 2
Shape!(QuartSize%) = Shape!(QuartSize%) * faktor1!
END SUB
In de praktijk worden nog tal van andere vensterfunkties toegepast: trapeziodaal, gauss-vensters, Hamming... Dit kan, in afwachting dat het in deze kursus wordt opgenomen, in de literatuur terzake (onderwerpen: meettechniek, signal processing en fast fourier transforms) teruggevonden worden. In samenwerking met wijlen kollega Dr.Jan Kruger werkten we aan een verdere uitwerking van dit onderwerp, dat gezien de opmars van de realtime audio alsmaar aktueler wordt.
Uitgebreide funkties zijn opgenomen en geintegreerd in onze <GMT> libraries, maar vormen tegenwoordig ook een vast bestanddeel van zowat alle audio-bewerkingssoftware. Uiteraard zijn ze ook geintegreerd in technisch-wetenschappelijke software zoals MatLab en Labview (National Instruments).
De algemene formule voor zowel hanning als hamming vensterfunkties is:
In toepassingssoftware is het gangbaar dergelijke arrays met wegingsfaktoren in een lookup table te plaatsen en ze vervolgens middels matrix operaties op de data toe te passen.
Filedate: 980129/ last update: 2013-04-29
Terug naar inhoudstafel kursus: <Index Kursus> | Naar homepage dr.Godfried-Willem RAES |