diff --git a/celt/bands.c b/celt/bands.c
index ae77ed7142d27fcf4e50f823281da66d87a4d1bc..f55a8fe00b60cc34977a6dee726caf0f6da669a6 100644
--- a/celt/bands.c
+++ b/celt/bands.c
@@ -205,17 +205,30 @@ void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
       for (i=start;i<end;i++)
       {
          int j, band_end;
-         celt_ener bandE;
-         opus_val32 g;
+         opus_val16 g;
          opus_val16 lg;
-         lg = ADD16(bandLogE[i+c*m->nbEBands], SHL16((opus_val16)eMeans[i],6));
-         bandE = PSHR32(celt_exp2(lg),4);
-         g = SHR32(bandE,1);
+#ifdef FIXED_POINT
+         int shift;
+#endif
          j=M*eBands[i];
          band_end = M*eBands[i+1];
+         lg = ADD16(bandLogE[i+c*m->nbEBands], SHL16((opus_val16)eMeans[i],6));
+#ifdef FIXED_POINT
+         /* Handle the integer part of the log energy */
+         shift = 16-(lg>>DB_SHIFT);
+         if (shift>31)
+         {
+            shift=0;
+            g=0;
+         } else {
+            /* Handle the fractional part. */
+            g = celt_exp2_frac(lg&((1<<DB_SHIFT)-1));
+         }
+#else
+         g = celt_exp2(lg);
+#endif
          do {
-            *f++ = SHL32(MULT16_32_Q15(*x, g),2);
-            x++;
+            *f++ = SHR32(MULT16_16(*x++, g), shift);
          } while (++j<band_end);
       }
       celt_assert(start <= end);
diff --git a/celt/mathops.h b/celt/mathops.h
index 18a66be165240f0ebce7100dbe3fc39e2313f644..44fa97c69751570143fb11c4802827083706b653 100644
--- a/celt/mathops.h
+++ b/celt/mathops.h
@@ -190,6 +190,13 @@ static inline opus_val16 celt_log2(opus_val32 x)
 #define D1 22804
 #define D2 14819
 #define D3 10204
+
+static inline opus_val32 celt_exp2_frac(opus_val16 x)
+{
+   opus_val16 frac;
+   frac = SHL16(x, 4);
+   return ADD16(D0, MULT16_16_Q15(frac, ADD16(D1, MULT16_16_Q15(frac, ADD16(D2 , MULT16_16_Q15(D3,frac))))));
+}
 /** Base-2 exponential approximation (2^x). (Q10 input, Q16 output) */
 static inline opus_val32 celt_exp2(opus_val16 x)
 {
@@ -200,8 +207,7 @@ static inline opus_val32 celt_exp2(opus_val16 x)
       return 0x7f000000;
    else if (integer < -15)
       return 0;
-   frac = SHL16(x-SHL16(integer,10),4);
-   frac = ADD16(D0, MULT16_16_Q15(frac, ADD16(D1, MULT16_16_Q15(frac, ADD16(D2 , MULT16_16_Q15(D3,frac))))));
+   frac = celt_exp2_frac(x-SHL16(integer,10));
    return VSHR32(EXTEND32(frac), -integer-2);
 }