summaryrefslogtreecommitdiff
path: root/streamer.c
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-07-08 21:30:31 +0200
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-07-08 22:50:46 +0200
commit425f2d8d2b252e027593808a8e297193e2c9f7de (patch)
treee848ed02ac5f68839124ffb4144dbfad31bd4be6 /streamer.c
parentbb6da46236137f12be28147f93ea9654c5ccc125 (diff)
[WIP] seamless playback
Diffstat (limited to 'streamer.c')
-rw-r--r--streamer.c156
1 files changed, 89 insertions, 67 deletions
diff --git a/streamer.c b/streamer.c
index 1c72775f..7023c5a7 100644
--- a/streamer.c
+++ b/streamer.c
@@ -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;
}