ubunt14.04下使用多线程操作录音和播放
来源:互联网 发布:学大数据能干金融吗 编辑:程序博客网 时间:2024/06/06 00:05
今天终于完成一个测试程序,开始感觉特别简单,但做的时候发现并不是想象的那么容易
需求:在开发板平台下利用2个线程交替执行,一个负责录音,一个负责播放
我下面的代码是在PC机测试通过,如果需要在开发板中使用,只需要修改其中的参数
但结果是可以测试的,但其中有些问题,会导致效率很低,但这是测试程序,只要可以
用,而且必须加快项目的进度。想到要将主要精力放到项目代码的编写和优化上面。
我下定决心以后要多写博客,原来也参加了很多的比赛也拿了很多奖品,但发现水平还
是不高,后来看到一些特别好的博客,上面的方法真的值得我们学习。
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <stdio.h>#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <alsa/asoundlib.h>
#define THRNUM 2
static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int flag = 1;//此变量是切换录音和播放的关键
char *buffer;//定义全局的char指针,用来存放录音数据[在这里申请空间],播放的时候打印出数据,且释放char指针
/*录音函数*/
{
long loops;
int rc;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val;
int dir;
snd_pcm_uframes_t frames;
rc=snd_pcm_open(&handle,"default",SND_PCM_STREAM_CAPTURE,0);
if (rc < 0) {
fprintf(stderr,"unable to open pcm device\n");
exit(1);
}
snd_pcm_hw_params_alloca(¶ms);
snd_pcm_hw_params_any(handle,params);
snd_pcm_hw_params_set_access(handle,params,SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_channels(handle,params,2);
val = 44100;
snd_pcm_hw_params_set_rate_near(handle,params,&val,&dir);
frames = 32;
snd_pcm_hw_params_set_period_size_near(handle,params,&frames,&dir);
rc = snd_pcm_hw_params(handle,params);
if (rc < 0) {
fprintf(stderr,"unable to set hw parameters\n");
exit(1);
}
snd_pcm_hw_params_get_period_size(params,&frames,&dir);
size = frames*4;
//printf("size = %d frames = %d\n",size,(int)frames);
buffer = (char *)malloc(size);
snd_pcm_hw_params_get_period_time(params,&val,&dir);
loops = 1000000/val;
while (loops > 0) {
loops--;
//录音只需要将声卡中的数据读到内存中就可以了
rc = snd_pcm_readi(handle,buffer,frames);
//printf("rc === %d frames == %d\n",rc,(int)frames);
if (rc == -EPIPE) {//在录音例子中,如果应用程序读取数据不够快,
//循环缓存区将会被新的数据覆盖。这种数据的丢失被称为overrun.
fprintf(stderr,"overrun\n");
snd_pcm_prepare(handle);
} else if (rc < 0) {
fprintf(stderr,"error form read\n");
} else if (rc != (int)frames) {
fprintf(stderr,"short read rc = %d frames = %d\n",rc,(int)frames);
}
}
printf("录音数据%s\n",buffer);
//free(buffer);
snd_pcm_drain(handle);
snd_pcm_close(handle);
}
/*播放*/
void aplay(void)
{
long loops;
int rc;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val;
int dir;
snd_pcm_uframes_t frames;
if (buffer != NULL)
{
printf("播放数据%s\n",buffer);
}
//打开声卡设备
rc=snd_pcm_open(&handle,"default",SND_PCM_STREAM_PLAYBACK,0);
if (rc < 0) {
fprintf(stderr,"unable to open pcm device\n");
exit(1);
}
//在栈上分配snd_pcm_hw_params_t
snd_pcm_hw_params_alloca(¶ms);
//初始化params
snd_pcm_hw_params_any(handle,params);
//设置为交错访问[记录完帧1的左声道数据和右声道数据,再记录帧2的左声道数据和右声道数据,依次继续]
snd_pcm_hw_params_set_access(handle,params,SND_PCM_ACCESS_RW_INTERLEAVED);
//设置数据格式 主要控制输入的音频数据的类型,无符号,有符号,小端,大端,位数
snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
//设置通道数 双通道[立体声]
snd_pcm_hw_params_set_channels(handle,params,2);
val = 44100;
//设置采样率
snd_pcm_hw_params_set_rate_near(handle,params,&val,&dir);
frames = 32;
//
snd_pcm_hw_params_set_period_size_near(handle,params,&frames,&dir);
//设置params
rc = snd_pcm_hw_params(handle,params);
if (rc < 0) {
fprintf(stderr,"unable to set hw parameters\n");
exit(1);
}
snd_pcm_hw_params_get_period_size(params,&frames,&dir);
size = frames*4;
snd_pcm_hw_params_get_period_time(params,&val,&dir);
loops = 1000000/val;
while (loops > 0) {
loops--;
rc = snd_pcm_writei(handle,buffer,frames);
if (rc == -EPIPE) {
//
fprintf(stderr,"underrun\n");
snd_pcm_prepare(handle);
} else if (rc < 0) {
fprintf(stderr,"error form read\n");
} else if (rc != (int)frames) {
fprintf(stderr,"short read rc = %d frames = %d\n",rc,(int)frames);
}
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
}
void *thr_func1(void *p)
{
while(1)
{
//加锁
pthread_mutex_lock(&mut);
while(flag != 1)
pthread_cond_wait(&cond,&mut);
//这里来调用录音函数
printf("录音开始\n");
arecord();
printf("录音结束\n");
printf("##################\n");
flag = 0;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mut);
}
pthread_exit(NULL);
}
void *thr_func2(void *p)
{
while(1)
{
pthread_mutex_lock(&mut);
while(flag != 0)
pthread_cond_wait(&cond,&mut);
//这里要调用播放函数
printf("播放开始\n");
aplay();
printf("播放结束\n");
flag = 1;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mut);
}
pthread_exit(NULL);
}
int main()
{
int i,err;
void *data = NULL;
pthread_t tid[THRNUM];
//for(i = 0 ; i < THRNUM ; i++)
{
err = pthread_create(tid+0,NULL,thr_func1,data);
if(err)
{
fprintf(stderr,"pthread_create():%s\n",strerror(err));
exit(1);
}
err = pthread_create(tid+1,NULL,thr_func2,data);
}
alarm(20);
for(i = 0 ; i < THRNUM ; i++)
pthread_join(tid[i],NULL);
exit(0);
}
最后说下其实这个程序特别简单,高手千万别吐,希望和大家一起进步,一起学习。
0 0
- ubunt14.04下使用多线程操作录音和播放
- Android音频操作:录音和播放
- android 录音和播放录音
- android录音和播放录音
- Android录音和播放录音
- Android 录音和播放录音
- AudioQueue 播放和录音
- AudioQueue 播放和录音
- Android 录音和播放
- iOS录音和播放
- iOS录音和播放
- android开发录音和播放录音
- 使用AudioRecord和 AudioTrack实现录音并播放
- IOS7使用Audio Queue同时进行录音和播放
- 实现录音和播放 使用wave系列函数
- ios之使用录音功能和设置音效播放
- 使用Android开发录音和播放功能小程序示例
- android 使用 audiorecord 和 audiotrack 实现实时录音播放
- DES算法原理完整版
- 【MySQL】字段拆分需求实现(group_concat的逆操作)
- recyclerview上下拉刷新加载——代码顺序
- QoS/ToS/CoS/DSCP 介绍
- 国内、海外高防秒解服务器、云服务器
- ubunt14.04下使用多线程操作录音和播放
- ShareSDK for unity3d
- Mac MyEclipse 运行tomcat日志乱码
- iOS基础呀
- iOS UIWebView 自定义 UserAgent
- android app在腾讯开放平台认领应用给空白包签名
- jquery效果
- 优秀代码的格式准则
- UVA-11080 Place the Guards(二分图染色)