ROS多个(单通道)分布式麦克风并行传输数据

前面文章已经讲过分布式麦克风linux下的开发,以及在ROS中的应用,也提到了实现多线程的方法,本文主要简单补充一下多个单通道麦克风并行收发数据的实现。

由于ros中多进程一般是指通过多个ros节点收发信息的方式,而多线程的实现仅在一个进程(一个节点)中就可以实现。前面博文已经说明多进程的工作机制,这里不再说明。

由于分布式麦克风是通过ip地址及端口号发送数据的,这里仅拓展到实现两个麦克风的情景,不过原理都是一样的,需要更多的话类似书写即可。

这里传输数据为了保证各个端口之间不会出现串扰的现象(其实不会发生),只是为了容易理解,我们将端口号和传输数据绑定在一起发送(publish),这是就需要创建自己的msg数据类型,以前的博文中有专门的讲述如何创建自己的msg,
如下所示:

float32[] data
uint16    size
Header    header
int64     port

data用来存储float类型的音频数据,size是传输的长度,一般为帧长,port就是我们创建的ip地址的端口号。
主要实现步骤如下:

创建两个端口号相匹配的线程(调用函数必须为(void *)类型):
pthread_t tid1,tid2;
pthread_create(&tid1,NULL, rx_x,& 需要传的参数,可为NULL);
pthread_create(&tid1,NULL, rx_x,& 需要传的参数,可为NULL );
while(1);

能够看到上面调用的函数是同一个函数,对的,我们需要实现的就是这种,多线程调用一个函数时的操作。
线程中调用的函数会再次调用函数,看你需要的地方了。具体实现如下:

if(port == 8888){
                pcm_file1 = fopen ("/home/yf415/a8888.pcm","a+");

//              if(flag%2 == 1){
//              r = play_one_frame(packet, r, decoder, snd, channels , pcm);
                r = play_one_frame(packet, r, decoder, snd, channels , pcm,port);
//              for (int j = 1; j <= r ;j++){
                msg.size = r ;
                for(int ii = 0 ; ii< r ; ii++ ){
                        msg.data.resize(r);
                        msg.data[ii] = pcm[ii] ;
                        msg.port = port;
//                      printf("%lf\n",pcm[ii]);
                }
                Pub.publish (msg);
                fwrite (pcm ,sizeof(float) , r , pcm_file1);
                fclose(pcm_file1);
//                      DATA_LOCK;    //加锁
//                      temp[0][j] = pcm[j];
//                      DATA_UNLOCK;     //解锁
//                      }
                }
                else if(port == 7777){
//              if(flag%2 == 0){
                pcm_file2 = fopen ("/home/yf415/a7777.pcm","a+");
                r = play_one_frame(packet, r, decoder, snd, channels , pcm ,port);
                msg.size = r ;
                for(int ii = 0; ii < r ; ii++){
                        msg.data.resize(r);
                        msg.data[ii] = pcm[ii] ;
                        msg.port = port;
//                      printf("%lf\n",pcm[ii]);
                }
                Pub.publish(msg);
                fwrite (pcm ,sizeof(float) , r , pcm_file2);
                fclose(pcm_file2);

                }

若是不使用绑定port的形式写音频数据的话会出现音频传输帧之间会有错乱的现象,这时候可以通过文件或存储空间加锁解锁的方式实现(以前博文有指出)。但是我们采用绑定port的目的在于ros的另一个接受端可以很清楚的知道这些数据是从哪一路传送过来的,也有助于我们再次利用这些音频数据。
顺便直接贴出接受端的订阅topic的callback函数如下:

void Callback(const jack_msgs::JackAudio::ConstPtr& msg)
{
        float *pcm = NULL;
        pcm =  (float *)alloca(sizeof(float) * 1920 * 1);
        if(msg->port == 8888){
        int data_length = msg->size;
        int k=0;
        short in_shorts[data_length];
        jack_mtx.lock();
        for(int i=0; i<data_length; i++){
                in_shorts[k] = (short)(msg->data[i] * 65535);
//              pcm[k] = (msg->data[i]);
                k++;
                printf ("8888 asr == %d\n", in_shorts[k]);
        }
        fwrite(in_shorts , sizeof(short) , data_length , pcm_file);
//      fwrite(pcm , sizeof(float) , data_length , pcm_file);
        jack_mtx.unlock();
        
        }
        else if( msg->port == 7777 ){
        int data_length = msg->size;
        int k=0;
        short in_shorts1[data_length];
        jack_mtx.lock();
        for(int i=0; i< data_length; i++){
                in_shorts1[k] = (short)(msg->data[i] * 65535);
                k++;
                printf ("7777 asr == %d\n", in_shorts1[k]);
        }
        fwrite(in_shorts1 , sizeof(short) , data_length , pcm_file1);
        jack_mtx.unlock();
       
        }
}

开发示例的流程就是这样,当然我们在接受端也可以实现多线程的方式接受,这个看个人了。
另一种想法是:ros中一般能采用多进程的话最好是多进程,实在不行采用多线程(学习一下很有帮助)。我们也可以将上面实现的方式换一下:发送端用多进程的方式发布多个topic,接受端用多线程的方式接受多个topic。既能保证同步性,还非常清晰明了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值