WaveWizard

Resofilter 1 staat wel op 1000 (Hz) moet dat niet zijn 2450 ???

Zoals je hoort, krijg je een AA-klinker (zoals in "maan") als Reso 1 op 1000 Hz staat. Maak je daar bijv. 800 Hz van, dan hoor je meer een A (zoals in "man"). Die 2450 Hz geeft een formantje dat min of meer samenvloeit met die van 2700 Hz; dat schiet dus niet echt op. Maar je kunt dat natuurlijk allemaal zelf controleren en ook eigen klinkers maken.
Ik zal binnenkort een methode beschrijven waarmee je formanten van bijv. je eigen stem kunt afleiden en uitdrukken in resonantiefrequenties, bandbreedtes en gains. (Dat kan met WW in principe ook geheel geautomatiseerd, maar in de huidige versie "slaapt" die instructie nog.)
 
Werkt dat zoiets als met dit Kyma prototype?

SqrtMagnitude

This is the square root of the sum of the left and right channels squared. If the square root of the sum of the squares is greater than 1.0, this Sound saturates at 1.0. It can be useful in doing spectral analysis where the left channel is defined to be the real part and the right channel as the imaginary part of a complex number. You could also use this as a strange kind of measure of the instantaneous "distance" between two signals, one in the left and one in the right.
 
Die SqrtMagnitude doet precies wat je al schrijft: van twee signalen Re[n] en Im[n] wordt steeds een sample gekwadrateerd en vervolgens worden de kwadraten opgeteld en wordt de wortel genomen. Die uitkomst is dan de magnitude of "lengte" (Pythagoras). Deze bewerking heeft alleen betekenis als die twee signalen of vectoren orthogonaal zijn (een "kwadratuur"-relatie hebben), zoals cosinus- (Re) en sinusspectrum (Im) in de Fouriertransformatie.

In code uitgedrukt is het soms helderder en in elk geval korter:
Code:
Bewerk signaal
  n0          0
  n1          aantal
  Bewerking   Magn[n] = (OutRe[n]^2 +  OutIm[n]^2)^0,5

Deze bewerking wordt in WaveWizard impliciet uitgevoerd als je de FFT berekent. Zowel de input als de output van de FFT zijn complexe signalen. Meestal wordt de output dan nog eens weergegeven in twee vormen: in rechthoekcoördinaten (x,y) of (Re,Im) en in poolcoördinaten (Amp,Fase). Amp wordt ook vaak Magnitude genoemd.

Code:
FFT
  In Re                S1[0]
  In Im                S2[0]
  Out Re               F1[0]
  Out Im               F2[0]
  Amp                  F3[0]
  Fase                 F4[0]
  Venster (in smp)     2^12
  Hann? ('j' of 'n')   n

Meestal wil je van een spectrum graag de amplitude- en fasespectrum weten en zul je dus gebruik maken van de outputs Amp en Fase.

Als je een spraakklank direct wil uitdrukken in termen van formanten, dus reso-frequentie, bandbreedte en gain, dan komt er nog wel wat meer on de hoek...
I'll be back... :yamaha:
 
Wat doet LPC?

Wat doet LPC?

Het LPC analyse-algoritme analyseert frame voor frame een (spraak)geluid.
Elk frame leidt tot een filter dat dezelfde klankkleur heeft als het frame.
Dus de input van het LPC analyse-algoritme is een spraaksignaal en de output is een rij filter-getallen (filtercoëfficiënten) a1, a2, a3, ... in de figuur te zien in de rode driehoeken.
Zie figuur.

attachment.php
 

Attachments

  • LPC-frames.jpg
    LPC-frames.jpg
    41,5 KB · Bekeken: 151
formantfilters

formantfilters

Deze filtergetallen kun je gebruiken in een filter en daarmee bijvoorbeeld een gitaar laten "praten". Maar je kunt die spraakklanken niet veranderen: een AA blijft een AA en wordt nooit een EU. Voor een dergelijke klankverandering is een nadere analyse van de filtergetallen nodig. Die analyse heet root finding en deelt het LPC-filter op in een lange serie eenvoudige resonantie- of formantfilters (zie boven: Bank-van-Jim). Elk daarvan heeft een eigen resonantiefrequentie en bandbreedte. Die kun je afzonderlijk van elkaar manipuleren en daarmee de klank veranderen. Nog beter gaat dat als je dit formant-seriefilter op zijn beurt omrekent (partial fraction) naar een formant-parallelfilter dat voor elk filtersegment, naast resonantiefrequentie en bandbreedte, ook een gain berekent. Je verandert een AA in een OE of een UU door per formantfilter "aan drie knopjes te draaien": resofreq, band en gain.

Je hebt hier dus een heleboel "handen" voor nodig: een LPC-formant-parallelfilter bestaat typisch uit meer dan 40 resonantiesegmenten; dus meer dan 120 knopjes om gelijktijdig aan te draaien.
Zoiets laat je natuurlijk over aan een fly-by-wire stuurprogramma dat wel een beetje lijkt op de sturing van potmeters van een mengtafel. Maar dan wel een stuk ingewikkelder: spraak komt er uit te zien als het op- en neer wapperen van zo'n 120 schuiven...
De bufferstructuur van WaveWizard, in combinatie met de automatische interpolatie-eigenschap staat een dergelijke fly-by-wire aansturing in principe wel toe. Een klank-compositieproces komt dan neer op de constructie van een serie met elkaar samenhangende stuursignalen. Hier ligt een boeiend interactie-vraagstuk.

Daarnaast is ook een heel andere soort analyse van het LPC-filter mogelijk die meer de kant opgaat van physical modeling: uit het spraakgeluid destilleer je een ruimtelijk model van het spraakkanaal in de vorm van een aantal achter elkaar liggende buissegmenten van verschillende diameters die gezamelijk een vorm hebben die misschien heel anders is dan die van het spraakkanaal in een zekere stand, maar die wel dezelfde klank oplevert. Zoals je bij een schuiftrompet een toon lager of hoger maakt door de lengte van een buis te veranderen, zo verander je een AA in een OE of een UU door de diameters van de buissegmenten te wijzigen.
Ook hier denk je natuurlijk gelijk aan die fly-by-wire aansturing, hoewel het aantal knopjes hier drie keer zo klein is als bij het formant-parallelfilter.
.
attachment.php
 

Attachments

  • LPC.jpg
    LPC.jpg
    36 KB · Bekeken: 149
Thx, Roland!

Hier de code van de figuren in https://www.synthforum.nl/forums/showpost.php?p=1775560&postcount=53.
In buffer F1 wordt een sinus pieptoon van 10 kHz aangemaakt,
In buffer F2 wordt deze sinus zodanig uitgerekt dat tussen elke twee sinus-samples negen vrije sample-plaatsen komen te staan (d.w.z. samples met uitwijking nul). Om die nul-samples toch te kunnen zien krijgen ze een ietsje grotere waarde (0,007).

Daaronder de instructies voor het instellen, plaatsen en opslaan van de grafieken.


Code:
!***********************
! Preset 10kHz sinustoon
!***********************

Declareer Freq; w

Freq = 10000
w    = 2*pi*Freq*Ts

!--------------------------------------------
! buffer F1: maak 10 kHz sinustoon 
!--------------------------------------------
Bewerk signaal
  n0          0
  n1          1000
  Bewerking   F1[n] = sin(w*n)

!--------------------------------------------
! buffer F2: sinustoon uitstrekken en nul-samples invoegen
!--------------------------------------------
Bewerk signaal
  n0          0
  n1          4000
  Bewerking   F2[n] = 0,007  ! maak van "nul-samples" zichtbaar
Bewerk signaal
  n0          0
  n1          1000
  Bewerking   F2[10*n] = F1[n]

!--------------------------------------------
! teken twee grafieken: sinus en sinus-strek
!--------------------------------------------
Wis Grafiekvenster
Grafische instellingen
  Afb       1           | 2
  Txfac     10          | 10
  Tyfac     200         | 200
  Stap      1           | 1
  Vanaf     0           | 0
  Aslang    1000        | 1000
  Asx       30          | 30
  Asy       300         | 730
  Modus     lijn        | lijn
  Kleur     zwart       | zwart
  Pendikte  3           | 3
  As        tijd        | tijd

Grafiek van F-buffer(s) F1 F2

!--------------------------------------------
! Sla twee grafieken op onder naam: Sinustoon_10kHz_1
!--------------------------------------------
Bitmap opslaan
  Naam                    Sinustoon_10kHz
  nummer                  1
  X1; Y1 (links boven)    0; 80
  X2; Y2 (rechts onder)   1100; 960
 
wacht even, hebben we het hier over zero-crossings, polynomials?

Nou in elk geval over zero padding. Zie https://www.synthforum.nl/forums/showpost.php?p=1775775&postcount=55.

zero-crossing: nul-doorgang: elke overschrijding van de horizontale as.
Nuldoorgangen doen zich bijv. bij een simpele sinus twee maal per periode voor.

Polynomial: veelterm.
Een filter kan worden gerepresenteerd door een veelterm ja, maar dan altijd in het frequentiedomein (of beter: z-domein). En jazeker, die Gains in https://www.synthforum.nl/forums/showpost.php?p=1774159&postcount=34 zijn niets anders dan filtercoefficienten, maar dat heb ik daar nog niet genoemd. Die hele draad gaat uiteraard over filtering en Fourier...;)
 
spectrum gatensinus

spectrum gatensinus

https://www.synthforum.nl/forums/showpost.php?p=1789901&postcount=170

Ik zat wat te klungelen met dat gatensinusspectrum, maar hier de code die bewijst dat alle spectraallijnen inderdaad even lang zijn.

Code:
!***************************
! Preset Spectrum Gatensinus
!***************************

Declareer Amp; Freq; w; Ndft; BinFreq

Wis buffers
  Wis buffer (F1...F32, S1, S2, S3)   F1 | F2 | F3 | F4 
Wis buffers
  Wis buffer (F1...F32, S1, S2, S3)   F5 | F6 | F7| F8
Wis buffers
  Wis buffer (F1...F32, S1, S2, S3)   F9 | F10| F11

Naam Buffer F1 = Sinus
Naam Buffer F2 = Gaten
Naam Buffer F3 = GatenSpectrum

Freq = 10000
w    = 2*pi*Freq*Ts

!-----------------------------------------------------
! Sinustoon 10 kHz in F1:
!-----------------------------------------------------
Bewerk signaal
  n0          0
  n1          1000
  Bewerking   Sinus[n] = cos(w*n)

!-----------------------------------------------------
! upsampling buffer F2:
!-----------------------------------------------------
Bewerk signaal
  n0          0
  n1          1000
  Bewerking   Gaten[10*n] = Sinus[n]

!-----------------------------------------------------
! Amplitudespectrum van Gatensinus:
!-----------------------------------------------------
! De frequentiereeks van de gatensinus is: 1000, 3410, 5410, 
! 7820, 9820, 12230, 14230, 16640, 18640, 21050. 
! Dat zijn allemaal veelvouden(en dus harmonischen) 
! van grondtoon 10 Hz.

BinFreq = 10
Ndft    = Fs/BinFreq

(I)DFT
  In Re                    Gaten[0]
  In Im                    nvt
  Out Re                   F11[0]
  Out Im                   F12[0]
  Amp                      GatenSpectrum[0]
  Fase                     F10[0]
  Venster (in smp)         Ndft
  Aantal spectraallijnen   Ndft
  DFT of IDFT              DFT

Grafische instellingen
  Afb       1
  Txfac     1
  Tyfac     1000
  Stap      1
  Vanaf     0
  Aslang    2300
  Asx       30
  Asy       400
  Modus     lijn
  Kleur     zwart
  Pendikte  1
  As        tijd

Wis Grafiekvenster
Grafiek van F-buffer(s) GatenSpectrum

Amplitudo, Maximum, Minimum, Som, RMS
  Buffer   GatenSpectrum[0]
  Aantal   Ndft/2
Print Minimum
Print Maximum

Piek detector
  Inputbuffer             GatenSpectrum[0]
  PiekBufX                F4[0]
  PiekBufY                F5[0]
  Aantal samples          Ndft/2
  M (aantal max-pieken)   Ndft/2

Geef indices zoek-interval
  Zoekbuffer                F5[0]
  indices naar Doelbuffer   F7[0]
  zoek x in a <= x <= b     0,001; 10*Maximum
  aantal                    Ndft/2

Print Indices

!-----------------------------------------------------
! F8[] = frequenties van de pieken
FOR k = 0 TO Indices-1
  F8[k] =  BinFreq * F4[F7[k]]
NEXT k

!-----------------------------------------------------
! F9[] = amplitudes van de pieken
FOR k = 0 TO Indices-1
  F9[k] =  F5[F7[k]]
NEXT k

!-----------------------------------------------------
Buffergetallen in tekstvorm
  Vanaf Buffer[index]           F8[0]
  Aantal Buffers (kolommen)     2
  Aantal regels                 Indices
  aantal cijfers achter komma   5

!-----------------------------------------------------

De output is zowel grafisch als numeriek. In memo verschijnt een lijstje met de gatensinus-frequenties ( 1000, 3410, 5410, ! 7820, 9820, 12230, 14230, 16640, 18640, 21050. en hun bijbehorende amplitudes (allemaal 0,05).
 
Hier is een Kyma convolution txt door Kurt Hebel:

| impulseFile sf impulseResponse impulseLength sourceFile sampleCount inBuffer destFile outBuffer |

"Ask for the impulse response file and read the samples into RAM. The samples file must be mono."
impulseFile :=
HostDriverInterface
getFileWithPrompt: 'Select the impulse response file:'
fileTypes: (Array with: HostDriverInterface sampleFileType)
ifCancel: [^ self]. sf := SamplesFile for: impulseFile ifAbsent: [^ self].
impulseLength := sf sampleFrames.
impulseResponse := sf getSamplesFromMonoWavetableFileStartingAt: 0 length: impulseLength.

"Ask for the file to be convolved." sourceFile :=
HostDriverInterface
getFileWithPrompt: 'Select the source file:'
fileTypes: (Array with: HostDriverInterface sampleFileType)
ifCancel: [^ self].
sf := SamplesFile for: sourceFile ifAbsent: [^ self].
sampleCount := sf sampleFrames. inBuffer :=sf readBuffer.

"Ask for the name of the output file."
destFile := HostDriverInterface
putFileWithPrompt: 'Select the source file:'
initially: sf filename
fileTypes: (Array with: HostDriverInterface sampleFileType)
ifCancel: [^ self].
sf := sf copyForFilename: destFile asFilename.
sf writeHeader. outBuffer := sf writeBuffer.

"Now, convolve. (This processes left channel only.)"
self dialogClass displayStringWithThermometer: 'Now computing convolution...' while: [
| pastInputSamples samplePair progressScale sampleScale |

pastInputSamples := Array new: impulseLength withAll: 0.
samplePair := Array new: 2.
progressScale := 1.0 / sampleCount.
sampleScale := (impulseResponse inject: 0 into: [ :sum :x | sum + x abs]) inverse.

1 to: sampleCount do: [ :x | | sum |
(x bitAnd: 16rFF) = 0 ifTrue: [self dialogClass thermometerSignal raiseRequestWith: x * progressScale].
pastInputSamples replaceFrom: 2 to: impulseLength with: pastInputSamples startingAt: 1.
inBuffer nextSampleInto: samplePair.
pastInputSamples at: 1 put: (samplePair at: 1).
sum := 0.
1 to: impulseLength do: [ :i | sum := (impulseResponse at: i) * (pastInputSamples at: i) + sum].
sum := sum * sampleScale.
outBuffer writeLeftSample: sum rightSample: sum]].

"Close the files, we are done."
inBuffer close.
outBuffer close.
 
De WaveWizard-versie van precies dezelfde functies (geluid en pulsrespons laden en convolveren d.m.v. de FFT) had ik in #524 al gegeven:

Code:
!***********************************************
! Preset galm door snelle convolutie pulsrespons
!***********************************************

Declareer Begin_pulsrepons; Begin_galm; ; duur; Galmduur


Begin_pulsrepons = 60*Fs       ! de pulsrespons wordt op spoor S1 en S2 geplaatst op tijdstip 60 sec.
Begin_galm       = 20*Fs       ! de galm-output wordt op spoor S1 en S2 geplaatst op tijdstip 20 sec.
Galmduur         = 121448      ! duur galm-pulsrespons wordt gegeven in Memo na openening wav.
duur             = 14 * Fs     ! duur van weerbericht.wav

Wis buffers
  Wis buffer (F1...F32, S1, S2, S3)    S1  |  S2  |  S3

!---------------------------------------------------------
! Open twee wav-bestanden en plaats ze op spoor S1 en S2:
!---------------------------------------------------------
Open WAV
  WAV naam   weerbericht.wav
  buffer     S1[0]

Open WAV
  WAV naam   Pulsrespons Surround.wav
  buffer     S1[Begin_pulsrepons]

!----------------------------------------
! Voeg galm toe d.m.v. snelle convolutie
!-----------------------------------------
! galm op spoor S1:
Snelle Convolutie (FFT en OLA)
  Input                   S1[0]
  Output                  S1[Begin_galm]
  coef's                  S1[Begin_pulsrepons]
  M                       Galmduur
  Duur (ook 'sec')        duur
  Additief ('j' of 'n')   n
  Schaalfactor coef's     10

! galm op spoor S2:
Snelle Convolutie (FFT en OLA)
  Input                   S2[0]
  Output                  S2[Begin_galm]
  coef's                  S2[Begin_pulsrepons]
  M                       Galmduur
  Duur (ook 'sec')        duur
  Additief ('j' of 'n')   n
  Schaalfactor coef's     10
 
Ik dacht dat je het misschien leuk zou vinden om de Kyma representatie ervan te zien.

Zeker! Dank daarvoor! :okdan:

Ik had de WaveWizard-versie in de bijlage van #524 gestopt, met nog wat code voor de analyse van de mate van stereo. Daarom hierboven nog eens de eigenlijk convolutie-code, zodat vergelijking met Kyma wat makkelijker wordt.
 
In de draad "Het einde van het keyboard" poste Roland (#100) (https://www.synthforum.nl/forums/showpost.php?p=1798412&postcount=100) een YouTube filmpje van een compositie van Ligeti: Poème Symphonique For 100 Metronomes.

Ik heb het geluid geanalyseerd en gesynthetiseerd met WaveWizard.

De analyse van de echte, akoestische metronomen die in het filmpje worden gebruikt zijn natuurlijk niet-ideaal en produceren ruis, dat kun je niet alleen beredeneren, maar het blijkt ook uit de computeranalyse.

In de synthese ben ik uitgegaan van ideale metronomen, d.w.z. met perfect periodiek tikken.

Hier het geluid van honderd perfect periodieke computermetronomen.
 

Attachments

  • 100 Metronomen.mp3
    2,3 MB · Bekeken: 145
Back
Top