diff options
author | Thomas Martitz <kugel@rockbox.org> | 2010-08-04 18:34:32 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2010-08-04 18:34:32 +0000 |
commit | bd9c0b21d6209b687be5f0006c0d9dc68aefbccf (patch) | |
tree | 900f199596e0442f1e52753a0b225cceffb93664 /android | |
parent | c216100f843d5ec0fba5a4f49907d666a65028b1 (diff) | |
download | rockbox-bd9c0b21d6209b687be5f0006c0d9dc68aefbccf.tar.gz rockbox-bd9c0b21d6209b687be5f0006c0d9dc68aefbccf.zip |
A bit of work in the pcm driver. Should be a bit more efficient, but more importantly more dependable. Stopping playback now properly recovers if playback crashed for some reason (shouldn't happen of course).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27698 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'android')
-rw-r--r-- | android/src/org/rockbox/RockboxPCM.java | 69 |
1 files changed, 37 insertions, 32 deletions
diff --git a/android/src/org/rockbox/RockboxPCM.java b/android/src/org/rockbox/RockboxPCM.java index f2568d8406..631d925b12 100644 --- a/android/src/org/rockbox/RockboxPCM.java +++ b/android/src/org/rockbox/RockboxPCM.java | |||
@@ -29,10 +29,12 @@ import android.util.Log; | |||
29 | public class RockboxPCM extends AudioTrack | 29 | public class RockboxPCM extends AudioTrack |
30 | { | 30 | { |
31 | byte[] raw_data; | 31 | byte[] raw_data; |
32 | private int buf_len; | ||
33 | private PCMListener l; | ||
32 | 34 | ||
33 | private void LOG(CharSequence text) | 35 | private void LOG(CharSequence text) |
34 | { | 36 | { |
35 | Log.d("RockboxBootloader", (String) text); | 37 | Log.d("Rockbox", (String) text); |
36 | } | 38 | } |
37 | 39 | ||
38 | public RockboxPCM() | 40 | public RockboxPCM() |
@@ -44,18 +46,11 @@ public class RockboxPCM extends AudioTrack | |||
44 | AudioFormat.ENCODING_PCM_16BIT, | 46 | AudioFormat.ENCODING_PCM_16BIT, |
45 | 24<<10, | 47 | 24<<10, |
46 | AudioTrack.MODE_STREAM); | 48 | AudioTrack.MODE_STREAM); |
47 | int buf_len = 24<<10; | 49 | buf_len = 24<<10; /* in bytes */ |
48 | 50 | ||
49 | raw_data = new byte[buf_len*2]; | 51 | raw_data = new byte[buf_len]; /* in shorts */ |
50 | for(int i = 0; i < raw_data.length; i++) raw_data[i] = (byte) 0x00; | 52 | for(int i = 0; i < raw_data.length; i++) raw_data[i] = (byte)0; |
51 | /* fill with silence */ | 53 | l = new PCMListener(buf_len); |
52 | write(raw_data, 0, raw_data.length); | ||
53 | if (getState() == AudioTrack.STATE_INITIALIZED) | ||
54 | { | ||
55 | if (setNotificationMarkerPosition(bytes2frames(buf_len*2)/4) != AudioTrack.SUCCESS) | ||
56 | LOG("setNotificationMarkerPosition Error"); | ||
57 | setPlaybackPositionUpdateListener(new PCMListener(buf_len*2)); | ||
58 | } | ||
59 | } | 54 | } |
60 | 55 | ||
61 | int bytes2frames(int bytes) { | 56 | int bytes2frames(int bytes) { |
@@ -70,28 +65,37 @@ public class RockboxPCM extends AudioTrack | |||
70 | 65 | ||
71 | @SuppressWarnings("unused") | 66 | @SuppressWarnings("unused") |
72 | private void play_pause(boolean pause) { | 67 | private void play_pause(boolean pause) { |
73 | LOG("play_pause()"); | ||
74 | if (pause) | 68 | if (pause) |
69 | { | ||
75 | pause(); | 70 | pause(); |
71 | } | ||
76 | else | 72 | else |
77 | { | 73 | { |
78 | if (getPlayState() == AudioTrack.PLAYSTATE_STOPPED) | 74 | if (getPlayState() == AudioTrack.PLAYSTATE_STOPPED) |
79 | { | 75 | { |
80 | for(int i = 0; i < raw_data.length; i++) raw_data[i] = (byte) 0x00; | ||
81 | LOG("Writing silence"); | ||
82 | /* fill with silence */ | ||
83 | write(raw_data, 0, raw_data.length); | ||
84 | RockboxService.startForeground(); | 76 | RockboxService.startForeground(); |
77 | if (getState() == AudioTrack.STATE_INITIALIZED) | ||
78 | { | ||
79 | if (setNotificationMarkerPosition(bytes2frames(buf_len)/4) != AudioTrack.SUCCESS) | ||
80 | LOG("setNotificationMarkerPosition Error"); | ||
81 | else | ||
82 | setPlaybackPositionUpdateListener(l); | ||
83 | } | ||
84 | /* need to fill with silence before starting playback */ | ||
85 | write(raw_data, frames2bytes(getPlaybackHeadPosition()), raw_data.length); | ||
85 | } | 86 | } |
86 | play(); | 87 | play(); |
87 | } | 88 | } |
88 | LOG("play_pause() return"); | ||
89 | } | 89 | } |
90 | 90 | ||
91 | @Override | 91 | @Override |
92 | public void stop() throws IllegalStateException | 92 | public void stop() throws IllegalStateException |
93 | { | 93 | { |
94 | super.stop(); | 94 | try { |
95 | super.stop(); | ||
96 | } catch (IllegalStateException e) { | ||
97 | throw new IllegalStateException(e); | ||
98 | } | ||
95 | RockboxService.stopForeground(); | 99 | RockboxService.stopForeground(); |
96 | } | 100 | } |
97 | 101 | ||
@@ -115,30 +119,31 @@ public class RockboxPCM extends AudioTrack | |||
115 | 119 | ||
116 | private class PCMListener implements OnPlaybackPositionUpdateListener { | 120 | private class PCMListener implements OnPlaybackPositionUpdateListener { |
117 | int max_len; | 121 | int max_len; |
122 | int refill_mark; | ||
118 | byte[] buf; | 123 | byte[] buf; |
119 | public PCMListener(int len) { | 124 | public PCMListener(int len) { |
120 | max_len = len; | 125 | max_len = len; |
121 | buf = new byte[len/2]; | 126 | /* refill to 100% when reached the 25% */ |
127 | buf = new byte[max_len*3/4]; | ||
128 | refill_mark = max_len - buf.length; | ||
122 | } | 129 | } |
123 | @Override | 130 | @Override |
124 | public void onMarkerReached(AudioTrack track) { | 131 | public void onMarkerReached(AudioTrack track) { |
125 | // push new data to the hardware | 132 | // push new data to the hardware |
126 | int result = 1; | 133 | RockboxPCM pcm = (RockboxPCM)track; |
127 | pcmSamplesToByteArray(buf); | 134 | int result = -1; |
128 | //LOG("Trying to write " + buf.length + " bytes"); | 135 | pcm.pcmSamplesToByteArray(buf); |
129 | result = track.write(buf, 0, buf.length); | 136 | result = track.write(buf, 0, buf.length); |
130 | if (result > 0) | 137 | if (result >= 0) |
131 | { | 138 | { |
132 | //LOG(result + " bytes written"); | ||
133 | track.setPlaybackPositionUpdateListener(this); | ||
134 | track.setNotificationMarkerPosition(bytes2frames(max_len)/4); | ||
135 | switch(track.getPlayState()) | 139 | switch(track.getPlayState()) |
136 | { | 140 | { |
137 | case AudioTrack.PLAYSTATE_PLAYING: | 141 | case AudioTrack.PLAYSTATE_PLAYING: |
138 | //LOG("State PLAYING"); | ||
139 | break; | ||
140 | case AudioTrack.PLAYSTATE_PAUSED: | 142 | case AudioTrack.PLAYSTATE_PAUSED: |
141 | LOG("State PAUSED"); | 143 | /* recharge */ |
144 | setPlaybackPositionUpdateListener(this); | ||
145 | /* refill at 25% no matter of how many bytes we've written */ | ||
146 | setNotificationMarkerPosition(bytes2frames(refill_mark)); | ||
142 | break; | 147 | break; |
143 | case AudioTrack.PLAYSTATE_STOPPED: | 148 | case AudioTrack.PLAYSTATE_STOPPED: |
144 | LOG("State STOPPED"); | 149 | LOG("State STOPPED"); |
@@ -147,8 +152,8 @@ public class RockboxPCM extends AudioTrack | |||
147 | } | 152 | } |
148 | else | 153 | else |
149 | { | 154 | { |
150 | LOG("Error in onMarkerReached"); | 155 | LOG("Error in onMarkerReached (result="+result+")"); |
151 | track.stop(); | 156 | stop(); |
152 | } | 157 | } |
153 | } | 158 | } |
154 | 159 | ||