diff options
author | Alexey Yakovenko <wakeroid@gmail.com> | 2009-07-08 21:30:31 +0200 |
---|---|---|
committer | Alexey Yakovenko <wakeroid@gmail.com> | 2009-07-08 22:50:46 +0200 |
commit | 425f2d8d2b252e027593808a8e297193e2c9f7de (patch) | |
tree | e848ed02ac5f68839124ffb4144dbfad31bd4be6 /streamer.c | |
parent | bb6da46236137f12be28147f93ea9654c5ccc125 (diff) |
[WIP] seamless playback
Diffstat (limited to 'streamer.c')
-rw-r--r-- | streamer.c | 156 |
1 files changed, 89 insertions, 67 deletions
@@ -10,9 +10,9 @@ extern int sdl_player_freq; // hack! static SRC_STATE *src; static SRC_DATA srcdata; static int codecleft; -static char g_readbuffer[20000]; // hack! -static float g_fbuffer[20000]; // hack! -static float g_srcbuffer[20000]; // hack! +static char g_readbuffer[200000]; // hack! +static float g_fbuffer[200000]; // hack! +static float g_srcbuffer[200000]; // hack! int streamer_init (void) { @@ -33,80 +33,102 @@ streamer_free (void) { } } +void +streamer_reset (void) { // must be called when current song changes by external reasons + codecleft = 0; + src_reset (src); +} + // returns number of bytes been read int streamer_read (char *bytes, int size) { - codec_t *codec = playlist_current.codec; - int bytesread = 0; - if (!codec) { - return 0; - } - // read and do SRC - if (codec->info.samplesPerSecond == sdl_player_freq) { - int i; - if (codec->info.channels == 2) { - codec_lock (); - bytesread = codec->read (bytes, size); + int initsize = size; + for (;;) { + int bytesread = 0; + codec_lock (); + codec_t *codec = playlist_current.codec; + if (!codec) { codec_unlock (); + break; } - else { - codec_lock (); - bytesread = codec->read (g_readbuffer, size/2); - for (i = 0; i < size/4; i++) { - int16_t sample = (int16_t)(((int32_t)(((int16_t*)g_readbuffer)[i]))); - ((int16_t*)bytes)[i*2+0] = sample; - ((int16_t*)bytes)[i*2+1] = sample; + int nchannels = codec->info.channels; + int samplerate = codec->info.samplesPerSecond; + // read and do SRC + if (codec->info.samplesPerSecond == sdl_player_freq) { + int i; + if (codec->info.channels == 2) { + bytesread = codec->read (bytes, size); + codec_unlock (); } - bytesread *= 2; - codec_unlock (); - } - } - else { - int nsamples = size/4; - // convert to codec samplerate - // add 5 extra samples for SRC - nsamples = nsamples * codec->info.samplesPerSecond / sdl_player_freq + 5; - // read data at source samplerate (with some room for SRC) - codec_lock (); - int nbytes = (nsamples - codecleft) * 2 * codec->info.channels; - bytesread = codec->read (g_readbuffer, nbytes); - // recalculate nsamples according to how many bytes we've got - nsamples -= (nbytes - bytesread) / (2 * codec->info.channels); - // convert to float, and apply soft volume - int i; - float *fbuffer = g_fbuffer + codecleft*2; - if (codec->info.channels == 2) { // convert mono to stereo - for (i = 0; i < (nsamples - codecleft) * 2; i++) { - fbuffer[i] = ((int16_t *)g_readbuffer)[i]/32767.f; + else { + bytesread = codec->read (g_readbuffer, size/2); + codec_unlock (); + for (i = 0; i < size/4; i++) { + int16_t sample = (int16_t)(((int32_t)(((int16_t*)g_readbuffer)[i]))); + ((int16_t*)bytes)[i*2+0] = sample; + ((int16_t*)bytes)[i*2+1] = sample; + } + bytesread *= 2; } } - else if (codec->info.channels == 1) { - for (i = 0; i < (nsamples - codecleft); i++) { - fbuffer[i*2+0] = ((int16_t *)g_readbuffer)[i]; - fbuffer[i*2+1] = fbuffer[i*2+0]; + else { + int nsamples = size/4; + // convert to codec samplerate + nsamples = nsamples * samplerate / sdl_player_freq * 2 ; + // read data at source samplerate (with some room for SRC) + int nbytes = (nsamples - codecleft) * 2 * nchannels; + bytesread = codec->read (g_readbuffer, nbytes); + codec_unlock (); + // recalculate nsamples according to how many bytes we've got + nsamples = bytesread / (2 * nchannels) + codecleft; + // convert to float + int i; + float *fbuffer = g_fbuffer + codecleft*2; + if (nchannels == 2) { + for (i = 0; i < (nsamples - codecleft) * 2; i++) { + fbuffer[i] = ((int16_t *)g_readbuffer)[i]/32767.f; + } + } + else if (nchannels == 1) { // convert mono to stereo + for (i = 0; i < (nsamples - codecleft); i++) { + fbuffer[i*2+0] = ((int16_t *)g_readbuffer)[i]/32767.f; + fbuffer[i*2+1] = fbuffer[i*2+0]; + } + } + // convert samplerate + srcdata.data_in = g_fbuffer; + srcdata.data_out = g_srcbuffer; + srcdata.input_frames = nsamples; + srcdata.output_frames = size/4; + srcdata.src_ratio = (double)sdl_player_freq/samplerate; + srcdata.end_of_input = 0; +// src_set_ratio (src, srcdata.src_ratio); + src_process (src, &srcdata); + //printf ("processed %d/%d samples (input=%d)\n", srcdata.output_frames_gen, srcdata.output_frames, srcdata.input_frames); + // convert back to s16 format + nbytes = size; + int genbytes = srcdata.output_frames_gen * 4; + bytesread = min(size, genbytes); + for (i = 0; i < bytesread/2; i++) { + ((int16_t*)bytes)[i] = (int16_t)(g_srcbuffer[i]*32767.f); } + // calculate how many unused input samples left + codecleft = nsamples - srcdata.input_frames_used; + // copy spare samples for next update + memmove (g_fbuffer, &g_fbuffer[srcdata.input_frames_used*2], codecleft * 8); } - // convert samplerate - srcdata.data_in = g_fbuffer; - srcdata.data_out = g_srcbuffer; - srcdata.input_frames = nsamples; - srcdata.output_frames = size/4; - srcdata.src_ratio = (double)sdl_player_freq/codec->info.samplesPerSecond; - srcdata.end_of_input = 0; - src_process (src, &srcdata); - // convert back to s16 format - nbytes = size; - int genbytes = srcdata.output_frames_gen * 4; - bytesread = min(size, genbytes); - - for (i = 0; i < bytesread/2; i++) { - ((int16_t*)bytes)[i] = (int16_t)(g_srcbuffer[i]*32767.f); + bytes += bytesread; + size -= bytesread; + if (size == 0) { + return initsize; + } + else { + //printf ("eof (size=%d)\n", size); + // that means EOF + if (ps_nextsong () < 0) { + break; + } } - // calculate how many unused input samples left - codecleft = nsamples - srcdata.input_frames_used; - // copy spare samples for next update - memmove (fbuffer, &fbuffer[srcdata.input_frames_used*2], codecleft * 8); - codec_unlock (); } - return bytesread; + return initsize - size; } |