/*
 * Created by Nick on May 16, 2005
 *
 */
package jmsltestsuite;

import java.util.Enumeration;
import java.util.Hashtable;

import com.softsynth.jmsl.*;
import com.softsynth.jmsl.jsyn.SampleLoopRegioner;
import com.softsynth.jmsl.jsyn.TransposingSampleSustainingInstrument;
import com.softsynth.jsyn.SynthSample;

/**
 * This subclass of TransposingSampleSustainingInstrument overrides
 * getAlternativeSampleIndex() to map note 60 to three different samples based
 * on amplitude. Notice that one sample is mapped to 60. Two additional samples
 * are mapped to pitches 200 and 201, which we never expect to play directly.
 * They serve as convenient places to stash alternative samples within the
 * existing API.
 * 
 * The logic of mapping quiet, medium, loud versions of middle c is implemented
 * in getAlternativeSampleIndex()
 * 
 * @author Nick Didkovsky, (c) 2004 All rights reserved, Email:
 *         didkovn@mail.rockefeller.edu
 *  
 */
public class TransposingSampleSustainingInstrumentWithAmplitudeMap extends TransposingSampleSustainingInstrument {

    public TransposingSampleSustainingInstrumentWithAmplitudeMap(String dir) {
        super(dir);
    }

    /**
     * Precondition: pitchIndex points to a valid sample, previously loaded with
     * addSamplePitch(). Override this method to point to a different valid
     * sample index. For example, you might store a loud sample at pitchIndex 60
     * and quiet sample at index 200 (ie some pitch index you'd never bang
     * directly), and if the amplitude of data[] < 0.3 return 200 for this
     * pitchIndex, else return 60)
     * 
     * <pre>
     * 
     *  
     *       public int getAlternativeSampleIndex(int pitchIndex, double timeStretch, double[] data) {
     *       double amp = data[2];
     *       if (pitchIndex == 60 &amp;&amp; amp &amp;lt 0.4) {
     *       return 201;
     *       }
     *       if (pitchIndex == 60 &amp;&amp; amp &amp;gt 0.7) {
     *       return 200;
     *       }
     *       return pitchIndex;
     *       }
     *       
     *  
     * </pre>
     * 
     * @return valid index to use instead of pitchIndex.
     */
    public int getAlternativeSampleIndex(int pitchIndex, double timeStretch, double[] data) {
        double amp = data[2];
        if (pitchIndex == 60 && amp < 0.4) {
            return 201;
        }
        if (pitchIndex == 60 && amp > 0.7) {
            return 200;
        }
        return pitchIndex;
    }

    public static void main(String args[]) {

        java.awt.Frame f = new java.awt.Frame(
                "TransposingSampleSustainingInstrument with alternative samples mapped to amplitude");
        f.addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent e) {
                JMSL.closeMusicDevices();
                System.exit(0);
            }
        });

        String mySampleDirectory = "E:/JMSLScoreWork/JMSLScoreSamples/";
        TransposingSampleSustainingInstrumentWithAmplitudeMap ins = new TransposingSampleSustainingInstrumentWithAmplitudeMap(
                mySampleDirectory);
        ins.getMusicDevice().open();

        ins.addSamplePitch("voice/c4_mf.wav", 60);
        ins.addSamplePitch("voice/c4_ff.wav", 200);
        ins.addSamplePitch("voice/c4_p.wav", 201);
        ins.buildFromAttributes();

        JMSLMixerContainer mixer = new JMSLMixerContainer();
        mixer.addInstrument(ins);
        mixer.start();

        JMSL.clock.setAdvance(0.5);
        MusicShape s = new MusicShape(4);
        s.add(2.0, 60, 0.5, 1.85); // mf
        s.add(2.0, 60, 0.75, 1.85); // ff
        s.add(2.0, 60, 0.25, 1.85); // p

        s.add(2.0, 61, 0.5, 1.85); // mf
        s.add(2.0, 61, 0.75, 1.85); // ff
        s.add(2.0, 61, 0.25, 1.85); // p

        s.add(2.0, 59, 0.5, 1.85); // mf
        s.add(2.0, 59, 0.75, 1.85); // ff
        s.add(2.0, 59, 0.25, 1.85); // p

        s.setInstrument(ins);
        s.setRepeats(13);
        s.launch(JMSL.now() + 0.5);

        f.add(mixer.getPanAmpControlPanel());

        f.pack();
        f.setVisible(true);

        Hashtable sampleHash = ins.getSynthSamples();
        for (Enumeration e = sampleHash.keys(); e.hasMoreElements();) {
            Integer key = (Integer) e.nextElement();
            int pitchIndex = key.intValue();
            SynthSample synthSample = (SynthSample) sampleHash.get(key);
            System.out.println("Pitch index " + pitchIndex + " is mapped to " + synthSample);
        }
        System.out.println("---");
        Hashtable sampleLoopRegionerHash = ins.getSampleLoopRegioners();
        for (Enumeration e = sampleLoopRegionerHash.keys(); e.hasMoreElements();) {
            Integer key = (Integer) e.nextElement();
            int pitchIndex = key.intValue();
            SampleLoopRegioner regioner = (SampleLoopRegioner)sampleLoopRegionerHash.get(key);
            System.out.println("Pitch index " + pitchIndex + " is mapped to a sample with the following loop region info:\n " + regioner.getSampleRegion());
        }
    }
}