Visuele Compositie
* Uitgedeeld op 30 november 2022.
* Deadline: aftekenen in de les, uiterlijk 22 december 2022.
* Met deze opdracht denken we dat je zo'n 2 - 4 uur bezig bent tot en met stap 5.
* Onderaan de pagina staat een gif van het beoogde eindresultaat.
* Bronnen bij deze opdracht: Syllabus | P5.js reference
Inleiding
We behandelen in deze opdracht alle lesstof die jullie afgelopen weken gehad hebben, inclusief het laatste onderdeel classes. Jullie gaan een muzikale sequentie generen en hierbij een visuele representatie van deze muzikale sequentie maken. Na de kerstvakantie, in semester twee gaan we nog verder met deze opdracht. Dus zorg dat je helder commentaar zet in je opdracht, zodat je er in februari weer mee verder kan.
Voorbereiding
Maak een kopie van het project van de vorige opdracht aan in je csdosc map met behulp van cp -r opdracht_4 *naam-van-je-nieuwe-project
Je maakt in deze opdracht gebruik van een aantal onderdelen uit de vorige opdracht.
Deel 1 - algoritmische compositie
Stap 1
zie voor meer informatie voor deze stap: array's in de syllabus
Gebruik de drie array's die je bij de vorige opdracht hebt aangemaakt, een voor midinoten, een voor amplitude en een voor nootduur. Maak deze array's nu vooralsnog leeg.
Stap 2
zie voor meer informatie voor deze stap: functies in de syllabus, for-loops in de syllabus
midi-waarden moeten een integer-getal tussen de 0 en 127 zijn.
- Maak voor de array waar midinoten in komen te staan een functie die een opgegeven aantal noten genereert.
- Verzin een (simpel) algoritme om deze array te vullen in de
setup()
functie van je sketch. Je mag geen gebruik maken van alleen maar een random getal. Er moet dus iets meer intelligentie achter deze functie zitten, waardoor het een muzikale melodie wordt. Denk aan gewogen random, kies noten uit een voorgedefinieerde lijst met noten, of als je meer uitdaging zoekt, maak een Markov-keten om nieuwe muziek te genereren, of baseer notenmateriaal op externe data. - Kijk in de syllabus hoe je een functie maakt en een argument (het aantal noten dat je wil genereren) kan meegeven aan een functie. Plaats je algoritme in een nieuwe eigen functie en voer deze uit in de
setup()
functie van je sketch.
Je code kan er als volgt uitzien:
let midiNotes = [];
function setup() {
createCanvas(300,300);
background(255);
//fillMidiNotes is de functie die automatisch midi-noten genereert,
//het getal 10 geeft aan hoeveel noten er in de array moet komen
midiNotes = fillMidiNotes(10);
console.log(midiNotes) // hier komt bijvoorbeeld
//[60,62,67,65,72,71,60,63,65,67] uit
}
function fillMidiNotes(number) {
//de number-variabele kan je gebruiken in een
//loop waarin je de noten genereert
let newArray = []; //nieuwe array om te vullen
//vul hier newArray met coole dingen
return newArray; //geef newArray terug aan hetgeen dat deze functie aanriep
}
Stap 3
Herhaal bij deze stap het principe uit stap-2. amplitude-waarden moeten een floating-point-getal tussen de 0. en 1. zijn.
- Maak een functie die een aantal amplitude-waarden genereert om de array te vullen waar amplitude-waarden in komen te staan.
- Zorg dat dit hetzelfde aantal is als het aantal noten dat je in stap 2 hebt gegenereerd, maar gebruik een ander algoritme.
- Kan je een link leggen tussen de toonhoogte en de amplitude?
Stap 4
Herhaal bij deze stap het principe uit stap 2 en stap 3. nootduur-waarden zijn in miliseconden en moeten een integer-getal zijn.
Doe hetzelfde voor de array met de duur van noten, dus genereer een nieuwe functie met een nieuw algoritme voor de nootlengten.
Stap 5
Ga terug naar de sequencer die je in de vorige opdracht gemaakt hebt. Kan je delen daarvan hergebruiken in deze opdracht om je gemaakte arrays hoorbaar te maken? Onderstaande code zou inspiratie kunnen zijn voor je project:
//bovenin de code:
let counter = 0;
// in de draw()-loop
if (frameCount % 30 === 0) {
//als het aantal reeds vertreken frames deelbaar is door 30 (dus dit wordt iedere 30 frames uitgevoerd)
counter ++; //tel 1 bij een counter variabele op
if (counter > midi.length) { //als de counter groter is dan dat de midi array lang is
counter = 0; //zet de counter dan weer terug op 0
}
//haal de noot uit de midi lijst op op index counter en bewaar deze in een variabele currentNote
let currentNote = midi[counter];
}
Laat met behulp van de simpele sequencer van vorige opdracht de noten afspelen en luister of het enigszins interessant klinkt, pas eventueel het algoritme aan als je nog niet tevreden bent over de uitkomst.
Deel 2 - visuele weergave
We gaan in dit deel de audio uit de sketch halen en ervoor zorgen dat iemand die niet kan horen toch de compositie kan meemaken. Dit door elke noot een visuele representatie te geven in plaats van een klank. Probeer hierbij verder te denken dan en balletje in het scherm, en denk buiten de bestaande muzieknotatie om. Wees creatief! Zorg er in ieder geval voor dat er beweging in de visualisatie zit. Dus laat iets niet alleen statisch verschijnen en verdwijnen, maar zorg voor beweging in het beeld. Maak voor deze opdracht gebruik van classes en objecten.
Stap 1:
schrijf op papier of in een tekstbestand wat er zichtbaar is als er een noot wordt afgespeeld.
- wat is de visuele representatie van de toonhoogte
- wat is de visuele representatie van de amplitude
- wat is de visuele representatie van de duur
- welke beweging is er zichtbaar
Stap 2:
zie voor meer informatie voor deze stap: classes in de syllabus
Maak een class-omschrijving waarin je alle benodigde eigenschappen en functionaliteiten maakt. Bij functionaliteit kan je denken aan beweging, tekenen van de vorm etc. bij eigenschappen gaat het om welke variabelen de toonhoogte, amplitude en duur duidelijk maken.
Je code kan er als volgt uitzien:
class Noot {
constructor() {
//definieer hier de eigenschappen van een object
}
//maak hieronder de functionaliteiten van een object
functionaliteitA() {
//beschrijf wat er moet gebeuren bij deze
//functionaliteit
}
functionaliteitB() {
//beschrijf wat er moet gebeuren bij deze
//functionaliteit
}
}
Stap 3:
zie voor meer informatie voor deze stap: de presentatie van les 11
Maak vanuit deze class-omschrijving eerst ÊÊn object. Kijk of deze naar wens werkt en pas de class-omschrijving daarna eventueel nog aan.
Stap 4:
Ga nu aan de slag met het maken van meerdere objecten in een array om zo elke noot een eigen object te geven.
Stap 5:
Pas voor deze stap de code die je uit de vorige opdracht hebt overgenomen aan. Zodat er geen makeNote gebruikt wordt, maar de 'noot' dus getekend wordt
Zorg dat de visuele noot zichtbaar wordt als deze door de sequencer wordt afgespeeld.
Deel 3: verklanking
Dit deel volgt na de kerstvakantie, deel 1 en 2 teken je al wel af voor de deadline. Zorg dat je duidelijk commentaar schrijft bij je code, zodat je in februari nog weet wat je gedaan hebt.