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