summaryrefslogtreecommitdiff
path: root/streamer.c
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-10-02 19:20:34 +0200
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-10-02 19:20:34 +0200
commit6cbf891c080008679dc344a5ed855af62b822fe8 (patch)
treeb21cfccdc4d02403d325a6d4c612d69b4d991a61 /streamer.c
parent8d67c4ea1f4171227e5dfb1842cffcde1693dac0 (diff)
converted streamer to use ringbuffer
that removes io/playback interlocking also faster
Diffstat (limited to 'streamer.c')
-rw-r--r--streamer.c64
1 files changed, 41 insertions, 23 deletions
diff --git a/streamer.c b/streamer.c
index fb4fc6e7..36d83ab5 100644
--- a/streamer.c
+++ b/streamer.c
@@ -53,8 +53,11 @@ static float g_srcbuffer[SRC_BUFFER_SIZE];
static int streaming_terminate;
// buffer up to 3 seconds at 44100Hz stereo
-#define STREAM_BUFFER_SIZE (44100*3*4)
+#define STREAM_BUFFER_SIZE 0x80000 // slightly more than 3 seconds of 44100 stereo
+#define STREAM_BUFFER_MASK 0x7ffff
+
static int streambuffer_fill;
+static int streambuffer_pos;
static int bytes_until_next_song = 0;
static char streambuffer[STREAM_BUFFER_SIZE];
static uintptr_t mutex;
@@ -317,6 +320,7 @@ streamer_thread (uintptr_t ctx) {
streamer_lock ();
playpos = str_playing_song.decoder->info.readpos;
streambuffer_fill = 0;
+ streambuffer_pos = 0;
streamer_unlock ();
codec_lock ();
codecleft = 0;
@@ -338,9 +342,23 @@ streamer_thread (uintptr_t ctx) {
}
sz = min (minsize, sz);
assert ((sz&3) == 0);
- int bytesread = streamer_read_async (&streambuffer[streambuffer_fill], sz);
- //printf ("req=%d, got=%d\n", sz, bytesread);
- streambuffer_fill += bytesread;
+
+ int writepos = (streambuffer_pos + streambuffer_fill) & STREAM_BUFFER_MASK;
+ int part1 = STREAM_BUFFER_SIZE-writepos;
+ part1 = min (part1, sz);
+ if (part1 > 0) {
+ streamer_unlock ();
+ int bytesread = streamer_read_async (streambuffer + writepos, part1);
+ streamer_lock ();
+ streambuffer_fill += bytesread;
+ }
+ sz -= part1;
+ if (sz > 0) {
+ streamer_unlock ();
+ int bytesread = streamer_read_async (streambuffer, sz);
+ streamer_lock ();
+ streambuffer_fill += bytesread;
+ }
}
streamer_unlock ();
struct timeval tm2;
@@ -390,6 +408,7 @@ void
streamer_reset (int full) { // must be called when current song changes by external reasons
codecleft = 0;
if (full) {
+ streambuffer_pos = 0;
streambuffer_fill = 0;
}
src_reset (src);
@@ -644,19 +663,6 @@ streamer_read_async (char *bytes, int size) {
nbytes = size;
int genbytes = srcdata.output_frames_gen * 4;
bytesread = min(size, genbytes);
-#if 0
- int i;
- for (i = 0; i < bytesread/2; i++) {
- float sample = g_srcbuffer[i];
- if (sample > 1) {
- sample = 1;
- }
- if (sample < -1) {
- sample = -1;
- }
- ((int16_t*)bytes)[i] = (int16_t)ftoi (sample*32767.f);
- }
-#endif
float32_to_int16 ((float*)g_srcbuffer, (int16_t*)bytes, bytesread>>1);
// calculate how many unused input samples left
codecleft = nsamples - srcdata.input_frames_used;
@@ -703,12 +709,24 @@ streamer_read (char *bytes, int size) {
streamer_lock ();
int sz = min (size, streambuffer_fill);
if (sz) {
- memcpy (bytes, streambuffer, sz);
- if (sz < streambuffer_fill) {
- // shift buffer
- memmove (streambuffer, &streambuffer[sz], streambuffer_fill-sz);
- }
- streambuffer_fill -= sz;
+ int cp = sz;
+ int readpos = streambuffer_pos & STREAM_BUFFER_MASK;
+ int part1 = STREAM_BUFFER_SIZE-readpos;
+ part1 = min (part1, cp);
+ if (part1 > 0) {
+ memcpy (bytes, streambuffer+readpos, part1);
+ streambuffer_pos += part1;
+ streambuffer_fill -= part1;
+ cp -= part1;
+ bytes += part1;
+ }
+ if (cp > 0) {
+ memcpy (bytes, streambuffer, cp);
+ streambuffer_pos += cp;
+ streambuffer_fill -= cp;
+ bytes += cp;
+ }
+ streambuffer_pos &= STREAM_BUFFER_MASK;
playpos += (float)sz/p_get_rate ()/4.f;
str_playing_song.playtime += (float)sz/p_get_rate ()/4.f;
if (playlist_current_ptr) {