1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
 android/src/org/rockbox/RockboxPCM.java      |   18 +++------
 firmware/target/hosted/android/pcm-android.c |   56 ++++++++-----------------
 2 files changed, 24 insertions(+), 50 deletions(-)

diff --git a/android/src/org/rockbox/RockboxPCM.java b/android/src/org/rockbox/RockboxPCM.java
index 146e639..1a123df 100644
--- a/android/src/org/rockbox/RockboxPCM.java
+++ b/android/src/org/rockbox/RockboxPCM.java
@@ -43,9 +43,9 @@ public class RockboxPCM extends AudioTrack
             AudioFormat.CHANNEL_CONFIGURATION_STEREO;
     private static final int encoding = 
             AudioFormat.ENCODING_PCM_16BIT;
-    /* 24k is plenty, but some devices may have a higher minimum */
+    /* 48k is plenty, but some devices may have a higher minimum */
     private static final int buf_len  = 
-            Math.max(24<<10, getMinBufferSize(samplerate, channels, encoding));
+            Math.max(48<<10, getMinBufferSize(samplerate, channels, encoding));

     private void LOG(CharSequence text)
     {
@@ -60,7 +60,6 @@ public class RockboxPCM extends AudioTrack
                 Process.THREAD_PRIORITY_URGENT_AUDIO);
         ht.start();
         raw_data = new byte[buf_len]; /* in shorts */
-        Arrays.fill(raw_data, (byte) 0);
         l = new PCMListener(buf_len);
     }    

@@ -98,6 +97,7 @@ public class RockboxPCM extends AudioTrack
                         setPlaybackPositionUpdateListener(l, h);
                 }
                 /* need to fill with silence before starting playback */
+                Arrays.fill(raw_data, (byte) 0);
                 write(raw_data, frames2bytes(getPlaybackHeadPosition()), 
                         raw_data.length);
             }
@@ -134,28 +134,22 @@ public class RockboxPCM extends AudioTrack
         setStereoVolume(fvolume, fvolume);
     }

-    public native void pcmSamplesToByteArray(byte[] dest);
+    public native int pcmSamplesToByteArray();

     private class PCMListener implements OnPlaybackPositionUpdateListener 
     {
-        private int max_len;
         private int refill_mark;
-        private byte[] buf;
         public PCMListener(int len) 
         {
-            max_len = len;
             /* refill to 100% when reached the 25% */
-            buf = new byte[max_len*3/4];
-            refill_mark = max_len - buf.length;
+            refill_mark = len * 3/4;
         }

         public void onMarkerReached(AudioTrack track) 
         {
             /* push new data to the hardware */
             RockboxPCM pcm = (RockboxPCM)track;
-            int result = -1;
-            pcm.pcmSamplesToByteArray(buf);
-            result = track.write(buf, 0, buf.length);
+            int result = pcm.pcmSamplesToByteArray();
             if (result >= 0)
             {
                 switch(track.getPlayState())
diff --git a/firmware/target/hosted/android/pcm-android.c b/firmware/target/hosted/android/pcm-android.c
index c8bc410..2cd7714 100644
--- a/firmware/target/hosted/android/pcm-android.c
+++ b/firmware/target/hosted/android/pcm-android.c
@@ -34,6 +34,7 @@ static char   *pcm_data_start;
 /* cache frequently called methods */
 static jmethodID play_pause_method;
 static jmethodID stop_method;
+static jmethodID write_method;
 static jmethodID set_volume_method;
 static jclass    RockboxPCM_class;
 static jobject   RockboxPCM_instance;
@@ -51,49 +52,27 @@ static jobject   RockboxPCM_instance;
  *
  * it is called from the PositionMarker callback of AudioTrack
  **/
-JNIEXPORT void JNICALL
+
+JNIEXPORT jint JNICALL
 Java_org_rockbox_RockboxPCM_pcmSamplesToByteArray(JNIEnv *env,
-                                                  jobject this,
-                                                  jbyteArray arr)
+                                                  jobject this)
 {
     (void)this;
-    size_t len;
-	size_t array_size = (*env)->GetArrayLength(env, arr);
-    if (array_size > pcm_data_size)
-        len = pcm_data_size;
-    else
-        len = array_size;
-
-	(*env)->SetByteArrayRegion(env, arr, 0, len, pcm_data_start);
-
-    if (array_size > pcm_data_size)
-    {   /* didn't have enough data for the array ? */
-        size_t remaining = array_size - pcm_data_size;
-        size_t offset = len;
-    retry:
+    if (pcm_data_size == 0)
         pcm_play_get_more_callback((void**)&pcm_data_start, &pcm_data_size);
-        if (pcm_data_size == 0)
-        {
-            DEBUGF("out of data\n");
-            return;
-        }
-        if (remaining > pcm_data_size)
-        {   /* got too little data, get more ... */
-            (*env)->SetByteArrayRegion(env, arr, offset, pcm_data_size, pcm_data_start);
-            /* advance in the java array by the amount we copied */
-            offset += pcm_data_size;
-            /* we copied at least a bit */
-            remaining -= pcm_data_size;
-            pcm_data_size = 0;
-            /* let's get another buch of data and try again */
-            goto retry;
-        }
-        else
-            (*env)->SetByteArrayRegion(env, arr, offset, remaining, pcm_data_start);
-        len = remaining;
+
+    if (pcm_data_size != 0)
+    {
+        jint result;
+        jbyteArray buf = (*env)->NewByteArray(env, (jsize)pcm_data_size);
+        (*env)->SetByteArrayRegion(env, buf, 0, (jsize)pcm_data_size, pcm_data_start);
+        result = (*env)->CallIntMethod(env, RockboxPCM_instance, write_method,
+                                       buf, 0, pcm_data_size);
+        pcm_data_size = 0;
+        return result;
     }
-    pcm_data_start += len;
-    pcm_data_size -= len;
+
+    return -1;
 }

 void pcm_play_lock(void)
@@ -163,6 +142,7 @@ void pcm_play_dma_init(void)
     play_pause_method = e->GetMethodID(env_ptr, RockboxPCM_class, "play_pause", "(Z)V");
     set_volume_method = e->GetMethodID(env_ptr, RockboxPCM_class, "set_volume", "(I)V");
     stop_method       = e->GetMethodID(env_ptr, RockboxPCM_class, "stop", "()V");
+    write_method      = e->GetMethodID(env_ptr, RockboxPCM_class, "write", "([BII)I");
     /* get initial pcm data, if any */
     pcm_play_get_more_callback((void*)&pcm_data_start, &pcm_data_size);
 }