package com.moseph.mra.agent; import java.awt.BorderLayout; import java.util.*; import javax.swing.*; import com.moseph.mra.*; import com.moseph.mra.agent.analyser.*; import com.moseph.mra.agent.attribute.*; import com.moseph.mra.visualise.*; import static com.moseph.mra.MRAUtilities.*; public class AnalysisSystem implements GuiComponent { Context context; List<Analyser> analysers; Map<String,Analyser> analyserMap; public static final double DEFAULT_SMOOTHING = 0.3; double smoothing = DEFAULT_SMOOTHING; FeatureSet featureSet; MusicianInformation me; String myName; ForceAnalysisSettings settings; AnnotatedScore annotatedWindow; AnalysisWindow window; double analysisLength = 4.0; boolean analyseSelf = true; boolean forceImmediateAnalysis = false; static double DEFAULT_ANALYSIS_LENGTH = 4.0; double patternOffset = 0.0; Box guiBox; boolean hasGUI = false; Score current; Map<String,FragmentDisplay> visualisers = new HashMap<String, FragmentDisplay>(); double chunkSize = 0.5; public AnalysisSystem( Context c, double analysisLength ) { this.context = c; me = context.getMyID(); //myName = me.getMusician().getName(); this.analysisLength = analysisLength; featureSet = context.getFeatures(); analysers = new Vector<Analyser>(); analyserMap = new HashMap<String, Analyser>(); window = new AnalysisWindow(analysisLength); } public AnalysisSystem( Context c ) { this( c, DEFAULT_ANALYSIS_LENGTH ); } public AnalysisSystem( Context c, double analysisLength, ForceAnalysisSettings settings ) { this( c, analysisLength ); this.settings = settings; } public AnalysisSystem( Context c, ForceAnalysisSettings settings, String...analysers ) { this( c, DEFAULT_ANALYSIS_LENGTH, settings, analysers ); } public AnalysisSystem( Context c, double analysisLength, ForceAnalysisSettings settings, String...analysers ) { this( c, analysisLength, settings ); for( String name : analysers ) addAnalyser( name ); } public void analyse( Score s ) { chunkSize = s.getLength(); if( forceImmediateAnalysis ) doAnalysis( s ); else { window.add( s ); setPatternOffset( window.getEndPoint() ); //System.out.println( "Analysing: " + window.getStartPoint() + " with pattern offset " + getPatternOffset() ); doAnalysis( window.getCurrent() ); } //featureSet.printFeatures(); } void doAnalysis( Score s ) { current = s; if( ! analyseSelf ) s.removeFragmentForName( me.getName() ); //System.out.println( "+++++++++++++ Doing analysis on length:" + s.getLength() + "\n" ); //System.err.println( "Analysing: " + s.copyChunk( pa, end ) ); for( Analyser analyser : analysers ) { //System.out.println( "Running Analyser: " + analyser.getFeature() ); analyser.analyse( s ); } //System.out.println( context ); //System.out.println( "Done Analysis!" ); if( hasGUI ) updateGUI(); } void setPatternOffset( double windowEnd ) { double patternStart = context.getPatternPointBefore( windowEnd ); //Fragments are delayed by 2 chunks by the time they're analysed! patternOffset = window.getStartPoint() - patternStart - chunkSize * 2; //System.out.println( "Setting pattern offset: " + patternOffset + " from ws: " + windowEnd + " and " + patternStart ); } public void addAnalyser( String name ) { addAnalyser( name, smoothing ); } public void addAnalyser( String name, double smooth ) { System.out.println( "Adding analyser: " + name ); Analyser analyser = null; if( name.equals( "Dynamics")) analyser = new DynamicAverageAnalyser( context, smooth ); else if( name.equals( "Density")) analyser = new DensityAnalysis( context, smooth ); else { if( analyserMap.containsKey( name )) return; String classname = "com.moseph.mra.agent.analyser." + name + "Analyser"; try { Class analyserClass = Class.forName( classname ); analyser = (Analyser)analyserClass.getConstructor( new Class[] { context.getClass(), java.lang.Double.TYPE } ).newInstance( context, new Double( smooth ) ); } catch( Exception e ) { System.out.println( "Bad analyser for " + me.name + ": " + name + "(from classname: " + classname + "\n" + e ); e.printStackTrace(); } } if( analyser != null ) { List<String> deps = analyser.dependsOn(); String depsString = "[ "; for( String d : deps ) depsString += d + " "; depsString += " ]"; //System.out.println( "+++" + depsString ); for( String dep : deps ) { //System.out.println( "+ Checking dep: " + dep ); if( ! analyserMap.containsKey( dep ) ) { //System.out.println( "Fixing dependancy: " + dep ); addAnalyser( dep ); } } analyser.setAnalyseSelf( analyseSelf ); analyser.setAnalysisSystem( this ); analyser.init(); analysers.add( analyser ); analyserMap.put( name, analyser ); } } public void setSmoothing( double smoothing ) { this.smoothing = smoothing; } public boolean isForceImmediateAnalysis() { return forceImmediateAnalysis; } public void setForceImmediateAnalysis( boolean forceImmediateAnalysis ) { this.forceImmediateAnalysis = forceImmediateAnalysis; } public boolean isAnalyseSelf() { return analyseSelf; } public void setAnalyseSelf( boolean analyseSelf ) { this.analyseSelf = analyseSelf; } /** * Gets the offset between the start of the analysis window and the last "PatternPoint" * This should be added to any pattern analysis which is done, so that patterns are correctly timed * @return */ public double getPatternOffset() { return patternOffset; } public AnalysisWindow getWindow() { return window; } public JComponent getGUIComponent() { if( guiBox == null ) guiBox = new Box( BoxLayout.Y_AXIS ); addAnalysersToBox( guiBox ); hasGUI = true; return guiBox; } void updateGUI() { if( !hasGUI || guiBox == null || current == null ) return; //guiBox.removeAll(); for( Fragment f : current.getFragments() ) { String name = f.getMusician( ).getName(); FragmentDisplay fv = visualisers.get( name ); if( fv == null ) { JPanel p = new JPanel(); p.setBorder( BorderFactory.createTitledBorder( f.getMusician( ).getName() ) ); p.setLayout( new BorderLayout() ); fv = new FragmentDisplay( f ); fv.setForceWidth( analysisLength ); p.add( BorderLayout.CENTER, fv ); guiBox.add( p ); visualisers.put( name, fv ); } fv.setFragment( f ); } //guiBox.revalidate(); } void addAnalysersToBox( Box b ) { for( Analyser a : analysers ) { if( a instanceof GuiComponent ) b.add( ( (GuiComponent)a ).getGUIComponent() ); } } public void setMinNotes( int min ) { for( Analyser a : analysers ) a.setMinNotes( min ); } public List<Analyser> getAnalysers() { return new Vector<Analyser>( analysers ); } }