Blame bat/common.h

Packit Service a9274b
/*
Packit Service a9274b
 * Copyright (C) 2013-2015 Intel Corporation
Packit Service a9274b
 *
Packit Service a9274b
 * This program is free software; you can redistribute it and/or modify
Packit Service a9274b
 * it under the terms of the GNU General Public License as published by
Packit Service a9274b
 * the Free Software Foundation; either version 2 of the License, or
Packit Service a9274b
 * (at your option) any later version.
Packit Service a9274b
 *
Packit Service a9274b
 * This program is distributed in the hope that it will be useful,
Packit Service a9274b
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service a9274b
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service a9274b
 * GNU General Public License for more details.
Packit Service a9274b
 *
Packit Service a9274b
 */
Packit Service a9274b
Packit Service a9274b
#define TEMP_RECORD_FILE_NAME		"/tmp/bat.wav.XXXXXX"
Packit Service a9274b
#define DEFAULT_DEV_NAME		"default"
Packit Service a9274b
Packit Service a9274b
#define OPT_BASE			300
Packit Service a9274b
#define OPT_LOG				(OPT_BASE + 1)
Packit Service a9274b
#define OPT_READFILE			(OPT_BASE + 2)
Packit Service a9274b
#define OPT_SAVEPLAY			(OPT_BASE + 3)
Packit Service a9274b
#define OPT_LOCAL			(OPT_BASE + 4)
Packit Service a9274b
#define OPT_STANDALONE			(OPT_BASE + 5)
Packit Service a9274b
#define OPT_ROUNDTRIPLATENCY		(OPT_BASE + 6)
Packit Service a9274b
#define OPT_SNRTHD_DB			(OPT_BASE + 7)
Packit Service a9274b
#define OPT_SNRTHD_PC			(OPT_BASE + 8)
Packit Service a9274b
Packit Service a9274b
#define COMPOSE(a, b, c, d)		((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
Packit Service a9274b
#define WAV_RIFF			COMPOSE('R', 'I', 'F', 'F')
Packit Service a9274b
#define WAV_WAVE			COMPOSE('W', 'A', 'V', 'E')
Packit Service a9274b
#define WAV_FMT				COMPOSE('f', 'm', 't', ' ')
Packit Service a9274b
#define WAV_DATA			COMPOSE('d', 'a', 't', 'a')
Packit Service a9274b
#define WAV_FORMAT_PCM			1	/* PCM WAVE file encoding */
Packit Service a9274b
Packit Service a9274b
#define MAX_CHANNELS			2
Packit Service a9274b
#define MIN_CHANNELS			1
Packit Service a9274b
#define MAX_PEAKS			10
Packit Service a9274b
#define MAX_FRAMES			(10 * 1024 * 1024)
Packit Service a9274b
/* Given in ms */
Packit Service a9274b
#define CAPTURE_DELAY			500
Packit Service a9274b
/* signal frequency should be less than samplerate * RATE_FACTOR */
Packit Service a9274b
#define RATE_FACTOR			0.4
Packit Service a9274b
/* valid range of samplerate: (1 - RATE_RANGE, 1 + RATE_RANGE) * samplerate */
Packit Service a9274b
#define RATE_RANGE			0.05
Packit Service a9274b
/* Given in us */
Packit Service a9274b
#define MAX_BUFFERTIME			500000
Packit Service a9274b
/* devide factor, was 4, changed to 8 to remove reduce capture overrun */
Packit Service a9274b
#define DIV_BUFFERTIME			8
Packit Service a9274b
/* margin to avoid sign inversion when generate sine wav */
Packit Service a9274b
#define RANGE_FACTOR			0.95
Packit Service a9274b
#define MAX_BUFFERSIZE			200000
Packit Service a9274b
#define MIN_BUFFERSIZE			32
Packit Service a9274b
#define MAX_PERIODSIZE			200000
Packit Service a9274b
#define MIN_PERIODSIZE			32
Packit Service a9274b
/* default period size for tinyalsa */
Packit Service a9274b
#define TINYALSA_PERIODSIZE			1024
Packit Service a9274b
Packit Service a9274b
#define LATENCY_TEST_NUMBER			5
Packit Service a9274b
#define LATENCY_TEST_TIME_LIMIT			25
Packit Service a9274b
#define DIV_BUFFERSIZE			2
Packit Service a9274b
Packit Service a9274b
#define EBATBASE			1000
Packit Service a9274b
#define ENOPEAK				(EBATBASE + 1)
Packit Service a9274b
#define EONLYDC				(EBATBASE + 2)
Packit Service a9274b
#define EBADPEAK			(EBATBASE + 3)
Packit Service a9274b
Packit Service a9274b
#define DC_THRESHOLD			7.01
Packit Service a9274b
Packit Service a9274b
/* tolerance of detected peak = max (DELTA_HZ, DELTA_RATE * target_freq).
Packit Service a9274b
 * If DELTA_RATE is too high, BAT may not be able to recognize negative result;
Packit Service a9274b
 * if too low, BAT may be too sensitive and results in uncecessary failure. */
Packit Service a9274b
#define DELTA_RATE			0.005
Packit Service a9274b
#define DELTA_HZ			1
Packit Service a9274b
Packit Service a9274b
#define FOUND_DC			(1<<1)
Packit Service a9274b
#define FOUND_WRONG_PEAK		(1<<0)
Packit Service a9274b
Packit Service a9274b
/* Truncate sample frames to (1 << N), for faster FFT analysis process. The
Packit Service a9274b
 * valid range of N is (SHIFT_MIN, SHIFT_MAX). When N increases, the analysis
Packit Service a9274b
 * will be more time-consuming, and the result will be more accurate. */
Packit Service a9274b
#define SHIFT_MAX			(sizeof(int) * 8 - 2)
Packit Service a9274b
#define SHIFT_MIN			8
Packit Service a9274b
Packit Service a9274b
/* Define SNR range in dB.
Packit Service a9274b
 * if the noise is equal to signal, SNR = 0.0dB;
Packit Service a9274b
 * if the noise is zero, SNR is limited by RIFF wav data width:
Packit Service a9274b
 *     8 bit  -->  20.0 * log10f (powf(2.0, 8.0))  = 48.16 dB
Packit Service a9274b
 *    16 bit  -->  20.0 * log10f (powf(2.0, 16.0)) = 96.33 dB
Packit Service a9274b
 *    24 bit  -->  20.0 * log10f (powf(2.0, 24.0)) = 144.49 dB
Packit Service a9274b
 *    32 bit  -->  20.0 * log10f (powf(2.0, 32.0)) = 192.66 dB
Packit Service a9274b
 * so define the SNR range (0.0, 200.0) dB, value out of range is invalid. */
Packit Service a9274b
#define SNR_DB_INVALID			-1.0
Packit Service a9274b
#define SNR_DB_MIN			0.0
Packit Service a9274b
#define SNR_DB_MAX			200.0
Packit Service a9274b
Packit Service a9274b
static inline bool snr_is_valid(float db)
Packit Service a9274b
{
Packit Service a9274b
	return (db > SNR_DB_MIN && db < SNR_DB_MAX);
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
struct wav_header {
Packit Service a9274b
	unsigned int magic; /* 'RIFF' */
Packit Service a9274b
	unsigned int length; /* file len */
Packit Service a9274b
	unsigned int type; /* 'WAVE' */
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
struct wav_chunk_header {
Packit Service a9274b
	unsigned int type; /* 'data' */
Packit Service a9274b
	unsigned int length; /* sample count */
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
struct wav_fmt {
Packit Service a9274b
	unsigned int magic; /* 'FMT '*/
Packit Service a9274b
	unsigned int fmt_size; /* 16 or 18 */
Packit Service a9274b
	unsigned short format; /* see WAV_FMT_* */
Packit Service a9274b
	unsigned short channels;
Packit Service a9274b
	unsigned int sample_rate; /* Frequency of sample */
Packit Service a9274b
	unsigned int bytes_p_second;
Packit Service a9274b
	unsigned short blocks_align; /* sample size; 1 or 2 bytes */
Packit Service a9274b
	unsigned short sample_length; /* 8, 12 or 16 bit */
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
struct chunk_fmt {
Packit Service a9274b
	unsigned short format; /* see WAV_FMT_* */
Packit Service a9274b
	unsigned short channels;
Packit Service a9274b
	unsigned int sample_rate; /* Frequency of sample */
Packit Service a9274b
	unsigned int bytes_p_second;
Packit Service a9274b
	unsigned short blocks_align; /* sample size; 1 or 2 bytes */
Packit Service a9274b
	unsigned short sample_length; /* 8, 12 or 16 bit */
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
struct wav_container {
Packit Service a9274b
	struct wav_header header;
Packit Service a9274b
	struct wav_fmt format;
Packit Service a9274b
	struct wav_chunk_header chunk;
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
struct bat;
Packit Service a9274b
Packit Service a9274b
enum _bat_pcm_format {
Packit Service a9274b
	BAT_PCM_FORMAT_UNKNOWN = -1,
Packit Service a9274b
	BAT_PCM_FORMAT_S16_LE = 0,
Packit Service a9274b
	BAT_PCM_FORMAT_S32_LE,
Packit Service a9274b
	BAT_PCM_FORMAT_U8,
Packit Service a9274b
	BAT_PCM_FORMAT_S24_3LE,
Packit Service a9274b
	BAT_PCM_FORMAT_MAX
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
enum _bat_op_mode {
Packit Service a9274b
	MODE_UNKNOWN = -1,
Packit Service a9274b
	MODE_SINGLE = 0,
Packit Service a9274b
	MODE_LOOPBACK,
Packit Service a9274b
	MODE_LAST
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
enum latency_state {
Packit Service a9274b
	LATENCY_STATE_COMPLETE_FAILURE = -1,
Packit Service a9274b
	LATENCY_STATE_COMPLETE_SUCCESS = 0,
Packit Service a9274b
	LATENCY_STATE_MEASURE_FOR_1_SECOND,
Packit Service a9274b
	LATENCY_STATE_PLAY_AND_LISTEN,
Packit Service a9274b
	LATENCY_STATE_WAITING,
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
struct pcm {
Packit Service a9274b
	unsigned int card_tiny;
Packit Service a9274b
	unsigned int device_tiny;
Packit Service a9274b
	char *device;
Packit Service a9274b
	char *file;
Packit Service a9274b
	enum _bat_op_mode mode;
Packit Service a9274b
	void *(*fct)(struct bat *);
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
struct sin_generator;
Packit Service a9274b
Packit Service a9274b
struct sin_generator {
Packit Service a9274b
	double state_real;
Packit Service a9274b
	double state_imag;
Packit Service a9274b
	double phasor_real;
Packit Service a9274b
	double phasor_imag;
Packit Service a9274b
	float frequency;
Packit Service a9274b
	float sample_rate;
Packit Service a9274b
	float magnitude;
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
struct roundtrip_latency {
Packit Service a9274b
	int number;
Packit Service a9274b
	enum latency_state state;
Packit Service a9274b
	float result[LATENCY_TEST_NUMBER];
Packit Service a9274b
	int final_result;
Packit Service a9274b
	int samples;
Packit Service a9274b
	float sum;
Packit Service a9274b
	int threshold;
Packit Service a9274b
	int error;
Packit Service a9274b
	bool is_capturing;
Packit Service a9274b
	bool is_playing;
Packit Service a9274b
	bool xrun_error;
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
struct noise_analyzer {
Packit Service a9274b
	int nsamples;			/* number of sample */
Packit Service a9274b
	float *source;			/* single-tone to be analyzed */
Packit Service a9274b
	float *target;			/* target single-tone as standard */
Packit Service a9274b
	float rms_tgt;			/* rms of target single-tone */
Packit Service a9274b
	float snr_db;			/* snr in dB */
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
struct bat {
Packit Service a9274b
	unsigned int rate;		/* sampling rate */
Packit Service a9274b
	int channels;			/* nb of channels */
Packit Service a9274b
	int frames;			/* nb of frames */
Packit Service a9274b
	int frame_size;			/* size of frame */
Packit Service a9274b
	int sample_size;		/* size of sample */
Packit Service a9274b
	enum _bat_pcm_format format;	/* PCM format */
Packit Service a9274b
	int buffer_size;		/* buffer size in frames */
Packit Service a9274b
	int period_size;		/* period size in frames */
Packit Service a9274b
Packit Service a9274b
	float sigma_k;			/* threshold for peak detection */
Packit Service a9274b
	float snr_thd_db;		/* threshold for noise detection (dB) */
Packit Service a9274b
	float target_freq[MAX_CHANNELS];
Packit Service a9274b
Packit Service a9274b
	int sinus_duration;		/* number of frames for playback */
Packit Service a9274b
	char *narg;			/* argument string of duration */
Packit Service a9274b
	char *logarg;			/* path name of log file */
Packit Service a9274b
	char *debugplay;		/* path name to store playback signal */
Packit Service a9274b
	bool standalone;		/* enable to bypass analysis */
Packit Service a9274b
	bool roundtriplatency;		/* enable round trip latency */
Packit Service a9274b
Packit Service a9274b
	struct pcm playback;
Packit Service a9274b
	struct pcm capture;
Packit Service a9274b
	struct roundtrip_latency latency;
Packit Service a9274b
Packit Service a9274b
	unsigned int periods_played;
Packit Service a9274b
	unsigned int periods_total;
Packit Service a9274b
	bool period_is_limited;
Packit Service a9274b
Packit Service a9274b
	FILE *fp;
Packit Service a9274b
Packit Service a9274b
	FILE *log;
Packit Service a9274b
	FILE *err;
Packit Service a9274b
Packit Service a9274b
	void (*convert_sample_to_float)(void *, float *, int);
Packit Service a9274b
	void (*convert_float_to_sample)(float *, void *, int, int);
Packit Service a9274b
Packit Service a9274b
	void *buf;			/* PCM Buffer */
Packit Service a9274b
Packit Service a9274b
	bool local;			/* true for internal test */
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
struct analyze {
Packit Service a9274b
	void *buf;
Packit Service a9274b
	float *in;
Packit Service a9274b
	float *out;
Packit Service a9274b
	float *mag;
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
void prepare_wav_info(struct wav_container *, struct bat *);
Packit Service a9274b
int read_wav_header(struct bat *, char *, FILE *, bool);
Packit Service a9274b
int write_wav_header(FILE *, struct wav_container *, struct bat *);
Packit Service a9274b
int update_wav_header(struct bat *, FILE *, int);
Packit Service a9274b
int generate_input_data(struct bat *, void *, int, int);