Mercurial > jmeCapture
comparison src/com/aurellem/capture/examples/Advanced.java @ 62:f5e52169f056
updated to work with new jme changes
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Wed, 14 Dec 2011 17:43:52 -0700 |
parents | afc437f637bd |
children | 23e3df41db3c |
comparison
equal
deleted
inserted
replaced
61:76581e11fb72 | 62:f5e52169f056 |
---|---|
1 package com.aurellem.capture.examples; | 1 package com.aurellem.capture.examples; |
2 | 2 |
3 import java.io.File; | 3 import java.io.File; |
4 import java.io.FileNotFoundException; | |
5 import java.io.IOException; | 4 import java.io.IOException; |
6 import java.lang.reflect.Field; | 5 import java.lang.reflect.Field; |
7 import java.nio.ByteBuffer; | 6 import java.nio.ByteBuffer; |
8 | 7 |
9 import javax.sound.sampled.AudioFormat; | 8 import javax.sound.sampled.AudioFormat; |
53 * @author Robert McIntyre | 52 * @author Robert McIntyre |
54 */ | 53 */ |
55 | 54 |
56 public class Advanced extends SimpleApplication { | 55 public class Advanced extends SimpleApplication { |
57 | 56 |
58 /** | 57 /** |
59 * You will see three grey cubes, a blue sphere, and a path which | 58 * You will see three grey cubes, a blue sphere, and a path which |
60 * circles each cube. The blue sphere is generating a constant | 59 * circles each cube. The blue sphere is generating a constant |
61 * monotone sound as it moves along the track. Each cube is | 60 * monotone sound as it moves along the track. Each cube is |
62 * listening for sound; when a cube hears sound whose intensity is | 61 * listening for sound; when a cube hears sound whose intensity is |
63 * greater than a certain threshold, it changes its color from | 62 * greater than a certain threshold, it changes its color from |
64 * grey to green. | 63 * grey to green. |
65 * | 64 * |
66 * Each cube is also saving whatever it hears to a file. The | 65 * Each cube is also saving whatever it hears to a file. The |
67 * scene from the perspective of the viewer is also saved to a | 66 * scene from the perspective of the viewer is also saved to a |
68 * video file. When you listen to each of the sound files | 67 * video file. When you listen to each of the sound files |
69 * alongside the video, the sound will get louder when the sphere | 68 * alongside the video, the sound will get louder when the sphere |
70 * approaches the cube that generated that sound file. This | 69 * approaches the cube that generated that sound file. This |
71 * shows that each listener is hearing the world from its own | 70 * shows that each listener is hearing the world from its own |
72 * perspective. | 71 * perspective. |
73 * | 72 * |
74 */ | 73 */ |
75 public static void main(String[] args) { | 74 public static void main(String[] args) { |
76 Advanced app = new Advanced(); | 75 Advanced app = new Advanced(); |
77 AppSettings settings = new AppSettings(true); | 76 AppSettings settings = new AppSettings(true); |
78 settings.setAudioRenderer(AurellemSystemDelegate.SEND); | 77 settings.setAudioRenderer(AurellemSystemDelegate.SEND); |
79 JmeSystem.setSystemDelegate(new AurellemSystemDelegate()); | 78 JmeSystem.setSystemDelegate(new AurellemSystemDelegate()); |
80 app.setSettings(settings); | 79 app.setSettings(settings); |
81 app.setShowSettings(false); | 80 app.setShowSettings(false); |
82 app.setPauseOnLostFocus(false); | 81 app.setPauseOnLostFocus(false); |
83 | 82 |
84 try { | 83 try { |
85 Capture.captureVideo(app, File.createTempFile("advanced",".avi")); | 84 //Capture.captureVideo(app, File.createTempFile("advanced",".avi")); |
86 Capture.captureAudio(app, File.createTempFile("advanced", ".wav")); | 85 Capture.captureAudio(app, File.createTempFile("advanced", ".wav")); |
87 } | 86 } |
88 catch (IOException e) {e.printStackTrace();} | 87 catch (IOException e) {e.printStackTrace();} |
88 | |
89 app.start(); | |
90 } | |
91 | |
92 | |
93 private Geometry bell; | |
94 private Geometry ear1; | |
95 private Geometry ear2; | |
96 private Geometry ear3; | |
97 private AudioNode music; | |
98 private MotionTrack motionControl; | |
99 private IsoTimer motionTimer = new IsoTimer(60); | |
100 | |
101 private Geometry makeEar(Node root, Vector3f position){ | |
102 Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); | |
103 Geometry ear = new Geometry("ear", new Box(1.0f, 1.0f, 1.0f)); | |
104 ear.setLocalTranslation(position); | |
105 mat.setColor("Color", ColorRGBA.Green); | |
106 ear.setMaterial(mat); | |
107 root.attachChild(ear); | |
108 return ear; | |
109 } | |
110 | |
111 private Vector3f[] path = new Vector3f[]{ | |
112 // loop 1 | |
113 new Vector3f(0, 0, 0), | |
114 new Vector3f(0, 0, -10), | |
115 new Vector3f(-2, 0, -14), | |
116 new Vector3f(-6, 0, -20), | |
117 new Vector3f(0, 0, -26), | |
118 new Vector3f(6, 0, -20), | |
119 new Vector3f(0, 0, -14), | |
120 new Vector3f(-6, 0, -20), | |
121 new Vector3f(0, 0, -26), | |
122 new Vector3f(6, 0, -20), | |
123 // loop 2 | |
124 new Vector3f(5, 0, -5), | |
125 new Vector3f(7, 0, 1.5f), | |
126 new Vector3f(14, 0, 2), | |
127 new Vector3f(20, 0, 6), | |
128 new Vector3f(26, 0, 0), | |
129 new Vector3f(20, 0, -6), | |
130 new Vector3f(14, 0, 0), | |
131 new Vector3f(20, 0, 6), | |
132 new Vector3f(26, 0, 0), | |
133 new Vector3f(20, 0, -6), | |
134 new Vector3f(14, 0, 0), | |
135 // loop 3 | |
136 new Vector3f(8, 0, 7.5f), | |
137 new Vector3f(7, 0, 10.5f), | |
138 new Vector3f(6, 0, 20), | |
139 new Vector3f(0, 0, 26), | |
140 new Vector3f(-6, 0, 20), | |
141 new Vector3f(0, 0, 14), | |
142 new Vector3f(6, 0, 20), | |
143 new Vector3f(0, 0, 26), | |
144 new Vector3f(-6, 0, 20), | |
145 new Vector3f(0, 0, 14), | |
146 // begin ellipse | |
147 new Vector3f(16, 5, 20), | |
148 new Vector3f(0, 0, 26), | |
149 new Vector3f(-16, -10, 20), | |
150 new Vector3f(0, 0, 14), | |
151 new Vector3f(16, 20, 20), | |
152 new Vector3f(0, 0, 26), | |
153 new Vector3f(-10, -25, 10), | |
154 new Vector3f(-10, 0, 0), | |
155 // come at me! | |
156 new Vector3f(-28.00242f, 48.005623f, -34.648228f), | |
157 new Vector3f(0, 0 , -20), | |
158 }; | |
159 | |
160 private void createScene() { | |
161 Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); | |
162 bell = new Geometry( "sound-emitter" , new Sphere(15,15,1)); | |
163 mat.setColor("Color", ColorRGBA.Blue); | |
164 bell.setMaterial(mat); | |
165 rootNode.attachChild(bell); | |
166 | |
167 ear1 = makeEar(rootNode, new Vector3f(0, 0 ,-20)); | |
168 ear2 = makeEar(rootNode, new Vector3f(0, 0 ,20)); | |
169 ear3 = makeEar(rootNode, new Vector3f(20, 0 ,0)); | |
170 | |
171 MotionPath track = new MotionPath(); | |
172 | |
173 for (Vector3f v : path){ | |
174 track.addWayPoint(v); | |
175 } | |
176 track.setCurveTension(0.80f); | |
177 | |
178 motionControl = new MotionTrack(bell,track); | |
179 // for now, use reflection to change the timer... | |
180 // motionControl.setTimer(new IsoTimer(60)); | |
89 | 181 |
90 app.start(); | 182 try { |
91 } | 183 Field timerField; |
92 | 184 timerField = AbstractCinematicEvent.class.getDeclaredField("timer"); |
93 | 185 timerField.setAccessible(true); |
94 private Geometry bell; | 186 try {timerField.set(motionControl, motionTimer);} |
95 private Geometry ear1; | 187 catch (IllegalArgumentException e) {e.printStackTrace();} |
96 private Geometry ear2; | 188 catch (IllegalAccessException e) {e.printStackTrace();} |
97 private Geometry ear3; | 189 } |
98 private AudioNode music; | 190 catch (SecurityException e) {e.printStackTrace();} |
99 private MotionTrack motionControl; | 191 catch (NoSuchFieldException e) {e.printStackTrace();} |
100 | 192 |
101 private Geometry makeEar(Node root, Vector3f position){ | 193 |
102 Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); | 194 motionControl.setDirectionType(MotionTrack.Direction.PathAndRotation); |
103 Geometry ear = new Geometry("ear", new Box(1.0f, 1.0f, 1.0f)); | 195 motionControl.setRotation(new Quaternion().fromAngleNormalAxis(-FastMath.HALF_PI, Vector3f.UNIT_Y)); |
104 ear.setLocalTranslation(position); | 196 motionControl.setInitialDuration(20f); |
105 mat.setColor("Color", ColorRGBA.Green); | 197 motionControl.setSpeed(1f); |
106 ear.setMaterial(mat); | 198 |
107 root.attachChild(ear); | 199 track.enableDebugShape(assetManager, rootNode); |
108 return ear; | 200 positionCamera(); |
109 } | 201 } |
110 | 202 |
111 private Vector3f[] path = new Vector3f[]{ | 203 |
112 // loop 1 | 204 private void positionCamera(){ |
113 new Vector3f(0, 0, 0), | 205 this.cam.setLocation(new Vector3f(-28.00242f, 48.005623f, -34.648228f)); |
114 new Vector3f(0, 0, -10), | 206 this.cam.setRotation(new Quaternion(0.3359635f, 0.34280345f, -0.13281013f, 0.8671653f)); |
115 new Vector3f(-2, 0, -14), | 207 } |
116 new Vector3f(-6, 0, -20), | 208 |
117 new Vector3f(0, 0, -26), | 209 private void initAudio() { |
118 new Vector3f(6, 0, -20), | 210 org.lwjgl.input.Mouse.setGrabbed(false); |
119 new Vector3f(0, 0, -14), | 211 music = new AudioNode(assetManager, "Sound/Effects/Beep.ogg", false); |
120 new Vector3f(-6, 0, -20), | 212 |
121 new Vector3f(0, 0, -26), | 213 rootNode.attachChild(music); |
122 new Vector3f(6, 0, -20), | 214 audioRenderer.playSource(music); |
123 // loop 2 | 215 music.setPositional(true); |
124 new Vector3f(5, 0, -5), | 216 music.setVolume(1f); |
125 new Vector3f(7, 0, 1.5f), | 217 music.setReverbEnabled(false); |
126 new Vector3f(14, 0, 2), | 218 music.setDirectional(false); |
127 new Vector3f(20, 0, 6), | 219 music.setMaxDistance(200.0f); |
128 new Vector3f(26, 0, 0), | 220 music.setRefDistance(1f); |
129 new Vector3f(20, 0, -6), | 221 //music.setRolloffFactor(1f); |
130 new Vector3f(14, 0, 0), | 222 music.setLooping(false); |
131 new Vector3f(20, 0, 6), | 223 audioRenderer.pauseSource(music); |
132 new Vector3f(26, 0, 0), | 224 } |
133 new Vector3f(20, 0, -6), | 225 |
134 new Vector3f(14, 0, 0), | 226 public class Dancer implements SoundProcessor { |
135 // loop 3 | 227 Geometry entity; |
136 new Vector3f(8, 0, 7.5f), | 228 float scale = 2; |
137 new Vector3f(7, 0, 10.5f), | 229 public Dancer(Geometry entity){ |
138 new Vector3f(6, 0, 20), | 230 this.entity = entity; |
139 new Vector3f(0, 0, 26), | 231 } |
140 new Vector3f(-6, 0, 20), | 232 |
141 new Vector3f(0, 0, 14), | 233 /** |
142 new Vector3f(6, 0, 20), | 234 * this method is irrelevant since there is no state to cleanup. |
143 new Vector3f(0, 0, 26), | 235 */ |
144 new Vector3f(-6, 0, 20), | 236 public void cleanup() {} |
145 new Vector3f(0, 0, 14), | 237 |
146 // begin ellipse | 238 |
147 new Vector3f(16, 5, 20), | 239 /** |
148 new Vector3f(0, 0, 26), | 240 * Respond to sound! This is the brain of an AI entity that |
149 new Vector3f(-16, -10, 20), | 241 * hears its surroundings and reacts to them. |
150 new Vector3f(0, 0, 14), | 242 */ |
151 new Vector3f(16, 20, 20), | 243 public void process(ByteBuffer audioSamples, int numSamples, AudioFormat format) { |
152 new Vector3f(0, 0, 26), | 244 audioSamples.clear(); |
153 new Vector3f(-10, -25, 10), | 245 byte[] data = new byte[numSamples]; |
154 new Vector3f(-10, 0, 0), | 246 float[] out = new float[numSamples]; |
155 // come at me! | 247 audioSamples.get(data); |
156 new Vector3f(-28.00242f, 48.005623f, -34.648228f), | 248 FloatSampleTools.byte2floatInterleaved(data, 0, out, 0, |
157 new Vector3f(0, 0 , -20), | 249 numSamples/format.getFrameSize(), format); |
158 }; | 250 |
159 | 251 float max = Float.NEGATIVE_INFINITY; |
160 private void createScene() { | 252 for (float f : out){if (f > max) max = f;} |
161 Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); | 253 audioSamples.clear(); |
162 bell = new Geometry( "sound-emitter" , new Sphere(15,15,1)); | 254 |
163 mat.setColor("Color", ColorRGBA.Blue); | 255 if (max > 0.1){entity.getMaterial().setColor("Color", ColorRGBA.Green);} |
164 bell.setMaterial(mat); | 256 else {entity.getMaterial().setColor("Color", ColorRGBA.Gray);} |
165 rootNode.attachChild(bell); | 257 } |
166 | 258 } |
167 ear1 = makeEar(rootNode, new Vector3f(0, 0 ,-20)); | 259 |
168 ear2 = makeEar(rootNode, new Vector3f(0, 0 ,20)); | 260 private void prepareEar(Geometry ear, int n){ |
169 ear3 = makeEar(rootNode, new Vector3f(20, 0 ,0)); | 261 if (this.audioRenderer instanceof MultiListener){ |
170 | 262 MultiListener rf = (MultiListener)this.audioRenderer; |
171 MotionPath track = new MotionPath(); | 263 |
172 | 264 Listener auxListener = new Listener(); |
173 for (Vector3f v : path){ | 265 auxListener.setLocation(ear.getLocalTranslation()); |
174 track.addWayPoint(v); | 266 |
175 } | 267 rf.addListener(auxListener); |
176 track.setCurveTension(0.80f); | 268 WaveFileWriter aux = null; |
177 | 269 |
178 motionControl = new MotionTrack(bell,track); | 270 try {aux = new WaveFileWriter(File.createTempFile("advanced-audio-" + n, ".wav"));} |
179 | 271 catch (IOException e) {e.printStackTrace();} |
180 // for now, use reflection to change the timer... | 272 |
181 // motionControl.setTimer(new IsoTimer(60)); | 273 rf.registerSoundProcessor(auxListener, |
182 try { | 274 new CompositeSoundProcessor(new Dancer(ear), aux)); |
183 Field timerField; | 275 |
184 timerField = AbstractCinematicEvent.class.getDeclaredField("timer"); | 276 } |
185 timerField.setAccessible(true); | 277 } |
186 try {timerField.set(motionControl, new IsoTimer(60));} | 278 |
187 catch (IllegalArgumentException e) {e.printStackTrace();} | 279 |
188 catch (IllegalAccessException e) {e.printStackTrace();} | 280 public void simpleInitApp() { |
189 } | 281 this.setTimer(new IsoTimer(60)); |
190 catch (SecurityException e) {e.printStackTrace();} | 282 initAudio(); |
191 catch (NoSuchFieldException e) {e.printStackTrace();} | 283 |
192 | 284 createScene(); |
193 motionControl.setDirectionType(MotionTrack.Direction.PathAndRotation); | 285 |
194 motionControl.setRotation(new Quaternion().fromAngleNormalAxis(-FastMath.HALF_PI, Vector3f.UNIT_Y)); | 286 prepareEar(ear1, 1); |
195 motionControl.setInitialDuration(20f); | 287 prepareEar(ear2, 1); |
196 motionControl.setSpeed(1f); | 288 prepareEar(ear3, 1); |
197 | 289 |
198 track.enableDebugShape(assetManager, rootNode); | 290 motionControl.play(); |
199 positionCamera(); | 291 |
200 } | 292 } |
201 | 293 |
202 | 294 public void simpleUpdate(float tpf) { |
203 private void positionCamera(){ | 295 motionTimer.update(); |
204 this.cam.setLocation(new Vector3f(-28.00242f, 48.005623f, -34.648228f)); | 296 if (music.getStatus() != AudioNode.Status.Playing){ |
205 this.cam.setRotation(new Quaternion(0.3359635f, 0.34280345f, -0.13281013f, 0.8671653f)); | 297 music.play(); |
206 } | 298 } |
207 | 299 Vector3f loc = cam.getLocation(); |
208 private void initAudio() { | 300 Quaternion rot = cam.getRotation(); |
209 org.lwjgl.input.Mouse.setGrabbed(false); | 301 listener.setLocation(loc); |
210 music = new AudioNode(assetManager, "Sound/Effects/Beep.ogg", false); | 302 listener.setRotation(rot); |
211 | 303 music.setLocalTranslation(bell.getLocalTranslation()); |
212 rootNode.attachChild(music); | 304 } |
213 audioRenderer.playSource(music); | |
214 music.setPositional(true); | |
215 music.setVolume(1f); | |
216 music.setReverbEnabled(false); | |
217 music.setDirectional(false); | |
218 music.setMaxDistance(200.0f); | |
219 music.setRefDistance(1f); | |
220 //music.setRolloffFactor(1f); | |
221 music.setLooping(false); | |
222 audioRenderer.pauseSource(music); | |
223 } | |
224 | |
225 public class Dancer implements SoundProcessor { | |
226 Geometry entity; | |
227 float scale = 2; | |
228 public Dancer(Geometry entity){ | |
229 this.entity = entity; | |
230 } | |
231 | |
232 /** | |
233 * this method is irrelevant since there is no state to cleanup. | |
234 */ | |
235 public void cleanup() {} | |
236 | |
237 | |
238 /** | |
239 * Respond to sound! This is the brain of an AI entity that | |
240 * hears it's surroundings and reacts to them. | |
241 */ | |
242 public void process(ByteBuffer audioSamples, int numSamples, AudioFormat format) { | |
243 audioSamples.clear(); | |
244 byte[] data = new byte[numSamples]; | |
245 float[] out = new float[numSamples]; | |
246 audioSamples.get(data); | |
247 FloatSampleTools.byte2floatInterleaved(data, 0, out, 0, | |
248 numSamples/format.getFrameSize(), format); | |
249 | |
250 float max = Float.NEGATIVE_INFINITY; | |
251 for (float f : out){if (f > max) max = f;} | |
252 audioSamples.clear(); | |
253 | |
254 if (max > 0.1){entity.getMaterial().setColor("Color", ColorRGBA.Green);} | |
255 else {entity.getMaterial().setColor("Color", ColorRGBA.Gray);} | |
256 } | |
257 } | |
258 | |
259 private void prepareEar(Geometry ear, int n){ | |
260 if (this.audioRenderer instanceof MultiListener){ | |
261 MultiListener rf = (MultiListener)this.audioRenderer; | |
262 | |
263 Listener auxListener = new Listener(); | |
264 auxListener.setLocation(ear.getLocalTranslation()); | |
265 | |
266 rf.addListener(auxListener); | |
267 WaveFileWriter aux = null; | |
268 | |
269 try {aux = new WaveFileWriter(new File("/home/r/tmp/ear"+n+".wav"));} | |
270 catch (FileNotFoundException e) {e.printStackTrace();} | |
271 | |
272 rf.registerSoundProcessor(auxListener, | |
273 new CompositeSoundProcessor(new Dancer(ear), aux)); | |
274 } | |
275 } | |
276 | |
277 | |
278 public void simpleInitApp() { | |
279 this.setTimer(new IsoTimer(60)); | |
280 initAudio(); | |
281 | |
282 createScene(); | |
283 | |
284 prepareEar(ear1, 1); | |
285 prepareEar(ear2, 1); | |
286 prepareEar(ear3, 1); | |
287 | |
288 motionControl.play(); | |
289 } | |
290 | |
291 public void simpleUpdate(float tpf) { | |
292 if (music.getStatus() != AudioNode.Status.Playing){ | |
293 music.play(); | |
294 } | |
295 Vector3f loc = cam.getLocation(); | |
296 Quaternion rot = cam.getRotation(); | |
297 listener.setLocation(loc); | |
298 listener.setRotation(rot); | |
299 music.setLocalTranslation(bell.getLocalTranslation()); | |
300 } | |
301 | 305 |
302 } | 306 } |