some more modes for AudioMixIn

git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@1203 8eb893ce-cfd4-0310-b710-fb5ebe64c474
sayer/1.4-spce2.6
Stefan Sayer 17 years ago
parent f3cc9015e1
commit d4cb6661ef

@ -6,20 +6,31 @@ that uses two AmAudio 'devices' (in the IVR: IvrAudioFile) as audio
sources, plays the first one, and periodically mixes in the second one.
The period, i.e. the time between two times mixing in the second audio,
can be specified, as well as the level with which the second one is
mixed into the first. The last parameter, a boolean, specifies whether
mixed into the first.
The last parameter, a boolean, specifies whether
playback of the second audio should be finished if the first is finished
while mixing in the second.
With the mix_once and the mix_immediate it can be specified whether it should
be mixed in onyl once, and whether it should be mixed in immediately.
E.g. if there should be some prompt or info tone played into the background
of a call, mix_once=True and mix_immediate=True are useful.
If level == 0, playback of the first is not continued when playing the
second, which means that it continues right where it was before
playback of the second started.
IVR usage:
init(IvrAudioFile first, IvrAudioFile second,
int interval, float level, boolean finish)
int interval, float level, boolean finish,
boolean mix_once, boolean mix_immediate)
C++ usage:
AmAudioMixIn::
AmAudioMixIn(AmAudio* A, AmAudioFile* B,
unsigned int interval, double level,
bool finish_b_while_mixing = false);
int flags);
where flags definitions can be found in AmAudioMixIn.h

@ -35,11 +35,11 @@ static PyObject* IvrAudioMixIn_init(IvrAudioMixIn* self, PyObject* args)
AmAudioFile* b = NULL;
int s;
double l;
int finish = 0;
int finish = 0, mix_once=0, mix_immediate=0;
PyObject *o_a, *o_b;
if(!PyArg_ParseTuple(args,"OOid|i", &o_a, &o_b, &s, &l, &finish))
if(!PyArg_ParseTuple(args,"OOid|iii", &o_a, &o_b, &s, &l, &finish, &mix_once, &mix_immediate))
return NULL;
if (o_a == Py_None) {
@ -69,7 +69,12 @@ static PyObject* IvrAudioMixIn_init(IvrAudioMixIn* self, PyObject* args)
delete self->mix;
}
self->mix = new AmAudioMixIn(a, b, s, l, finish);
int flags = 0;
if (finish) flags |=AUDIO_MIXIN_FINISH_B_MIX;
if (mix_once) flags |=AUDIO_MIXIN_ONCE;
if (mix_immediate) flags |=AUDIO_MIXIN_IMMEDIATE_START;
self->mix = new AmAudioMixIn(a, b, s, l, flags);
Py_INCREF(Py_None);
return Py_None;

@ -28,32 +28,43 @@
#include "AmAudioMixIn.h"
#include "SampleArray.h"
#define IS_FINISH_B_MIX (flags & AUDIO_MIXIN_FINISH_B_MIX)
#define IS_ONLY_ONCE (flags & AUDIO_MIXIN_ONCE)
#define IS_IMMEDIATE_START (flags & AUDIO_MIXIN_IMMEDIATE_START)
AmAudioMixIn::AmAudioMixIn(AmAudio* A, AmAudioFile* B,
unsigned int s, double l,
bool finish_b_while_mixing)
unsigned int flags)
: A(A),B(B), s(s), l(l),
mixing(false), next_start_ts_i(false),
finish_b_while_mixing(finish_b_while_mixing)
flags(flags)
{
}
AmAudioMixIn::~AmAudioMixIn() { }
int AmAudioMixIn::get(unsigned int user_ts, unsigned char* buffer,
unsigned int nb_samples) {
unsigned int nb_samples) {
if (!mixing) {
if (!next_start_ts_i) {
next_start_ts_i = true;
next_start_ts = IS_IMMEDIATE_START ?
user_ts : user_ts + s*DEFAULT_SAMPLE_RATE;
}
if (!ts_less()(user_ts, next_start_ts)) {
DBG("starting mix-in\n");
mixing = true;
next_start_ts = user_ts + s*DEFAULT_SAMPLE_RATE;
} else {
if (ts_less()(next_start_ts, user_ts)) {
DBG("starting mix-in\n");
mixing = true;
next_start_ts = user_ts + s*DEFAULT_SAMPLE_RATE;
}
}
}
if (!mixing) {
if (NULL == A)
return -1;
B_mut.lock();
if (!mixing || NULL == B) {
B_mut.unlock();
return A->get(user_ts, buffer, nb_samples);
} else {
if (l < 0.01) { // epsilon
@ -62,8 +73,12 @@ int AmAudioMixIn::get(unsigned int user_ts, unsigned char* buffer,
if (res <= 0) { // B empty
res = A->get(user_ts, buffer, nb_samples);
mixing = false;
B->rewind();
if (IS_ONLY_ONCE)
B = NULL;
else
B->rewind();
}
B_mut.unlock();
return res;
} else { // mix the two
int res = 0;
@ -71,10 +86,11 @@ int AmAudioMixIn::get(unsigned int user_ts, unsigned char* buffer,
// get audio from A
int len = A->get(user_ts, (unsigned char*)mix_buf, nb_samples);
if ((len<0) && !finish_b_while_mixing) { // A finished
if ((len<0) && !IS_FINISH_B_MIX) { // A finished
B_mut.unlock();
return len;
}
for (int i=0;i<len;i++) {
for (int i=0; i<(PCM16_B2S(len)); i++) {
pdest[i]=(short)(((double)mix_buf[i])*(1.0-l));
}
@ -85,29 +101,42 @@ int AmAudioMixIn::get(unsigned int user_ts, unsigned char* buffer,
if (res>0)
len_from_a=(unsigned int)res;
if (nb_samples<<1 != len_from_a)
if (PCM16_S2B(nb_samples) != len_from_a)
memset((void*)&pdest[len_from_a>>1], 0,
(nb_samples<<1) - len_from_a);
// add audio from B
len = B->get(user_ts, (unsigned char*)mix_buf, nb_samples);
if (len<0) { // B finished
mixing = false;
B->rewind();
if (IS_ONLY_ONCE)
B = NULL;
else
B->rewind();
} else {
for (int i=0;i<len;i++) {
pdest[i]+=(short)(((double)mix_buf[i])*l);
}
if (len>res) // audio from B is longer than from A
res = len;
for (int i=0; i<(PCM16_B2S(len)); i++) {
pdest[i]+=(short)(((double)mix_buf[i])*l);
}
if (len>res) // audio from B is longer than from A
res = len;
}
B_mut.unlock();
return res;
}
return res;
}
}
}
int AmAudioMixIn::put(unsigned int user_ts, unsigned char* buffer, unsigned int size) {
ERROR("writing not supported\n");
return -1;
}
int AmAudioMixIn::put(unsigned int user_ts, unsigned char* buffer, unsigned int size) {
ERROR("writing not supported\n");
return -1;
}
void AmAudioMixIn::mixin(AmAudioFile* f) {
B_mut.lock();
B = f;
mixing = next_start_ts_i = false; /* so that mix in will re-start */
B_mut.unlock();
}

@ -32,7 +32,7 @@
#include "AmAudioFile.h"
#define MAX_PACKETLENGTH_MS 30
#define MAX_PACKETLENGTH_MS 80
#define MAX_BUF_SAMPLES SYSTEM_SAMPLERATE * MAX_PACKETLENGTH_MS / 1000
#define DEFAULT_SAMPLE_RATE SYSTEM_SAMPLERATE // eh...
@ -46,15 +46,21 @@
* playback of B started.
*
*/
#define AUDIO_MIXIN_FINISH_B_MIX 1 /* when A ends while mixing in B, end playback only after B has ended */
#define AUDIO_MIXIN_ONCE 1 << 1 /* only mix in once */
#define AUDIO_MIXIN_IMMEDIATE_START 1 << 2 /* start mixing in immediately, or wait s seconds before */
class AmAudioMixIn : public AmAudio {
AmAudio* A;
AmAudioFile* B;
unsigned int s;
double l;
bool finish_b_while_mixing;
int flags;
bool mixing;
AmMutex B_mut;
unsigned int next_start_ts;
bool next_start_ts_i;
@ -64,8 +70,11 @@ class AmAudioMixIn : public AmAudio {
public:
AmAudioMixIn(AmAudio* A, AmAudioFile* B,
unsigned int s, double l,
bool finish_b_while_mixing = false);
unsigned int flags = 0);
~AmAudioMixIn();
void mixin(AmAudioFile* f);
protected:
// not used
int read(unsigned int user_ts, unsigned int size){ return -1; }

Loading…
Cancel
Save