// Rainbow Notes // By Karl Hornell, 1997-02-10 import java.awt.*; import java.awt.image.*; import java.net.*; import java.io.*; import sun.audio.*; public final class rainbow extends java.applet.Applet { int i,j,k,l,m,n,o,p; double sc; boolean dragging=false,drawStrip=false; int freeRight[]=new int[9],occupied[][]=new int[2][8]; int maxVol[]=new int[7],lCount[]=new int[7]; byte noteData[][]=new byte[15][720],audioTable[]=new byte[16384]; byte rawAudio[]=new byte[10],fileBuffer[]=new byte[2048],btemp; byte smallAudio[]=new byte[4266]; char outChars[]=new char[65]; double waveData[][]=new double[7][64]; double frequencies[]=new double[72]; int scrollPos=0,oldScrollPos=0,barLength=8,lastBar=1,lastNote=-1,currCol=0,mx=0,my=0; int stripX=0,dx,selectedVal=0,selectedCol=0,selectedLen=0,selectedPos=0,barStart=0; int bufLength=0,bufPos=0,oldLength=0; final int colVals[]={255,0,0, 255,128,0, 255,255,0, 0,255,0, 120,140,255, 0,0,255, 128,0,128, 0,0,0}; final int opaque=0xff000000; final int noteH[]={141,138,138,134,134,131,127,127,124,124,120,120,117, 113,113,110,110,106,103,103,99,99,96,96,92,89,89,85,85,82,78,78, -100,-100,-100,-100, 74,74,71,71,67,64,64,60,60,57,53,53,50,50,46,46,43,39,39,36,36,32, 29,29,25,25,22,22,18,15,15,11,11,8,4,4}; final int lines[]={137,137,137,130,130,130,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 88,88,88,88,81,81,81,74,74,0,0, 70,70,70,70,63,63,63,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,21,21,21,14,14,14,14,7,7,7}; final int noteHash[]={0,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,1, 0,0,1,0,1,0,0,1,0,1,0,1, 0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,0,1}; final int lengthOffset[]={0,0,8,16,24,0,40,0,56}; final int lengthVal[]={0,0,2,4,6,0,8,0,10}; int pauseOffset[]={0,0,8,24,56},pauseLength[]={1,2,4,8}; int noteDH[]=new int[72],flipOffset[]=new int[72]; int waveforms[][]=new int[7][64],envelopes[][]=new int[7][64]; int waveCopy[][]=new int[7][64],envCopy[][]=new int[7][64]; final String colNames="ROYGBIV"; String s,s1; Scrollbar bar,speedBar; Label labels[]=new Label[3]; ActiveCanvas waveC,envC; Choice inFiles=new Choice(),trueInFiles=new Choice(); Panel sevenNotes,sevenAndText,mainButtons,buttonPlusBar,allOfIt; Panel specialHolder,canvasHolder,midCHolder,speedHolder,choiceHolder; Button noteB[]=new Button[7],controlB[]=new Button[9],extraB; Color noteCol[]=new Color[7]; Font smallText; Image splash1,splash2,offImage,clefs,paces[]=new Image[2],pauses[]=new Image[4]; Image clefIm,offImage2,notePics[][]=new Image[7][24],strip,strip2; Graphics offG,offG2,clefG,sG,sG2; InputStream fileInput,soundStream=new AudioDataStream(new AudioData(rawAudio));; public void init() { for (i=0;i<72;i++) if ((i<15)||((i>35)&&(i<52))) { noteDH[i]=-21; flipOffset[i]=0; } else { noteDH[i]=-3; flipOffset[i]=12; } s=getParameter("file1"); i=1; while (s!=null) { s1=getParameter("title"+i); if (s1!=null) inFiles.addItem(s1); else inFiles.addItem(s); i++; trueInFiles.addItem(s); s=getParameter("file"+i); } smallText=new Font("Helvetica",Font.PLAIN,10); labels[0]=new Label("Speed"); labels[1]=new Label("Waveform"); labels[2]=new Label("Envelope"); for (i=0;i<3;i++) { labels[i].setFont(smallText); labels[i].setForeground(Color.white); labels[i].setAlignment(Label.RIGHT); } labels[1].setAlignment(Label.LEFT); for (i=0;i<7;i++) { noteCol[i]=new Color(colVals[i*3],colVals[i*3+1],colVals[i*3+2]); } colVals[21]=Color.gray.getRed(); colVals[22]=Color.gray.getGreen(); colVals[23]=Color.gray.getBlue(); prepareGraphics(); System.gc(); fixAudioBytes(); for (i=0;i<64;i++) { if (i<32) waveforms[0][i]=29; else waveforms[0][i]=-30; waveforms[1][i]=(int)Math.abs(59.9*(32-i)/32.0)-30; waveforms[2][i]=(int)(29.9-i*0.95); waveforms[3][i]=(int)(30*Math.sin(0.0981*i)); waveforms[4][i]=(int)(20*Math.sin(0.0981*i)+15*Math.sin(0.196*i)); if (i<21) waveforms[5][i]=29; else if (i>43) waveforms[5][i]=-30; else waveforms[5][i]=0; waveforms[6][i]=(int)(50.9*Math.random()-30); } for (i=0;i<7;i++) for (j=0;j<64;j++) { envelopes[i][j]=4032-64*j; } for (i=0;i<7;i++) for (j=0;j<64;j++) { envCopy[i][j]=envelopes[i][j]; waveCopy[i][j]=waveforms[i][j]; } for (i=0;i<36;i++) { frequencies[i]=123.4708*Math.pow(2.0,i/12.0); frequencies[i+36]=195.9977*Math.pow(2.0,i/12.0); } setBackground(Color.gray); setForeground(Color.black); sevenNotes=new Panel(); sevenNotes.setLayout(new FlowLayout(FlowLayout.LEFT,1,2)); sevenAndText=new Panel(); sevenAndText.setLayout(new BorderLayout(0,1)); mainButtons=new Panel(); mainButtons.setLayout(new GridLayout(1,9,1,1)); allOfIt=new Panel(); allOfIt.setLayout(new BorderLayout(3,1)); midCHolder=new Panel(); midCHolder.setLayout(new BorderLayout()); midCHolder.add("North",labels[1]); midCHolder.add("South",labels[2]); canvasHolder=new Panel(); canvasHolder.setLayout(new GridLayout(1,3,1,1)); waveC=new ActiveCanvas(noteCol[0],waveforms[0],-30,30); envC=new ActiveCanvas(noteCol[0],envelopes[0],0,4096); canvasHolder.add(waveC); canvasHolder.add(midCHolder); canvasHolder.add(envC); for (i=0;i<7;i++) { noteB[i]=new Button(colNames.substring(i,i+1)); noteB[i].setBackground(noteCol[i]); sevenNotes.add(noteB[i]); } speedHolder=new Panel(); speedHolder.setLayout(new BorderLayout()); speedHolder.add("West",labels[0]); speedBar=new Scrollbar(Scrollbar.HORIZONTAL,15,5,55,90); speedHolder.add("Center",speedBar); sevenAndText.add("North",sevenNotes); sevenAndText.add("South",speedHolder); specialHolder=new Panel(); specialHolder.setLayout(new BorderLayout(3,1)); bar=new Scrollbar(Scrollbar.HORIZONTAL,0,48,0,1488); controlB[0]=new Button("Make"); controlB[1]=new Button("Play"); controlB[2]=new Button("Stop"); controlB[3]=new Button("3/4"); controlB[4]=new Button("4/4"); controlB[5]=new Button("Clear"); controlB[6]=new Button("Load"); controlB[7]=new Button("Reset"); controlB[8]=new Button("Save"); for (i=0;i<9;i++) { controlB[i].setBackground(Color.lightGray); mainButtons.add(controlB[i]); } allOfIt.add("North",bar); specialHolder.add("West",sevenAndText); specialHolder.add("Center",canvasHolder); allOfIt.add("Center",specialHolder); allOfIt.add("South",mainButtons); setLayout(new BorderLayout()); choiceHolder=new Panel(); inFiles.setBackground(Color.lightGray); choiceHolder.add(inFiles); add("South",allOfIt); add("North",choiceHolder); choiceHolder.hide(); drawPace(); computePauses(0); if (inFiles.countItems()>0) loadNotes(trueInFiles.getItem(0)); updateSheet(); } public void prepareGraphics() { int colHoriz[]=new int[210]; int colVert[]=new int[50]; MediaTracker mt=new MediaTracker(this); Image inPic = getImage(getCodeBase(),"notes.gif"); mt.addImage(inPic,0); for (j=0;j<7;j++) for (k=0;k<30;k++) colHoriz[j*30+k]=(((int)(colVals[j*3]*(30-k)/30.0+colVals[j*3+3]*k/30.0))<<16) | (((int)(colVals[j*3+1]*(30-k)/30.0+colVals[j*3+4]*k/30.0))<<8) | ((int)(colVals[j*3+2]*(30-k)/30.0+colVals[j*3+5]*k/30.0)) | opaque; splash1=createImage(new MemoryImageSource(210,1,colHoriz,0,210)); for (k=0;k<50;k++) colVert[k]=(((int)(colVals[0]*(50-k)/50.0+colVals[21]*k/50.0))<<16) | (((int)(colVals[1]*(50-k)/50.0+colVals[22]*k/50.0))<<8) | ((int)(colVals[2]*(50-k)/50.0+colVals[23]*k/50.0)) | opaque; splash2=createImage(new MemoryImageSource(1,50,colVert,0,1)); mt.addImage(splash1,0); mt.addImage(splash2,0); try { mt.waitForID(0); } catch(InterruptedException e) {} int noteInts[]=new int[96*144]; PixelGrabber pg=new PixelGrabber(inPic,0,0,96,144,noteInts,0,96); showStatus("Grabbing pixels"); try { pg.grabPixels(); } catch(InterruptedException e) {} MemoryImageSource ip=new MemoryImageSource(32,144,noteInts,64,96); clefs=createImage(new FilteredImageSource(ip, new CropImageFilter(0,0,32,102))); mt.addImage(clefs,1); paces[0]=createImage(new FilteredImageSource(ip, new CropImageFilter(0,102,8,15))); mt.addImage(paces[0],1); paces[1]=createImage(new FilteredImageSource(ip, new CropImageFilter(8,102,8,15))); mt.addImage(paces[1],1); for (i=0;i<4;i++) { pauses[i]=createImage(new FilteredImageSource(ip, new CropImageFilter(i*8,120,8,24))); mt.addImage(pauses[i],1); } try { mt.waitForID(1); } catch(InterruptedException e) {} byte noteBytes[]=new byte[64*144]; for (i=0;i<144;i++) for (j=0;j<64;j++) noteBytes[i*64+j]=(byte)(noteInts[i*96+j]&255); byte RGB[][]=new byte[4][256]; for (i=0;i<4;i++) { RGB[i][255]=(byte)255; } RGB[3][0]=(byte)255; RGB[3][63]=(byte)255; for (i=0;i<7;i++) { RGB[0][63]=(byte)colVals[i*3]; RGB[1][63]=(byte)colVals[i*3+1]; RGB[2][63]=(byte)colVals[i*3+2]; MemoryImageSource mis=new MemoryImageSource(64,144,new IndexColorModel(8,256, RGB[0],RGB[1],RGB[2],RGB[3]),noteBytes,0,64); showStatus("Creating note set "+i); for (j=0;j<6;j++) for (k=0;k<4;k++) { notePics[i][j*4+k]=createImage(new FilteredImageSource(mis, new CropImageFilter(k*16,j*24,16,24))); mt.addImage(notePics[i][j*4+k],2); } } showStatus("Waiting for completion"); try { mt.waitForID(2); } catch(InterruptedException e) {} clefIm=createImage(46,142); clefG=clefIm.getGraphics(); clefG.setColor(Color.white); clefG.fillRect(0,0,46,144); clefG.drawImage(clefs,0,22,this); clefG.setColor(Color.black); for (i=0;i<5;i++) { clefG.drawLine(32,28+7*i,46,28+7*i); clefG.drawLine(32,95+7*i,46,95+7*i); } offImage=createImage(382,142); offG=offImage.getGraphics(); offImage2=createImage(382,142); offG2=offImage2.getGraphics(); strip=createImage(16,142); sG=strip.getGraphics(); strip2=createImage(16,142); sG2=strip2.getGraphics(); } public void drawPace() { if (barLength==6) { clefG.drawImage(paces[1],35,35,this); clefG.drawImage(paces[1],35,102,this); } else { clefG.drawImage(paces[0],35,35,this); clefG.drawImage(paces[0],35,102,this); } if (barLength==8) // Make sure full pause mark looks right pauseOffset[4]=56; else pauseOffset[4]=40; pauseLength[3]=barLength; } public void drawNote(int x,int val,int length,int col,Graphics g) { if (lines[val]>0) { g.setColor(Color.black); g.drawLine(x+2,lines[val],x+14, lines[val]); } g.drawImage(notePics[col][flipOffset[val]+lengthVal[length]+noteHash[val]], x,noteH[val]+noteDH[val],this); } public void drawBar(int x,int barNum,Graphics g) { g.setColor(Color.white); g.fillRect(x,0,barLength*16+8,142); g.setColor(Color.black); g.drawLine(x+barLength*16+6,28,x+barLength*16+6,123); g.drawLine(x+barLength*16+7,28,x+barLength*16+7,123); for (i=0;i<5;i++) { g.drawLine(x,28+7*i,x+barLength*16+8,28+7*i); g.drawLine(x,95+7*i,x+barLength*16+8,95+7*i); } if ((barNum==lastBar)&&(barNum>0)) g.fillRect(x+2,28,3,95); for (l=0;l<7;l++) for (i=0;i0) drawNote(x+4+i*16+lengthOffset[noteData[l][barNum*barLength+i]], noteData[l+7][barNum*barLength+i], noteData[l][barNum*barLength+i],l,g); for (i=0;i0) g.drawImage(pauses[(m&7)-1],x+8+i*16+pauseOffset[m&7],98,this); if ((m/8)>0) g.drawImage(pauses[(m/8)-1],x+8+i*16+pauseOffset[m/8],31,this); } } public void updateSheet() { if (scrollPos<6) offG.drawImage(clefIm,-scrollPos*8,0,this); j=(scrollPos+barLength*2+1-6)/(barLength*2+1)-1; k=j*8*(barLength*2+1)+46-8*scrollPos; while (j<0) { j++; k+=8*(barLength*2+1); } l=k; while (k<382) { drawBar(k,j,offG); j++; k+=8*(barLength*2+1); } } public void computePauses(int bar) { for (j=0;j0) if (noteData[j+7][bar*barLength+k]<36) for (l=0;l=0;k--) { m=0; for (l=barLength-1;l>=0;l--) { if (occupied[n][l]==0) m++; else m=0; freeRight[l]=m; } for (l=0;l=pauseLength[k]) { noteData[14][bar*barLength+l]+=(1+n*7)*(k+1); for (m=l;m>> j)); audioTable[8192-l]=(byte)(audioTable[8192+l]&0x7f); l++; } j++; n-=16; i*=2; o=m; m+=i; } audioTable[8192]=(byte)255; } public void buildAudioStream() { double fCount[]=new double[7],eCount[]=new double[7],step,goal,nLength,eStep; double d=0,t,fStep[]=new double[7]; step=2.0e-6*speedBar.getValue(); eStep=0.015; rawAudio=new byte[(int)(lastBar/step)+2]; System.gc(); nLength=1.0/barLength; goal=0; for (i=0;i<7;i++) for (j=0;j<64;j++) waveData[i][j]=waveforms[i][j]/30.0; sc=getScale(); k=0; for (i=0;i0) { lCount[j]=noteData[j][i]; fStep[j]=frequencies[noteData[j+7][i]]*0.008; eCount[j]=0; } } goal+=nLength; while (d0) { t+=waveData[j][(int)fCount[j]]*envelopes[j][(int)eCount[j]]; fCount[j]+=fStep[j]; if (fCount[j]>=64.0) fCount[j]-=64.0; eCount[j]+=eStep; if (eCount[j]>63.0) eCount[j]=63.0; } rawAudio[k]=audioTable[8192+(int)(t*sc)]; d+=step; k++; } if ((i%barLength)==0) showStatus("Processing..."+(100*i/lastBar/barLength)+"%"); } } public void buildNoteSample(int note) // Used for playing a single note { double eCount=0,wCount=0,wStep=frequencies[note]*0.008; for (k=0;k<4266;k++) { smallAudio[k]=audioTable[8192+(int)(waveforms[currCol][(int)wCount]* envelopes[currCol][(int)eCount]*0.033)]; eCount+=0.015; wCount+=wStep; if (wCount>=64.0) wCount-=64.0; } } public double getScale() { waveC.extractData(); envC.extractData(); for (i=0;i<7;i++) { k=0; for (j=0;j<64;j++) if (envelopes[i][j]>k) k=envelopes[i][j]; maxVol[i]=k; lCount[i]=0; } l=0; for (i=0;i0) lCount[j]=noteData[j][i]; if (lCount[j]>0) k+=maxVol[j]; } if (k>l) l=k; } if (l>8150) return 8150.0/l; else return 1.0; } public void saveNotes() { int exist[]=new int[7]; waveC.extractData(); // Make sure the waveform and envelopes are up to date waveC.newData(waveforms[currCol],noteCol[currCol]); envC.extractData(); envC.newData(envelopes[currCol],noteCol[currCol]); bufPos=0; sc=getScale(); putFileByte(barLength); putFileByte(speedBar.getValue()-15); putFileByte(lastBar/64); putFileByte(lastBar%64); putFileByte(((int)(sc*4095))/64); putFileByte(((int)(sc*4095))%64); j=6; for (i=0;i<7;i++) { exist[i]=0; k=lastBar*barLength; for (l=0;l0) l=k+1; if (l>k) { exist[i]=1; putFileByte(i); } } putFileByte(40); // Marks end outChars[64]='\0'; while(bufPos<64) outChars[bufPos++]='\0'; for (i=0;i<7;i++) if (exist[i]>0) { for (j=0;j<64;j++) // Save waveform and envelope putFileByte(30+waveforms[i][j]); for (j=0;j<64;j++) { putFileByte(envelopes[i][j]/64); putFileByte(envelopes[i][j]%64); } j=0; // Save note data k=0; l=0; while (j<(lastBar*barLength)) { if (k>63) { putFileByte(72); putFileByte(64); k=0; } else if (noteData[i][j]==0) { j++; k++; } else { if (k>0) { putFileByte(72); putFileByte(k); k=0; } putFileByte(noteData[i+7][j]); putFileByte(noteData[i][j]); j+=noteData[i][j]; } } if (k>0) { putFileByte(72); putFileByte(k); } while(bufPos<64) outChars[bufPos++]='\0'; } System.out.println(outChars); } public void putFileByte(int c) { if (bufPos>63) { System.out.println(outChars); bufPos=0; } outChars[bufPos++]=(char)(32+c); } public void loadNotes(String s) { oldLength=barLength*lastBar; int exist[]=new int[7]; bufPos=0;bufLength=0; try { URL levFile=new URL(getCodeBase(),s); URLConnection fileConn=levFile.openConnection(); fileConn.connect(); fileInput=fileConn.getInputStream(); } catch (Exception ex) {} barLength=getFileByte(); speedBar.setValue(getFileByte()+15); lastBar=64*getFileByte(); lastBar+=getFileByte(); j=getFileByte(); // Read past unnecessary data j=getFileByte(); for (i=0;i<7;i++) exist[i]=0; j=getFileByte(); while (j<8) { exist[j]=1; j=getFileByte(); } for (i=0;i<7;i++) // Read each voice { for (j=0;j<(barLength*lastBar);j++) // Clear noteData[i][j]=0; if (exist[i]>0) { for (j=0;j<64;j++) waveforms[i][j]=getFileByte()-30; for (j=0;j<64;j++) envelopes[i][j]=64*getFileByte()+getFileByte(); if (i==currCol) { waveC.newData(waveforms[currCol],noteCol[currCol]); envC.newData(envelopes[currCol],noteCol[currCol]); } j=0; while (j<(barLength*lastBar)) { k=getFileByte(); l=getFileByte(); if (k<72) // Real note, not pause { noteData[i][j]=(byte)l; noteData[i+7][j]=(byte)k; } j+=l; } } } drawPace(); for (i=0;i(lastBar*barLength)) for (i=lastBar*barLength;i=bufLength) { try { bufLength=fileInput.read(fileBuffer); } catch (Exception ex) {} bufPos=0; } btemp=fileBuffer[bufPos++]; } return (byte)(btemp-32); } public boolean handleEvent(Event e) { scrollPos=bar.getValue(); if ((e.target.equals(bar))&&(scrollPos!=oldScrollPos)) { if ((e.id == Event.SCROLL_ABSOLUTE)||(e.id == Event.SCROLL_PAGE_UP)|| (e.id == Event.SCROLL_PAGE_DOWN)) { updateSheet(); } else if (e.id == Event.SCROLL_LINE_DOWN) { offG2.drawImage(offImage,0,0,this); j=(scrollPos+barLength*2+1-6)/(barLength*2+1)-1; k=j*8*(barLength*2+1)+46-8*scrollPos; while (k<382-8*(barLength*2+1)) { j++; k+=8*(barLength*2+1); } offG.drawImage(offImage2,-8,0,this); drawBar(k,j,offG); } else if (e.id == Event.SCROLL_LINE_UP) { offG2.drawImage(offImage,0,0,this); if (scrollPos<6) offG.drawImage(clefIm,-scrollPos*8,0,this); j=(scrollPos+barLength*2+1-6)/(barLength*2+1)-1; k=j*8*(barLength*2+1)+46-8*scrollPos; while (j<0) { j++; k+=8*(barLength*2+1); } offG.drawImage(offImage2,8,0,this); drawBar(k,j,offG); } repaint(); oldScrollPos=scrollPos; } switch(e.id) { case Event.KEY_PRESS: checkKey(e.key,e.controlDown()); break; case Event.MOUSE_MOVE: mx=e.x; my=e.y; break; case Event.MOUSE_DOWN: // Note selected? i=getBarNum(); if (i>=0) { n=-1; m=100; j=getXOffset(i); for (l=6;l>=0;l--) for (k=0;k0) { o=k*16+11+lengthOffset[noteData[l][barLength*i+k]]-j; o*=o; o+=(9+noteH[noteData[l+7][barLength*i+k]]-my)* (9+noteH[noteData[l+7][barLength*i+k]]-my); if ((o<100)&&(o=0) { selectedCol=n&7; selectedPos=barLength*i+(n/8); selectedLen=noteData[selectedCol][selectedPos]; selectedVal=noteData[selectedCol+7][selectedPos]; noteData[selectedCol][selectedPos]=0; noteData[selectedCol+7][selectedPos]=0; barStart=mx-j-9; stripX=9+barStart+4+16*(n/8)+lengthOffset[selectedLen]; dx=stripX-Math.max(Math.min(stripX,375),9); drawBar(barStart-stripX+9+dx,i,sG); sG2.drawImage(strip,0,0,this); drawNote(dx,selectedVal,selectedLen,selectedCol,sG); drawStrip=true; stripX-=dx; repaint(); } } break; case Event.MOUSE_DRAG: // Note dragged? if (selectedLen>0) { my=e.y; selectedVal=-1; j=25; for (i=0;i<72;i++) { k=9+noteH[i]-2*noteHash[i]-my; k*=k; if (k0) drawNote(dx,selectedVal,selectedLen,selectedCol,sG); drawStrip=true; repaint(); } break; case Event.MOUSE_UP: // Note released? if (selectedLen>0) { drawStrip=false; if (selectedVal>=0) { noteData[selectedCol][selectedPos]=(byte)selectedLen; noteData[selectedCol+7][selectedPos]=(byte)selectedVal; } computePauses(selectedPos/barLength); drawBar(barStart,selectedPos/barLength,offG); selectedLen=0; repaint(); } break; case Event.ACTION_EVENT: if (e.target instanceof Button) { for (i=0;i<7;i++) if (e.target.equals(noteB[i])) { currCol=i; waveC.extractData(); waveC.newData(waveforms[i],noteCol[i]); envC.extractData(); envC.newData(envelopes[i],noteCol[i]); } p=-1; for (i=0;i<9;i++) if (e.target.equals(controlB[i])) p=i; switch(p) { case 6: // Load file choiceHolder.show(); validate(); break; case 8: // "Save" file saveNotes(); break; case 7: // Reset waveform & envelope for (i=0;i<64;i++) { waveforms[currCol][i]=waveCopy[currCol][i]; envelopes[currCol][i]=envCopy[currCol][i]; } waveC.newData(waveforms[currCol],noteCol[currCol]); envC.newData(envelopes[currCol],noteCol[currCol]); break; case 0: // Generate melody and play waveC.extractData(); envC.extractData(); AudioPlayer.player.stop(soundStream); buildAudioStream(); soundStream = new AudioDataStream(new AudioData(rawAudio)); AudioPlayer.player.start(soundStream); break; case 1: // Play AudioPlayer.player.stop(soundStream); soundStream = new AudioDataStream(new AudioData(rawAudio)); AudioPlayer.player.start(soundStream); break; case 2: // Stop AudioPlayer.player.stop(soundStream); break; case 5: // Clear for (i=0;i=0) { j=getXOffset(i); for (k=0;k0)&&(k=(key&15))) { l=k; m=n; } } if (l>=0) { n=100; for (k=0;k<72;k++) // Find closest note { o=9+noteH[k]-my; o*=o; if (o0)) // Hashed? m++; noteData[currCol+7][barLength*i+l]=(byte)m; lastNote=barLength*i+l; o=j; computePauses(i); if (i=0) { for (j=0;j0)&&(i==(lastBar-1))) // Move the end mark? { for (j=0;j=0) { if ((key==80) && (noteHash[n+1]>0)) // Hashed? n++; buildNoteSample(n); AudioPlayer.player.stop(soundStream); soundStream = new AudioDataStream(new AudioData(smallAudio)); AudioPlayer.player.start(soundStream); } break; case 8: // Delete i=getBarNum(); if (i>=0) { n=-1; m=100; j=getXOffset(i); for (l=6;l>=0;l--) for (k=0;k0) { o=k*16+11+lengthOffset[noteData[l][barLength*i+k]]-j; o*=o; o+=(9+noteH[noteData[l+7][barLength*i+k]]-my)* (9+noteH[noteData[l+7][barLength*i+k]]-my); if ((o<100)&&(o=0) { noteData[n&7][barLength*i+(n/8)]=0; noteData[n&7+7][barLength*i+(n/8)]=0; o=j; m=0; for (j=0;j0)&&(i==(lastBar-1))) { for (j=0;j=9)&&(mx<391)&&(my>=9)&&(my<155)&&(mx-46+scrollPos*8>=0)) return (mx-9-46+scrollPos*8)/(barLength*16+8); else return -1; } public int getXOffset(int b) { return mx-9-46+scrollPos*8-b*(barLength*16+8); } public void paint(Graphics g) { g.drawImage(splash1,0,0,370,7,this); g.drawImage(splash2,0,7,7,100,this); g.setColor(Color.gray); g.draw3DRect(8,8,383,143,false); g.draw3DRect(7,7,385,145,false); g.setColor(Color.white); g.drawImage(offImage,9,9,this); } public void update(Graphics g) { if (drawStrip) { g.drawImage(strip,stripX,9,this); drawStrip=false; } else g.drawImage(offImage,9,9,this); } } class ActiveCanvas extends Canvas { private Color c; private int graphData[],inData[],maxVal,minVal; private int i,j,k,l,m,startX=0,startY=0,ix1=0,ix2=0; private Dimension d; private boolean visualized=false,altered=false; private double a; ActiveCanvas(Color curve, int data[],int min,int max) { this.setBackground(Color.white); c=curve; inData=data; maxVal=max; minVal=min; } public void newData(int data[],Color curve) { altered=false; c=curve; inData=data; visualized=false; repaint(); } public void extractData() { if (altered) { d=this.size(); for (i=0;i<64;i++) { inData[i]=minVal+(maxVal-minVal)*(d.height-1-graphData[i*d.width/64])/d.height; } } } public boolean mouseDown(java.awt.Event evt, int x, int y) { startX=x; startY=y; return false; } public boolean mouseUp(java.awt.Event evt, int x, int y) { repaint(); return false; } public boolean mouseDrag(java.awt.Event evt, int x, int y) { d=this.size(); i=Math.max(Math.min(startX,x),0); j=Math.min(Math.max(startX,x),d.width-1); if (i!=j) { altered=true; if (x>startX) { l=startY; m=y; } else { l=y; m=startY; } l=Math.min(Math.max(0,l),d.height-1); m=Math.min(Math.max(0,m),d.height-1); for (k=i;k<=j;k++) graphData[k]=(int)(1.0*(m*(k-i)+l*(j-k))/(j-i)); startX=x; startY=y; ix1=i; ix2=j+1; repaint(); } return false; } private void prepareGraph() { d=this.size(); graphData=new int[d.width]; for (i=0;i