1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
|
import javax.sound.midi.*;
import java.io.File;
import ddf.minim.*;
String midiFileName = "The Son is the One Midi 113bpm.mid";
String audioFileName = "The Son is the One.mp3";
Sequencer s;
MetaListener metaListener;
Note[] notes = new Note[128];
int NOTE_LOW = 0, NOTE_HIGH = 29;
Minim minim;
AudioPlayer audioPlayer;
int pw=10;int ph=10;
PImage sc; //=createImage(width,height);
//convolution matrix
float[][] matrix = { { 0,.2, 0 },
{0, .59, 0 },
{ 0, .2,0 } };
//vary size and matrix over piece
//matrix comes in slowly
//
//overall weighting of matrix is strongly determinant
//functions that map the frequency of change
//stepped by the notes will tend to maximise change where the music is busiest.
//map the notes to cyclers- independently - no cant be done
class FMcycler {
float cycleA;
float cycleB;
float offset;
float weight;
//takes a normalised coordinate and calculates a zeroed FM cycle
FMcycler(float _A, float _B) {
cycleA=_A;
cycleB=_B;
offset=0;
weight=1;
}
FMcycler(float _A, float _B,float _offs,float _wei) {
cycleA=_A;
cycleB=_B;
offset=_offs;
weight=_wei;
}
float map(float f) {
return offset+(weight*sin(cycleB*sin(cycleA*f*2*PI)*2*PI));
}
}
FMcycler off=new FMcycler(0,0,1.0,0);
FMcycler[][] cyclematrix = { { off, new FMcycler(0.5,1.2,0,0), off },
{ off, new FMcycler(0.5,1.2,1.0,0), off},
{ off, new FMcycler(0.5,1.2,0,0), off } };
FMcycler poscycler;
FMcycler scalecycler;
FMcycler vertcycler;
void setup(){
poscycler=new FMcycler(0.5,1.7);
scalecycler=new FMcycler(0.5,3.1);
vertcycler=new FMcycler(0.5,0.9);
size(300, 110, P3D);
frameRate(15);
for(int i = NOTE_LOW; i < NOTE_HIGH; i++){
notes[i]=new Note();
}
//load audio file
minim = new Minim(this);
audioPlayer = minim.loadFile(audioFileName, 2048);
audioPlayer.play();
//audioPlayer.loop(9999999);
//audioPlayer is started when midi sequencer is started
startMidiFile();
sc=createImage(width,height,RGB);
background(0);
rectMode(CORNER);
noStroke();
colorMode(RGB, 255);
//app=new PlayApp(this,"localhost","Backing & Veering","Sunken Foal",153f);
swidth=width-2;
soffset=1;
}
int swidth;
int soffset;
float time=0;
void draw(){
time+=(1f/(153f*25));
// for (int i=0;i<matrix.length;i++) {
// for (int j=0;j<matrix[0].length;j++) matrix[i][j]=cyclematrix[i][j].map(time);
//}
//matrix = { { 0, 0, 0 },{ 0, 1, 0 },{ 0, 0,0 } };
//println(time);
//scroll whole screen downwards how
//maybe copy the screen to the buffer offset a bit up, then draw in a blank rectangle and the new notes
//can the notes overlap?
loadPixels();
//sc=get(-1,0,width,height);
//sc=get(0,0,width,height);
//sc.filter(BLUR,1);
if (time>0.6) matrix[1][1]=0.6+(sin(((time-0.6)*0.25)*PI)*0.2);
sc=convolution(matrix,get(0,0,width,height));
background(0);
//image(sc,1,15,width,height);
image(sc,1,3.2+(vertcycler.map(time)*1.7),width-1,height);
//image(sc,soffset,5,swidth,height);
//image(sc,(int)(poscycler.map(time)*0)+1,5,width-2+(int)(scalecycler.map(time)*0),height);
//for (int i=15*width;i<height*width;i++) pixels[i]=color(255,255,255);
//image(sc,0,0,width,height);
updatePixels();
for(int i = NOTE_LOW; i < NOTE_HIGH; i++){
int v=notes[i].velocity;
if(v>0) {
//draw the note
colorMode(HSB, 255);
fill(200-v,255,255);
colorMode(RGB, 255);
rect(i*pw,0,pw,ph);
}
}
saveFrame("frames/img####.png");
if (!audioPlayer.isPlaying()) exit();
}
//change rate of drop?
//veering??
void startMidiFile(){
InputStream midiFileStream = createInput(midiFileName);
try {
s = MidiSystem.getSequencer(false);
s.setSequence(MidiSystem.getSequence(midiFileStream));
//Create a MidiReceiver that listens to NOTE ON and OFF events
Receiver midiReceiver = new MidiReceiver();
Transmitter midiTransmitter = s.getTransmitter();
midiTransmitter.setReceiver(midiReceiver);
//Create a MetaEventListener that listens to the END OF TRACK event
metaListener = new MetaListener();
s.addMetaEventListener(metaListener);
s.open();
s.setTickPosition(0L);
s.start();
}
catch(Exception e) {
println(e);
background(0, 100, 100); //red screen if erro
//stop();
}
}
void stop(){
s.stop();
}
PImage convolution(float[][] matrix, PImage img)
{
//return img;
PImage newimg=createImage(img.width,img.height,RGB);
newimg.loadPixels();
int matrixsize = matrix[0].length;
int offset = matrixsize / 2;
for (int x=0;x<img.width;x++) {
for (int y=0;y<img.height;y++) {
float rtotal = 0.0;
float gtotal = 0.0;
float btotal = 0.0;
for (int i = 0; i < matrixsize; i++){
for (int j= 0; j < matrixsize; j++){
// What pixel are we testing
int xloc = x+i-offset;
int yloc = y+j-offset;
int loc = xloc + img.width*yloc;
// Make sure we haven't walked off our image, we could do better here
loc = constrain(loc,0,img.pixels.length-1);
// Calculate the convolution
rtotal += (red(img.pixels[loc]) * matrix[i][j]);
gtotal += (green(img.pixels[loc]) * matrix[i][j]);
btotal += (blue(img.pixels[loc]) * matrix[i][j]);
}
}
// Make sure RGB is within range
rtotal = constrain(rtotal,0,255);
gtotal = constrain(gtotal,0,255);
btotal = constrain(btotal,0,255);
//write a buffer
newimg.pixels[x+y*img.width]=color(rtotal,gtotal,btotal);
//newimg.pixels[x+y*img.width]=color(255,255,255);
}
}
//save the buffer
newimg.updatePixels();
return newimg;
}
void keyPressed() {
switch(key){
case 'q':
swidth-=1;
break;
case 'w':
swidth+=1;
break;
case 'e':
soffset-=1;
break;
case 'r':
soffset+=1;
break;
}
}
|