Bakgrund
Min äldre bror stötte nyligen på ett nytt intressant programspråk ”Julia” som har influerats av Python, Matlab och många andra programmeringsspråk. Julia har en relativt intuitiv syntax vilket betyder att det är rätt enkelt att lära sig språket då man har använt andra programmeringsspråk. Julia påminner om språket Python men Julia kan vara tiotals gånger snabbare … nästan lika snabbt som kompilerad c-kod trots att Julia är ett tolkat språk med alla de fördelar detta medför (bl.a. enkelt att skriva program stegvis och tista medan man skriver).
Problemet att ur spelad musik har intresserat mig länge men jag har inte kommit mig för att skriva verktyg. Julia råkade nu bli den faktor som gjorde att jag började experimentera med notgenerering för att samtidigt lära mig språket Julia.
Det här kommer antagligen att bli en serie artiklar där olika aspekter av problemet behandlas … och det finns inga garantier för att slutresultatet på riktigt blir användbart.
Existerande hjälpmedel
Tanken är inte att skriva allt som behövs själv utan existerande programkod kommer att användas. Följande program används för närvarande.
- Programmet Audacity används för inspelning. I samband med inspelningen normaliseras ljudfilen till standardamplitud eftersom detta förenklar analysen.
- Julia används för programmeringen och Julia innehåller de FFT (fast fourier transform) rutiner som behövs för att plocka ut toner ur ljudmassan.
- Programmet LilyPond används för att generera noter
Konvertering av ljudfilen till musikaliska toner
Det första programmet extract_notes.jl läser block om 8152 ljudsampel från ljudfilen som är samplad i CD-kvalité d.v.s. 44100 Hz. Ett datablock motsvarar då ungefär 200 ms ljud och den teoretiska upplösningen i spektret som skapas med FFT är ungefär 5 Hz.
Tanken är att analysera hela filen i 200 ms block. blocken/tonerna kan senare kombineras till något som motsvarar verkliga noter men detta är något för framtiden. Det är självklart att inte endast en ton utan en hel serie toner kommer att hittas i varje tonblock eftersom en fiolton innehåller en lång serie övertoner. Hur jag väljer att utnyttja övertonsserierna är också ett problem som lämnas för framtida optimering.
Programmet extract_notes.jl skapar en textfil som innehåller de noter programmet hittade samt amplituden för de olika tonerna (tonstyrkan). Textfilen ser för närvarande inte vacker ut:
Length:605696
Längd i sekunder:13.734603174603174
N ASCIIString[”d'”,”a””,”a”'”,”c”””,”d”””,”?”,”?”,”?”,”?”,”?”,”?”, … ,”?”,”?”,”?”,”?”,”?”]
A [-31.890321498989003,-30.634769023040928,-32.27245706229339,-30.018825559930626,-29.475444684452142,-9999.0,-9999.0, … , -9999.0,-9999.0,-9999.0,-9999.0,-9999.0,-9999.0,-9999.0,-9999.0,-9999.0,-9999.0]
N ASCIIString[”d'”,”d””,”a””,”c”””,”d”””,”?”,”?”,”?”,”?”,”?”,”?”,”?”,”?”,”?”, … , ”?”,”?”,”?”,”?”,”?”,”?”]
o.s.v.
En rad som börjar med ”N” innehåller detekterade noter t.ex. ” d’ ” , ” a” ” . ”?” betyder att ingen not har hittas för denna position i tabellen.
En rad som börjar med ”A” innehåller amplituder. En amplitud med värdet -9999.0 betyder att ingen amplitud finns för denna not.
Notnotationen är den som används i LilyPond.
Generering av noter
För att generera noter behöver vi nu endast plocka ut notvärdena ur tabellen och skriva ut noterna (de harmoniska övertonerna) som ett ackord i LilyPond.
Ett ackord i LilyPond betecknas med:
< not0 not1 not2 … >
Då vi plockar ut noterna får vi:
< d’ a” a”’ c”” d”” >
Vi kan titta på noterna genom att helt enkelt lägga till LilyPond startkod och slutkod så att man får en LilyPondfil som kan kompileras. Jag har skrivit ett separat litet program som läser textfilen ovan och konverterar den till kompilerbar LilyPond-kod. Programmet heter process_notes.jl .
Startkoden är:
\version ”2.16.2”
{
Slutkoden är:
}
Resultatet för melodin ”Gubben noak” blev:
\version ”2.16.2”
{< d’ a” a”’ c”” d”” >
< d’ d” a” c”” d”” >
< d’ d” a” fis”’ a”’ >
< d’ dis’ d” a” fis”’ >
< d’ d” a” a”’ c”” >
< d’ d” a” c”” d”” >
< d’ d” a” c”” d”” >
< d’ d” a” c”” d”” >
< d’ d” a” fis”’ a”’ >
< cis’ d’ d” a” c”” >
< d’ d” a” fis”’ c”” >
< d’ d” a” a”’ c”” >
< d’ d” a” fis”’ a”’ >
< d’ dis’ d” a” a”’ >
< d’ dis’ d” a” a”’ >
< fis’ cis”’ fis”’ cis”” >
< fis’ fis” cis”’ fis”’ cis”” >
< fis’ fis” cis”’ fis”’ cis”” >
< fis’ fis” cis”’ fis”’ cis”” >
< fis’ fis” cis”’ fis”’ cis”” >
< e’ g”’ >
< e’ e” b” g”’ gis”’ >
< e’ e” b” gis”’ b”’ >
< e’ e” b” gis”’ b”’ >
< dis’ e’ e” b” g”’ >
< e’ e” b” gis”’ b”’ >
< e’ e” b” gis”’ b”’ >
< e’ e” b” gis”’ b”’ >
< e’ e” b” e”’ gis”’ >
< dis’ e’ e” b” gis”’ >
< e’ e” b” gis”’ b”’ >
< e’ e” b” gis”’ b”’ >
< e’ e” b” gis”’ b”’ >
< e’ e” b” gis”’ b”’ >
< g’ d”’ g”’ b”’ d”” >
< g’ d”’ g”’ b”’ d”” >
< g’ d”’ g”’ b”’ d”” >
< g’ d”’ g”’ b”’ d”” >
< fis’ g’ cis”’ >
< fis’ cis”’ fis”’ cis”” >
< fis’ fis” cis”’ fis”’ ais”’ >
< fis’ cis”’ fis”’ ais”’ cis”” >
< fis’ cis”’ fis”’ cis”” >
< fis’ fis” cis”’ fis”’ ais”’ >
< fis’ fis” cis”’ fis”’ ais”’ >
< fis’ fis” cis”’ fis”’ ais”’ >
< fis’ fis” cis”’ fis”’ ais”’ >
< fis’ cis”’ cis”” >
< e’ e” gis”’ b”’ >
< e’ e” b” gis”’ b”’ >
< e’ e” b” gis”’ b”’ >
< e’ e” b” gis”’ b”’ >
< e’ e” b” gis”’ b”’ >
< e’ e” gis”’ b”’ >
< e’ e” gis”’ b”’ cis”” >
< e’ e” gis”’ b”’ cis”” >
< e’ e” gis”’ b”’ cis”” >
< e’ e” gis”’ b”’ cis”” >
< cis’ d’ >
< d’ d” a” c”” d”” >
< d’ d” a” c”” d”” >
< d’ d” a” c”” d”” >
< d’ d” a” c”” d”” >
< d’ d” a” c”” d”” >
< d’ d” a” c”” d”” >
< d’ d” a” c”” d”” >
< d’ d” a” c”” d”” >
< d’ d” a” c”” d”” >
< d’ a” >
}
Den här filen kan nu LilyPond processa:
lilypond mellanresultat.ly
Resultatet blir en pdf-fil som heter mellanresultat.pdf .
Mängden av toner är en följd av att en fiolton är mycket övertonsrik och spektret således inte innehåller endast en ton utan en mycket lång rad harmoniska och icke harmoniska övertoner.
Då man betraktar bilden så ser man en hel del dubletter som ligger på ett halvt tonstegs avstånd från varandra. Detta betyder inte att tonen är skärande dissonant utan på att ifrågavarande ton är relativt kraftig och spektraltoppen relativt bred. Resultatet är att analysprogrammet kommer att få flera träffar vid en ton. Frågan blir då hur man bäst filtrerar bort de oönskade tonerna?
Svaret på frågan får vila till nästa artikel 🙂 .
Etiketter: fast fourier transform, FFT, notgenerering
Kommentera