Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ausine module #1021

Merged
merged 5 commits into from Jun 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -228,6 +228,7 @@ aubridge Audio bridge module
audiounit AudioUnit audio driver for MacOSX/iOS
aufile Audio module for using a WAV-file as audio input
auloop Audio-loop test module
ausine Audio sine wave input module
avcapture Video source using iOS AVFoundation video capture
avcodec Video codec using FFmpeg/libav libavcodec
avformat Video source using FFmpeg/libav libavformat
Expand Down
2 changes: 1 addition & 1 deletion mk/modules.mk
Expand Up @@ -291,7 +291,7 @@ MODULES += vidloop
MODULES += vumeter

ifneq ($(HAVE_PTHREAD),)
MODULES += aubridge aufile
MODULES += aubridge aufile ausine
endif

endif
Expand Down
209 changes: 209 additions & 0 deletions modules/ausine/ausine.c
@@ -0,0 +1,209 @@
/**
* @file ausine.c sine Audio Source
*
* Copyright (C) 2020 Creytiv.com
*/
#define _DEFAULT_SOURCE 1
#define _BSD_SOURCE 1
#include <pthread.h>
#include <re.h>
#include <rem.h>
#include <baresip.h>
#include <stdlib.h>
#include <math.h>
#define SCALE (32767)


/**
* @defgroup ausine ausine
*
* Audio module generating sine wave as audio input
*
* Sample config:
*
\verbatim
audio_source ausine,400
\endverbatim
*/

static const double PI = 3.14159265358979323846264338328;

struct ausrc_st {
const struct ausrc *as; /* base class */

uint32_t ptime;
size_t sampc;
bool run;
pthread_t thread;
ausrc_read_h *rh;
ausrc_error_h *errh;
void *arg;
int freq;
double sec_offset;
};


static struct ausrc *ausrc;


static void destructor(void *arg)
{
struct ausrc_st *st = arg;

if (st->run) {
st->run = false;
pthread_join(st->thread, NULL);
}
}


static void *play_thread(void *arg)
{
uint64_t now, ts = tmr_jiffies();
struct ausrc_st *st = arg;
int16_t *sampv;
double sample, rad_per_sec;
double sec_per_frame = 1.0 / 48000;
int inc;
size_t frames;

sampv = mem_alloc(st->sampc * sizeof(int16_t), NULL);
if (!sampv)
return NULL;

while (st->run) {

struct auframe af = {
.fmt = AUFMT_S16LE,
.sampv = sampv,
.sampc = st->sampc,
.timestamp = ts * 1000
};

sys_msleep(4);

now = tmr_jiffies();

if (ts > now)
continue;

inc = 0;
rad_per_sec = st->freq * 2.0 * PI;
frames = st->sampc / 2;

for (size_t frame = 0; frame < frames; frame += 1) {
sample = sin((st->sec_offset + frame * sec_per_frame)
* rad_per_sec);
sampv[inc] = (int16_t)(SCALE * 50 / 100.0f * sample);
sampv[inc+1] = (int16_t)(SCALE * 50 / 100.0f * sample);
inc += 2;
}

st->sec_offset = fmod(st->sec_offset + sec_per_frame * frames,
1.0);

st->rh(&af, st->arg);

ts += st->ptime;
}

mem_deref(sampv);

return NULL;
}


static int alloc_handler(struct ausrc_st **stp, const struct ausrc *as,
struct media_ctx **ctx,
struct ausrc_prm *prm, const char *dev,
ausrc_read_h *rh, ausrc_error_h *errh, void *arg)
{
struct ausrc_st *st;
int err;
(void)ctx;

if (!stp || !as || !prm || !rh || !dev)
return EINVAL;

if (prm->fmt != AUFMT_S16LE) {
warning("ausine: unsupported sample format (%s)\n",
aufmt_name(prm->fmt));
return ENOTSUP;
}

if (prm->srate != 48000) {
warning("ausine: supports only 48kHz samplerate");
return ENOTSUP;
}

if (prm->ch != 2) {
warning("ausine: supports only 2 channels");
return ENOTSUP;
}

st = mem_zalloc(sizeof(*st), destructor);
if (!st)
return ENOMEM;

st->as = as;
st->rh = rh;
st->errh = errh;
st->arg = arg;
st->sec_offset = 0.0;

st->freq = atoi(dev);

if (st->freq < 10 || st->freq > 20000)
{
err = ENOTSUP;
goto out;
}

info("ausine: %u Hz, %d channels, frequency %d Hz\n",
prm->srate, prm->ch, st->freq);

st->sampc = prm->srate * prm->ch * prm->ptime / 1000;

st->ptime = prm->ptime;

info("ausine: audio ptime=%u sampc=%zu\n",
st->ptime, st->sampc);

st->run = true;
err = pthread_create(&st->thread, NULL, play_thread, st);
if (err) {
st->run = false;
goto out;
}

out:
if (err)
mem_deref(st);
else
*stp = st;

return err;
}


static int module_init(void)
{
return ausrc_register(&ausrc, baresip_ausrcl(),
"ausine", alloc_handler);
}


static int module_close(void)
{
ausrc = mem_deref(ausrc);

return 0;
}


EXPORT_SYM const struct mod_export DECL_EXPORTS(ausine) = {
"ausine",
"ausrc",
module_init,
module_close
};
11 changes: 11 additions & 0 deletions modules/ausine/module.mk
@@ -0,0 +1,11 @@
#
# module.mk
#
# Copyright (C) 2010 Creytiv.com
#

MOD := ausine
$(MOD)_SRCS += ausine.c
$(MOD)_LFLAGS +=

include mk/mod.mk
1 change: 1 addition & 0 deletions src/config.c
Expand Up @@ -793,6 +793,7 @@ int config_write_template(const char *file, const struct config *cfg)
(void)re_fprintf(f, "#module\t\t\t" "portaudio" MOD_EXT "\n");
(void)re_fprintf(f, "#module\t\t\t" "aubridge" MOD_EXT "\n");
(void)re_fprintf(f, "#module\t\t\t" "aufile" MOD_EXT "\n");
(void)re_fprintf(f, "#module\t\t\t" "ausine" MOD_EXT "\n");


(void)re_fprintf(f, "\n# Video codec Modules (in order)\n");
Expand Down