tarina

git clone https://git.tarina.org/tarina
Log | Files | Refs | README | LICENSE

common.h (7495B)


      1 /*
      2  * Copyright (C) 2013-2015 Intel Corporation
      3  *
      4  * This program is free software; you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation; either version 2 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  * GNU General Public License for more details.
     13  *
     14  */
     15 
     16 #define TEMP_RECORD_FILE_NAME		"/tmp/bat.wav.XXXXXX"
     17 #define DEFAULT_DEV_NAME		"default"
     18 
     19 #define OPT_BASE			300
     20 #define OPT_LOG				(OPT_BASE + 1)
     21 #define OPT_READFILE			(OPT_BASE + 2)
     22 #define OPT_SAVEPLAY			(OPT_BASE + 3)
     23 #define OPT_LOCAL			(OPT_BASE + 4)
     24 #define OPT_STANDALONE			(OPT_BASE + 5)
     25 #define OPT_ROUNDTRIPLATENCY		(OPT_BASE + 6)
     26 #define OPT_SNRTHD_DB			(OPT_BASE + 7)
     27 #define OPT_SNRTHD_PC			(OPT_BASE + 8)
     28 
     29 #define COMPOSE(a, b, c, d)		((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
     30 #define WAV_RIFF			COMPOSE('R', 'I', 'F', 'F')
     31 #define WAV_WAVE			COMPOSE('W', 'A', 'V', 'E')
     32 #define WAV_FMT				COMPOSE('f', 'm', 't', ' ')
     33 #define WAV_DATA			COMPOSE('d', 'a', 't', 'a')
     34 #define WAV_FORMAT_PCM			1	/* PCM WAVE file encoding */
     35 
     36 #define MAX_CHANNELS			2
     37 #define MIN_CHANNELS			1
     38 #define MAX_PEAKS			10
     39 #define MAX_FRAMES			(10 * 1024 * 1024)
     40 /* Given in ms */
     41 #define CAPTURE_DELAY			500
     42 /* signal frequency should be less than samplerate * RATE_FACTOR */
     43 #define RATE_FACTOR			0.4
     44 /* valid range of samplerate: (1 - RATE_RANGE, 1 + RATE_RANGE) * samplerate */
     45 #define RATE_RANGE			0.05
     46 /* Given in us */
     47 #define MAX_BUFFERTIME			500000
     48 /* devide factor, was 4, changed to 8 to remove reduce capture overrun */
     49 #define DIV_BUFFERTIME			8
     50 /* margin to avoid sign inversion when generate sine wav */
     51 #define RANGE_FACTOR			0.95
     52 #define MAX_BUFFERSIZE			200000
     53 #define MIN_BUFFERSIZE			32
     54 #define MAX_PERIODSIZE			200000
     55 #define MIN_PERIODSIZE			32
     56 /* default period size for tinyalsa */
     57 #define TINYALSA_PERIODSIZE			1024
     58 
     59 #define LATENCY_TEST_NUMBER			5
     60 #define LATENCY_TEST_TIME_LIMIT			25
     61 #define DIV_BUFFERSIZE			2
     62 
     63 #define EBATBASE			1000
     64 #define ENOPEAK				(EBATBASE + 1)
     65 #define EONLYDC				(EBATBASE + 2)
     66 #define EBADPEAK			(EBATBASE + 3)
     67 
     68 #define DC_THRESHOLD			7.01
     69 
     70 /* tolerance of detected peak = max (DELTA_HZ, DELTA_RATE * target_freq).
     71  * If DELTA_RATE is too high, BAT may not be able to recognize negative result;
     72  * if too low, BAT may be too sensitive and results in uncecessary failure. */
     73 #define DELTA_RATE			0.005
     74 #define DELTA_HZ			1
     75 
     76 #define FOUND_DC			(1<<1)
     77 #define FOUND_WRONG_PEAK		(1<<0)
     78 
     79 /* Truncate sample frames to (1 << N), for faster FFT analysis process. The
     80  * valid range of N is (SHIFT_MIN, SHIFT_MAX). When N increases, the analysis
     81  * will be more time-consuming, and the result will be more accurate. */
     82 #define SHIFT_MAX			(sizeof(int) * 8 - 2)
     83 #define SHIFT_MIN			8
     84 
     85 /* Define SNR range in dB.
     86  * if the noise is equal to signal, SNR = 0.0dB;
     87  * if the noise is zero, SNR is limited by RIFF wav data width:
     88  *     8 bit  -->  20.0 * log10f (powf(2.0, 8.0))  = 48.16 dB
     89  *    16 bit  -->  20.0 * log10f (powf(2.0, 16.0)) = 96.33 dB
     90  *    24 bit  -->  20.0 * log10f (powf(2.0, 24.0)) = 144.49 dB
     91  *    32 bit  -->  20.0 * log10f (powf(2.0, 32.0)) = 192.66 dB
     92  * so define the SNR range (0.0, 200.0) dB, value out of range is invalid. */
     93 #define SNR_DB_INVALID			-1.0
     94 #define SNR_DB_MIN			0.0
     95 #define SNR_DB_MAX			200.0
     96 
     97 static inline bool snr_is_valid(float db)
     98 {
     99 	return (db > SNR_DB_MIN && db < SNR_DB_MAX);
    100 }
    101 
    102 struct wav_header {
    103 	unsigned int magic; /* 'RIFF' */
    104 	unsigned int length; /* file len */
    105 	unsigned int type; /* 'WAVE' */
    106 };
    107 
    108 struct wav_chunk_header {
    109 	unsigned int type; /* 'data' */
    110 	unsigned int length; /* sample count */
    111 };
    112 
    113 struct wav_fmt {
    114 	unsigned int magic; /* 'FMT '*/
    115 	unsigned int fmt_size; /* 16 or 18 */
    116 	unsigned short format; /* see WAV_FMT_* */
    117 	unsigned short channels;
    118 	unsigned int sample_rate; /* Frequency of sample */
    119 	unsigned int bytes_p_second;
    120 	unsigned short blocks_align; /* sample size; 1 or 2 bytes */
    121 	unsigned short sample_length; /* 8, 12 or 16 bit */
    122 };
    123 
    124 struct chunk_fmt {
    125 	unsigned short format; /* see WAV_FMT_* */
    126 	unsigned short channels;
    127 	unsigned int sample_rate; /* Frequency of sample */
    128 	unsigned int bytes_p_second;
    129 	unsigned short blocks_align; /* sample size; 1 or 2 bytes */
    130 	unsigned short sample_length; /* 8, 12 or 16 bit */
    131 };
    132 
    133 struct wav_container {
    134 	struct wav_header header;
    135 	struct wav_fmt format;
    136 	struct wav_chunk_header chunk;
    137 };
    138 
    139 struct bat;
    140 
    141 enum _bat_pcm_format {
    142 	BAT_PCM_FORMAT_UNKNOWN = -1,
    143 	BAT_PCM_FORMAT_S16_LE = 0,
    144 	BAT_PCM_FORMAT_S32_LE,
    145 	BAT_PCM_FORMAT_U8,
    146 	BAT_PCM_FORMAT_S24_3LE,
    147 	BAT_PCM_FORMAT_MAX
    148 };
    149 
    150 enum _bat_op_mode {
    151 	MODE_UNKNOWN = -1,
    152 	MODE_SINGLE = 0,
    153 	MODE_LOOPBACK,
    154 	MODE_LAST
    155 };
    156 
    157 enum latency_state {
    158 	LATENCY_STATE_COMPLETE_FAILURE = -1,
    159 	LATENCY_STATE_COMPLETE_SUCCESS = 0,
    160 	LATENCY_STATE_MEASURE_FOR_1_SECOND,
    161 	LATENCY_STATE_PLAY_AND_LISTEN,
    162 	LATENCY_STATE_WAITING,
    163 };
    164 
    165 struct pcm {
    166 	unsigned int card_tiny;
    167 	unsigned int device_tiny;
    168 	char *device;
    169 	char *file;
    170 	enum _bat_op_mode mode;
    171 	void *(*fct)(struct bat *);
    172 };
    173 
    174 struct sin_generator;
    175 
    176 struct sin_generator {
    177 	double state_real;
    178 	double state_imag;
    179 	double phasor_real;
    180 	double phasor_imag;
    181 	float frequency;
    182 	float sample_rate;
    183 	float magnitude;
    184 };
    185 
    186 struct roundtrip_latency {
    187 	int number;
    188 	enum latency_state state;
    189 	float result[LATENCY_TEST_NUMBER];
    190 	int final_result;
    191 	int samples;
    192 	float sum;
    193 	int threshold;
    194 	int error;
    195 	bool is_capturing;
    196 	bool is_playing;
    197 	bool xrun_error;
    198 };
    199 
    200 struct noise_analyzer {
    201 	int nsamples;			/* number of sample */
    202 	float *source;			/* single-tone to be analyzed */
    203 	float *target;			/* target single-tone as standard */
    204 	float rms_tgt;			/* rms of target single-tone */
    205 	float snr_db;			/* snr in dB */
    206 };
    207 
    208 struct bat {
    209 	unsigned int rate;		/* sampling rate */
    210 	int channels;			/* nb of channels */
    211 	int frames;			/* nb of frames */
    212 	int frame_size;			/* size of frame */
    213 	int sample_size;		/* size of sample */
    214 	enum _bat_pcm_format format;	/* PCM format */
    215 	int buffer_size;		/* buffer size in frames */
    216 	int period_size;		/* period size in frames */
    217 
    218 	float sigma_k;			/* threshold for peak detection */
    219 	float snr_thd_db;		/* threshold for noise detection (dB) */
    220 	float target_freq[MAX_CHANNELS];
    221 
    222 	int sinus_duration;		/* number of frames for playback */
    223 	char *narg;			/* argument string of duration */
    224 	char *logarg;			/* path name of log file */
    225 	char *debugplay;		/* path name to store playback signal */
    226 	bool standalone;		/* enable to bypass analysis */
    227 	bool roundtriplatency;		/* enable round trip latency */
    228 
    229 	struct pcm playback;
    230 	struct pcm capture;
    231 	struct roundtrip_latency latency;
    232 
    233 	unsigned int periods_played;
    234 	unsigned int periods_total;
    235 	bool period_is_limited;
    236 
    237 	FILE *fp;
    238 
    239 	FILE *log;
    240 	FILE *err;
    241 
    242 	void (*convert_sample_to_float)(void *, float *, int);
    243 	void (*convert_float_to_sample)(float *, void *, int, int);
    244 
    245 	void *buf;			/* PCM Buffer */
    246 
    247 	bool local;			/* true for internal test */
    248 };
    249 
    250 struct analyze {
    251 	void *buf;
    252 	float *in;
    253 	float *out;
    254 	float *mag;
    255 };
    256 
    257 void prepare_wav_info(struct wav_container *, struct bat *);
    258 int read_wav_header(struct bat *, char *, FILE *, bool);
    259 int write_wav_header(FILE *, struct wav_container *, struct bat *);
    260 int update_wav_header(struct bat *, FILE *, int);
    261 int generate_input_data(struct bat *, void *, int, int);