summaryrefslogtreecommitdiff
path: root/libs/audiographer/private
diff options
context:
space:
mode:
authorSakari Bergen <sakari.bergen@beatwaves.net>2010-03-15 19:11:48 +0000
committerSakari Bergen <sakari.bergen@beatwaves.net>2010-03-15 19:11:48 +0000
commit830911f6f9451d83a58043b3f9084d3caa164b7b (patch)
treef4ca4e3d86b51d66e7cecfb6b370cc4eb553e2d7 /libs/audiographer/private
parent44f4b84551d36ef4103d09452768f5ba53e0002c (diff)
Fix export, which has been broken since the boost::signals2 changes. Also update Audiographer, bacause of its incomplete sndfile handling. Audiographer is equal to revision 74
git-svn-id: svn://localhost/ardour2/branches/3.0@6760 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/audiographer/private')
-rw-r--r--libs/audiographer/private/gdither/gdither.cc474
-rw-r--r--libs/audiographer/private/gdither/gdither.h92
-rw-r--r--libs/audiographer/private/gdither/gdither_types.h48
-rw-r--r--libs/audiographer/private/gdither/gdither_types_internal.h74
-rw-r--r--libs/audiographer/private/gdither/noise.h38
-rw-r--r--libs/audiographer/private/sndfile.hh399
6 files changed, 1125 insertions, 0 deletions
diff --git a/libs/audiographer/private/gdither/gdither.cc b/libs/audiographer/private/gdither/gdither.cc
new file mode 100644
index 0000000000..966da47b06
--- /dev/null
+++ b/libs/audiographer/private/gdither/gdither.cc
@@ -0,0 +1,474 @@
+/*
+ * Copyright (C) 2002 Steve Harris <steve@plugin.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "gdither_types_internal.h"
+#include "gdither.h"
+#include "noise.h"
+
+/* this monstrosity is necessary to get access to lrintf() and random().
+ whoever is writing the glibc headers <cmath> and <cstdlib> should be
+ hauled off to a programmer re-education camp. for the rest of
+ their natural lives. or longer. <paul@linuxaudiosystems.com>
+*/
+
+#define _ISOC9X_SOURCE 1
+#define _ISOC99_SOURCE 1
+#ifdef __cplusplus
+#include <cmath>
+#else
+#include <math.h>
+#endif
+
+#undef __USE_SVID
+#define __USE_SVID 1
+#ifdef __cplusplus
+#include <cstdlib>
+#else
+#include <stdlib.h>
+#endif
+
+#include <sys/types.h>
+
+/* Lipshitz's minimally audible FIR, only really works for 46kHz-ish signals */
+static const float shaped_bs[] = { 2.033f, -2.165f, 1.959f, -1.590f, 0.6149f };
+
+/* Some useful constants */
+#define MAX_U8 255
+#define MIN_U8 0
+#define SCALE_U8 128.0f
+
+#define MAX_S16 32767
+#define MIN_S16 -32768
+#define SCALE_S16 32768.0f
+
+#define MAX_S24 8388607
+#define MIN_S24 -8388608
+#define SCALE_S24 8388608.0f
+
+GDither gdither_new(GDitherType type, uint32_t channels,
+
+ GDitherSize bit_depth, int dither_depth)
+{
+ GDither s;
+
+ s = (GDither)calloc(1, sizeof(struct GDither_s));
+ s->type = type;
+ s->channels = channels;
+ s->bit_depth = (int)bit_depth;
+
+ if (dither_depth <= 0 || dither_depth > (int)bit_depth) {
+ dither_depth = (int)bit_depth;
+ }
+ s->dither_depth = dither_depth;
+
+ s->scale = (float)(1LL << (dither_depth - 1));
+ if (bit_depth == GDitherFloat || bit_depth == GDitherDouble) {
+ s->post_scale_fp = 1.0f / s->scale;
+ s->post_scale = 0;
+ } else {
+ s->post_scale_fp = 0.0f;
+ s->post_scale = 1 << ((int)bit_depth - dither_depth);
+ }
+
+ switch (bit_depth) {
+ case GDither8bit:
+ /* Unsigned 8 bit */
+ s->bias = 1.0f;
+ s->clamp_u = 255;
+ s->clamp_l = 0;
+ break;
+ case GDither16bit:
+ /* Signed 16 bit */
+ s->bias = 0.0f;
+ s->clamp_u = 32767;
+ s->clamp_l = -32768;
+ break;
+ case GDither32bit:
+ /* Signed 24 bit, in upper 24 bits of 32 bit word */
+ s->bias = 0.0f;
+ s->clamp_u = 8388607;
+ s->clamp_l = -8388608;
+ break;
+ case GDitherFloat:
+ /* normalised float */
+ s->bias = 0.0f;
+ s->clamp_u = lrintf(s->scale);
+ s->clamp_l = lrintf(-s->scale);
+ break;
+ case GDitherDouble:
+ /* normalised float */
+ s->bias = 0.0f;
+ s->clamp_u = lrintf(s->scale);
+ s->clamp_l = lrintf(-s->scale);
+ break;
+ case 23:
+ /* special performance test case */
+ s->scale = SCALE_S24;
+ s->post_scale = 256;
+ s->bias = 0.0f;
+ s->clamp_u = 8388607;
+ s->clamp_l = -8388608;
+ break;
+ default:
+ /* Not a bit depth we can handle */
+ free(s);
+
+ return NULL;
+ break;
+ }
+
+ switch (type) {
+ case GDitherNone:
+ case GDitherRect:
+ /* No state */
+ break;
+
+ case GDitherTri:
+ /* The last whitenoise sample */
+ s->tri_state = (float *) calloc(channels, sizeof(float));
+ break;
+
+ case GDitherShaped:
+ /* The error from the last few samples encoded */
+ s->shaped_state = (GDitherShapedState*)
+ calloc(channels, sizeof(GDitherShapedState));
+ break;
+ }
+
+ return s;
+}
+
+void gdither_free(GDither s)
+{
+ if (s) {
+ free(s->tri_state);
+ free(s->shaped_state);
+ free(s);
+ }
+}
+
+inline static void gdither_innner_loop(const GDitherType dt,
+ const uint32_t stride, const float bias, const float scale,
+
+ const uint32_t post_scale, const int bit_depth,
+ const uint32_t channel, const uint32_t length, float *ts,
+
+ GDitherShapedState *ss, float const *x, void *y, const int clamp_u,
+
+ const int clamp_l)
+{
+ uint32_t pos, i;
+ uint8_t *o8 = (uint8_t*) y;
+ int16_t *o16 = (int16_t*) y;
+ int32_t *o32 = (int32_t*) y;
+ float tmp, r, ideal;
+ int64_t clamped;
+
+ i = channel;
+ for (pos = 0; pos < length; pos++, i += stride) {
+ tmp = x[i] * scale + bias;
+
+ switch (dt) {
+ case GDitherNone:
+ break;
+ case GDitherRect:
+ tmp -= GDITHER_NOISE;
+ break;
+ case GDitherTri:
+ r = GDITHER_NOISE - 0.5f;
+ tmp -= r - ts[channel];
+ ts[channel] = r;
+ break;
+ case GDitherShaped:
+ /* Save raw value for error calculations */
+ ideal = tmp;
+
+ /* Run FIR and add white noise */
+ ss->buffer[ss->phase] = GDITHER_NOISE * 0.5f;
+ tmp += ss->buffer[ss->phase] * shaped_bs[0]
+ + ss->buffer[(ss->phase - 1) & GDITHER_SH_BUF_MASK]
+ * shaped_bs[1]
+ + ss->buffer[(ss->phase - 2) & GDITHER_SH_BUF_MASK]
+ * shaped_bs[2]
+ + ss->buffer[(ss->phase - 3) & GDITHER_SH_BUF_MASK]
+ * shaped_bs[3]
+ + ss->buffer[(ss->phase - 4) & GDITHER_SH_BUF_MASK]
+ * shaped_bs[4];
+
+ /* Roll buffer and store last error */
+ ss->phase = (ss->phase + 1) & GDITHER_SH_BUF_MASK;
+ ss->buffer[ss->phase] = (float)lrintf(tmp) - ideal;
+ break;
+ }
+
+ clamped = lrintf(tmp);
+ if (clamped > clamp_u) {
+ clamped = clamp_u;
+ } else if (clamped < clamp_l) {
+ clamped = clamp_l;
+ }
+
+ switch (bit_depth) {
+ case GDither8bit:
+ o8[i] = (u_int8_t) (clamped * post_scale);
+ break;
+ case GDither16bit:
+ o16[i] = (int16_t) (clamped * post_scale);
+ break;
+ case GDither32bit:
+ o32[i] = (int32_t) (clamped * post_scale);
+ break;
+ }
+ }
+}
+
+/* floating pint version of the inner loop function */
+inline static void gdither_innner_loop_fp(const GDitherType dt,
+ const uint32_t stride, const float bias, const float scale,
+
+ const float post_scale, const int bit_depth,
+ const uint32_t channel, const uint32_t length, float *ts,
+
+ GDitherShapedState *ss, float const *x, void *y, const int clamp_u,
+
+ const int clamp_l)
+{
+ uint32_t pos, i;
+ float *oflt = (float*) y;
+ double *odbl = (double*) y;
+ float tmp, r, ideal;
+ double clamped;
+
+ i = channel;
+ for (pos = 0; pos < length; pos++, i += stride) {
+ tmp = x[i] * scale + bias;
+
+ switch (dt) {
+ case GDitherNone:
+ break;
+ case GDitherRect:
+ tmp -= GDITHER_NOISE;
+ break;
+ case GDitherTri:
+ r = GDITHER_NOISE - 0.5f;
+ tmp -= r - ts[channel];
+ ts[channel] = r;
+ break;
+ case GDitherShaped:
+ /* Save raw value for error calculations */
+ ideal = tmp;
+
+ /* Run FIR and add white noise */
+ ss->buffer[ss->phase] = GDITHER_NOISE * 0.5f;
+ tmp += ss->buffer[ss->phase] * shaped_bs[0]
+ + ss->buffer[(ss->phase - 1) & GDITHER_SH_BUF_MASK]
+ * shaped_bs[1]
+ + ss->buffer[(ss->phase - 2) & GDITHER_SH_BUF_MASK]
+ * shaped_bs[2]
+ + ss->buffer[(ss->phase - 3) & GDITHER_SH_BUF_MASK]
+ * shaped_bs[3]
+ + ss->buffer[(ss->phase - 4) & GDITHER_SH_BUF_MASK]
+ * shaped_bs[4];
+
+ /* Roll buffer and store last error */
+ ss->phase = (ss->phase + 1) & GDITHER_SH_BUF_MASK;
+ ss->buffer[ss->phase] = (float)lrintf(tmp) - ideal;
+ break;
+ }
+
+ clamped = rintf(tmp);
+ if (clamped > clamp_u) {
+ clamped = clamp_u;
+ } else if (clamped < clamp_l) {
+ clamped = clamp_l;
+ }
+
+ switch (bit_depth) {
+ case GDitherFloat:
+ oflt[i] = (float) (clamped * post_scale);
+ break;
+ case GDitherDouble:
+ odbl[i] = (double) (clamped * post_scale);
+ break;
+ }
+ }
+}
+
+#define GDITHER_CONV_BLOCK 512
+
+void gdither_run(GDither s, uint32_t channel, uint32_t length,
+ double const *x, void *y)
+{
+ float conv[GDITHER_CONV_BLOCK];
+ uint32_t i, pos;
+ char *ycast = (char *)y;
+
+ int step;
+
+ switch (s->bit_depth) {
+ case GDither8bit:
+ step = 1;
+ break;
+ case GDither16bit:
+ step = 2;
+ break;
+ case GDither32bit:
+ case GDitherFloat:
+ step = 4;
+ break;
+ case GDitherDouble:
+ step = 8;
+ break;
+ default:
+ step = 0;
+ break;
+ }
+
+ pos = 0;
+ while (pos < length) {
+ for (i=0; (i + pos) < length && i < GDITHER_CONV_BLOCK; i++) {
+ conv[i] = x[pos + i];
+ }
+ gdither_runf(s, channel, i, conv, ycast + s->channels * step);
+ pos += i;
+ }
+}
+
+void gdither_runf(GDither s, uint32_t channel, uint32_t length,
+ float const *x, void *y)
+{
+ uint32_t pos, i;
+ float tmp;
+ int64_t clamped;
+ GDitherShapedState *ss = NULL;
+
+ if (!s || channel >= s->channels) {
+ return;
+ }
+
+ if (s->shaped_state) {
+ ss = s->shaped_state + channel;
+ }
+
+ if (s->type == GDitherNone && s->bit_depth == 23) {
+ int32_t *o32 = (int32_t*) y;
+
+ for (pos = 0; pos < length; pos++) {
+ i = channel + (pos * s->channels);
+ tmp = x[i] * 8388608.0f;
+
+ clamped = lrintf(tmp);
+ if (clamped > 8388607) {
+ clamped = 8388607;
+ } else if (clamped < -8388608) {
+ clamped = -8388608;
+ }
+
+ o32[i] = (int32_t) (clamped * 256);
+ }
+
+ return;
+ }
+
+ /* some common case handling code - looks a bit wierd, but it allows
+ * the compiler to optimise out the branches in the inner loop */
+ if (s->bit_depth == 8 && s->dither_depth == 8) {
+ switch (s->type) {
+ case GDitherNone:
+ gdither_innner_loop(GDitherNone, s->channels, 128.0f, SCALE_U8,
+ 1, 8, channel, length, NULL, NULL, x, y,
+ MAX_U8, MIN_U8);
+ break;
+ case GDitherRect:
+ gdither_innner_loop(GDitherRect, s->channels, 128.0f, SCALE_U8,
+ 1, 8, channel, length, NULL, NULL, x, y,
+ MAX_U8, MIN_U8);
+ break;
+ case GDitherTri:
+ gdither_innner_loop(GDitherTri, s->channels, 128.0f, SCALE_U8,
+ 1, 8, channel, length, s->tri_state,
+ NULL, x, y, MAX_U8, MIN_U8);
+ break;
+ case GDitherShaped:
+ gdither_innner_loop(GDitherShaped, s->channels, 128.0f, SCALE_U8,
+ 1, 8, channel, length, NULL,
+ ss, x, y, MAX_U8, MIN_U8);
+ break;
+ }
+ } else if (s->bit_depth == 16 && s->dither_depth == 16) {
+ switch (s->type) {
+ case GDitherNone:
+ gdither_innner_loop(GDitherNone, s->channels, 0.0f, SCALE_S16,
+ 1, 16, channel, length, NULL, NULL, x, y,
+ MAX_S16, MIN_S16);
+ break;
+ case GDitherRect:
+ gdither_innner_loop(GDitherRect, s->channels, 0.0f, SCALE_S16,
+ 1, 16, channel, length, NULL, NULL, x, y,
+ MAX_S16, MIN_S16);
+ break;
+ case GDitherTri:
+ gdither_innner_loop(GDitherTri, s->channels, 0.0f, SCALE_S16,
+ 1, 16, channel, length, s->tri_state,
+ NULL, x, y, MAX_S16, MIN_S16);
+ break;
+ case GDitherShaped:
+ gdither_innner_loop(GDitherShaped, s->channels, 0.0f,
+ SCALE_S16, 1, 16, channel, length, NULL,
+ ss, x, y, MAX_S16, MIN_S16);
+ break;
+ }
+ } else if (s->bit_depth == 32 && s->dither_depth == 24) {
+ switch (s->type) {
+ case GDitherNone:
+ gdither_innner_loop(GDitherNone, s->channels, 0.0f, SCALE_S24,
+ 256, 32, channel, length, NULL, NULL, x,
+ y, MAX_S24, MIN_S24);
+ break;
+ case GDitherRect:
+ gdither_innner_loop(GDitherRect, s->channels, 0.0f, SCALE_S24,
+ 256, 32, channel, length, NULL, NULL, x,
+ y, MAX_S24, MIN_S24);
+ break;
+ case GDitherTri:
+ gdither_innner_loop(GDitherTri, s->channels, 0.0f, SCALE_S24,
+ 256, 32, channel, length, s->tri_state,
+ NULL, x, y, MAX_S24, MIN_S24);
+ break;
+ case GDitherShaped:
+ gdither_innner_loop(GDitherShaped, s->channels, 0.0f, SCALE_S24,
+ 256, 32, channel, length,
+ NULL, ss, x, y, MAX_S24, MIN_S24);
+ break;
+ }
+ } else if (s->bit_depth == GDitherFloat || s->bit_depth == GDitherDouble) {
+ gdither_innner_loop_fp(s->type, s->channels, s->bias, s->scale,
+ s->post_scale_fp, s->bit_depth, channel, length,
+ s->tri_state, ss, x, y, s->clamp_u, s->clamp_l);
+ } else {
+ /* no special case handling, just process it from the struct */
+
+ gdither_innner_loop(s->type, s->channels, s->bias, s->scale,
+ s->post_scale, s->bit_depth, channel,
+ length, s->tri_state, ss, x, y, s->clamp_u,
+ s->clamp_l);
+ }
+}
+
+/* vi:set ts=8 sts=4 sw=4: */
diff --git a/libs/audiographer/private/gdither/gdither.h b/libs/audiographer/private/gdither/gdither.h
new file mode 100644
index 0000000000..d2b2657f32
--- /dev/null
+++ b/libs/audiographer/private/gdither/gdither.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2002 Steve Harris <steve@plugin.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef GDITHER_H
+#define GDITHER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "gdither_types.h"
+
+/* Create and initialise a state structure, takes a dither type, a number of
+ * channels and a bit depth as input
+ *
+ * The Dither type is one of
+ *
+ * GDitherNone - straight nearest neighbour rounding. Theres no pressing
+ * reason to do this at 8 or 16 bit, but you might want to at 24, for some
+ * reason. At the lest it will save you writing int->float conversion code,
+ * which is arder than it sounds.
+ *
+ * GDitherRect - mathematically most accurate, lowest noise floor, but not
+ * that good for audio. It is the fastest though.
+ *
+ * GDitherTri - a happy medium between Rectangular and Shaped, reasonable
+ * noise floor, not too obvious, quite fast.
+ *
+ * GDitherShaped - should have the least audible impact, but has the highest
+ * noise floor, fairly CPU intensive. Not advisible if your going to apply
+ * any frequency manipulation afterwards.
+ *
+ * channels, sets the number of channels in the output data, output data will
+ * be written interleaved into the area given to gdither_run(). Set to 1
+ * if you are not working with interleaved buffers.
+ *
+ * bit depth, sets the bit width of the output sample data, it can be one of:
+ *
+ * GDither8bit - 8 bit unsiged
+ * GDither16bit - 16 bit signed
+ * GDither32bit - 24+bits in upper bits of a 32 bit word
+ * GDitherFloat - IEEE floating point (32bits)
+ * GDitherDouble - Double precision IEEE floating point (64bits)
+ *
+ * dither_depth, set the number of bits before the signal will be truncated to,
+ * eg. 16 will produce an output stream with 16bits-worth of signal. Setting to
+ * zero or greater than the width of the output format will dither to the
+ * maximum precision allowed by the output format.
+ */
+GDither gdither_new(GDitherType type, uint32_t channels,
+
+ GDitherSize bit_depth, int dither_depth);
+
+/* Frees memory used by gdither_new.
+ */
+void gdither_free(GDither s);
+
+/* Applies dithering to the supplied signal.
+ *
+ * channel is the channel number you are processing (0 - channles-1), length is
+ * the length of the input, in samples, x is the input samples (float), y is
+ * where the output samples will be written, it should have the approaprate
+ * type for the chosen bit depth
+ */
+void gdither_runf(GDither s, uint32_t channel, uint32_t length,
+ float const *x, void *y);
+
+/* see gdither_runf, vut input argument is double format */
+void gdither_run(GDither s, uint32_t channel, uint32_t length,
+ double const *x, void *y);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/audiographer/private/gdither/gdither_types.h b/libs/audiographer/private/gdither/gdither_types.h
new file mode 100644
index 0000000000..bcc0097d7f
--- /dev/null
+++ b/libs/audiographer/private/gdither/gdither_types.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2002 Steve Harris <steve@plugin.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef GDITHER_TYPES_H
+#define GDITHER_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ GDitherNone = 0,
+ GDitherRect,
+ GDitherTri,
+ GDitherShaped
+} GDitherType;
+
+typedef enum {
+ GDither8bit = 8,
+ GDither16bit = 16,
+ GDither32bit = 32,
+ GDitherFloat = 25,
+ GDitherDouble = 54
+} GDitherSize;
+
+typedef void *GDither;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/audiographer/private/gdither/gdither_types_internal.h b/libs/audiographer/private/gdither/gdither_types_internal.h
new file mode 100644
index 0000000000..6cb0c48af9
--- /dev/null
+++ b/libs/audiographer/private/gdither/gdither_types_internal.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2002 Steve Harris <steve@plugin.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef GDITHER_TYPES_H
+#define GDITHER_TYPES_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GDITHER_SH_BUF_SIZE 8
+#define GDITHER_SH_BUF_MASK 7
+
+/* this must agree with whats in gdither_types.h */
+typedef enum {
+ GDitherNone = 0,
+ GDitherRect,
+ GDitherTri,
+ GDitherShaped
+} GDitherType;
+
+typedef enum {
+ GDither8bit = 8,
+ GDither16bit = 16,
+ GDither32bit = 32,
+ GDitherFloat = 25,
+ GDitherDouble = 54
+} GDitherSize;
+
+typedef struct {
+ uint32_t phase;
+ float buffer[GDITHER_SH_BUF_SIZE];
+} GDitherShapedState;
+
+typedef struct GDither_s {
+ GDitherType type;
+ uint32_t channels;
+ uint32_t bit_depth;
+ uint32_t dither_depth;
+ float scale;
+ uint32_t post_scale;
+ float post_scale_fp;
+ float bias;
+
+ int clamp_u;
+
+ int clamp_l;
+ float *tri_state;
+ GDitherShapedState *shaped_state;
+} *GDither;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/audiographer/private/gdither/noise.h b/libs/audiographer/private/gdither/noise.h
new file mode 100644
index 0000000000..96a582ef9b
--- /dev/null
+++ b/libs/audiographer/private/gdither/noise.h
@@ -0,0 +1,38 @@
+/*
+ Copyright (C) 2000-2007 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef NOISE_H
+#define NOISE_H
+
+/* Can be overrriden with any code that produces whitenoise between 0.0f and
+ * 1.0f, eg (random() / (float)RAND_MAX) should be a good source of noise, but
+ * its expensive */
+#ifndef GDITHER_NOISE
+#define GDITHER_NOISE gdither_noise()
+#endif
+
+inline static float gdither_noise()
+{
+ static uint32_t rnd = 23232323;
+ rnd = (rnd * 196314165) + 907633515;
+
+ return rnd * 2.3283064365387e-10f;
+}
+
+#endif
diff --git a/libs/audiographer/private/sndfile.hh b/libs/audiographer/private/sndfile.hh
new file mode 100644
index 0000000000..d8f459f196
--- /dev/null
+++ b/libs/audiographer/private/sndfile.hh
@@ -0,0 +1,399 @@
+/*
+** Copyright (C) 2005-2007 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the author nor the names of any contributors may be used
+** to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+** The above modified BSD style license (GPL and LGPL compatible) applies to
+** this file. It does not apply to libsndfile itself which is released under
+** the GNU LGPL or the libsndfile test suite which is released under the GNU
+** GPL.
+** This means that this header file can be used under this modified BSD style
+** license, but the LGPL still holds for the libsndfile library itself.
+*/
+
+/*
+** sndfile.hh -- A lightweight C++ wrapper for the libsndfile API.
+**
+** All the methods are inlines and all functionality is contained in this
+** file. There is no separate implementation file.
+**
+** API documentation is in the doc/ directory of the source code tarball
+** and at http://www.mega-nerd.com/libsndfile/api.html.
+*/
+
+#ifndef SNDFILE_HH
+#define SNDFILE_HH
+
+#include <sndfile.h>
+
+#include <string>
+#include <new> // for std::nothrow
+
+// Prevent conflicts
+namespace AudioGrapher {
+
+class SndfileHandle
+{ private :
+ struct SNDFILE_ref
+ { SNDFILE_ref (void) ;
+ ~SNDFILE_ref (void) ;
+
+ SNDFILE *sf ;
+ SF_INFO sfinfo ;
+ int ref ;
+ } ;
+
+ SNDFILE_ref *p ;
+
+ public :
+ /* Default constructor */
+ SndfileHandle (void) : p (NULL) {} ;
+ SndfileHandle (const char *path, int mode = SFM_READ,
+ int format = 0, int channels = 0, int samplerate = 0) ;
+ SndfileHandle (std::string const & path, int mode = SFM_READ,
+ int format = 0, int channels = 0, int samplerate = 0) ;
+ SndfileHandle (int fd, bool close_desc, int mode = SFM_READ,
+ int format = 0, int channels = 0, int samplerate = 0) ;
+ ~SndfileHandle (void) ;
+
+ SndfileHandle (const SndfileHandle &orig) ;
+ SndfileHandle & operator = (const SndfileHandle &rhs) ;
+
+ /* Mainly for debugging/testing. */
+ int refCount (void) const { return (p == NULL) ? 0 : p->ref ; }
+
+ operator bool () const { return (p != NULL) ; }
+
+ bool operator == (const SndfileHandle &rhs) const { return (p == rhs.p) ; }
+
+ sf_count_t frames (void) const { return p ? p->sfinfo.frames : 0 ; }
+ int format (void) const { return p ? p->sfinfo.format : 0 ; }
+ int channels (void) const { return p ? p->sfinfo.channels : 0 ; }
+ int samplerate (void) const { return p ? p->sfinfo.samplerate : 0 ; }
+
+ int error (void) const ;
+ const char * strError (void) const ;
+
+ int command (int cmd, void *data, int datasize) ;
+
+ sf_count_t seek (sf_count_t frames, int whence) ;
+
+ void writeSync (void) ;
+
+ int setString (int str_type, const char* str) ;
+
+ const char* getString (int str_type) const ;
+
+ static int formatCheck (int format, int channels, int samplerate) ;
+
+ sf_count_t read (short *ptr, sf_count_t items) ;
+ sf_count_t read (int *ptr, sf_count_t items) ;
+ sf_count_t read (float *ptr, sf_count_t items) ;
+ sf_count_t read (double *ptr, sf_count_t items) ;
+
+ sf_count_t write (const short *ptr, sf_count_t items) ;
+ sf_count_t write (const int *ptr, sf_count_t items) ;
+ sf_count_t write (const float *ptr, sf_count_t items) ;
+ sf_count_t write (const double *ptr, sf_count_t items) ;
+
+ sf_count_t readf (short *ptr, sf_count_t frames) ;
+ sf_count_t readf (int *ptr, sf_count_t frames) ;
+ sf_count_t readf (float *ptr, sf_count_t frames) ;
+ sf_count_t readf (double *ptr, sf_count_t frames) ;
+
+ sf_count_t writef (const short *ptr, sf_count_t frames) ;
+ sf_count_t writef (const int *ptr, sf_count_t frames) ;
+ sf_count_t writef (const float *ptr, sf_count_t frames) ;
+ sf_count_t writef (const double *ptr, sf_count_t frames) ;
+
+ sf_count_t readRaw (void *ptr, sf_count_t bytes) ;
+ sf_count_t writeRaw (const void *ptr, sf_count_t bytes) ;
+
+} ;
+
+/*==============================================================================
+** Nothing but implementation below.
+*/
+
+inline
+SndfileHandle::SNDFILE_ref::SNDFILE_ref (void)
+: ref (1)
+{}
+
+inline
+SndfileHandle::SNDFILE_ref::~SNDFILE_ref (void)
+{ if (sf != NULL) sf_close (sf) ; }
+
+inline
+SndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, int srate)
+: p (NULL)
+{
+ p = new (std::nothrow) SNDFILE_ref () ;
+
+ if (p != NULL)
+ { p->ref = 1 ;
+
+ p->sfinfo.frames = 0 ;
+ p->sfinfo.channels = chans ;
+ p->sfinfo.format = fmt ;
+ p->sfinfo.samplerate = srate ;
+ p->sfinfo.sections = 0 ;
+ p->sfinfo.seekable = 0 ;
+
+ p->sf = sf_open (path, mode, &p->sfinfo) ;
+ } ;
+
+ return ;
+} /* SndfileHandle const char * constructor */
+
+inline
+SndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int chans, int srate)
+: p (NULL)
+{
+ p = new (std::nothrow) SNDFILE_ref () ;
+
+ if (p != NULL)
+ { p->ref = 1 ;
+
+ p->sfinfo.frames = 0 ;
+ p->sfinfo.channels = chans ;
+ p->sfinfo.format = fmt ;
+ p->sfinfo.samplerate = srate ;
+ p->sfinfo.sections = 0 ;
+ p->sfinfo.seekable = 0 ;
+
+ p->sf = sf_open (path.c_str (), mode, &p->sfinfo) ;
+ } ;
+
+ return ;
+} /* SndfileHandle std::string constructor */
+
+SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int chans, int srate)
+: p (NULL)
+{
+ if (fd < 0)
+ return;
+
+ p = new (std::nothrow) SNDFILE_ref () ;
+
+ if (p != NULL)
+ { p->ref = 1 ;
+
+ p->sfinfo.frames = 0 ;
+ p->sfinfo.channels = chans ;
+ p->sfinfo.format = fmt ;
+ p->sfinfo.samplerate = srate ;
+ p->sfinfo.sections = 0 ;
+ p->sfinfo.seekable = 0 ;
+
+ p->sf = sf_open_fd (fd, mode, &p->sfinfo, close_desc) ;
+ } ;
+
+ return ;
+} /* SndfileHandle fd constructor */
+
+inline
+SndfileHandle::~SndfileHandle (void)
+{ if (p != NULL && --p->ref == 0)
+ delete p ;
+} /* SndfileHandle destructor */
+
+
+inline
+SndfileHandle::SndfileHandle (const SndfileHandle &orig)
+: p (orig.p)
+{ if (p != NULL)
+ ++p->ref ;
+} /* SndfileHandle copy constructor */
+
+inline SndfileHandle &
+SndfileHandle::operator = (const SndfileHandle &rhs)
+{
+ if (&rhs == this)
+ return *this ;
+ if (p != NULL && --p->ref == 0)
+ delete p ;
+
+ p = rhs.p ;
+ if (p != NULL)
+ ++p->ref ;
+
+ return *this ;
+} /* SndfileHandle assignment operator */
+
+inline int
+SndfileHandle::error (void) const
+{ return sf_error (p->sf) ; }
+
+inline const char *
+SndfileHandle::strError (void) const
+{ return sf_strerror (p->sf) ; }
+
+inline int
+SndfileHandle::command (int cmd, void *data, int datasize)
+{ return sf_command (p->sf, cmd, data, datasize) ; }
+
+inline sf_count_t
+SndfileHandle::seek (sf_count_t frame_count, int whence)
+{ return sf_seek (p->sf, frame_count, whence) ; }
+
+inline void
+SndfileHandle::writeSync (void)
+{ sf_write_sync (p->sf) ; }
+
+inline int
+SndfileHandle::setString (int str_type, const char* str)
+{ return sf_set_string (p->sf, str_type, str) ; }
+
+inline const char*
+SndfileHandle::getString (int str_type) const
+{ return sf_get_string (p->sf, str_type) ; }
+
+inline int
+SndfileHandle::formatCheck(int fmt, int chans, int srate)
+{
+ SF_INFO sfinfo ;
+
+ sfinfo.frames = 0 ;
+ sfinfo.channels = chans ;
+ sfinfo.format = fmt ;
+ sfinfo.samplerate = srate ;
+ sfinfo.sections = 0 ;
+ sfinfo.seekable = 0 ;
+
+ return sf_format_check (&sfinfo) ;
+}
+
+/*---------------------------------------------------------------------*/
+
+inline sf_count_t
+SndfileHandle::read (short *ptr, sf_count_t items)
+{ return sf_read_short (p->sf, ptr, items) ; }
+
+inline sf_count_t
+SndfileHandle::read (int *ptr, sf_count_t items)
+{ return sf_read_int (p->sf, ptr, items) ; }
+
+inline sf_count_t
+SndfileHandle::read (float *ptr, sf_count_t items)
+{ return sf_read_float (p->sf, ptr, items) ; }
+
+inline sf_count_t
+SndfileHandle::read (double *ptr, sf_count_t items)
+{ return sf_read_double (p->sf, ptr, items) ; }
+
+inline sf_count_t
+SndfileHandle::write (const short *ptr, sf_count_t items)
+{ return sf_write_short (p->sf, ptr, items) ; }
+
+inline sf_count_t
+SndfileHandle::write (const int *ptr, sf_count_t items)
+{ return sf_write_int (p->sf, ptr, items) ; }
+
+inline sf_count_t
+SndfileHandle::write (const float *ptr, sf_count_t items)
+{ return sf_write_float (p->sf, ptr, items) ; }
+
+inline sf_count_t
+SndfileHandle::write (const double *ptr, sf_count_t items)
+{ return sf_write_double (p->sf, ptr, items) ; }
+
+inline sf_count_t
+SndfileHandle::readf (short *ptr, sf_count_t frame_count)
+{ return sf_readf_short (p->sf, ptr, frame_count) ; }
+
+inline sf_count_t
+SndfileHandle::readf (int *ptr, sf_count_t frame_count)
+{ return sf_readf_int (p->sf, ptr, frame_count) ; }
+
+inline sf_count_t
+SndfileHandle::readf (float *ptr, sf_count_t frame_count)
+{ return sf_readf_float (p->sf, ptr, frame_count) ; }
+
+inline sf_count_t
+SndfileHandle::readf (double *ptr, sf_count_t frame_count)
+{ return sf_readf_double (p->sf, ptr, frame_count) ; }
+
+inline sf_count_t
+SndfileHandle::writef (const short *ptr, sf_count_t frame_count)
+{ return sf_writef_short (p->sf, ptr, frame_count) ; }
+
+inline sf_count_t
+SndfileHandle::writef (const int *ptr, sf_count_t frame_count)
+{ return sf_writef_int (p->sf, ptr, frame_count) ; }
+
+inline sf_count_t
+SndfileHandle::writef (const float *ptr, sf_count_t frame_count)
+{ return sf_writef_float (p->sf, ptr, frame_count) ; }
+
+inline sf_count_t
+SndfileHandle::writef (const double *ptr, sf_count_t frame_count)
+{ return sf_writef_double (p->sf, ptr, frame_count) ; }
+
+inline sf_count_t
+SndfileHandle::readRaw (void *ptr, sf_count_t bytes)
+{ return sf_read_raw (p->sf, ptr, bytes) ; }
+
+inline sf_count_t
+SndfileHandle::writeRaw (const void *ptr, sf_count_t bytes)
+{ return sf_write_raw (p->sf, ptr, bytes) ; }
+
+
+#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES
+
+inline
+SndfileHandle::SndfileHandle (LPCWSTR wpath, int mode, int fmt, int chans, int srate)
+: p (NULL)
+{
+ p = new (std::nothrow) SNDFILE_ref () ;
+
+ if (p != NULL)
+ { p->ref = 1 ;
+
+ p->sfinfo.frames = 0 ;
+ p->sfinfo.channels = chans ;
+ p->sfinfo.format = fmt ;
+ p->sfinfo.samplerate = srate ;
+ p->sfinfo.sections = 0 ;
+ p->sfinfo.seekable = 0 ;
+
+ p->sf = sf_wchar_open (wpath, mode, &p->sfinfo) ;
+ } ;
+
+ return ;
+} /* SndfileHandle const wchar_t * constructor */
+
+#endif
+
+} // namespace AudioGrapher
+
+#endif /* SNDFILE_HH */
+