源码
一、修改Android.bp源码 - - 将tinyplay.c编译成静态可执行文件
将对应的Android.bp文件中添加 static_executable: true,
即可。
二、修改tinyplay.c源码
1、通过输入的参数控制循环播放次数
上图修改就是实现音频循环的关键了,下面就需要通过参数调用这个函数实现循环播放次数了。
2、使用守护进程使adb shell执行tinyplay工具脱离终端
原因:因为生产工具使用的使adb shell执行tinyplay工具来播放对应的wav格式的音频文件,而执行adb shell指令播放音频需要播放完毕后才会退出adb shell,这样就导致生产工具执行不能边播放音频,边执行下一条指令了,因此需要执行tinyplay工具时,让其成为守护进程,脱离终端,那么adb shell就会退出,此时生产工具才能执行下一条指令,不会被阻塞。
以下是我之前写的博客,有对守护进程相关的讲解。
博客链接
三、源码修改补丁
diff --git a/android/external/tinyalsa/Android.bp b/android/external/tinyalsa/Android.bp
index 090d91c0f8..f8ab2516a9 100644
--- a/android/external/tinyalsa/Android.bp
+++ b/android/external/tinyalsa/Android.bp
@@ -24,8 +24,10 @@ cc_binary {
name: "tinyplay",
host_supported: true,
srcs: ["tinyplay.c"],
- shared_libs: ["libtinyalsa"],
+ static_libs: ["libtinyalsa"],
+ stl: "libc++_static",
cflags: ["-Werror"],
+ static_executable: true,
target: {
darwin: {
enabled: false,
@@ -36,27 +38,31 @@ cc_binary {
cc_binary {
name: "tinycap",
srcs: ["tinycap.c"],
- shared_libs: ["libtinyalsa"],
+ static_libs: ["libtinyalsa"],
cflags: ["-Werror"],
+ static_executable: true,
}
cc_binary {
name: "tinymix",
srcs: ["tinymix.c"],
- shared_libs: ["libtinyalsa"],
+ static_libs: ["libtinyalsa"],
cflags: ["-Werror", "-Wall"],
+ static_executable: true,
}
cc_binary {
name: "tinyhostless",
srcs: ["tinyhostless.c"],
- shared_libs: ["libtinyalsa"],
+ static_libs: ["libtinyalsa"],
cflags: ["-Werror"],
+ static_executable: true,
}
cc_binary {
name: "tinypcminfo",
srcs: ["tinypcminfo.c"],
- shared_libs: ["libtinyalsa"],
+ static_libs: ["libtinyalsa"],
cflags: ["-Werror"],
+ static_executable: true,
}
diff --git a/android/external/tinyalsa/tinyplay.c b/android/external/tinyalsa/tinyplay.c
index 0354df6cb8..702b1f677d 100644
--- a/android/external/tinyalsa/tinyplay.c
+++ b/android/external/tinyalsa/tinyplay.c
@@ -33,6 +33,10 @@
#include <string.h>
#include <signal.h>
#include <endian.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <sys/stat.h>
#define ID_RIFF 0x46464952
#define ID_WAVE 0x45564157
@@ -59,17 +63,17 @@ struct chunk_fmt {
uint16_t bits_per_sample;
};
-static int close = 0;
+static int tiny_close = 0;
void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels,
unsigned int rate, unsigned int bits, unsigned int period_size,
- unsigned int period_count, uint32_t data_sz);
+ unsigned int period_count, uint32_t data_sz, unsigned int play_count);
void stream_close(int sig)
{
/* allow the stream to be closed gracefully */
signal(sig, SIG_IGN);
- close = 1;
+ tiny_close = 1;
}
int main(int argc, char **argv)
@@ -84,81 +88,133 @@ int main(int argc, char **argv)
unsigned int period_count = 4;
char *filename;
int more_chunks = 1;
-
- if (argc < 2) {
- fprintf(stderr, "Usage: %s file.wav [-D card] [-d device] [-p period_size]"
- " [-n n_periods] \n", argv[0]);
- return 1;
+ unsigned int play_count = 1; //播放次数初始为1次
+ pid_t pid;
+ int i;
+
+ pid = fork();
+ if(pid < 0)
+ {
+ fprintf(stderr, "fork failed");
+ exit(1);
}
- filename = argv[1];
- file = fopen(filename, "rb");
- if (!file) {
- fprintf(stderr, "Unable to open file '%s'\n", filename);
- return 1;
+ if(pid > 0) {
+ fprintf(stderr, "parent\n");
+ sleep(1);
+ exit(0);
}
- fread(&riff_wave_header, sizeof(riff_wave_header), 1, file);
- if ((riff_wave_header.riff_id != ID_RIFF) ||
- (riff_wave_header.wave_id != ID_WAVE)) {
- fprintf(stderr, "Error: '%s' is not a riff/wave file\n", filename);
- fclose(file);
- return 1;
- }
+ if(pid == 0) {
+ fprintf(stderr, "child\n");
- do {
- fread(&chunk_header, sizeof(chunk_header), 1, file);
-
- switch (chunk_header.id) {
- case ID_FMT:
- fread(&chunk_fmt, sizeof(chunk_fmt), 1, file);
- /* If the format header is larger, skip the rest */
- if (chunk_header.sz > sizeof(chunk_fmt))
- fseek(file, chunk_header.sz - sizeof(chunk_fmt), SEEK_CUR);
- break;
- case ID_DATA:
- /* Stop looking for chunks */
- more_chunks = 0;
- chunk_header.sz = le32toh(chunk_header.sz);
- break;
- default:
- /* Unknown chunk, skip bytes */
- fseek(file, chunk_header.sz, SEEK_CUR);
- }
- } while (more_chunks);
-
- /* parse command line arguments */
- argv += 2;
- while (*argv) {
- if (strcmp(*argv, "-d") == 0) {
- argv++;
- if (*argv)
- device = atoi(*argv);
- }
- if (strcmp(*argv, "-p") == 0) {
- argv++;
- if (*argv)
- period_size = atoi(*argv);
+ /* 创建新会话,脱离控制终端 */
+ if(setsid() < 0) {
+ fprintf(stderr,"setsid error\n");
+ exit(-1);
}
- if (strcmp(*argv, "-n") == 0) {
- argv++;
- if (*argv)
- period_count = atoi(*argv);
+ /* 设置单曲工作目录为根目录 */
+ if(0 > chdir("/")) {
+ fprintf(stderr,"setsid error\n");
+ exit(-1);
}
- if (strcmp(*argv, "-D") == 0) {
- argv++;
- if (*argv)
- card = atoi(*argv);
+ /* 重设文件权限掩码 umask */
+ umask(0);
+ /* 关闭所有文件描述符 */
+ for(i = 0; i < sysconf(_SC_OPEN_MAX); i++) {
+ close(i);
}
- if (*argv)
- argv++;
- }
+ /* 将文件描述符号为0、1、2定位到/dev/null */
+ open("/dev/null", O_RDWR);
+ dup(0);
+ dup(0);
+ /* 忽略SIGCHLD信号 */
+ signal(SIGCHLD, SIG_IGN);
+
+ for( ; ; ) {
+ /*****************************************************/
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s file.wav [-D card] [-d device] [-p period_size]"
+ " [-n n_periods] \n", argv[0]);
+ return 1;
+ }
- play_sample(file, card, device, chunk_fmt.num_channels, chunk_fmt.sample_rate,
- chunk_fmt.bits_per_sample, period_size, period_count, chunk_header.sz);
+ filename = argv[1];
+ file = fopen(filename, "rb");
+ if (!file) {
+ fprintf(stderr, "Unable to open file '%s'\n", filename);
+ return 1;
+ }
- fclose(file);
+ fread(&riff_wave_header, sizeof(riff_wave_header), 1, file);
+ if ((riff_wave_header.riff_id != ID_RIFF) ||
+ (riff_wave_header.wave_id != ID_WAVE)) {
+ fprintf(stderr, "Error: '%s' is not a riff/wave file\n", filename);
+ fclose(file);
+ return 1;
+ }
+ do {
+ fread(&chunk_header, sizeof(chunk_header), 1, file);
+
+ switch (chunk_header.id) {
+ case ID_FMT:
+ fread(&chunk_fmt, sizeof(chunk_fmt), 1, file);
+ /* If the format header is larger, skip the rest */
+ if (chunk_header.sz > sizeof(chunk_fmt))
+ fseek(file, chunk_header.sz - sizeof(chunk_fmt), SEEK_CUR);
+ break;
+ case ID_DATA:
+ /* Stop looking for chunks */
+ more_chunks = 0;
+ chunk_header.sz = le32toh(chunk_header.sz);
+ break;
+ default:
+ /* Unknown chunk, skip bytes */
+ fseek(file, chunk_header.sz, SEEK_CUR);
+ }
+ } while (more_chunks);
+
+ /* parse command line arguments */
+ argv += 2;
+ while (*argv) {
+ if (strcmp(*argv, "-d") == 0) {
+ argv++;
+ if (*argv)
+ device = atoi(*argv);
+ }
+ if (strcmp(*argv, "-p") == 0) {
+ argv++;
+ if (*argv)
+ period_size = atoi(*argv);
+ }
+ if (strcmp(*argv, "-n") == 0) {
+ argv++;
+ if (*argv)
+ period_count = atoi(*argv);
+ }
+ if (strcmp(*argv, "-D") == 0) {
+ argv++;
+ if (*argv)
+ card = atoi(*argv);
+ }
+ if (strcmp(*argv, "-pp") == 0) {
+ argv++;
+ if (*argv)
+ play_count = atoi(*argv);
+ }
+ if (*argv)
+ argv++;
+ }
+ fprintf(stderr,"chunk_fmt.num_channels huidu = %d\n", chunk_fmt.num_channels);
+ play_sample(file, card, device, chunk_fmt.num_channels, chunk_fmt.sample_rate,
+ chunk_fmt.bits_per_sample, period_size, period_count, chunk_header.sz, play_count);
+
+ fclose(file);
+ exit(0);
+ /*****************************************************/
+ }
+ }
return 0;
}
@@ -212,13 +268,14 @@ int sample_is_playable(unsigned int card, unsigned int device, unsigned int chan
void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels,
unsigned int rate, unsigned int bits, unsigned int period_size,
- unsigned int period_count, uint32_t data_sz)
+ unsigned int period_count, uint32_t data_sz, unsigned int play_count)
{
struct pcm_config config;
struct pcm *pcm;
char *buffer;
unsigned int size, read_sz;
int num_read;
+ uint32_t data_sz_save = data_sz; //保存播放音频的字节数
memset(&config, 0, sizeof(config));
config.channels = channels;
@@ -260,17 +317,26 @@ void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned in
/* catch ctrl-c to shutdown cleanly */
signal(SIGINT, stream_close);
- do {
- read_sz = size < data_sz ? size : data_sz;
- num_read = fread(buffer, 1, read_sz, file);
- if (num_read > 0) {
- if (pcm_write(pcm, buffer, num_read)) {
- fprintf(stderr, "Error playing sample\n");
- break;
+ /* 通过play_count变量判断循环播放次数 */
+ while(play_count > 0) {
+
+ do {
+ read_sz = size < data_sz ? size : data_sz;
+ num_read = fread(buffer, 1, read_sz, file);
+ if (num_read > 0) {
+ if (pcm_write(pcm, buffer, num_read)) {
+ fprintf(stderr, "Error playing sample\n");
+ break;
+ }
+ data_sz -= num_read;
}
- data_sz -= num_read;
- }
- } while (!close && num_read > 0 && data_sz > 0);
+ } while (!tiny_close && num_read > 0 && data_sz > 0);
+
+ data_sz = data_sz_save; //播放完一下,将音频数据个数兼数据位置恢复到起始位置
+ fseek(file, 0, SEEK_SET); //文件指针回到起始位置
+ play_count--; //播放次数减一
+ }
+
free(buffer);
pcm_close(pcm);
关于audacity软件
这个软件可以裁剪音频,特别是做一些音频测试相关的,比如左、右声道单独测试什么,网上直接搜索就有了,我也上传了资源->链接