2 * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #include <alsa/asoundlib.h>
26 #include "static_queue.h"
28 #define FIXME_FORMAT_SIZE 2
29 #define CTL_LOOPBACK_DEVICE "hw:Loopback"
30 #define PCM_MASTER_ACTIVE "PCM Master Active"
31 #define PCM_SLAVE_ACTIVE "PCM Slave Active"
59 unsigned int buffer_size;
60 unsigned int buffer_time;
61 unsigned int period_size;
62 unsigned int buffer_frame;
63 unsigned int period_time;
68 struct loopback_dev *dev[DEV_MAX];
69 struct pollfd pfds[POLL_MAX];
85 snd_ctl_elem_value_t *elm_active;
87 /* related to reference */
94 sq *refq; /* recording consumption */
95 sq *master_refq; /* playback feeding */
100 static int __open_loopback_controls(loopback_t *loopback, const char *dev, const char *elm);
101 static int __check_ctl_active_event(loopback_t *loopback, int *status);
102 static int __handle_revents(loopback_t *loopback, int mode, unsigned short revents);
103 static void *__loop_thread(void *userdata);
105 static void __close_dev(loopback_t *loopback);
106 static int __open_dev(loopback_t *loopback, int index, struct pollfd *pfd);
107 static int __xrun_recovery(loopback_dev_t *dev, int err);
108 static int __print_buffer(loopback_t *loopback);
110 loopback_dev_t *loopback_alloc_device(const char *name, int mode, int rate,
111 int channels, int format, int buffer_frame)
113 loopback_dev_t *dev = (loopback_dev_t *)calloc(1, sizeof(struct loopback_dev));
115 LOGE("Failed to alloc memory");
119 dev->name = strdup(name);
122 dev->channels = channels;
123 dev->format = format;
124 dev->buffer_frame = buffer_frame;
129 int loopback_free_device(loopback_dev_t *dev)
142 static int __open_loopback_controls(loopback_t *loopback, const char *dev, const char *elm)
146 const char *elm_name = elm;
148 loopback->ctl_id = dev[12] - '0';
149 loopback->ctl_subid = dev[14] - '0';
151 for (k = 0; *dev != ',' && *dev != '\0'; dev++)
152 ctl_name[k++] = *dev;
155 err = snd_ctl_open(&loopback->ctl, ctl_name, SND_CTL_NONBLOCK);
157 LOGE("Failed to open capture control. name(%s)", ctl_name);
161 err = snd_ctl_subscribe_events(loopback->ctl, 1);
163 LOGE("Failed to subscribe ctrl event");
167 if (snd_ctl_elem_value_malloc(&loopback->elm_active) < 0) {
168 LOGE("Failed to alloc elem");
172 snd_ctl_elem_value_set_interface(loopback->elm_active, SND_CTL_ELEM_IFACE_PCM);
173 snd_ctl_elem_value_set_device(loopback->elm_active, loopback->ctl_id);
174 snd_ctl_elem_value_set_subdevice(loopback->elm_active, loopback->ctl_subid);
175 snd_ctl_elem_value_set_name(loopback->elm_active, elm_name);
177 LOGD("loopback ctrl opened. name(%s) id(%d) subid(%d) elm_name(%s)",
178 ctl_name, loopback->ctl_id, loopback->ctl_subid, elm_name);
184 snd_ctl_close(loopback->ctl);
185 if (loopback->elm_active)
186 snd_ctl_elem_value_free(loopback->elm_active);
191 loopback_t *loopback_create(const char *name,
192 loopback_dev_t *capture,
193 loopback_dev_t *playback,
194 int process_frame, int nbuffer)
196 const char *elm_name;
198 loopback_t *loopback;
201 if (capture->rate != playback->rate ||
202 capture->channels != playback->channels ||
203 capture->format != playback->format) {
204 /* TODO: support resample or remap */
205 LOGE("capture and playback info is not matched."
206 "rate(%d:%d), channels(%d:%d), format(%d:%d)",
207 capture->rate, playback->rate,
208 capture->channels, playback->channels,
209 capture->format, playback->format);
213 len = strlen(CTL_LOOPBACK_DEVICE);
214 if (!strncmp(capture->name, CTL_LOOPBACK_DEVICE, len))
215 dev_loopback = capture->name;
216 else if (!strncmp(playback->name, CTL_LOOPBACK_DEVICE, len))
217 dev_loopback = playback->name;
223 loopback = (loopback_t *)calloc(1, sizeof(struct loopback));
225 LOGE("Failed to alloc memory");
228 loopback->name = name ? strdup(name) : strdup("noname");
229 loopback->dev[CAPTURE] = capture;
230 loopback->dev[PLAYBACK] = playback;
231 loopback->state = STATE_STOPPED;
233 /* TODO: Support resample */
234 loopback->channels = capture->channels;
235 loopback->rate = capture->rate;
237 elm_name = dev_loopback == capture->name ? PCM_SLAVE_ACTIVE : PCM_MASTER_ACTIVE;
238 if (__open_loopback_controls(loopback, dev_loopback, elm_name)) {
239 LOGE("Failed to open loopback control. name(%s)", elm_name);
243 loopback->ec_frame = process_frame;
244 bytes = loopback->ec_frame * capture->channels * FIXME_FORMAT_SIZE;
246 // TEMP: padding for speex
249 loopback->q = create_static_queue(bytes, nbuffer);
251 LOGE("Failed to create sq");
254 LOGI("created static-queue bytes(%d), n(%d)", bytes, nbuffer);
256 loopback->empty_buf = (char *)calloc(1, bytes);
257 if (!loopback->empty_buf) {
258 LOGE("Failed to alloc empty_buf\n");
262 if (pipe(loopback->wakeup)) {
263 LOGE("Failed to create pipe");
271 snd_ctl_close(loopback->ctl);
272 if (loopback->elm_active)
273 snd_ctl_elem_value_free(loopback->elm_active);
275 destory_static_queue(loopback->q);
276 if (loopback->empty_buf)
277 free(loopback->empty_buf);
284 int loopback_start(loopback_t *loopback)
287 LOGE("loopback is not ready\n");
291 loopback->pfds[POLL_WAKEUP].fd = loopback->wakeup[0];
292 loopback->pfds[POLL_WAKEUP].events = POLLIN;
295 if (snd_ctl_poll_descriptors(loopback->ctl, &(loopback->pfds[POLL_CTRL]), 1) <= 0) {
296 LOGE("cannot get ctrl descriptor\n");
300 loopback->poll_cnt = POLL_CTRL + 1;
303 if (loopback->op->init(loopback->ec_frame, loopback->rate, loopback->channels)) {
304 LOGE("ec init failed\n");
309 if (pthread_create(&loopback->t, NULL, __loop_thread, (void *)loopback) < 0) {
310 LOGE("failed to create thread\nn");
317 int loopback_stop(loopback_t *loopback)
327 n = write(loopback->wakeup[1], &dummy, 1);
329 LOGE("Failed to wake up thread");
333 if (pthread_join(loopback->t, (void **)&status)) {
334 LOGE("thread join failed\nn");
343 int loopback_destroy(loopback_t *loopback)
348 if (loopback->state == STATE_RUNNING) {
349 LOGE("Failed to destroy loopback. state running");
354 destory_static_queue(loopback->q);
357 destory_static_queue(loopback->refq);
359 if (loopback->name) {
360 free(loopback->name);
361 loopback->name = NULL;
364 if (loopback->empty_buf) {
365 free(loopback->empty_buf);
366 loopback->empty_buf = NULL;
369 if (loopback->elm_active) {
370 snd_ctl_elem_value_free(loopback->elm_active);
371 loopback->elm_active = NULL;
375 snd_ctl_close(loopback->ctl);
376 loopback->ctl = NULL;
379 __close_dev(loopback);
386 int loopback_bind_reference(loopback_t *loopback, loopback_t *ref, ec_operation_t *op)
388 if (loopback->state == STATE_RUNNING) {
389 LOGE("Failed to bind. state(%d)", loopback->state);
393 if (loopback->refq) {
394 LOGE("Failed to bind. already bound.");
399 loopback->refq = create_static_queue(0, 0);
401 ref->master = loopback;
402 ref->master_refq = loopback->refq;
404 LOGI("bind loopback master(%s), refernece(%s)", loopback->name, ref->name);
409 static int __handle_revents(struct loopback *loopback, int mode, unsigned short revents)
412 struct loopback_dev *dev = loopback->dev[mode];
413 snd_pcm_sframes_t frames = loopback->ec_frame;
414 snd_pcm_sframes_t avail;
416 if (revents & POLLIN) {
417 unsigned char *recbuf;
420 avail = snd_pcm_avail_update(dev->handle);
422 LOGW("%s: Can't get avail: %s", dev->name, snd_strerror(avail));
424 if (__xrun_recovery(dev, avail)) {
425 LOGE("%s: AEC will be stopped.", dev->name);
429 } else if (avail < frames) {
430 LOGW("%s: not enough avail(%ld) < frames(%ld)\n", dev->name, avail, frames);
434 rec = sq_get_node_lock(loopback->q);
436 LOGE("%s: Failed to get valid sq node. maybe overflow", dev->name);
440 recbuf = sq_get_buffer(rec);
441 if ((err = snd_pcm_readi(dev->handle, recbuf, frames)) < 0) {
442 LOGE("%s: Failed to read: %s(%d)", dev->name, snd_strerror(err), err);
444 sq_put_node_lock(rec);
445 __xrun_recovery(dev, err);
450 sq_enqueue_node(loopback->q, rec);
452 } else if (revents & POLLOUT) {
453 unsigned char *playbuf;
456 avail = snd_pcm_avail_update(dev->handle);
458 LOGW("%s: Can't get avail. Try to recover: %s", dev->name, snd_strerror(avail));
460 if (__xrun_recovery(dev, avail))
461 LOGE("%s: Failed to recover. AEC will be stopped.", dev->name);
465 } else if (avail < frames) {
466 LOGW("%s: not enough avail(%ld) < frames(%ld)\n", dev->name, avail, frames);
470 play = sq_dequeue_node(loopback->q);
472 if ((err = snd_pcm_writei(dev->handle, loopback->empty_buf, frames)) < 0)
473 LOGE("%s: Failed to write. frame(%ld): %s(%d)",
474 dev->name, frames, snd_strerror(err), err);
478 playbuf = sq_get_buffer(play);
480 /* only recording thread */
481 if (loopback->refq && !sq_is_empty_lock(loopback->refq)) {
482 sqbuffer *ref = sq_dequeue_node_lock(loopback->refq);
483 sqbuffer *out = sq_get_node_lock(loopback->q);
484 unsigned char *refbuf = sq_get_buffer(ref);
485 unsigned char *outbuf = sq_get_buffer(out);
487 loopback->op->process(playbuf, refbuf, outbuf);
489 sq_put_node_lock(play);
490 sq_put_node_lock(ref);
497 if ((err = snd_pcm_writei(dev->handle, playbuf, frames)) < 0) {
498 LOGE("%s: Failed to write: %s", dev->name, snd_strerror(err));
499 if (__xrun_recovery(dev, err))
500 sq_put_node_lock(play);
504 /* only reference thread */
505 if (loopback->master && loopback->master->state == STATE_RUNNING) {
506 sq_enqueue_node_lock(loopback->master_refq, play);
510 sq_put_node_lock(play);
512 LOGD("unknown event %x\n", revents);
517 static int __check_ctl_active_event(loopback_t *loopback, int *status)
520 unsigned int event_mask;
522 snd_ctl_elem_id_t *id1, *id2;
524 snd_ctl_event_alloca(&ev);
525 snd_ctl_elem_id_alloca(&id1);
526 snd_ctl_elem_id_alloca(&id2);
528 while ((err = snd_ctl_read(loopback->ctl, ev)) != 0 && err != -EAGAIN);
530 snd_ctl_elem_value_get_id(loopback->elm_active, id1);
531 snd_ctl_event_elem_get_id(ev, id2);
533 event_mask = snd_ctl_event_elem_get_mask(ev);
535 if (event_mask == SND_CTL_EVENT_MASK_REMOVE || !(event_mask & SND_CTL_EVENT_MASK_VALUE))
539 LOGD("intf(%d:%d) id(%d:%d) subid(%d:%d) elem(%s:%s) index(%d:%d)\n",
540 snd_ctl_elem_id_get_interface(id1), snd_ctl_elem_id_get_interface(id2),
541 snd_ctl_elem_id_get_device(id1), snd_ctl_elem_id_get_device(id2),
542 snd_ctl_elem_id_get_subdevice(id1), snd_ctl_elem_id_get_subdevice(id2),
543 snd_ctl_elem_id_get_name(id1), snd_ctl_elem_id_get_name(id2),
544 snd_ctl_elem_id_get_index(id1), snd_ctl_elem_id_get_index(id2));
547 if (snd_ctl_elem_id_get_interface(id1) != snd_ctl_elem_id_get_interface(id2))
550 if (snd_ctl_elem_id_get_device(id1) != snd_ctl_elem_id_get_device(id2))
553 if (snd_ctl_elem_id_get_subdevice(id1) != snd_ctl_elem_id_get_subdevice(id2))
556 if (strcmp(snd_ctl_elem_id_get_name(id1), snd_ctl_elem_id_get_name(id2)) != 0)
559 if (snd_ctl_elem_id_get_index(id1) != snd_ctl_elem_id_get_index(id2))
562 err = snd_ctl_elem_read(loopback->ctl, loopback->elm_active);
564 LOGE("Failed to read ctl elem\n");
568 err = snd_ctl_elem_value_get_boolean(loopback->elm_active, 0);
572 LOGE("dev:subid:elm(%d:%d:%s) is changed to (%d)\n",
573 snd_ctl_elem_id_get_device(id2), snd_ctl_elem_id_get_subdevice(id2),
574 snd_ctl_elem_id_get_name(id2), *status);
579 static void *__loop_thread(void *userdata)
582 unsigned short revents;
583 struct loopback *loopback = (struct loopback *)userdata;
584 struct loopback_dev **dev = loopback->dev;
586 LOGI("start thread. name(%s), capture(%s) playback(%s), frame(%d), poll_cnt(%d)\n",
587 loopback->name, dev[CAPTURE]->name, dev[PLAYBACK]->name,
588 loopback->ec_frame, loopback->poll_cnt);
591 if (poll(loopback->pfds, loopback->poll_cnt, -1) < 0) {
592 LOGE("poll err %s\n", strerror(errno));
596 if (loopback->quit) {
598 loopback->op->deinit();
600 __close_dev(loopback);
601 loopback->state = STATE_STOPPED;
603 LOGE("thread(%s) exit\n", loopback->name);
609 if (!snd_ctl_poll_descriptors_revents(loopback->ctl, &loopback->pfds[POLL_CTRL], 1, &revents)) {
612 if (__check_ctl_active_event(loopback, &onoff)) {
613 if (onoff) { /* Turn on */
614 if (__open_dev(loopback, PLAYBACK, loopback->pfds+POLL_PLAYBACK)) {
615 LOGE("failed to open playback dev\n");
619 if (__open_dev(loopback, CAPTURE, loopback->pfds+POLL_CAPTURE)) {
620 LOGE("failed to open capture dev\n");
624 if ((err = snd_pcm_start(dev[CAPTURE]->handle)) < 0)
625 LOGE("capture dev start failed. %s\n", snd_strerror(err));
627 loopback->state = STATE_RUNNING;
629 } else { /* Turn off */
630 loopback->state = STATE_STOPPED;
632 __close_dev(loopback);
634 sq_flush(loopback->q);
635 sq_flush_lock(loopback->refq);
644 if (loopback->state != STATE_RUNNING)
648 if (!snd_pcm_poll_descriptors_revents(dev[CAPTURE]->handle,
649 &loopback->pfds[POLL_CAPTURE], 1, &revents)) {
651 __handle_revents(loopback, CAPTURE, revents);
654 if (!snd_pcm_poll_descriptors_revents(dev[PLAYBACK]->handle,
655 &loopback->pfds[POLL_PLAYBACK], 1, &revents)) {
657 __handle_revents(loopback, PLAYBACK, revents);
660 if (loopback->logcnt++ > 100) {
661 loopback->logcnt = 0;
662 __print_buffer(loopback);
667 static void __close_dev(loopback_t *loopback)
669 if (loopback->dev[PLAYBACK]->handle) {
670 snd_pcm_close(loopback->dev[PLAYBACK]->handle);
671 loopback->dev[PLAYBACK]->handle = NULL;
673 loopback->poll_cnt--;
675 if (loopback->dev[CAPTURE]->handle) {
676 snd_pcm_close(loopback->dev[CAPTURE]->handle);
677 loopback->dev[CAPTURE]->handle = NULL;
679 loopback->poll_cnt--;
682 static int __xrun_recovery(struct loopback_dev *dev, int err)
684 snd_pcm_state_t state;
686 state = snd_pcm_state(dev->handle);
688 if (state != SND_PCM_STATE_XRUN) {
689 LOGW("Invalid state(%d)", state);
693 LOGE("%s: Try to recover. state(%d)\n", dev->name, state);
695 if (err == -EPIPE) { /* underrun or overrun */
696 err = snd_pcm_prepare(dev->handle);
698 LOGE("XRUN: Failed to prepare pcm\n");
701 } else if (err == -ESTRPIPE) { /* suspended */
702 while ((err = snd_pcm_resume(dev->handle)) == -EAGAIN)
706 LOGE("XRUN: Failed to resume pcm\n");
710 err = snd_pcm_prepare(dev->handle);
712 LOGE("XRUN: Failed to prepare pcm\n");
716 LOGE("XRUN: Unknown error\n");
720 // TODO: add device close open
721 LOGE("XRUN: recovered");
726 static int __open_dev(loopback_t *loopback, int index, struct pollfd *pfd)
729 int flags = SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_RESAMPLE | SND_PCM_NO_AUTO_FORMAT;
730 unsigned int buffer_time;
732 const char *name = loopback->dev[index]->name;
733 int mode = loopback->dev[index]->mode;
734 unsigned int rate = loopback->dev[index]->rate;
735 unsigned int _rate = rate;
736 int channels = loopback->dev[index]->channels;
737 //int format = dev->format;
738 snd_pcm_uframes_t buffer_frame = loopback->dev[index]->buffer_frame;
739 struct loopback_dev *dev = loopback->dev[index];
741 snd_pcm_stream_t _mode = (mode == CAPTURE) ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK;
742 snd_pcm_sw_params_t *sw_params = NULL;
743 snd_pcm_hw_params_t *hw_params = NULL;
744 snd_pcm_uframes_t buffer_size, period_size;
746 if ((err = snd_pcm_open(&dev->handle, name, _mode, flags)) < 0) {
747 LOGE("%s: cannot open audio device (%s)\n", name, snd_strerror(err));
751 if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
752 LOGE("%s: cannot allocate hardware parameter structure(%s)\n", name, snd_strerror(err));
756 if ((err = snd_pcm_hw_params_any(dev->handle, hw_params)) < 0) {
757 LOGE("%s: cannot initialize hardware parameter structure(%s)\n", name, snd_strerror(err));
761 if ((err = snd_pcm_hw_params_set_rate_resample(dev->handle, hw_params, 0)) < 0) {
762 LOGE("%s: cannot set sample SAMPLE_RATE(%s)\n", name, snd_strerror(err));
766 if ((err = snd_pcm_hw_params_set_access(dev->handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
767 LOGE("%s: cannot set access type(%s)\n", name, snd_strerror(err));
771 if ((err = snd_pcm_hw_params_set_format(dev->handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
772 LOGE("%s: cannot set sample format(%s)\n", name, snd_strerror(err));
776 if ((err = snd_pcm_hw_params_set_channels(dev->handle, hw_params, channels)) < 0) {
779 LOGE("%s: cannot set channel. try near. channels(%d). %s\n",
780 name, channels, snd_strerror(err));
782 if ((err = snd_pcm_hw_params_set_channels_near(dev->handle, hw_params, &ch)) < 0) {
783 LOGE("%s: cannot set channel. %s\n", name, snd_strerror(err));
789 if ((err = snd_pcm_hw_params_set_rate_near(dev->handle, hw_params, &_rate, NULL)) < 0) {
790 LOGE("%s: cannot set sample SAMPLE_RATE(%s)\n", name, snd_strerror(err));
795 LOGE("%s: rate doesn't matched rate(%d) _rate(%d)\n", name, rate, _rate);
799 if ((err = snd_pcm_hw_params_set_buffer_size_near(dev->handle, hw_params, &buffer_frame)) < 0) {
800 LOGE("%s: snd_pcm_hw_params_set_buffer_size_near(%s)\n", name, snd_strerror(err));
804 snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size);
805 snd_pcm_hw_params_get_buffer_time(hw_params, &buffer_time, NULL);
807 unsigned int period_time = buffer_time / 4;
808 if ((err = snd_pcm_hw_params_set_period_time_near(dev->handle, hw_params, &period_time, NULL))) {
809 LOGE("%s: hw set period time near %d)\n", name, period_time);
813 if ((err = snd_pcm_hw_params_get_period_size(hw_params, &period_size, NULL))) {
814 LOGE("%s: hw set period time near %d)\n", name, period_time);
818 if ((err = snd_pcm_hw_params(dev->handle, hw_params)) < 0) {
819 LOGE("%s: cannot set parameters(%s)\n", name, snd_strerror(err));
823 snd_pcm_hw_params_free(hw_params);
826 if ((err = snd_pcm_sw_params_malloc(&sw_params)) < 0) {
827 LOGE("%s: cannot allocate software parameters structure(%s)\n", name, snd_strerror(err));
831 err = snd_pcm_sw_params_current(dev->handle, sw_params);
833 LOGE("%s: cannot initialize software parameters structure(%s)\n", name, snd_strerror(err));
837 err = snd_pcm_sw_params_set_start_threshold(dev->handle, sw_params, period_size);
839 LOGE("Unable to set start threshold mode for %s", snd_strerror(err));
843 if ((err = snd_pcm_sw_params_set_avail_min(dev->handle, sw_params, period_size)) < 0) {
844 LOGE("%s: cannot set minimum available count(%s)\n", name, snd_strerror(err));
848 err = snd_pcm_sw_params(dev->handle, sw_params);
850 LOGE("Unable to set sw params for %s", snd_strerror(err));
854 snd_pcm_sw_params_free(sw_params);
856 dev->period_size = period_size;
857 dev->period_time = period_time;
858 dev->buffer_size = buffer_size;
859 dev->buffer_time = buffer_time;
862 if (snd_pcm_poll_descriptors(dev->handle, pfd, 1) <= 0) {
863 LOGE("cannot get capture descriptor\n");
868 loopback->poll_cnt++;
870 LOGI("%s dev(%s) opened successfully. rate(%d), ch(%d), request buffer_frame(%d)\n",
871 mode ? "playback" : "capture", name, dev->rate, dev->channels, dev->buffer_frame);
872 LOGI("\tbuffer size : %ld frames, %d usec\n", buffer_size, buffer_time);
873 LOGI("\tperiod size : %ld frames, %d usec\n", period_size, period_time);
874 LOGI("\tthread_hold : %ld, avail_min %ld\n", period_size, period_size);
875 LOGI("\tloopback process frame %d", loopback->ec_frame);
881 snd_pcm_close(dev->handle);
883 snd_pcm_hw_params_free(hw_params);
885 snd_pcm_sw_params_free(sw_params);
890 static int __print_buffer(loopback_t *loopback)
892 struct loopback_dev **dev = loopback->dev;
893 snd_pcm_sframes_t c_avail, c_delay;
894 snd_pcm_sframes_t p_avail, p_delay;
898 snd_pcm_avail_delay(dev[CAPTURE]->handle, &c_avail, &c_delay);
899 snd_pcm_avail_delay(dev[PLAYBACK]->handle, &p_avail, &p_delay);
901 capture = (float)c_avail / (float)(dev[CAPTURE]->buffer_size) * 100;
902 playback = (float)p_avail / (float)(dev[PLAYBACK]->buffer_size) * 100;
904 LOGD("name(%s) capture avail(%.2f%%), playback avail(%.2f%%) buffer delay(%d)",
905 loopback->name, capture, playback, sq_get_work_node_count(loopback->q));
908 LOGE("refq delay(%d)", sq_get_work_node_count(loopback->refq));