Fredagsfordypning uke 6

Frist for innlevering: Mandag 2. oktober kl. 23:59

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 installert p? pc-en din. Ta kontakt dersom du har problemer med ? installere disse!

NB: Oppgaven 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 oppgaven. Oppgaven fortsetter p? konseptene og koden som blir introdusert i undervisningen.

Prekode

Lag en fil lyd.py hvor du importerer numpy og numpy slik:

import numpy as np

Alle oppgavene kan gj?res i filen lyd.py.

P? gruppetimen har vi skrevet (eller vil skrive) en funksjon for ? lage en liste som representerer 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 skriv_lyd_til_fil:

import numpy as np
import wave

def skriv_lyd_til_fil(data, sample_rate, filnavn):
    # tatt fra https://stackoverflow.com/a/64376061
    audio = np.array([data, data]).T
    audio = audio.astype("<h")

    with wave.open(filnavn, "w") as f:
        f.setnchannels(2)
        f.setsampwidth(2)
        f.setframerate(sample_rate)
        f.writeframes(audio.tobytes())
       

Test at du f?r laget en tone og skrevet denne til fil og spilt den av (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):

skriv_lyd_til_fil(lag_tone(3, 440), 44100, "filnavn.wav")

Hvis koden over fungerer og du f?r spilt av lyden, er du klar til ? begynne p? oppgavene.

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 denne 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],  ...

Sjekk at du forst?r dette formatet (hva denne n?stede listen betyr og representerer) f?r du g?r videre.

Oppgave 2:

Lag en funksjon lag_sang_fra_noter.

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 skriv_lyd_til_fil) 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.

Krav til innlevering

For ? levere:

  1. Logg inn p? Devilry.
  2. Lever alle .py-filene.
  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.