com.softsynth.jmsl.jsyn
Class SimpleSamplePlayingInstrument

java.lang.Object
  extended by com.softsynth.jmsl.InstrumentAdapter
      extended by com.softsynth.jmsl.jsyn.SimpleSamplePlayingInstrument
All Implemented Interfaces:
Editable, Instrument, Namable, OutputProvider, Transposable, AttributeBuildable, DirectorySettable, HandleSpecialXMLTag
Direct Known Subclasses:
SimpleSamplePlayingInstrumentWithAmplitudeMap, SimpleSamplePlayingInstrumentWithLoops, SupoveVox

public class SimpleSamplePlayingInstrument
extends InstrumentAdapter
implements AttributeBuildable, DirectorySettable, HandleSpecialXMLTag, Editable

A JMSL Instrument that plays SynthSamples, mapped to integer pitch values. "One shot" style. No transposition, no loop points, plays all the way through

If loadSample() fails to find it it will open a SampleFinderDialog.

IMPORTANT: For Applets, the root sample directory passed to the constructor is ignored and CODEBASE is used instead!!!! So your samples should be in your applet's CODEBASE. The use of subfolders is ok, just make everything relative to CODEBASE. So for example, if locally you have a root sample directory called F:/JMSLScoreWork/JMSLScoreSamples/ relative to which all your samples are located, and inside it is hr16_stereo/AlesisKick.aif, then your applet's CODEBASE, which might be a folder called "classes", should contain hr16_stereo/AlesisKick.aif

IMPORTANT: stereo samples must be AIFF for versions of JSyn prior to 1.43 ( see http://www.softsynth.com/jsyn/support/bugs.html#BUG0007 )

Since JMSLv103, SimpleSamplePlayingInstrument performs stereo AIF samples as well. For example:

 SimpleSamplePlayingInstrument ins = new SimpleSamplePlayingInstrument("F:\\JMSLScoreWork\\JMSLScoreSamples\\");
 ins.setNumChannels(2);
 
 ins.getMusicDevice().edit(f);
 ins.getMusicDevice().open();
 
 ins.addSamplePitch("hr16_stereo\\AlesisKick.aif", 60);
 ins.addSamplePitch("hr16_stereo\\AlesisSnare.aif", 61);
 ins.addSamplePitch("hr16_stereo\\AlesisFloorTom.aif", 62);
 ins.addSamplePitch("hr16_stereo\\AlesisRackTom1.aif", 63);
 ins.addSamplePitch("hr16_stereo\\AlesisRackTom2.aif", 64);
 ins.buildFromAttributes();
 
 JMSLMixerContainer mixer = new JMSLMixerContainer();
 mixer.addInstrument(ins);
 mixer.start();
 
 
This version adds new feature of being able to map pitches to different samples based on performance data, by overriding getAlternativeSampleIndex().
New to build 20060408, this class supports new methods loadSample(SynthSample sample, int noteIndex) and loadSample(short[] shorts, int noteIndex) for dynamically created sample data

Author:
Nick Didkovsky, didkovn@mail.rockefeller.edu (C) 2000 Nick Didkovsky, all rights reserved.
See Also:
SimpleSamplePlayingInstrumentWithAmplitudeMap

Field Summary
 int POLYPHONY
          max number of voices to allocate, default 32.
 
Constructor Summary
SimpleSamplePlayingInstrument()
           
SimpleSamplePlayingInstrument(java.lang.String sampleDirectory)
          Sample directory string must end in file separator, ex "F:\samples\" All samples will be sought in this directory.
 
Method Summary
 void addEditListener(EditListener listener)
           
 void addSamplePitch(short[] shorts, int pitch)
          Assign a dynamically created sample to a note index.
 void addSamplePitch(java.lang.String filename, int pitch)
          Assign a sample to be triggered when noteIndex is passed to play().
 void addSamplePitch(com.softsynth.jsyn.SynthSample sample, int pitch)
          Assign a dynamically created sample to a note index.
 void buildFromAttributes()
           
 void clear()
          remove all samples and pitch mappings
 double close(double time)
           
 void edit(java.awt.Frame fr)
          Open a Frame containing a SampleInstrumentMapperPanel for this instrument.
 int getAlternativeSampleIndex(int pitchIndex, double timeStretch, double[] data)
          Precondition: pitchIndex points to a valid sample, previously loaded with addSamplePitch().
 java.lang.String getDirectory()
           
 boolean getEditEnabled()
           
 int getNumChannels()
           
 int getNumOutputs()
           
 java.lang.Object getOutput()
          get this output (SynthOutput in the case of a JSyn Instrument, for example
 java.lang.Object getOutput(int part)
          same as getOutput(), only one output
 double[] getPitches()
           
 java.lang.String getSampleFilename(int pitch)
           
 java.util.Hashtable getSynthSamples()
           
 Tuning getTuning()
           
 java.util.Hashtable getVoices()
          voices is a hashtable whose keys are synthnotes returned by allocator.steal() ( called in on() method), and whose values are the pitch which they were used to bang.
 boolean handleSpecialTag(java.lang.String tag, java.util.Hashtable attributes)
          HandleSpecialXMLTag interface.
static void main(java.lang.String[] args)
           
 void notifyEditListeners()
           
 java.lang.Object off(double playTime, double timeStretch, double[] dar)
          Turn off all voices that are playing the sample associated with pitchIndex dar[1].
 java.lang.Object on(double playTime, double timeStretch, double[] dar)
          Look up sample assiciated with dar[1].
 double open(double time)
           
 double play(double playTime, double timeStretch, double[] dar)
          If there is a sample loaded at dar[1], bang it.
 void reload()
           
 void removeEditListener(EditListener listener)
           
 void setDirectory(java.lang.String dir)
           
 void setEditEnabled(boolean flag)
          noop
 void setNumChannels(int i)
           
 void setTuning(Tuning tuning)
           
 void testSampleDirectory()
           
 void writeSpecialXMLTags(java.io.PrintWriter out)
          write pitch / soundfilename pairs to XML file These are not covered by simple bean model since there are many such pairs.
 
Methods inherited from class com.softsynth.jmsl.InstrumentAdapter
getDimensionNameSpace, getInterpreter, getMixerClassName, getMusicDevice, getName, getTransposition, noteOff, noteOn, noteOnFor, setDimensionNameSpace, setInterpreter, setMixerClassName, setMusicDevice, setName, setTransposition, toString, update
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

POLYPHONY

public int POLYPHONY
max number of voices to allocate, default 32. You may this change before creating new instances of this class and its subclasses

Constructor Detail

SimpleSamplePlayingInstrument

public SimpleSamplePlayingInstrument()

SimpleSamplePlayingInstrument

public SimpleSamplePlayingInstrument(java.lang.String sampleDirectory)
Sample directory string must end in file separator, ex "F:\samples\" All samples will be sought in this directory. They can be in subfolders, but all must be relative to this dir.

Method Detail

clear

public void clear()
remove all samples and pitch mappings


open

public double open(double time)
            throws java.lang.InterruptedException
Specified by:
open in interface Instrument
Overrides:
open in class InstrumentAdapter
Throws:
java.lang.InterruptedException

close

public double close(double time)
             throws java.lang.InterruptedException
Specified by:
close in interface Instrument
Overrides:
close in class InstrumentAdapter
Throws:
java.lang.InterruptedException

setDirectory

public void setDirectory(java.lang.String dir)
Specified by:
setDirectory in interface DirectorySettable

getDirectory

public java.lang.String getDirectory()
Specified by:
getDirectory in interface DirectorySettable

testSampleDirectory

public void testSampleDirectory()

reload

public void reload()

getOutput

public java.lang.Object getOutput()
Description copied from interface: OutputProvider
get this output (SynthOutput in the case of a JSyn Instrument, for example

Specified by:
getOutput in interface OutputProvider
Overrides:
getOutput in class InstrumentAdapter
Returns:
null

getOutput

public java.lang.Object getOutput(int part)
same as getOutput(), only one output

Specified by:
getOutput in interface OutputProvider
Overrides:
getOutput in class InstrumentAdapter
Returns:
null

getNumOutputs

public int getNumOutputs()
Specified by:
getNumOutputs in interface OutputProvider
Overrides:
getNumOutputs in class InstrumentAdapter
Returns:
1 or 2

addSamplePitch

public void addSamplePitch(java.lang.String filename,
                           int pitch)
Assign a sample to be triggered when noteIndex is passed to play().
For example, let's say all your samples are in C:\mysamples\
You pass "C:\mysamples\" to the constructor.
Let's say C:\mysamples\ contains a directory called DrumMachine which contains snare.wav
Then you would call addSamplePitch() with "DrumMachine/snare.wav" since that is its location relative to C:\mysamples\ The recommended way to subclass this instrument is to override buildFromAttributes, making multiple calls to addSamplePitch() first, finally calling super.buildFromAttributes()


addSamplePitch

public void addSamplePitch(com.softsynth.jsyn.SynthSample sample,
                           int pitch)
Assign a dynamically created sample to a note index. If you do this you will not be able to save/reload. You are committed to runtime building


addSamplePitch

public void addSamplePitch(short[] shorts,
                           int pitch)
Assign a dynamically created sample to a note index. If you do this you will not be able to save/reload from file. You are committed to runtime building


getSampleFilename

public java.lang.String getSampleFilename(int pitch)

getSynthSamples

public java.util.Hashtable getSynthSamples()
Returns:
hashtable of (Integer) pitchindex keys and SynthSample values

getPitches

public double[] getPitches()
Returns:
array of pitches which have been assigned to a sample

getAlternativeSampleIndex

public int getAlternativeSampleIndex(int pitchIndex,
                                     double timeStretch,
                                     double[] data)
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)

Returns:
valid index to use instead of pitchIndex. This default version returns incoming pitchIndex

on

public java.lang.Object on(double playTime,
                           double timeStretch,
                           double[] dar)
Look up sample assiciated with dar[1]. Allocate a FixedRateSampleReader to play it. dar[3] is not used to cut sample short if the value is less than duration of sample. This instrument imsply queues up a sample and lets it run. Use off() to terminate early.

Specified by:
on in interface Instrument
Overrides:
on in class InstrumentAdapter
Returns:
the allocated FixedRateSampleReader or null of there is no sample associated with dar[1]
See Also:
Instrument.on(double, double, double[])

play

public double play(double playTime,
                   double timeStretch,
                   double[] dar)
If there is a sample loaded at dar[1], bang it. No sustain, no transposition. Hold time is not used to terminate sample early.

Specified by:
play in interface Instrument
Overrides:
play in class InstrumentAdapter

off

public java.lang.Object off(double playTime,
                            double timeStretch,
                            double[] dar)
Turn off all voices that are playing the sample associated with pitchIndex dar[1]. These voices are stored in a hsahtable whenever play() is called. There may be more than one voice playing the sample mapped to index 60 for example. Turning off is accomplished by queuing up the last frame of the sample, with Synth.FLAG_AUTO_STOP

Specified by:
off in interface Instrument
Overrides:
off in class InstrumentAdapter
Returns:
null
See Also:
com.softsynth.jmsl.Instrument#off(double, Object)

buildFromAttributes

public void buildFromAttributes()
Specified by:
buildFromAttributes in interface AttributeBuildable

getTuning

public Tuning getTuning()
Returns:
tuning stored in this instrument. Not used to perform.

setTuning

public void setTuning(Tuning tuning)
Parameters:
tuning - to be stored in this instrument. Not used to perform.

handleSpecialTag

public boolean handleSpecialTag(java.lang.String tag,
                                java.util.Hashtable attributes)
HandleSpecialXMLTag interface. Store pitch / soundfilename pairs for loading later

Specified by:
handleSpecialTag in interface HandleSpecialXMLTag
Returns:
true if this tag is recognized as special, false if the object permits normal bean model to handle attribute/value pairs
See Also:
HandleSpecialXMLTag.handleSpecialTag(java.lang.String, java.util.Hashtable)

writeSpecialXMLTags

public void writeSpecialXMLTags(java.io.PrintWriter out)
                         throws java.io.IOException
write pitch / soundfilename pairs to XML file These are not covered by simple bean model since there are many such pairs.

Specified by:
writeSpecialXMLTags in interface HandleSpecialXMLTag
Throws:
java.io.IOException
See Also:
HandleSpecialXMLTag.writeSpecialXMLTags(java.io.PrintWriter)

notifyEditListeners

public void notifyEditListeners()

addEditListener

public void addEditListener(EditListener listener)
Specified by:
addEditListener in interface Editable

removeEditListener

public void removeEditListener(EditListener listener)
Specified by:
removeEditListener in interface Editable

edit

public void edit(java.awt.Frame fr)
Open a Frame containing a SampleInstrumentMapperPanel for this instrument.

Specified by:
edit in interface Editable
See Also:
Editable.edit(java.awt.Frame)

setEditEnabled

public void setEditEnabled(boolean flag)
noop

Specified by:
setEditEnabled in interface Editable
See Also:
Editable.setEditEnabled(boolean)

getEditEnabled

public boolean getEditEnabled()
Specified by:
getEditEnabled in interface Editable
Returns:
true

main

public static void main(java.lang.String[] args)

getNumChannels

public int getNumChannels()
Returns:

setNumChannels

public void setNumChannels(int i)
Parameters:
i -

getVoices

public java.util.Hashtable getVoices()
voices is a hashtable whose keys are synthnotes returned by allocator.steal() ( called in on() method), and whose values are the pitch which they were used to bang. This is used to retrieve the synthnote in off() and turn it off

Returns:
Returns the voices.