Muusika Helilõigud, MIDI, saatehääl, kolmkõlad, kvanditud heli, stereo Klippide mängimine Esimesest versioonist peale suudavad java programmid mängida au lihtsamas formaadis faile. Versioonist 1.2 on juurde liidetud ka muude (wav, midi) helifailitüüpide mängimise võimalus. Muusika mängimiseks tuleb luua AudioClip. Selle meetoditega play, loop ning stop saab panna klipi mängima ning mängimine katkestada. Loop tähendab, et klippi mängitakse pidevalt, s.t. pärast lõpetamist hakatakse mängimisega uuesti algusest peale. import java.applet.*; public class Muusika1 extends Applet{ public void start(){ AudioClip lugu=getAudioClip(getCodeBase(), "spacemusic.au"); lugu.play(); } } Järgneva näite puhul hakatakse korduvalt mängima lehele tulles ning lehelt lahkudes lõpetatakse mängimine. import java.applet.*; public class Muusika2 extends Applet{ AudioClip lugu; public void init(){ lugu=getAudioClip(getCodeBase(), "spacemusic.au"); } public void start(){ lugu.loop(); } public void stop(){ lugu.stop(); } } Iseseisva programmi puhul saab klipi kätte klassi Applet staatilise meetodi newAudioClip abil, meetodi parameetriks on helifaili URL. import java.applet.*; import java.net.URL; public class Muusika3a{ public static void main(String argumendid[]) throws Exception{ AudioClip lugu=Applet.newAudioClip( new URL("http://minitorn.tpu.ee/~jaagup/kool/java/"+ "abiinfo/tutorial/sound/example-1dot2/bottle-open.wav") ); lugu.play(); Thread.sleep(5000); } } Kui soovitakse mängida lugu samast masinast, siis tuleb ka see kohalik aadress enne URLiks muuta. import java.applet.*; import java.net.URL; public class Muusika3{ public static void main(String argumendid[]) throws Exception{ AudioClip lugu=Applet.newAudioClip( new File("spacemusic.au").toURL() ); lugu.play(); Thread.sleep(5000); } } MIDI Lisaks varemvalminud lugude esitamisele saab ka ise meloodiaid kokku panna. MIDI abil saame määrata, millist nooti millal mängida. Salvestatud pillide helinäidete järgi luuakse selle tulemusena meie poolt küsitud hääl. Kui soovitakse samaaegselt kuulda mitme pilli meloodiat, tuleb need paigutada eri kanalitele. Iga kanal võib korraga teha ühe pilli häält ning harilikult on kanaleid kokku kuni 16. Kanalist väljuvat heli saab kontrollida sinna saadetavate käskudega. Enamkasutatavad on noteOn ja noteOff. Esimene neist palub nooti mängima hakata, teine mängimise lõpetada. Meetod noteOn vajab kahte parameetrit: heli kõrgust ja valjust, noodi kõlamise lõpetamiseks piisab noodi numbrist. MIDI standardi järgi on igal pooltoonil oma number vahemikus 0-127. Esimese oktaavi C väärtuseks on näiteks 60, sealt saab siis vastavalt poole tooni kaupa üles ja allapoole arvutada. Valjust tähistab samuti number samast vahemikust. MIDI vahendid asuvad paketis javax.sound, mis kuulub standardvahendite hulka alates JDK versioonist 1.3. Operatsiooni muusikavahendite poole pöördumiseks saab kasutada klassi MidiSystem. Üksik noot Järgnevas näites küsitakse selle klassi kaudu helitekitamise seade ehk süntesaator ning avatakse. Viimase käest küsitakse tema külge kuuluv kanalite massiiv ning sealt omakorda kanal nr. 0. Järgnevalt palun vastaval kanalil mängida A nooti (noot nr. 69) valjusega 65. Ootan sekundi ning siis lasen noodi kõlamise lõpetada. System.exit viimase käsuna on tarvilik, kuna MIDI vahendite tarvitamisega virtuaalmasina poolt loodud lõim ei oska nootide lõpuga oma tööd lõpetada ning programm jääks viimasele reale rippuma. Analoogiline olukord on ka graafikakomponentide juures, kus programmi töö lõpetamiseks tuleb kirjutada System.exit(0). import javax.sound.midi.*; public class Noot{ public static void main(String argumendid[]) throws Exception{ Synthesizer synthesizer=MidiSystem.getSynthesizer(); synthesizer.open(); MidiChannel kanal=synthesizer.getChannels()[0]; //kanal 0; int korgus=69; //A int valjus=65; //keskmine kanal.noteOn(korgus, valjus); Thread.sleep(1000); kanal.noteOff(korgus); System.exit(0); } } Kromaatiline heliredel Kromaatilist heliredelit võib mängida tsükli abil: for(int i=40; i<120; i++){ kanal.noteOn(i, 60); Thread.sleep(200); kanal.noteOff(i); } Kui soovida, et samal kanalil mängiks korraga mitu nooti, tuleb lihtsalt ükshaaval määrata, millised helikõrgused peavad kõlama. Kõikide mängimise saab korraga lõpetada käsuga allNotesOff(). Helikõrguse ujumine Kuigi MIDI puhul öeldakse helikõrgus numbriga ette, on ka siin võimalik toonil ujuda lasta. Seda saab käsuga setPitchBend, andes ette numbri, palju kõrgust muuta. Vaikimisi väärtuseks on 8192, sellisel juhul vastab noodi number tema helikõrgusele. Iga number sellest ülespoole viib helikõrgust kõrgemale, allapoole aga madalamaks. Vaikiva kokkuleppe järgi tähistab number 0 tooni võrra madalamat ning 16363 tooni jagu kõrgemat heli, kuid see kõikumise piirkond võib ka erineda. Järgnevas näites peaks tooni ülalt alla ujumine kuulda olema. kanal.noteOn(60, 70); kanal.noteOn(64, 70); for(int korgus=16383; korgus>0; korgus-=500){ Thread.sleep(200); kanal.setPitchBend(korgus); } kanal.allNotesOff(); Pillide loetelu Kanalil mängivat instrumenti saab muuta käsuga programChange, andes parameetritena ette uue pilli helipanga ning panga sees sellele pillile vastava programmijupi järjenumbri. Süntesaatorile kättesaadavad pillid saab küsida getDefaultSoundbank().getInstruments() abil. All näites paiknevad trükitakse tsüklis järgemööda välja pillide nimed ning mängitakse igal pillil noot. Instrument[] pillid=synthesizer.getDefaultSoundbank(). getInstruments(); MidiChannel kanal=synthesizer.getChannels()[0]; for(int i=0; i" + name + "", seq); sequenceNode = new DefaultMutableTreeNode(noh); Track[] rajad = seq.getTracks(); System.out.println(rajad.length+" rada"); for (int nr = 0; nr < rajad.length; nr++){ trackNode = new DefaultMutableTreeNode(rajad[nr]); sequenceNode.add(trackNode); } treeModel.insertNodeInto(sequenceNode, rootNode, rootNode.getChildCount()); } public void actionPerformed(ActionEvent e) { if (e.getSource() == btnPlay) { play(); } else if (e.getSource() == btnStop) { stop(); } else if (e.getSource() == btnCopy) { copyTrack(); } else if (e.getSource() == btnNew) { newSequence(); } else if (e.getSource() == btnCut) { cutTrack(); } else if (e.getSource() == btnPaste) { pasteTrack(); } else if (e.getSource() == btnDelete) { deleteTrack(); } else if (e.getSource() == mnLoad) { loadFile(); } else if (e.getSource() == mnSave) { saveFile(); } } JFileChooser fc = new JFileChooser(); public void loadFile() { int returnVal = fc.showOpenDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { file = fc.getSelectedFile(); try { System.out.println("Opening: " + file.getCanonicalPath()); sekvents = MidiSystem.getSequence(file); addSeqenceToTree(sekvents, file.getName()); } catch (Exception ex) { ex.printStackTrace(); } } else { System.out.println("Open command cancelled by user."); } } public void saveFile() { sekvents = getCurrentSequence(); //millist faili salvestada if (sekvents == null) return; int returnVal = fc.showSaveDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { file = fc.getSelectedFile(); try { MidiSystem.write(sekvents, 1, new FileOutputStream(file.getCanonicalPath())); System.out.println("Saved: " + file.getCanonicalPath()); } catch (IOException ex) { ex.printStackTrace(); } } else { System.out.println("Save command cancelled by user."); } } JMenuItem mnUus, mnLoad, mnSave; public JMenuBar createMenuBar() { JMenuBar menuBar = new JMenuBar(); JMenu menu = null; JMenuItem menuItem = null; menu = new JMenu("Failid"); menuItem = new JMenuItem("Lae.."); menuItem.addActionListener(this); menu.add(menuItem); mnLoad = menuItem; menuItem = new JMenuItem("Salvesta.."); menuItem.addActionListener(this); menu.add(menuItem); mnSave = menuItem; menuBar.add(menu); return menuBar; } public static void main(String[] args) { // JFrame.setDefaultLookAndFeelDecorated(true); // Käsk kasutatav alates JDK versioonist 1.4 JFrame frame = new JFrame("KMidi"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); KMidi kodContentPane = new KMidi(); kodContentPane.setOpaque(true); frame.setJMenuBar(kodContentPane.createMenuBar()); frame.setContentPane(kodContentPane); frame.pack(); frame.setSize(600, 400); frame.setVisible(true); } } /** * Vahend, mille abil hoida objekti koos tema juurde kuuluva sildiga * Swingi puu tarvis esitataval kujul. Kasutatakse näiteks sekventsi * hoidmiseks. */ class NodeObjectHolder { public String label = "no name"; public Object userObject = null; public NodeObjectHolder() { } public NodeObjectHolder(String label, Object userObject) { this.label = label; this.userObject = userObject; } public String toString() { return label; } } Ülesandeid Mandoliin · Joonista ekraanile mandoliin. · Kasutaja saab määrata joonistatavate krihvide arvu ning kaela laiust. · Vajutades keele ja krihvi ristumiskohale, kõlab sellele vastav heli. Kitarri mudel · Joonista 6-keelse kitarri kaela mudel · Mängi kitarriakord (E, H, G, D, A, E) (64, 59, 55, 50, 45, 40) · Peenemal keelel saab määrata, milline krihv on alla vajutatud. Hääl kõlab vastavalt vajutatule · Krihve saab valida ka teiste keelte puhul ning kuulata tulemust · Lisaks võib valida täisakorde. Akordion · Joonista klaviatuuri ja 36 bassiga akordion. · Basside ridade ja veergude arvu saab kasutaja määrata. Samuti hiire abil lõõtsa lahti ja kokku vedada. · Lisaks eelmisele kõlab bassinuppudele vajutades neile vastav heli. Vilepill · Joonista vilepill. Pillil on avatud tekstiväljas määratud hulk auke. · Lisaks eelmisele teeb pillile vajutamisel viimane häält. · Augule vajutamisel on augud lõpust kuni sinnani avatud. Kõlab sellisele sõrmede paigutusele vastav hääl. MIDI fail · Mängi MIDI fail · Väljasta radade arv · Salvesta fail tooni jagu kõrgemalt. · Kopeeri faili muusika iseendale sappa · Lisa rada, kus viisi mängitakse nihkega (kaanon)