我们经常会遇到这样的问题,应用读取到的音频有问题,需要在tinyalsa里面读取音频来确认是底层音频有问题,还是应用处理之后存在的问题。
所以,这个patch就出现了
代码的逻辑很简单,主要是在pcm_read的时候,同时把这个数据写入一个文件里面,这个只能在调试的时候使用,如果一直使用会导致这个文件会一直变大,到最后系统因为没有存储出现问题的。
现在写android代码已经不使用android.mk了,代替它的是android.bp,如果需要包含头文件,也需要在这里面修改。相关的文章网上一箩筐,我就不说了。
有个指针的处理,我觉得是比较巧妙的,大家如果喜欢研究代码的话,欢迎去github看看源码。
如果对代码还是不理解,可以去看看tinycap.c,里面的解析录音操作虽然简单,但是对我们帮助挺大的。
代码修改的diff如下
diff --git a/external/tinyalsa/Android.bp b/external/tinyalsa/Android.bp
old mode 100644
new mode 100755
index 090d91c0f8..79a6ceaee2
--- a/external/tinyalsa/Android.bp
+++ b/external/tinyalsa/Android.bp
@@ -9,6 +9,7 @@ cc_library {"mixer.c","pcm.c",],
+ shared_libs: ["liblog"],cflags: ["-Werror", "-Wno-macro-redefined"],export_include_dirs: ["include"],local_include_dirs: ["include"],
diff --git a/external/tinyalsa/pcm.c b/external/tinyalsa/pcm.c
old mode 100644
new mode 100755
index 4ae321bf93..de0deab9d0
--- a/external/tinyalsa/pcm.c
+++ b/external/tinyalsa/pcm.c
@@ -35,11 +35,17 @@#include <unistd.h>#include <poll.h>+#include <stdint.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/ioctl.h>#include <sys/mman.h>#include <sys/time.h>#include <limits.h>+#include <android/log.h>
+#include <linux/ioctl.h>#define __force#define __bitwise
@@ -48,6 +54,10 @@#include <tinyalsa/asoundlib.h>+#define LOG_TAG "TINYALSA_QIFA"
+#define ALOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##args)
+#define ALOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, fmt, ##args)
+#define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL/* Logs information into a string; follows snprintf() in that
@@ -242,6 +252,10 @@ static void param_init(struct snd_pcm_hw_params *p)struct pcm {int fd;
+ //int fd_test;
+ FILE *fd_test;
+ unsigned int size_test;
+ void *test_buffer;unsigned int flags;int running:1;int prepared:1;
@@ -566,6 +580,7 @@ int pcm_read(struct pcm *pcm, void *data, unsigned int count)x.frames = count / (pcm->config.channels *pcm_format_to_bits(pcm->config.format) / 8);+ ALOGE("x.frames:%ld count:%d",x.frames,count);for (;;) {if (!pcm->running) {if (pcm_start(pcm) < 0) {
@@ -583,6 +598,12 @@ int pcm_read(struct pcm *pcm, void *data, unsigned int count)}return oops(pcm, errno, "cannot read stream data");}
+
+ if (fwrite(x.buf, 1, count, pcm->fd_test) != count) {
+ fprintf(stderr,"Error capturing sample\n");
+ ALOGE("Error capturing sample");
+ }
+return 0;}}
@@ -864,6 +885,8 @@ int pcm_close(struct pcm *pcm)if (pcm->fd >= 0)close(pcm->fd);
+ if (pcm->fd_test >= 0)
+ fclose(pcm->fd_test);pcm->prepared = 0;pcm->running = 0;pcm->buffer_size = 0;
@@ -872,6 +895,8 @@ int pcm_close(struct pcm *pcm)return 0;}+
+struct pcm *pcm_open(unsigned int card, unsigned int device,unsigned int flags, struct pcm_config *config){
@@ -900,7 +925,12 @@ struct pcm *pcm_open(unsigned int card, unsigned int device,oops(pcm, errno, "cannot open device '%s'", fn);return pcm;}
-
+ /*weiqifa*/
+ pcm->fd_test = fopen("/sdcard/ref_temp.pcm", "wb");
+ if (!pcm->fd_test) {
+ fprintf(stderr, "Unable to create file /sdcard/ref_temp.pcm\n");
+ } else ALOGD("creat /sdcard/ref_temp.pcm file success");
+if (fcntl(pcm->fd, F_SETFL, fcntl(pcm->fd, F_GETFL) &~O_NONBLOCK) < 0) {oops(pcm, errno, "failed to reset blocking mode '%s'", fn);
(END)int running:1;int prepared:1;
@@ -566,6 +580,7 @@ int pcm_read(struct pcm *pcm, void *data, unsigned int count )x.frames = count / (pcm->config.channels *pcm_format_to_bits(pcm->config.format) / 8);+ ALOGE("x.frames:%ld count:%d",x.frames,count);for (;;) {if (!pcm->running) {if (pcm_start(pcm) < 0) {
@@ -583,6 +598,12 @@ int pcm_read(struct pcm *pcm, void *data, unsigned int coun t)}return oops(pcm, errno, "cannot read stream data");}
+
+ if (fwrite(x.buf, 1, count, pcm->fd_test) != count) {
+ fprintf(stderr,"Error capturing sample\n");
+ ALOGE("Error capturing sample");
+ }
+return 0;
:int running:1;int prepared:1;
@@ -566,6 +580,7 @@ int pcm_read(struct pcm *pcm, void *data, unsigned int count)x.frames = count / (pcm->config.channels *pcm_format_to_bits(pcm->config.format) / 8);+ ALOGE("x.frames:%ld count:%d",x.frames,count);for (;;) {if (!pcm->running) {if (pcm_start(pcm) < 0) {
@@ -583,6 +598,12 @@ int pcm_read(struct pcm *pcm, void *data, unsigned int count)}return oops(pcm, errno, "cannot read stream data");}
+
+ if (fwrite(x.buf, 1, count, pcm->fd_test) != count) {
+ fprintf(stderr,"Error capturing sample\n");
+ ALOGE("Error capturing sample");
+ }
+return 0;}}
@@ -864,6 +885,8 @@ int pcm_close(struct pcm *pcm)if (pcm->fd >= 0)close(pcm->fd);
+ if (pcm->fd_test >= 0)
+ fclose(pcm->fd_test);pcm->prepared = 0;pcm->running = 0;pcm->buffer_size = 0;
@@ -872,6 +895,8 @@ int pcm_close(struct pcm *pcm)return 0;}+
+struct pcm *pcm_open(unsigned int card, unsigned int device,unsigned int flags, struct pcm_config *config){
@@ -900,7 +925,12 @@ struct pcm *pcm_open(unsigned int card, unsigned int device,oops(pcm, errno, "cannot open device '%s'", fn);return pcm;}
-
+ /*weiqifa*/
+ pcm->fd_test = fopen("/sdcard/ref_temp.pcm", "wb");
+ if (!pcm->fd_test) {
+ fprintf(stderr, "Unable to create file /sdcard/ref_temp.pcm\n");
+ } else ALOGD("creat /sdcard/ref_temp.pcm file success");
+if (fcntl(pcm->fd, F_SETFL, fcntl(pcm->fd, F_GETFL) &~O_NONBLOCK) < 0) {oops(pcm, errno, "failed to reset blocking mode '%s'", fn);
weiqifa@bsp-ubuntu1804:~/is13-sdk$
核心代码在pcm.c里面
int pcm_read(struct pcm *pcm, void *data, unsigned int count)
{struct snd_xferi x;if (!(pcm->flags & PCM_IN))return -EINVAL;x.buf = data;x.frames = count / (pcm->config.channels *pcm_format_to_bits(pcm->config.format) / 8);ALOGE("x.frames:%ld count:%d",x.frames,count);for (;;) {if (!pcm->running) {if (pcm_start(pcm) < 0) {fprintf(stderr, "start error");return -errno;}}if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) {pcm->prepared = 0;pcm->running = 0;if (errno == EPIPE) {/* we failed to make our window -- try to restart */pcm->underruns++;continue;}return oops(pcm, errno, "cannot read stream data");}if (fwrite(x.buf, 1, count, pcm->fd_test) != count) {fprintf(stderr,"Error capturing sample\n");ALOGE("Error capturing sample");}return 0;}
}
x.buf
是一个指针,但是这个指针用的是从应用程序传下来的地址,所以在这里面也不需要给 x.buf
分配空间,具体可以参考tinycap
的做法。
在tinycap,还会给音频文件写入一个header,我们这里没有写入,没有太大的关系,打开音频的时候直接导入原始音频就可以了。
xxx:/ # ls -al /sdcard/ref_temp.pcm
-rw-rw---- 1 root sdcard_rw 79298560 2021-01-08 15:24 /sdcard/ref_temp.pcm
xxx:/ #
完整代码如下:
https://github.com/weiqifa0/tinyalsa