summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdkdrawing.c10
-rw-r--r--gtkplaylist.c1
-rw-r--r--playlist.c12
-rw-r--r--playlist.h5
-rw-r--r--plugins/mpgmad/mpgmad.c15
-rw-r--r--streamer.c123
6 files changed, 97 insertions, 69 deletions
diff --git a/gdkdrawing.c b/gdkdrawing.c
index a096dc0e..621ee92e 100644
--- a/gdkdrawing.c
+++ b/gdkdrawing.c
@@ -41,11 +41,11 @@ draw_begin (uintptr_t canvas) {
void
draw_end (void) {
- if (pango_ready) {
- g_object_unref (pangolayout);
- g_object_unref (pangoctx);
- pango_ready = 0;
- }
+// if (pango_ready) {
+// g_object_unref (pangolayout);
+// g_object_unref (pangoctx);
+// pango_ready = 0;
+// }
drawable = NULL;
if (gc) {
g_object_unref (gc);
diff --git a/gtkplaylist.c b/gtkplaylist.c
index 54e6b36f..7307462a 100644
--- a/gtkplaylist.c
+++ b/gtkplaylist.c
@@ -1378,6 +1378,7 @@ gtkpl_playsong (gtkplaylist_t *ps) {
streamer_set_nextsong (ps->row, 1);
}
else {
+ p_stop ();
streamer_set_nextsong (0, 1);
}
}
diff --git a/playlist.c b/playlist.c
index 0136caf0..bc046b78 100644
--- a/playlist.c
+++ b/playlist.c
@@ -843,18 +843,6 @@ pl_randomsong (void) {
}
void
-pl_start_current (void) {
- codec_lock ();
- playItem_t *it = playlist_current_ptr;
- if (it && it->decoder) {
- // don't do anything on fail, streamer will take care
- it->decoder->free ();
- it->decoder->init (DB_PLAYITEM (it));
- }
- codec_unlock ();
-}
-
-void
pl_add_meta (playItem_t *it, const char *key, const char *value) {
// check if it's already set
metaInfo_t *m = it->meta;
diff --git a/playlist.h b/playlist.h
index e27b0df3..1c2038b9 100644
--- a/playlist.h
+++ b/playlist.h
@@ -124,11 +124,6 @@ pl_prevsong (void);
int
pl_randomsong (void);
-// starts current playlist item from position 0
-// only if the item is still in playlist
-void
-pl_start_current (void);
-
void
pl_add_meta (playItem_t *it, const char *key, const char *value);
diff --git a/plugins/mpgmad/mpgmad.c b/plugins/mpgmad/mpgmad.c
index 70de0e56..99279faf 100644
--- a/plugins/mpgmad/mpgmad.c
+++ b/plugins/mpgmad/mpgmad.c
@@ -22,8 +22,8 @@
#include <stdlib.h>
#include "../../deadbeef.h"
-//#define trace(...) { fprintf(stderr, __VA_ARGS__); }
-#define trace(fmt,...)
+#define trace(...) { fprintf(stderr, __VA_ARGS__); }
+//#define trace(fmt,...)
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
@@ -482,13 +482,7 @@ cmp3_init (DB_playItem_t *it) {
if (skip > 0) {
fseek(buffer.file, skip, SEEK_SET);
}
- buffer.remaining = 0;
- //buffer.output = NULL;
- buffer.readsize = 0;
- buffer.cachefill = 0;
- buffer.cachepos = 0;
plugin.info.readpos = 0;
-
cmp3_scan_stream (&buffer, -1); // scan entire stream, calc duration
if (it->endsample > 0) {
buffer.startsample = it->startsample;
@@ -505,7 +499,7 @@ cmp3_init (DB_playItem_t *it) {
fseek (buffer.file, buffer.startoffset, SEEK_SET);
}
if (buffer.samplerate == 0) {
- //fprintf (stderr, "bad mpeg file: %f\n", it->fname);
+ trace ("bad mpeg file: %f\n", it->fname);
fclose (buffer.file);
return -1;
}
@@ -666,7 +660,8 @@ cmp3_decode (void) {
buffer.readsize -= sizeof (mad_fixed_t);
if (MAD_NCHANNELS(&frame.header) == 2) {
if (buffer.cachefill >= CACHE_SIZE - sizeof (mad_fixed_t)) {
- trace ("readsize=%d, pcm.length=%d(%d), cachefill=%d, cachepos=%d(%d)\n", buffer.readsize, synth.pcm.length, i, buffer.cachefill, buffer.cachepos, cachepos);
+ trace ("mpgmad: readsize=%d, pcm.length=%d(%d), cachefill=%d, cachepos=%d(%d)\n", buffer.readsize, synth.pcm.length, i, buffer.cachefill, buffer.cachepos, cachepos);
+ return 0;
}
assert (buffer.cachefill < CACHE_SIZE - sizeof (mad_fixed_t));
memcpy (buffer.cache+cachepos, &synth.pcm.samples[1][i], sizeof (mad_fixed_t));
diff --git a/streamer.c b/streamer.c
index 5e0df775..618e2ddb 100644
--- a/streamer.c
+++ b/streamer.c
@@ -40,12 +40,20 @@ static intptr_t streamer_tid;
static SRC_STATE *src;
static SRC_DATA srcdata;
static int codecleft;
-static char g_readbuffer[200000]; // hack!
-static float g_fbuffer[200000]; // hack!
-static float g_srcbuffer[200000]; // hack!
+
+// that's buffer for resampling.
+// our worst case is 192KHz downsampling to 22050Hz with 2048 sample output buffer
+#define INPUT_BUFFER_SIZE (2048*192000/22050*8)
+static char g_readbuffer[INPUT_BUFFER_SIZE];
+// fbuffer contains readbuffer converted to floating point, to pass to SRC
+static float g_fbuffer[INPUT_BUFFER_SIZE];
+// output SRC buffer - can't really exceed INPUT_BUFFER_SIZE
+#define SRC_BUFFER_SIZE (INPUT_BUFFER_SIZE*2)
+static float g_srcbuffer[SRC_BUFFER_SIZE];
static int streaming_terminate;
-#define STREAM_BUFFER_SIZE (200000)
+// buffer up to 3 seconds at 44100Hz stereo
+#define STREAM_BUFFER_SIZE (44100*3*4)
static int streambuffer_fill;
static int bytes_until_next_song = 0;
static char streambuffer[STREAM_BUFFER_SIZE];
@@ -64,8 +72,8 @@ playItem_t str_streaming_song;
static playItem_t *orig_playing_song;
static playItem_t *orig_streaming_song;
-//#define trace(...) { fprintf(stderr, __VA_ARGS__); }
-#define trace(fmt,...)
+#define trace(...) { fprintf(stderr, __VA_ARGS__); }
+//#define trace(fmt,...)
// playlist must call that whenever item was removed
void
@@ -462,6 +470,56 @@ apply_replay_gain_float32 (playItem_t *it, char *bytes, int size) {
}
}
+static void
+mono_int16_to_stereo_int16 (int16_t *in, uint16_t *out, int nsamples) {
+ while (nsamples > 0) {
+ int16_t sample = *in;
+ *out++ = sample;
+ *out++ = sample;
+ in++;
+ nsamples--;
+ }
+}
+
+static void
+int16_to_float32 (int16_t *in, float *out, int nsamples) {
+ while (nsamples > 0) {
+ *out++ = (*in++)/(float)0x7fff;
+ nsamples--;
+ }
+}
+
+static void
+mono_int16_to_stereo_float32 (int16_t *in, float *out, int nsamples) {
+ while (nsamples > 0) {
+ float sample = (*in++)/(float)0x7fff;
+ *out++ = sample;
+ *out++ = sample;
+ nsamples--;
+ }
+}
+
+static void
+mono_float32_to_stereo_float32 (float *in, float *out, int nsamples) {
+ while (nsamples > 0) {
+ float sample = *in++;
+ *out++ = sample;
+ *out++ = sample;
+ nsamples--;
+ }
+}
+
+static void
+float32_to_int16 (float *in, int16_t *out, int nsamples) {
+ fpu_control ctl;
+ fpu_setround (&ctl);
+ while (nsamples > 0) {
+ *out++ = (int16_t)ftoi ((*in++)*0x7fff);
+ nsamples--;
+ }
+ fpu_restore (ctl);
+}
+
// returns number of bytes been read
static int
streamer_read_async (char *bytes, int size) {
@@ -478,8 +536,8 @@ streamer_read_async (char *bytes, int size) {
if (decoder->info.samplerate != -1) {
int nchannels = decoder->info.channels;
int samplerate = decoder->info.samplerate;
- // read and do SRC
if (decoder->info.samplerate == p_get_rate ()) {
+ // samplerate match
int i;
if (decoder->info.channels == 2) {
bytesread = decoder->read_int16 (bytes, size);
@@ -487,25 +545,17 @@ streamer_read_async (char *bytes, int size) {
apply_replay_gain_int16 (&str_streaming_song, bytes, size);
}
else {
- bytesread = decoder->read_int16 (g_readbuffer, size/2);
+ bytesread = decoder->read_int16 (g_readbuffer, size>>1);
codec_unlock ();
- apply_replay_gain_int16 (&str_streaming_song, 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;
- }
+ apply_replay_gain_int16 (&str_streaming_song, g_readbuffer, size>>1);
+ mono_int16_to_stereo_int16 ((int16_t*)g_readbuffer, (int16_t*)bytes, size>>1);
bytesread *= 2;
}
}
- else {
+ else if (src_is_valid_ratio ((double)p_get_rate ()/samplerate)) {
+ // read and do SRC
int nsamples = size/4;
- // convert to codec samplerate
nsamples = nsamples * samplerate / p_get_rate () * 2;
- if (!src_is_valid_ratio ((double)p_get_rate ()/samplerate)) {
- printf ("invalid ratio! %d / %d = %f", p_get_rate (), samplerate, (float)p_get_rate ()/samplerate);
- }
- assert (src_is_valid_ratio ((double)p_get_rate ()/samplerate));
// read data at source samplerate (with some room for SRC)
int nbytes = (nsamples - codecleft) * 2 * nchannels;
int samplesize = 2;
@@ -513,11 +563,11 @@ streamer_read_async (char *bytes, int size) {
nbytes = 0;
}
else {
-// if (nbytes & 3) {
-// printf ("FATAL: nbytes=%d, nsamples=%d, codecleft=%d, nchannels=%d, ratio=%f\n", nbytes, nsamples, codecleft, nchannels, (float)p_get_rate ()/samplerate);
-// assert ((nbytes & 3) == 0);
-// }
if (!decoder->read_float32) {
+ if (nbytes > INPUT_BUFFER_SIZE) {
+ trace ("input buffer overflow\n");
+ nbytes = INPUT_BUFFER_SIZE;
+ }
bytesread = decoder->read_int16 (g_readbuffer, nbytes);
apply_replay_gain_int16 (&str_streaming_song, g_readbuffer, nbytes);
}
@@ -533,16 +583,13 @@ streamer_read_async (char *bytes, int size) {
nsamples = bytesread / (samplesize * nchannels) + codecleft;
// convert to float
float *fbuffer = g_fbuffer + codecleft*2;
+ int n = nsamples - codecleft;
if (nchannels == 2) {
- for (i = 0; i < (nsamples - codecleft) * 2; i++) {
- fbuffer[i] = ((int16_t *)g_readbuffer)[i]/32767.f;
- }
+ n <<= 1;
+ int16_to_float32 ((int16_t*)g_readbuffer, fbuffer, n);
}
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];
- }
+ mono_int16_to_stereo_float32 ((int16_t*)g_readbuffer, fbuffer, n);
}
}
else {
@@ -553,10 +600,7 @@ streamer_read_async (char *bytes, int size) {
codec_unlock ();
apply_replay_gain_float32 (&str_streaming_song, g_readbuffer, nbytes*2);
nsamples = bytesread / (samplesize * nchannels) + codecleft;
- for (i = 0; i < (nsamples - codecleft); i++) {
- fbuffer[i*2+0] = ((float *)g_readbuffer)[i];
- fbuffer[i*2+1] = fbuffer[i*2+0];
- }
+ mono_float32_to_stereo_float32 ((float *)g_readbuffer, fbuffer, nsamples-codecleft);
}
else {
codec_lock ();
@@ -582,6 +626,7 @@ 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];
@@ -593,11 +638,16 @@ streamer_read_async (char *bytes, int size) {
}
((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;
// copy spare samples for next update
memmove (g_fbuffer, &g_fbuffer[srcdata.input_frames_used*2], codecleft * 8);
}
+ else {
+ fprintf (stderr, "invalid ratio! %d / %d = %f", p_get_rate (), samplerate, (float)p_get_rate ()/samplerate);
+ }
}
else {
codec_unlock ();
@@ -608,10 +658,9 @@ streamer_read_async (char *bytes, int size) {
return initsize;
}
else {
-// trace ("EOF, buns=%d\n", bytes_until_next_song);
// that means EOF
if (bytes_until_next_song < 0) {
-// trace ("finished streaming song, queueing next\n");
+ trace ("finished streaming song, queueing next\n");
bytes_until_next_song = streambuffer_fill;
pl_nextsong (0);
}