Java tutorial
/* * Computoser is a music-composition algorithm and a website to present the results * Copyright (C) 2012-2014 Bozhidar Bozhanov * * Computoser is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * Computoser is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Computoser. If not, see <http://www.gnu.org/licenses/>. */ package com.music.tools; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.Map.Entry; import jm.constants.Scales; import jm.music.data.Note; import jm.music.data.Part; import jm.music.data.Score; import jm.music.tools.PhraseAnalysis; import jm.util.Play; import jm.util.Read; import com.google.common.collect.HashMultiset; import com.google.common.collect.Multiset; public class MidiAnalyzer { public static void main(String[] args) { Score score = new Score(); Read.midi(score, "C:\\workspace\\music\\analysis\\midi\\jarre\\EQUINOX3.MID"); for (Part part : score.getPartArray()) { System.out.println(part.getTitle() + " : " + part.getInstrument()); } Part part = score.getPart(1); System.out.println(part.getInstrument()); part.setTempo(160); int previousPitch = 0; int prePreviousPitch = 0; System.out.println(score.getTimeSignature()); Multiset<Integer> uniqueIntervals = HashMultiset.create(); int directionChanges = 0; int directionRetentions = 0; LinkedList<Double> noteLengths = new LinkedList<>(); for (Note note : part.getPhrase(0).getNoteArray()) { System.out.println(note.getPitch()); if (!note.isRest()) { if (prePreviousPitch != 0) { int previousDiff = previousPitch - prePreviousPitch; int diff = note.getPitch() - previousPitch; if (Math.signum(previousDiff) != Math.signum(diff) && diff != 0 && previousDiff != 0) { directionChanges++; System.out.println(prePreviousPitch + ":" + previousPitch + ":" + note.getPitch()); } else if (diff != 0 && previousDiff != 0) { directionRetentions++; } } if (note.getPitch() - previousPitch != 0) { prePreviousPitch = previousPitch; } uniqueIntervals.add(previousPitch - note.getPitch()); previousPitch = note.getPitch(); } noteLengths.add(note.getRhythmValue()); } double normalizedBeatSize = 1d * score.getNumerator() * 4 / score.getDenominator(); System.out.println("Beat size: " + normalizedBeatSize); double currentBeatSize = 0; int beats = 0; int beatsWithPerfectHalves = 0; // reverse, to avoid off-beats for (Iterator<Double> it = noteLengths.descendingIterator(); it.hasNext();) { currentBeatSize += it.next(); ; if (currentBeatSize >= normalizedBeatSize) { currentBeatSize = 0; beats++; } if (currentBeatSize == normalizedBeatSize / 2) { beatsWithPerfectHalves++; } } System.out.println("Beats:beats with perfect halves -- " + beats + ":" + beatsWithPerfectHalves); Hashtable<String, Object> table = PhraseAnalysis.getAllStatistics(score.getPart(1).getPhrase(0), 1, 0, Scales.MAJOR_SCALE); for (Entry<String, Object> entry : table.entrySet()) { System.out.println(entry.getKey() + "=" + entry.getValue()); } for (Integer interval : uniqueIntervals.elementSet()) { System.out.println(interval + " : " + uniqueIntervals.count(interval)); } System.out.println("---"); System.out.println(directionChanges + " : " + directionRetentions); Play.midi(part); } }