diff --git a/src/opus.h b/src/opus.h
index 1cf61cf1e70cbc5b7f6ce631f286cdf36f676f56..a95659375701a3a29e00e709cfdfac24d7b5086e 100644
--- a/src/opus.h
+++ b/src/opus.h
@@ -33,11 +33,11 @@ extern "C" {
 #endif
 
 #if defined(__GNUC__) && defined(OPUS_BUILD)
-#define EXPORT __attribute__ ((visibility ("default")))
+#define OPUS_EXPORT __attribute__ ((visibility ("default")))
 #elif defined(WIN32)
-#define EXPORT __declspec(dllexport)
+#define OPUS_EXPORT __declspec(dllexport)
 #else
-#define EXPORT
+#define OPUS_EXPORT
 #endif
 
 #define __check_int(x) (((void)((x) == (int)0)), (int)(x))
@@ -133,36 +133,40 @@ extern "C" {
 typedef struct OpusEncoder OpusEncoder;
 typedef struct OpusDecoder OpusDecoder;
 
-EXPORT OpusEncoder *opus_encoder_create(int Fs, int channels);
+OPUS_EXPORT OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels);
+
+OPUS_EXPORT OpusEncoder *opus_encoder_create(int Fs, int channels);
 
 /* returns length of data payload (in bytes) */
-EXPORT int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
+OPUS_EXPORT int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
 		unsigned char *data, int max_data_bytes);
 
-EXPORT void opus_encoder_destroy(OpusEncoder *st);
+OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st);
+
+OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...);
 
-EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...);
+OPUS_EXPORT OpusDecoder *opus_decoder_init(OpusDecoder *st, int Fs, int channels);
 
-EXPORT OpusDecoder *opus_decoder_create(int Fs, int channels);
+OPUS_EXPORT OpusDecoder *opus_decoder_create(int Fs, int channels);
 
 /* returns (CELT) error code */
-EXPORT int opus_decode(OpusDecoder *st, const unsigned char *data, int len,
+OPUS_EXPORT int opus_decode(OpusDecoder *st, const unsigned char *data, int len,
 		short *pcm, int frame_size, int decode_fec);
 
-EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...);
+OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...);
 
-EXPORT void opus_decoder_destroy(OpusDecoder *st);
+OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st);
 
-EXPORT int opus_packet_get_bandwidth(const unsigned char *data);
-EXPORT int opus_packet_get_samples_per_frame(const unsigned char *data, int Fs);
-EXPORT int opus_packet_get_nb_channels(const unsigned char *data);
-EXPORT int opus_packet_get_nb_frames(const unsigned char packet[], int len);
-EXPORT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], int len);
+OPUS_EXPORT int opus_packet_get_bandwidth(const unsigned char *data);
+OPUS_EXPORT int opus_packet_get_samples_per_frame(const unsigned char *data, int Fs);
+OPUS_EXPORT int opus_packet_get_nb_channels(const unsigned char *data);
+OPUS_EXPORT int opus_packet_get_nb_frames(const unsigned char packet[], int len);
+OPUS_EXPORT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], int len);
 
 
 #if OPUS_TEST_RANGE_CODER_STATE
-EXPORT int opus_encoder_get_final_range(OpusEncoder *st);
-EXPORT int opus_decoder_get_final_range(OpusDecoder *st);
+OPUS_EXPORT int opus_encoder_get_final_range(OpusEncoder *st);
+OPUS_EXPORT int opus_decoder_get_final_range(OpusDecoder *st);
 #endif
 
 
diff --git a/src/opus_decoder.c b/src/opus_decoder.c
index 9a4757bc136299b3e82fe163676d7e6b6137f9aa..82453cdf2bfdc410b95ea1ee551d027ec0185bea 100644
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -29,6 +29,7 @@
 #include "config.h"
 #endif
 
+#include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
@@ -38,27 +39,44 @@
 #include "modes.h"
 #include "SKP_Silk_SDK_API.h"
 
+/* Make sure everything's aligned to 4 bytes (this may need to be increased
+   on really weird architectures) */
+static inline int align(int i)
+{
+	return (i+3)&-4;
+}
 
-OpusDecoder *opus_decoder_create(int Fs, int channels)
+int opus_decoder_get_size(int channels)
+{
+	int silkDecSizeBytes, celtDecSizeBytes;
+	int ret;
+    ret = SKP_Silk_SDK_Get_Decoder_Size( &silkDecSizeBytes );
+	if(ret)
+		return 0;
+	silkDecSizeBytes = align(silkDecSizeBytes);
+    celtDecSizeBytes = celt_decoder_get_size(channels);
+    return align(sizeof(OpusDecoder))+silkDecSizeBytes+celtDecSizeBytes;
+
+}
+
+OpusDecoder *opus_decoder_init(OpusDecoder *st, int Fs, int channels)
 {
 	void *silk_dec;
 	CELTDecoder *celt_dec;
-    char *raw_state;
 	int ret, silkDecSizeBytes, celtDecSizeBytes;
-	OpusDecoder *st;
 
+	memset(st, 0, sizeof(OpusDecoder));
 	/* Initialize SILK encoder */
     ret = SKP_Silk_SDK_Get_Decoder_Size( &silkDecSizeBytes );
     if( ret ) {
-        /* Handle error */
+        return NULL;
     }
+    silkDecSizeBytes = align(silkDecSizeBytes);
     celtDecSizeBytes = celt_decoder_get_size(channels);
-    raw_state = calloc(sizeof(OpusDecoder)+silkDecSizeBytes+celtDecSizeBytes, 1);
-    st = (OpusDecoder*)raw_state;
-    st->silk_dec_offset = sizeof(OpusDecoder);
-    st->celt_dec_offset = sizeof(OpusDecoder)+silkDecSizeBytes;
-    silk_dec = raw_state+st->silk_dec_offset;
-    celt_dec = (CELTDecoder*)(raw_state+st->celt_dec_offset);
+    st->silk_dec_offset = align(sizeof(OpusDecoder));
+    st->celt_dec_offset = st->silk_dec_offset+silkDecSizeBytes;
+    silk_dec = (char*)st+st->silk_dec_offset;
+    celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
     st->stream_channels = st->channels = channels;
 
     st->Fs = Fs;
@@ -66,15 +84,28 @@ OpusDecoder *opus_decoder_create(int Fs, int channels)
     /* Reset decoder */
     ret = SKP_Silk_SDK_InitDecoder( silk_dec );
     if( ret ) {
-        /* Handle error */
+        goto failure;
     }
 
 	/* Initialize CELT decoder */
-	celt_decoder_init(celt_dec, Fs, channels, NULL);
+	celt_decoder_init(celt_dec, Fs, channels, &ret);
+	if (ret != CELT_OK)
+		goto failure;
     celt_decoder_ctl(celt_dec, CELT_SET_SIGNALLING(0));
 
 	st->prev_mode = 0;
 	return st;
+failure:
+    free(st);
+    return NULL;
+}
+
+OpusDecoder *opus_decoder_create(int Fs, int channels)
+{
+    char *raw_state = malloc(opus_decoder_get_size(channels));
+    if (raw_state == NULL)
+    	return NULL;
+    return opus_decoder_init((OpusDecoder*)raw_state, Fs, channels);
 }
 
 static void smooth_fade(const short *in1, const short *in2, short *out,
diff --git a/src/opus_encoder.c b/src/opus_encoder.c
index 117c8b5a82456be5b46959db8036da7e110163c4..ca302ee99fbd82844a998bcb9fd170a864c12c20 100644
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -29,6 +29,7 @@
 #include "config.h"
 #endif
 
+#include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
@@ -54,27 +55,42 @@ static const int audio_bandwidth_thresholds[10] = {
 		33000, 2000, /* SWB<->FB */
 };
 
+/* Make sure everything's aligned to 4 bytes (this may need to be increased
+   on really weird architectures) */
+static inline int align(int i)
+{
+	return (i+3)&-4;
+}
 
-OpusEncoder *opus_encoder_create(int Fs, int channels)
+int opus_encoder_get_size(int channels)
+{
+	int silkEncSizeBytes, celtEncSizeBytes;
+	int ret;
+	ret = SKP_Silk_SDK_Get_Encoder_Size( &silkEncSizeBytes );
+	if(ret)
+		return 0;
+	silkEncSizeBytes = align(silkEncSizeBytes);
+    celtEncSizeBytes = celt_encoder_get_size(channels);
+    return align(sizeof(OpusEncoder))+silkEncSizeBytes+celtEncSizeBytes;
+
+}
+
+OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels)
 {
 	void *silk_enc;
 	CELTEncoder *celt_enc;
     int err;
-    char *raw_state;
-	OpusEncoder *st;
 	int ret, silkEncSizeBytes, celtEncSizeBytes;
 
+	memset(st, 0, sizeof(OpusEncoder));
     /* Create SILK encoder */
     ret = SKP_Silk_SDK_Get_Encoder_Size( &silkEncSizeBytes );
     if( ret )
     	return NULL;
+	silkEncSizeBytes = align(silkEncSizeBytes);
     celtEncSizeBytes = celt_encoder_get_size(channels);
-    raw_state = calloc(sizeof(OpusEncoder)+silkEncSizeBytes+celtEncSizeBytes, 1);
-    if (raw_state == NULL)
-    	return NULL;
-    st = (OpusEncoder*)raw_state;
-    st->silk_enc_offset = sizeof(OpusEncoder);
-    st->celt_enc_offset = sizeof(OpusEncoder)+silkEncSizeBytes;
+    st->silk_enc_offset = align(sizeof(OpusEncoder));
+    st->celt_enc_offset = st->silk_enc_offset+silkEncSizeBytes;
     silk_enc = (char*)st+st->silk_enc_offset;
     celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset);
 
@@ -123,6 +139,14 @@ failure:
     return NULL;
 }
 
+OpusEncoder *opus_encoder_create(int Fs, int channels)
+{
+    char *raw_state = malloc(opus_encoder_get_size(channels));
+    if (raw_state == NULL)
+    	return NULL;
+    return opus_encoder_init((OpusEncoder*)raw_state, Fs, channels);
+}
+
 int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
 		unsigned char *data, int max_data_bytes)
 {