view Block.java @ 47:be66ee2fe9fe

Added abstract class EndBlockPanel to deliver end of block messages (e.g. end of practice block). Added and implemented EndTestPanel which gives "thank you for participating" etc message at end of test.
author Carl Bussey <c.bussey@se10.qmul.ac.uk>
date Thu, 13 Jun 2013 18:33:34 +0100
parents 014c83185b2a
children
line wrap: on
line source
/*=============================================================================
 * File:       Block.java
 * Author:     Marcus Pearce <m.pearce@gold.ac.uk>
 * Created:    <2008-01-07 10:38:45 marcusp>
 * Time-stamp: <2011-12-09 17:59:20 marcusp>
 *=============================================================================
 */

import java.util.Collections;
import java.util.ArrayList; 
import java.util.Iterator;
import java.util.HashMap;
import java.io.*;

public class Block { 
    
    /* Label */ 
    private String label; 
    private boolean writeResults; 

    /* the list of midi files, the current midi file and the midi directory*/ 
    private FileList filelist; 
    private String filename; 
    private int melodyNumber; 

    /* The Experiment and GUI */ 
    private ExperimentGui gui; 
    private Experiment exp; 
    
    /* The MidiPlayer */ 
    private MidiPlayer mp; 

    /* Probe positions, note onsets, durations, IOIs and pitches */ 
    //private ArrayList probes, onsets, iois, durations, pitches, clockStartTimes; 
    private ArrayList<Integer> iois, pitches;
    private ArrayList<Long> onsets, durations, clockStartTimes;
    private ArrayList<ProbeID> probes;
    private long tatum; 

    /* The start of the song in nanoseconds */ 
    private long startTime; 
    
    /* Results */ 
    private MelodyResults mResults; 
    
    /* whether the current song has run yet or not */ 
    private boolean hasRun;

    /*
     * Accessors 
     */ 
    public String getLabel() { return label; }
    public int getMelodyNumber() { return melodyNumber; }
    public void setMelodyNumber(int n) { melodyNumber = n; }
    public long getTatum() { return tatum; } 
    public MelodyResults getMelodyResults() { return mResults; }
    public ArrayList getProbePositions() { return probes; } 
    public ArrayList<Integer> getInterOnsetIntervals() { return iois; } 
    public ArrayList<Long> getOnsets() { return onsets; } 
    public ArrayList<Long> getClockStartTimes() { return clockStartTimes; } 
    public MidiPlayer getMidiPlayer() { return mp; }

    /* set the start time in nanoseconds to NOW */ 
    public long getStartTime() { return startTime; }
    public void setStartTime() { startTime = System.nanoTime(); }
    
    /* 
     * constructor 
     */ 
    public Block(Experiment e, ExperimentGui eg, String fl, String lab, 
                 boolean wr) { 
        // set-up variables 
        exp = e; 
        gui = eg; 
        label = lab; 
        filelist = new FileList(fl); 
        filename = (String)filelist.currentFile(); 
        melodyNumber = 1; 
        writeResults = wr; 
        // initialise the block 
        hasRun = false; 
        initialiseBlock();

        // Initialise the Midiplayer - already done in initialiseBlock?
        //mp = new MidiPlayer(exp.getMidiDirectory().concat(filename), exp.getMidiDeviceNumber(), false);

        // Write out stimulus structure for all melodies in block
        //writeStimuli();
    }

    /* initialise the block */ 
    public void initialiseBlock() { 
	if (exp.getDebug())
	    System.out.println("Initialising block for " + filename);

        // Initialise the Midiplayer 
        mp = new MidiPlayer(exp.getMidiDirectory().concat(filename), exp.getMidiDeviceNumber(), false); 
        // Set up the melody structure and the probe positions 
        setupSong(); 
        setupProbes();
        if (exp.getDebug())
            printProbes();
        // Set up the results object for this melody
        mResults = new MelodyResults(filename, probes, 
                                     onsets, iois, durations, pitches); 
        mResults.setSubjectID(exp.getSubjectID()); 
        hasRun = false; 
    }

    public void storeMelodyResult() { 
        if (writeResults && hasRun)
            exp.addToSubjectResults(mResults); 
    }
    
    private void setupSong() { 
        // Get the note IOI and Onset lists 
        onsets = mp.getOnsets(); 
        durations = mp.getDurations(); 
        iois = mp.getInterOnsetIntervals(); 
        pitches = mp.getPitches(); 
        tatum = mp.getTatum();
        if (exp.getDebug())
            System.out.println("\nTatum = " + tatum);
    }

    private void setupProbes() { 
        ArrayList probePos = filelist.currentProbes(); 
        Iterator ppi = probePos.iterator(); 
        
        // By convention, the first probe position is the unexpected
        // one and  the second is the expected one. 
        //probeValues.add(ProbeID.PROBE_UNEX); 
        //probeValues.add(ProbeID.PROBE_EX); 

        ArrayList probeValues = new ArrayList(probePos.size()); 
        for (int i = 0; i < probePos.size(); i++)
            probeValues.add(ProbeID.PROBE);
        Iterator pvi = probeValues.iterator(); 

        // Set up probes 
        probes = new ArrayList(onsets.size()); 
        for (int i = 0; i < onsets.size(); i++) 
            probes.add(ProbeID.NOT_PROBE); 

        while(ppi.hasNext()) { 
            int probe = ((Integer)ppi.next()).intValue();
	    System.out.println(filename + ": probe at " + (probe + 1) + " out of " + onsets.size());
            // probes.set(probe - numEvents, ProbeID.START_CLOCK); 
            
            probes.set(probe - 1, ProbeID.BEFORE_PROBE); 
            probes.set(probe, (ProbeID)pvi.next()); 
            if (probe < (onsets.size() - 1)) 
                probes.set(probe + 1, ProbeID.AFTER_PROBE); 
        }
        
        // Set up the clock start times 
        clockStartTimes = new ArrayList(probePos.size()); 
        long clockTimeInMicroseconds = 
            (tatum * exp.getClockUnits() * exp.getNumUnits()); 
        for (int i = 0; i < probePos.size(); i++) { 
            int ppos = ((Integer)probePos.get(i)).intValue(); 
            long onset = ((Long)(onsets.get(ppos))).longValue(); 
            clockStartTimes.add(onset - clockTimeInMicroseconds);
            if (exp.getDebug())
                System.out.println("ppos = " + ppos + "; onset = " + onset + "; clockTimeInMicroseconds = " + clockTimeInMicroseconds);
        }
        try { 
            Collections.sort(clockStartTimes); 
        } catch (Exception e) { 
            e.printStackTrace(); 
        }
    }
   

    public void printProbes() { 
        Iterator pi = probes.iterator(); 
        Iterator oi = onsets.iterator(); 

        int i = 1; 
	System.out.println("Events for " + filename + "...");
        while(pi.hasNext() && oi.hasNext()) { 
            System.out.println("Event " + i + ": " + pi.next() + ", " + oi.next()); 
            i++; 
        }
    }
                
    public String nextFile() {
        filelist.incrementFileIndex(); 
        filename = filelist.currentFile(); 
        melodyNumber = melodyNumber + 1; 
        return filename;
    }

    /* add a reponse i and time t (nanoseconds) */ 
    public void addResponse(int i, long t) { 
        //System.out.println("answer = " + i + 
        //                    "; responseTime = " + t + 
        //                    "; startTime = " + startTime + 
        //                    "; answer = " + (t - startTime) / 1000); 
        // add relative responseTime in microseconds 
        mResults.addResponse(i, (t - startTime) / 1000); 
    }

    public void addMelodyQA(String q, String a) { 
        mResults.addQuestion(q); 
        mResults.addAnswer(a); 
    }

    public void presentStimulus() { 
        // Start the experiment 
        //mp.stop();
        setStartTime(); 
        mp.play(); 
        hasRun = true; 
        
        // Wait for midi file to stop playing 
        //try { Thread.sleep((mp.getLength() / 1000) + 2000); } 
        //catch (InterruptedException e) {}
    }

    public boolean isRunning() { return mp.getSequencer().isRunning(); }
    public boolean hasRun() { return hasRun; } 


    /* 
     * Write out stimulus onsets and probe positions 
     */ 

    public void writeStimuli() {
        String midiFile; 
        while((midiFile = filelist.currentFile()) != null) { 
            
            Writer writer = null;
            String composition = midiFile.substring(0, midiFile.length() - 4);
            String outFile = 
                exp.RESULTS_DIRECTORY + File.separator + 
                "stimuli" + File.separator + composition 
                + ".onsets"; 
            File outputFile = new File(outFile); 
            
            MidiPlayer midip = 
                new MidiPlayer(exp.getMidiDirectory().concat(midiFile), exp.getMidiDeviceNumber(), false); 

            // Setup the probes 
            ArrayList probePos = filelist.currentProbes(); 
            // Write the data 
            try {
                writer = new FileWriter (outputFile, true);
            } catch (IOException e) {
                System.out.println("Could not write file: " + 
                                   outputFile.getPath());
                return;
            }
            try {
                writeResults(writer, midip, probePos, composition); 
                writer.close();
            } catch (IOException e) {
                System.out.println (e.getMessage());
                return;
            }
            // increment the file index 
            filelist.incrementFileIndex(); 
        }
        // Reset filelist 
        filelist.setFileIndex(0); 
    }

    private void writeResults(Writer w, MidiPlayer mipl, ArrayList probePos, 
                              String composition) 
        throws IOException { 

        System.out.println(composition); 

        ArrayList ons = mipl.getOnsets(); 
        ArrayList pits = mipl.getPitches(); 
        
        Iterator oi = ons.iterator(); 
        Iterator piti = pits.iterator(); 

        // setup probes 
        Iterator ppi = probePos.iterator(); 
            
        // By convention, the first probe position is the unexpected
        // one and  the second is the expected one. 
        // probeValues.add(ProbeID.PROBE_UNEX);
        // probeValues.add(ProbeID.PROBE_EX);

        ArrayList probeValues = new ArrayList(probePos.size()); 
        for (int i = 0; i < probePos.size(); i++)
            probeValues.add(ProbeID.PROBE);

        Iterator pvi = probeValues.iterator(); 
        
        ArrayList pprobes = new ArrayList(ons.size()); 
        for (int i = 0; i < ons.size(); i++) 
            pprobes.add(ProbeID.NOT_PROBE); 
        
        while(ppi.hasNext()) { 
            int probe = ((Integer)ppi.next()).intValue(); 
            pprobes.set(probe - 1, ProbeID.BEFORE_PROBE); 
            pprobes.set(probe, (ProbeID)pvi.next()); 
            pprobes.set(probe + 1, ProbeID.AFTER_PROBE); 
        }
        
        Iterator pi = pprobes.iterator(); 
        int eventIndex = 1; 
        
        //writeHeader(w); 
        //might be sensible to create the hashmap somewhere else
        HashMap<ProbeID, Integer> idMap = new HashMap<ProbeID, Integer>();
        idMap.put(ProbeID.NOT_PROBE, 0);
        idMap.put(ProbeID.START_CLOCK, 0);
        idMap.put(ProbeID.BEFORE_PROBE, 0);        
        idMap.put(ProbeID.AFTER_PROBE, 0); 
        idMap.put(ProbeID.PROBE, 1);
        idMap.put(ProbeID.PROBE_EX, 2);
        idMap.put(ProbeID.PROBE_UNEX, 1);
        while(oi.hasNext()) { 
            long onset = ((Long)oi.next()).longValue();
            int pitch = ((Integer)piti.next()).intValue(); 

            ProbeID p = (ProbeID)pi.next(); 
            
            int probe = 0; 
            
            if(idMap.containsKey(p))
            {
                probe = idMap.get(p);
                System.out.println("Adding probe: ");
            }
            
            else
                System.out.println("Unexpected probe id: " + p);
            
            
            w.write(composition + " " +  eventIndex + " " + 
                    onset + " " + pitch + " " + 
                    probe + "\n"); 
            eventIndex++; 
        }
    }
    
    private void writeHeader(Writer w) throws IOException {
        w.write("melody note " + 
                "onset pitch " + 
                "probe"); 
        w.write("\n"); 
    }

}