view Block.java @ 34:f23acab50cd3

Changed pleasantness question
author Jeremy Gow <jeremy.gow@gmail.com>
date Wed, 14 Nov 2012 12:12:19 +0000
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"); 
    }

}