summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlfred E. Heggestad <alfred.heggestad@gmail.com>2017-11-09 17:10:07 +0100
committerGitHub <noreply@github.com>2017-11-09 17:10:07 +0100
commita9e09b2c0a99efddfcc16f5e413e2d73aa0e1732 (patch)
treee53a738b94461189540bfe1a2c7b643b41ac488f
parent4d5d9a6e4e0811b52b427602261d5e0b9bc85f21 (diff)
add support for specifying sample format (#317)
API: ausrc and auplay - add config items for ausrc/auplay format: ausrc_format s16|float auplay_format s16|float - audio.c: convert audio samples to/from signed 16-bit Modules: alsa add test for sample format FLOAT rst: add support for FLOAT sample format audiounit: add support for FLOAT sample format coreaudio: check for signed 16-bit audio format oss: check for signed 16-bit sample format winwave: check for S16LE pulse: add support for FLOAT sample format sndio: check for S16 format gst1: check sample format aufile: check sample format aubridge: check sample format gst: check sample format opensles: check for S16 sample format jack: check sample format alsa: remove usage of local config test: change samples to void pointer test: change sample type to void pointer
-rw-r--r--include/baresip.h8
-rw-r--r--modules/alsa/alsa.c22
-rw-r--r--modules/alsa/alsa.h2
-rw-r--r--modules/alsa/alsa_play.c30
-rw-r--r--modules/alsa/alsa_src.c34
-rw-r--r--modules/aubridge/play.c7
-rw-r--r--modules/aubridge/src.c7
-rw-r--r--modules/audiounit/player.c29
-rw-r--r--modules/audiounit/recorder.c30
-rw-r--r--modules/aufile/aufile.c6
-rw-r--r--modules/auloop/auloop.c33
-rw-r--r--modules/coreaudio/player.c3
-rw-r--r--modules/coreaudio/recorder.c2
-rw-r--r--modules/gst/gst.c2
-rw-r--r--modules/gst1/gst.c6
-rw-r--r--modules/jack/jack_play.c6
-rw-r--r--modules/jack/jack_src.c6
-rw-r--r--modules/opensles/player.c7
-rw-r--r--modules/opensles/recorder.c7
-rw-r--r--modules/oss/oss.c4
-rw-r--r--modules/portaudio/portaudio.c15
-rw-r--r--modules/pulse/player.c21
-rw-r--r--modules/pulse/recorder.c21
-rw-r--r--modules/rst/audio.c28
-rw-r--r--modules/sndio/sndio.c12
-rw-r--r--modules/winwave/play.c6
-rw-r--r--modules/winwave/src.c6
-rw-r--r--src/audio.c106
-rw-r--r--src/config.c39
-rw-r--r--src/play.c3
-rw-r--r--test/call.c68
-rw-r--r--test/main.c1
-rw-r--r--test/mock/mock_auplay.c5
-rw-r--r--test/mock/mock_ausrc.c5
-rw-r--r--test/play.c2
-rw-r--r--test/test.h3
36 files changed, 459 insertions, 133 deletions
diff --git a/include/baresip.h b/include/baresip.h
index efa047c..a59c676 100644
--- a/include/baresip.h
+++ b/include/baresip.h
@@ -204,6 +204,8 @@ struct config_audio {
bool src_first; /**< Audio source opened first */
enum audio_mode txmode; /**< Audio transmit mode */
bool level; /**< Enable audio level indication */
+ int src_fmt; /**< Audio source sample format */
+ int play_fmt; /**< Audio playback sample format */
};
#ifdef USE_VIDEO
@@ -365,9 +367,10 @@ struct ausrc_prm {
uint32_t srate; /**< Sampling rate in [Hz] */
uint8_t ch; /**< Number of channels */
uint32_t ptime; /**< Wanted packet-time in [ms] */
+ int fmt; /**< Sample format (enum aufmt) */
};
-typedef void (ausrc_read_h)(const int16_t *sampv, size_t sampc, void *arg);
+typedef void (ausrc_read_h)(const void *sampv, size_t sampc, void *arg);
typedef void (ausrc_error_h)(int err, const char *str, void *arg);
typedef int (ausrc_alloc_h)(struct ausrc_st **stp, const struct ausrc *ausrc,
@@ -397,9 +400,10 @@ struct auplay_prm {
uint32_t srate; /**< Sampling rate in [Hz] */
uint8_t ch; /**< Number of channels */
uint32_t ptime; /**< Wanted packet-time in [ms] */
+ int fmt; /**< Sample format (enum aufmt) */
};
-typedef void (auplay_write_h)(int16_t *sampv, size_t sampc, void *arg);
+typedef void (auplay_write_h)(void *sampv, size_t sampc, void *arg);
typedef int (auplay_alloc_h)(struct auplay_st **stp, const struct auplay *ap,
struct auplay_prm *prm, const char *device,
diff --git a/modules/alsa/alsa.c b/modules/alsa/alsa.c
index d695056..78de296 100644
--- a/modules/alsa/alsa.c
+++ b/modules/alsa/alsa.c
@@ -29,7 +29,6 @@
char alsa_dev[64] = "default";
-enum aufmt alsa_sample_format = AUFMT_S16LE;
static struct ausrc *ausrc;
static struct auplay *auplay;
@@ -146,24 +145,13 @@ static int alsa_init(void)
struct pl val;
int err;
+ /* XXX: remove check later */
if (0 == conf_get(conf_cur(), "alsa_sample_format", &val)) {
- if (0 == pl_strcasecmp(&val, "s16")) {
- alsa_sample_format = AUFMT_S16LE;
- }
- else if (0 == pl_strcasecmp(&val, "float")) {
- alsa_sample_format = AUFMT_FLOAT;
- }
- else if (0 == pl_strcasecmp(&val, "s24_3le")) {
- alsa_sample_format = AUFMT_S24_3LE;
- }
- else {
- warning("alsa: unknown sample format '%r'\n", &val);
- return EINVAL;
- }
-
- info("alsa: configured sample format `%s'\n",
- aufmt_name(alsa_sample_format));
+ warning("alsa: alsa_sample_format is deprecated"
+ " -- use ausrc_format or auplay_format instead\n");
+
+ (void)val;
}
err = ausrc_register(&ausrc, baresip_ausrcl(),
diff --git a/modules/alsa/alsa.h b/modules/alsa/alsa.h
index 61c408c..fbd67f2 100644
--- a/modules/alsa/alsa.h
+++ b/modules/alsa/alsa.h
@@ -6,7 +6,7 @@
extern char alsa_dev[64];
-extern enum aufmt alsa_sample_format;
+
int alsa_reset(snd_pcm_t *pcm, uint32_t srate, uint32_t ch,
uint32_t num_frames, snd_pcm_format_t pcmfmt);
diff --git a/modules/alsa/alsa_play.c b/modules/alsa/alsa_play.c
index aca8da2..6547e21 100644
--- a/modules/alsa/alsa_play.c
+++ b/modules/alsa/alsa_play.c
@@ -22,14 +22,12 @@ struct auplay_st {
pthread_t thread;
bool run;
snd_pcm_t *write;
- int16_t *sampv;
- void *xsampv;
+ void *sampv;
size_t sampc;
auplay_write_h *wh;
void *arg;
struct auplay_prm prm;
char *device;
- enum aufmt aufmt;
};
@@ -48,7 +46,6 @@ static void auplay_destructor(void *arg)
snd_pcm_close(st->write);
mem_deref(st->sampv);
- mem_deref(st->xsampv);
mem_deref(st->device);
}
@@ -67,14 +64,7 @@ static void *write_thread(void *arg)
st->wh(st->sampv, st->sampc, st->arg);
- if (st->aufmt == AUFMT_S16LE) {
- sampv = st->sampv;
- }
- else {
- sampv = st->xsampv;
- auconv_from_s16(st->aufmt, st->xsampv,
- st->sampv, st->sampc);
- }
+ sampv = st->sampv;
n = snd_pcm_writei(st->write, sampv, samples);
@@ -127,26 +117,16 @@ int alsa_play_alloc(struct auplay_st **stp, const struct auplay *ap,
st->ap = ap;
st->wh = wh;
st->arg = arg;
- st->aufmt = alsa_sample_format;
st->sampc = prm->srate * prm->ch * prm->ptime / 1000;
num_frames = st->prm.srate * st->prm.ptime / 1000;
- st->sampv = mem_alloc(2 * st->sampc, NULL);
+ st->sampv = mem_alloc(aufmt_sample_size(prm->fmt) * st->sampc, NULL);
if (!st->sampv) {
err = ENOMEM;
goto out;
}
- if (st->aufmt != AUFMT_S16LE) {
- size_t sz = aufmt_sample_size(st->aufmt) * st->sampc;
- st->xsampv = mem_alloc(sz, NULL);
- if (!st->xsampv) {
- err = ENOMEM;
- goto out;
- }
- }
-
err = snd_pcm_open(&st->write, st->device, SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0) {
warning("alsa: could not open auplay device '%s' (%s)\n",
@@ -154,10 +134,10 @@ int alsa_play_alloc(struct auplay_st **stp, const struct auplay *ap,
goto out;
}
- pcmfmt = aufmt_to_alsaformat(st->aufmt);
+ pcmfmt = aufmt_to_alsaformat(prm->fmt);
if (pcmfmt == SND_PCM_FORMAT_UNKNOWN) {
warning("alsa: unknown sample format '%s'\n",
- aufmt_name(st->aufmt));
+ aufmt_name(prm->fmt));
err = EINVAL;
goto out;
}
diff --git a/modules/alsa/alsa_src.c b/modules/alsa/alsa_src.c
index 6e850a7..a21f846 100644
--- a/modules/alsa/alsa_src.c
+++ b/modules/alsa/alsa_src.c
@@ -22,14 +22,12 @@ struct ausrc_st {
pthread_t thread;
bool run;
snd_pcm_t *read;
- int16_t *sampv;
- void *xsampv;
+ void *sampv;
size_t sampc;
ausrc_read_h *rh;
void *arg;
struct ausrc_prm prm;
char *device;
- enum aufmt aufmt;
};
@@ -48,7 +46,6 @@ static void ausrc_destructor(void *arg)
snd_pcm_close(st->read);
mem_deref(st->sampv);
- mem_deref(st->xsampv);
mem_deref(st->device);
}
@@ -73,10 +70,7 @@ static void *read_thread(void *arg)
size_t sampc;
void *sampv;
- if (st->aufmt == AUFMT_S16LE)
- sampv = st->sampv;
- else
- sampv = st->xsampv;
+ sampv = st->sampv;
err = snd_pcm_readi(st->read, sampv, num_frames);
if (err == -EPIPE) {
@@ -89,11 +83,6 @@ static void *read_thread(void *arg)
sampc = err * st->prm.ch;
- if (st->aufmt != AUFMT_S16LE) {
- auconv_to_s16(st->sampv, st->aufmt,
- st->xsampv, sampc);
- }
-
st->rh(st->sampv, sampc, st->arg);
}
@@ -132,26 +121,16 @@ int alsa_src_alloc(struct ausrc_st **stp, const struct ausrc *as,
st->as = as;
st->rh = rh;
st->arg = arg;
- st->aufmt = alsa_sample_format;
st->sampc = prm->srate * prm->ch * prm->ptime / 1000;
num_frames = st->prm.srate * st->prm.ptime / 1000;
- st->sampv = mem_alloc(2 * st->sampc, NULL);
+ st->sampv = mem_alloc(aufmt_sample_size(prm->fmt) * st->sampc, NULL);
if (!st->sampv) {
err = ENOMEM;
goto out;
}
- if (st->aufmt != AUFMT_S16LE) {
- size_t sz = aufmt_sample_size(st->aufmt) * st->sampc;
- st->xsampv = mem_alloc(sz, NULL);
- if (!st->xsampv) {
- err = ENOMEM;
- goto out;
- }
- }
-
err = snd_pcm_open(&st->read, st->device, SND_PCM_STREAM_CAPTURE, 0);
if (err < 0) {
warning("alsa: could not open ausrc device '%s' (%s)\n",
@@ -159,10 +138,10 @@ int alsa_src_alloc(struct ausrc_st **stp, const struct ausrc *as,
goto out;
}
- pcmfmt = aufmt_to_alsaformat(st->aufmt);
+ pcmfmt = aufmt_to_alsaformat(prm->fmt);
if (pcmfmt == SND_PCM_FORMAT_UNKNOWN) {
warning("alsa: unknown sample format '%s'\n",
- aufmt_name(st->aufmt));
+ aufmt_name(prm->fmt));
err = EINVAL;
goto out;
}
@@ -182,7 +161,8 @@ int alsa_src_alloc(struct ausrc_st **stp, const struct ausrc *as,
goto out;
}
- debug("alsa: recording started (%s)\n", st->device);
+ debug("alsa: recording started (%s) format=%s\n",
+ st->device, aufmt_name(prm->fmt));
out:
if (err)
diff --git a/modules/aubridge/play.c b/modules/aubridge/play.c
index 37c04fa..ff0b98f 100644
--- a/modules/aubridge/play.c
+++ b/modules/aubridge/play.c
@@ -4,6 +4,7 @@
* Copyright (C) 2010 Creytiv.com
*/
#include <re.h>
+#include <rem.h>
#include <baresip.h>
#include "aubridge.h"
@@ -28,6 +29,12 @@ int play_alloc(struct auplay_st **stp, const struct auplay *ap,
if (!stp || !ap || !prm)
return EINVAL;
+ if (prm->fmt != AUFMT_S16LE) {
+ warning("aubridge: playback: unsupported sample format (%s)\n",
+ aufmt_name(prm->fmt));
+ return ENOTSUP;
+ }
+
st = mem_zalloc(sizeof(*st), auplay_destructor);
if (!st)
return ENOMEM;
diff --git a/modules/aubridge/src.c b/modules/aubridge/src.c
index 22ce13a..87fd64a 100644
--- a/modules/aubridge/src.c
+++ b/modules/aubridge/src.c
@@ -4,6 +4,7 @@
* Copyright (C) 2010 Creytiv.com
*/
#include <re.h>
+#include <rem.h>
#include <baresip.h>
#include "aubridge.h"
@@ -31,6 +32,12 @@ int src_alloc(struct ausrc_st **stp, const struct ausrc *as,
if (!stp || !as || !prm)
return EINVAL;
+ if (prm->fmt != AUFMT_S16LE) {
+ warning("aubridge: source: unsupported sample format (%s)\n",
+ aufmt_name(prm->fmt));
+ return ENOTSUP;
+ }
+
st = mem_zalloc(sizeof(*st), ausrc_destructor);
if (!st)
return ENOMEM;
diff --git a/modules/audiounit/player.c b/modules/audiounit/player.c
index 372f139..230b1ad 100644
--- a/modules/audiounit/player.c
+++ b/modules/audiounit/player.c
@@ -7,6 +7,7 @@
#include <AudioToolbox/AudioToolbox.h>
#include <pthread.h>
#include <re.h>
+#include <rem.h>
#include <baresip.h>
#include "audiounit.h"
@@ -18,6 +19,7 @@ struct auplay_st {
pthread_mutex_t mutex;
auplay_write_h *wh;
void *arg;
+ uint32_t sampsz;
};
@@ -68,7 +70,7 @@ static OSStatus output_callback(void *inRefCon,
AudioBuffer *ab = &ioData->mBuffers[i];
- wh(ab->mData, ab->mDataByteSize/2, arg);
+ wh(ab->mData, ab->mDataByteSize/st->sampsz, arg);
}
return 0;
@@ -86,6 +88,17 @@ static void interrupt_handler(bool interrupted, void *arg)
}
+static uint32_t aufmt_to_formatflags(enum aufmt fmt)
+{
+ switch (fmt) {
+
+ case AUFMT_S16LE: return kLinearPCMFormatFlagIsSignedInteger;
+ case AUFMT_FLOAT: return kLinearPCMFormatFlagIsFloat;
+ default: return 0;
+ }
+}
+
+
int audiounit_player_alloc(struct auplay_st **stp, const struct auplay *ap,
struct auplay_prm *prm, const char *device,
auplay_write_h *wh, void *arg)
@@ -130,21 +143,23 @@ int audiounit_player_alloc(struct auplay_st **stp, const struct auplay *ap,
goto out;
}
+ st->sampsz = (uint32_t)aufmt_sample_size(prm->fmt);
+
fmt.mSampleRate = prm->srate;
fmt.mFormatID = kAudioFormatLinearPCM;
#if TARGET_OS_IPHONE
- fmt.mFormatFlags = kAudioFormatFlagIsSignedInteger
+ fmt.mFormatFlags = aufmt_to_formatflags(prm->fmt)
| kAudioFormatFlagsNativeEndian
| kAudioFormatFlagIsPacked;
#else
- fmt.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger
- | kLinearPCMFormatFlagIsPacked;
+ fmt.mFormatFlags = aufmt_to_formatflags(prm->fmt)
+ | kAudioFormatFlagIsPacked;
#endif
- fmt.mBitsPerChannel = 16;
+ fmt.mBitsPerChannel = 8 * st->sampsz;
fmt.mChannelsPerFrame = prm->ch;
- fmt.mBytesPerFrame = 2 * prm->ch;
+ fmt.mBytesPerFrame = st->sampsz * prm->ch;
fmt.mFramesPerPacket = 1;
- fmt.mBytesPerPacket = 2 * prm->ch;
+ fmt.mBytesPerPacket = st->sampsz * prm->ch;
ret = AudioUnitInitialize(st->au);
if (ret)
diff --git a/modules/audiounit/recorder.c b/modules/audiounit/recorder.c
index cf6a1af..b66ba07 100644
--- a/modules/audiounit/recorder.c
+++ b/modules/audiounit/recorder.c
@@ -8,6 +8,7 @@
#include <TargetConditionals.h>
#include <pthread.h>
#include <re.h>
+#include <rem.h>
#include <baresip.h>
#include "audiounit.h"
@@ -20,6 +21,7 @@ struct ausrc_st {
int ch;
ausrc_read_h *rh;
void *arg;
+ uint32_t sampsz;
};
@@ -67,7 +69,7 @@ static OSStatus input_callback(void *inRefCon,
abl.mNumberBuffers = 1;
abl.mBuffers[0].mNumberChannels = st->ch;
abl.mBuffers[0].mData = NULL;
- abl.mBuffers[0].mDataByteSize = inNumberFrames * 2;
+ abl.mBuffers[0].mDataByteSize = inNumberFrames * st->sampsz;
ret = AudioUnitRender(st->au,
ioActionFlags,
@@ -80,7 +82,8 @@ static OSStatus input_callback(void *inRefCon,
return ret;
}
- rh(abl.mBuffers[0].mData, abl.mBuffers[0].mDataByteSize/2, arg);
+ rh(abl.mBuffers[0].mData,
+ abl.mBuffers[0].mDataByteSize/st->sampsz, arg);
return 0;
}
@@ -97,6 +100,17 @@ static void interrupt_handler(bool interrupted, void *arg)
}
+static uint32_t aufmt_to_formatflags(enum aufmt fmt)
+{
+ switch (fmt) {
+
+ case AUFMT_S16LE: return kLinearPCMFormatFlagIsSignedInteger;
+ case AUFMT_FLOAT: return kLinearPCMFormatFlagIsFloat;
+ default: return 0;
+ }
+}
+
+
int audiounit_recorder_alloc(struct ausrc_st **stp, const struct ausrc *as,
struct media_ctx **ctx,
struct ausrc_prm *prm, const char *device,
@@ -178,21 +192,23 @@ int audiounit_recorder_alloc(struct ausrc_st **stp, const struct ausrc *as,
goto out;
#endif
+ st->sampsz = (uint32_t)aufmt_sample_size(prm->fmt);
+
fmt.mSampleRate = prm->srate;
fmt.mFormatID = kAudioFormatLinearPCM;
#if TARGET_OS_IPHONE
- fmt.mFormatFlags = kAudioFormatFlagIsSignedInteger
+ fmt.mFormatFlags = aufmt_to_formatflags(prm->fmt)
| kAudioFormatFlagsNativeEndian
| kAudioFormatFlagIsPacked;
#else
- fmt.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger
+ fmt.mFormatFlags = aufmt_to_formatflags(prm->fmt)
| kLinearPCMFormatFlagIsPacked;
#endif
- fmt.mBitsPerChannel = 16;
+ fmt.mBitsPerChannel = 8 * st->sampsz;
fmt.mChannelsPerFrame = prm->ch;
- fmt.mBytesPerFrame = 2 * prm->ch;
+ fmt.mBytesPerFrame = st->sampsz * prm->ch;
fmt.mFramesPerPacket = 1;
- fmt.mBytesPerPacket = 2 * prm->ch;
+ fmt.mBytesPerPacket = st->sampsz * prm->ch;
fmt.mReserved = 0;
ret = AudioUnitSetProperty(st->au, kAudioUnitProperty_StreamFormat,
diff --git a/modules/aufile/aufile.c b/modules/aufile/aufile.c
index 3f9c77f..307aee1 100644
--- a/modules/aufile/aufile.c
+++ b/modules/aufile/aufile.c
@@ -159,6 +159,12 @@ static int alloc_handler(struct ausrc_st **stp, const struct ausrc *as,
if (!stp || !as || !prm || !rh)
return EINVAL;
+ if (prm->fmt != AUFMT_S16LE) {
+ warning("aufile: unsupported sample format (%s)\n",
+ aufmt_name(prm->fmt));
+ return ENOTSUP;
+ }
+
info("aufile: loading input file '%s'\n", dev);
st = mem_zalloc(sizeof(*st), destructor);
diff --git a/modules/auloop/auloop.c b/modules/auloop/auloop.c
index 22dd1b0..5573621 100644
--- a/modules/auloop/auloop.c
+++ b/modules/auloop/auloop.c
@@ -44,6 +44,7 @@ struct audio_loop {
struct tmr tmr;
uint32_t srate;
uint32_t ch;
+ enum aufmt fmt;
uint32_t n_read;
uint32_t n_write;
@@ -90,9 +91,9 @@ static void print_stats(struct audio_loop *al)
if (al->n_write)
rw_ratio = 1.0 * al->n_read / al->n_write;
- (void)re_fprintf(stderr, "\r%uHz %dch "
+ (void)re_fprintf(stderr, "\r%uHz %dch %s "
" n_read=%u n_write=%u rw_ratio=%.2f",
- al->srate, al->ch,
+ al->srate, al->ch, aufmt_name(al->fmt),
al->n_read, al->n_write, rw_ratio);
if (str_isset(aucodec))
@@ -136,23 +137,25 @@ static int codec_read(struct audio_loop *al, int16_t *sampv, size_t sampc)
}
-static void read_handler(const int16_t *sampv, size_t sampc, void *arg)
+static void read_handler(const void *sampv, size_t sampc, void *arg)
{
struct audio_loop *al = arg;
+ size_t num_bytes = sampc * aufmt_sample_size(al->fmt);
int err;
++al->n_read;
- err = aubuf_write_samp(al->ab, sampv, sampc);
+ err = aubuf_write(al->ab, sampv, num_bytes);
if (err) {
warning("auloop: aubuf_write: %m\n", err);
}
}
-static void write_handler(int16_t *sampv, size_t sampc, void *arg)
+static void write_handler(void *sampv, size_t sampc, void *arg)
{
struct audio_loop *al = arg;
+ size_t num_bytes = sampc * aufmt_sample_size(al->fmt);
int err;
++al->n_write;
@@ -166,7 +169,7 @@ static void write_handler(int16_t *sampv, size_t sampc, void *arg)
}
}
else {
- aubuf_read_samp(al->ab, sampv, sampc);
+ aubuf_read(al->ab, sampv, num_bytes);
}
}
@@ -218,9 +221,23 @@ static int auloop_reset(struct audio_loop *al)
if (!cfg)
return ENOENT;
+ if (cfg->audio.src_fmt != cfg->audio.play_fmt) {
+ warning("auloop: ausrc_format and auplay_format"
+ " must be the same\n");
+ return EINVAL;
+ }
+
+ al->fmt = cfg->audio.src_fmt;
+
/* Optional audio codec */
- if (str_isset(aucodec))
+ if (str_isset(aucodec)) {
+ if (cfg->audio.src_fmt != AUFMT_S16LE) {
+ warning("auloop: only s16 supported with codec\n");
+ return EINVAL;
+ }
+
start_codec(al, aucodec);
+ }
/* audio player/source must be stopped first */
al->auplay = mem_deref(al->auplay);
@@ -248,6 +265,7 @@ static int auloop_reset(struct audio_loop *al)
auplay_prm.srate = al->srate;
auplay_prm.ch = al->ch;
auplay_prm.ptime = PTIME;
+ auplay_prm.fmt = al->fmt;
err = auplay_alloc(&al->auplay, baresip_auplayl(),
cfg->audio.play_mod, &auplay_prm,
cfg->audio.play_dev, write_handler, al);
@@ -261,6 +279,7 @@ static int auloop_reset(struct audio_loop *al)
ausrc_prm.srate = al->srate;
ausrc_prm.ch = al->ch;
ausrc_prm.ptime = PTIME;
+ ausrc_prm.fmt = al->fmt;
err = ausrc_alloc(&al->ausrc, baresip_ausrcl(),
NULL, cfg->audio.src_mod,
&ausrc_prm, cfg->audio.src_dev,
diff --git a/modules/coreaudio/player.c b/modules/coreaudio/player.c
index 16cfa33..7d247cd 100644
--- a/modules/coreaudio/player.c
+++ b/modules/coreaudio/player.c
@@ -88,6 +88,9 @@ int coreaudio_player_alloc(struct auplay_st **stp, const struct auplay *ap,
(void)device;
+ if (!stp || !ap || !prm || prm->fmt != AUFMT_S16LE)
+ return EINVAL;
+
st = mem_zalloc(sizeof(*st), auplay_destructor);
if (!st)
return ENOMEM;
diff --git a/modules/coreaudio/recorder.c b/modules/coreaudio/recorder.c
index c913485..9ceae60 100644
--- a/modules/coreaudio/recorder.c
+++ b/modules/coreaudio/recorder.c
@@ -102,7 +102,7 @@ int coreaudio_recorder_alloc(struct ausrc_st **stp, const struct ausrc *as,
(void)device;
(void)errh;
- if (!stp || !as || !prm)
+ if (!stp || !as || !prm || prm->fmt != AUFMT_S16LE)
return EINVAL;
st = mem_zalloc(sizeof(*st), ausrc_destructor);
diff --git a/modules/gst/gst.c b/modules/gst/gst.c
index dc00dd4..d729b70 100644
--- a/modules/gst/gst.c
+++ b/modules/gst/gst.c
@@ -376,6 +376,8 @@ static int gst_alloc(struct ausrc_st **stp, const struct ausrc *as,
if (!prm)
return EINVAL;
+ if (prm->fmt != AUFMT_S16LE)
+ return ENOTSUP;
st = mem_zalloc(sizeof(*st), gst_destructor);
if (!st)
diff --git a/modules/gst1/gst.c b/modules/gst1/gst.c
index 6f704e5..7510cac 100644
--- a/modules/gst1/gst.c
+++ b/modules/gst1/gst.c
@@ -383,6 +383,12 @@ static int gst_alloc(struct ausrc_st **stp, const struct ausrc *as,
if (!prm)
return EINVAL;
+ if (prm->fmt != AUFMT_S16LE) {
+ warning("gst: unsupported sample format (%s)\n",
+ aufmt_name(prm->fmt));
+ return ENOTSUP;
+ }
+
st = mem_zalloc(sizeof(*st), gst_destructor);
if (!st)
return ENOMEM;
diff --git a/modules/jack/jack_play.c b/modules/jack/jack_play.c
index 4f19b68..f890ddd 100644
--- a/modules/jack/jack_play.c
+++ b/modules/jack/jack_play.c
@@ -201,6 +201,12 @@ int jack_play_alloc(struct auplay_st **stp, const struct auplay *ap,
if (prm->ch > ARRAY_SIZE(st->portv))
return EINVAL;
+ if (prm->fmt != AUFMT_S16LE) {
+ warning("jack: playback: unsupported sample format (%s)\n",
+ aufmt_name(prm->fmt));
+ return ENOTSUP;
+ }
+
st = mem_zalloc(sizeof(*st), auplay_destructor);
if (!st)
return ENOMEM;
diff --git a/modules/jack/jack_src.c b/modules/jack/jack_src.c
index e4662c3..0ef1e42 100644
--- a/modules/jack/jack_src.c
+++ b/modules/jack/jack_src.c
@@ -196,6 +196,12 @@ int jack_src_alloc(struct ausrc_st **stp, const struct ausrc *as,
if (prm->ch > ARRAY_SIZE(st->portv))
return EINVAL;
+ if (prm->fmt != AUFMT_S16LE) {
+ warning("jack: source: unsupported sample format (%s)\n",
+ aufmt_name(prm->fmt));
+ return ENOTSUP;
+ }
+
st = mem_zalloc(sizeof(*st), ausrc_destructor);
if (!st)
return ENOMEM;
diff --git a/modules/opensles/player.c b/modules/opensles/player.c
index 347240f..59964f0 100644
--- a/modules/opensles/player.c
+++ b/modules/opensles/player.c
@@ -4,6 +4,7 @@
* Copyright (C) 2010 Creytiv.com
*/
#include <re.h>
+#include <rem.h>
#include <baresip.h>
#include <SLES/OpenSLES.h>
#include "SLES/OpenSLES_Android.h"
@@ -153,6 +154,12 @@ int opensles_player_alloc(struct auplay_st **stp, const struct auplay *ap,
if (!stp || !ap || !prm || !wh)
return EINVAL;
+ if (prm->fmt != AUFMT_S16LE) {
+ warning("opensles: player: unsupported sample format (%s)\n",
+ aufmt_name(prm->fmt));
+ return ENOTSUP;
+ }
+
debug("opensles: opening player %uHz, %uchannels\n",
prm->srate, prm->ch);
diff --git a/modules/opensles/recorder.c b/modules/opensles/recorder.c
index 0a4c5ef..b26190b 100644
--- a/modules/opensles/recorder.c
+++ b/modules/opensles/recorder.c
@@ -4,6 +4,7 @@
* Copyright (C) 2010 Creytiv.com
*/
#include <re.h>
+#include <rem.h>
#include <baresip.h>
#include <string.h>
#include <SLES/OpenSLES.h>
@@ -165,6 +166,12 @@ int opensles_recorder_alloc(struct ausrc_st **stp, const struct ausrc *as,
if (!stp || !as || !prm || !rh)
return EINVAL;
+ if (prm->fmt != AUFMT_S16LE) {
+ warning("opensles: record: unsupported sample format (%s)\n",
+ aufmt_name(prm->fmt));
+ return ENOTSUP;
+ }
+
debug("opensles: opening recorder %uHz, %uchannels\n",
prm->srate, prm->ch);
diff --git a/modules/oss/oss.c b/modules/oss/oss.c
index 4a8af92..0d47dd1 100644
--- a/modules/oss/oss.c
+++ b/modules/oss/oss.c
@@ -226,7 +226,7 @@ static int src_alloc(struct ausrc_st **stp, const struct ausrc *as,
(void)ctx;
(void)errh;
- if (!stp || !as || !prm || !rh)
+ if (!stp || !as || !prm || prm->fmt != AUFMT_S16LE || !rh)
return EINVAL;
st = mem_zalloc(sizeof(*st), ausrc_destructor);
@@ -285,7 +285,7 @@ static int play_alloc(struct auplay_st **stp, const struct auplay *ap,
struct auplay_st *st;
int err;
- if (!stp || !ap || !prm || !wh)
+ if (!stp || !ap || !prm || prm->fmt != AUFMT_S16LE || !wh)
return EINVAL;
st = mem_zalloc(sizeof(*st), auplay_destructor);
diff --git a/modules/portaudio/portaudio.c b/modules/portaudio/portaudio.c
index cd4b973..b856502 100644
--- a/modules/portaudio/portaudio.c
+++ b/modules/portaudio/portaudio.c
@@ -99,6 +99,17 @@ static int write_callback(const void *inputBuffer, void *outputBuffer,
}
+static PaSampleFormat aufmt_to_pasampleformat(enum aufmt fmt)
+{
+ switch (fmt) {
+
+ case AUFMT_S16LE: return paInt16;
+ case AUFMT_FLOAT: return paFloat32;
+ default: return 0;
+ }
+}
+
+
static int read_stream_open(struct ausrc_st *st, const struct ausrc_prm *prm,
uint32_t dev)
{
@@ -109,7 +120,7 @@ static int read_stream_open(struct ausrc_st *st, const struct ausrc_prm *prm,
memset(&prm_in, 0, sizeof(prm_in));
prm_in.device = dev;
prm_in.channelCount = prm->ch;
- prm_in.sampleFormat = paInt16;
+ prm_in.sampleFormat = aufmt_to_pasampleformat(prm->fmt);
prm_in.suggestedLatency = 0.100;
st->stream_rd = NULL;
@@ -142,7 +153,7 @@ static int write_stream_open(struct auplay_st *st,
memset(&prm_out, 0, sizeof(prm_out));
prm_out.device = dev;
prm_out.channelCount = prm->ch;
- prm_out.sampleFormat = paInt16;
+ prm_out.sampleFormat = aufmt_to_pasampleformat(prm->fmt);
prm_out.suggestedLatency = 0.100;
st->stream_wr = NULL;
diff --git a/modules/pulse/player.c b/modules/pulse/player.c
index 480ba6a..d65e7a8 100644
--- a/modules/pulse/player.c
+++ b/modules/pulse/player.c
@@ -18,8 +18,9 @@ struct auplay_st {
pa_simple *s;
pthread_t thread;
bool run;
- int16_t *sampv;
+ void *sampv;
size_t sampc;
+ size_t sampsz;
auplay_write_h *wh;
void *arg;
};
@@ -46,7 +47,7 @@ static void auplay_destructor(void *arg)
static void *write_thread(void *arg)
{
struct auplay_st *st = arg;
- const size_t num_bytes = st->sampc * 2;
+ const size_t num_bytes = st->sampc * st->sampsz;
int ret, pa_error = 0;
while (st->run) {
@@ -64,6 +65,17 @@ static void *write_thread(void *arg)
}
+static int aufmt_to_pulse_format(enum aufmt fmt)
+{
+ switch (fmt) {
+
+ case AUFMT_S16LE: return PA_SAMPLE_S16NE;
+ case AUFMT_FLOAT: return PA_SAMPLE_FLOAT32NE;
+ default: return 0;
+ }
+}
+
+
int pulse_player_alloc(struct auplay_st **stp, const struct auplay *ap,
struct auplay_prm *prm, const char *device,
auplay_write_h *wh, void *arg)
@@ -88,14 +100,15 @@ int pulse_player_alloc(struct auplay_st **stp, const struct auplay *ap,
st->arg = arg;
st->sampc = prm->srate * prm->ch * prm->ptime / 1000;
+ st->sampsz = aufmt_sample_size(prm->fmt);
- st->sampv = mem_alloc(2 * st->sampc, NULL);
+ st->sampv = mem_alloc(st->sampsz * st->sampc, NULL);
if (!st->sampv) {
err = ENOMEM;
goto out;
}
- ss.format = PA_SAMPLE_S16NE;
+ ss.format = aufmt_to_pulse_format(prm->fmt);
ss.channels = prm->ch;
ss.rate = prm->srate;
diff --git a/modules/pulse/recorder.c b/modules/pulse/recorder.c
index 64df6c4..8ef1b96 100644
--- a/modules/pulse/recorder.c
+++ b/modules/pulse/recorder.c
@@ -18,8 +18,9 @@ struct ausrc_st {
pa_simple *s;
pthread_t thread;
bool run;
- int16_t *sampv;
+ void *sampv;
size_t sampc;
+ size_t sampsz;
ausrc_read_h *rh;
void *arg;
};
@@ -46,7 +47,7 @@ static void ausrc_destructor(void *arg)
static void *read_thread(void *arg)
{
struct ausrc_st *st = arg;
- const size_t num_bytes = st->sampc * 2;
+ const size_t num_bytes = st->sampc * st->sampsz;
int ret, pa_error = 0;
while (st->run) {
@@ -65,6 +66,17 @@ static void *read_thread(void *arg)
}
+static int aufmt_to_pulse_format(enum aufmt fmt)
+{
+ switch (fmt) {
+
+ case AUFMT_S16LE: return PA_SAMPLE_S16NE;
+ case AUFMT_FLOAT: return PA_SAMPLE_FLOAT32NE;
+ default: return 0;
+ }
+}
+
+
int pulse_recorder_alloc(struct ausrc_st **stp, const struct ausrc *as,
struct media_ctx **ctx,
struct ausrc_prm *prm, const char *device,
@@ -95,14 +107,15 @@ int pulse_recorder_alloc(struct ausrc_st **stp, const struct ausrc *as,
st->arg = arg;
st->sampc = prm->srate * prm->ch * prm->ptime / 1000;
+ st->sampsz = aufmt_sample_size(prm->fmt);
- st->sampv = mem_alloc(2 * st->sampc, NULL);
+ st->sampv = mem_alloc(st->sampsz * st->sampc, NULL);
if (!st->sampv) {
err = ENOMEM;
goto out;
}
- ss.format = PA_SAMPLE_S16NE;
+ ss.format = aufmt_to_pulse_format(prm->fmt);
ss.channels = prm->ch;
ss.rate = prm->srate;
diff --git a/modules/rst/audio.c b/modules/rst/audio.c
index 666b09a..4bb7e0d 100644
--- a/modules/rst/audio.c
+++ b/modules/rst/audio.c
@@ -28,6 +28,7 @@ struct ausrc_st {
bool run;
uint32_t ptime;
size_t sampc;
+ size_t sampsz;
};
@@ -59,9 +60,10 @@ static void *play_thread(void *arg)
{
uint64_t now, ts = tmr_jiffies();
struct ausrc_st *st = arg;
- int16_t *sampv;
+ void *sampv;
+ size_t num_bytes = st->sampc * st->sampsz;
- sampv = mem_alloc(st->sampc * 2, NULL);
+ sampv = mem_alloc(num_bytes, NULL);
if (!sampv)
return NULL;
@@ -80,7 +82,7 @@ static void *play_thread(void *arg)
}
#endif
- aubuf_read_samp(st->aubuf, sampv, st->sampc);
+ aubuf_read(st->aubuf, sampv, num_bytes);
st->rh(sampv, st->sampc, st->arg);
@@ -148,6 +150,18 @@ void rst_audio_feed(struct ausrc_st *st, const uint8_t *buf, size_t sz)
}
+static int aufmt_to_encoding(enum aufmt fmt)
+{
+ switch (fmt) {
+
+ case AUFMT_S16LE: return MPG123_ENC_SIGNED_16;
+ case AUFMT_FLOAT: return MPG123_ENC_FLOAT_32;
+ case AUFMT_S24_3LE: return MPG123_ENC_SIGNED_24; /* NOTE: endian */
+ default: return 0;
+ }
+}
+
+
static int alloc_handler(struct ausrc_st **stp, const struct ausrc *as,
struct media_ctx **ctx,
struct ausrc_prm *prm, const char *dev,
@@ -184,10 +198,12 @@ static int alloc_handler(struct ausrc_st **stp, const struct ausrc *as,
/* Set wanted output format */
mpg123_format_none(st->mp3);
- mpg123_format(st->mp3, prm->srate, prm->ch, MPG123_ENC_SIGNED_16);
+ mpg123_format(st->mp3, prm->srate, prm->ch,
+ aufmt_to_encoding(prm->fmt));
mpg123_volume(st->mp3, 0.3);
st->sampc = prm->srate * prm->ch * prm->ptime / 1000;
+ st->sampsz = aufmt_sample_size(prm->fmt);
st->ptime = prm->ptime;
@@ -198,8 +214,8 @@ static int alloc_handler(struct ausrc_st **stp, const struct ausrc *as,
/* 1 - 20 seconds of audio */
err = aubuf_alloc(&st->aubuf,
- prm->srate * prm->ch * 2,
- prm->srate * prm->ch * 40);
+ prm->srate * prm->ch * st->sampsz,
+ prm->srate * prm->ch * st->sampsz * 20);
if (err)
goto out;
diff --git a/modules/sndio/sndio.c b/modules/sndio/sndio.c
index d3ca9d6..6ac4b67 100644
--- a/modules/sndio/sndio.c
+++ b/modules/sndio/sndio.c
@@ -154,6 +154,12 @@ static int src_alloc(struct ausrc_st **stp, const struct ausrc *as,
if (!stp || !as || !prm)
return EINVAL;
+ if (prm->fmt != AUFMT_S16LE) {
+ warning("sndio: source: unsupported sample format (%s)\n",
+ aufmt_name(prm->fmt));
+ return ENOTSUP;
+ }
+
name = (str_isset(device)) ? device : SIO_DEVANY;
if ((st = mem_zalloc(sizeof(*st), ausrc_destructor)) == NULL)
@@ -222,6 +228,12 @@ static int play_alloc(struct auplay_st **stp, const struct auplay *ap,
if (!stp || !ap || !prm)
return EINVAL;
+ if (prm->fmt != AUFMT_S16LE) {
+ warning("sndio: playback: unsupported sample format (%s)\n",
+ aufmt_name(prm->fmt));
+ return ENOTSUP;
+ }
+
name = (str_isset(device)) ? device : SIO_DEVANY;
if ((st = mem_zalloc(sizeof(*st), auplay_destructor)) == NULL)
diff --git a/modules/winwave/play.c b/modules/winwave/play.c
index b9129fa..e987fc7 100644
--- a/modules/winwave/play.c
+++ b/modules/winwave/play.c
@@ -202,6 +202,12 @@ int winwave_play_alloc(struct auplay_st **stp, const struct auplay *ap,
if (!stp || !ap || !prm)
return EINVAL;
+ if (prm->fmt != AUFMT_S16LE) {
+ warning("winwave: playback: unsupported sample format (%s)\n",
+ aufmt_name(prm->fmt));
+ return ENOTSUP;
+ }
+
st = mem_zalloc(sizeof(*st), auplay_destructor);
if (!st)
return ENOMEM;
diff --git a/modules/winwave/src.c b/modules/winwave/src.c
index e96915e..6240899 100644
--- a/modules/winwave/src.c
+++ b/modules/winwave/src.c
@@ -201,6 +201,12 @@ int winwave_src_alloc(struct ausrc_st **stp, const struct ausrc *as,
if (!stp || !as || !prm)
return EINVAL;
+ if (prm->fmt != AUFMT_S16LE) {
+ warning("winwave: source: unsupported sample format (%s)\n",
+ aufmt_name(prm->fmt));
+ return ENOTSUP;
+ }
+
st = mem_zalloc(sizeof(*st), ausrc_destructor);
if (!st)
return ENOMEM;
diff --git a/src/audio.c b/src/audio.c
index 422926b..1dad716 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -93,6 +93,8 @@ struct autx {
bool marker; /**< Marker bit for outgoing RTP */
bool muted; /**< Audio source is muted */
int cur_key; /**< Currently transmitted event */
+ enum aufmt src_fmt;
+ bool need_conv;
union {
struct tmr tmr; /**< Timer for sending RTP packets */
@@ -136,6 +138,8 @@ struct aurx {
int pt; /**< Payload type for incoming RTP */
double level_last;
bool level_set;
+ enum aufmt play_fmt;
+ bool need_conv;
};
@@ -442,7 +446,35 @@ static void poll_aubuf_tx(struct audio *a)
sampc = tx->psize / 2;
/* timed read from audio-buffer */
- aubuf_read_samp(tx->aubuf, tx->sampv, sampc);
+
+ if (tx->src_fmt == AUFMT_S16LE) {
+
+ aubuf_read(tx->aubuf, (uint8_t *)tx->sampv,
+ sampc * aufmt_sample_size(tx->src_fmt));
+ }
+ else {
+ /* Convert from ausrc format to 16-bit format */
+
+ void *tmp_sampv;
+ size_t num_bytes = sampc * aufmt_sample_size(tx->src_fmt);
+
+ if (!tx->need_conv) {
+ info("audio: NOTE: source sample conversion"
+ " needed: %s --> %s\n",
+ aufmt_name(tx->src_fmt), aufmt_name(AUFMT_S16LE));
+ tx->need_conv = true;
+ }
+
+ tmp_sampv = mem_zalloc(num_bytes, NULL);
+ if (!tmp_sampv)
+ return;
+
+ aubuf_read(tx->aubuf, tmp_sampv, num_bytes);
+
+ auconv_to_s16(sampv, tx->src_fmt, tmp_sampv, sampc);
+
+ mem_deref(tmp_sampv);
+ }
/* optional resampler */
if (tx->resamp.resample) {
@@ -511,15 +543,18 @@ static void check_telev(struct audio *a, struct autx *tx)
*
* @note This function may be called from any thread
*
+ * @note The sample format is set in rx->play_fmt
+ *
* @param buf Buffer to fill with audio samples
* @param sz Number of bytes in buffer
* @param arg Handler argument
*/
-static void auplay_write_handler(int16_t *sampv, size_t sampc, void *arg)
+static void auplay_write_handler(void *sampv, size_t sampc, void *arg)
{
struct aurx *rx = arg;
+ size_t num_bytes = sampc * aufmt_sample_size(rx->play_fmt);
- aubuf_read_samp(rx->aubuf, sampv, sampc);
+ aubuf_read(rx->aubuf, sampv, num_bytes);
}
@@ -534,15 +569,16 @@ static void auplay_write_handler(int16_t *sampv, size_t sampc, void *arg)
* @param sz Number of bytes in buffer
* @param arg Handler argument
*/
-static void ausrc_read_handler(const int16_t *sampv, size_t sampc, void *arg)
+static void ausrc_read_handler(const void *sampv, size_t sampc, void *arg)
{
struct audio *a = arg;
struct autx *tx = &a->tx;
+ size_t num_bytes = sampc * aufmt_sample_size(tx->src_fmt);
if (tx->muted)
- memset((void *)sampv, 0, sampc*2);
+ memset((void *)sampv, 0, num_bytes);
- (void)aubuf_write_samp(tx->aubuf, sampv, sampc);
+ (void)aubuf_write(tx->aubuf, sampv, num_bytes);
if (a->cfg.txmode == AUDIO_MODE_POLL) {
unsigned i;
@@ -662,9 +698,39 @@ static int aurx_stream_decode(struct aurx *rx, struct mbuf *mb)
sampc = sampc_rs;
}
- err = aubuf_write_samp(rx->aubuf, sampv, sampc);
- if (err)
- goto out;
+ if (rx->play_fmt == AUFMT_S16LE) {
+ err = aubuf_write_samp(rx->aubuf, sampv, sampc);
+ if (err)
+ goto out;
+ }
+ else {
+
+ /* Convert from 16-bit to auplay format */
+
+ void *tmp_sampv;
+ size_t num_bytes = sampc * aufmt_sample_size(rx->play_fmt);
+
+ if (!rx->need_conv) {
+ info("audio: NOTE: playback sample conversion"
+ " needed: %s --> %s\n",
+ aufmt_name(AUFMT_S16LE),
+ aufmt_name(rx->play_fmt));
+ rx->need_conv = true;
+ }
+
+ tmp_sampv = mem_zalloc(num_bytes, NULL);
+ if (!tmp_sampv)
+ return ENOMEM;
+
+ auconv_from_s16(rx->play_fmt, tmp_sampv, sampv, sampc);
+
+ err = aubuf_write(rx->aubuf, tmp_sampv, num_bytes);
+
+ mem_deref(tmp_sampv);
+
+ if (err)
+ goto out;
+ }
out:
return err;
@@ -801,6 +867,9 @@ int audio_alloc(struct audio **ap, const struct stream_param *stream_prm,
tx = &a->tx;
rx = &a->rx;
+ tx->src_fmt = cfg->audio.src_fmt;
+ rx->play_fmt = cfg->audio.play_fmt;
+
err = stream_alloc(&a->strm, stream_prm, &cfg->avt, call, sdp_sess,
"audio", label,
mnat, mnat_sess, menc, menc_sess,
@@ -845,8 +914,8 @@ int audio_alloc(struct audio **ap, const struct stream_param *stream_prm,
}
tx->mb = mbuf_alloc(STREAM_PRESZ + 4096);
- tx->sampv = mem_zalloc(AUDIO_SAMPSZ * 2, NULL);
- rx->sampv = mem_zalloc(AUDIO_SAMPSZ * 2, NULL);
+ tx->sampv = mem_zalloc(AUDIO_SAMPSZ * sizeof(int16_t), NULL);
+ rx->sampv = mem_zalloc(AUDIO_SAMPSZ * sizeof(int16_t), NULL);
if (!tx->mb || !tx->sampv || !rx->sampv) {
err = ENOMEM;
goto out;
@@ -1113,11 +1182,13 @@ static int start_player(struct aurx *rx, struct audio *a)
prm.srate = srate_dsp;
prm.ch = channels_dsp;
prm.ptime = rx->ptime;
+ prm.fmt = rx->play_fmt;
if (!rx->aubuf) {
size_t psize;
+ size_t sz = aufmt_sample_size(rx->play_fmt);
- psize = 2 * calc_nsamp(prm.srate, prm.ch, prm.ptime);
+ psize = sz * calc_nsamp(prm.srate, prm.ch, prm.ptime);
err = aubuf_alloc(&rx->aubuf, psize * 1, psize * 8);
if (err)
@@ -1135,6 +1206,9 @@ static int start_player(struct aurx *rx, struct audio *a)
}
rx->auplay_prm = prm;
+
+ info("audio: player started with sample format %s\n",
+ aufmt_name(rx->play_fmt));
}
return 0;
@@ -1192,6 +1266,7 @@ static int start_source(struct autx *tx, struct audio *a)
prm.srate = srate_dsp;
prm.ch = channels_dsp;
prm.ptime = tx->ptime;
+ prm.fmt = tx->src_fmt;
tx->psize = 2 * calc_nsamp(prm.srate, prm.ch, prm.ptime);
@@ -1237,6 +1312,9 @@ static int start_source(struct autx *tx, struct audio *a)
}
tx->ausrc_prm = prm;
+
+ info("audio: source started with sample format %s\n",
+ aufmt_name(tx->src_fmt));
}
return 0;
@@ -1627,7 +1705,9 @@ int audio_debug(struct re_printf *pf, const struct audio *a)
aubuf_debug, tx->aubuf,
tx->ptime);
- err |= re_hprintf(pf, " rx: %H %H ptime=%ums pt=%d\n",
+ err |= re_hprintf(pf,
+ " rx: %H %H\n"
+ " ptime=%ums pt=%d\n",
aucodec_print, rx->ac,
aubuf_debug, rx->aubuf,
rx->ptime, rx->pt);
diff --git a/src/config.c b/src/config.c
index be26798..1e28def 100644
--- a/src/config.c
+++ b/src/config.c
@@ -56,6 +56,8 @@ static struct config core_config = {
false,
AUDIO_MODE_POLL,
false,
+ AUFMT_S16LE,
+ AUFMT_S16LE,
},
#ifdef USE_VIDEO
@@ -139,11 +141,22 @@ static int dns_server_handler(const struct pl *pl, void *arg)
}
+static enum aufmt resolve_aufmt(const struct pl *fmt)
+{
+ if (0 == pl_strcasecmp(fmt, "s16")) return AUFMT_S16LE;
+ if (0 == pl_strcasecmp(fmt, "float")) return AUFMT_FLOAT;
+ if (0 == pl_strcasecmp(fmt, "s24_3le")) return AUFMT_S24_3LE;
+
+ return (enum aufmt)-1;
+}
+
+
int config_parse_conf(struct config *cfg, const struct conf *conf)
{
struct pl pollm, as, ap;
enum poll_method method;
struct vidsz size = {0, 0};
+ struct pl fmt;
uint32_t v;
int err = 0;
@@ -209,6 +222,32 @@ int config_parse_conf(struct config *cfg, const struct conf *conf)
(void)conf_get_bool(conf, "audio_level", &cfg->audio.level);
+ if (0 == conf_get(conf, "ausrc_format", &fmt)) {
+
+ cfg->audio.src_fmt = resolve_aufmt(&fmt);
+ if (cfg->audio.src_fmt == -1) {
+ warning("ausrc_format: sample format not supported"
+ " (%r)\n", &fmt);
+ return EINVAL;
+ }
+
+ info("ausrc: using audio sample format `%s'\n",
+ aufmt_name(cfg->audio.src_fmt));
+ }
+
+ if (0 == conf_get(conf, "auplay_format", &fmt)) {
+
+ cfg->audio.play_fmt = resolve_aufmt(&fmt);
+ if (cfg->audio.play_fmt == -1) {
+ warning("auplay_format: audio format not supported"
+ " (%r)\n", &fmt);
+ return EINVAL;
+ }
+
+ info("auplay: using audio sample format `%s'\n",
+ aufmt_name(cfg->audio.play_fmt));
+ }
+
#ifdef USE_VIDEO
/* Video */
(void)conf_get_csv(conf, "video_source",
diff --git a/src/play.c b/src/play.c
index bd5d3de..aa0b59f 100644
--- a/src/play.c
+++ b/src/play.c
@@ -69,7 +69,7 @@ static void tmr_polling(void *arg)
/**
* NOTE: DSP cannot be destroyed inside handler
*/
-static void write_handler(int16_t *sampv, size_t sampc, void *arg)
+static void write_handler(void *sampv, size_t sampc, void *arg)
{
struct play *play = arg;
size_t sz = sampc * 2;
@@ -242,6 +242,7 @@ int play_tone(struct play **playp, struct player *player,
wprm.ch = ch;
wprm.srate = srate;
wprm.ptime = PTIME;
+ wprm.fmt = AUFMT_S16LE;
err = auplay_alloc(&play->auplay, baresip_auplayl(),
cfg->audio.alert_mod, &wprm,
diff --git a/test/call.c b/test/call.c
index 0cd0394..b86ce6a 100644
--- a/test/call.c
+++ b/test/call.c
@@ -5,6 +5,7 @@
*/
#include <string.h>
#include <re.h>
+#include <rem.h>
#include <baresip.h>
#include "test.h"
@@ -721,7 +722,7 @@ int test_call_video(void)
#endif
-static void mock_sample_handler(const int16_t *sampv, size_t sampc, void *arg)
+static void mock_sample_handler(const void *sampv, size_t sampc, void *arg)
{
struct fixture *fix = arg;
bool got_aulevel;
@@ -819,3 +820,68 @@ int test_call_progress(void)
return err;
}
+
+
+static void float_sample_handler(const void *sampv, size_t sampc, void *arg)
+{
+ struct fixture *fix = arg;
+ (void)sampv;
+ (void)sampc;
+
+ if (sampc && fix->a.n_established && fix->b.n_established)
+ re_cancel();
+}
+
+
+int test_call_format_float(void)
+{
+ struct fixture fix, *f = &fix;
+ struct ausrc *ausrc = NULL;
+ struct auplay *auplay = NULL;
+ int err = 0;
+
+ fixture_init(f);
+
+ conf_config()->audio.src_fmt = AUFMT_FLOAT;
+ conf_config()->audio.play_fmt = AUFMT_FLOAT;
+
+ err = mock_ausrc_register(&ausrc);
+ TEST_ERR(err);
+ err = mock_auplay_register(&auplay, float_sample_handler, f);
+ TEST_ERR(err);
+
+ f->estab_action = ACTION_NOTHING;
+
+ f->behaviour = BEHAVIOUR_ANSWER;
+
+ /* Make a call from A to B */
+ err = ua_connect(f->a.ua, 0, NULL, f->buri, NULL, VIDMODE_OFF);
+ TEST_ERR(err);
+
+ /* run main-loop with timeout, wait for events */
+ err = re_main_timeout(5000);
+ TEST_ERR(err);
+ TEST_ERR(fix.err);
+
+ ASSERT_EQ(0, fix.a.n_incoming);
+ ASSERT_EQ(1, fix.a.n_established);
+ ASSERT_EQ(0, fix.a.n_closed);
+ ASSERT_EQ(0, fix.a.close_scode);
+
+ ASSERT_EQ(1, fix.b.n_incoming);
+ ASSERT_EQ(1, fix.b.n_established);
+ ASSERT_EQ(0, fix.b.n_closed);
+
+ out:
+ conf_config()->audio.src_fmt = AUFMT_S16LE;
+ conf_config()->audio.play_fmt = AUFMT_S16LE;
+
+ fixture_close(f);
+ mem_deref(auplay);
+ mem_deref(ausrc);
+
+ if (fix.err)
+ return fix.err;
+
+ return err;
+}
diff --git a/test/main.c b/test/main.c
index 497d347..e917f2d 100644
--- a/test/main.c
+++ b/test/main.c
@@ -35,6 +35,7 @@ static const struct test tests[] = {
TEST(test_call_dtmf),
TEST(test_call_aulevel),
TEST(test_call_progress),
+ TEST(test_call_format_float),
#ifdef USE_VIDEO
TEST(test_call_video),
TEST(test_video),
diff --git a/test/mock/mock_auplay.c b/test/mock/mock_auplay.c
index 9857d9f..2a4ffcc 100644
--- a/test/mock/mock_auplay.c
+++ b/test/mock/mock_auplay.c
@@ -4,6 +4,7 @@
* Copyright (C) 2010 - 2016 Creytiv.com
*/
#include <re.h>
+#include <rem.h>
#include <baresip.h>
#include "../test.h"
@@ -13,7 +14,7 @@ struct auplay_st {
struct tmr tmr;
struct auplay_prm prm;
- int16_t *sampv;
+ void *sampv;
size_t sampc;
auplay_write_h *wh;
void *arg;
@@ -72,7 +73,7 @@ static int mock_auplay_alloc(struct auplay_st **stp, const struct auplay *ap,
st->sampc = prm->srate * prm->ch * prm->ptime / 1000;
- st->sampv = mem_zalloc(2 * st->sampc, NULL);
+ st->sampv = mem_zalloc(aufmt_sample_size(prm->fmt) * st->sampc, NULL);
if (!st->sampv) {
err = ENOMEM;
goto out;
diff --git a/test/mock/mock_ausrc.c b/test/mock/mock_ausrc.c
index 39512f1..070cbfc 100644
--- a/test/mock/mock_ausrc.c
+++ b/test/mock/mock_ausrc.c
@@ -4,6 +4,7 @@
* Copyright (C) 2010 - 2016 Creytiv.com
*/
#include <re.h>
+#include <rem.h>
#include <baresip.h>
#include "../test.h"
@@ -13,7 +14,7 @@ struct ausrc_st {
struct tmr tmr;
struct ausrc_prm prm;
- int16_t *sampv;
+ void *sampv;
size_t sampc;
ausrc_read_h *rh;
void *arg;
@@ -65,7 +66,7 @@ static int mock_ausrc_alloc(struct ausrc_st **stp, const struct ausrc *as,
st->sampc = prm->srate * prm->ch * prm->ptime / 1000;
- st->sampv = mem_zalloc(2 * st->sampc, NULL);
+ st->sampv = mem_zalloc(aufmt_sample_size(prm->fmt) * st->sampc, NULL);
if (!st->sampv) {
err = ENOMEM;
goto out;
diff --git a/test/play.c b/test/play.c
index 9e8c09c..82c8813 100644
--- a/test/play.c
+++ b/test/play.c
@@ -39,7 +39,7 @@ static struct mbuf *generate_tone(void)
}
-static void sample_handler(const int16_t *sampv, size_t sampc, void *arg)
+static void sample_handler(const void *sampv, size_t sampc, void *arg)
{
struct test *test = arg;
size_t bytec = sampc * 2;
diff --git a/test/test.h b/test/test.h
index 572e179..f276a8d 100644
--- a/test/test.h
+++ b/test/test.h
@@ -143,7 +143,7 @@ int mock_ausrc_register(struct ausrc **ausrcp);
struct auplay;
-typedef void (mock_sample_h)(const int16_t *sampv, size_t sampc, void *arg);
+typedef void (mock_sample_h)(const void *sampv, size_t sampc, void *arg);
int mock_auplay_register(struct auplay **auplayp,
mock_sample_h *sampleh, void *arg);
@@ -206,6 +206,7 @@ int test_call_dtmf(void);
int test_call_video(void);
int test_call_aulevel(void);
int test_call_progress(void);
+int test_call_format_float(void);
#ifdef USE_VIDEO
int test_video(void);