source: osm/applications/editors/josm/plugins/wms-turbo-challenge2/src/wmsturbochallenge/EngineSound.java

Last change on this file was 33342, checked in by stoecker, 8 years ago

checkstyle fixes

File size: 4.8 KB
RevLine 
[19990]1/*
2 * GPLv2 or 3, Copyright (c) 2010 Andrzej Zaborowski
3 */
4package wmsturbochallenge;
5
6import java.util.Timer;
7import java.util.TimerTask;
8
[32322]9import javax.sound.sampled.AudioFormat;
[19990]10import javax.sound.sampled.AudioSystem;
11import javax.sound.sampled.DataLine;
12import javax.sound.sampled.SourceDataLine;
13
[33342]14/**
15 * This class simulates a car engine. What does a car engine do? It
16 * makes a pc-speaker-like buzz. The PC Speaker could only emit
17 * a (nearly) square wave and we simulate it here for maximum realism.
18 */
[32322]19class EngineSound {
[33342]20 EngineSound() {
[23190]21 rpm = 0.0;
22 }
[19990]23
[23190]24 public void start() {
25 rpm = 0.3;
26 speed = 0.0;
27 n = 0;
[19990]28
[23190]29 if (output != null)
30 stop();
[19990]31
[23190]32 AudioFormat output_format =
[32914]33 new AudioFormat(S_RATE, 16, 1, true, true);
[23190]34 DataLine.Info info =
[32914]35 new DataLine.Info(SourceDataLine.class, output_format);
[19990]36
[23190]37 /* Get the data line, open it and initialise the device */
38 try {
39 output = (SourceDataLine) AudioSystem.getLine(info);
40 output.open(output_format);
41 output.start();
42 frames_written = 0;
43 reschedule(0);
44 } catch (Exception e) {
45 output = null;
46 System.out.println("Audio not available: " +
47 e.getClass().getSimpleName());
48 }
49 }
[19990]50
[23190]51 public void stop() {
52 rpm = 0.0;
53 n = 0;
[19990]54
[23190]55 if (output == null)
56 return;
[19990]57
[23190]58 tick.cancel();
59 tick.purge();
[19990]60
[23190]61 output.stop();
62 output.flush();
63 output.close();
64 output = null;
65 }
[19990]66
[23190]67 public void set_speed(double speed) {
68 /* This engine is equipped with an automatic gear box that
69 * switches gears when the RPM becomes too high or too low. */
70 double new_speed = Math.abs(speed);
71 double accel = new_speed - this.speed;
72 this.speed = new_speed;
[19990]73
[23190]74 if (accel > 0.05)
75 accel = 0.05;
76 else if (accel < -0.05)
77 accel = -0.05;
78 rpm += accel;
[19990]79
[23190]80 if (accel > 0.0 && rpm > 1.0 + n * 0.2 && speed > 0.0) {
81 rpm = 0.3 + n * 0.2;
[33342]82 n++;
[23190]83 } else if (accel < 0.0 && rpm < 0.3) {
84 if (n > 0) {
85 rpm = 0.7 + n * 0.1;
[33342]86 n--;
[23190]87 } else
88 rpm = 0.2;
89 }
90 if (speed < 2.0)
91 n = 0;
92 }
[19990]93
[23190]94 public boolean is_on() {
95 return output != null;
96 }
[19990]97
[23190]98 protected double speed;
99 protected double rpm;
100 protected int n;
[19990]101
[23190]102 protected SourceDataLine output = null;
103 protected long frames_written;
104 protected Timer tick = new Timer();
[19990]105
[23190]106 /* Audio parameters. */
107 protected static final int S_RATE = 44100;
108 protected static final int MIN_BUFFER = 4096;
109 protected static final double volume = 0.3;
[19990]110
[23190]111 protected class audio_task extends TimerTask {
[32914]112 @Override
[23190]113 public void run() {
114 if (output == null)
115 return;
[19990]116
[23190]117 /* If more than a two buffers left to play,
118 * reschedule and try to wake up closer to the
119 * end of already written data. */
120 long frames_current = output.getLongFramePosition();
121 if (frames_current < frames_written - MIN_BUFFER * 2) {
122 reschedule(frames_current);
123 return;
124 }
[19990]125
[23190]126 /* Build a new buffer */
127 /* double freq = 20 * Math.pow(1.3, rpm * 5.0); */
128 double freq = (rpm - 0.1) * 160.0;
129 int wavelen = (int) (S_RATE / freq);
130 int bufferlen = MIN_BUFFER - (MIN_BUFFER % wavelen) +
[32914]131 wavelen;
[23190]132 int value = (int) (0x7fff * volume);
[19990]133
[23190]134 bufferlen *= 2;
135 byte[] buffer = new byte[bufferlen];
[33342]136 for (int b = 0; b < bufferlen;) {
[23190]137 int j;
[33342]138 for (j = wavelen / 2; j > 0; j--) {
139 buffer[b++] = (byte) (value >> 8);
140 buffer[b++] = (byte) (value & 0xff);
[23190]141 }
142 value = 0x10000 - value;
[33342]143 for (j = wavelen - wavelen / 2; j > 0; j--) {
144 buffer[b++] = (byte) (value >> 8);
145 buffer[b++] = (byte) (value & 0xff);
[23190]146 }
147 value = 0x10000 - value;
148 }
[19990]149
[23190]150 frames_written +=
[32914]151 output.write(buffer, 0, bufferlen) / 2;
[19990]152
[23190]153 reschedule(frames_current);
154 }
155 }
[19990]156
[23190]157 protected void reschedule(long frames) {
158 /* Send a new buffer as close to the end of the
159 * currently playing buffer as possible (aim at
160 * about half into the last frame). */
161 long delay = (frames_written - frames - MIN_BUFFER / 2) *
[32914]162 1000 / S_RATE;
[23190]163 if (delay < 0)
164 delay = 0;
165 tick.schedule(new audio_task(), delay);
166 }
[19990]167}
Note: See TracBrowser for help on using the repository browser.