Limit mode creation to supported modes.
authorTimothy B. Terriberry <tterribe@xiph.org>
Tue, 1 Feb 2011 23:36:59 +0000 (15:36 -0800)
committerJean-Marc Valin <jean-marc.valin@octasic.com>
Tue, 1 Feb 2011 23:58:07 +0000 (18:58 -0500)
We did no real error checking to see if a mode is supported when it
 is created.
This patch implements checks for Jean-Marc's rules:
1) A mode must have frames at least 1ms in length (no more than
    1000 per second).
2) A mode must have shorts of at most 3.33 ms (at least 300 per
    second).
It also adds error checking to dump_modes so we report the error
 instead of crashing when we fail to create a mode.

libcelt/dump_modes.c
libcelt/modes.c

index 340dcfc..ac2e88b 100644 (file)
@@ -34,6 +34,7 @@
 #include "config.h"
 #endif
 
 #include "config.h"
 #endif
 
+#include <stdlib.h>
 #include <stdio.h>
 #include "modes.h"
 #include "celt.h"
 #include <stdio.h>
 #include "modes.h"
 #include "celt.h"
@@ -308,6 +309,12 @@ int main(int argc, char **argv)
       Fs      = atoi(argv[2*i+1]);
       frame   = atoi(argv[2*i+2]);
       m[i] = celt_mode_create(Fs, frame, NULL);
       Fs      = atoi(argv[2*i+1]);
       frame   = atoi(argv[2*i+2]);
       m[i] = celt_mode_create(Fs, frame, NULL);
+      if (m[i]==NULL)
+      {
+         fprintf(stderr,"Error creating mode with Fs=%s, frame_size=%s\n",
+               argv[2*i+1],argv[2*i+2]);
+         return EXIT_FAILURE;
+      }
    }
    file = fopen(BASENAME ".c", "w");
    dump_modes(file, m, nb);
    }
    file = fopen(BASENAME ".c", "w");
    dump_modes(file, m, nb);
index 259a49b..6414d2f 100644 (file)
@@ -331,7 +331,35 @@ CELTMode *celt_mode_create(celt_int32 Fs, int frame_size, int *error)
          *error = CELT_BAD_ARG;
       return NULL;
    }
          *error = CELT_BAD_ARG;
       return NULL;
    }
-   
+   /* Frames of less than 1ms are not supported. */
+   if ((celt_int32)frame_size*1000 < Fs)
+   {
+      if (error)
+         *error = CELT_INVALID_MODE;
+      return NULL;
+   }
+
+   if ((celt_int32)frame_size*75 >= Fs && (frame_size%16)==0)
+   {
+     LM = 3;
+   } else if ((celt_int32)frame_size*150 >= Fs && (frame_size%8)==0)
+   {
+     LM = 2;
+   } else if ((celt_int32)frame_size*300 >= Fs && (frame_size%4)==0)
+   {
+     LM = 1;
+   } else if ((celt_int32)frame_size*300 <= Fs)
+   {
+     LM = 0;
+   }
+   /* Shorts longer than 3.3ms are not supported. */
+   else
+   {
+      if (error)
+         *error = CELT_INVALID_MODE;
+      return NULL;
+   }
+
    mode = celt_alloc(sizeof(CELTMode));
    if (mode==NULL)
       goto failure;
    mode = celt_alloc(sizeof(CELTMode));
    if (mode==NULL)
       goto failure;
@@ -366,20 +394,6 @@ CELTMode *celt_mode_create(celt_int32 Fs, int frame_size, int *error)
       mode->preemph[3] =  QCONST16(1.f, 13);
    }
 
       mode->preemph[3] =  QCONST16(1.f, 13);
    }
 
-   if ((celt_int32)frame_size*75 >= Fs && (frame_size%16)==0)
-   {
-     LM = 3;
-   } else if ((celt_int32)frame_size*150 >= Fs && (frame_size%8)==0)
-   {
-     LM = 2;
-   } else if ((celt_int32)frame_size*300 >= Fs && (frame_size%4)==0)
-   {
-     LM = 1;
-   } else
-   {
-     LM = 0;
-   }
-
    mode->maxLM = LM;
    mode->nbShortMdcts = 1<<LM;
    mode->shortMdctSize = frame_size/mode->nbShortMdcts;
    mode->maxLM = LM;
    mode->nbShortMdcts = 1<<LM;
    mode->shortMdctSize = frame_size/mode->nbShortMdcts;