Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DrumThumper: hack latency buttons, Do Not Merge #2098

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions samples/drumthumper/src/main/cpp/DrumPlayerJNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ JNIEXPORT void JNICALL Java_com_plausiblesoftware_drumthumper_DrumPlayer_clearOu
*/
JNIEXPORT void JNICALL Java_com_plausiblesoftware_drumthumper_DrumPlayer_restartStream(JNIEnv*, jobject) {
sDTPlayer.resetAll();
sDTPlayer.teardownAudioStream();
usleep(40 * 1000); // give samples time to stop
if (sDTPlayer.openStream() && sDTPlayer.startStream()){
__android_log_print(ANDROID_LOG_INFO, TAG, "openStream successful");
} else {
Expand Down Expand Up @@ -162,6 +164,18 @@ JNIEXPORT jfloat JNICALL Java_com_plausiblesoftware_drumthumper_DrumPlayer_getGa
return sDTPlayer.getGain(index);
}

JNIEXPORT void JNICALL
Java_com_plausiblesoftware_drumthumper_DrumPlayer_setLatencyMode(JNIEnv *env, jobject thiz,
jint latencyMode) {
const int LATENCY_LOW_MMAP = 0; // Must match definitions in DrumPlayer.java
const int LATENCY_NORMAL = 2;
sDTPlayer.setMMapEnabled(latencyMode == LATENCY_LOW_MMAP);
sDTPlayer.setPerformanceMode(
(latencyMode == LATENCY_NORMAL)
? oboe::PerformanceMode::None
: oboe::PerformanceMode::LowLatency);
}

#ifdef __cplusplus
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ class DrumPlayer {
val PAN_HIHATOPEN: Float = -1.0f // Hard Left
val PAN_HIHATCLOSED: Float = -1.0f // Hard Left

val LATENCY_LOW_MMAP = 0
val LATENCY_LOW_LEGACY = 1
val LATENCY_NORMAL = 2

// Logging Tag
val TAG: String = "DrumPlayer"
}
Expand Down Expand Up @@ -111,4 +115,6 @@ class DrumPlayer {
external fun clearOutputReset()

external fun restartStream()

external fun setLatencyMode(latncyMode: Int)
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.LinearLayout
import android.widget.RadioButton
import android.widget.SeekBar
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
Expand Down Expand Up @@ -159,13 +160,43 @@ class DrumThumperActivity : AppCompatActivity(),
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

// UI
setContentView(R.layout.drumthumper_activity)

mAudioMgr = getSystemService(Context.AUDIO_SERVICE) as AudioManager

val mRadioLatency0 = findViewById<View>(R.id.latencyMode0) as RadioButton
mRadioLatency0.setOnClickListener(View.OnClickListener { view ->
onLatencyRadioButtonClicked(view, 0)
})

val mRadioLatency1 = findViewById<View>(R.id.latencyMode1) as RadioButton?
if (mRadioLatency1 != null) {
mRadioLatency1.setOnClickListener(View.OnClickListener { view ->
onLatencyRadioButtonClicked(view, 1)
})
}

val mRadioLatency2 = findViewById<View>(R.id.latencyMode2) as RadioButton?
if (mRadioLatency2 != null) {
mRadioLatency2.setOnClickListener(View.OnClickListener { view ->
onLatencyRadioButtonClicked(view, 2)
})
}
}

private fun onLatencyRadioButtonClicked(view: View, mode: Int) {
val checked = (view as RadioButton).isChecked
if (!checked) return
mDrumPlayer.setLatencyMode(mode)
mDrumPlayer.restartStream()
}

override fun onStart() {
super.onStart()

mDrumPlayer.setLatencyMode(DrumPlayer.LATENCY_LOW_MMAP)

mDrumPlayer.setupAudioStream()

mDrumPlayer.loadWavAssets(getAssets())
Expand All @@ -180,9 +211,6 @@ class DrumThumperActivity : AppCompatActivity(),
override fun onResume() {
super.onResume()

// UI
setContentView(R.layout.drumthumper_activity)

// "Kick" drum
findViewById<TriggerPad>(R.id.kickPad).addListener(this)
connectMixSliders(R.id.kickPan, R.id.kickGain, DrumPlayer.BASSDRUM)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -491,9 +491,54 @@
</LinearLayout>
</LinearLayout>
</LinearLayout>
<Button

<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hide/Show Mix Controls"
android:id="@+id/mixCtrlBtn"/>
android:layout_height="match_parent">

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hide/Show Mix Controls"
android:id="@+id/mixCtrlBtn"/>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:text="Latency:" />

<RadioGroup
android:id="@+id/latencyModeGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">

<RadioButton
android:id="@+id/latencyMode0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:textSize="20sp"
android:text="MMAP"
/>

<RadioButton
android:id="@+id/latencyMode1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:text="Legacy"
/>

<RadioButton
android:id="@+id/latencyMode2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:text="None"
/>
</RadioGroup>
</LinearLayout>
</LinearLayout>
45 changes: 45 additions & 0 deletions samples/drumthumper/src/main/res/layout/drumthumper_activity.xml
Original file line number Diff line number Diff line change
Expand Up @@ -508,4 +508,49 @@
android:layout_height="wrap_content"
android:text="Hide/Show Mix Controls"
android:id="@+id/mixCtrlBtn"/>

<LinearLayout
android:orientation="horizontal"
android:padding="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:text="Latency:" />

<RadioGroup
android:id="@+id/latencyModeGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">

<RadioButton
android:id="@+id/latencyMode0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:textSize="20sp"
android:text="MMAP"
/>

<RadioButton
android:id="@+id/latencyMode1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:text="Legacy"
/>

<RadioButton
android:id="@+id/latencyMode2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:text="None"
/>
</RadioGroup>
</LinearLayout>
</LinearLayout>
9 changes: 6 additions & 3 deletions samples/iolib/src/main/cpp/player/SimpleMultiPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,14 @@ bool SimpleMultiPlayer::openStream() {
// we will resample source data to device rate, so take default sample rate
builder.setDataCallback(mDataCallback);
builder.setErrorCallback(mErrorCallback);
builder.setPerformanceMode(PerformanceMode::LowLatency);
builder.setPerformanceMode(mPerformanceMode);
builder.setSharingMode(SharingMode::Exclusive);
builder.setSampleRateConversionQuality(SampleRateConversionQuality::Medium);
// builder.setSampleRateConversionQuality(SampleRateConversionQuality::Medium);

bool wasMMapEnabled = OboeExtensions::isMMapEnabled();
OboeExtensions::setMMapEnabled(mMMapEnabled);
Result result = builder.openStream(mAudioStream);
OboeExtensions::setMMapEnabled(wasMMapEnabled);
if (result != Result::OK){
__android_log_print(
ANDROID_LOG_ERROR,
Expand Down Expand Up @@ -119,7 +122,7 @@ bool SimpleMultiPlayer::startStream() {
int tryCount = 0;
while (tryCount < 3) {
bool wasOpenSuccessful = true;
// Assume that apenStream() was called successfully before startStream() call.
// Assume that openStream() was called successfully before startStream() call.
if (tryCount > 0) {
usleep(20 * 1000); // Sleep between tries to give the system time to settle.
wasOpenSuccessful = openStream(); // Try to open the stream again after the first try.
Expand Down
20 changes: 20 additions & 0 deletions samples/iolib/src/main/cpp/player/SimpleMultiPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,22 @@ class SimpleMultiPlayer {
void setGain(int index, float gain);
float getGain(int index);

oboe::PerformanceMode getPerformanceMode() const {
return mPerformanceMode;
}

void setPerformanceMode(oboe::PerformanceMode performanceMode) {
mPerformanceMode = performanceMode;
}

bool isMMapEnabled() const {
return mMMapEnabled;
}

void setMMapEnabled(bool enabled) {
mMMapEnabled = enabled;
}

private:
class MyDataCallback : public oboe::AudioStreamDataCallback {
public:
Expand Down Expand Up @@ -101,6 +117,10 @@ class SimpleMultiPlayer {
// Playback Audio attributes
int32_t mChannelCount;
int32_t mSampleRate;
oboe::PerformanceMode mPerformanceMode = oboe::PerformanceMode::LowLatency;

private:
bool mMMapEnabled = false;

// Sample Data
int32_t mNumSampleBuffers;
Expand Down