Skip to content

Commit 19647dd

Browse files
committed
WIP
Signed-off-by: Daniel W. S. Almeida <[email protected]>
1 parent 1308834 commit 19647dd

File tree

3 files changed

+149
-27
lines changed

3 files changed

+149
-27
lines changed

app/src/main/java/io/pslab/activity/WaveGeneratorActivity.java

+129-26
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import android.graphics.drawable.Drawable;
1010
import android.location.Location;
1111
import android.location.LocationManager;
12+
import android.media.AudioDeviceInfo;
1213
import android.media.AudioFormat;
1314
import android.media.AudioManager;
1415
import android.media.AudioTrack;
@@ -140,6 +141,8 @@ public class WaveGeneratorActivity extends AppCompatActivity {
140141
Button btnAnalogMode;
141142
@BindView(R.id.digital_mode_btn)
142143
Button btnDigitalMode;
144+
@BindView(R.id.use_phone_btn)
145+
Button btnUsePhone;
143146
@BindView(R.id.pwm_btn_freq)
144147
Button pwmBtnFreq;
145148
@BindView(R.id.pwm_btn_duty)
@@ -187,7 +190,9 @@ public class WaveGeneratorActivity extends AppCompatActivity {
187190
private RelativeLayout squareModeControls;
188191
private LineChart previewChart;
189192
private boolean isPlayingSound = false;
193+
private boolean usePhone = false;
190194
private ProduceSoundTask produceSoundTask;
195+
private GenerateWavesFromPhoneTask generateWavesFromPhoneTask;
191196

192197
@SuppressLint("ClickableViewAccessibility")
193198
@Override
@@ -334,6 +339,21 @@ public void onClick(View v) {
334339
}
335340
});
336341

342+
btnUsePhone.setOnClickListener(new View.OnClickListener() {
343+
@Override
344+
public void onClick(View v) {
345+
usePhone = !usePhone;
346+
if(usePhone) {
347+
btnUsePhone.setText(R.string.text_use_pslab);
348+
generateWavesFromPhoneTask = new GenerateWavesFromPhoneTask(WaveGeneratorActivity.this);
349+
generateWavesFromPhoneTask.execute();
350+
} else {
351+
btnUsePhone.setText(R.string.text_use_phone);
352+
generateWavesFromPhoneTask.cancel(true);
353+
}
354+
}
355+
});
356+
337357
btnPwmSq1.setOnClickListener(new View.OnClickListener() {
338358
@Override
339359
public void onClick(View view) {
@@ -1282,6 +1302,42 @@ public void recordSensorData(RealmObject sensorData) {
12821302
realm.commitTransaction();
12831303
}
12841304

1305+
/**
1306+
* Samples a wave into an AudioTrack instance. Useful for either playing sound or pushing the signal
1307+
* through the headphone jack.
1308+
*
1309+
*/
1310+
public void sampleWaveIntoAudioTrack(AudioTrack track, int sampleRateInHz, int bufferLength) {
1311+
assert(track != null);
1312+
1313+
short[] buffer = new short[bufferLength];
1314+
float angle = 0;
1315+
float samples[] = new float[bufferLength];
1316+
double frequency;
1317+
1318+
while(true) {
1319+
if (WaveGeneratorCommon.mode_selected == WaveConst.SQUARE) {
1320+
frequency = WaveGeneratorCommon.wave.get(waveBtnActive).get(WaveConst.FREQUENCY);
1321+
} else {
1322+
frequency = WaveGeneratorCommon.wave.get(WaveConst.SQR1).get(WaveConst.FREQUENCY);
1323+
}
1324+
float increment = (float) ((2 * Math.PI) * frequency / sampleRateInHz);
1325+
for (int i = 0; i < samples.length; i++) {
1326+
samples[i] = (float) Math.sin(angle);
1327+
if (WaveGeneratorCommon.mode_selected == WaveConst.PWM) {
1328+
samples[i] = (samples[i] >= 0.0) ? 1 : -1;
1329+
} else {
1330+
if (WaveGeneratorCommon.wave.get(waveBtnActive).get(WaveConst.WAVETYPE) == 2) {
1331+
samples[i] = (float) ((2 / Math.PI) * Math.asin(samples[i]));
1332+
}
1333+
}
1334+
buffer[i] = (short) (samples[i] * Short.MAX_VALUE);
1335+
angle += increment;
1336+
}
1337+
track.write(buffer, 0, buffer.length);
1338+
}
1339+
}
1340+
12851341
public enum WaveConst {WAVETYPE, WAVE1, WAVE2, SQR1, SQR2, SQR3, SQR4, FREQUENCY, PHASE, DUTY, SQUARE, PWM}
12861342

12871343
public enum WaveData {
@@ -1300,47 +1356,94 @@ public final int getValue() {
13001356

13011357
private class ProduceSoundTask extends AsyncTask<Void, Void, Void> {
13021358

1303-
private AudioTrack track;
1359+
final int sampleRateInHz = 44100;
1360+
final int bufferLength = 1024;
1361+
private AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRateInHz, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferLength, AudioTrack.MODE_STREAM);
1362+
private Thread thread = new Thread(new Runnable() {
1363+
@Override
1364+
public void run() {
1365+
track.play();
1366+
sampleWaveIntoAudioTrack(track, sampleRateInHz, bufferLength);
1367+
}
1368+
});
13041369

13051370
@Override
13061371
protected Void doInBackground(Void... voids) {
1307-
short[] buffer = new short[1024];
1308-
track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, buffer.length, AudioTrack.MODE_STREAM);
1309-
float angle = 0;
1310-
float samples[] = new float[1024];
1311-
1312-
track.play();
1313-
double frequency;
1314-
while (isPlayingSound) {
1315-
if (WaveGeneratorCommon.mode_selected == WaveConst.SQUARE) {
1316-
frequency = WaveGeneratorCommon.wave.get(waveBtnActive).get(WaveConst.FREQUENCY);
1317-
} else {
1318-
frequency = WaveGeneratorCommon.wave.get(WaveConst.SQR1).get(WaveConst.FREQUENCY);
1372+
thread.start();
1373+
while(isPlayingSound) {} /* loop until button is unselected */
1374+
thread.interrupt();
1375+
return null;
1376+
}
1377+
1378+
@Override
1379+
protected void onCancelled() {
1380+
super.onCancelled();
1381+
thread.interrupt();
1382+
track.flush();
1383+
track.stop();
1384+
track.release();
1385+
}
1386+
}
1387+
1388+
private class GenerateWavesFromPhoneTask extends AsyncTask<Void, Void, Void> {
1389+
1390+
WaveGeneratorActivity activity = null;
1391+
final int sampleRateInHz = 44100;
1392+
final int bufferLength = 1024;
1393+
private AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRateInHz, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferLength, AudioTrack.MODE_STREAM);
1394+
private Thread thread = new Thread(new Runnable() {
1395+
@Override
1396+
public void run() {
1397+
track.play();
1398+
sampleWaveIntoAudioTrack(track, sampleRateInHz, bufferLength);
1399+
}
1400+
});
1401+
1402+
public GenerateWavesFromPhoneTask(WaveGeneratorActivity activity) {
1403+
this.activity = activity;
1404+
}
1405+
1406+
@Override
1407+
protected Void doInBackground(Void... voids) {
1408+
boolean wired = false;
1409+
AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
1410+
AudioDeviceInfo[] audioDevices = audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
1411+
for(AudioDeviceInfo deviceInfo : audioDevices){
1412+
if(deviceInfo.getType()==AudioDeviceInfo.TYPE_WIRED_HEADPHONES
1413+
|| deviceInfo.getType()==AudioDeviceInfo.TYPE_WIRED_HEADSET){
1414+
wired = true;
1415+
break;
13191416
}
1320-
float increment = (float) ((2 * Math.PI) * frequency / 44100);
1321-
for (int i = 0; i < samples.length; i++) {
1322-
samples[i] = (float) Math.sin(angle);
1323-
if (WaveGeneratorCommon.mode_selected == WaveConst.PWM) {
1324-
samples[i] = (samples[i] >= 0.0) ? 1 : -1;
1325-
} else {
1326-
if (WaveGeneratorCommon.wave.get(waveBtnActive).get(WaveConst.WAVETYPE) == 2) {
1327-
samples[i] = (float) ((2 / Math.PI) * Math.asin(samples[i]));
1328-
}
1417+
}
1418+
if(!wired) {
1419+
activity.runOnUiThread(new Runnable() {
1420+
@Override
1421+
public void run() {
1422+
Toast.makeText(getApplicationContext(), R.string.text_not_wired,Toast.LENGTH_SHORT).show();
13291423
}
1330-
buffer[i] = (short) (samples[i] * Short.MAX_VALUE);
1331-
angle += increment;
1332-
}
1333-
track.write(buffer, 0, buffer.length);
1424+
});
1425+
return null;
13341426
}
1427+
thread.start();
1428+
while(usePhone) {} /* loop until button is unselected */
1429+
thread.interrupt();
13351430
return null;
13361431
}
13371432

13381433
@Override
13391434
protected void onCancelled() {
13401435
super.onCancelled();
1436+
thread.interrupt();
13411437
track.flush();
13421438
track.stop();
13431439
track.release();
13441440
}
1441+
1442+
@Override
1443+
protected void onPostExecute(Void aVoid) {
1444+
super.onPostExecute(aVoid);
1445+
activity.usePhone = false;
1446+
activity.btnUsePhone.setText(R.string.text_use_phone);
1447+
}
13451448
}
13461449
}

app/src/main/res/layout/wave_generator_main_controls.xml

+17
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,21 @@
5151
android:textAllCaps="false"
5252
android:textColor="@color/white"
5353
android:textSize="@dimen/wave_gen_control_text_size" />
54+
55+
<Button
56+
android:id="@+id/use_phone_btn"
57+
android:layout_width="match_parent"
58+
android:layout_height="match_parent"
59+
android:layout_marginStart="@dimen/margin_btn"
60+
android:layout_marginTop="@dimen/margin_btn"
61+
android:layout_marginEnd="@dimen/margin_btn"
62+
android:layout_marginBottom="@dimen/margin_btn"
63+
android:layout_weight="1"
64+
android:background="@drawable/btn_back_rounded"
65+
android:minWidth="@dimen/btn_min_width"
66+
android:stateListAnimator="@animator/selector_animator"
67+
android:text="@string/text_use_phone"
68+
android:textAllCaps="false"
69+
android:textColor="@color/white"
70+
android:textSize="@dimen/wave_gen_control_text_size" />
5471
</LinearLayout>

app/src/main/res/values/strings.xml

+3-1
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,9 @@
695695
<string name="duty_cycle">Duty Cycle:</string>
696696
<string name="mode">Mode</string>
697697
<string name="text_digital">Digital</string>
698-
698+
<string name="text_use_phone">Use Phone</string>
699+
<string name="text_use_pslab">Use PSLab</string>
700+
<string name="text_not_wired">Nothing plugged in the headphone jack</string>
699701
<string name="text_connected">Connected</string>
700702
<string name="text_disconnected">Disconnected</string>
701703

0 commit comments

Comments
 (0)