Bruke Python til ? manipulere og spille av lyd
L?ringsm?l denne uken
- Kjenne til innlesing fra og utskrift til fil, inkludert organisering av informasjon innad p? linjer
- Kunne bruke filer, l?kker, samlinger og funksjoner for ? l?se mer sammensatte problemer
Denne uken skal vi jobbe med lyd i Python. Vi skal se at lyd egentlig bare er b?lger, og at vi enkelt kan representere slike b?lger ved hjelp av en liste (der hvert element representerer b?lgeh?yden p? et gitt tidsrom).
For ? gj?re denne innleveringen trenger du ? ha numpy
og simpleaudio
installert p? pc-en din.
Installere bibliotekene vi trenger
Denne uken trenger vi noen biblioteker som ikke er standard i Python:
- Simpleaudio
- NumPy
- Matplotlib (Ikke helt n?dvendig, men nyttig p? den valgfrie oppgaven i obligen)
Linkene over inneholder instrukser for ? installere disse bibliotekene, og det b?r g? greit ? installere disse b?de p? Windows, Mac og Linux gitt at du har pip installert f?rst.
Hvis du har Python3 installert slik at du vanligvis kj?rer python3 program.py
i terminalen n?r du kj?rer Python-programmer, har du sannsynligvis ogs? pip tilgjengelig, og kan installere en pakke slik:
# Installer simpleaudio ved ? skrive dette i terminalen:
python3 -m pip install simpleaudio
# Tilsvarende for numpy:
python3 -m pip install numpy
# Tilsvarende for matplotlib:
python3 -m pip install matplotlib
NB: Noen ganger (kanskje bare p? linux?) kan det v?re n?dvendig med sudo f?rst, alts? sudo python3 -m pip install ...
NB 2: Hvis du kj?rer Python3 med kommandoen python
, s? m? du pytte ut python3
med python
i instruksene over.
NB 3: Hvis du er vant med ? installere pakker via Conda, skal det g? fint som alternativ til pip.
Hvis installasjonene fungerer skal du kunne lage en python-fil med disse tre linjene og kj?re den uten ? f? noen feilmeldinger:
import numpy
import simpleaudio
import matplotlib
Hvis du st?r fast, send gjerne en e-post til ivargry@ifi.uio.no. Beskriv hva du har pr?vd og hvor du st?r fast.
Kort introduksjon
- Lyd er variasjoner i trykket i luften (eller massen som lyden beveger seg gjennom), og kan tenkes p? som b?ler. I gruppetimen kommer vi til ? g? litt n?rmere inn p? dette.
- N?r lyd treffer ?ret ditt merker du disse vibrasjonene. I et gitt tidsrom er det et visst trykk mot ?ret (eller mot en mikrofon), og vi kan representere dette trykket. Lyd over tid kan derfor representeres som en sekvens av slike verdier.
- N?r man representerer lyd p? en datamaskin bruker man f. eks 44100 slike verdier i l?pet av et sekund.
- Lister i Python fungerer bra til ? representere disse verdiene.
Bruke simpleaudio i Python
Hvis du har f?tt til ? installere simpleaudio og NumPy ved ? f?lge instruksene over, er du klar for denne ukens opplegg.
For ? gj?re ting enklere for oss, ?nsker vi ? ha en funksjon som kan ta en liste som parameter og spille av lyden
som den listen representerer. Dette krever noen kall til numpy (for ? omgj?re listen til bytes som maskinen kan spilles av)
og til simpleaudio. Lag en fil lyd.py
hvor du starter med denne koden:
import simpleaudio
import numpy as np
def spill_lyd(lydliste):
lyd = np.array(lydliste).astype(np.int16)
lydobjekt = simpleaudio.play_buffer(lyd, 1, 2, 44100)
lydobjekt.wait_done()
I kallet til simpleaudio.play_buffer
spesifiserer vi at lyden v?r har "sample-rate" 44100, som betyr at
vi har 44100 verdier (samples) i sekundet. Simpleaudio vil da prosessere og spille av listen vi sender inn i en slik
hastighet at det blir spilt av 44100 verdier i sekundet.
Teste ut simpleaudio med st?y
Vi lager en funksjon tilfeldig_lyd(antall_sekunder)
som lager en lyd som skal vare i antall_sekunder
der hver lyd-verdi
er et tilfeldig tall mellom 0 og 32000. Funksjonen skal lage returnere en liste som representerer lyden.
PS: En lyd som skal vare i et sekund m? ha 44100 verdier, en lyd som skal vare i 2 sekunder m? ha det dobbelte av det, osv.
# Legg denne linjen ?verst i filen
from random import randint
def tilfeldig_lyd(antall_sekunder):
lyd = []
for i in range(44100 * antall_sekunder):
lyd.append(randint(0, 32767))
return lyd
spill_lyd(tilfeldig_lyd(4))
OBS! Det kan v?re lurt ? skru ned volumet en del f?r man spiller av disse lydene.
Oppgave: Lag en funksjon som returnerer en lyd (liste) der de f?rste 50 verdiene er 0, de neste 50 verdiene er 32000, de neste 50 er 0, osv ... Hvordan h?res lyden ut?
Spille rene toner
Lyden vi lagde i forrige oppgave ser omtrent slik ut hvis vi hadde plottet den som en graf:
Lyden er faktisk en ren A (i musikkverden). Hvis du spiller en A p? en gitar, vil strengen vibrere 440 ganger i sekundet (440 b?lgetopper/daler i sekundet). Det har lyden du lagde ogs?.
Lyden du lagde h?res derimot litt hakkete ut. Det er fordi det ikke er helt naturlige b?lger (som du ser p? plottet).
Oppgave: Lag en funksjon lyd_trekant(antall_sekunder)
som returnerer en lyd som ser slik ut:
H?res denne lyden bedre ut enn den "firkantede"?
Enda bedre lyd (perfekt sinus-kurve)
Den "trekantede" lyden var mer behagelig ? h?re p? enn den firkantede. Lyd i naturen er stort sett mer lik naturlige b?lger (som b?lger p? et hav), og har mye mykere svingninger:
En slik lyd kan genereres slik:
def lyd_sinus(antall_sekunder):
lyd = []
for i in range(44100 * antall_sekunder):
lyd.append(16000 * (1 + np.sin(440 * i/44100 * 2 * np.pi)))
return lyd
Spille toner med en gitt frekvens
I koden over ganger vi en del tall med 440, og f?r dermed en lyd som svinger 440 ganger i sekundet (akkurat hvordan matematikken fungerer her trenger du ikke tenke p?, annet enn at det magiske tallet 440 f?rer til det blir 440 b?lgetopper/-bunner i sekundet).
Oppgave: Endre koden slik at funksjonen tar enda et parameter som er antall svingninger i sekundet og bruk det parameteret i stedet for 440. Denne funksjonen som tar to parametere vil du trenge i obligen denne uken.