|
@@ -19,18 +19,27 @@
|
|
|
#define AUDIO_STRM_ON 1
|
|
|
#define AUDIO_STRM_OFF 0
|
|
|
|
|
|
+#ifndef RVC_MAX_AUDIO_BUFFER_LEN
|
|
|
+#define RVC_MAX_AUDIO_BUFFER_LEN 1024
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifndef RVC_DELAY_AUDIO_LEN
|
|
|
+#define RVC_DELAY_AUDIO_LEN 160
|
|
|
+#endif
|
|
|
+
|
|
|
#ifndef RVC_PA_ADJUST_LATENCY_PROTOCOL_VERSION
|
|
|
#define RVC_PA_ADJUST_LATENCY_PROTOCOL_VERSION 13
|
|
|
#endif
|
|
|
|
|
|
static uint32_t latency_ms = 10; // requested initial latency in milisec: 0 use max
|
|
|
-static pa_usec_t latency = 0; //real latency in usec (for timestamping)
|
|
|
+static pa_usec_t latency = 0; //real latency in usec (for timestamping)
|
|
|
|
|
|
+static pa_usec_t play_latency = 0; //real latency in usec (for timestamping)
|
|
|
|
|
|
-pa_stream* recordstream; /* pulse audio stream*/
|
|
|
-pa_context* pa_ctx; /* pulse context*/
|
|
|
+//pa_stream* recordstream; /* pulse audio stream*/
|
|
|
+//pa_context* pa_ctx; /* pulse context*/
|
|
|
|
|
|
-pa_stream* playstream; /* pulse audio stream*/
|
|
|
+//pa_stream* playstream; /* pulse audio stream*/
|
|
|
pa_context* play_pa_ctx; /* pulse context*/
|
|
|
|
|
|
static apr_status_t read_frame(void* self, audioframe_t* frame)
|
|
@@ -352,30 +361,31 @@ int pa_get_devicelist(audio_context_t* audio_ctx)
|
|
|
int audio_init_pulseaudio(audio_context_t* audio_ctx)
|
|
|
{
|
|
|
/*assertions*/
|
|
|
- assert(NULL != audio_ctx);
|
|
|
+assert(NULL != audio_ctx);
|
|
|
|
|
|
- if (pa_get_devicelist(audio_ctx) < 0)
|
|
|
- {
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "pulse audio failed to get audio device list from pulse server.");
|
|
|
- return -1;
|
|
|
- }
|
|
|
+if (pa_get_devicelist(audio_ctx) < 0)
|
|
|
+{
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "pulse audio failed to get audio device list from pulse server.");
|
|
|
+ return -1;
|
|
|
+}
|
|
|
|
|
|
- return 0;
|
|
|
+return 0;
|
|
|
}
|
|
|
|
|
|
apr_status_t audio_context_create(apr_pool_t* pool, audio_context_t** audio_ctx)
|
|
|
{
|
|
|
audio_context_t* actx = (audio_context_t*)apr_pcalloc(pool, sizeof(audio_context_t));
|
|
|
-
|
|
|
+
|
|
|
if (NULL == actx) {
|
|
|
audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d couldn't apr_pcalloc audio context.", __FUNCTION__, __LINE__);
|
|
|
return APR_EGENERAL;
|
|
|
}
|
|
|
|
|
|
- /*initialize the mutex*/
|
|
|
- pthread_mutex_init(&actx->mutex, NULL);
|
|
|
+ actx->paudio_buffer = (char*)malloc(RVC_MAX_AUDIO_BUFFER_LEN*sizeof(char));
|
|
|
+ actx->uaudio_len = 0;
|
|
|
+
|
|
|
|
|
|
- if (audio_init_pulseaudio(actx)){
|
|
|
+ if (audio_init_pulseaudio(actx)) {
|
|
|
audio_log_v(AUDIO_LOG_LEVEL_ERROR, "%s:%d audio init pulse audio failed.", __FUNCTION__, __LINE__);
|
|
|
}
|
|
|
else
|
|
@@ -405,53 +415,92 @@ static void get_latency(pa_stream* s)
|
|
|
{
|
|
|
pa_usec_t l;
|
|
|
int negative;
|
|
|
-
|
|
|
pa_stream_get_timing_info(s);
|
|
|
-
|
|
|
if (pa_stream_get_latency(s, &l, &negative) != 0)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
+ latency = l;
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
- latency = l;
|
|
|
+static void get_play_latency(pa_stream* s)
|
|
|
+{
|
|
|
+ pa_usec_t l;
|
|
|
+ int negative;
|
|
|
|
|
|
+ pa_stream_get_timing_info(s);
|
|
|
+ if (pa_stream_get_latency(s, &l, &negative) != 0) {
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d pa_stream_get_latency failed for %s.", __FUNCTION__, __LINE__, pa_strerror(pa_context_errno(play_pa_ctx)));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ play_latency = l;
|
|
|
}
|
|
|
|
|
|
|
|
|
+
|
|
|
static void stream_write_request_cb(pa_stream* s, size_t length, void* data)
|
|
|
{
|
|
|
audio_context_t* audio_ctx = (audio_context_t*)data;
|
|
|
- if (audio_ctx->channels == 0) {
|
|
|
- return;
|
|
|
- }
|
|
|
|
|
|
- if (audio_ctx->samprate == 0) {
|
|
|
+ if (0 == audio_ctx->play_channels || 0 == audio_ctx->play_samprate) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d .", __FUNCTION__, __LINE__);
|
|
|
- while (pa_stream_writable_size(s) > 0)
|
|
|
+ size_t nbytes = 0;
|
|
|
+ void* audiodata;
|
|
|
+ while ((nbytes = pa_stream_writable_size(s)) != (size_t)-1)
|
|
|
{
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d .", __FUNCTION__, __LINE__);
|
|
|
- /*write to stream*/
|
|
|
- char playBuffer[160] = { 0 };
|
|
|
- if (audio_ctx->bstart_put_flag && audio_ctx->micspkpulse_parent) {
|
|
|
- int iget = delay_buf_get((delay_buf*)((audiomicspkpulse_t*)(audio_ctx->micspkpulse_parent))->ply_buf, (short*)playBuffer);
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d delay_buf_get ret is %d.", __FUNCTION__, __LINE__, iget);
|
|
|
+ get_play_latency(s);
|
|
|
+ if (0 == nbytes){
|
|
|
+ return;
|
|
|
}
|
|
|
- if (pa_stream_write(playstream, (void*)& playBuffer, write,
|
|
|
- NULL, (int64_t)0, PA_SEEK_RELATIVE) != PA_OK)
|
|
|
+
|
|
|
+ /*write to stream*/
|
|
|
+ if (PA_OK == pa_stream_begin_write(s, &audiodata, &nbytes))
|
|
|
{
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "AUDIO: pulse audio pa_stream_write failed!");
|
|
|
- return;
|
|
|
+ //audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d pa_stream_begin_write nbytes = %d.", __FUNCTION__, __LINE__, nbytes);
|
|
|
+
|
|
|
+ while (audio_ctx->uaudio_len < nbytes)
|
|
|
+ {
|
|
|
+ char delaybuffer[RVC_DELAY_AUDIO_LEN] = { 0 };
|
|
|
+ if (audio_ctx->bstart_get_flag && audio_ctx->micspkpulse_parent) {
|
|
|
+ if (0 == ((audiomicspkpulse_t*)(audio_ctx->micspkpulse_parent))->ply_buf_cnt) {
|
|
|
+ int iget = delay_buf_get((delay_buf*)((audiomicspkpulse_t*)(audio_ctx->micspkpulse_parent))->ply_dbuf, (short*)delaybuffer);
|
|
|
+ if (0 == iget){
|
|
|
+ if (audio_ctx->uaudio_len + RVC_DELAY_AUDIO_LEN < RVC_MAX_AUDIO_BUFFER_LEN){
|
|
|
+ memcpy(audio_ctx->paudio_buffer + audio_ctx->uaudio_len, delaybuffer, RVC_DELAY_AUDIO_LEN);
|
|
|
+ audio_ctx->uaudio_len += RVC_DELAY_AUDIO_LEN;
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ memcpy(audio_ctx->paudio_buffer + audio_ctx->uaudio_len, delaybuffer, RVC_MAX_AUDIO_BUFFER_LEN - audio_ctx->uaudio_len);
|
|
|
+ audio_ctx->uaudio_len = nbytes = RVC_MAX_AUDIO_BUFFER_LEN;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ int ileft = audio_ctx->uaudio_len - nbytes;
|
|
|
+ memcpy(audiodata, audio_ctx->paudio_buffer, nbytes);
|
|
|
+ audio_ctx->uaudio_len = ileft;
|
|
|
+ if (ileft > 0) {
|
|
|
+ memcpy(audio_ctx->paudio_buffer, audio_ctx->paudio_buffer + nbytes, ileft);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (PA_OK != pa_stream_write(s, audiodata, nbytes, NULL, 0, PA_SEEK_RELATIVE)) {
|
|
|
+ //audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d pa_stream_write failed.", __FUNCTION__, __LINE__);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ //else {
|
|
|
+ // audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d pa_stream_write success.", __FUNCTION__, __LINE__);
|
|
|
+ //}
|
|
|
}
|
|
|
else {
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d AUDIO: pulse audio pa_stream_write success!", __FUNCTION__, __LINE__);
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d pa_stream_begin_write failed for %s.", __FUNCTION__, __LINE__, pa_strerror(pa_context_errno(play_pa_ctx)));
|
|
|
}
|
|
|
-
|
|
|
- pa_stream_drop(s); /*clean the samples*/
|
|
|
}
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d .", __FUNCTION__, __LINE__);
|
|
|
}
|
|
|
|
|
|
static void stream_request_cb(pa_stream* s, size_t length, void* data)
|
|
@@ -480,7 +529,7 @@ static void stream_request_cb(pa_stream* s, size_t length, void* data)
|
|
|
/*read from stream*/
|
|
|
if (pa_stream_peek(s, &inputBuffer, &length) < 0)
|
|
|
{
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "AUDIO: pulse audio pa_stream_peek failed");
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "AUDIO: pulse audio pa_stream_peek failed.");
|
|
|
return;
|
|
|
}
|
|
|
else {
|
|
@@ -516,6 +565,7 @@ void* pulse_read_audio(void* data)
|
|
|
|
|
|
pa_mainloop* pa_ml;
|
|
|
pa_mainloop_api* pa_mlapi;
|
|
|
+ pa_context* pa_ctx;
|
|
|
pa_buffer_attr bufattr;
|
|
|
pa_sample_spec ss;
|
|
|
pa_stream_flags_t flags = PA_STREAM_NOFLAGS;
|
|
@@ -566,7 +616,7 @@ void* pulse_read_audio(void* data)
|
|
|
ss.channels = audio_ctx->channels;
|
|
|
ss.format = audio_ctx->eformat/*PA_SAMPLE_FLOAT32LE*/; /*for PCM -> PA_SAMPLE_S16LE*/
|
|
|
|
|
|
- recordstream = pa_stream_new(pa_ctx, "Record", &ss, NULL);
|
|
|
+ pa_stream* recordstream = pa_stream_new(pa_ctx, "Record", &ss, NULL);
|
|
|
if (!recordstream){
|
|
|
audio_log_v(AUDIO_LOG_LEVEL_INFO, "pulse audio pa_stream_new failed (chan:%d rate:%d)", ss.channels, ss.rate);
|
|
|
}
|
|
@@ -610,7 +660,7 @@ void* pulse_read_audio(void* data)
|
|
|
|
|
|
if (r < 0)
|
|
|
{
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "AUDIO: (pulse audio) pa_stream_connect_record failed for %s.", pa_context_errno(pa_ctx));
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "AUDIO: (pulse audio) pa_stream_connect_record failed for %d.", pa_context_errno(pa_ctx));
|
|
|
finish(pa_ctx, pa_ml);
|
|
|
return ((void*)-1);
|
|
|
}
|
|
@@ -658,6 +708,13 @@ int audio_start_pulseaudio(audio_context_t* audio_ctx)
|
|
|
}
|
|
|
|
|
|
|
|
|
+static void stream_latency_cb(pa_stream* p, void* userdata)
|
|
|
+{
|
|
|
+ pa_operation* o;
|
|
|
+ o = pa_stream_update_timing_info(p, NULL, NULL);
|
|
|
+ pa_operation_unref(o);
|
|
|
+}
|
|
|
+
|
|
|
void* pulse_write_audio(void* data)
|
|
|
{
|
|
|
audio_context_t* audio_ctx = (audio_context_t*)data;
|
|
@@ -670,6 +727,7 @@ void* pulse_write_audio(void* data)
|
|
|
pa_sample_spec ss;
|
|
|
pa_stream_flags_t flags = PA_STREAM_NOFLAGS;
|
|
|
int32_t pastream_flag = (int32_t)PA_STREAM_NOFLAGS;
|
|
|
+
|
|
|
int r;
|
|
|
int pa_ready = 0;
|
|
|
char* dev = NULL;
|
|
@@ -682,7 +740,7 @@ void* pulse_write_audio(void* data)
|
|
|
play_pa_ctx = pa_context_new(pa_mlapi, "rvc play api");
|
|
|
|
|
|
if (PA_OK != pa_context_connect(play_pa_ctx, NULL, PA_CONTEXT_NOFLAGS, NULL)) {
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "AUDIO: PULSE - unable to connect to server: pa_context_connect failed for %s.", pa_context_errno(play_pa_ctx));
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "AUDIO: PULSE - unable to connect to server: pa_context_connect failed for %d.", pa_context_errno(play_pa_ctx));
|
|
|
finish(play_pa_ctx, pa_ml);
|
|
|
return ((void*)-1);
|
|
|
}
|
|
@@ -695,38 +753,35 @@ void* pulse_write_audio(void* data)
|
|
|
* If there's an error, the callback will set pa_ready to 2
|
|
|
*/
|
|
|
pa_context_set_state_callback(play_pa_ctx, pa_state_cb, &pa_ready);
|
|
|
-
|
|
|
/*
|
|
|
* We can't do anything until PA is ready, so just iterate the mainloop
|
|
|
* and continue
|
|
|
*/
|
|
|
|
|
|
-
|
|
|
while (pa_ready == 0) {
|
|
|
pa_mainloop_iterate(pa_ml, 1, NULL);
|
|
|
}
|
|
|
if (pa_ready == 2) {
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d", __FUNCTION__, __LINE__);
|
|
|
finish(play_pa_ctx, pa_ml);
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d", __FUNCTION__, __LINE__);
|
|
|
return ((void*)-1);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/* set the sample spec (frame rate, channels and format) */
|
|
|
ss.rate = audio_ctx->play_samprate;
|
|
|
ss.channels = audio_ctx->play_channels;
|
|
|
ss.format = audio_ctx->play_eformat;
|
|
|
|
|
|
- playstream = pa_stream_new(play_pa_ctx, "playStream", &ss, NULL);
|
|
|
+ pa_stream* playstream = pa_stream_new(play_pa_ctx, "playStream", &ss, NULL);
|
|
|
if (!playstream) {
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "play audio pa_stream_new failed (chan:%d rate:%d) for %s.", ss.channels, ss.rate, pa_context_errno(play_pa_ctx));
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "play audio pa_stream_new failed (chan:%d rate:%d) for %d.", ss.channels, ss.rate, pa_context_errno(play_pa_ctx));
|
|
|
}
|
|
|
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "play audio stream state is %d", pa_stream_get_state(playstream));
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "play audio stream state is %d.", pa_stream_get_state(playstream));
|
|
|
/* define the callbacks */
|
|
|
pa_stream_set_write_callback(playstream, stream_write_request_cb, (void*)audio_ctx);
|
|
|
|
|
|
+ pa_stream_set_latency_update_callback(playstream, stream_latency_cb, NULL);
|
|
|
+
|
|
|
// Set properties of the record buffer
|
|
|
pa_zero(bufattr);
|
|
|
/* optimal value for all is (uint32_t)-1 ~= 2 sec */
|
|
@@ -734,44 +789,36 @@ void* pulse_write_audio(void* data)
|
|
|
bufattr.prebuf = (uint32_t)-1;
|
|
|
bufattr.minreq = (uint32_t)-1;
|
|
|
|
|
|
- if (audio_ctx->latency > 0) {
|
|
|
- bufattr.fragsize = bufattr.tlength = pa_usec_to_bytes((audio_ctx->latency * 1000) * PA_USEC_PER_MSEC, &ss);
|
|
|
+ if (audio_ctx->play_latency > 0) {
|
|
|
+ bufattr.fragsize = bufattr.tlength = pa_usec_to_bytes((audio_ctx->play_latency * 1000) * PA_USEC_PER_MSEC, &ss);
|
|
|
pastream_flag |= PA_STREAM_ADJUST_LATENCY;
|
|
|
}
|
|
|
- else {
|
|
|
+ else{
|
|
|
bufattr.fragsize = bufattr.tlength = (uint32_t)-1;
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
pastream_flag |= PA_STREAM_INTERPOLATE_TIMING;
|
|
|
pastream_flag |= PA_STREAM_AUTO_TIMING_UPDATE;
|
|
|
|
|
|
dev = audio_ctx->list_output_devices[audio_ctx->play_device].name;
|
|
|
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "play audio connecting to device %s (channels %d rate %d)", dev, ss.channels, ss.rate);
|
|
|
-
|
|
|
- //if (update_speaker_volume_at_startup_) {
|
|
|
- // pa_cvolume cVolumes;
|
|
|
- // ptr_cvolume = &cVolumes;
|
|
|
-
|
|
|
- // // Set the same volume for all channels
|
|
|
- // const pa_sample_spec* spec = LATE(pa_stream_get_sample_spec)(_playStream);
|
|
|
- // LATE(pa_cvolume_set)(&cVolumes, spec->channels, volume);
|
|
|
- // update_speaker_volume_at_startup_ = false;
|
|
|
- //}
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "play audio connecting to device %s (channels %d rate %d buf fragsize %d buf tlength %d)", dev, ss.channels, ss.rate, bufattr.fragsize, bufattr.tlength);
|
|
|
|
|
|
// Connect the stream to a sink
|
|
|
r = pa_stream_connect_playback(playstream, dev, &bufattr, (pa_stream_flags_t)pastream_flag, ptr_cvolume, NULL);
|
|
|
if (PA_OK != r)
|
|
|
{
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "play stream connected failed for %s.", pa_context_errno(play_pa_ctx));
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "play stream connected failed for %d.", pa_context_errno(play_pa_ctx));
|
|
|
finish(play_pa_ctx, pa_ml);
|
|
|
return ((void*)-1);
|
|
|
}
|
|
|
+ else {
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "play stream connected.");
|
|
|
+ const pa_sample_spec* spec = pa_stream_get_sample_spec(playstream);
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "play stream spec->format = %d, spec->channels = %d, spec->rate = %d.", spec->format, spec->channels, spec->rate);
|
|
|
+ }
|
|
|
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "play stream connected");
|
|
|
-
|
|
|
- get_latency(playstream);
|
|
|
+ get_play_latency(playstream);
|
|
|
|
|
|
/*
|
|
|
* Iterate the main loop while streaming. The second argument is whether
|
|
@@ -804,7 +851,7 @@ int audio_start_audioplay(audio_context_t* audio_ctx)
|
|
|
if (pthread_create(&audio_ctx->writethreadid, NULL, pulse_write_audio, (void*)audio_ctx)) {
|
|
|
audio_log_v(AUDIO_LOG_LEVEL_INFO, "AUDIO: (pulse audio) write thread creation failed.");
|
|
|
audio_ctx->play_stream_flag = AUDIO_STRM_OFF;
|
|
|
- return (-1);
|
|
|
+ return -1;
|
|
|
}
|
|
|
else {
|
|
|
audio_log_v(AUDIO_LOG_LEVEL_INFO, "AUDIO: (pulse audio) write thread create success, and thread id is %u.", audio_ctx->writethreadid);
|
|
@@ -862,15 +909,21 @@ void audio_close_pulseaudio(audio_context_t* audio_ctx)
|
|
|
audio_stop_pulseaudio(audio_ctx);
|
|
|
}
|
|
|
|
|
|
- if (audio_ctx->list_input_devices != NULL) {
|
|
|
+ if (NULL != audio_ctx->list_input_devices) {
|
|
|
free(audio_ctx->list_input_devices);
|
|
|
}
|
|
|
audio_ctx->list_input_devices = NULL;
|
|
|
|
|
|
- if (audio_ctx->list_output_devices != NULL) {
|
|
|
+ if (NULL != audio_ctx->list_output_devices) {
|
|
|
free(audio_ctx->list_output_devices);
|
|
|
}
|
|
|
audio_ctx->list_output_devices = NULL;
|
|
|
+
|
|
|
+ if (NULL != audio_ctx->paudio_buffer){
|
|
|
+ free(audio_ctx->paudio_buffer);
|
|
|
+ }
|
|
|
+ audio_ctx->paudio_buffer = NULL;
|
|
|
+ audio_ctx->uaudio_len = 0;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -958,7 +1011,8 @@ static int initialize_speaker(audiomicspkpulse_t* micspk)
|
|
|
}
|
|
|
|
|
|
audio_set_playdeviceid(micspk->audio_ctx, ply_dev_id);
|
|
|
- audio_set_play_latency(micspk->audio_ctx, 0.01);
|
|
|
+ //audio_set_play_latency(micspk->audio_ctx, 0.01325);
|
|
|
+ audio_set_play_latency(micspk->audio_ctx, 0.02);
|
|
|
audio_set_play_samprate(micspk->audio_ctx, 8000);
|
|
|
audio_set_play_channels(micspk->audio_ctx, 1);
|
|
|
audio_set_playformat(micspk->audio_ctx, PA_SAMPLE_S16LE);
|
|
@@ -993,11 +1047,11 @@ static int initialize_micro(audiomicspkpulse_t* micspk)
|
|
|
audio_set_channels(micspk->audio_ctx, 1);
|
|
|
audio_set_capformat(micspk->audio_ctx, PA_SAMPLE_S16LE);
|
|
|
|
|
|
- if (0 == audio_start_pulseaudio(micspk->audio_ctx)){
|
|
|
+ if (0 == audio_start_pulseaudio(micspk->audio_ctx)) {
|
|
|
audio_log_v(AUDIO_LOG_LEVEL_INFO, "audio micro create success, audio input device start pulse audio success!");
|
|
|
iret = 0;
|
|
|
}
|
|
|
- else{
|
|
|
+ else {
|
|
|
audio_log_v(AUDIO_LOG_LEVEL_INFO, "audio micro create success, audio input device start pulse audio failed!");
|
|
|
}
|
|
|
|
|
@@ -1049,7 +1103,7 @@ void* APR_THREAD_FUNC* audiowork_proc(apr_thread_t* threadhandle, void* param)
|
|
|
// record and play <---> record and play
|
|
|
//
|
|
|
audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d micspk addr is 0x%0x, current sem addr is 0x%0x.started flag is %s.", __FUNCTION__, __LINE__, param, micspk->audio_device_started_sem, micspk->baudio_device_started_flag ? "true" : "false");
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d micspk->opt = %d.", __FUNCTION__, __LINE__, micspk->opt);
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d micspk->opt = %d.", __FUNCTION__, __LINE__, micspk->opt);
|
|
|
|
|
|
if (micspk->opt & AMS_OPT_RECPLAY) {
|
|
|
rc = initialize_speaker(micspk);
|
|
@@ -1201,7 +1255,7 @@ apr_status_t audiomicspkpulse_create(apr_pool_t* pool,
|
|
|
apr_status_t err = apr_thread_create(&micspk->audio_work_thread, NULL, &audiowork_proc, micspk, pool);
|
|
|
if (APR_SUCCESS == err) {
|
|
|
bool baudio_work_thread_exit = false;
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d audio_work_thread id is %d.", __FUNCTION__, __LINE__, micspk->audio_work_thread);
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d audio_work_thread id is %u.", __FUNCTION__, __LINE__, micspk->audio_work_thread);
|
|
|
|
|
|
do {
|
|
|
struct timespec ts;
|
|
@@ -1239,9 +1293,9 @@ apr_status_t audiomicspkpulse_create(apr_pool_t* pool,
|
|
|
|
|
|
micspk->audio_ctx->micspkpulse_parent = (void*)micspk;
|
|
|
micspk->audio_ctx->bstart_put_flag = true;
|
|
|
+ micspk->audio_ctx->bstart_get_flag = true;
|
|
|
*p_micspk = micspk;
|
|
|
|
|
|
-
|
|
|
return APR_SUCCESS;
|
|
|
}
|
|
|
|
|
@@ -1249,8 +1303,6 @@ apr_status_t audiomicspkpulse_create(apr_pool_t* pool,
|
|
|
void audiomicspkpulse_destroy(audiomicspkpulse_t* micspk)
|
|
|
{
|
|
|
assert(NULL != micspk);
|
|
|
- /*destroy the mutex*/
|
|
|
- pthread_mutex_destroy(&micspk->audio_ctx->mutex);
|
|
|
|
|
|
sem_post(micspk->audio_device_started_sem);
|
|
|
|