shithub: dumb

Download patch

ref: b6c4ec4579a2f9bce76ae66ac09812947fa12896
parent: e41744273f75f23a5dc9d1d705bb517fff51b7b1
author: dmitrykos <dmitrykos@neutroncode.com>
date: Thu Feb 4 12:58:44 EST 2016

* Reverted duh_get_tag_iterator_size(), duh_get_tag_iterator_get() API which allowed easy iteration over existing tags.
* New duh_render_float() API to render data to float and double types (it has modified behavior in comparison with duh_render() which allows to avoid buffer allocation on every subsequent call).
* Deprecated duh_render() in favor of duh_render_int() API.
* Added ARM NEON specific defines to allow NEON optimizations on non-Apple platforms as well (for example: Android, BlackBerry BB10/PlayBook, Tizen).

--- a/dumb/include/dumb.h
+++ b/dumb/include/dumb.h
@@ -228,6 +228,8 @@
 long duh_get_length(DUH *duh);
 
 const char *duh_get_tag(DUH *duh, const char *key);
+int duh_get_tag_iterator_size(DUH *duh);
+int duh_get_tag_iterator_get(DUH *duh, const char **key, const char **tag, int i);
 
 /* Signal Rendering Functions */
 
@@ -317,14 +319,40 @@
 
 /* DUH Rendering Functions */
 
-long duh_render(
+/* For packed integers: 8, 16, 24-bit wide. 
+ * Intermediary buffer sig_samples must be freed with destroy_sample_buffer()
+ * in the end of the rendering loop.
+ */
+long duh_render_int(
 	DUH_SIGRENDERER *sigrenderer,
+	sample_t ***sig_samples,
+	long *sig_samples_size,
 	int bits, int unsign,
 	float volume, float delta,
 	long size, void *sptr
 );
 
+/* For floats: 32, 64-bit wide.
+ * Intermediary buffer sig_samples must be freed with destroy_sample_buffer()
+ * in the end of the rendering loop.
+ */
+long duh_render_float(
+	DUH_SIGRENDERER *sigrenderer,
+	sample_t ***sig_samples,
+	long *sig_samples_size,
+	int bits,
+	float volume, float delta,
+	long size, void *sptr
+);
+
 #ifdef DUMB_DECLARE_DEPRECATED
+
+long duh_render(
+	DUH_SIGRENDERER *sigrenderer,
+	int bits, int unsign,
+	float volume, float delta,
+	long size, void *sptr
+) DUMB_DEPRECATED;
 
 long duh_render_signal(
 	DUH_SIGRENDERER *sigrenderer,
--- a/dumb/src/core/duhtag.c
+++ b/dumb/src/core/duhtag.c
@@ -36,3 +36,23 @@
 
 	return NULL;
 }
+
+
+
+int duh_get_tag_iterator_size(DUH *duh)
+{
+	return (duh && duh->tag ? duh->n_tags : 0);
+}
+
+
+int duh_get_tag_iterator_get(DUH *duh, const char **key, const char **tag, int i)
+{
+	ASSERT(key);
+	ASSERT(value);
+	if (!duh || !duh->tag || i >= duh->n_tags) return -1;
+
+	*key = duh->tag[i][0];
+	*tag = duh->tag[i][1];
+
+	return 0;
+}
--- a/dumb/src/core/rendduh.c
+++ b/dumb/src/core/rendduh.c
@@ -70,8 +70,23 @@
 
 #endif
 
+#define CONVERT24(src, pos) {                         \
+	signed int f = src;			                      \
+	f = MID(-8388608, f, 8388607);				      \
+	((unsigned char*)sptr)[pos  ] = (f)       & 0xFF; \
+	((unsigned char*)sptr)[pos+1] = (f >> 8)  & 0xFF; \
+	((unsigned char*)sptr)[pos+2] = (f >> 16) & 0xFF; \
+}
 
+#define CONVERT32F(src, pos) {                                     \
+	((float*)sptr)[pos] = (float)((signed int)src) * (1.0f/(float)(0xffffff/2+1)); \
+}
 
+#define CONVERT64F(src, pos) {                                     \
+	((double*)sptr)[pos] = (double)((signed int)src) * (1.0/(double)(0xffffff/2+1)); \
+}
+
+
 /* DEPRECATED */
 DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos)
 {
@@ -79,7 +94,7 @@
 }
 
 
-
+/* DEPRECATED */
 long duh_render(
 	DUH_SIGRENDERER *sigrenderer,
 	int bits, int unsign,
@@ -135,6 +150,138 @@
 	return size;
 }
 
+
+long duh_render_int(
+	DUH_SIGRENDERER *sigrenderer,
+	sample_t ***sig_samples,
+	long *sig_samples_size,
+	int bits, int unsign,
+	float volume, float delta,
+	long size, void *sptr
+)
+{
+	long n;
+
+	sample_t **sampptr;
+
+	int n_channels;
+
+	ASSERT(bits == 8 || bits == 16 || bits == 24);
+	ASSERT(sptr);
+	ASSERT(sig_samples);
+	ASSERT(sig_samples_size);
+
+	if (!sigrenderer)
+		return 0;
+
+	n_channels = duh_sigrenderer_get_n_channels(sigrenderer);
+
+	ASSERT(n_channels > 0);
+	/* This restriction will be removed when need be. At the moment, tightly
+	 * optimised loops exist for exactly one or two channels.
+	 */
+	ASSERT(n_channels <= 2);
+
+	if ((*sig_samples == NULL) || (*sig_samples_size != size))
+	{
+		destroy_sample_buffer(*sig_samples);
+		*sig_samples = allocate_sample_buffer(n_channels, size);
+		*sig_samples_size = size;
+	}
+	sampptr = *sig_samples;
+
+	if (!sampptr)
+		return 0;
+
+	dumb_silence(sampptr[0], n_channels * size);
+
+	size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr);
+
+	if (bits == 24) {
+		long i = 0;
+		ASSERT(unsign == 0);
+		
+		for (n = 0; n < size * n_channels; n++, i += 3) {
+			CONVERT24(sampptr[0][n], i);
+		}
+	} else
+	if (bits == 16) {
+		int signconv = unsign ? 0x8000 : 0x0000;
+
+		for (n = 0; n < size * n_channels; n++) {
+			CONVERT16(sampptr[0][n], n, signconv);
+		}
+	} else {
+		char signconv = unsign ? 0x80 : 0x00;
+
+		for (n = 0; n < size * n_channels; n++) {
+			CONVERT8(sampptr[0][n], n, signconv);
+		}
+	}
+
+	return size;
+}
+
+
+long duh_render_float(
+	DUH_SIGRENDERER *sigrenderer,
+	sample_t ***sig_samples,
+	long *sig_samples_size,
+	int bits,
+	float volume, float delta,
+	long size, void *sptr
+)
+{
+	long n;
+
+	sample_t **sampptr;
+
+	int n_channels;
+
+	ASSERT(bits == 32 || bits == 64);
+	ASSERT(sptr);
+	ASSERT(sig_samples);
+	ASSERT(sig_samples_size);
+
+	if (!sigrenderer)
+		return 0;
+
+	n_channels = duh_sigrenderer_get_n_channels(sigrenderer);
+
+	ASSERT(n_channels > 0);
+	/* This restriction will be removed when need be. At the moment, tightly
+	 * optimised loops exist for exactly one or two channels.
+	 */
+	ASSERT(n_channels <= 2);
+
+	if ((*sig_samples == NULL) || (*sig_samples_size != size))
+	{
+		destroy_sample_buffer(*sig_samples);
+		*sig_samples = allocate_sample_buffer(n_channels, size);
+		*sig_samples_size = size;
+	}
+	sampptr = *sig_samples;
+
+	if (!sampptr)
+		return 0;
+
+	dumb_silence(sampptr[0], n_channels * size);
+
+	size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr);
+
+	if (bits == 64) {
+		for (n = 0; n < size * n_channels; n++) {
+			CONVERT64F(sampptr[0][n], n);
+		}
+	} else
+	if (bits == 32) {
+		for (n = 0; n < size * n_channels; n++) {
+			CONVERT32F(sampptr[0][n], n);
+		}
+	} 
+
+	return size;
+}
 
 
 /* DEPRECATED */
--- a/dumb/src/helpers/resampler.c
+++ b/dumb/src/helpers/resampler.c
@@ -11,6 +11,8 @@
 #if TARGET_CPU_ARM || TARGET_CPU_ARM64
 #define RESAMPLER_NEON
 #endif
+#elif (defined(__arm__) && defined(__ARM_NEON__))
+#define RESAMPLER_NEON
 #endif
 #ifdef RESAMPLER_NEON
 #include <arm_neon.h>