1b815c7f3Sopenharmony_ci/*
2b815c7f3Sopenharmony_ci** Copyright (C) 1999-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
3b815c7f3Sopenharmony_ci**
4b815c7f3Sopenharmony_ci** This program is free software; you can redistribute it and/or modify
5b815c7f3Sopenharmony_ci** it under the terms of the GNU General Public License as published by
6b815c7f3Sopenharmony_ci** the Free Software Foundation; either version 2 of the License, or
7b815c7f3Sopenharmony_ci** (at your option) any later version.
8b815c7f3Sopenharmony_ci**
9b815c7f3Sopenharmony_ci** This program is distributed in the hope that it will be useful,
10b815c7f3Sopenharmony_ci** but WITHOUT ANY WARRANTY; without even the implied warranty of
11b815c7f3Sopenharmony_ci** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12b815c7f3Sopenharmony_ci** GNU General Public License for more details.
13b815c7f3Sopenharmony_ci**
14b815c7f3Sopenharmony_ci** You should have received a copy of the GNU General Public License
15b815c7f3Sopenharmony_ci** along with this program; if not, write to the Free Software
16b815c7f3Sopenharmony_ci** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17b815c7f3Sopenharmony_ci*/
18b815c7f3Sopenharmony_ci
19b815c7f3Sopenharmony_ci#include "sfconfig.h"
20b815c7f3Sopenharmony_ci
21b815c7f3Sopenharmony_ci#include <stdio.h>
22b815c7f3Sopenharmony_ci#if HAVE_UNISTD_H
23b815c7f3Sopenharmony_ci#include <unistd.h>
24b815c7f3Sopenharmony_ci#else
25b815c7f3Sopenharmony_ci#include "sf_unistd.h"
26b815c7f3Sopenharmony_ci#endif
27b815c7f3Sopenharmony_ci#include <stdlib.h>
28b815c7f3Sopenharmony_ci#include <string.h>
29b815c7f3Sopenharmony_ci#include <math.h>
30b815c7f3Sopenharmony_ci
31b815c7f3Sopenharmony_ci#include "g72x.h"
32b815c7f3Sopenharmony_ci#include "g72x_priv.h"
33b815c7f3Sopenharmony_ci
34b815c7f3Sopenharmony_ci#ifndef		M_PI
35b815c7f3Sopenharmony_ci#define		M_PI		3.14159265358979323846264338
36b815c7f3Sopenharmony_ci#endif
37b815c7f3Sopenharmony_ci
38b815c7f3Sopenharmony_ci#define		BUFFER_SIZE		(1 << 14)
39b815c7f3Sopenharmony_ci#define		SAMPLE_RATE		11025
40b815c7f3Sopenharmony_ci
41b815c7f3Sopenharmony_ci
42b815c7f3Sopenharmony_cistatic void g721_test	(void) ;
43b815c7f3Sopenharmony_cistatic void g723_test	(double margin) ;
44b815c7f3Sopenharmony_ci
45b815c7f3Sopenharmony_cistatic void	gen_signal_double (double *data, double scale, int datalen) ;
46b815c7f3Sopenharmony_cistatic int error_function (double data, double orig, double margin) ;
47b815c7f3Sopenharmony_ci
48b815c7f3Sopenharmony_cistatic int	oct_save_short	(short *a, short *b, int len) ;
49b815c7f3Sopenharmony_ci
50b815c7f3Sopenharmony_ciint
51b815c7f3Sopenharmony_cimain (int argc, char *argv [])
52b815c7f3Sopenharmony_ci{	int		bDoAll = 0 ;
53b815c7f3Sopenharmony_ci	int		nTests = 0 ;
54b815c7f3Sopenharmony_ci
55b815c7f3Sopenharmony_ci	if (argc != 2)
56b815c7f3Sopenharmony_ci	{	printf ("Usage : %s <test>\n", argv [0]) ;
57b815c7f3Sopenharmony_ci		printf ("    Where <test> is one of the following:\n") ;
58b815c7f3Sopenharmony_ci		printf ("           g721  - test G721 encoder and decoder\n") ;
59b815c7f3Sopenharmony_ci		printf ("           g723  - test G721 encoder and decoder\n") ;
60b815c7f3Sopenharmony_ci		printf ("           all   - perform all tests\n") ;
61b815c7f3Sopenharmony_ci		exit (1) ;
62b815c7f3Sopenharmony_ci		} ;
63b815c7f3Sopenharmony_ci
64b815c7f3Sopenharmony_ci	bDoAll = !strcmp (argv [1], "all") ;
65b815c7f3Sopenharmony_ci
66b815c7f3Sopenharmony_ci	if (bDoAll || ! strcmp (argv [1], "g721"))
67b815c7f3Sopenharmony_ci	{	g721_test	() ;
68b815c7f3Sopenharmony_ci		nTests++ ;
69b815c7f3Sopenharmony_ci		} ;
70b815c7f3Sopenharmony_ci
71b815c7f3Sopenharmony_ci	if (bDoAll || ! strcmp (argv [1], "g723"))
72b815c7f3Sopenharmony_ci	{	g723_test	(0.53) ;
73b815c7f3Sopenharmony_ci		nTests++ ;
74b815c7f3Sopenharmony_ci		} ;
75b815c7f3Sopenharmony_ci
76b815c7f3Sopenharmony_ci	if (nTests == 0)
77b815c7f3Sopenharmony_ci	{	printf ("Mono : ************************************\n") ;
78b815c7f3Sopenharmony_ci		printf ("Mono : *  No '%s' test defined.\n", argv [1]) ;
79b815c7f3Sopenharmony_ci		printf ("Mono : ************************************\n") ;
80b815c7f3Sopenharmony_ci		return 1 ;
81b815c7f3Sopenharmony_ci		} ;
82b815c7f3Sopenharmony_ci
83b815c7f3Sopenharmony_ci	return 0 ;
84b815c7f3Sopenharmony_ci} /* main */
85b815c7f3Sopenharmony_ci
86b815c7f3Sopenharmony_cistatic void
87b815c7f3Sopenharmony_cig721_test	(void)
88b815c7f3Sopenharmony_ci{
89b815c7f3Sopenharmony_ci	return ;
90b815c7f3Sopenharmony_ci} /* g721_test */
91b815c7f3Sopenharmony_ci
92b815c7f3Sopenharmony_cistatic void
93b815c7f3Sopenharmony_cig723_test	(double margin)
94b815c7f3Sopenharmony_ci{	static double	orig_buffer [BUFFER_SIZE] ;
95b815c7f3Sopenharmony_ci	static short 	orig [BUFFER_SIZE] ;
96b815c7f3Sopenharmony_ci	static short 	data [BUFFER_SIZE] ;
97b815c7f3Sopenharmony_ci
98b815c7f3Sopenharmony_ci	G72x_STATE encoder_state, decoder_state ;
99b815c7f3Sopenharmony_ci
100b815c7f3Sopenharmony_ci	long	k ;
101b815c7f3Sopenharmony_ci	int 	code, position, max_err ;
102b815c7f3Sopenharmony_ci
103b815c7f3Sopenharmony_ci	private_init_state (&encoder_state) ;
104b815c7f3Sopenharmony_ci	encoder_state.encoder = g723_24_encoder ;
105b815c7f3Sopenharmony_ci	encoder_state.codec_bits = 3 ;
106b815c7f3Sopenharmony_ci
107b815c7f3Sopenharmony_ci	private_init_state (&decoder_state) ;
108b815c7f3Sopenharmony_ci	decoder_state.decoder = g723_24_decoder ;
109b815c7f3Sopenharmony_ci	decoder_state.codec_bits = 3 ;
110b815c7f3Sopenharmony_ci
111b815c7f3Sopenharmony_ci	memset (data, 0, BUFFER_SIZE * sizeof (short)) ;
112b815c7f3Sopenharmony_ci	memset (orig, 0, BUFFER_SIZE * sizeof (short)) ;
113b815c7f3Sopenharmony_ci
114b815c7f3Sopenharmony_ci	printf ("    g723_test    : ") ;
115b815c7f3Sopenharmony_ci	fflush (stdout) ;
116b815c7f3Sopenharmony_ci
117b815c7f3Sopenharmony_ci	gen_signal_double (orig_buffer, 32000.0, BUFFER_SIZE) ;
118b815c7f3Sopenharmony_ci	for (k = 0 ; k < BUFFER_SIZE ; k++)
119b815c7f3Sopenharmony_ci		orig [k] = (short) orig_buffer [k] ;
120b815c7f3Sopenharmony_ci
121b815c7f3Sopenharmony_ci	/* Write and read data here. */
122b815c7f3Sopenharmony_ci	position = 0 ;
123b815c7f3Sopenharmony_ci	max_err = 0 ;
124b815c7f3Sopenharmony_ci	for (k = 0 ; k < BUFFER_SIZE ; k++)
125b815c7f3Sopenharmony_ci	{	code = encoder_state.encoder (orig [k], &encoder_state) ;
126b815c7f3Sopenharmony_ci		data [k] = decoder_state.decoder (code, &decoder_state) ;
127b815c7f3Sopenharmony_ci		if (abs (orig [k] - data [k]) > max_err)
128b815c7f3Sopenharmony_ci		{	position = k ;
129b815c7f3Sopenharmony_ci			max_err = abs (orig [k] - data [k]) ;
130b815c7f3Sopenharmony_ci			} ;
131b815c7f3Sopenharmony_ci		} ;
132b815c7f3Sopenharmony_ci
133b815c7f3Sopenharmony_ci	printf ("\n\nMax error of %d at postion %d.\n", max_err, position) ;
134b815c7f3Sopenharmony_ci
135b815c7f3Sopenharmony_ci	for (k = 0 ; k < BUFFER_SIZE ; k++)
136b815c7f3Sopenharmony_ci	{	if (error_function (data [k], orig [k], margin))
137b815c7f3Sopenharmony_ci		{	printf ("Line %d: Incorrect sample A (#%ld : %d should be %d).\n", __LINE__, k, data [k], orig [k]) ;
138b815c7f3Sopenharmony_ci			oct_save_short (orig, data, BUFFER_SIZE) ;
139b815c7f3Sopenharmony_ci			exit (1) ;
140b815c7f3Sopenharmony_ci			} ;
141b815c7f3Sopenharmony_ci		} ;
142b815c7f3Sopenharmony_ci
143b815c7f3Sopenharmony_ci
144b815c7f3Sopenharmony_ci	printf ("ok\n") ;
145b815c7f3Sopenharmony_ci
146b815c7f3Sopenharmony_ci	return ;
147b815c7f3Sopenharmony_ci} /* g723_test */
148b815c7f3Sopenharmony_ci
149b815c7f3Sopenharmony_ci
150b815c7f3Sopenharmony_ci#define		SIGNAL_MAXVAL	30000.0
151b815c7f3Sopenharmony_ci#define		DECAY_COUNT		1000
152b815c7f3Sopenharmony_ci
153b815c7f3Sopenharmony_cistatic void
154b815c7f3Sopenharmony_cigen_signal_double (double *gendata, double scale, int gendatalen)
155b815c7f3Sopenharmony_ci{	int		k, ramplen ;
156b815c7f3Sopenharmony_ci	double	amp = 0.0 ;
157b815c7f3Sopenharmony_ci
158b815c7f3Sopenharmony_ci	ramplen = DECAY_COUNT ;
159b815c7f3Sopenharmony_ci
160b815c7f3Sopenharmony_ci	for (k = 0 ; k < gendatalen ; k++)
161b815c7f3Sopenharmony_ci	{	if (k <= ramplen)
162b815c7f3Sopenharmony_ci			amp = scale * k / ((double) ramplen) ;
163b815c7f3Sopenharmony_ci		else if (k > gendatalen - ramplen)
164b815c7f3Sopenharmony_ci			amp = scale * (gendatalen - k) / ((double) ramplen) ;
165b815c7f3Sopenharmony_ci
166b815c7f3Sopenharmony_ci		gendata [k] = amp * (0.4 * sin (33.3 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))
167b815c7f3Sopenharmony_ci						+ 0.3 * cos (201.1 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))) ;
168b815c7f3Sopenharmony_ci		} ;
169b815c7f3Sopenharmony_ci
170b815c7f3Sopenharmony_ci	return ;
171b815c7f3Sopenharmony_ci} /* gen_signal_double */
172b815c7f3Sopenharmony_ci
173b815c7f3Sopenharmony_cistatic int
174b815c7f3Sopenharmony_cierror_function (double data, double orig, double margin)
175b815c7f3Sopenharmony_ci{	double error ;
176b815c7f3Sopenharmony_ci
177b815c7f3Sopenharmony_ci	if (fabs (orig) <= 500.0)
178b815c7f3Sopenharmony_ci		error = fabs (fabs (data) - fabs (orig)) / 2000.0 ;
179b815c7f3Sopenharmony_ci	else if (fabs (orig) <= 1000.0)
180b815c7f3Sopenharmony_ci		error = fabs (data - orig) / 3000.0 ;
181b815c7f3Sopenharmony_ci	else
182b815c7f3Sopenharmony_ci		error = fabs (data - orig) / fabs (orig) ;
183b815c7f3Sopenharmony_ci
184b815c7f3Sopenharmony_ci	if (error > margin)
185b815c7f3Sopenharmony_ci	{	printf ("\n\n*******************\nError : %f\n", error) ;
186b815c7f3Sopenharmony_ci		return 1 ;
187b815c7f3Sopenharmony_ci		} ;
188b815c7f3Sopenharmony_ci	return 0 ;
189b815c7f3Sopenharmony_ci} /* error_function */
190b815c7f3Sopenharmony_ci
191b815c7f3Sopenharmony_cistatic int
192b815c7f3Sopenharmony_cioct_save_short	(short *a, short *b, int len)
193b815c7f3Sopenharmony_ci{	FILE 	*file ;
194b815c7f3Sopenharmony_ci	int		k ;
195b815c7f3Sopenharmony_ci
196b815c7f3Sopenharmony_ci	if (! (file = fopen ("error.dat", "w")))
197b815c7f3Sopenharmony_ci		return 1 ;
198b815c7f3Sopenharmony_ci
199b815c7f3Sopenharmony_ci	fprintf (file, "# Not created by Octave\n") ;
200b815c7f3Sopenharmony_ci
201b815c7f3Sopenharmony_ci	fprintf (file, "# name: a\n") ;
202b815c7f3Sopenharmony_ci	fprintf (file, "# type: matrix\n") ;
203b815c7f3Sopenharmony_ci	fprintf (file, "# rows: %d\n", len) ;
204b815c7f3Sopenharmony_ci	fprintf (file, "# columns: 1\n") ;
205b815c7f3Sopenharmony_ci
206b815c7f3Sopenharmony_ci	for (k = 0 ; k < len ; k++)
207b815c7f3Sopenharmony_ci		fprintf (file, "% d\n", a [k]) ;
208b815c7f3Sopenharmony_ci
209b815c7f3Sopenharmony_ci	fprintf (file, "# name: b\n") ;
210b815c7f3Sopenharmony_ci	fprintf (file, "# type: matrix\n") ;
211b815c7f3Sopenharmony_ci	fprintf (file, "# rows: %d\n", len) ;
212b815c7f3Sopenharmony_ci	fprintf (file, "# columns: 1\n") ;
213b815c7f3Sopenharmony_ci
214b815c7f3Sopenharmony_ci	for (k = 0 ; k < len ; k++)
215b815c7f3Sopenharmony_ci		fprintf (file, "% d\n", b [k]) ;
216b815c7f3Sopenharmony_ci
217b815c7f3Sopenharmony_ci	fclose (file) ;
218b815c7f3Sopenharmony_ci	return 0 ;
219b815c7f3Sopenharmony_ci} /* oct_save_short */
220b815c7f3Sopenharmony_ci
221