Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel W. S. Almeida <[email protected]>
  • Loading branch information
dwlsalmeida committed Nov 13, 2019
1 parent 1308834 commit 04ddfa7
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 31 deletions.
138 changes: 108 additions & 30 deletions app/src/main/java/io/pslab/activity/WaveGeneratorActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationManager;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
Expand Down Expand Up @@ -140,6 +141,8 @@ public class WaveGeneratorActivity extends AppCompatActivity {
Button btnAnalogMode;
@BindView(R.id.digital_mode_btn)
Button btnDigitalMode;
@BindView(R.id.use_phone_btn)
Button btnUsePhone;
@BindView(R.id.pwm_btn_freq)
Button pwmBtnFreq;
@BindView(R.id.pwm_btn_duty)
Expand Down Expand Up @@ -187,7 +190,9 @@ public class WaveGeneratorActivity extends AppCompatActivity {
private RelativeLayout squareModeControls;
private LineChart previewChart;
private boolean isPlayingSound = false;
private boolean usePhone = false;
private ProduceSoundTask produceSoundTask;
private GenerateWavesFromPhoneTask generateWavesFromPhoneTask;

@SuppressLint("ClickableViewAccessibility")
@Override
Expand Down Expand Up @@ -334,6 +339,24 @@ public void onClick(View v) {
}
});

btnUsePhone.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
usePhone = !usePhone;
if(usePhone) {
if(isPlayingSound) {
btnProduceSound.callOnClick();
}
btnUsePhone.setText(R.string.text_use_pslab);
generateWavesFromPhoneTask = new GenerateWavesFromPhoneTask(WaveGeneratorActivity.this);
generateWavesFromPhoneTask.execute();
} else {
btnUsePhone.setText(R.string.text_use_phone);
generateWavesFromPhoneTask.cancel(true);
}
}
});

btnPwmSq1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Expand Down Expand Up @@ -1282,6 +1305,42 @@ public void recordSensorData(RealmObject sensorData) {
realm.commitTransaction();
}

/**
* Samples a wave into an AudioTrack instance. Useful for either playing sound or pushing the signal
* through the headphone jack.
*
*/
public void sampleWaveIntoAudioTrack(AudioTrack track, int sampleRateInHz, int bufferLength, AsyncTask asyncTask) {
assert(track != null);

short[] buffer = new short[bufferLength];
float angle = 0;
float samples[] = new float[bufferLength];
double frequency;

while(!asyncTask.isCancelled()) {
if (WaveGeneratorCommon.mode_selected == WaveConst.SQUARE) {
frequency = WaveGeneratorCommon.wave.get(waveBtnActive).get(WaveConst.FREQUENCY);
} else {
frequency = WaveGeneratorCommon.wave.get(WaveConst.SQR1).get(WaveConst.FREQUENCY);
}
float increment = (float) ((2 * Math.PI) * frequency / sampleRateInHz);
for (int i = 0; i < samples.length; i++) {
samples[i] = (float) Math.sin(angle);
if (WaveGeneratorCommon.mode_selected == WaveConst.PWM) {
samples[i] = (samples[i] >= 0.0) ? 1 : -1;
} else {
if (WaveGeneratorCommon.wave.get(waveBtnActive).get(WaveConst.WAVETYPE) == 2) {
samples[i] = (float) ((2 / Math.PI) * Math.asin(samples[i]));
}
}
buffer[i] = (short) (samples[i] * Short.MAX_VALUE);
angle += increment;
}
track.write(buffer, 0, buffer.length);
}
}

public enum WaveConst {WAVETYPE, WAVE1, WAVE2, SQR1, SQR2, SQR3, SQR4, FREQUENCY, PHASE, DUTY, SQUARE, PWM}

public enum WaveData {
Expand All @@ -1300,47 +1359,66 @@ public final int getValue() {

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

private AudioTrack track;
final int sampleRateInHz = 44100;
final int bufferLength = 1024;
private AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRateInHz, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferLength, AudioTrack.MODE_STREAM);

@Override
protected Void doInBackground(Void... voids) {
short[] buffer = new short[1024];
track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, buffer.length, AudioTrack.MODE_STREAM);
float angle = 0;
float samples[] = new float[1024];

track.play();
double frequency;
while (isPlayingSound) {
if (WaveGeneratorCommon.mode_selected == WaveConst.SQUARE) {
frequency = WaveGeneratorCommon.wave.get(waveBtnActive).get(WaveConst.FREQUENCY);
} else {
frequency = WaveGeneratorCommon.wave.get(WaveConst.SQR1).get(WaveConst.FREQUENCY);
}
float increment = (float) ((2 * Math.PI) * frequency / 44100);
for (int i = 0; i < samples.length; i++) {
samples[i] = (float) Math.sin(angle);
if (WaveGeneratorCommon.mode_selected == WaveConst.PWM) {
samples[i] = (samples[i] >= 0.0) ? 1 : -1;
} else {
if (WaveGeneratorCommon.wave.get(waveBtnActive).get(WaveConst.WAVETYPE) == 2) {
samples[i] = (float) ((2 / Math.PI) * Math.asin(samples[i]));
}
}
buffer[i] = (short) (samples[i] * Short.MAX_VALUE);
angle += increment;
}
track.write(buffer, 0, buffer.length);
}
sampleWaveIntoAudioTrack(track, sampleRateInHz, bufferLength, this);
track.flush();
track.stop();
track.release();
return null;
}
}

private class GenerateWavesFromPhoneTask extends AsyncTask<Void, Void, Void> {

WaveGeneratorActivity activity = null;
final int sampleRateInHz = 44100;
final int bufferLength = 1024;
private AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRateInHz, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferLength, AudioTrack.MODE_STREAM);

public GenerateWavesFromPhoneTask(WaveGeneratorActivity activity) {
this.activity = activity;
}

@Override
protected void onCancelled() {
super.onCancelled();
protected Void doInBackground(Void... voids) {
boolean wired = false;
AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
AudioDeviceInfo[] audioDevices = audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
for(AudioDeviceInfo deviceInfo : audioDevices){
if(deviceInfo.getType()==AudioDeviceInfo.TYPE_WIRED_HEADPHONES
|| deviceInfo.getType()==AudioDeviceInfo.TYPE_WIRED_HEADSET){
wired = true;
break;
}
}
if(!wired) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), R.string.text_not_wired,Toast.LENGTH_SHORT).show();
}
});
return null;
}
track.play();
sampleWaveIntoAudioTrack(track, sampleRateInHz, bufferLength, this);
track.flush();
track.stop();
track.release();
return null;
}

@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
activity.usePhone = false;
activity.btnUsePhone.setText(R.string.text_use_phone);
}
}
}
17 changes: 17 additions & 0 deletions app/src/main/res/layout/wave_generator_main_controls.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,21 @@
android:textAllCaps="false"
android:textColor="@color/white"
android:textSize="@dimen/wave_gen_control_text_size" />

<Button
android:id="@+id/use_phone_btn"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/margin_btn"
android:layout_marginTop="@dimen/margin_btn"
android:layout_marginEnd="@dimen/margin_btn"
android:layout_marginBottom="@dimen/margin_btn"
android:layout_weight="1"
android:background="@drawable/btn_back_rounded"
android:minWidth="@dimen/btn_min_width"
android:stateListAnimator="@animator/selector_animator"
android:text="@string/text_use_phone"
android:textAllCaps="false"
android:textColor="@color/white"
android:textSize="@dimen/wave_gen_control_text_size" />
</LinearLayout>
4 changes: 3 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,9 @@
<string name="duty_cycle">Duty Cycle:</string>
<string name="mode">Mode</string>
<string name="text_digital">Digital</string>

<string name="text_use_phone">Use Phone</string>
<string name="text_use_pslab">Use PSLab</string>
<string name="text_not_wired">Nothing plugged in the headphone jack</string>
<string name="text_connected">Connected</string>
<string name="text_disconnected">Disconnected</string>

Expand Down

0 comments on commit 04ddfa7

Please sign in to comment.