|
本帖最后由 airqj 于 2014-7-20 21:46 编辑
做这个最开始是想用linux的curses库来做的,就是那种基于终端的显示方式。后来想想效果可能会不是很明显,最后决定使用Qt + qwt库作为显示界面。
前一个文章说道如何读取音频数据并作初步处理,这里则如何使用Qt将音频数据显示在屏幕上。因为篇幅原因,先上主要的代码
- void Plot::getdata_from_shm()
- {
- float_t *addr_ptr=(float_t *)shm_client_addr;
- fft_client_waiting_for_read(sem_client_id);
- for(Plot::index=d_interval.minValue();Plot::index<d_interval.maxValue();Plot::index+=0.020833)
- {
- const QPointF s(index,*addr_ptr);
- SignalData::instance().append(s);
- addr_ptr++;
- }
- fft_client_release(sem_client_id);
- }
复制代码
这里大家估计都看出来了,我这个频谱仪使用了两个进程,服务端进行初步的数据处理,前台进程从共享内存中读取数据后显示在开发板的屏幕上。为什么要使用两个进程来做这个频谱仪呢?主要是因为如果只使用一个进程来做的话,就得既得处理数据又得显示数据,而在处理数据的时候是需要一定的时间的,这样就得停滞,从而实时性可能得不到要求。而且am3359有512M的内存,放着这么多的内存不用起步可惜。这里使用了共享内存作为数据交换的方式,信号量控制读写同步。shm_client_addr就是共享内存的地址,sem_client_id就是信号量在客户端的id。对于这方面不熟悉的同学可以上网查一下这方面的资料.大家可能会对后面那个数字感到奇怪,这个数字主要是因为使用48kHz采样频率,1/48000就可以得到这个数字了
为了便于大家学习,贴上共享内存和信号量在服务器端的主要代码
共享内存:- char * shm_init()
- {
- printf("before shmget shm_id is %d\n",shm_id);
- fflush(stdout);
- shm_id=shmget(SHM_KEY,SHM_SIZE,IPC_CREAT|0777);
- char *addr=NULL;
- if(shm_id<=0)
- {
- perror("shmget error\n");
- printf("errorno is %d\n",errno);
- }
- addr=(char *)shmat(shm_id,NULL,0777);
- if(NULL==addr)
- {
- perror("shmat error\n");
- }
- return addr;
- }
复制代码 这个是信号量的- union semun {
- int val;
- struct semid_ds *buf;
- unsigned short *array;
- struct seminfo * __buf;
- };
- void clear_sem(int semid,int sem_nu)
- {
- union semun sem_initial;
- sem_initial.val=0;
- if(semctl(semid,sem_nu,SETVAL,sem_initial))
- {
- perror("clear sem faild\n");
- _Exit(1);
- }
- }
- static int fft_server_sem_id;
- int sem_init()
- {
- fft_server_sem_id=semget(SEM_KEY,SEM_NUM,IPC_CREAT|0777);
- if(fft_server_sem_id<=0)
- {
- perror("server semget error\n");
- _Exit(1);
- }
- clear_sem(fft_server_sem_id,0);
- clear_sem(fft_server_sem_id,1);
- return fft_server_sem_id;
- }
- void fft_server_waiting_for_write(int sem_id)
- {
- struct sembuf actions[2]; //wait sem 0 is 0 : read sem
- actions[0].sem_num=0;
- actions[0].sem_flg=SEM_UNDO;
- actions[0].sem_op=0;
- actions[1].sem_num=1;
- actions[1].sem_flg=SEM_UNDO;
- actions[1].sem_op=1;
- if(0!=semop(sem_id,actions,2))
- {
- perror("server client semop faild\n");
- _Exit(1);
- }
- }
- void fft_client_waiting_for_read(int sem_id)
- {
- struct sembuf actions[2];
- actions[0].sem_num=1;
- actions[0].sem_op=0;
- actions[0].sem_flg=SEM_UNDO;
- actions[1].sem_num=0;
- actions[1].sem_flg=SEM_UNDO;
- actions[1].sem_op=1;
- if(0!=semop(sem_id,actions,2))
- {
- perror("client read error\n");
- _Exit(1);
- }
- }
- void fft_server_release(int sem_id)
- {
- struct sembuf action;
- action.sem_num=1;
- action.sem_flg=SEM_UNDO;
- action.sem_op=-1;
- if(0!=semop(sem_id,&action,1))
- {
- perror("server release faild\n ");
- _Exit(1);
- }
- }
- void fft_client_release(int sem_id)
- {
- struct sembuf action;
- action.sem_num=0;
- action.sem_flg=SEM_UNDO;
- action.sem_op=-1;
- if(0!=semop(sem_id,&action,1))
- {
- perror("client release semop faild\n");
- _Exit(1);
- }
- }
复制代码 信号量的相对于共享内存稍微复杂一些,有什么问题大家可以回帖提问
|
|