Skip to content

Commit

Permalink
add support for specifying sample format (baresip#317)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
alfredh authored Nov 9, 2017
1 parent 4d5d9a6 commit a9e09b2
Show file tree
Hide file tree
Showing 36 changed files with 459 additions and 133 deletions.
8 changes: 6 additions & 2 deletions include/baresip.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
22 changes: 5 additions & 17 deletions modules/alsa/alsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@


char alsa_dev[64] = "default";
enum aufmt alsa_sample_format = AUFMT_S16LE;

static struct ausrc *ausrc;
static struct auplay *auplay;
Expand Down Expand Up @@ -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(),
Expand Down
2 changes: 1 addition & 1 deletion modules/alsa/alsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
30 changes: 5 additions & 25 deletions modules/alsa/alsa_play.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};


Expand All @@ -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);
}

Expand All @@ -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);

Expand Down Expand Up @@ -127,37 +117,27 @@ 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",
st->device, snd_strerror(err));
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;
}
Expand Down
34 changes: 7 additions & 27 deletions modules/alsa/alsa_src.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};


Expand All @@ -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);
}

Expand All @@ -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) {
Expand All @@ -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);
}

Expand Down Expand Up @@ -132,37 +121,27 @@ 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",
st->device, snd_strerror(err));
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;
}
Expand All @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions modules/aubridge/play.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Copyright (C) 2010 Creytiv.com
*/
#include <re.h>
#include <rem.h>
#include <baresip.h>
#include "aubridge.h"

Expand All @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions modules/aubridge/src.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Copyright (C) 2010 Creytiv.com
*/
#include <re.h>
#include <rem.h>
#include <baresip.h>
#include "aubridge.h"

Expand Down Expand Up @@ -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;
Expand Down
29 changes: 22 additions & 7 deletions modules/audiounit/player.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <AudioToolbox/AudioToolbox.h>
#include <pthread.h>
#include <re.h>
#include <rem.h>
#include <baresip.h>
#include "audiounit.h"

Expand All @@ -18,6 +19,7 @@ struct auplay_st {
pthread_mutex_t mutex;
auplay_write_h *wh;
void *arg;
uint32_t sampsz;
};


Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
Loading

0 comments on commit a9e09b2

Please sign in to comment.