Author: sayer
Date: 2008-12-19 18:23:15 +0100 (Fri, 19 Dec 2008)
New Revision: 1203
Modified:
trunk/apps/examples/mixin_announce/Readme.mixin_announce
trunk/apps/ivr/IvrAudioMixIn.cpp
trunk/core/AmAudioMixIn.cpp
trunk/core/AmAudioMixIn.h
Log:
some more modes for AudioMixIn
Modified: trunk/apps/examples/mixin_announce/Readme.mixin_announce
===================================================================
--- trunk/apps/examples/mixin_announce/Readme.mixin_announce 2008-12-19
17:13:42 UTC (rev 1202)
+++ trunk/apps/examples/mixin_announce/Readme.mixin_announce 2008-12-19
17:23:15 UTC (rev 1203)
@@ -6,20 +6,31 @@
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
+
Modified: trunk/apps/ivr/IvrAudioMixIn.cpp
===================================================================
--- trunk/apps/ivr/IvrAudioMixIn.cpp 2008-12-19 17:13:42 UTC (rev 1202)
+++ trunk/apps/ivr/IvrAudioMixIn.cpp 2008-12-19 17:23:15 UTC (rev 1203)
@@ -35,11 +35,11 @@
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,8 +69,13 @@
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;
}
Modified: trunk/core/AmAudioMixIn.cpp
===================================================================
--- trunk/core/AmAudioMixIn.cpp 2008-12-19 17:13:42 UTC (rev 1202)
+++ trunk/core/AmAudioMixIn.cpp 2008-12-19 17:23:15 UTC (rev 1203)
@@ -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 @@
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 @@
// 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 @@
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();
+ }
+
Modified: trunk/core/AmAudioMixIn.h
===================================================================
--- trunk/core/AmAudioMixIn.h 2008-12-19 17:13:42 UTC (rev 1202)
+++ trunk/core/AmAudioMixIn.h 2008-12-19 17:23:15 UTC (rev 1203)
@@ -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 @@
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; }
_______________________________________________
Semsdev mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/semsdev