Merge commit 'origin/master'
[opus.git] / libcelt / testcelt.c
1 /* (C) 2007 Jean-Marc Valin, CSIRO
2 */
3 /*
4    Redistribution and use in source and binary forms, with or without
5    modification, are permitted provided that the following conditions
6    are met:
7    
8    - Redistributions of source code must retain the above copyright
9    notice, this list of conditions and the following disclaimer.
10    
11    - Redistributions in binary form must reproduce the above copyright
12    notice, this list of conditions and the following disclaimer in the
13    documentation and/or other materials provided with the distribution.
14    
15    - Neither the name of the Xiph.org Foundation nor the names of its
16    contributors may be used to endorse or promote products derived from
17    this software without specific prior written permission.
18    
19    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include "celt.h"
37 #include "arch.h"
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <math.h>
41 #include <string.h>
42
43 #define MAX_PACKET 1024
44
45 int main(int argc, char *argv[])
46 {
47    char *inFile, *outFile;
48    FILE *fin, *fout;
49    CELTMode *mode=NULL;
50    CELTEncoder *enc;
51    CELTDecoder *dec;
52    int len;
53    celt_int32_t frame_size, channels;
54    int bytes_per_packet;
55    unsigned char data[MAX_PACKET];
56    int rate;
57    int complexity;
58 #if !(defined (FIXED_POINT) && defined(STATIC_MODES))
59    int i;
60    double rmsd = 0;
61 #endif
62    int count = 0;
63    celt_int32_t skip;
64    celt_int16_t *in, *out;
65    if (argc != 9 && argc != 8 && argc != 7)
66    {
67       fprintf (stderr, "Usage: testcelt <rate> <channels> <frame size> "
68                " <bytes per packet> [<complexity> [packet loss rate]] "
69                "<input> <output>\n");
70       return 1;
71    }
72    
73    rate = atoi(argv[1]);
74    channels = atoi(argv[2]);
75    frame_size = atoi(argv[3]);
76    mode = celt_mode_create(rate, channels, frame_size, NULL);
77    celt_mode_info(mode, CELT_GET_LOOKAHEAD, &skip);
78    
79    if (mode == NULL)
80    {
81       fprintf(stderr, "failed to create a mode\n");
82       return 1;
83    }
84    
85    bytes_per_packet = atoi(argv[4]);
86    if (bytes_per_packet < 0 || bytes_per_packet > MAX_PACKET)
87    {
88       fprintf (stderr, "bytes per packet must be between 0 and %d\n",
89                         MAX_PACKET);
90       return 1;
91    }
92
93    inFile = argv[argc-2];
94    fin = fopen(inFile, "rb");
95    if (!fin)
96    {
97       fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
98       return 1;
99    }
100    outFile = argv[argc-1];
101    fout = fopen(outFile, "wb+");
102    if (!fout)
103    {
104       fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
105       return 1;
106    }
107    
108    enc = celt_encoder_create(mode);
109    dec = celt_decoder_create(mode);
110
111    if (argc>7)
112    {
113       complexity=atoi(argv[5]);
114       celt_encoder_ctl(enc,CELT_SET_COMPLEXITY(complexity));
115    }
116    
117    celt_mode_info(mode, CELT_GET_FRAME_SIZE, &frame_size);
118    celt_mode_info(mode, CELT_GET_NB_CHANNELS, &channels);
119    in = (celt_int16_t*)malloc(frame_size*channels*sizeof(celt_int16_t));
120    out = (celt_int16_t*)malloc(frame_size*channels*sizeof(celt_int16_t));
121    while (!feof(fin))
122    {
123       fread(in, sizeof(short), frame_size*channels, fin);
124       if (feof(fin))
125          break;
126       len = celt_encode(enc, in, in, data, bytes_per_packet);
127       if (len <= 0)
128       {
129          fprintf (stderr, "celt_encode() returned %d\n", len);
130          return 1;
131       }
132       /* This is for simulating bit errors */
133 #if 0
134       int errors = 0;
135       int eid = 0;
136       /* This simulates random bit error */
137       for (i=0;i<len*8;i++)
138       {
139          if (rand()%atoi(argv[8])==0)
140          {
141             if (i<64)
142             {
143                errors++;
144                eid = i;
145             }
146             data[i/8] ^= 1<<(7-(i%8));
147          }
148       }
149       if (errors == 1)
150          data[eid/8] ^= 1<<(7-(eid%8));
151       else if (errors%2 == 1)
152          data[rand()%8] ^= 1<<rand()%8;
153 #endif
154 #if 1 /* Set to zero to use the encoder's output instead */
155       /* This is to simulate packet loss */
156       if (argc==9 && rand()%1000<atoi(argv[argc-3]))
157       /*if (errors && (errors%2==0))*/
158          celt_decode(dec, NULL, len, out);
159       else
160          celt_decode(dec, data, len, out);
161 #else
162       for (i=0;i<frame_size*channels;i++)
163          out[i] = in[i];
164 #endif
165 #if !(defined (FIXED_POINT) && defined(STATIC_MODES))
166       for (i=0;i<frame_size*channels;i++)
167       {
168          rmsd += (in[i]-out[i])*1.0*(in[i]-out[i]);
169          /*out[i] -= in[i];*/
170       }
171 #endif
172       count++;
173       fwrite(out+skip, sizeof(short), (frame_size-skip)*channels, fout);
174       skip = 0;
175    }
176    PRINT_MIPS(stderr);
177    
178    celt_encoder_destroy(enc);
179    celt_decoder_destroy(dec);
180    fclose(fin);
181    fclose(fout);
182 #if !(defined (FIXED_POINT) && defined(STATIC_MODES))
183    if (rmsd > 0)
184    {
185       rmsd = sqrt(rmsd/(1.0*frame_size*channels*count));
186       fprintf (stderr, "Error: encoder doesn't match decoder\n");
187       fprintf (stderr, "RMS mismatch is %f\n", rmsd);
188       return 1;
189    } else {
190       fprintf (stderr, "Encoder matches decoder!!\n");
191    }
192 #endif
193    celt_mode_destroy(mode);
194    free(in);
195    free(out);
196    return 0;
197 }
198