WaveWizard

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.
WaveWizard-input-functies graag ?
 
WaveWizard-input-functies graag ?

Per lus wordt een random metronoom tempo gekozen en worden overeenkomstige pulsen op spoor 1 gezet. Nadat alle pulsen van alle 100 metronoomlussen zijn berekend, worden drie resonanties toegevoegd, die ongeveer overeenkomen met die van een echte metronoom; de resonantiefrequenties zijn 800, 1200 en 1730 Hz. Ik heb die zo maar in de gauwigheid een beetje geschat; kan natuurlijk veel realistischer.

De output spoor S2 wordt geschaald en gekopieerd naar spoor S1. Tot slot de code die automatisch een wav aanmaakt en opslaat in dezelfde map als WaveWizard.exe.

In memo worden de 100 random BPM-waarden van de metronomen uitgeprint. (ze kunnen ook opgeslagen worden, wat belangrijk is voor latere analyse. Die analyse dient als voorstudie van de analyse van de akoestische opname van het YouTube filmpje, om aan te tonen dat de echte, akoestische metronomen licht chaotisch zijn (zoals uit verschillende tests inmiddels al is gebleken - daarover later meer).

Code:
!**********************
! Preset 100 Metronomen
!**********************

Declareer duur; t; AantalMetronomen
duur = 60*Fs
AantalMetronomen = 100

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

! het metroombereik loopt van 40 - 240 BPM ofwel 0,667 - 4 Hz.
! 0,667 Hz = 66117 smp; 4 Hz = 11019 smp.

FOR k = 1 TO AantalMetronomen
  Print AantalMetronomen - k
  t = random(11019; 66117)
  F3[k] = t
  Bewerk signaal
    n0          0
    n1          duur/t
    Bewerking   S1[n*t] = S1[n*t] + 1000
NEXT k

Resofilter
  Input                             S1[5]
  Output                            S2[0]
  Gain                              3
  ResoFreq                          800
  bandbreedte                       100
  duur                              duur
  additief ('j' of 'n')             n
  filtercoef's in Memo ('j' of 'n') j
Resofilter
  Input                             S1[5]
  Output                            S2[0]
  Gain                              2
  ResoFreq                          1200
  bandbreedte                       200
  duur                              duur
  additief ('j' of 'n')             j
  filtercoef's in Memo ('j' of 'n') j
Resofilter
  Input                             S1[5]
  Output                            S2[0]
  Gain                              1
  ResoFreq                          1730
  bandbreedte                       400
  duur                              duur
  additief ('j' of 'n')             j
  filtercoef's in Memo ('j' of 'n') j

Amplitudo, Maximum, Minimum, Som, RMS
  Buffer S2[0]
  Aantal duur

x = 24000 / Amplitudo
Bewerk signaal
  n0        0
  n1        duur
  Bewerking S2[n] = x*S2[n]
Bewerk signaal
  n0        0
  n1        duur
  Bewerking S1[n] = S2[n]

FOR k = 1 TO AantalMetronomen
  Print 60 / (F3[k]/Fs)          ! BPM
NEXT k

WAV Opslaan
  WAV Naam 100 Metronomen.wav
  bron     S1[0]
  duur     duur
 
Laatst gewijzigd:
Analyzers: nog vaak in de schaduw...

Analyzers: nog vaak in de schaduw...

Wat mij opvalt in veel audiosoftware is dat je meestal wel een boel geavanceerde synthese-functies aantreft, maar relatief weinig analyzers. Voor allerlei sounddesign- en klanksynthese-doeleinden wil je graag eigenschappen van bestaande geluiden gebruiken om processen mee aan te sturen. Je hebt dan analyzers nodig om die eigenschappen boven tafel te krijgen. Het bekendste voorbeeld van signaalanalyse is natuurlijk het spectrum: de fameuze FFT.

De reden van dat gebrek aan analyzers is, denk ik, dat eigenlijk alleen code-software (zoals WaveWizard, Synthesis ToolKit, SuperCollider, CSound, en natuurlijk reuzen zoals Matlab) over de goede "infrastructuur" beschikken om analyse-data ook daadwerkelijk rechtstreeks toe te passen in synthese-functies. Maar toch. Kan eigenlijk geen reden bedenken waarom Max of Kyma of Reaktor ze niet op een zinvolle wijze zouden kunnen inpassen in hun modulaire opzet. Misschien gebeurt dat ook wel...

Heel essentieel en universeel zijn twee nieuwe WaveWizard analysefuncties die ik in #631 al had gebruikt, maar nog niet besproken:

(1) Piek detector
(2) Geef indices zoek-interval

Zal daar een paar toepassingen van geven binnenkort.:yamaha:
 
Analyzer "Geef indices zoek-interval"

Analyzer "Geef indices zoek-interval"

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

F1[0] = 5
F1[1] = 19
F1[2] = 2*pi
F1[3] = -6
F1[4] = 11

Geef indices zoek-interval
  Zoekbuffer                F1[0]
  indices naar Doelbuffer   F2[0]
  zoek x in a <= x <= b     6; 12
  aantal                    13

Print Indices

FOR k = 0 TO Indices-1
  Print F2[k]
NEXT k

FOR k = 0 TO Indices-1
  Print F1[F2[k]]
NEXT k

Deze functie zoekt in getalbuffer F1 de eerste N getallen tussen (en incl.) 4 en 12.
Van alle gevonden getallen wordt de index ("adres", rangnummer) opgeslagen in buffer F2.
De functie heeft een return variabele "Indices" die vertelt hoeveel getallen zijn gevonden.

Hieronder het resultaat in Memo:

Code:
Geef indices zoek-interval: Indices = 2

  F2[k] = 2
  F2[k] = 4

  F1[F2[k]] = 6,28318530717959
  F1[F2[k]] = 11

Enorm saaie functie natuurlijk, maar met enorm boeiende, onverwachte toepassingen.
Binnenkort een paar voorbeelden.
 
Voorbeeld echo-tijd berekening

Voorbeeld echo-tijd berekening

Hier een opgave uit de (nog te verschijnen) tekst "Een echo-effect is een kamfilter", voor leerlingen VWO die de NLT-module Sound Design doen:

Een (digitaal) signaal bestaat uit een mix van twee sinusgolven. Die zijn precies even hard en hebben frequenties van 105 Hz en 210 Hz. Door een echo toe te voegen wil je bereiken dat de hoge sinus twee keer zo hard klinkt als de lage.
(a) Welke echo-tijd heb je daar voor nodig?
(b) Schrijf code waarmee je dit echo-effect kunt uitvoeren.
(c) Hoe kun je met de computer controleren of je code het gewenste resultaat geeft? Gebruik twee methodes.

Om de juiste echo-tijd te vinden moet een vergelijking worden opgesteld die alleen maar numeriek (dus met de computer) kan worden opgelost. Dat doe je door de computer de grafiek van een functie te laten tekenen die zo is gedefinieerd dat de oplossing van de vergelijking bestaat uit de verzameling van punten waarin de grafiek de horizontale as snijdt (de nulpunten).

Op het oog zie je die punten direct en je kunt hun positie op de horizontale as ook wel redelijk schatten. Maar dat is iets anders dan de nulpunten met grote nauwkeurigheid automatisch vinden en opslaan! En dat laatste doe je in WaveWizard met de hierboven besproken functie "Geef indices zoek-interval".

De opgave geeft leerlingen een preset met onderstaand code-voorbeeld voor het vinden van de nulpunten van een voorbeeldfunctie. Die code kunnen ze aanpassen door een andere formule in te voeren en zo de juiste echo-tijd te vinden.

De voorbeeldpreset: voor welke waarde(n?) van x is x*log(x) - x^0,5 = 0?
De computer vindt één waarde: x = 3,4526548.
De nauwkeurigheid van het antwoord is regelbaar door het zoek-interval kleiner te maken.

Hieronder de grafiek van de functie f(x) = x*log(x) - x^0,5. Het nulpunt wordt aangegeven door een stip waarvan de x-coördinaat wordt gespecificeerd als de uitkomst van de "Geef indices zoek-interval". dat is dus die waarde x = 3,4526548.

Conclusie. Hier wordt een echo-effect gerealiseerd door een analyzer in de code op te nemen die eerst de juiste instelling van het effect (hier de echo-tijd) uitrekent. In dit voorbeeld bekijkt de analyzer een wiskundige functie en leidt daar de waarde van een instelling uit af. Veel vaker komt het voor dat de analyzer gesampelde geluiden bestudeert en verwerkt. Ook daarvan zal ik nog voorbeelden geven.

Code:
!**************************************
! Preset vergelijking numeriek oplossen
!**************************************

!---------------------------------------------------------
! Voor welke waarde van x is x*log(x) - x^0,5 = 0 ?
!---------------------------------------------------------

Declareer x1; x2; s; domein; N

Naam Buffer F1 = X
Naam Buffer F2 = f

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

x1 = 0,001 ! linker domeingrens
x2 = 10    ! rechter domeingrens
N  = 10^4  ! aantal functiewaarden, maximaal 140.000

!---------------------------------------------------------
! het domein [x1,x2] is een lineaire functie X[n] = s*n+x1
! van het aantal functiewaarden, x1 en x2:
!---------------------------------------------------------
domein = x2 - x1
s      = domein/N          ! stapgrootte

Bewerk signaal
  n0          0
  n1          N
  Bewerking   X[n] = s*n + x1

!---------------------------------------------------------
! Evalueer x*log(x) - x^0,5 met de x-waarden van X[n]:
!---------------------------------------------------------
Bewerk signaal
  n0          0
  n1          N
  Bewerking   f[n] = X[n]*log(X[n]) - X[n]^0,5

!---------------------------------------------------------
! Zoek de nulpunten van f[X[n]]:
!---------------------------------------------------------
Geef indices zoek-interval
  Zoekbuffer                f[0]
  indices naar Doelbuffer   F3[0]
  zoek x in a <= x <= b     -0,0001; 0,0001
  aantal                    N

! Melding in Memo:
! 'Geef indices zoek-interval: Indices = 1'.
! 'Indices' is een systeemvariabele waarin het
! aantal gevonden waarden wordt opgeslagen die
! voldoen aan zoekcriterium.
! In dit geval is er 1 functiewaarde gevonden:
!   [COLOR="Red"]X[F3[0]][/COLOR] = 3,4526548                 gevonden x-waarde
!   f[F3[0]] = -7,49841879361668E-5      gevonden "nulpunt"

!---------------------------------------------------------
! Print de nulpunt-candidaten van f[X[n]:
!---------------------------------------------------------
FOR k = 0 TO Indices - 1
  Print X[F3[k]]          ! x-waarden
  Print f[F3[k]]          ! f(x)-waarden
NEXT k

!---------------------------------------------------------
Wis Grafiekvenster
Grafiekpapier
  Linkerbovenhoek x; y (pix)   0; 0
  Breedte; Hoogte (pix)        1200; 600
  Domein x1; x2                x1; x2
  Bereik y1; y2                -2; 7
  Rooster x; y                 1; 1
Pen
  Kleur   rood
  Dikte   3
  Modus   continu
Grafiek van functie met 1 variabele
  f[x]     x*log(x) - x^0,5
  Domein   x1; x2
  Modus    continu
  Stap     s

Pen
  Kleur   zwart
  Dikte   8
  Modus   continu

Punt   [COLOR="Red"]X[F3[0]][/COLOR]; 0

attachment.php
 

Attachments

  • Grafiek vergelijking numeriek oplossen_0.jpg
    Grafiek vergelijking numeriek oplossen_0.jpg
    31,1 KB · Bekeken: 146
Ligeti's 100 metronomen als ritme dictee

Ligeti's 100 metronomen als ritme dictee

In #640 - #642 de simulatie van honderd perfect regelmatig tikkende metronomen. Een heel ander probleem is proberen om op basis van het geluidsspoor van het YouTube-filmpje de tijdstippen van de tikken te registreren. Een bizar ritme dictee! Is dat eigenlijk wel mogelijk? Zeker in 't begin, als de veren van alle metronomen nog helemaal opgewonden zijn, hoor je een soort gedruis in plaats van of naast duidelijk onderscheiden tikken. Waar ligt voor de computer de grens tussen ruis en waarneembare tikken? Met welke (on)nauwkeurigheid kun je de tijdstippen van de tikken vastleggen?

Je komt voor nog meer lastige vragen te staan: is het geluid van een metronoom-tik ook echt een afzonderlijke puls? Dat blijkt niet 't geval: elke tik is een kort trillinkje met een snel dempende golfvorm. De metronomen zijn allemaal van hetzelfde type en hebben dus ook ongeveer, maar niet precies dezelfde golfvorm; twee tikken die bijna samenvallen kunnen elkaar ook gedeeltelijk uitdoven en een kleinere of gelijke amplitude hebben als de afzonderlijke tikken. Bovendien staan de metronomen in een galmende ruimte; de galm voegt een zeer complexe vervorming toe aan de golf, een vervorming die voor elke metronoom weer anders is, want elke metronoom staat op een iets andere plaats en elke plaats in een zaal geeft een ander reflectiepatroon.

Ik werk aan een oplossing met WaveWizard die gebruik maakt van de twee analyzers uit #644. Binnenkort de resultaten en de code.
 
Zoals je tekening laar zien, werkt het Schroeder-algo met een All Pass filter.
Een All Pass filter laat, zoals de term al aangeeft, alle frequenties door, zonder ze te versterken of verzwakken. De karakteristiek ervan ziet er dus uit als een kaarsrechte, horizontale lijn.
Een Kamfilter daarentegen heeft een karakteristiek die eruit ziet als... je raadt het nooit, een kam.
Er bestaat dus een nogal drastisch verschil tussen beiden...

Waar het Schroeder allemaal om te doen is, is galm maken. Hij wil dat bereiken door een aantal echo-effecten in serie te zetten. Maar een echo heeft de vervelende eigenschap dat het een kamfilter is en dus een ware slachting aanricht in de spectrale structuur van het geluid. Dat is die typische hiss die je hoort als je een geluid door een delay haalt. Zet je een boel delays achter elkaar, dan maak je spectraal gehakt van het oorspronkelijke geluid. En dat is natuurlijk wat Schroeder niet ziet zitten. Hij wil galm zonder gehakt.

De oplossing van Schroeder is de combinatie van twee soorten echo: een echo-feedforward en een echo-feedback met dezelfde echo-tijd kunnen immers samen een All Pass opleveren. Dat komt omdat een feedback-echo een kam-effect geeft met resonanties (pieken in het spectrum) en een feedforward een kam-effect met antiresonanties (dips in het spectrum). Als de echotijden en gains van beiden gelijk zijn, dan vallen de pieken van de één samen met de dips van de ander en heffen ze elkaars desastreuze werking op. Zo krijg je een All Pass die een echo geeft! Zet er daar een aantal van achter elkaar, in serie, en je krijgt... Schroeder-galm! :kroon:
 
Hier het metronoom dictee.
De preset analyseert het YouTube audiosignaal en stelt de tijdstippen vast van pieken binnen een bepaald amplitudebereik. Eerst wordt een (erg lange) lijst gemaakt van alle uitwijkingswaarden binnen het opgegeven amplitudebereik. Dat gebeurt met 'Geef indices zoek-interval'. Vervolgens wordt met 'Piek detector' binnen die lijst gezocht naar de pieken. De tijdstippen van de pieken worden opgeslagen in een tweede lijst. Ik ben ervan uitgegaan dat je deze pieken mag identificeren met de triggermomenten van de metronoomtikken. Op basis van deze triggerlijst maak ik een pulssignaal dat gefilterd wordt met drie Butterworth bandddoorlaatfilters die de klank van de metronoomkast enigszins benaderen (dat kan natuurlijk veel beter). Details in de code hieronder.
attachment.php



Code:
!********************************
! Preset Ligeti Metronomen dictee
!********************************

Declareer Marge

Marge = 4500

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

!-----------------------------------------------------
! Open geluidsbestand 'Ligeti 100 Metronomen.wav'.
! de functie heeft als return variabele 'WAV_lengte' 
! die het aantal sample-getallen aangeeft.

!-----------------------------------------------------
Open WAV
  WAV naam Ligeti 100 Metronomen.wav
  vanaf    0
  duur     ?
  buffer   S1[0]

!-----------------------------------------------------
! Bereken de Amplitudo, Maximum, Minimum, Som en 
! RMS-waarde (Root-Mean-Square). 
! Sla die op in de 5 gelijknamige return variabelen. 
!-----------------------------------------------------
Amplitudo, Maximum, Minimum, Som, RMS
  Buffer S1[0]
  Aantal WAV_lengte

!-----------------------------------------------------
! Registreer de tijdstippen van alle uitwijkingwaarden
! tussen Amplitudo en Amplitudo-Marge:
!-----------------------------------------------------
Geef indices zoek-interval
  Zoekbuffer              S1[150*Fs]
  indices naar Doelbuffer F1[0]
  zoek x in a <= x <= b   Amplitudo-Marge; Amplitudo
  aantal                  WAV_lengte

Print Indices

!-----------------------------------------------------
! Maak op spoor S3 een signaal aan dat alleen de 
! geselecteerde uitwijkingswaarden bevat:
!-----------------------------------------------------
Bewerk signaal
  n0        0
  n1        Indices - 1
  Bewerking S3[F1[n]] = S1[F1[n]]

!-----------------------------------------------------
! Registreer de pieken van spoor S3
!-----------------------------------------------------
Piek detector
  Inputbuffer           S3[0]
  PiekBufX              F2[0]
  PiekBufY              F3[0]
  Aantal samples        WAV_lengte
  M (aantal max-pieken) nvt
Print AantalPieken

!-----------------------------------------------------
! Maak op spoor S2 een pulssignaal dat bestaat uit
! alleen de pieken van spoor S3. 
!-----------------------------------------------------
Bewerk signaal
  n0        0
  n1        AantalPieken - 1
  Bewerking S2[F2[n]] = F3[n]

!-----------------------------------------------------
! Het resultaat op spoor S2 zijn (een schatting van) 
! de begintijdstippen van de metronoomtikken. 
! Filter S2 om de pulsen een "metronoomklank" te geven
!-----------------------------------------------------
Butterworth Banddoorlaat
  Input                  S2[0]
  Output                 S2[0]
  Centrumfrequentie (Hz) 1200
  Bandbreedte (Hz)       200
  Duur (ook 'sec')       WAV_lengte
  Flanksteilheid (< 50)  1
  Volume (0...100)       2
  Additief ('j' of 'n')  n
Butterworth Banddoorlaat
  Input                  S2[0]
  Output                 S2[0]
  Centrumfrequentie (Hz) 3500
  Bandbreedte (Hz)       400
  Duur (ook 'sec')       WAV_lengte
  Flanksteilheid (< 50)  1
  Volume (0...100)       1
  Additief ('j' of 'n')  j
Butterworth Banddoorlaat
  Input                  S2[0]
  Output                 S2[0]
  Centrumfrequentie (Hz) 7100
  Bandbreedte (Hz)       700
  Duur (ook 'sec')       WAV_lengte
  Flanksteilheid (< 50)  1
  Volume (0...100)       0,5
  Additief ('j' of 'n')  j

Het linker spoor van de mp3 is het originele YouTube audiosignaal. Het rechter spoor is het dictee. Ik heb er niet naar gestreefd om de klank van het origineel zo goed mogelijk na te doen. Het gaat me hier vooral om de vraag of je op deze manier de triggermomenten kunt vinden, zodat ze samenvallen met die in het origineel.
 

Attachments

  • 100 Metronomen muziekdictee.mp3
    900 KB · Bekeken: 152
  • Vergelijk origineel en reconstructie.jpg
    Vergelijk origineel en reconstructie.jpg
    19 KB · Bekeken: 152
Last edited by a moderator:
Thx. Het moeilijkste moet nog komen: een schatting van de BPM-waarden waarop de 100 metronomen waren ingesteld. Ook hier komen die twee analyzers om de hoek kijken. Maar ik weet nog niet precies hoe ik het ga aanpakken :frons:
 
Als het lukt om de BPM's te vinden, dan kun je vervolgens ook beter de kwaliteit van het ritme-dictee hierboven inschatten, immers de metronoomtikken zijn (quasi-)periodiek.
Dus verschillende analyzers kunnen elkaar feedback geven en elkaars kwaliteit/effectiviteit verhogen.
Zo gaan we langzaam richting kunstmatige intelligentie, een trend die overal, ook in audio, steeds duidelijker wordt.
 
Een lastige kwestie ja, en een fundamenteel signaalverwerkingsprobleem. Die 100 metronomen zijn natuurlijk gewoon 100 LFO's met random ingestelde frequenties. Het gaat dus om een frequentie-analyse. In dit geval 100 frequenties binnen 2,5 octaaf. De FFT zal dan een spectrum geven waarin een groot deel van de boventonen van de langzaam tikkende metronomen verspreid liggen in het gebied van de sneller tikkende metronomen. Het spectrum is dus net zo'n zootje als het tijdsignaal. Als het metronoom tik-bereik binnen het octaaf zou liggen, dan was de FFT natuurlijk prima. Maar hier moet zwaarder materieel worden ingevlogen...:P
 
WaveWizard op YouTube en Soundcloud

WaveWizard op YouTube en Soundcloud

WaveWizard op YouTube en Soundcloud

Animaties bij het nieuwe hoofdstuk 8 "Oscillatie en resonantie" op YouTube:

Kanaal: "NLT module Sound Design"

H8 §16 gaat over de modale klanksynthese van snaren, staven en membranen.

Trillingsbeweging van snaar
Klik met rechter muisknop in beeld en selecteer Lus-weergave.
NLT-module Sound Design Hoofdstuk 8, Oscillatie en Resonantie - Intro Complexe Getallen, §16.


Trillend membraan: de eerste 5 cirkelvormige trillingsmodi


SoundCloud

tik tegen metalen staaf:
https://soundcloud.com/rutger-teunissen/staaf-met-vrije-uiteinden

slag tegen cirkelvormig membraan met 58 trillingmodi (boventonen) en frequentieafhankelijke demping:
https://soundcloud.com/rutger-teuni...t-lange-frequentieafhankelijke-dempingstijden
 
Back
Top