基于生产者/消费者设计模式的连续音频信号采集系统
扫描二维码
随时随地手机看文章
0 引 言
LabVIEW 是美国NI公司1986年推出的一种图形化的编程语言和开发环境。作为虚拟仪器开发平台,由于其图形化的编程方式具有简单易学、直观方便、功能强大等特点,是很多工程设计人员进行虚拟仪器开发的首选。生产者/消费者设计模式是NI公司最新推出的程序设计概念,它从主/从设计模式发展而来,生产者/消费者设计模式将生产和消费数据速度不同的任务分开处理,大大提高了不同速率的多个循环之间数据共享的能力,对于多任务处理和实时性、连续性要求严格的程序设计,生产者/消费者设计模式是较好的选择。在虚拟仪器系统中,硬件解决信号的输入和输出,软件可以方便地更新仪器系统的功能,以适应不同使用者的需要。其中信号的输入部分一般使用数据采集卡实现,商用的数据采集卡具有较大的逋用性。普通声卡具有16位的量化精度、数据采集频率是44 kHz,完全可以满足特定音频信号范围内数据采集的需要,个别性能指标还优于商用数据采集卡,而价格却为商用数据采集卡的十几分之一甚至几十分之一。若保证信号采集的逼真性,在采集过程中的连续性和实时控制显得尤为重要。
本文以LabVIEW为平台,着重介绍了生产者/消费者模式的实现,以及在实时控制的连续音频采集系统中的应用。
1 生产者/消费者设计模式概念及其实现
1.1 生产者/消费者设计模式概念
生产者/消费者设计模式包括多个并行循环,每个循环以不同的速率执行任务。一个循环作为生产数据的循环,其他循环作为消费数据的循环。生产数据的循环控制所有消费数据的循环,并且使用通信技术与它们进行通信。
1.2 生产者循环与消费者循环之间的通信
在LabVIEW程序设计过程中,变量(局部变量和全局变量)、通知器、队列常用于多个循环之间传递数据。
LabVIEW中的变量是程序框图中的元素,通过它可以在另一位置访问或存储数据。根据不同的变量类型,数据的实际位置也不一样。局部变量将数据存储在前面板的输入控件和显示控件中,全局变量和单进程共享变量将数据存储在特殊的通过多个VI可以访问的仓库中。不管变量将数据存储在何处,所有的变量都可以在不使用连线连接两个地方的条件下把数据从一个地方传递到另一个地方,而不必使用正常的数据流。但是变量的使用有着其自身的缺点,变量不仅不能保证各个循环之间的同步,而且使用变量会破坏LabVIEW的数据流模式,在对变量进行读写操作时容易产生内存拷贝,浪费内存资源,影响系统运行效率。
变量还允许竞争状态的出现,竞争状态不容易识别和调试,因为输出取决于操作系统执行排定的任务和外部时间定时的顺序。任务之间和任务同计算机之间的交互方式,以及外部时间的任意定时都使这种顺序变得随机。很多情况下,带有竞争状态的代码会在数千次测试中返回相同的结果,但仍然可能会在运行时返回一个不同的结果。
对生产者/消费者设计模式的一个更有效的实现是使用通知器和队列使数据传输保持同步。通知器在发出数据可用的通知时,将同时发送数据。使用通知器将数据从主循环传送到从循环消除了和竞争状态相关的问题。使用通知器还有同步的好处,因为数据可用时,主从循环都已完成定时,并准备实现一个良好的生产者/消费者设计模式。但是通知器不会缓冲数据,如果主循环在从循环读取第一份数据之前发送另一份数据,那么原来那份数据就会被覆盖并丢失。队列类似于通知器。但它可以存储多份数据,默认情况下,队列按照FIFO(先进先出)的方式执行。因此,第一份插入队列的数据,也是第一份从队列中删除的数据。在实时控制的连续音频信号采集过程中,由于需要处理许多用户界面的事件,为了不造成数据丢失,选择队列在各个循环之间传递数据,实现过程如图1所示。
如图1所示,在循环开始使用“获取队列引用”函数之前,队列就已经创建完毕。生产者循环使用“元素入队列”函数向队列中添加数据。消费者循环使用“元素出队列”函数从队列中移除数据。消费者循环一直到队列中的数据可用时才执行。
可见,在此生产者/消费者设计模式中,两个循环均被同步为与生产者循环一致。消费者循环只在队列中的数据可用时才执行。这样就保证了消费者循环执行任务的连续性和高效性。并且,队列用于循环之间的数据传递,创建全局可用的位于队列中的数据,而且在添加新的数据到队列时,避免了丢失数据的可能性。
2 实时控制的连续音频信号采集系统
2.1 声卡简介
从数据采集的角度看,声卡是一种音频范围内的数据采集卡,是计算机与外部模拟量环境联系的重要途径。一般声卡都是由以下几部分组成:声音控制/处理芯片,功放芯片,声音输入/输出端口等。
声音控制/处理芯片是声卡的核心,集成了采样保持、A/D转换、D/A转换、音效处理等电路,它决定了声卡的性能和档次,基本功能包括对声波采样和回放控制、处理MIDI指令等,有的厂家还加进了混响、合声、音场调整等功能。