diff --git a/ti/Makefile.dspgw b/ti/Makefile.dspgw
new file mode 100644
index 0000000..be2ebed
--- /dev/null
+++ b/ti/Makefile.dspgw
@@ -0,0 +1,70 @@
+  
+#
+# Makefile for speex
+#
+TOOLS_DIR = /opt/ti_dsptools
+CC = $(TOOLS_DIR)/cgtools-c5500-v2.56/bin/cl55
+AS = $(CC)
+LD = $(CC)
+TOKLI_DIR = /opt/ti_dsptools/dspgw
+TINKERNEL = /opt/ti_dsptools/dspgw/avs_kernel.out
+
+#
+# compiler options
+#
+INCD =	-i$(TOKLI_DIR) \
+	-i/usr/local/src/dsp/dspgw-3.3.1-dsp/src/tokliBIOS \
+	-i/usr/local/src/dsp/dspgw-3.3.1-dsp/ \
+	-i$(TOOLS_DIR)/cgtools-c5500-v2.56/include \
+	-i$(TOOLS_DIR)/bios_5_03/ti/bios/include \
+	-i$(TOOLS_DIR)/ccs221_content/c5500/xdais/include \
+	-i$(TOOLS_DIR)/ccs221_content/c5500/xdais/src/api \
+    -i../ti -i../include
+
+CFLAGS = -q -o3 -ml -dCONFIG_TI_C55X -dHAVE_CONFIG_H -fr../libspeex
+#
+# linker options
+#
+
+LIBD =	-i$(TOKLI_DIR) \
+	-i$(TOOLS_DIR)/cgtools-c5500-v2.56/lib \
+	-i$(TOOLS_DIR)/bios_5_03/ti/bios/lib \
+	-i$(TOOLS_DIR)/ccs221_content/c5500/rtdx/lib
+
+
+LDFLAGS = -z -x -r -cr
+LIBS =	-llnknone.a55L \
+	-ldrivers.a55L \
+	-lsioboth.a55L \
+	-lbios1510.a55L \
+	-lbios.a55L \
+	-lrtdxx.lib \
+	-lrts55x.lib
+
+
+
+all: dummy_kernel.obj speex_enc.o 
+
+speex_enc.o: ../libspeex/bits.o ../libspeex/cb_search.o ../libspeex/exc_10_16_table.o ../libspeex/exc_10_32_table.o ../libspeex/exc_20_32_table.o ../libspeex/exc_5_256_table.o ../libspeex/exc_5_64_table.o ../libspeex/exc_8_128_table.o ../libspeex/filters.o ../libspeex/gain_table.o ../libspeex/gain_table_lbr.o ../libspeex/lpc.o ../libspeex/lsp.o ../libspeex/lsp_tables_nb.o ../libspeex/ltp.o ../libspeex/math_approx.o ../libspeex/misc.o ../libspeex/modes.o ../libspeex/nb_celp.o ../libspeex/quant_lsp.o ../libspeex/sb_celp.o ../libspeex/speex.o ../libspeex/speex_callbacks.o ../libspeex/vbr.o ../libspeex/vq.o ../libspeex/window.o ../libspeex/speex-dspgw.o
+	$(LD) $(LDFLAGS) ../libspeex/bits.obj ../libspeex/cb_search.obj ../libspeex/exc_10_16_table.obj ../libspeex/exc_10_32_table.obj ../libspeex/exc_20_32_table.obj ../libspeex/exc_5_256_table.obj ../libspeex/exc_5_64_table.obj ../libspeex/exc_8_128_table.obj ../libspeex/filters.obj ../libspeex/gain_table.obj ../libspeex/gain_table_lbr.obj ../libspeex/lpc.obj ../libspeex/lsp.obj ../libspeex/lsp_tables_nb.obj ../libspeex/ltp.obj ../libspeex/math_approx.obj ../libspeex/misc.obj ../libspeex/modes.obj ../libspeex/nb_celp.obj ../libspeex/quant_lsp.obj ../libspeex/sb_celp.obj ../libspeex/speex.obj ../libspeex/speex_callbacks.obj ../libspeex/vbr.obj ../libspeex/vq.obj ../libspeex/window.obj ../libspeex/speex-dspgw.obj dummy_kernel.obj $(LIBD) $(LIBS) -o$@
+	coff_unresolve -s .tinkernel $@
+
+# Just because I don't know how to do this more properly
+../libspeex/speex-dspgw.c:
+	cp speex-dspgw.c ../libspeex
+
+clean:
+	-rm ../libspeex/*.obj ../libspeex/speex-dspgw.c speex_enc.o dummy_kernel.obj 
+
+.c.o:
+	$(CC) $(CFLAGS) $(INCD) $< 
+
+dummy_kernel.obj: $(TINKERNEL)
+	gen_dummy_kernel $< -o $@
+$(TINKERNEL):
+	@echo
+	@echo '************************************************'
+	@echo '$(TINKERNEL) not found.'
+	@echo '************************************************'
+	@echo
+	@exit 1
diff --git a/ti/speex-dspgw.c b/ti/speex-dspgw.c
new file mode 100644
index 0000000..cb5d049
--- /dev/null
+++ b/ti/speex-dspgw.c
@@ -0,0 +1,274 @@
+#include "../libspeex/arch.h" /* BYTES_PER_CHAR */
+#include "config.h"           /* must be included after arch.h */
+#include <std.h>
+#include "mailbox/mailbox.h"
+#include "include/tokliBIOS.h"
+#include <speex/speex.h>
+
+#define TEST_QUALITY           4   /* 8kbps */
+#define USE_GLOBAL_IP_BUF      1 /* defined == global, undef == private */
+
+
+/*
+ * Input and output ip buffers to and from ARM side
+ */
+#pragma DATA_SECTION(read_buf, "ipbuf"); 
+#pragma DATA_SECTION(write_buf, "ipbuf"); 
+
+static short read_buf[FRAME_SIZE];
+static short write_buf[FRAME_SIZE];
+struct dsptask *global_task_ptr;
+
+/* Take all Speex space from this private heap */ 
+/* This is useful for multichannel applications */
+/* tkFIXME: private heap ? */
+/*#pragma DATA_SECTION(spxHeap, ".myheap"); */
+static char spxHeap[SPEEX_PERSIST_STACK_SIZE];
+
+/*#pragma DATA_SECTION(spxScratch, ".myheap"); */
+static char spxScratch[SPEEX_SCRATCH_STACK_SIZE];
+
+/* 
+ * Speex manual memory allocation pointers
+ */
+char *spxGlobalHeapPtr, *spxGlobalHeapEnd;
+char *spxGlobalScratchPtr, *spxGlobalScratchEnd;
+long spxGlobalHeapInd;
+long spxGlobalScratchInd;
+
+
+/*
+ * Task's user data
+ */
+struct speex_data {
+    void *st;              /* encoder state */
+    SpeexBits bits;        /* encoder bits (data) */
+    short *read_buf;       /* pointer for input buffer from ARM */
+    short *write_buf;      /* pointer for ouput buffer to ARM */
+};
+
+
+/*
+ * Global user data 
+ * tkFIXME: why global? How to set this in struct dsptask as not global?
+ */
+static struct speex_data speex_data;
+
+
+/*
+ * Init task (mainly the speex encoder). Called from MBCMD_TCTL_TINIT
+ */
+static Uns codec_init(struct dsptask *task)
+{
+    struct speex_data *data = task->udata;
+    spx_int32_t tmp;
+    dbg(task, "initializing");
+    
+    global_task_ptr = task;
+    /* Set up the manual memory allocation variables */
+    spxGlobalHeapPtr = spxHeap;
+    spxGlobalHeapEnd = spxHeap + sizeof(spxHeap);
+    spxGlobalHeapInd = 0;
+
+    dbg(task, "heap: %04p - %04p, size: %lld", 
+        spxGlobalHeapPtr, spxGlobalHeapEnd,
+        (long long)spxGlobalHeapEnd - (long long)spxGlobalHeapPtr);
+
+    spxGlobalScratchPtr = spxScratch;
+    spxGlobalScratchEnd = spxScratch + sizeof(spxScratch);
+    spxGlobalScratchInd = 0;
+
+    dbg(task, "scratch: %04p - %04p, size: %lld",
+        spxGlobalScratchPtr, spxGlobalScratchEnd,
+        (long long)spxGlobalScratchEnd - (long long)spxGlobalScratchPtr);
+
+    dbg(task, "init: encoder init");
+
+    /* Init encoder */
+    data->st = speex_encoder_init(&speex_nb_mode);
+    if (data->st == NULL) {
+        dbg(task, "init: encoder ret val BAD!!");
+        return MBCMD_EID_NOMEM;
+    }
+
+    /* set buffer pointers. */
+    /* tkFIXME: not really needed, could use read/write_buf directly?*/
+    data->read_buf = read_buf;
+    data->write_buf = write_buf;
+
+    dbg(task, "init: setting options");
+
+    /* disable VBR */
+    tmp = 0;
+    speex_encoder_ctl(data->st, SPEEX_SET_VBR, &tmp);
+
+    /* set quality */
+    tmp = TEST_QUALITY;
+    speex_encoder_ctl(data->st, SPEEX_SET_QUALITY, &tmp);
+
+    /* set low cpu usage */
+    tmp = 1;  /* Lowest */
+    speex_encoder_ctl(data->st, SPEEX_SET_COMPLEXITY, &tmp);
+
+    /* Init speex bits */
+    dbg(task, "init: bits init");
+    speex_bits_init(&data->bits);
+
+    dbg(task, "init: requesting buffer");
+
+    /* Request a new input buffer */
+#ifdef USE_GLOBAL_IP_BUF
+    dbg(task, "Using global IP buffers");
+    bkreq(task, FRAME_SIZE * sizeof(short));
+#else
+    bkreqp(task, data->read_buf, FRAME_SIZE * sizeof(short));
+#endif
+
+    dbg(task, "init: requested new input buffer (%d bytes)", 
+        FRAME_SIZE * sizeof(short));
+
+    return 0;
+}
+
+
+
+/*
+ * This is called once we have new data from ARM side.
+ * task is our current task, count is the number of bytes (16bits) we got.
+ * bid is buffer ID, if we are using global buffers.
+ */
+#ifdef USE_GLOBAL_IP_BUF
+static Uns rcv_bksnd(struct dsptask *task, Uns bid, Uns count)
+#else 
+static Uns rcv_bksnd(struct dsptask *task, Uns count)
+#endif
+{
+    Uns u_bid;
+    struct speex_data *data = task->udata;
+    int nbChars;
+
+    global_task_ptr = task;
+
+    poll_disable(task);
+
+    /* Too much data sent across */
+    if (count > FRAME_SIZE * sizeof(short))
+        return MBCMD_EID_BADCNT;
+
+#ifdef USE_GLOBAL_IP_BUF
+    /* copy data from global buffer to our temp buffer */
+    /* tkFIXME: the inbuf_d[bid] should be probably used instead of copying */
+    /* tkFIXME: the same buffer could be probably used for outgoing too */
+    memcpy(data->read_buf, ipbuf_d[bid], count);
+    unuse_ipbuf(task, bid);
+#endif
+
+    dbg(task, "rcv_bksnd: got %d bytes of data: 0x%04x 0x%04x 0x%04x 0x%04x",
+        count, 
+        data->read_buf[0], data->read_buf[1],
+        data->read_buf[2], data->read_buf[3]);
+
+    /* encode */
+    speex_encode_int(data->st, data->read_buf, &data->bits);
+
+    /* write bits to output buffer */
+    nbChars = speex_bits_write(&data->bits, (char*)data->write_buf, 
+                               FRAME_SIZE);
+    dbg(task, "got %d bytes of data (will be /2)", nbChars);
+    nbChars /= BYTES_PER_CHAR;
+
+    /* reset bits for next round */
+    speex_bits_reset(&data->bits);
+    
+
+    /* Send the output buffer */
+#ifdef USE_GLOBAL_IP_BUF
+    /* allocate IPBUF */
+    u_bid = get_free_ipbuf(task);
+    if (u_bid == MBCMD_BID_NULL)
+        return MBCMD_EID_STVBUF;
+
+    /* copy data from output buffer to global buf */
+    memcpy(ipbuf_d[u_bid], data->write_buf, nbChars);
+    bksnd(task, u_bid, nbChars);
+#else
+    bksndp(task, data->write_buf, nbChars);
+#endif
+  
+    dbg(task, "sent buffer (%d bytes): 0x%04x 0x%04x 0x%04x 0x%04x",
+        nbChars,
+        data->write_buf[0], data->write_buf[1],
+        data->write_buf[2], data->write_buf[3]);
+
+    /* Request a new input buffer */
+#ifdef USE_GLOBAL_IP_BUF
+    bkreq(task, FRAME_SIZE * sizeof(short));
+#else
+    bkreqp(task, data->read_buf, FRAME_SIZE * sizeof(short));
+#endif
+
+    dbg(task, "requested new input buffer (%d bytes)", 
+        FRAME_SIZE * sizeof(short));
+
+    return 0;
+}
+
+
+
+/*
+ * This is called when the task's dev file is ioctl'ed
+ */
+static Uns rcv_tctl(struct dsptask *task, Uns ctlcmd, Uns *ret, Uns arg)
+{
+    struct speex_data *data = task->udata;
+    global_task_ptr = task;
+
+    switch (ctlcmd) {
+    case MBCMD_TCTL_TINIT:
+        /* Init is called automatically when the device file is opened */
+        return codec_init(task);
+    case MBCMD_TCTL_TCLR:
+    case MBCMD_TCTL_TKILL:
+        /* Kill is called automatically when the device file is closed */
+        if (data->st) {
+            speex_encoder_destroy(data->st);
+        }
+        return 0;
+    default:
+        return MBCMD_EID_BADTCTL;
+    }
+
+}
+
+
+/*
+ * This defines the dsp tasks callbacks and data transfer behaviour
+ */
+#pragma DATA_SECTION(task_speex_enc, "dspgw_task")
+struct dsptask task_speex_enc = {
+	TID_MAGIC,	/* tid */
+	"speex_enc",	/* name */
+#ifdef USE_GLOBAL_IP_BUF
+	MBCMD_TTYP_GBDM | MBCMD_TTYP_GBMD | /* global buffers both directions */
+#else
+	MBCMD_TTYP_PVDM | MBCMD_TTYP_PVMD | /* private buffers both directions */
+#endif
+	MBCMD_TTYP_BKDM | MBCMD_TTYP_BKMD | /* block data transfer */
+	MBCMD_TTYP_ASND | MBCMD_TTYP_ARCV,  /* active sending and receiving */
+	rcv_bksnd,  /* rcv_snd */
+	NULL,	    /* rcv_req */
+	rcv_tctl,   /* rcv_tctl */
+	NULL,		/* tsk_attrs */
+	NULL,		/* mmap_info */
+	&speex_data	/* udata */
+};
+
+
+
+/* Emacs indentatation information
+ * Local Variables:
+ * c-file-style:"stroustrup"
+ * c-basic-offset:4
+ * indent-tabs-mode:nil
+ * End:
+ */
diff --git a/ti/test_speex.c b/ti/test_speex.c
new file mode 100644
index 0000000..1b39fc2
--- /dev/null
+++ b/ti/test_speex.c
@@ -0,0 +1,138 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <strings.h>
+#include <unistd.h>
+
+#define FRAME_SIZE 160
+#define DO_MEASUREMENTS 1
+
+#ifdef DO_MEASUREMENTS
+#include <sys/time.h>
+#include <time.h>
+#endif
+
+
+short inbuf[FRAME_SIZE];
+unsigned char outbuf[FRAME_SIZE*sizeof(short)];
+
+/*
+**************************************************************************
+**************************************************************************
+*/
+
+int main(int argc, char **argv)
+{
+    short count;
+    int infd, outfd;
+    int fd;
+    int cnt1, cnt2;
+    char *devfn = "/dev/dsptask/speex_enc";
+    struct timeval tv_start, tv_stop;
+#ifdef DO_MEASUREMENTS
+    double ms;
+    int ms_i = 0;
+#endif
+
+    if (argc != 1 && argc != 2) {
+        fprintf(stderr, "Usage: %s <foo> (reads from stdin and writes to stdout), foo for stop after a frame\n",
+                argv[0]);
+        return 1; /* Exit, error code 1 */
+    }
+ 
+    fd = open(devfn, O_RDWR);
+    if (fd < 0) {
+        fprintf(stderr, "cannot open %s: %s\n", devfn, strerror(errno));
+        return 1;
+    }
+    fprintf(stderr, "Opened device\n");
+
+    do
+    {
+        short i;
+        count = 0;
+        while (count < FRAME_SIZE * sizeof(short)) {
+            int retval;
+            retval = read(STDIN_FILENO, &inbuf[count],
+                          FRAME_SIZE * sizeof(short) - count);
+            if (retval < 0) {
+                perror("stdin read failed");
+                return 1;
+            }
+            if (retval == 0) {
+                fprintf(stderr, "Read 0 bytes, exiting\n");
+                exit(0);
+            }
+            count += retval;
+        }
+
+        if (count != FRAME_SIZE * sizeof(short)) {
+            fprintf(stderr, "read wrong number of bytes: %d\n", count);
+            return 1;
+        }
+
+#ifdef DO_MEASUREMENTS
+        gettimeofday(&tv_start, NULL);
+#endif
+        /* Write these data to the DSP */
+        cnt1 = write(fd, inbuf, FRAME_SIZE * sizeof(short));
+        if (cnt1 < 0) {
+            perror("write failed");
+            return 1;
+        }
+        /*fprintf(stderr, "Written %d shorts to device\n", cnt1);*/
+
+        /* Read processed data from the DSP */
+        cnt2 = read(fd, outbuf, FRAME_SIZE * sizeof(short));
+        if (cnt2 < 0) {
+            perror("read failed");
+            return 1;
+        }
+        /*fprintf(stderr, "Read %d chars from device\n", cnt2);*/
+#ifdef DO_MEASUREMENTS
+        gettimeofday(&tv_stop, NULL);
+        tv_stop.tv_sec -= tv_start.tv_sec;
+        tv_stop.tv_usec -= tv_start.tv_usec;
+        if (tv_stop.tv_usec < 0) {
+            --tv_stop.tv_sec;
+            tv_stop.tv_usec += 1000000;
+           
+        }
+        
+        ms += ((tv_stop.tv_usec + tv_stop.tv_sec * 1000000) / 1000.0);
+        if (++ms_i == 100) {
+            fprintf(stderr, "TIME: %2.6f\n", ms / (double)ms_i);
+            ms_i = 0;
+            ms = 0;
+        }
+#endif
+
+        if (write(STDOUT_FILENO, outbuf, cnt2) != cnt2) {
+            perror("Write error"); 
+            return 1;
+        }
+        if (argc == 2) {
+            exit(0);
+        }
+        /*fprintf(stderr, "Written %d chars to output file\n", count);*/
+    } while (1);
+
+    close(fd);
+    fprintf(stderr, "Closed files and device and exiting\n");
+
+    return 0; /* Exit, no errors */
+}
+
+
+
+/* Emacs indentatation information
+ * Local Variables:
+ * c-file-style:"stroustrup"
+ * c-basic-offset:4
+ * indent-tabs-mode:nil
+ * End:
+ */
diff --git a/ti/user_misc.h b/ti/user_misc.h
index 9e2a4f5..82c3714 100644
--- a/ti/user_misc.h
+++ b/ti/user_misc.h
@@ -30,98 +30,113 @@
    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
-
-#ifdef MANUAL_ALLOC
-
-/* To avoid changing the Speex call model, this file relies on four static variables 
-   The user main creates two linear buffers, and initializes spxGlobalHeap/ScratchPtr 
-   to point to the start of the two buffers, and initializes spxGlobalHeap/ScratchEnd 
-   to point to the first address following the last byte of the two buffers.
-   
-   This mechanism allows, for example, data caching for multichannel applications, 
-   where the Speex state is swapped from a large slow memory to a small fast memory 
-   each time the codec runs.
-   
-   Persistent data is allocated in spxGlobalHeap (instead of calloc), while scratch
-   data is allocated in spxGlobalScratch.
-*/
-
-extern char *spxGlobalHeapPtr, *spxGlobalHeapEnd; 
-extern char *spxGlobalScratchPtr, *spxGlobalScratchEnd;
-
-/* Make sure that all structures are aligned to largest type */
-#define BLOCK_MASK      (sizeof(long double)-1)
-
-#define OVERRIDE_SPEEX_ALLOC
-void *speex_alloc (int size)
-{
-    void *ptr;
-    
-    ptr = (void *) (((int)spxGlobalHeapPtr + BLOCK_MASK) & ~BLOCK_MASK);  //Start on 8 boundary
-
-    spxGlobalHeapPtr = (char *)((int)ptr + size);	// Update pointer to next free location
-
-    if (spxGlobalHeapPtr > spxGlobalHeapEnd ) 
-    {
-#ifdef VERBOSE_ALLOC
-	    fprintf (stderr, "insufficient space for persistent alloc request %d bytes\n", size);
-#endif
-       return 0;
-    }
-   
-#ifdef VERBOSE_ALLOC
-    fprintf (stderr, "Persist Allocated %d chars at %x, %d remaining\n", size, ptr, ((int)spxGlobalHeapEnd - (int)spxGlobalHeapPtr));
-#endif
-    memset(ptr, 0, size);
-    return ptr;
-}
-
-#define OVERRIDE_SPEEX_ALLOC_SCRATCH
-void *speex_alloc_scratch (int size)
-{
-    void *ptr;
-
-    ptr = (void *) (((int)spxGlobalScratchPtr + BLOCK_MASK) & ~BLOCK_MASK);  //Start on 8 boundary
-
-    spxGlobalScratchPtr = (char *)((int)ptr + size);	// Update pointer to next free location
-
-    if (spxGlobalScratchPtr > spxGlobalScratchEnd ) 
-    {
-#ifdef VERBOSE_ALLOC
-	    fprintf (stderr, "insufficient space for scratch alloc request %d bytes\n", size);
-#endif
-       return 0;
-    }
-   
-#ifdef VERBOSE_ALLOC
-    fprintf (stderr, "Scratch Allocated %d chars at %x, %d remaining\n", size, ptr, ((int)spxGlobalScratchEnd - (int)spxGlobalScratchPtr));
-#endif
-    memset(ptr, 0, size);
-    return ptr;
-}
-
-#define OVERRIDE_SPEEX_REALLOC
-void *speex_realloc (void *ptr, int size)
-{
-#ifdef VERBOSE_ALLOC
-   speex_warning("realloc attempted, not allowed");
-#endif
-   return 0;
-}
-
-#define OVERRIDE_SPEEX_FREE
-void speex_free (void *ptr)
-{
-#ifdef VERBOSE_ALLOC
-   speex_warning("at speex_free");
-#endif
-}
-#define OVERRIDE_SPEEX_FREE_SCRATCH
-void speex_free_scratch (void *ptr)
-{
-#ifdef VERBOSE_ALLOC
-   speex_warning("at speex_free_scratch");
-#endif
-}
-
-#endif    /* !MANUAL_ALLOC */
+
+
+#ifdef MANUAL_ALLOC
+#include "include/tokliBIOS.h"
+
+/* To avoid changing the Speex call model, this file relies on four
+   static variables The user main creates two linear buffers, and
+   initializes spxGlobalHeap/ScratchPtr to point to the start of the
+   two buffers, and initializes spxGlobalInd/ScratchInd to be used as
+   indexes to the buffers.
+   
+   This mechanism allows, for example, data caching for multichannel
+   applications, where the Speex state is swapped from a large slow
+   memory to a small fast memory each time the codec runs.
+   
+   Persistent data is allocated in spxGlobalHeap (instead of calloc),
+   while scratch data is allocated in spxGlobalScratch.
+*/
+
+extern char *spxGlobalHeapPtr;
+extern char *spxGlobalScratchPtr;
+extern long spxGlobalHeapInd;
+extern long spxGlobalScratchInd;
+
+/* hack for dbg() */
+extern struct dsptask *global_task_ptr;
+
+/* generic memory allocation for speex_alloc and speex_alloc_scratch */
+static void *_alloc (int size, char *mem, long *index, int max_size,
+					 char *type);
+
+
+#define OVERRIDE_SPEEX_ALLOC
+void *speex_alloc (int size)
+{
+  return _alloc(size, spxGlobalHeapPtr, &spxGlobalHeapInd, 
+				SPEEX_PERSIST_STACK_SIZE, "persist");
+}
+
+
+
+#define OVERRIDE_SPEEX_ALLOC_SCRATCH
+void *speex_alloc_scratch (int size)
+{
+  return _alloc(size, spxGlobalScratchPtr, &spxGlobalScratchInd, 
+				SPEEX_SCRATCH_STACK_SIZE, "scratch");
+}
+
+
+
+/*
+ * Allocate size bytes from mem and increase index. Check that it
+ * doesn't overflow over max_size. The type string can be used in
+ * debugs.
+ */
+static void *_alloc (int size, char *mem, long *index, int max_size, char *type)
+{
+  void *ptr;
+  
+  if (size % sizeof(long) != 0) {
+	// round up to next X bytes (long = 2, long long = 4)
+	size += sizeof(long) - (size % sizeof(long));
+  }
+  
+  if (*index + size > max_size) { // check for overflow
+#ifdef VERBOSE_ALLOC
+	dbg(global_task_ptr, "insufficient space for %s alloc request %d bytes\n",
+		type, size);
+#endif
+	return NULL;
+  }
+
+  ptr = &mem[*index]; // get address for allocated memory  
+  *index = *index + size; // update index for next allocation
+
+#ifdef VERBOSE_ALLOC
+  dbg(global_task_ptr, "%s allocated %d chars at %p, %ld remaining\n",
+	  type, size, ptr, max_size - *index);
+#endif
+  memset(ptr, 0, size); // clear the memory area
+  return ptr;
+}
+
+
+
+#define OVERRIDE_SPEEX_REALLOC
+void *speex_realloc (void *ptr, int size)
+{
+#ifdef VERBOSE_ALLOC
+   speex_warning("realloc attempted, not allowed");
+#endif
+   return 0;
+}
+
+#define OVERRIDE_SPEEX_FREE
+void speex_free (void *ptr)
+{
+#ifdef VERBOSE_ALLOC
+   speex_warning("at speex_free");
+#endif
+}
+#define OVERRIDE_SPEEX_FREE_SCRATCH
+void speex_free_scratch (void *ptr)
+{
+#ifdef VERBOSE_ALLOC
+   speex_warning("at speex_free_scratch");
+#endif
+}
+
+#endif    /* !MANUAL_ALLOC */
