Continuity preserving signal processing

voorbereiding
Lees de teksten over CPSP in de klapper van te voren door zodat je zo ongeveer weet wat een cochleogram is en hoe de datastructuren eruit zien. Deze tekst dient vooral als referentie. CPSP wordt in dit practicum vooral gezien als een methodiek voor signaalanalyse en minder als een methode om het auditief systeem te begrijpen (hoewel het daar bij helpt). CPSP is (wellicht net als het auditieve systeem) geoptimaliseerd om in het input signaal informatie over de aanwezigheid en de ontwikkeling van individuele bronnen te kunnen vaststellen. Het volgen (tracking) van signaalcomponenten is daarom heel belangrijk. De reden waarom CPSP voor dit doel handiger is dan op FFT-gebaseerde methoden is dat er gebruik gemaakt wordt van de continuïteit van het basilair membraan model. Dit is niet geval bij een FFT waar bij ervan uitgegaan wordt dat alle informatie die je nodig hebt aanwezig is in een window (van bijvoorbeeld 25 ms). Door de frame gebaseerde aanpak is een FFT-spectrum vooral geschikt voor analyse per frame, ofwel de verticale richting van een spectrum, terwijl het in CPSP (en in het auditief systeem) ook gemakkelijk is in om temporele (horizontale) richting te analyseren.

  • Je kan de software vinden op /home/soundrecognition/cpsp/current/. Zorg dat je startup in matlab draait in deze directory (als je matlab opstart in deze directory wordt startup automatisch door matlab gedraaid).
  • Start functionsTest en kies plotNSC2 en calcRS. Zet het referentie spectrum op uniform m.b.v. Config, en kies in Config van plotNSC2 voor Show EdB. Verwerk de file nul.wav met Run Wav. Met plotNSC2 zie je behalve het cochleogram ook signaalcomponenten (de witte lijnen). De horizontale signaalcomponenten in spraak zijn schattingen van de harmonischen.
    Belangrijk: de computers in de practicumruimte zijn niet zo snel, dit betekent dat je veel geduld moet hebben de eerste keer dat je plotNSC2 of calcNSC2 berekent. Daarna wordt alle informatie opgehaald uit een hash-file, dus zal het veel sneller gaan (als je de instellingen niet verandert!) Wanneer je op een /tmp schijf werkt is het daarom handig deze hash-file (in matlab/processSoundFunctions/initPAS/cache/) te bewaren op je eigen schijf, en bij een nieuwe installatie op dezelfde plek terug te zetten.
  • Verander het aantal segmenten van 100 naar 200 m.b.v. Config TFProcessor en bekijk het resulterende cochleogram (met plotProcessSound i.p.v. plotNSC2). Door de aanpassing van het aantal segmenten moeten een aantal zaken opnieuwe worden berekend. Dit kan even duren. Kom zolang Matlab "busy" is niet aan de knoppen van de interface (Matlab vindt dat niet leuk!). Het cochleogram is nu nog wat scherper omdat de frequentieresolutie hoger is.
  • Verander het aantal segmenten terug naar 100, verwijder calcRS uit de lijst en bereken weer het cochleogram. Nu worden de hogere frequenties minder goed zichtbaar.
  • In Config van calcEdB kan je de instellingen van het dynamisch bereik veranderen. Wanneer je bijvoorbeeld een klein dynamisch bereik hebt kan je limit EdB aanklikken. Als je vervolgens op Recalculate klikt krijg je een vernieuwde plot.

Toets env in de Matlab command window. Als het goed is vind je voor de belangrijkste parameters:

env = 
                gdCorrection: 0
                        nseg: 100
                        maxf: 4000
            desiredFrameSize: 5
                        Qfac: 0.0500
                         tau: 0
                     nPeriod: 2
                energyCorFac: 1.0000e+10
                     maxDiff: 0.0050
                     initdep: 1
             amplitudeMatrix: 0
    processSoundFunctionsDir: {'../processSoundFunctions/'}
                   frameSize: 5
                          gd: [1x100 double]
                          fm: [100x1 double]
            cochleaFrequency: 22400
    

onderwerpen

Cochleogram van "nul"

Beluister het inputsignaal.

opdracht A

  1. Geef de tijdsintervallen voor de de drie spraakklanken van "nul".
  2. Waarom is er rond t = 120 ms sprake van een vrij scherpe overgang? Wat is daar de fysische reden voor?
  3. Schat op t = 175 ms de frequentie van de formanten. Dit is het gemakkelijkst door een doorsnede op dit tijdstip (framenummer 35) te plotten:

    global D
    figure, plot(D.EdB(:,35))

    Geef van alle formanten (ook de eerste) aan hoe nauwkeurig je ze kunt schatten. Leg uit waarom sommige formanten vooral bij vrouwen moeilijk te schatten zijn.
  4. Zet de hoogste frequentie (Fmax) op 10.000 Hz, bereken en plot een cochleogram met plotProcessSound en bereken vervolgens een FFT-spectogram:

    [x fs] = wavread('wav/nul.wav');
    nfft = 256;
    stepT = env.frameSize;
    windowName = 'hanning';
    PLOT = 1;
    figure
    [S, SInfo] = fftGram(x, fs, nfft, stepT, windowName, PLOT);

    Vergelijk het FFT-spectrogram met het cochleogram. Geef zoveel mogelijk verschillen. Het aantal "kanalen" in beide verschilt niet veel: 100 voor het cochleamodel en 128 voor de FFT.
  5. Verdubbel nu nfft. Wat betekent dit voor de windowgrootte en daarmee voor de temporele resolutie?
  6. Visualiseer van zowel het cochleogram als het FFT-spectrum de doorsnede op t = 175 ms (frame 35).

    figure
    subplot(2,1,1); plot(D.EdB(:,35));
    set(gca, 'xdir', 'reverse'); grid on;
    xlabel('segment nummer');
    title('Cochleogram doorsnede op t = 175');
    subplot(2,1,2); plot(SInfo.F, S(:,35));
    axis([0 6000 -inf inf]); grid on;
    xlabel('Freq in Hz');
    title('FFT-spectrum voor t = 175')

    Geef overeenkomstige structuren in beide representaties aan. Vergelijk voor de FFT een nfft van 256 en 512.
    Vergelijk verder het scheidend vermogen van naburige frequentiecomponenten van beide representaties. Welke representatie heeft je voorkeur voor het scheiden bij lage frequenties en welke voor hoge frequenties? Mensen kunnen de eerste 8 tot 10 harmonischen scheiden.
    N.B. Wanneer je wilt weten welke frequentie hoort bij segment 100 doe dan: env.fm(100).
  7. Deze spreekster heeft een vrij hoge stem. Stel dat je een lage mannenstem analyseert (f0 ongeveer 70 Hz), wat zou er dan veranderen? Welke representatie levert dan een beter gescheiden resultaat?

Zet, zo nodig, het aantal segmenten weer op 100, kies als hoogste frequentie Fmax 4000 Hz, en bereken een cochleogram met daarin de NSC's van het harmonische complex van de klank. Dit kun je doen door HCBits te selecteren uit de functielijst. Kies ook plotProcessSound, zodat het cochleogram wordt geplot. Dit levert onder andere een variabele CHH op, met daarin allerlei informatie, waaronder de NSC's (signaalcomponenten) waaruit het harmonisch complex bestaat. Harmonische complexen worden bepaald door eerst alle horizontale signaalcomponenten (tonen) te zoeken, en vervolgens te kijken of er een harmonische relatie is tussen sommige van deze tonen. Als er een harmonische relatie wordt gevonden wordt er een CHH gemaakt, waarin de signaalcomponenten staan waaruit dit harmonisch complex is opgebouwd. Hieronder een aantal velden uit eem voorbeeld van de variabele CHH. (Het aantal harmonische complexen, dus het aantal CHH's dat wordt gevonden is afhankelijk van de geluidsfile die je verwerkt.)
N.B. De variabelen D, NSC en CHH zijn niet altijd per default beschikbaar. Wanneer een variabele onbekend is, maak deze dan globaal met global D NSC CHH, afhankelijk van welke variabelen je uitgerekend hebt.

CHH = 
1x13 struct array with fields:
    nsc
    fr
    harm
    f0
    score
    onsetNSC
    segmentOffset
    rms
    startIndex
    startFrame
    sn
    det
    pearsonCorr
    

In een CHH kan je o.a. vinden welke NSC's deze CHH is opgebouwd. Vervolgens kan je in de NSC variable weer meer vinden over deze NSC's, bijvoorbeeld:

ans = 
            fr: [1x79 double]
           seg: [1x79 double]
             L: 79
      salience: 2
          type: 0
          freq: [1x79 double]
           EdB: [1x79 double]
           PAS: [1x79 double]
    medianFreq: 113.3302
    

Wanneer er sprake is van een enkele spraakklank in een geluidsfile, dan zullen er niet veel CHH's zijn waar informatie instaat. Je kunt de niet-lege CHH's vinden door diegene te selecteren die een positieve score hebben:

find([CHH.score] > 0)

Wanneer je de juiste CHH hebt gevonden, kan je de fundamentele frequentie f0 en de bijbehorende NSC's plotten in het cochleogram:

hold on
plot(CHH(9).fr, freq2seg(CHH(9).f0), 'k', 'LineWidth', 3)
for ii = CHH(9).nsc'
  plot(NSC(ii).fr, NSC(ii).seg, 'w', 'LineWidth', 3)
end

We gaan nu het frequentieverloop onder de f0 onderzoeken.

opdracht B

  1. Voer uit (zorg dat je het juiste CHH-nummer kiest!):

    figure
    plot(CHH(9).fr, CHH(9).f0)
    grid on

    Wat zijn de frequenties van het eerste en het laatste frame van de f0 schatting?
  2. Geef een schatting van de snelste toonhoogteverandering in termen van Hz per seconde (1 frame = 5 ms). Wat is deze snelheid in octaven (factoren 2) per seconde?
    N.B. Deze snelheden zijn heel normaal voor (spontane) spraak.

We kunnen de frequenties van de NSC's die een CHH opbouwen plotten en bovendien kunnen we, wanneer we de frequentie door het harmonische nummer delen, zien wat de "mening" van elk van de harmonischen is over de fundamentele frequente f0.
N.B. De NSC's die de harmonischen voorstellen komen niet perse overeen met onderstaande lijst. Afhankelijk van de instellingen vindt de functie meer over minder NSC's. Check dus voor je eigen signaal welke NSC's overeenkomen met welke harmonischen. Een makkelijke manier om dit te checken is in D.NSC_S, via figure, imagesc(D.NSC_S). Wanneer je vervolgens met de datacursor over de gekleurde NSC's gaat kun je zien welk index nummer ze hebben. Vergelijk deze NSC nummers met de NSC's in de CHH.

figure
for ii = 1:length(CHH(9).harm)
   nsc = CHH(9).nsc(ii);
   t = NSC(nsc).fr * env.frameSize/1000;
   freq = smooth(seg2freq(NSC(nsc).seg));
   subplot(1,2,1); hold on
   plot(t, freq)
   subplot(1,2,2); hold on;
   plot(t, freq/CHH(9).harm(ii))
end
subplot(1,2,1); axis tight; box on;
xlabel('Tijd in sec'); ylabel('Freq in Hz');
title('Frequentieontwikkeling harmonischen');
grid on;
subplot(1,2,2); axis tight; box on;
xlabel('Tijd in sec'); ylabel('Freq in Hz');
title('Schatting f_0')
grid on;

Wat opvalt in het rechter plaatje, is dat de frequenties niet echt mooi op elkaar passen, maar dat er sprake lijkt te zijn van een systematische fout. De lagere harmonischen (die, afgezien van de tweede harmonische, in tijd later ophouden) zijn ten opzichte van de hogere harmonischen iets verschoven naar latere tijdstippen. Dit is een effect van group delay (zie voor uitgebreide uitleg proefschrift H 3.2, onderaan pagina 88). De group delay is al uitgerekend en opgeslagen in env.gd. Omdat de GD segmentafhankelijk is, moet er ook segmentsgewijs voor worden gecorrigeerd. Dit gebeurt in de regel met GD correctie. Hierin is env.gd(seg) de GD correctie in ms. Wanneer dit gedeeld wordt door env.frameSize krijg je een correctie in frames. Een en ander geeft nu:

figure
for ii = 1:length(CHH(9).harm)
   nsc = CHH(9).nsc(ii);
   frGDcor = NSC(nsc).fr - env.gd(round(NSC(nsc).seg))/env.frameSize;
   t = frGDcor * env.frameSize/1000;
   freq = smooth(seg2freq(NSC(nsc).seg));
   subplot(1,2,1); hold on
   plot(t, freq)
   subplot(1,2,2); hold on;
   plot(t, freq/CHH(9).harm(ii))
end
subplot(1,2,1); axis tight; box on;
xlabel('Tijd in sec'); ylabel('Freq in Hz');
title('Frequentieontwikkeling harmonischen');
grid on;
subplot(1,2,2); axis tight; box on;
xlabel('Tijd in sec'); ylabel('Freq in Hz');
title('Schatting f_0')
grid on;

opdracht C

  • Vergelijk de twee figuren (met en zonder gd-correctie). Wat zijn de verschillen? Controleer dit voor een tweetal segmenten met behulp van env.gd.
  • Schat in de figuur met GD correctie de f0 op t = 200 ms en de bijbehorende fout. Gebruik hiervoor de zoom-functie in Matlab.
  • Maak met

    figure
    [x fs] = wavread('wav/nul.wav');
    nfft = 512;
    stepT = env.frameSize;
    windowName = 'hanning';
    PLOT = 0;
    [S, SInfo] = fftGram(x, fs, nfft, stepT, windowName, PLOT);
    fr = round(200/SInfo.stepT);
    plot(SInfo.F, S(:,fr)); axis([0 2000 -30 40])
    xlabel('Freq in Hz');
    grid on;

    een doorsnede van het FFT-spectrum rond t = 200 ms. Maak op basis hiervan een alternatieve schatting van de fundamentele frequentie met bijbehorende fouten. Leg uit en onderbouw of deze schatting even nauwkeurig kan worden.
  • Plaats-frequentie relatie en group delay

    Tot slot gaan we even wat beter kijken naar de plaats-frequentie relatie en de group delay (GD) die respectievelijk in env.fm en env.gd opgeslagen zijn.

    GD is een vertraging die samenhangt met de frequentiespecificiteit van de segmenten van (de plaats op) de cochlea. Des te meer een segment zich specialiseert op een beperkt frequentie gebiedje, des te langer duurt het voordat het systeem heeft 'besloten' hoe het moet reageren op input. Grotere frequentie specificiteit leidt dus tot een vertraging (zie proefschrift 3.2). Met onderstaande commando's worden de GD en de plaats-frequentie relatie op een aantal manieren gevisualiseerd.

    figure
    subplot(2,2,1);
    plot(1:length(env.gd), env.gd); grid on;
    title('Group delay als fie van segm. #')
    ylabel('GD in ms')
    subplot(2,2,2);
    plot(env.fm/1000, env.gd, env.fm/1000, 10*1000./env.fm); grid on;
    legend({'Group delay', 'GD~10/(BF)'}, 1)
    axis([0 env.fm(1)/1000 0 env.gd(end)]);
    title('Group delay als fie van best freq.')
    xlabel('Best freq. in kHz')
    ylabel('GD in ms')
    subplot(2,2,3);
    plot(1:length(env.fm), env.fm/1000); grid on;
    title('Plaats frequentie-relatie')
    xlabel('Segment nummer')
    ylabel('Best Freq in kHz')
    subplot(2,2,4);
    semilogy(1:length(env.fm), env.fm/1000); grid on;
    title('Plaats frequentie relatie')
    xlabel('Segment nummer')
    ylabel('Best Freq in kHz')

    group delay en plaat-frequentie relatie

    De plaats-frequentierelatie gedraagt zich volgen de zogenaamde Greenwood map (proefschrift H 3.3) en is ongeveer lineair voor frequenties onder de 100 Hz en logaritmisch voor frequenties boven de 400 Hz, daartussen is een overgangsgebied. De groene lijn in de rechterbovenhoek is een benadering van het de relatie tussen de GD en de karakteristieke frequentie (best frequency).

    opdracht D

    1. Zoek in env de combinaties van de karakteristieke frequentie en de GD voor het eerste segment, het laatste segment, en een segment halverwege de cochlea. Noteer de waarden en geef ze aan in bovenstaande subplots.
    2. Schat de waarde van c in formule 3.4 van het proefschrift.

    Impuls respons

    Nu gaan we de respons van het systeem op een standaardsignaal bestuderen, namelijk de puls.

    • Verander de Famesize in 1 ms.
    • Verander onder config van calcEdB de dynamic range in 90 dB en bereken een cochleogram van de file puls8kHz.wav met een uniform referentie spectrum.
    • Bekijk het resultaat. De hogere frequenties zijn bevatten meer energie dan de lagere frequenties. Dit ligt aan de keuze van het referentie spectrum.
    • Verander het referentie spectrum in impulse, en reken weer een cochleogram uit. De nadruk verschuift nu meer naar de lagere frequenties.

    Op het eerste gezicht lijkt het alsof een impuls, en dan vooral aan de laag-frequentie kant, tot een enorm brede excitatie van meer dan een halve seconde leidt. Maar vergeet niet dat de kleur codering hier 90 dB is, en dus een factor miljard omvat. In het lineaire domein is de situatie minder dramatisch. Het is mogelijk om de impuls respons in lineaire eenheden (opgeslagen in D.E) van elk 20ste segment te plotten met behulp van:

    figure
    fr = 1:300;
    plot(fr * env.frameSize, D.E(10:20:end,fr)');
    grid on;
    title('Impuls respons van segmenten 10:20:100');
    xlabel('Tijd in ms');
    ylabel('Energie (lineair)');
    env.fm(10:20:100)

    opdracht E

    1. De group delay is (per definitie) te bepalen uit de impuls respons als het zwaartepunt van de energie verdeling in de tijd per segment. Kies drie segmenten, schat het zwaartepunt (het tijdstip dat het oppervlak onder de curve in tweeën deelt) en vergelijk deze waarde met de waarden in env.gd of de grafieken hierboven. Klopt je schatting?
    2. Leg een relatie tussen de impuls respons en de forward masking zoals die in de psychofysica bekend is. Wanneer is er sprake van forward masking?

    Spraakanalyse

    We zetten het systeem nu weer op geschikte default waarden voor spraaksignalen:

    • Framesize weer naar 5 ms.
    • Bij het uitrekenen van de cochleogram de dynamic range (onder config van calcEdB) weer terugveranderen naar 60 dB, en het referentie spectrum (onder config van calcRS) weer terug naar uniform.

    Dit leidt tot een env:

    env = 
                    gdCorrection: 0
                            nseg: 100
                            maxf: 4000
                desiredFrameSize: 5
                            Qfac: 0.0500
                             tau: 0
                         nPeriod: 2
                    energyCorFac: 1.0000e+10
                         maxDiff: 0.0050
                         initdep: 1
                 amplitudeMatrix: 0
        processSoundFunctionsDir: {'.../processSoundFunctions/'}
                       frameSize: 5
                              gd: [1x100 double]
                              fm: [100x1 double]
                cochleaFrequency: 22400
        

    Neem in Audacity een zinnetje op met een klein aantal lange harmonische complexen op. Bijvoorbeeld "Why I owe you more?". Bereken een cochleogram (via plotProcessSound en HCBits, zodat ook de NSC's berekend en geplot worden) van deze zin en sla het resultaat van de NSC's en CHH('s) op in NSC1 en CHH1.

    global NSC CHH;
    NSC1 = NSC;
    CHH1 = CHH;

    opdracht F

    1. Zoek de NSC('s) die corresponderen met de grondtoon. Laat duidelijk zien hoe je de juiste NSC vindt. Bepaal op basis van de NSC frequenties en op basis van de f0 in de CHH('s) de gemiddelde toonhoogte. Is er een verschil?
    2. Neem de zin nog twee keer op, maar nu met een zo laag en zo hoog mogelijk toonhoogte. Bereken weer de cochleogrammen met plotProcessSound en HCBits tot CHH2 en CHH3.
      Bepaal nu weer je toonhoogtebereik met de f0 in de CHH('s). (Deze f0 wordt bepaald op basis van de hogere harmonischen en is daarom een betere schatting voor de f0 dan de laagste NSC.)

    Neem nu een aantal keer /oe ie aa/ op, maar spreek elke klank vragend (toonhoogte omhoog gaand), of zelfs met een fluctuerende toonhoogte uit, zodat de kans groot is dat een harmonische van de laagste formant op enig moment precies onder het midden van de formant valt.

    opdracht G

    1. Bepaal nauwkeurig je klinkerdriehoek door de frequentie van de NSC op het moment van de hoogste energie in de formant te bepalen.

    Contact

    postadres
    Auditory Cognition Group
    Kunstmatige Intelligentie
    Rijksuniversiteit Groningen
    Postbus 407
    9700 AK Groningen

    bezoekadres
    Bernoulliborg
    Nijenborgh 9
    9747 AG Groningen

    How to reach us