diff options
author | Alexey Yakovenko <wakeroid@gmail.com> | 2009-10-02 19:20:34 +0200 |
---|---|---|
committer | Alexey Yakovenko <wakeroid@gmail.com> | 2009-10-02 19:20:34 +0200 |
commit | 6cbf891c080008679dc344a5ed855af62b822fe8 (patch) | |
tree | b21cfccdc4d02403d325a6d4c612d69b4d991a61 /streamer.c | |
parent | 8d67c4ea1f4171227e5dfb1842cffcde1693dac0 (diff) |
converted streamer to use ringbuffer
that removes io/playback interlocking
also faster
Diffstat (limited to 'streamer.c')
-rw-r--r-- | streamer.c | 64 |
1 files changed, 41 insertions, 23 deletions
@@ -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) { |