diff options
-rw-r--r-- | cmp3.c | 5 | ||||
-rw-r--r-- | main.c | 13 | ||||
-rw-r--r-- | playlist.c | 3 | ||||
-rw-r--r-- | psdl.c | 6 | ||||
-rw-r--r-- | streamer.c | 94 | ||||
-rw-r--r-- | streamer.h | 6 |
6 files changed, 103 insertions, 24 deletions
@@ -62,6 +62,7 @@ cmp3_init (const char *fname, int track, float start, float end) { if (cmp3_get_stream_info2 () == -1) { return -1; } +// printf ("song %s samplerate %d\n", fname, cmp3.info.samplesPerSecond); fseek (buffer.file, 0, SEEK_SET); // cmp3_decode (); // this 1st run will read 1st frame, but will not decode anything except header @@ -158,7 +159,6 @@ cmp3_get_stream_info2 (void) { // layer info int layer = (hdr & (3<<17)) >> 17; -// printf ("layer = %xh\n", layer); // bitrate int brtable[16] = { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1 }; @@ -180,7 +180,8 @@ cmp3_get_stream_info2 (void) { int nchannels = (hdr & (0x3 << 6)) >> 6; nchannels = chantbl[nchannels]; - if (nframe == 0) { + if (nframe == 0 || cmp3.info.samplesPerSecond == -1) + { cmp3.info.bitsPerSample = 16; cmp3.info.channels = nchannels; cmp3.info.samplesPerSecond = samplerate; @@ -11,6 +11,7 @@ #include "messages.h" #include "gtkplaylist.h" #include "codec.h" +#include "streamer.h" GtkWidget *mainwin; @@ -18,8 +19,6 @@ int psdl_terminate = 0; void psdl_thread (uintptr_t ctx) { - codec_init_locking (); - psdl_init (); psdl_play (); while (!psdl_terminate) { uint32_t msg; @@ -84,14 +83,14 @@ psdl_thread (uintptr_t ctx) { gtkps_update_songinfo (); // handle message pump here } - psdl_free (); - codec_free_locking (); - ps_free (); } int main (int argc, char *argv[]) { messagepump_init (); + codec_init_locking (); + streamer_init (); + psdl_init (); thread_start (psdl_thread, 0); g_thread_init (NULL); @@ -111,5 +110,9 @@ main (int argc, char *argv[]) { gdk_threads_leave (); messagepump_free (); psdl_terminate = 1; + psdl_free (); + streamer_free (); + codec_free_locking (); + ps_free (); return 0; } @@ -404,7 +404,7 @@ ps_item_free (playItem_t *it) { void ps_set_current (playItem_t *it) { if (it) { - printf ("ps_set_current (%s)\n", it->displayname); +// printf ("ps_set_current (%s)\n", it->displayname); } if (it == playlist_current_ptr) { if (it && it->codec) { @@ -429,7 +429,6 @@ ps_set_current (playItem_t *it) { } if (playlist_current_ptr) { streamer_reset (); - printf ("streamer_reset\n"); } codec_unlock (); } @@ -12,13 +12,10 @@ int psdl_init (void) { SDL_AudioSpec obt; int formats[] = { AUDIO_S16, -1 }; - int freqs[] = { 22050, 48000, 44100, -1 }; + int freqs[] = { 44100, 48000, -1 }; const char *fmtnames[] = { "16 bit signed integer" }; int fmt, frq; int success = 0; - if (streamer_init () < 0) { - return -1; - } fprintf (stderr, "sdl_player_init\n"); for (fmt = 0; formats[fmt] != -1; fmt++) { for (frq = 0; freqs[frq] != -1; frq++) { @@ -50,7 +47,6 @@ psdl_init (void) { void psdl_free (void) { SDL_CloseAudio (); - streamer_free (); } int @@ -2,10 +2,13 @@ #include <string.h> #include <stdio.h> #include <assert.h> +#include <unistd.h> #include <samplerate.h> +#include "threading.h" #include "codec.h" #include "playlist.h" #include "common.h" +#include "streamer.h" extern int sdl_player_freq; // hack! static SRC_STATE *src; @@ -14,24 +17,60 @@ static int codecleft; static char g_readbuffer[200000]; // hack! static float g_fbuffer[200000]; // hack! static float g_srcbuffer[200000]; // hack! +static int streaming_terminate; + +#define STREAM_BUFFER_SIZE 200000 +static int streambuffer_fill; +static char streambuffer[STREAM_BUFFER_SIZE+1000]; +static uintptr_t mutex; + +static int +streamer_read_async (char *bytes, int size); + +void +streamer_thread (uintptr_t ctx) { + codecleft = 0; + + while (!streaming_terminate) { + streamer_lock (); + if (streambuffer_fill < STREAM_BUFFER_SIZE) { + int sz = STREAM_BUFFER_SIZE - streambuffer_fill; + int minsize = 500; + if (streambuffer_fill < 16384) { + minsize = 16384; + } + sz = min (minsize, sz); +// printf ("reading %d\n", sz); + int bytesread = streamer_read_async (&streambuffer[streambuffer_fill], sz); + streambuffer_fill += bytesread; + } + streamer_unlock (); + usleep (3000); + //printf ("fill: %d \r", streambuffer_fill); + } + + if (src) { + src_delete (src); + src = NULL; + } +} int streamer_init (void) { -//// src = src_new (SRC_LINEAR, 2, NULL); - src = src_new (SRC_SINC_BEST_QUALITY, 2, NULL); + mutex = mutex_create (); +// src = src_new (SRC_SINC_BEST_QUALITY, 2, NULL); + src = src_new (SRC_LINEAR, 2, NULL); if (!src) { return -1; } - codecleft = 0; + thread_start (streamer_thread, 0); return 0; } void streamer_free (void) { - if (src) { - src_delete (src); - src = NULL; - } + streaming_terminate = 1; + mutex_free (mutex); } void @@ -41,8 +80,8 @@ streamer_reset (void) { // must be called when current song changes by external } // returns number of bytes been read -int -streamer_read (char *bytes, int size) { +static int +streamer_read_async (char *bytes, int size) { int initsize = size; for (;;) { int bytesread = 0; @@ -76,10 +115,19 @@ streamer_read (char *bytes, int size) { int nsamples = size/4; // convert to codec samplerate nsamples = nsamples * samplerate / sdl_player_freq * 2; + if (!src_is_valid_ratio ((double)sdl_player_freq/samplerate)) { + printf ("invalid ratio! %d / %d = %f", sdl_player_freq, samplerate, (float)sdl_player_freq/samplerate); + } assert (src_is_valid_ratio ((double)sdl_player_freq/samplerate)); // read data at source samplerate (with some room for SRC) int nbytes = (nsamples - codecleft) * 2 * nchannels; - bytesread = codec->read (g_readbuffer, nbytes); + if (nbytes < 0) { + nbytes = 0; + } + else { + //printf ("reading %d bytes from mp3\n", nbytes); + bytesread = codec->read (g_readbuffer, nbytes); + } codec_unlock (); // recalculate nsamples according to how many bytes we've got nsamples = bytesread / (2 * nchannels) + codecleft; @@ -141,3 +189,29 @@ streamer_read (char *bytes, int size) { } return initsize - size; } + +void +streamer_lock (void) { + mutex_lock (mutex); +} + +void +streamer_unlock (void) { + mutex_unlock (mutex); +} + +int +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; + } + streamer_unlock (); + return sz; +} @@ -13,4 +13,10 @@ streamer_read (char *bytes, int size); void streamer_reset (void); +void +streamer_lock (void); + +void +streamer_unlock (void); + #endif // __STREAMER_H |