annotate src/uk/ac/qmul/eecs/depic/daw/haptics/HapticTrigger.java @ 4:473da40f3d39 tip

added html formatting to Daw/package-info.java
author Fiore Martin <f.martin@qmul.ac.uk>
date Thu, 25 Feb 2016 17:50:09 +0000
parents c0412c81d274
children
rev   line source
f@0 1 package uk.ac.qmul.eecs.depic.daw.haptics;
f@0 2
f@0 3 import uk.ac.qmul.eecs.depic.daw.Chunk;
f@0 4 import uk.ac.qmul.eecs.depic.daw.SoundWave;
f@0 5 import uk.ac.qmul.eecs.depic.daw.SoundWaveEvent;
f@0 6 import uk.ac.qmul.eecs.depic.daw.SoundWaveListener;
f@0 7 import uk.ac.qmul.eecs.depic.jhapticgui.Haptics;
f@0 8 import uk.ac.qmul.eecs.depic.patterns.MathUtils;
f@0 9 import uk.ac.qmul.eecs.depic.patterns.Range;
f@0 10 import uk.ac.qmul.eecs.depic.patterns.Sequence;
f@0 11 import uk.ac.qmul.eecs.depic.patterns.Sequence.Value;
f@0 12 import uk.ac.qmul.eecs.depic.patterns.SequenceEvent;
f@0 13 import uk.ac.qmul.eecs.depic.patterns.SequenceListener;
f@0 14 import uk.ac.qmul.eecs.depic.patterns.SequenceMapping;
f@0 15
f@2 16 /**
f@2 17 *
f@2 18 * Listens to elements of the DAW and sends commands to the haptic device in order to
f@2 19 * render such elements in haptics. It implements all the listeners interfaces because it reacts
f@2 20 * to changes and mirrors them in haptics.
f@2 21 *
f@2 22 * It is used to render sound waves and automations (sequences) in haptics
f@2 23 *
f@2 24 */
f@0 25 public class HapticTrigger implements SequenceMapping, SequenceListener, SoundWaveListener {
f@0 26 public enum DisplayType {
f@0 27 DISPLAY_SEQUENCE,
f@0 28 DISPLAY_NONE,
f@0 29 DISPLAY_PEAKS,
f@0 30 DISPLAY_RENDER_CURVE_AT,
f@0 31 DISPLAY_RENDER_VALUE
f@0 32 }
f@0 33
f@0 34 public abstract class Command {
f@0 35 /**
f@0 36 * Message to display a graph
f@0 37 *
f@0 38 * Arguments: intitial y value, max y value, min y value, max x value, x viewport size
f@0 39 */
f@0 40 public static final String DISPLAY_SEQUENCE = "display.seq";
f@0 41 public static final String DISPLAY_RENDER_CURVE_AT = "display.curve_at";
f@0 42 public static final String DISPLAY_RENDER_VALUE = "display.value";
f@0 43 /**
f@0 44 * display nothing. takes no args
f@0 45 */
f@0 46 public static final String DISPLAY_NONE = "display.none";
f@0 47 public static final String DISPLAY_PEAKS = "display.peaks";
f@0 48
f@0 49 /**
f@0 50 * Arguments : x time position, y in normalized form
f@0 51 */
f@0 52 public static final String SEQUENCE_VALUE_ADD = "seq.value.add";
f@0 53 public static final String SEQUENCE_VALUE_CHANGE = "seq.value.change";
f@0 54 public static final String SEQUENCE_VALUE_REMOVE = "seq.value.rem";
f@0 55 public static final String SEQUENCE_VALUE_FIND = "seq.value.find";
f@0 56 public static final String SEQUENCE_SHIFT = "seq.shift";
f@0 57 public static final String SEQUENCE_BEGIN = "seq.begin";
f@0 58
f@0 59 public static final String RENDER_VALUE = "render_value";
f@0 60 public static final String RENDER_CURVE_AT = "render_curve_at";
f@0 61 /**
f@0 62 * Message to rotate the viscosity scrub line in the haptic space
f@0 63 *
f@0 64 * Argument is the degree of rotation
f@0 65 */
f@0 66 public static final String ROTATE_Z = "rotate.z";
f@0 67 public static final String ROTATE_Y = "rotate.y";
f@0 68 public static final String ROTATE_X = "rotate.x";
f@0 69 }
f@0 70
f@0 71 private DisplayType displayType;
f@0 72 private Haptics haptics;
f@0 73
f@0 74 public HapticTrigger(Haptics haptics, DisplayType type){
f@0 75 if(haptics == null)
f@0 76 throw new IllegalArgumentException("haptics cannot be null");
f@0 77 this.haptics = haptics;
f@0 78 displayType = type;
f@0 79 haptics.sendMessage(Command.DISPLAY_NONE,"",0);
f@0 80 }
f@0 81
f@0 82 @Override
f@0 83 public void renderValue(Value val) {
f@0 84 /* sends a normalized value of the chunk size */
f@0 85 haptics.sendMessage(Command.RENDER_VALUE, Float.toString(val.getValue()) , val.hashCode());
f@0 86 }
f@0 87
f@0 88 @Override
f@0 89 public void renderCurve(Sequence m, float startTime) {
f@0 90 throw new UnsupportedOperationException("Only update implemented");
f@0 91 }
f@0 92
f@0 93 @Override
f@0 94 public void renderCurveAt(Sequence sequence, float time, float duration) {
f@0 95 float val = new MathUtils.Interpolate(sequence).linear(time);
f@0 96
f@0 97 /* normalize the value to [0-1] range */
f@0 98 float normalizedValue = new MathUtils.Scale(sequence.getRange(), new Range<Float>(0.0f,1.0f)).linear(val);
f@0 99 haptics.sendMessage(Command.RENDER_CURVE_AT, ""+normalizedValue, sequence.hashCode());
f@0 100 }
f@0 101
f@0 102 @Override
f@0 103 public <T extends SequenceEvent> void sequenceUpdated(T t) {
f@0 104 SequenceEvent.What evtType = t.getWhat();
f@0 105
f@0 106 if(displayType == DisplayType.DISPLAY_SEQUENCE) {
f@0 107 if(SequenceEvent.What.VALUE_ADDED.equals(evtType)){
f@0 108 Sequence.Value aVal = t.getValue();
f@0 109
f@0 110 /* since the haptic graph y value are in normalized form normalize first */
f@0 111 float verticalValue = new MathUtils.Scale(t.getSource().getRange(), Range.NORMALIZED_RANGE_F).linear(aVal.getValue());
f@0 112
f@0 113 haptics.sendMessage(Command.SEQUENCE_VALUE_ADD, aVal.getTimePosition()+" "+verticalValue, aVal.hashCode());
f@0 114 }else if(SequenceEvent.What.VALUE_CHANGED.equals(evtType)){
f@0 115 Sequence.Value aVal = t.getValue();
f@0 116
f@0 117 float verticalValue = new MathUtils.Scale(t.getSource().getRange(), Range.NORMALIZED_RANGE_F).linear(aVal.getValue());
f@0 118
f@0 119 haptics.sendMessage(Command.SEQUENCE_VALUE_CHANGE, aVal.getTimePosition() +" "+verticalValue, aVal.hashCode());
f@0 120 }else if(SequenceEvent.What.VALUE_REMOVED.equals(evtType)){
f@0 121 Sequence.Value aVal = t.getValue();
f@0 122 haptics.sendMessage(Command.SEQUENCE_VALUE_REMOVE, "", aVal.hashCode());
f@0 123 }else if(SequenceEvent.What.BEGIN_CHANGED.equals(evtType)){
f@0 124 Sequence sequence = t.getSource();
f@0 125
f@0 126 haptics.sendMessage(Command.SEQUENCE_BEGIN,
f@0 127 ""+new MathUtils.Scale(sequence.getRange(),Range.NORMALIZED_RANGE_F).linear(sequence.getBegin()),
f@0 128 0
f@0 129 );
f@0 130 }
f@0 131 }
f@0 132
f@0 133 }
f@0 134
f@0 135 /**
f@0 136 * Gets an update from a {@code SoundWave} this class is a listener of, and send a message to the {@code HapticDevice}
f@0 137 * thread accordingly.
f@0 138 *
f@0 139 * @param evt the new event
f@0 140 */
f@0 141 @Override
f@0 142 public void update(SoundWaveEvent evt) {
f@0 143 String evtType = evt.getType();
f@0 144
f@0 145 if(SoundWaveEvent.POSITION_CHANGED.equals(evtType)){
f@0 146 SoundWave wave = evt.getSource();
f@0 147 int pos = (Integer)evt.getArgs();
f@0 148
f@0 149 if(pos < wave.getChunkNum()){
f@0 150 Chunk chunk = wave.getChunkAt(pos);
f@0 151 float chunkSize = chunk.getNormEnd() - chunk.getNormStart();
f@0 152 /* sends a normalized value of the chunk size */
f@0 153 haptics.sendMessage(Command.RENDER_VALUE, Float.toString(chunkSize) , chunk.hashCode());
f@0 154 }else{
f@0 155 /* if the scub goes past the audio wave just send wave amp = 0 */
f@0 156 haptics.sendMessage(Command.RENDER_VALUE, "0", 0);
f@0 157 }
f@0 158 }else if(SoundWaveEvent.CLOSE.equals(evtType)){
f@0 159 /* removes itself from listeners */
f@0 160 evt.getSource().removeSoundWaveListener(this);
f@0 161 }
f@0 162 }
f@0 163
f@0 164
f@0 165
f@0 166 }