From f4251af2a2dc55c6e2398c5ff1a985238759bb32 Mon Sep 17 00:00:00 2001 From: Julian Winkler Date: Sun, 8 Oct 2023 16:16:36 +0200 Subject: [PATCH] Add more AudioTrack APIs needed for exoplayer. Also fix compiler warnings --- .../audio/android_media_AudioTrack.c | 16 +++--- .../android_media_AudioTrack.h | 14 +++-- src/api-impl/android/media/AudioTrack.java | 51 +++++++++++++++++-- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/api-impl-jni/audio/android_media_AudioTrack.c b/src/api-impl-jni/audio/android_media_AudioTrack.c index 2fdea9e9..d2c4a836 100644 --- a/src/api-impl-jni/audio/android_media_AudioTrack.c +++ b/src/api-impl-jni/audio/android_media_AudioTrack.c @@ -42,8 +42,8 @@ JNIEXPORT void JNICALL Java_android_media_AudioTrack_native_1constructor(JNIEnv snd_pcm_t *pcm_handle; snd_pcm_hw_params_t *params; - jint channels_out; - jint period_time; + unsigned int channels_out; + unsigned int period_time; int ret; @@ -158,7 +158,7 @@ JNIEXPORT jint JNICALL Java_android_media_AudioTrack_getMinBufferSize(JNIEnv *en if((*env)->ExceptionCheck(env)) (*env)->ExceptionDescribe(env); - printf("\n\nJava_android_media_AudioTrack_getMinBufferSize is returning: %d\n\n\n", frames * num_channels * 2); + printf("\n\nJava_android_media_AudioTrack_getMinBufferSize is returning: %ld\n\n\n", frames * num_channels * 2); return frames * num_channels * 2; // FIXME: 2 bytes = 16 bits (s16) } @@ -197,11 +197,8 @@ void periodic_update_callback(snd_async_handler_t *pcm_callback) // return G_SOURCE_REMOVE; } -JNIEXPORT void JNICALL Java_android_media_AudioTrack_play(JNIEnv *env, jobject this) +JNIEXPORT void JNICALL Java_android_media_AudioTrack_native_1play(JNIEnv *env, jobject this) { - pthread_t periodic_notification_thread; - int ret; - jint period_time = _GET_INT_FIELD(this, "period_time"); // FIXME - this callback should probably be set up elsewhere @@ -229,17 +226,15 @@ JNIEXPORT void JNICALL Java_android_media_AudioTrack_play(JNIEnv *env, jobject t /*--↑*/ } -JNIEXPORT jint JNICALL Java_android_media_AudioTrack_write(JNIEnv *env, jobject this, jbyteArray audioData, jint offsetInBytes, jint sizeInBytes) +JNIEXPORT jint JNICALL Java_android_media_AudioTrack_native_1write(JNIEnv *env, jobject this, jbyteArray audioData, jint offsetInBytes, jint frames_to_write) { int ret; if(!PCM_DEVICE) return 0; // STUB - jint channels = _GET_INT_FIELD(this, "channels"); snd_pcm_t *pcm_handle = _PTR(_GET_LONG_FIELD(this, "pcm_handle")); - snd_pcm_sframes_t frames_to_write = sizeInBytes / channels / 2; // FIXME - 2 means PCM16 snd_pcm_sframes_t frames_written; jbyte *buffer = _GET_BYTE_ARRAY_ELEMENTS(audioData); @@ -257,4 +252,5 @@ JNIEXPORT jint JNICALL Java_android_media_AudioTrack_write(JNIEnv *env, jobject // printf("::::> tried to write %d frames, actually wrote %d frames.\n", frames_to_write, frames_written); _RELEASE_BYTE_ARRAY_ELEMENTS(audioData, buffer); + return frames_written; } diff --git a/src/api-impl-jni/generated_headers/android_media_AudioTrack.h b/src/api-impl-jni/generated_headers/android_media_AudioTrack.h index c8a99fac..ff4a91dd 100644 --- a/src/api-impl-jni/generated_headers/android_media_AudioTrack.h +++ b/src/api-impl-jni/generated_headers/android_media_AudioTrack.h @@ -7,6 +7,12 @@ #ifdef __cplusplus extern "C" { #endif +#undef android_media_AudioTrack_PLAYSTATE_STOPPED +#define android_media_AudioTrack_PLAYSTATE_STOPPED 1L +#undef android_media_AudioTrack_PLAYSTATE_PAUSED +#define android_media_AudioTrack_PLAYSTATE_PAUSED 2L +#undef android_media_AudioTrack_PLAYSTATE_PLAYING +#define android_media_AudioTrack_PLAYSTATE_PLAYING 3L /* * Class: android_media_AudioTrack * Method: native_constructor @@ -25,18 +31,18 @@ JNIEXPORT jint JNICALL Java_android_media_AudioTrack_getMinBufferSize /* * Class: android_media_AudioTrack - * Method: play + * Method: native_play * Signature: ()V */ -JNIEXPORT void JNICALL Java_android_media_AudioTrack_play +JNIEXPORT void JNICALL Java_android_media_AudioTrack_native_1play (JNIEnv *, jobject); /* * Class: android_media_AudioTrack - * Method: write + * Method: native_write * Signature: ([BII)I */ -JNIEXPORT jint JNICALL Java_android_media_AudioTrack_write +JNIEXPORT jint JNICALL Java_android_media_AudioTrack_native_1write (JNIEnv *, jobject, jbyteArray, jint, jint); #ifdef __cplusplus diff --git a/src/api-impl/android/media/AudioTrack.java b/src/api-impl/android/media/AudioTrack.java index b65ae97c..0459b3fb 100644 --- a/src/api-impl/android/media/AudioTrack.java +++ b/src/api-impl/android/media/AudioTrack.java @@ -6,6 +6,10 @@ public class AudioTrack { void onPeriodicNotification(AudioTrack track); } + public static final int PLAYSTATE_STOPPED = 1; + public static final int PLAYSTATE_PAUSED = 2; + public static final int PLAYSTATE_PLAYING = 3; + int streamType; int sampleRateInHz; int channelConfig; @@ -13,6 +17,8 @@ public class AudioTrack { int bufferSizeInBytes; int mode; private int sessionId; + private int playbackState = PLAYSTATE_STOPPED; + private int playbackHeadPosition = 0; // for native code's use long pcm_handle; @@ -39,6 +45,9 @@ public class AudioTrack { case 2: num_channels = 1; break; + case 12: + num_channels = 2; + break; default: num_channels = 1; } @@ -66,10 +75,15 @@ public class AudioTrack { return this.frames; } - public native void play(); + public void play() { + System.out.println("calling AudioTrack.play()\n"); + playbackState = PLAYSTATE_PLAYING; + native_play(); + } public void stop() { System.out.println("calling stop(), how did this not get reported before DIDREEEEEEEEEEEEEEEEEEEEEEEEE\n"); + playbackState = PLAYSTATE_STOPPED; } public void flush() { @@ -81,12 +95,43 @@ public class AudioTrack { } public int getState() { - return 0; // TODO: fix up the native part and make this work properly + return 1; // TODO: fix up the native part and make this work properly } - public native int write(byte[] audioData, int offsetInBytes, int sizeInBytes); + public int write(byte[] audioData, int offsetInBytes, int sizeInBytes) { + int framesToWrite = sizeInBytes / channels / 2; // 2 means PCM16 + int ret = native_write(audioData, offsetInBytes, framesToWrite); + if (ret > 0) { + playbackHeadPosition += ret; + } + return ret * channels * 2; // 2 means PCM16 + } public int getAudioSessionId() { return sessionId; } + + public int getSampleRate() { + return sampleRateInHz; + } + + public int setStereoVolume(float leftVolume, float rightVolume) { + return 0; + } + + public int getPlayState() { + return playbackState; + } + + public void pause() { + System.out.println("calling AudioTrack.pause()\n"); + playbackState = PLAYSTATE_PAUSED; + } + + public int getPlaybackHeadPosition() { + return playbackHeadPosition; + } + + public native void native_play(); + private native int native_write(byte[] audioData, int offsetInBytes, int sizeInBytes); }