38#define MOD_NAME "[Audio testcard] "
64#define AUDIO_CAPTURE_TESTCARD_MAGIC 0xf4b3c9c9u
66#define DEFAULT_AUDIO_BPS 2
67#define DEFAULT_AUDIO_SAMPLE_RATE 48000
69#define CHUNKS_PER_SEC 25
72#define DEFAULT_FREQUENCY 1000
73#define DEFAULT_VOLUME -18.0
106 *available_devices = calloc(1,
sizeof(
struct device_info));
107 strcpy((*available_devices)[0].dev,
"");
108 strcpy((*available_devices)[0].
name,
"Testing 1 kHZ signal");
115 assert(
data != NULL);
116 double scale = pow(10.0, volume / 20.0) * sqrt(2.0);
120 for (
int channel = 0; channel <
channels; ++channel) {
121 double sine = sin(((
double) i / ((
double)
sample_rate / frequency)) * M_PI * 2. );
122 if (crescendo_spd != 0) {
124 sine *= 2 * multiplier;
126 int32_t
val =
CLAMP(sine * INT32_MAX * scale, (
double) INT32_MIN, (
double) INT32_MAX);
128 bps, (
char *) &
val,
sizeof val, 1 *
sizeof val, dither);
140 char *ret = (
char *) calloc(1, *total_samples *
channels *
bps);
142 double scale = pow(10.0, volume / 20.0) * sqrt(2.0);
147 for (
int channel = 0; channel <
channels; ++channel) {
149 round(sin(((
double) i /
155 (ptrdiff_t)
bps * channel,
161 for (
int channel = 0; channel <
channels; ++channel) {
172 (ptrdiff_t)
bps * channel,
187 unsigned char *ret = malloc(
len);
189 for (
size_t i = 0; i <
len; ++i) {
190 ret[i] = (
unsigned char) (rand() % 256);
196 char **audio_samples,
size_t *total_samples,
197 unsigned long long int *chunk_size) {
198 FILE *wav = fopen(wav_filename,
"rb");
213 if (*chunk_size == 0) {
223 const int audio_samples_size = samples_data_size +
headroom;
224 *audio_samples = (
char *) calloc(1, audio_samples_size);
225 assert(*audio_samples != NULL);
230 read_to = *audio_samples;
232 tmp = (
char *) calloc(1, metadata.
data_size);
235 unsigned int samples =
wav_read(read_to, *total_samples, wav, &metadata);
237 if (samples != *total_samples) {
243 *total_samples = samples;
252 memcpy(*audio_samples + samples_data_size, *audio_samples,
headroom);
259 char wav_file[
static MAX_PATH_SIZE],
double *volume,
int *frequency,
263 char *save_ptr = NULL;
265 while ((
item = strtok_r(
fmt,
":", &save_ptr))) {
266 if (strncasecmp(
item,
"vol=", strlen(
"vol=")) == 0 ||
267 strncasecmp(
item,
"volume=", strlen(
"volume=")) == 0) {
268 *volume = strtod(strchr(
item,
'=') + 1, NULL);
269 assert(*volume > 0.0);
270 }
else if (strncasecmp(
item,
"file=", strlen(
"file=")) == 0) {
274 }
else if (strncasecmp(
item,
"frames=", strlen(
"frames=")) ==
277 }
else if (strncasecmp(
278 item,
"frequency=", strlen(
"frequency=")) == 0) {
279 long val = strtol(
item + strlen(
"frequency="), NULL, 10);
280 assert(
val > 0 &&
val <= INT_MAX);
281 *frequency = (int)
val;
282 }
else if (strstr(
item,
"crescendo") ==
item) {
287 if (strcmp(
val,
"help") == 0) {
289 "testcard:crescendo=<val>\n\t<"
290 "val> - crescendo duration "
291 "multiplier (default 1)\n");
298 }
else if (strcasecmp(
item,
"ebu") == 0) {
300 }
else if (strcasecmp(
item,
"noise") == 0) {
302 }
else if (strcasecmp(
item,
"silence") == 0) {
322 int frequency,
double volume)
336 const char *pattern_name =
"(unknown)";
340 pattern_name =
pattern ==
SINE ?
"sine" :
"crescendo";
348 pattern_name =
"EBU tone";
354 pattern_name =
"silence";
361 pattern_name =
"noise";
372 MOD_NAME "Generating %d Hz (%.2f RMS dBFS) %s (%s, "
373 "samples per frame: %llu).\n",
374 frequency, volume, pattern_name,
398 if (strcmp(cfg,
"help") == 0) {
401 {
"file=<wav>",
"a wav file to be played" },
402 {
"frames=<nf>",
"sets number of audio frames per packet" },
403 {
"frequency=<f>",
"frequency of sinusoide" },
404 {
"ebu",
"use EBU sound" },
405 {
"silence",
"emit silence" },
406 {
"crescendo[=<spd>]",
"produce amplying sinusoide (optionally accelerated)" },
407 {
"noise",
"emit noise" },
411 color_printf(
"\nYou can also consider using " TBOLD(
"sdl_mixer")
" audio capture card to generate a more complex pattern. "
412 "(It already includes a MIDI that can be played immediately.)\n");
421 char *tmp = strdup(cfg);
int void(** deleter)(void *))
static struct audio_frame * audio_cap_testcard_read(void *state)
static const struct audio_capture_info acap_testcard_info
#define DEFAULT_FREQUENCY
static char * get_sine_signal(int sample_rate, int bps, int channels, int frequency, double volume, int crescendo_spd)
static bool parse_fmt(struct state_audio_capture_testcard *s, char *fmt, char wav_file[static MAX_PATH_SIZE], double *volume, int *frequency, enum pattern *pattern)
#define DEFAULT_AUDIO_SAMPLE_RATE
static bool audio_testcard_read_wav(const char *wav_filename, struct audio_frame *audio_frame, char **audio_samples, size_t *total_samples, unsigned long long int *chunk_size)
static char * get_ebu_signal(int sample_rate, int bps, int channels, int frequency, double volume, size_t *total_samples)
static void * audio_cap_testcard_init(struct module *parent, const char *cfg)
static void audio_cap_testcard_done(void *state)
static bool generate_signal(struct state_audio_capture_testcard *s, enum pattern pattern, int frequency, double volume)
static char * get_noise(size_t len)
#define AUDIO_CAPTURE_TESTCARD_MAGIC
static void audio_cap_testcard_probe(struct device_info **available_devices, int *count, void(**deleter)(void *))
#define DEFAULT_AUDIO_BPS
This file contains definition of some common audio types.
#define STORE_I32_SAMPLE(ptr, val, out_bps)
stores given int32_t sample at required out_bps
#define AUDIO_CAPTURE_ABI_VERSION
int color_printf(const char *format,...)
static __device__ vec3 round(const vec3 &v)
void log_msg(int level, const char *format,...)
#define LOG_LEVEL_NOTICE
information that may be interesting
#define LOG_LEVEL_ERROR
general errors
#define LOG_LEVEL_VERBOSE
#define LOG_LEVEL_WARNING
less severe errors
unsigned int audio_capture_bps
const char * get_commandline_param(const char *key)
unsigned int audio_capture_sample_rate
unsigned int audio_capture_channels
#define DEFAULT_AUDIO_CAPTURE_CHANNELS
@ LIBRARY_CLASS_AUDIO_CAPTURE
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
#define CLAMP(x, low, high)
void print_module_usage(const char *module_name, const struct key_val *options, const struct key_val *options_full, bool print_full_help)
struct used to comunicate with audio capture/playback device
double seconds_tone_played
unsigned int samples_played
time_ns_t next_audio_time
unsigned long long int chunk_size
static time_ns_t get_time_in_ns()
int usleep(unsigned int usec)
struct audio_desc audio_desc_from_frame(const struct audio_frame *frame)
void change_bps2(char *out, int out_bps, const char *in, int in_bps, int in_len, bool dither)
changes bps with option to specify whether or not do the dithering
void change_bps(char *out, int out_bps, const char *in, int in_bps, int in_len)
const char * audio_desc_to_cstring(struct audio_desc desc)
constexpr size_t headroom
const char * get_wav_error(int errcode)
size_t wav_read(void *buffer, size_t sample_count, FILE *wav_file, struct wav_metadata *metadata)
int read_wav_header(FILE *wav_file, struct wav_metadata *metadata)