1*a58d3d2aSXin Li /* Copyright (c) 2017 Google Inc.
2*a58d3d2aSXin Li Written by Andrew Allen */
3*a58d3d2aSXin Li /*
4*a58d3d2aSXin Li Redistribution and use in source and binary forms, with or without
5*a58d3d2aSXin Li modification, are permitted provided that the following conditions
6*a58d3d2aSXin Li are met:
7*a58d3d2aSXin Li
8*a58d3d2aSXin Li - Redistributions of source code must retain the above copyright
9*a58d3d2aSXin Li notice, this list of conditions and the following disclaimer.
10*a58d3d2aSXin Li
11*a58d3d2aSXin Li - Redistributions in binary form must reproduce the above copyright
12*a58d3d2aSXin Li notice, this list of conditions and the following disclaimer in the
13*a58d3d2aSXin Li documentation and/or other materials provided with the distribution.
14*a58d3d2aSXin Li
15*a58d3d2aSXin Li THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16*a58d3d2aSXin Li ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17*a58d3d2aSXin Li LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18*a58d3d2aSXin Li A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19*a58d3d2aSXin Li OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20*a58d3d2aSXin Li EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21*a58d3d2aSXin Li PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22*a58d3d2aSXin Li PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23*a58d3d2aSXin Li LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24*a58d3d2aSXin Li NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25*a58d3d2aSXin Li SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*a58d3d2aSXin Li */
27*a58d3d2aSXin Li
28*a58d3d2aSXin Li #ifdef HAVE_CONFIG_H
29*a58d3d2aSXin Li #include "config.h"
30*a58d3d2aSXin Li #endif
31*a58d3d2aSXin Li
32*a58d3d2aSXin Li #include <stdio.h>
33*a58d3d2aSXin Li #include <stdlib.h>
34*a58d3d2aSXin Li #include <stdint.h>
35*a58d3d2aSXin Li #include <string.h>
36*a58d3d2aSXin Li #include "float_cast.h"
37*a58d3d2aSXin Li #include "opus.h"
38*a58d3d2aSXin Li #include "test_opus_common.h"
39*a58d3d2aSXin Li #include "opus_projection.h"
40*a58d3d2aSXin Li #include "mathops.h"
41*a58d3d2aSXin Li #include "../src/mapping_matrix.h"
42*a58d3d2aSXin Li #include "mathops.h"
43*a58d3d2aSXin Li
44*a58d3d2aSXin Li #define BUFFER_SIZE 960
45*a58d3d2aSXin Li #define MAX_DATA_BYTES 32768
46*a58d3d2aSXin Li #define MAX_FRAME_SAMPLES 5760
47*a58d3d2aSXin Li #define ERROR_TOLERANCE 1
48*a58d3d2aSXin Li
49*a58d3d2aSXin Li #define SIMPLE_MATRIX_SIZE 12
50*a58d3d2aSXin Li #define SIMPLE_MATRIX_FRAME_SIZE 10
51*a58d3d2aSXin Li #define SIMPLE_MATRIX_INPUT_SIZE 30
52*a58d3d2aSXin Li #define SIMPLE_MATRIX_OUTPUT_SIZE 40
53*a58d3d2aSXin Li
assert_is_equal(const opus_val16 * a,const opus_int16 * b,int size,opus_int16 tolerance)54*a58d3d2aSXin Li int assert_is_equal(
55*a58d3d2aSXin Li const opus_val16 *a, const opus_int16 *b, int size, opus_int16 tolerance)
56*a58d3d2aSXin Li {
57*a58d3d2aSXin Li int i;
58*a58d3d2aSXin Li for (i = 0; i < size; i++)
59*a58d3d2aSXin Li {
60*a58d3d2aSXin Li #ifdef FIXED_POINT
61*a58d3d2aSXin Li opus_int16 val = a[i];
62*a58d3d2aSXin Li #else
63*a58d3d2aSXin Li opus_int16 val = FLOAT2INT16(a[i]);
64*a58d3d2aSXin Li #endif
65*a58d3d2aSXin Li if (abs(val - b[i]) > tolerance)
66*a58d3d2aSXin Li return 1;
67*a58d3d2aSXin Li }
68*a58d3d2aSXin Li return 0;
69*a58d3d2aSXin Li }
70*a58d3d2aSXin Li
assert_is_equal_short(const opus_int16 * a,const opus_int16 * b,int size,opus_int16 tolerance)71*a58d3d2aSXin Li int assert_is_equal_short(
72*a58d3d2aSXin Li const opus_int16 *a, const opus_int16 *b, int size, opus_int16 tolerance)
73*a58d3d2aSXin Li {
74*a58d3d2aSXin Li int i;
75*a58d3d2aSXin Li for (i = 0; i < size; i++)
76*a58d3d2aSXin Li if (abs(a[i] - b[i]) > tolerance)
77*a58d3d2aSXin Li return 1;
78*a58d3d2aSXin Li return 0;
79*a58d3d2aSXin Li }
80*a58d3d2aSXin Li
test_simple_matrix(void)81*a58d3d2aSXin Li void test_simple_matrix(void)
82*a58d3d2aSXin Li {
83*a58d3d2aSXin Li const MappingMatrix simple_matrix_params = {4, 3, 0};
84*a58d3d2aSXin Li const opus_int16 simple_matrix_data[SIMPLE_MATRIX_SIZE] = {0, 32767, 0, 0, 32767, 0, 0, 0, 0, 0, 0, 32767};
85*a58d3d2aSXin Li const opus_int16 input_int16[SIMPLE_MATRIX_INPUT_SIZE] = {
86*a58d3d2aSXin Li 32767, 0, -32768, 29491, -3277, -29491, 26214, -6554, -26214, 22938, -9830,
87*a58d3d2aSXin Li -22938, 19661, -13107, -19661, 16384, -16384, -16384, 13107, -19661, -13107,
88*a58d3d2aSXin Li 9830, -22938, -9830, 6554, -26214, -6554, 3277, -29491, -3277};
89*a58d3d2aSXin Li const opus_int16 expected_output_int16[SIMPLE_MATRIX_OUTPUT_SIZE] = {
90*a58d3d2aSXin Li 0, 32767, 0, -32768, -3277, 29491, 0, -29491, -6554, 26214, 0, -26214,
91*a58d3d2aSXin Li -9830, 22938, 0, -22938, -13107, 19661, 0, -19661, -16384, 16384, 0, -16384,
92*a58d3d2aSXin Li -19661, 13107, 0, -13107, -22938, 9830, 0, -9830, -26214, 6554, 0, -6554,
93*a58d3d2aSXin Li -29491, 3277, 0, -3277};
94*a58d3d2aSXin Li
95*a58d3d2aSXin Li int i, ret;
96*a58d3d2aSXin Li opus_int32 simple_matrix_size;
97*a58d3d2aSXin Li opus_val16 *input_val16;
98*a58d3d2aSXin Li opus_val16 *output_val16;
99*a58d3d2aSXin Li opus_int16 *output_int16;
100*a58d3d2aSXin Li MappingMatrix *simple_matrix;
101*a58d3d2aSXin Li
102*a58d3d2aSXin Li /* Allocate input/output buffers. */
103*a58d3d2aSXin Li input_val16 = (opus_val16 *)opus_alloc(sizeof(opus_val16) * SIMPLE_MATRIX_INPUT_SIZE);
104*a58d3d2aSXin Li output_int16 = (opus_int16 *)opus_alloc(sizeof(opus_int16) * SIMPLE_MATRIX_OUTPUT_SIZE);
105*a58d3d2aSXin Li output_val16 = (opus_val16 *)opus_alloc(sizeof(opus_val16) * SIMPLE_MATRIX_OUTPUT_SIZE);
106*a58d3d2aSXin Li
107*a58d3d2aSXin Li /* Initialize matrix */
108*a58d3d2aSXin Li simple_matrix_size = mapping_matrix_get_size(simple_matrix_params.rows,
109*a58d3d2aSXin Li simple_matrix_params.cols);
110*a58d3d2aSXin Li if (!simple_matrix_size)
111*a58d3d2aSXin Li test_failed();
112*a58d3d2aSXin Li
113*a58d3d2aSXin Li simple_matrix = (MappingMatrix *)opus_alloc(simple_matrix_size);
114*a58d3d2aSXin Li mapping_matrix_init(simple_matrix, simple_matrix_params.rows,
115*a58d3d2aSXin Li simple_matrix_params.cols, simple_matrix_params.gain, simple_matrix_data,
116*a58d3d2aSXin Li sizeof(simple_matrix_data));
117*a58d3d2aSXin Li
118*a58d3d2aSXin Li /* Copy inputs. */
119*a58d3d2aSXin Li for (i = 0; i < SIMPLE_MATRIX_INPUT_SIZE; i++)
120*a58d3d2aSXin Li {
121*a58d3d2aSXin Li #ifdef FIXED_POINT
122*a58d3d2aSXin Li input_val16[i] = input_int16[i];
123*a58d3d2aSXin Li #else
124*a58d3d2aSXin Li input_val16[i] = (1/32768.f)*input_int16[i];
125*a58d3d2aSXin Li #endif
126*a58d3d2aSXin Li }
127*a58d3d2aSXin Li
128*a58d3d2aSXin Li /* _in_short */
129*a58d3d2aSXin Li for (i = 0; i < SIMPLE_MATRIX_OUTPUT_SIZE; i++)
130*a58d3d2aSXin Li output_val16[i] = 0;
131*a58d3d2aSXin Li for (i = 0; i < simple_matrix->rows; i++)
132*a58d3d2aSXin Li {
133*a58d3d2aSXin Li mapping_matrix_multiply_channel_in_short(simple_matrix,
134*a58d3d2aSXin Li input_int16, simple_matrix->cols, &output_val16[i], i,
135*a58d3d2aSXin Li simple_matrix->rows, SIMPLE_MATRIX_FRAME_SIZE);
136*a58d3d2aSXin Li }
137*a58d3d2aSXin Li ret = assert_is_equal(output_val16, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
138*a58d3d2aSXin Li if (ret)
139*a58d3d2aSXin Li test_failed();
140*a58d3d2aSXin Li
141*a58d3d2aSXin Li /* _out_short */
142*a58d3d2aSXin Li for (i = 0; i < SIMPLE_MATRIX_OUTPUT_SIZE; i++)
143*a58d3d2aSXin Li output_int16[i] = 0;
144*a58d3d2aSXin Li for (i = 0; i < simple_matrix->cols; i++)
145*a58d3d2aSXin Li {
146*a58d3d2aSXin Li mapping_matrix_multiply_channel_out_short(simple_matrix,
147*a58d3d2aSXin Li &input_val16[i], i, simple_matrix->cols, output_int16,
148*a58d3d2aSXin Li simple_matrix->rows, SIMPLE_MATRIX_FRAME_SIZE);
149*a58d3d2aSXin Li }
150*a58d3d2aSXin Li ret = assert_is_equal_short(output_int16, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
151*a58d3d2aSXin Li if (ret)
152*a58d3d2aSXin Li test_failed();
153*a58d3d2aSXin Li
154*a58d3d2aSXin Li #if !defined(DISABLE_FLOAT_API) && !defined(FIXED_POINT)
155*a58d3d2aSXin Li /* _in_float */
156*a58d3d2aSXin Li for (i = 0; i < SIMPLE_MATRIX_OUTPUT_SIZE; i++)
157*a58d3d2aSXin Li output_val16[i] = 0;
158*a58d3d2aSXin Li for (i = 0; i < simple_matrix->rows; i++)
159*a58d3d2aSXin Li {
160*a58d3d2aSXin Li mapping_matrix_multiply_channel_in_float(simple_matrix,
161*a58d3d2aSXin Li input_val16, simple_matrix->cols, &output_val16[i], i,
162*a58d3d2aSXin Li simple_matrix->rows, SIMPLE_MATRIX_FRAME_SIZE);
163*a58d3d2aSXin Li }
164*a58d3d2aSXin Li ret = assert_is_equal(output_val16, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
165*a58d3d2aSXin Li if (ret)
166*a58d3d2aSXin Li test_failed();
167*a58d3d2aSXin Li
168*a58d3d2aSXin Li /* _out_float */
169*a58d3d2aSXin Li for (i = 0; i < SIMPLE_MATRIX_OUTPUT_SIZE; i++)
170*a58d3d2aSXin Li output_val16[i] = 0;
171*a58d3d2aSXin Li for (i = 0; i < simple_matrix->cols; i++)
172*a58d3d2aSXin Li {
173*a58d3d2aSXin Li mapping_matrix_multiply_channel_out_float(simple_matrix,
174*a58d3d2aSXin Li &input_val16[i], i, simple_matrix->cols, output_val16,
175*a58d3d2aSXin Li simple_matrix->rows, SIMPLE_MATRIX_FRAME_SIZE);
176*a58d3d2aSXin Li }
177*a58d3d2aSXin Li ret = assert_is_equal(output_val16, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
178*a58d3d2aSXin Li if (ret)
179*a58d3d2aSXin Li test_failed();
180*a58d3d2aSXin Li #endif
181*a58d3d2aSXin Li
182*a58d3d2aSXin Li opus_free(input_val16);
183*a58d3d2aSXin Li opus_free(output_int16);
184*a58d3d2aSXin Li opus_free(output_val16);
185*a58d3d2aSXin Li opus_free(simple_matrix);
186*a58d3d2aSXin Li }
187*a58d3d2aSXin Li
test_creation_arguments(const int channels,const int mapping_family)188*a58d3d2aSXin Li void test_creation_arguments(const int channels, const int mapping_family)
189*a58d3d2aSXin Li {
190*a58d3d2aSXin Li int streams;
191*a58d3d2aSXin Li int coupled_streams;
192*a58d3d2aSXin Li int enc_error;
193*a58d3d2aSXin Li int dec_error;
194*a58d3d2aSXin Li int ret;
195*a58d3d2aSXin Li OpusProjectionEncoder *st_enc = NULL;
196*a58d3d2aSXin Li OpusProjectionDecoder *st_dec = NULL;
197*a58d3d2aSXin Li
198*a58d3d2aSXin Li const opus_int32 Fs = 48000;
199*a58d3d2aSXin Li const int application = OPUS_APPLICATION_AUDIO;
200*a58d3d2aSXin Li
201*a58d3d2aSXin Li int order_plus_one = (int)floor(sqrt((float)channels));
202*a58d3d2aSXin Li int nondiegetic_channels = channels - order_plus_one * order_plus_one;
203*a58d3d2aSXin Li
204*a58d3d2aSXin Li int is_channels_valid = 0;
205*a58d3d2aSXin Li int is_projection_valid = 0;
206*a58d3d2aSXin Li
207*a58d3d2aSXin Li st_enc = opus_projection_ambisonics_encoder_create(Fs, channels,
208*a58d3d2aSXin Li mapping_family, &streams, &coupled_streams, application, &enc_error);
209*a58d3d2aSXin Li if (st_enc != NULL)
210*a58d3d2aSXin Li {
211*a58d3d2aSXin Li opus_int32 matrix_size;
212*a58d3d2aSXin Li unsigned char *matrix;
213*a58d3d2aSXin Li
214*a58d3d2aSXin Li ret = opus_projection_encoder_ctl(st_enc,
215*a58d3d2aSXin Li OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST, &matrix_size);
216*a58d3d2aSXin Li if (ret != OPUS_OK || !matrix_size)
217*a58d3d2aSXin Li test_failed();
218*a58d3d2aSXin Li
219*a58d3d2aSXin Li matrix = (unsigned char *)opus_alloc(matrix_size);
220*a58d3d2aSXin Li ret = opus_projection_encoder_ctl(st_enc,
221*a58d3d2aSXin Li OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST, matrix, matrix_size);
222*a58d3d2aSXin Li
223*a58d3d2aSXin Li opus_projection_encoder_destroy(st_enc);
224*a58d3d2aSXin Li
225*a58d3d2aSXin Li st_dec = opus_projection_decoder_create(Fs, channels, streams,
226*a58d3d2aSXin Li coupled_streams, matrix, matrix_size, &dec_error);
227*a58d3d2aSXin Li if (st_dec != NULL)
228*a58d3d2aSXin Li {
229*a58d3d2aSXin Li opus_projection_decoder_destroy(st_dec);
230*a58d3d2aSXin Li }
231*a58d3d2aSXin Li opus_free(matrix);
232*a58d3d2aSXin Li }
233*a58d3d2aSXin Li
234*a58d3d2aSXin Li is_channels_valid = (order_plus_one >= 2 && order_plus_one <= 6) &&
235*a58d3d2aSXin Li (nondiegetic_channels == 0 || nondiegetic_channels == 2);
236*a58d3d2aSXin Li is_projection_valid = (enc_error == OPUS_OK && dec_error == OPUS_OK);
237*a58d3d2aSXin Li if (is_channels_valid ^ is_projection_valid)
238*a58d3d2aSXin Li {
239*a58d3d2aSXin Li fprintf(stderr, "Channels: %d, Family: %d\n", channels, mapping_family);
240*a58d3d2aSXin Li fprintf(stderr, "Order+1: %d, Non-diegetic Channels: %d\n",
241*a58d3d2aSXin Li order_plus_one, nondiegetic_channels);
242*a58d3d2aSXin Li fprintf(stderr, "Streams: %d, Coupled Streams: %d\n",
243*a58d3d2aSXin Li streams, coupled_streams);
244*a58d3d2aSXin Li test_failed();
245*a58d3d2aSXin Li }
246*a58d3d2aSXin Li }
247*a58d3d2aSXin Li
generate_music(short * buf,opus_int32 len,opus_int32 channels)248*a58d3d2aSXin Li void generate_music(short *buf, opus_int32 len, opus_int32 channels)
249*a58d3d2aSXin Li {
250*a58d3d2aSXin Li opus_int32 i,j,k;
251*a58d3d2aSXin Li opus_int32 *a,*b,*c,*d;
252*a58d3d2aSXin Li a = (opus_int32 *)malloc(sizeof(opus_int32) * channels);
253*a58d3d2aSXin Li b = (opus_int32 *)malloc(sizeof(opus_int32) * channels);
254*a58d3d2aSXin Li c = (opus_int32 *)malloc(sizeof(opus_int32) * channels);
255*a58d3d2aSXin Li d = (opus_int32 *)malloc(sizeof(opus_int32) * channels);
256*a58d3d2aSXin Li memset(a, 0, sizeof(opus_int32) * channels);
257*a58d3d2aSXin Li memset(b, 0, sizeof(opus_int32) * channels);
258*a58d3d2aSXin Li memset(c, 0, sizeof(opus_int32) * channels);
259*a58d3d2aSXin Li memset(d, 0, sizeof(opus_int32) * channels);
260*a58d3d2aSXin Li j=0;
261*a58d3d2aSXin Li
262*a58d3d2aSXin Li for(i=0;i<len;i++)
263*a58d3d2aSXin Li {
264*a58d3d2aSXin Li for(k=0;k<channels;k++)
265*a58d3d2aSXin Li {
266*a58d3d2aSXin Li opus_uint32 r;
267*a58d3d2aSXin Li opus_int32 v;
268*a58d3d2aSXin Li v=(((j*((j>>12)^((j>>10|j>>12)&26&j>>7)))&128)+128)<<15;
269*a58d3d2aSXin Li r=fast_rand();v+=r&65535;v-=r>>16;
270*a58d3d2aSXin Li b[k]=v-a[k]+((b[k]*61+32)>>6);a[k]=v;
271*a58d3d2aSXin Li c[k]=(30*(c[k]+b[k]+d[k])+32)>>6;d[k]=b[k];
272*a58d3d2aSXin Li v=(c[k]+128)>>8;
273*a58d3d2aSXin Li buf[i*channels+k]=v>32767?32767:(v<-32768?-32768:v);
274*a58d3d2aSXin Li if(i%6==0)j++;
275*a58d3d2aSXin Li }
276*a58d3d2aSXin Li }
277*a58d3d2aSXin Li
278*a58d3d2aSXin Li free(a);
279*a58d3d2aSXin Li free(b);
280*a58d3d2aSXin Li free(c);
281*a58d3d2aSXin Li free(d);
282*a58d3d2aSXin Li }
283*a58d3d2aSXin Li
test_encode_decode(opus_int32 bitrate,opus_int32 channels,const int mapping_family)284*a58d3d2aSXin Li void test_encode_decode(opus_int32 bitrate, opus_int32 channels,
285*a58d3d2aSXin Li const int mapping_family)
286*a58d3d2aSXin Li {
287*a58d3d2aSXin Li const opus_int32 Fs = 48000;
288*a58d3d2aSXin Li const int application = OPUS_APPLICATION_AUDIO;
289*a58d3d2aSXin Li
290*a58d3d2aSXin Li OpusProjectionEncoder *st_enc;
291*a58d3d2aSXin Li OpusProjectionDecoder *st_dec;
292*a58d3d2aSXin Li int streams;
293*a58d3d2aSXin Li int coupled;
294*a58d3d2aSXin Li int error;
295*a58d3d2aSXin Li short *buffer_in;
296*a58d3d2aSXin Li short *buffer_out;
297*a58d3d2aSXin Li unsigned char data[MAX_DATA_BYTES] = { 0 };
298*a58d3d2aSXin Li int len;
299*a58d3d2aSXin Li int out_samples;
300*a58d3d2aSXin Li opus_int32 matrix_size = 0;
301*a58d3d2aSXin Li unsigned char *matrix = NULL;
302*a58d3d2aSXin Li
303*a58d3d2aSXin Li buffer_in = (short *)malloc(sizeof(short) * BUFFER_SIZE * channels);
304*a58d3d2aSXin Li buffer_out = (short *)malloc(sizeof(short) * BUFFER_SIZE * channels);
305*a58d3d2aSXin Li
306*a58d3d2aSXin Li st_enc = opus_projection_ambisonics_encoder_create(Fs, channels,
307*a58d3d2aSXin Li mapping_family, &streams, &coupled, application, &error);
308*a58d3d2aSXin Li if (error != OPUS_OK) {
309*a58d3d2aSXin Li fprintf(stderr,
310*a58d3d2aSXin Li "Couldn\'t create encoder with %d channels and mapping family %d.\n",
311*a58d3d2aSXin Li channels, mapping_family);
312*a58d3d2aSXin Li free(buffer_in);
313*a58d3d2aSXin Li free(buffer_out);
314*a58d3d2aSXin Li test_failed();
315*a58d3d2aSXin Li }
316*a58d3d2aSXin Li
317*a58d3d2aSXin Li error = opus_projection_encoder_ctl(st_enc,
318*a58d3d2aSXin Li OPUS_SET_BITRATE(bitrate * 1000 * (streams + coupled)));
319*a58d3d2aSXin Li if (error != OPUS_OK)
320*a58d3d2aSXin Li {
321*a58d3d2aSXin Li goto bad_cleanup;
322*a58d3d2aSXin Li }
323*a58d3d2aSXin Li
324*a58d3d2aSXin Li error = opus_projection_encoder_ctl(st_enc,
325*a58d3d2aSXin Li OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST, &matrix_size);
326*a58d3d2aSXin Li if (error != OPUS_OK || !matrix_size)
327*a58d3d2aSXin Li {
328*a58d3d2aSXin Li goto bad_cleanup;
329*a58d3d2aSXin Li }
330*a58d3d2aSXin Li
331*a58d3d2aSXin Li matrix = (unsigned char *)opus_alloc(matrix_size);
332*a58d3d2aSXin Li error = opus_projection_encoder_ctl(st_enc,
333*a58d3d2aSXin Li OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST, matrix, matrix_size);
334*a58d3d2aSXin Li
335*a58d3d2aSXin Li st_dec = opus_projection_decoder_create(Fs, channels, streams, coupled,
336*a58d3d2aSXin Li matrix, matrix_size, &error);
337*a58d3d2aSXin Li opus_free(matrix);
338*a58d3d2aSXin Li
339*a58d3d2aSXin Li if (error != OPUS_OK) {
340*a58d3d2aSXin Li fprintf(stderr,
341*a58d3d2aSXin Li "Couldn\'t create decoder with %d channels, %d streams "
342*a58d3d2aSXin Li "and %d coupled streams.\n", channels, streams, coupled);
343*a58d3d2aSXin Li goto bad_cleanup;
344*a58d3d2aSXin Li }
345*a58d3d2aSXin Li
346*a58d3d2aSXin Li generate_music(buffer_in, BUFFER_SIZE, channels);
347*a58d3d2aSXin Li
348*a58d3d2aSXin Li len = opus_projection_encode(
349*a58d3d2aSXin Li st_enc, buffer_in, BUFFER_SIZE, data, MAX_DATA_BYTES);
350*a58d3d2aSXin Li if(len<0 || len>MAX_DATA_BYTES) {
351*a58d3d2aSXin Li fprintf(stderr,"opus_encode() returned %d\n", len);
352*a58d3d2aSXin Li goto bad_cleanup;
353*a58d3d2aSXin Li }
354*a58d3d2aSXin Li
355*a58d3d2aSXin Li out_samples = opus_projection_decode(
356*a58d3d2aSXin Li st_dec, data, len, buffer_out, MAX_FRAME_SAMPLES, 0);
357*a58d3d2aSXin Li if(out_samples!=BUFFER_SIZE) {
358*a58d3d2aSXin Li fprintf(stderr,"opus_decode() returned %d\n", out_samples);
359*a58d3d2aSXin Li goto bad_cleanup;
360*a58d3d2aSXin Li }
361*a58d3d2aSXin Li
362*a58d3d2aSXin Li opus_projection_decoder_destroy(st_dec);
363*a58d3d2aSXin Li opus_projection_encoder_destroy(st_enc);
364*a58d3d2aSXin Li free(buffer_in);
365*a58d3d2aSXin Li free(buffer_out);
366*a58d3d2aSXin Li return;
367*a58d3d2aSXin Li bad_cleanup:
368*a58d3d2aSXin Li free(buffer_in);
369*a58d3d2aSXin Li free(buffer_out);
370*a58d3d2aSXin Li test_failed();
371*a58d3d2aSXin Li }
372*a58d3d2aSXin Li
main(int _argc,char ** _argv)373*a58d3d2aSXin Li int main(int _argc, char **_argv)
374*a58d3d2aSXin Li {
375*a58d3d2aSXin Li unsigned int i;
376*a58d3d2aSXin Li
377*a58d3d2aSXin Li (void)_argc;
378*a58d3d2aSXin Li (void)_argv;
379*a58d3d2aSXin Li
380*a58d3d2aSXin Li /* Test simple matrix multiplication routines. */
381*a58d3d2aSXin Li test_simple_matrix();
382*a58d3d2aSXin Li
383*a58d3d2aSXin Li /* Test full range of channels in creation arguments. */
384*a58d3d2aSXin Li for (i = 0; i < 255; i++)
385*a58d3d2aSXin Li test_creation_arguments(i, 3);
386*a58d3d2aSXin Li
387*a58d3d2aSXin Li /* Test encode/decode pipeline. */
388*a58d3d2aSXin Li test_encode_decode(64 * 18, 18, 3);
389*a58d3d2aSXin Li
390*a58d3d2aSXin Li fprintf(stderr, "All projection tests passed.\n");
391*a58d3d2aSXin Li return 0;
392*a58d3d2aSXin Li }
393*a58d3d2aSXin Li
394