Obligatorisk innlevering uke 5
Frist for innlevering: 29.09. 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. I gruppetimen har vi sett 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
(dette skal vi ha installert i gruppetimen).
NB: Det er viktig at du har fulgt undervisningsopplegget og gjort oppgavene knyttet til lyd der f?r du gj?r denne obligatoriske oppgaven. 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.
Som del av ukesoppgavene (og livekoding) har vi skrevet 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, som vi skrev p? gruppetimen:
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))
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 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 f?lgende ordbok 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 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
som tar en liste av den typen les_sang_fra_fil
returnerer som parameter, og returnerer en liste som kan
sendes rett inn til spill_sang
for ? bli spilt av.
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 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 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.