Obligatorisk innlevering uke 5
Frist for innlevering: 05.10. kl 23:59
Sp?rsm?l eller kommentarer til oppgaveteksten sendes til ivargry@ifi.uio.no.
Denne uken skal vi jobbe med lyd i Python. Vi kommer til ? snakke om lyd i gruppetimen, og vil se at lyd egentlig bare er b?lger, og at vi enkelt kan representere slike b?lger ved hjelp av en liste i Python (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. Ta kontakt dersom du har problemer med ? installere disse!
NB: Obligen bygger p? oppgavene for uken (vi jobber og g?r gjennom disse p? fredag) og det anbefales ? gj?res disse f?r du gj?r obligen. Oppgavene her fortsetter p? konseptene og koden som blir introdusert i undervisningen.
Prekode
Lag en fil lyd.py hvor du importerer numpy og simpleaudio slik:
import simpleaudio
import numpy as np
Alle oppgavene i denne obligen kan gj?res i filen lyd.py.
P? gruppetimen har vi skrevet (eller vil skrive) en funksjon for ? spille av en tone med en gitt frekvens i et gitt antall sekunder:
Legg denne funksjonen, som vi kaller lag_tone
i lyd.py:
def lag_tone(antall_sekunder, antall_svingninger_i_sekundet):
lyd = []
for i in range(int(44100 * antall_sekunder)):
lyd.append(16000 * (1 + np.sin(antall_svingninger_i_sekundet * i/44100 * 2 * np.pi)))
return lyd
Du trenger ogs? funksjonen spill_lyd:
def spill_lyd(lydliste):
lyd = np.array(lydliste).astype(np.int16)
lydobjekt = simpleaudio.play_buffer(lyd, 1, 2, 44100)
lydobjekt.wait_done()
Test at du f?r spilt av en tone (NB: det kan v?re lurt ? ikke ha p? for h?yt volum f?rste gang du pr?ver, i tilfelle lyden er h?y/ubehagelig):
spill_lyd(lag_tone(3, 440))
Hvis koden over fungerer, er du klar til ? begynne p? obligen.
Oppgave 1: Lese noter fra fil
Vi ?nsker n? lage et lite program som kan spille musikk som er skrevet ved hjelp av tekst i en fil. Sangen v?r ser slik ut (se under). Hver linje inneholder navnet p? en note og varigheten til noten (hvor lenge den skal spilles).
Kopier innholdet her og lagre innholdet i en fil sang.txt
:
E 0.3
- 0.1
E 0.3
- 0.1
E 0.7
- 0.1
E 0.3
- 0.1
E 0.3
- 0.1
E 0.7
- 0.1
E 0.3
- 0.1
G 0.3
- 0.1
C 0.5
- 0.1
D 0.2
E 1.5
- 0.1
F 0.3
- 0.1
F 0.3
- 0.1
F 0.5
- 0.1
F 0.2
F 0.3
- 0.1
E 0.3
- 0.1
E 0.3
- 0.1
E 0.1
- 0.1
E 0.1
- 0.1
E 0.3
- 0.1
D 0.3
- 0.1
D 0.3
- 0.1
E 0.3
- 0.1
D 0.7
- 0.1
G 0.8
PS: Pass p? at du ikke f?r noen ekstra tomme linjer til slutt n?r du lagrer filen.
Hver note tilsvarer en frekvens (antall svingninger i sekundet). For eksempel tilsvarer A frekvensen 440.
Vi kan bruke denen ordboken for ? representere hvilke noter som tilsvarer hvilke frekvenser:
noter = {
"A": 440,
"G": 392,
"F": 349,
"E": 330,
"D": 294,
"B": 247,
"C": 261,
"-": 0
}
PS: Vi bruker "-" til ? representere en stille tone (pause). Denne har frekvens 0, og vil ikke gi noen lyd.
Lag en funksjon les_sang_fra_fil
som tar filnavn
som parameter, leser sangen fra filen og returnerer en liste
der hvert element i listen er en ny liste best?ende av to elementer: frekvens og varighet. Denne listen som returneres
vil representere sangen i filen p? et format som vi kan bruke til ? spille av sangen senere.
Test funksjonen les_sang_fra_fil
p? filen sang.txt. Print listen som returneres, og sjekk at den
starter slik:
[[330, 0.3], [0, 0.1], [330, 0.3], [0, 0.1], ...
Oppgave 2:
Lag en funksjon lag_sang_fra_noter
.
- Denne funksjonen skal i motsetning til
les_sang_fra_fil
ikke ta et filnavn som parameter, men i stedet ta en liste av den typenles_sang_fra_fil
returnerer. - Oppgaven til denne funksjonen er ? lage en "sang", dvs. én enkelt liste som representerer lydb?lgene til sangen, og som kan sendes rett inn til
spill_sang
for ? bli spilt av. - Funksjonen m? alts? ta inn den n?stede listen med noter, g? gjennom hver note for ? lage lydb?lgene til den noten og sl? alt sammen til én enkelt liste som kan spilles av med
spill_sang
.
Test funksjonen med sangen du lagret i sang.txt, og spill av lyden som blir generert. Kjenner du igjen hvilken sang det er?
Oppgave 3:
Lag en funksjon fade_ut
som tar en komplett lyd (en liste av typen som kan sendes inn til spill_lyd) og fader den ut (senker volumet gradvis).
Volum er rett og slett hvor h?ye verdier det er i lyden. Du kan derfor fade sangen ut ved ? gange verdiene med gradvis lavere og lavere tall. Det er ulike m?ter ? gj?re dette p?. Pr?v deg frem til du f?r noe du er forn?yd med.
Oppgave 4
Lag en funksjon forenkle_lyd
som tar en lyd (en liste) og endrer hver verdi i lyden slik:
- Hvis verdien er under 16000: Sett verdien til ? v?re 0
- Hvis verdien er over 16000: Sett verdien til ? v?re 32000
Test funksjonen p? lyden generert fra sangen i oppgave 2. F?r du h?rer p? resultatet, gjett om du tror du kommer til ? kjenne igjen sangen eller ikke.
Oppgave 5 (valgfri konkurranse)
Skriv koden for denne oppgaven i en fil med navn konkurranse.py og lever den filen for ? delta i konkurransen.
Her finner du en fil med et lydsignal som inneholder en hemmelig kode. Koden er vanskelig/umulig ? h?re pga st?y og andre problemer med lyden. Last ned filen og legg den i samme mappe som konkurranse.py ligger. Prekoden under viser deg hvordan du spiller av lyden.
Konkurransen g?r ut p? ? skrive kode som endrer lyden slik at du klarer ? h?re hva den hemmelige koden er. Jo renere og penere lyd du klarer ? f?, jo bedre. Det er alts? to m?l i konkurransen:
- F? tak i den hemmelige koden
- Lag en ny lyd som er s? ren og pen som mulig (lite st?y og andre artifakter). Vi vil h?re p? de ulike bidragene i neste gruppetime og sammen k?re en vinner.
Start med f?lgende prekode og f?lg instruksjonene i kommentarene:
import simpleaudio
import numpy as np
import matplotlib.pyplot as plt
import pickle
def spill_lyd(lydliste):
lyd = np.array(lydliste).astype(np.int16)
lydobjekt = simpleaudio.play_buffer(lyd, 1, 2, 44100)
lydobjekt.wait_done()
def les_lyd_fra_fil():
lyd = pickle.load(open("kode.pickle", "rb"))
return lyd
hemmelig_kode = les_lyd_fra_fil()
# hemmelig_kode er n? en liste som inneholder lyden du skal jobbe med
# Start gjerne med ? spille av hemmelig_kode for ? se hva du har ? jobbe med:
spill_lyd(hemmelig_kode)
# Det kan v?re lurt ? plotte lyden for ? se etter mulige problemer og ting du kan gj?re for ? forbedre signalet
plt.plot(hemmelig_kode)
plt.show()
# tips: Det kan v?re lurt ? zoome inn p? deler av plottet for ? studere det n?rmere
def fiks_lyd(lyd):
# Implementer ditt bidrag til konkurransen i denne funksjonen
# denne funksjonen kan kalle andre funksjoner (om du vil dele opp koden din),
# men den skal returnere en ny liste som er den korrigerte lyden
# det er denne lyden du vil bli vurdert p?
pass
Et hint: St?y i lyd kommer ofte i form av enkeltverdier som er mye h?yere eller lavere enn verdier i n?rheten:
[1, 2, 3, 4, 1000, 5, 4, 3, 2, 1, 0, 1, 2, 3]
Her er typisk tallet 1000 st?y, og lyden vil h?res bedre ut om man hadde byttet ut 1000 med f. eks verdien f?r eller etter (eller gjennomsnittet/medianen av verdiene rundt).
Krav til innlevering
- Kun .py-filene skal leveres inn.
- Sp?rsm?lene til innleveringen (nedenfor) skal besvares i kommentarfeltet.
- Koden skal inneholde gode kommentarer som forklarer hva programmet gj?r.
- Programmet skal inneholde gode utskriftssetninger som gj?r det enkelt for bruker ? forst?.
Hvordan levere oppgaven
Kommenter p? f?lgende sp?rsm?l i kommentarfeltet i Devilry. Sp?rsm?lene skal besvares.
- Hvordan synes du innleveringen var? Hva var enkelt og hva var vanskelig?
- Hvor lang tid (ca) brukte du p? innleveringen?
- Var det noen oppgaver du ikke fikk til? Hvis ja: i. Hvilke(n) oppave(r) er det som ikke fungerer i innleveringen? ii. Hvorfor tror du at oppgaven ikke fungerer? iii. Hva ville du gjort for ? f? oppgaven til ? fungere hvis du hadde mer tid?
For ? levere:
- Logg inn p? Devilry.
- Lever alle .py-filene , og husk ? svare p? sp?rsm?lene i kommentarfeltet.
- Husk ? trykke lever/add delivery og sjekk deretter at innleveringen din er komplett. Du kan levere flere ganger, men alle filer m? v?re med i hver innlevering.
- Den obligatoriske innleveringen er minimum av hva du b?r ha programmert i l?pet av en uke. Du finner flere oppgaver for denne uken p? semestersiden.