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:

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:

  1. F? tak i den hemmelige koden
  2. 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

Hvordan levere oppgaven

Kommenter p? f?lgende sp?rsm?l i kommentarfeltet i Devilry. Sp?rsm?lene skal besvares.

For ? levere:

  1. Logg inn p? Devilry.
  2. Lever alle .py-filene , og husk ? svare p? sp?rsm?lene i kommentarfeltet.
  3. 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.
  4. 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.