summaryrefslogtreecommitdiff
path: root/firmware/target/hosted/android
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-06-29 06:37:04 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-06-29 06:37:04 +0000
commita2b6703a369f6cdbfec1f150c408dadc877631fb (patch)
tree3145a8c1372c44711d38feefeba39c7d4098f139 /firmware/target/hosted/android
parent8411614b8a068a4f274c3841aa55aab1df1bc246 (diff)
downloadrockbox-a2b6703a369f6cdbfec1f150c408dadc877631fb.tar.gz
rockbox-a2b6703a369f6cdbfec1f150c408dadc877631fb.zip
Commit FS#12150 - Fully-functional audio mixer - and finally whip old limitations about playback of voice and other sounds when paused. Channels are independent in state and amplitude. Fade on stop/pause is handled by the channel's volume control rather than global volume which means it now works from anywhere. Opens up the possibility of plugin sounds during music playback by merely adding an additional channel enum. If any PCM drivers were not properly modified, see one of the last comments in the task for a description of the simple change that is expected. Some params are tunable in firmware/export/pcm-mixer.h as well.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30097 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/hosted/android')
-rw-r--r--firmware/target/hosted/android/pcm-android.c54
1 files changed, 52 insertions, 2 deletions
diff --git a/firmware/target/hosted/android/pcm-android.c b/firmware/target/hosted/android/pcm-android.c
index 88792cd76f..cbd6cb3228 100644
--- a/firmware/target/hosted/android/pcm-android.c
+++ b/firmware/target/hosted/android/pcm-android.c
@@ -23,14 +23,18 @@
23#include <stdbool.h> 23#include <stdbool.h>
24#define _SYSTEM_WITH_JNI /* for getJavaEnvironment */ 24#define _SYSTEM_WITH_JNI /* for getJavaEnvironment */
25#include <system.h> 25#include <system.h>
26#include <pthread.h>
26#include "debug.h" 27#include "debug.h"
27#include "pcm.h" 28#include "pcm.h"
29#include "pcm-internal.h"
28 30
29extern JNIEnv *env_ptr; 31extern JNIEnv *env_ptr;
30 32
31/* infos about our pcm chunks */ 33/* infos about our pcm chunks */
32static size_t pcm_data_size; 34static size_t pcm_data_size;
33static char *pcm_data_start; 35static char *pcm_data_start;
36static int audio_locked = 0;
37static pthread_mutex_t audio_lock_mutex = PTHREAD_MUTEX_INITIALIZER;
34 38
35/* cache frequently called methods */ 39/* cache frequently called methods */
36static jmethodID play_pause_method; 40static jmethodID play_pause_method;
@@ -42,6 +46,20 @@ static jobject RockboxPCM_instance;
42 46
43 47
44/* 48/*
49 * mutex lock/unlock wrappers neatness' sake
50 */
51static inline void lock_audio(void)
52{
53 pthread_mutex_lock(&audio_lock_mutex);
54}
55
56static inline void unlock_audio(void)
57{
58 pthread_mutex_unlock(&audio_lock_mutex);
59}
60
61
62/*
45 * write pcm samples to the hardware. Calls AudioTrack.write directly (which 63 * write pcm samples to the hardware. Calls AudioTrack.write directly (which
46 * is usually a blocking call) 64 * is usually a blocking call)
47 * 65 *
@@ -54,10 +72,17 @@ JNIEXPORT jint JNICALL
54Java_org_rockbox_RockboxPCM_nativeWrite(JNIEnv *env, jobject this, 72Java_org_rockbox_RockboxPCM_nativeWrite(JNIEnv *env, jobject this,
55 jbyteArray temp_array, jint max_size) 73 jbyteArray temp_array, jint max_size)
56{ 74{
75 bool new_buffer = false;
76
77 lock_audio();
78
57 jint left = max_size; 79 jint left = max_size;
58 80
59 if (!pcm_data_size) /* get some initial data */ 81 if (!pcm_data_size) /* get some initial data */
82 {
83 new_buffer = true;
60 pcm_play_get_more_callback((void**) &pcm_data_start, &pcm_data_size); 84 pcm_play_get_more_callback((void**) &pcm_data_start, &pcm_data_size);
85 }
61 86
62 while(left > 0 && pcm_data_size) 87 while(left > 0 && pcm_data_size)
63 { 88 {
@@ -70,23 +95,49 @@ Java_org_rockbox_RockboxPCM_nativeWrite(JNIEnv *env, jobject this,
70 95
71 ret = (*env)->CallIntMethod(env, this, write_method, 96 ret = (*env)->CallIntMethod(env, this, write_method,
72 temp_array, 0, transfer_size); 97 temp_array, 0, transfer_size);
98
99 if (new_buffer)
100 {
101 new_buffer = false;
102 pcm_play_dma_started_callback();
103
104 /* NOTE: might need to release the mutex and sleep here if the
105 buffer is shorter than the required buffer (like pcm-sdl.c) to
106 have the mixer clocked at a regular interval */
107 }
108
73 if (ret < 0) 109 if (ret < 0)
110 {
111 unlock_audio();
74 return ret; 112 return ret;
113 }
75 114
76 if (pcm_data_size == 0) /* need new data */ 115 if (pcm_data_size == 0) /* need new data */
116 {
117 new_buffer = true;
77 pcm_play_get_more_callback((void**)&pcm_data_start, &pcm_data_size); 118 pcm_play_get_more_callback((void**)&pcm_data_start, &pcm_data_size);
119 }
78 else /* increment data pointer and feed more */ 120 else /* increment data pointer and feed more */
79 pcm_data_start += transfer_size; 121 pcm_data_start += transfer_size;
80 } 122 }
123
124 if (new_buffer && pcm_data_size)
125 pcm_play_dma_started_callback();
126
127 unlock_audio();
81 return max_size - left; 128 return max_size - left;
82} 129}
83 130
84void pcm_play_lock(void) 131void pcm_play_lock(void)
85{ 132{
133 if (++audio_locked == 1)
134 lock_audio();
86} 135}
87 136
88void pcm_play_unlock(void) 137void pcm_play_unlock(void)
89{ 138{
139 if (--audio_locked == 0)
140 unlock_audio();
90} 141}
91 142
92void pcm_dma_apply_settings(void) 143void pcm_dma_apply_settings(void)
@@ -153,8 +204,6 @@ void pcm_play_dma_init(void)
153 set_volume_method = e->GetMethodID(env_ptr, RockboxPCM_class, "set_volume", "(I)V"); 204 set_volume_method = e->GetMethodID(env_ptr, RockboxPCM_class, "set_volume", "(I)V");
154 stop_method = e->GetMethodID(env_ptr, RockboxPCM_class, "stop", "()V"); 205 stop_method = e->GetMethodID(env_ptr, RockboxPCM_class, "stop", "()V");
155 write_method = e->GetMethodID(env_ptr, RockboxPCM_class, "write", "([BII)I"); 206 write_method = e->GetMethodID(env_ptr, RockboxPCM_class, "write", "([BII)I");
156 /* get initial pcm data, if any */
157 pcm_play_get_more_callback((void*)&pcm_data_start, &pcm_data_size);
158} 207}
159 208
160void pcm_postinit(void) 209void pcm_postinit(void)
@@ -173,6 +222,7 @@ void pcm_shutdown(void)
173 JNIEnv e = *env_ptr; 222 JNIEnv e = *env_ptr;
174 jmethodID release = e->GetMethodID(env_ptr, RockboxPCM_class, "release", "()V"); 223 jmethodID release = e->GetMethodID(env_ptr, RockboxPCM_class, "release", "()V");
175 e->CallVoidMethod(env_ptr, RockboxPCM_instance, release); 224 e->CallVoidMethod(env_ptr, RockboxPCM_instance, release);
225 pthread_mutex_destroy(&audio_lock_mutex);
176} 226}
177 227
178/* Due to limitations of default_event_handler(), parameters gets swallowed when 228/* Due to limitations of default_event_handler(), parameters gets swallowed when