diff --git a/src/opus.h b/src/opus.h
index fb49b0b1fe0fa0654a8121cc8e2a9d7db009c41d..20a01afeac52e16daa3e2b136ac0a4c074bac112 100644
--- a/src/opus.h
+++ b/src/opus.h
@@ -157,6 +157,8 @@ extern "C" {
 #define OPUS_GET_LOOKAHEAD_REQUEST 27
 #define OPUS_GET_LOOKAHEAD(x) OPUS_GET_LOOKAHEAD_REQUEST, __opus_check_int_ptr(x)
 
+#define OPUS_RESET_STATE 28
+
 /* For testing purposes: the encoder and decoder state should
    always be identical after coding a payload */
 #define OPUS_GET_FINAL_RANGE_REQUEST 29
diff --git a/src/opus_decoder.c b/src/opus_decoder.c
index 074b9d6e05dbd5826d01fcf7da6a8d931d1c5f36..9f10554c77dbf1c45228f1ae86cfa48018dbdde7 100644
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -50,17 +50,19 @@ struct OpusDecoder {
    int          celt_dec_offset;
    int          silk_dec_offset;
    int          channels;
+   int          Fs;          /** Sampling rate (at the API level) */
+
+   /* Everything beyond this point gets cleared on a reset */
+#define OPUS_DECODER_RESET_START stream_channels
    int          stream_channels;
 
-    int          bandwidth;
-    /* Sampling rate (at the API level) */
-    int          Fs;
-    int          mode;
-    int          prev_mode;
-    int          frame_size;
-    int          prev_redundancy;
+   int          bandwidth;
+   int          mode;
+   int          prev_mode;
+   int          frame_size;
+   int          prev_redundancy;
 
-    int          rangeFinal;
+   int          rangeFinal;
 };
 
 #ifdef FIXED_POINT
@@ -216,7 +218,6 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
     {
     	data = NULL;
     	/* In that case, don't conceal more than what the ToC says */
-    	/* FIXME: What if st->frame_size has never been set? */
     	frame_size = IMIN(frame_size, st->frame_size);
     }
     if (data != NULL)
@@ -759,6 +760,24 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
       *value = st->rangeFinal;
    }
    break;
+   case OPUS_RESET_STATE:
+   {
+      void *silk_dec;
+      CELTDecoder *celt_dec;
+
+      silk_dec = (char*)st+st->silk_dec_offset;
+      celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
+
+      OPUS_CLEAR((char*)&st->OPUS_DECODER_RESET_START,
+            opus_decoder_get_size(st->channels)-
+            ((char*)&st->OPUS_DECODER_RESET_START - (char*)st));
+
+      celt_decoder_ctl(celt_dec, CELT_RESET_STATE);
+      silk_InitDecoder( silk_dec );
+      st->stream_channels = st->channels;
+      st->frame_size = st->Fs/400;
+   }
+   break;
    default:
       /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
       ret = OPUS_BAD_ARG;