Laboration 3: Musikbibliotek



Relevanta dokument
Laboration 3. Redovisning. Snabbkurs i digitalt ljud. Objektorienterad programmering

Laboration 4. Redovisning Uppgifterna skall vara demonstrerade för och godkända av en handledare senast måndag 23/2.

Laboration 4: Digitala bilder

Dagens program. Programmeringsteknik och Matlab. Objektorienterad programmering. Vad är vitsen med att ha både metoder och data i objekten?

Lite om felhantering och Exceptions Mer om variabler och parametrar Fält (eng array) och klassen ArrayList.

1 Uppgift 1. a) Skapar ett Company-objekt med hjälp av den överlagrade konstruktorn. Du kan själv välja värden på instansvariablerna.

Tentamen, EDAA10 Programmering i Java

Föreläsnings 9 - Exceptions, I/O

Instuderingsfrågor, del D

Laboration 1. "kompilera"-ikonen "exekvera"-ikonen

LÖSNINGSFÖRSLAG Programmeringsteknik För Ing. - Java, 5p

Uppgiften är att beskriva en kvadrat i ett Java program. En första version av programmet skulle kunna se ut så här:

Objektorienterad programmering. Fält som funktionsresultat. Mer om fält: att uppdatera ett parameterfält. Kontrast: Parametrar av primitiv typ

Föreläsning 3-4 Innehåll

Laboration 2. returnerar true om det är omöjligt för roboten att göra move() utan att. exekveringsfel erhålls, annars returnera false.

Objektorienterad Programmering (TDDC77)

Objektorienterad programmering E. Telefonboken, än en gång. Gränssnitt. Telefonboken med gränssnitt specificerat, del 1.

Outline. I Vi kan lätt göra samma sak för fyra variabler... I Hur gör vi för 400 inlästa värden? I Ofta behöver man flera likadana variabler

OOP Objekt-orienterad programmering

TDDC77 Objektorienterad Programmering

Objektorienterad programmering D2

ITK:P1 Föreläsning 1. Programmering. Programmeringsspråket Java. Stark typning Explicit typning Strukturerat Hög säkerhet

DUGGA: Objektorienterade applikationer. Läs detta! Uppgifterna är inte avsiktligt ordnade efter svårighetsgrad.

Högskolan Dalarna sid 1 av 7 DI-institutionen Hans-Edy Mårtensson Sten Sundin

Tentamen OOP

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Felsökning. Datatyper. Referenstyper. Metoder / funktioner

Objektorienterad programmering i Java I. Uppgifter: 2 Beräknad tid: 5-8 timmar (OBS! Endast ett labbtillfälle) Att läsa: kapitel 5 6

Kort repetition. Programmeringsteknik för Bio1 och I1. Vad ska vi lära oss idag? Ett exempel

Föreläsning 3-4 Innehåll. Diskutera. Metod. Programexempel med metod

Grundläggande programmering, STS 1, VT Sven Sandberg. Föreläsning 12

(Man brukar säga att) Java är... Denna föreläsning. Kompilering av Java. Historik: Java. enkelt. baserat på C/C++ Allmänt om Java

Föreläsning 5-6 Innehåll. Exempel på program med objekt. Exempel: kvadratobjekt. Objekt. Skapa och använda objekt Skriva egna klasser

EDAA20 Programmering och databaser. Mål komprimerat se kursplanen för detaljer. Checklista. Föreläsning 1-2 Innehåll. Programmering.

Föreläsning 5-6 Innehåll

Tentamen i EDAF oktober Skrivtid: Skriv bara på ena sidan av pappret tentorna kommer att scannas in, och endast framsidorna rättas.

Lite mer om Javas stöd för fält. Programmering. Exempel: vad är det största talet? hh.se/db2004. Fält samt Input/Output

TENTAMEN I PROGRAMMERING. På tentamen ges graderade betyg:. 3:a 24 poäng, 4:a 36 poäng och 5:a 48 poäng

ID1004 Laboration 4, November 2012

Bankkonto - övning. Övning 2 Skriv en metod, geträntan, som returnerar räntan.

Lösningsförslag övning 2.

Programstruktur och terminologi. Programmet producerar följande utskrift i terminalfönstret: Ett Javaprogram består av en eller flera klasser

DAT043 Objektorienterad Programmering

Programmering med Java. Grunderna. Programspråket Java. Programmering med Java. Källkodsexempel. Java API-exempel In- och utmatning.

Introduktion till Datalogi DD1339. Föreläsning 2 22 sept 2014

Administrativt. Programmeringsteknik för I1. Dagens program. Objektorienterad programmering

Laboration 1. "kompilera"-ikonen "exekvera"-ikonen

Föreläsning 2 Objektorienterad programmering DD1332. Typomvandling

Föreläsning 8 SLUMPTAL, SIMULERING + INTRODUKTION TILL VEKTORER

DI-institutionen Sid 1 av 6 Hans-Edy Mårtensson Sten Sundin

DELPROV 1 I DATAVETENSKAP

Anmälningskod: Lägg uppgifterna i ordning. Skriv uppgiftsnummer (gäller B-delen) och din kod överst i högra hörnet på alla papper

Grundläggande programmering med C# 7,5 högskolepoäng

Lite om reella tal. Programmering. I java. Om operatorers associativitet och prioritet

Föreläsning 6: Metoder och fält (arrays)

Anmälningskod: Lägg uppgifterna i ordning. Skriv uppgiftsnummer (gäller B-delen) och din kod överst i högra hörnet på alla papper

Chapter 4: Writing Classes/ Att skriva egna klasser.

Vem är vem på kursen. Objektorienterad programvaruutveckling GU (DIT011) Kursbok Cay Horstmann: Big Java 3rd edition.

Typkonvertering. Java versus C

Föreläsning 2. Täcker material från lektion 1, 2, 3 och 4:

Algoritmer. Två gränssnitt

Laboration 3, uppgift En klass för en räknare

Grundkurs i programmering, 6 hp (725G61) Dugga 2 tillfälle 2

Det är principer och idéer som är viktiga. Skriv så att du övertygar examinatorn om att du har förstått dessa även om detaljer kan vara felaktiga.

Inledande programmering med C# (1DV402) Tärningarna ska kastas

Datatyper. Programmering. Att definiera datatyper i Java. Laddade partiklar. (x,y) (Rx,Ry) hh.se/db2004

Inledande programmering med C# (1DV402) Ditt första C#-program med Visual Studio

Tentamen FYTA11 Javaprogrammering

Metodanrop - primitiva typer. Föreläsning 4. Metodanrop - referenstyper. Metodanrop - primitiva typer

Laboration 10 - Eclipse

Tentamen DE12, IMIT12, SYST12, ITEK11 (även öppen för övriga)

Laboration 1 Introduktion till Visual Basic 6.0

EDAA20 Programmering och databaser. Mål komprimerat se kursplanen för detaljer. Om att lära sig programmera. Föreläsning 1-2 Innehåll.

Objektorienterad programmering i Java Undantag Sven-Olof Nyström Uppsala Universitet Skansholm: Kapitel 11

TUTORIAL: SAMLING & KONSOLL

Chapter 3: Using Classes and Objects

Malmö högskola 2008/2009 CTS

Laboration 1. Objektorienterad programmering, Z1. Syfte

DAT043 Objektorienterad programmering för D, DIT011 Objektorienterad programvaruutveckling för GU

Objektorienterad programmering i Java Undantag Sven-Olof Nyström Uppsala Universitet Skansholm: Kapitel 11

Datatyper och kontrollstrukturer. Skansholm: Kapitel 2) De åtta primitiva typerna. Typ Innehåll Defaultvärde Storlek

Att bekanta dig med NetBeans programmeringsmiljö och skriva några enkla program med programmeringsspråket Java.

DD1311 Programmeringsteknik för S1 Laborationer läsåret

Det finns en referensbok (Java) hos vakten som du får gå fram och läsa men inte ta tillbaka till bänken.

JAVA Mer om klasser och objektorientering

Objektorienterad programmering i Java

PROGRAMMERING-Java TENTAMINA

OBJEKTORIENTERAD PROGRAMVARUUTVECKLING

Objektorienterad programmering Föreläsning 5

PROGRAMMERING-JAVA TENTAMINA

Innehållsförteckning. 9 Större projekt Övningsuppgifter...32

Input. Programmering. Andra källor

Objektorientering: Lagring, räckvidd och livstid

Idag. Exempel, version 2. Exempel, version 3. Ett lite större exempel

Översikt MERA JAVA OCH ECLIPSE. Uttryck och tilldelning. Uttryck och tilldelning. Uttryck och tilldelning. Uttryck och tilldelning

Tentamen i Objektorienterad programmering

Lösningsförslag, tentamen FYTA11 Javaprogrammering

Java: Utvecklingsverktyg, datatyper, kontrollstrukturer

Diagnostiskt Prov. Antaganden Om förutsättningar saknas I en uppgift skall rimliga antaganden göras och nedtecknas.

Tentamen för kursen Objektorienterad programvaruutveckling GU (DIT010)

Redovisning av inlämningsuppgifter

Transkript:

Laboration 3: Musikbibliotek Objektorienterad programmering, Z1 Syfte I denna laboration ska ni definiera ett litet bibliotek för att generera musik som kan avlyssnas med vanliga musikprogram. Tiden medger inte något omfattande bibliotek, så den musik vi kan åstadkomma är begränsad. Syftet med denna laboration är att få övning i att använda en-dimensionella fält. Redovisning Källkoden för uppgifterna skall lämnas in via Fire senast torsdag 16/10. Lämna in samtliga källkodsfiler som en komprimerad zip-fil. Förberedelser 1. Snabbkurs i digitalt ljud Ljud uppstår genom att en tryckvåg fortplantas genom luften; vi har alltså ett analogt fenomen. För behandling i datorer vill vi ha en digital representation av den analoga signalen. Vi betraktar följande figur: Den grå analoga signalen har samplats (avlästs) vid diskreta tidpunkter (de vertikala streckade linjerna). Dessutom har signalvärdena (amplituderna) vid dessa tidpunkter avrundats till närmaste heltalsvärde, representerat av de horisontella streckade linjerna. Den samplade digitala signalen är alltså i detta fall [0, 4, 5, 4, 3, 4, 6, 7, 5, 3, 3, 4, 4, 3]. En vanlig standard för digital musik, som används för CD-skivor, har samplingsfrekvensen 44100 Hz (dvs antalet avläsningar av signalen per sekund). Noggrannheten i amplitud är typiskt 16 bitar, dvs 2 16 =65536 olika amplituder kan anges. I vårt bibliotek ska vi sampla signaler med denna frekvens, men representera amplituder med värden av typen double, skalade så att amplituden alltid ligger mellan -1 och 1. Först i sista steget, i en klass som ni får given, gör vi om till 16 bitars värden för amplituden. En lämplig datatyp för musik är alltså ett fält av flyttal, dvs double[]. Vi kan göra två observationer: Det mänskliga örat kan uppfatta ljud ungefär i intervallet 20-20000 Hz. Grundfrekvensen för ettstrukna A (den ton efter vilken instrument stäms) är 440 Hz. När en sinussignal med denna frekvens samplas med samplingsfrekvens 44.1 khz får man alltså med ca 100 värden per period, dvs den samplade signalen ger en mycket god bild av den analoga signalen. Nedan visas en period av en sinuskurva, samplad med 100 punkter. För högre frekvenser blir givetvis upplösningen sämre, men för hörbara signaler har man ändå minst två avläsningar per period. Om man sparar en digital signal i en fil med 16 bitar, dvs två bytes, per avläsning och 44100 avläsningar per sekund, så blir det 88 kbytes per sekund, dvs ca 5 Mbytes per minut. Och detta i mono; med två kanaler fördubblas filstorleken till 10 Mbytes per minut. Ljudfiler i detta format blir därför stora. Ofta använder man därför komprimerade format som MP3, vilka tappar en del ljudinformation men ger mycket mindre filer. Vi ska dock i denna laboration hålla oss till okomprimerade filer i formatet WAV. Laboration 3 - Musikbibliotek 1 (5) Z1 Objektorienterad programmering HT14

Förberedelser 2. Tillhandahållna klasser Skapa en ny mapp för denna laboration och ladda ner filen fileslab3.zip från kurshemsidan till denna mapp. Bekanta er sedan med det givna programmet: 1. Ladda in filen Main.java i JGrasp. Kompilera och kör programmet (med hörlurar på!). Ni hör en ren sinussignal med frekvensen 440 Hz i två sekunder, följt av en lika lång signal en oktav högre. 2. Titta på filen Main.java: import java.io.file; public class Main { public static double[] sine(double freq, double duration) { int n = (int) (duration*sounddevice.sampling_rate); double[] a = new double[n]; double dx = 2*Math.PI*freq / SoundDevice.SAMPLING_RATE; for (int i = 0; i < n; i = i + 1) { a[i] = Math.sin(i * dx); } return a; }//sine public static void main(string[] args) { SoundDevice device = new SoundDevice(); Song song = new Song(5); song.add(sine(440, 2)); song.add(sine(880, 2)); song.play(device); song.save(device.getformat(), new File("twotones.wav")); }//main } //Main Vi börjar med att titta på metoden main. Först skapas två objekt, en SoundDevice och en Song. Klassen SoundDevice får ni given. Denna klass gör det möjligt att komma åt datorns ljudkort. Klassen Song, som ni också får given, används för att avbilda en sång. Klassen innehåller metoden add för att lägga till toner, metoden play för att spela sången, samt metoden save för att spara sången på en fil. Vi läser vidare i main. Två gånger lägger vi till toner genom att anropa song.add. Tonerna som läggs till är resultat av metoden sine (som definieras ovanför main). Metoden sine producerar en sinussignal med given frekvens och längd. Därefter spelas sången (vilket ni hörde) genom att anropa song.play. Med anropet song.save sparas slutligen sången på en fil med namnet "twotones.wav". (Filen kan öppnas och spelas upp med datorns CD-spelare (om en sådan finns). Gör detta och kolla att ni höra de två tonerna.) Vi är nu i en vanlig situation. Vi har fått ett program, provkört det, tittat på det och förstår en del av vad som pågår. Men en del är fortfarande konstigt. Vad betyder till exempel 5 i new Song(5)? 3. I underkatalogen doc finns dokumentation av de två klasserna Song och SoundDevice. Studera denna dokumentation och källkoden för de båda klasserna. Genom att läsa dokumentationen om Song bör ni kunna förstå vad femman betyder. För laborationen behöver vi inte förstå hur klassen SoundDevice är uppbyggd. Det räcker att se att konstanten SAMPLING_RATE = 44100 definieras i denna klass. 4. Det återstår att förstå funktionen sine som skapar och fyller ett fält med avläsningar av en ren sinusfunktion. Antalet värden i fältet är antalet avläsningar per sekund (SAMPLING_RATE) gånger tonens längd i sekunder (duration). Den funktion vi ska sampla är s(t) = sin(2π f t), där f är frekvensen (som heter freq i metoden). Ska vi fylla fältet a med SAMPLING_RATE avläsningar av denna funktion så bör elementet med nummer i vara s(i/sampling_rate), eller sin(i dx), där dx definieras som i koden ovan. Laboration 3 - Musikbibliotek 2 (5) Z1 Objektorienterad programmering HT14

Uppgift 1: Ljudet av en sträng Nu är det dags att skapa ett musikaliskt intressantare ljud än en ren sinuston. Er uppgift är att definiera en metod public static double[] pluck(double freq, double duration) som genererar en ton med den givna frekvensen och varaktigheten och som liknar ljudet då man knäpper på en sträng på ett stränginstrument. För detta finns en berömd metod: Karplus-Strongs algoritm, uppfunnen för cirka 30 år sedan. Notera att metoden pluck har samma parametrar som metoden sine, dvs tonens frekvens och varaktighet. Trots det kommer den att låta annorlunda. Börja med att skapa en ny klass MusicUtils (i en ny fil MusicUtils.java). Flytta dit sine från Main. När ni flyttat bort sine från klassen Main måste ni ändra användningen av den i metoden main; ni måste nu skriva MusicUtils.sine för att java-kompilatorn ska hitta metoden. Gör det, kompilera om och kolla att ni fortfarande kan köra Main och höra de två sinustonerna. Ni ska nu lägga till pluck till klassen MusicUtils. Karplus-Strongs algoritm fungerar på följande sätt: Först måste ni deklarera och skapa ett fält av flyttal av lämplig storlek på precis samma sätt som i funktionen sine. Sedan ska ni fylla ni fältets element med värden. Detta görs i två steg: 1. Låt p vara antalet avläsningar per period, dvs samplingsfrekvensen 44100 dividerat med frekvensen freq för den önskade tonen. Fyll de första p elementen med slumptal i intervallet [-1.0, 1.0[. För att få slumptal använder instansmetoden nextdouble() i klassen Random. Om ni tittar i API'n, ser ni att metoden nextdouble() ger ett ett värde i intervallet [0.0, 1.0[; hur gör man om det till ett tal mellan -1 och 1? 2. Övriga element i fältet, elementen efter de p första elementen, beräknas på följande sätt: elementet med index i är summan av elementen med index i-p och i-(p-1), multiplicerad med en dämpkonstant k. Ett lämpligt värde på k är 0.498, men ni får gärna experimentera med olika värden (som ger olika ljud). Intressanta ljud fås bara för k-värden litet mindre än 0.5. Testa er metod genom att ändra i main så att ni anropar pluck i stället för sine. Ändra också namnet på filen där ni sparar sången. Ni bör fortfarande höra två toner, men nu ska de låta som när man knäpper på en sträng. Vi kan nu se att koden i sine och pluck har samma struktur: vi deklarerar och skapar ett fält, fyller det med innehåll och returnerar det. Innehållet blir olika i de två fallen och vi får därför olika ljud när vi spelar upp filen. Uppgift 2: Ett bättre sätt att ange toner Hittills har vi angett toner genom att ge frekvens och varaktighet. Vi vill nu närma oss hur toner anges normalt i musik, dvs med noter i en skala. Vi kan inte gå igenom musikteori här, utan nöjer oss med att konstatera att på till exempel en pianoklaviatur finns tolv tangenter per oktav, sju vita och fem svarta: Vi skall inte ange toner med de vanliga bokstäverna CDEFGAH, eftersom det kräver förtecken för de svarta tonerna och dessutom något sätt att ange oktav. Istället numrerar vi tonerna med heltal som på klaviaturen ovan, där ettstrukna A ges nummer 0 (vi väljer A som utgångspunkt, eftersom den, med frekvensen 440 Hz, oftast är referenspunkt för musikaliska skalor). Ettstrukna C är alltså -9, tvåstrukna C är 3, trestrukna C är 15, osv. Detta har också fördelen att vi lätt får en direkt formel för frekvensen för en given ton: ton nummer k har frekvensen 440*2 k/12 Hz. Ettstrukna C har alltså frekvensen 440*2-9/12 =261.63 Hz. Er uppgift är nu att utöka MusicUtils med ytterligare en metod public static double[] note(int pitch, double duration) som genererar en ton med givet nummer (anges med parametern pitch) och varaktighet (anges med parametern duration). Observera: Det enda man behöver göra är att räkna ut frekvensen från tonens nummer, anropa pluck för att få ett fält och returnera detta fält. I note ska man varken skapa eller fylla fältet; det sköter pluck om. Laboration 3 - Musikbibliotek 3 (5) Z1 Objektorienterad programmering HT14

När ni gjort detta kan ni testa resultatet genom att ändra i main så att programmet spelar till exempel början på Gubben Noak: song.add(musicutils.note(-4, 0.4)); song.add(musicutils.note(-9, 1)); song.play(device); Valet av 0.4 sekunder per ton här är en smaksak; ni kan välja annat tempo om ni så önskar. Vi ser också att det blir mycket omständligt att beskriva musik på detta sätt. Men innan vi ger oss på att åtgärda detta ska vi förbättra ljudet ytterligare. Uppgift 3: Att blanda ljud Ett betydligt intressantare ljud fås om vi spelar flera toner samtidigt. Som ett första steg ska ni skriva en metod public static double[] average(double[] t1, double[] t2) som genererar ett medelvärde av tonerna t1 och t2. Vi förutsätter också att de två tonerna har samma varaktighet så att fälten är lika långa. Metoden average ska helt enkelt skapa ett nytt fält och för varje index ta medelvärdet av motsvarande värden i t1 och t2. Nästa steg är att ni skall skriva en metod public static double[] harmonic(int pitch, double duration) som skapar en ton med givet nummer och varaktighet genom att blanda tre toner som skapats med note, nämligen tonerna med nummer pitch, pitch-12 och pitch+12 (dvs också de två tonerna en oktav under och över den avsedda). Förslagsvis blandas först de två sistnämnda tonerna med metoden average och sedan blandas resultatet med den första tonen, återigen med metoden average. Slutligen kan ni testa resultatet genom att i main ersätta alla note med harmonic. När ni kommit så här långt har ni definierat en biblioteksklass MusicUtils som innehåller fem funktioner; sine som ni fick given samt pluck, note, average och harmonic som ni definierat själva. Uppgift 4: Att separera sånger från programmet I main ovan var beskrivningen av Gubben Noak en del av programmet. Mycket bättre är att spara beskrivningen av sången i en fil noak.txt som börjar -4 0.4 och sedan låta programmet läsa denna fil och med hjälp av informationen på varje rad skapa en ton som läggs till sången. Ännu bättre är kanske att ändra varaktigheten för tonerna i filen till 0.25, svarande mot en kvartston, och sedan separat ange tempot. Laboration 3 - Musikbibliotek 4 (5) Z1 Objektorienterad programmering HT14

Ändra nu Main så att en sångbeskrivning läses från en fil genom att ge filnamnet som argument till main-metoden. Koppla sedan filen till ett Scanner-objekt. Detta görs på följande vis public static void main(string[] args) throws FileNotFoundException { Scanner sc = new Scanner(new File(args[0]));... }//main Klassen Scanner har en konstruktor som göra att Scanner-objektet läser data från en fil. En fil handhas som ett objekt av klassen File och klassen File har en konstruktor vars parameter är namnet på den fysiska filen. Vid anropet av new File(arg[0]) inträffar en exception av typen FileNotFoundException om den angivna fysiska filen inte finns. FileNotFoundException tillhör en typ av exceptions som måste tas hand om eller kastas vidare. Här kastar vi FileNotFoundException vidare, därav står det throws FileNotFoundException i metodhuvudet till main-metoden. I er katalog finns också en fil elise.txt som ni kan använda för testning, om ni inte vill skriva en egen fil för någon musik ni föredrar. Denna fil utnyttjar ovan antydda förbättring; varaktigheten 0.125 betyder en åttondelston. Om man låter detta vara synonymt med varaktigheten hos tonen i sekunder så blir det alldeles för högt tempo. Om en åttondel varar i 0.125 sekunder så hinner man 240 fjärdedelsnoter på en minut; 148 fjärdedelar per minut är mer lagom. En möjlighet är att även ange tempot som argument till main-metoden. Gör det! Slutkommentarer Förhoppningsvis har ni nu lärt er en del programmering med fält och en del om digital audio. Avslutningsvis skall påpekas att vi i ett avseende gjort det enkelt för oss: vi har slösat med minne. Vi skapar många och långa fält också för korta ljudsekvenser. Det går att göra det vi gjort, och mer, med mycket mindre minneskonsumtion. För ett allvarligt menat musikprogram måste man vara mer ekonomisk, men för vårt syfte här lämpar sig en mer frikostig attityd till minnesförbrukning bättre. Laboration 3 - Musikbibliotek 5 (5) Z1 Objektorienterad programmering HT14