十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MATLAB声卡数据采集系统:从音频采集到频谱分析

MATLAB声卡数据采集系统:从音频采集到频谱分析 简介毕业设计文档围绕“基于MATLAB的数据采集系统”展开以计算机为核心设计了传感器、声卡与计算机三大模块构成的音频信号采集与分析方案。系统重点处理10kHz以内的声音信号采用麦克风作为传感器、声卡完成模数转换并利用MATLAB数据采集工具箱实现信号采集、显示、存储、频谱分析及处理结果对比等功能。文档还给出了硬件电路设计要点包括输入输出信号调理电路、抗混叠滤波器、缓冲放大器及USB供电电路并规划了从开题到答辩的16周完整进度安排配有中英文摘要和参考文献结构规范。资源为1个doc文档共428KB适合电子信息、自动化、计算机等专业毕业生参考选题框架、系统设计思路与论文撰写方法。已有315人学习下载。1. 用声卡当采集卡MATLAB 数据采集系统的方案为什么能成立对于很多实验室场景一台电脑上最现成的数据采集设备不是昂贵的采集卡而是那块自带 A/D 转换的声卡。这套毕业设计的设计思路就是把麦克风、声卡、计算机三步串成一条音频采集链路麦克风负责拾取声音声卡完成前置放大、抗混叠和模数转换MATLAB 用数据采集工具箱直接读取声卡数据并做频谱分析。整个系统不需要外购采集卡却能覆盖 10kHz 以内的信号。它适合用来完成语音信号采集实验、做 GUI 示波器或者快速验证一段数字信号处理算法。选择这套方案要接受的限制也很明确声卡的采样率只能四挡可选输入通道的增益范围有限因此后续所有参数设置和调试都围绕“在低成本硬件上做出可信结果”展开。2. 采集链路拆解传感器、声卡与数据采集工具箱的三层关系2.1 从麦克风到声卡信号链路的三个环节在把数据放进 MATLAB 之前物理链路已经完成了一多半的处理。麦克风是传感器将声压转换为毫伏级电压信号声卡输入接口对信号做偏置和放大声卡内部的 ADC 采样电路再以固定量化精度转换成数字信号。这里的三个环节分别对应论文里的输入放大器、抗混叠滤波器和缓冲放大器顺序不能颠倒放大不足会让量化噪声占主导放大过了又会削波。实际操作时我一般会先在 MATLAB 里读取一段静音数据用mean(data)观察直流偏移再做一次plot看底噪。这比直接进入频谱分析更省时间。因为声卡的麦克风通道通常按语音电平优化不是所有接口电路都能直接匹配外部传感器的输出阻抗。文档里强调信号接口电路板需要“模拟电路和测试电路接口”目的就是让使用者可以在接入声卡前对信号做幅度和阻抗预处理。2.2 MATLAB 数据采集工具箱的三层结构M文件、引擎与适配器旧版 MATLAB 数据采集工具箱能工作靠的是三层结构。M文件负责提供analoginput、addchannel、getdata这组用户接口数据采集引擎在后台维护设备对象和事件硬件驱动适配器负责和具体声卡通信经典适配器名称是winsound。设备对象分为模拟输入AI、模拟输出AO、数字量输入输出DIO三类声音采集只需要 AI。下面这段代码用于确认环境里可用的采集设备% 列出当前 MATLAB 可识别的数据采集设备 daq.getDevices % 经典版本R2010a 前后用 winsound 适配器 ai analoginput(winsound); ch addchannel(ai, 1);daq.getDevices能返回设备名和供应商信息方便确认采样率范围analoginput(winsound)则是旧版创建模拟输入对象的入口。这里的关键点是ch必须被添加否则后续start(ai)虽然不报错但不会有任何数据流进入缓冲区。设备对象把声卡抽象成一个带属性的对象采样率、采样长度、触发方式全部挂在对象上这一点和普通函数式调用有本质区别。2.3 声卡方案和四种常见低端采集方案的对比文档整理了当时常见的方案。RS232 串口最简单但速率低AT89C51 加 TLC2543 成本低但要写单片机固件USB 数据采集器速度快代价是想在 MATLAB 中控制它还要用 C 语言开发 MEX 驱动ARMGPRS 嵌入式方案功能强调试周期很长。声卡方案属于“零门槛但有限制”。方案链路核心优点主要限制RS232 采集模块serial 对象函数易用速率低AT89C51 TLC2543单片机 12bit ADC成本低精度有限USB 数据采集器C/MEX 驱动速度快驱动复杂ARM GPRSLinux 嵌入式扩展性强周期长声卡 winsound声卡 A/D零额外硬件采样率分档对比之后选声卡直接理由是声卡普遍是 16 位量化比低端 12 位采集卡更高而且它自带滤波和 D/A 功能连信号回放都可以直接做。真正要接受的是它的采样率档位限制一般只有 44.1k、22.05k、11.025k、8k 四档。如果信号带宽接近 10kHz优先选择 44.1k 档留足抗混叠余量。3. 声卡参数设置与经典采集代码采样率、位数与触发方式3.1 采样位数与采样频率不只是越大越好声卡的性能基本由两个参数决定采样位数和采样频率。16 位对音频实验意味着量化电平数为 65536理论动态范围接近 96dB但麦克风前端噪声会降低实际有效位数所以把采样位数调高并不是解决微弱信号的办法。采样频率则由硬件固化为几个档位不能像数据采集卡那样任意设置。因为奈奎斯特定理要求采样频率大于信号最高频率的两倍而工程上通常留出至少 20% 余量。对于 10kHz 目标带宽44.1kHz 档是最稳妥的选择信号频率降到 5kHz 以下可以试试 22.05kHz 档。下面是声卡档位与信号频率上限的搭配采样频率信号最高频率适宜信号8000 Hz4 kHz电话语音11025 Hz5.5 kHz语音命令22050 Hz11 kHz语音音乐44100 Hz22 kHz10kHz 实验信号这里要特别提醒档位值是理论上限不代表声卡会准确落在设定值。有些声卡返回的SampleRate与设定值相差 0.1%做频谱时如果不回读真实值谱峰位置就会出现可观察的偏移。3.2 一段完整的声音采集流程代码以下代码基于旧版数据采集工具箱也是这套毕业设计的主流程。% 创建模拟输入对象使用声卡的麦克风通道 ai analoginput(winsound); addchannel(ai, 1); % 添加第一通道 set(ai, SampleRate, 44100); % 请求 44.1kHz set(ai, SamplesPerTrigger, 44100); % 一次触发采集 1 秒 set(ai, TriggerType, immediate); % 立即触发 start(ai); % 启动设备对象 data getdata(ai); % 阻塞获取数据矩阵 stop(ai); delete(ai); % 释放声卡防止下次占用addchannel(ai, 1)中的 1 对应麦克风输入的左声道。如果需要同时使用左右声道可以写成addchannel(ai, 1:2)但两声道的直流偏置通常不一样分析音频信号时最好分开看。SamplesPerTrigger设为 44100结合 44.1kHz 采样率就是 1 秒钟波形如果希望界面响应更快可以改成 8192。最后delete(ai)很重要漏掉之后第二次运行容易报 “Device is already opened”。参数设置的逻辑是先确定物理通道再确定采样率和触发方式。对单次测量immediate触发足够对需要等待某个外部事件的测量使用manual触发并手动调用trigger(ai)反而更清楚。3.3 连续采集与缓冲区的经验设置如果要做实时示波器单次触发是不够的。常见做法是把SamplesPerTrigger设成较小值比如 2048然后用timer每 40ms 调用一次getdata(ai)。这时要关注BufferingConfig数据采集引擎会按这里的值预分配缓冲区设置过小容易丢数设置过大又带来延迟。我一般会把BufferingConfig设为不低于两次取数的数据量。代码示例set(ai, BufferingConfig, [2048, 10]); % 每次预分配 10 块前一个参数是单块点数后一个是块数总容量 2048*10。这样的配置对 44.1kHz 采集可以应付界面绘制带来的随机延迟。连续采集时getdata返回的数据块长度会略小于预分配值绘制坐标轴时要按实际长度生成时间轴不要用固定长度。4. 从数据到图形MATLAB GUI 示波器与频谱分析实现4.1 用 GUIDE 布局还是手写回调文档软件模块明确提到了“图形用户接口软件界面”。常见实现方式是guide命令生成.fig界面文件再在回调函数里写采集和显示代码。界面至少要包含两个 axes、一个“开始采集”按钮、一个“保存数据”按钮以及一个显示采样率的文本框。控件Tag作用AxesaxesTime显示时域波形AxesaxesFreq显示频谱PushButtonbtnStart开始/停止PushButtonbtnSave保存 mat 文件EditeditFs显示采样率实际上我更喜欢把editFs做成可编辑让用户可以在 8k 到 44.1k 直接切换。切换时要注意set(ai,SampleRate, 新值)后必须回读一次因为声卡很可能把请求值吸附到相邻标准档位。4.2 回调函数里的采集与 FFT 代码按钮回调一般放在dataCapture_OpeningFcn初始化之后。核心函数如下function btnStart_Callback(hObject, eventdata, handles) global ai data Fs; Fs str2double(get(handles.editFs, String)); if isempty(ai) || ~isvalid(ai) ai analoginput(winsound); addchannel(ai, 1); set(ai, SampleRate, Fs); set(ai, SamplesPerTrigger, Fs * 0.5); set(ai, TriggerType, immediate); end start(ai); data getdata(ai); stop(ai); t (0:length(data)-1) / Fs; axes(handles.axesTime); plot(t, data); xlabel(时间/s); ylabel(幅度); N length(data); win hann(N, periodic); X fft(data .* win); f (0:N/2-1) * Fs / N; axes(handles.axesFreq); plot(f, 20*log10(abs(X(1:N/2)) eps)); xlabel(频率/Hz); ylabel(功率/dB); end代码先判断ai是否有效避免每次点击都重新创建设备对象。采集长度为 0.5 秒足够观察 1kHz 以上的波形成分。FFT 部分加了hann窗抑制由非整周期采样引起的频谱泄漏。纵轴取20*log10(abs(X)eps)把幅值变成 dB能明显看到噪声基底和主峰之间的距离。需要说明的是getdata(ai)是阻塞调用在 0.5 秒数据未读满前按钮回调不会返回。如果采集过程中界面卡死可以改成timer方案start(ai)后由 timer 定期读取新数据并更新曲线界面只负责触发。4.3 信号存储与回放让实验结果可复现采集数据只有保存下来才有后处理价值。最简单的做法是存成 MAT 文件function btnSave_Callback(hObject, eventdata, handles) global data Fs; save([capture_, datestr(now, yyyymmdd_HHMMSS), .mat], data, Fs); end文件名带时间戳可以避免多次实验时互相覆盖。回放用soundsc(data, Fs)它会自动按数据范围归一化幅度适合快速听辨如果想保持采样时的实际音量用sound(data, Fs)。对需要做对比分析的场景我一般会把原始数据和 FFT 结果都存进同一个结构体后续写脚本直接load避免重复采集。5. 调试与验证抗混叠、缓冲区和链路自检5.1 抗混叠滤波器不是 MATLAB 层面能解决的问题文档硬件要求里写得很清楚输出路径需要“输入放大器、抗混叠滤波器、幅度可调输出放大器”。这说明抗混叠必须发生在 ADC 之前声卡内部的抗混叠滤波器是按声卡最高采样率设计的当用户把采样率调低到 8k 时它不会自动把带宽压到 4kHz。一个 10kHz 输入信号在 8k 采样下会混叠成 6kHz 的假峰。判断混叠的方法是改变采样率看谱峰是否移动如果移动基本可以断定是混叠。5.2 常见错误与排查顺序现象可能原因处理方式Device is already opened上次采集未删除对象delete(ai)或clear all数据全部为 0麦克风未插好或静音检查系统录音设备频谱峰偏移实际采样率≠设定值用get(ai,SampleRate)回读波形上下削平输入信号超过声卡满量程降低输入增益或加衰减界面无响应getdata 阻塞主线程改用 timer 或异步读取按顺序排查先确认设备打开再看数据是否为零然后检查回读采样率最后才考虑信号本身。实际操作中数据全为 0 最常见的原因是 Windows 里把麦克风设置成了“禁用”而不是 MATLAB 代码写错。5.3 用 1kHz 标准音做采集链路自检最直接的验证方式是用声卡播放一个 1kHz 正弦波同时通过麦克风通道采集回来。选择 1kHz 是因为它落在声卡所有采样率的可重构范围内而且 1 秒数据在 44.1kHz 下正好是 1000 个完整周期FFT 后谱线不会因周期截断而涂抹。fs 44100; t (0:fs-1) / fs; send 0.5 * sin(2 * pi * 1000 * t); sound(send, fs); % 回放测试信号 % 等待 200ms 后采集 pause(0.2); ai analoginput(winsound); addchannel(ai, 1); set(ai, SampleRate, fs); set(ai, SamplesPerTrigger, fs); start(ai); recv getdata(ai); stop(ai); delete(ai); N length(recv); X fft(recv .* hann(N)); f (0:N/2-1) * fs / N; [~, idx] max(abs(X(1:N/2))); fprintf(检测到主峰频率%.2f Hz\n, f(idx));如果打印出的频率不是 1000Hz优先检查系统录音源。录制音量过低时max(abs(X))可能落在 50Hz 工频上可以先把直流和低频部分去掉再做峰值搜索。这种自检流程比单纯看波形更客观也适合留档作为验收记录。6. 进阶把采集程序编译部署再用声卡输出做闭环6.1 MATLAB Compiler 部署时设备对象怎么处理文档要求 MATLAB 程序“编译成可执行文件”在老旧本科毕业设计中常见。把 GUI 编译成 exe 时数据采集工具箱的某些 adaptor 不会被打进安装包目标机器上需要有对应声卡驱动和 MATLAB Runtime。更稳妥的方式是将采集逻辑和界面分离把采集部分做成 MATLAB Production Server 调用或者干脆重新用支持新版工具箱的函数重写一遍界面。6.2 从 winsound 迁移到 audioDeviceReader新版 MATLAB 不再使用analoginput(winsound)改为 Audio Toolbox 的audioDeviceReader。同样实现采集 1 秒声音代码结构变化如下adr audioDeviceReader(SampleRate, 44100, ... SamplesPerFrame, 44100, NumChannels, 1); data adr(); % 一次读取一帧 release(adr);SamplesPerFrame对应SamplesPerTriggerrelease代替delete。连续采集时可以在while循环里逐帧处理实时性比getdata更容易控制。建议把论文里的旧代码和这段新代码放在一起对照迁移核心算法不需要改动只有设备对象创建和读取部分不同。6.3 用声卡输出做整链路闭环验证没有信号发生器时声卡本身就是最好的信号源。用sound放出一个扫频信号再用麦克风采回可以验证从 D/A 到 A/D 的整条链路。例如t (0:fs-1) / fs; chirp_signal chirp(t, 100, 1, 5000); sound(chirp_signal, fs); % 用之前的采集代码把声音采回来采集回来后画出时频图能看出声卡和麦克风的幅频响应是否平坦。这种“输出-采集”闭环比单纯录音多了发送端约束排查问题范围会小很多。如果谱线在某个频率出现明显衰减先换一个参考麦克风再怀疑房间声学或驱动设置不要一上来就调 MATLAB 参数。本文还有配套的精品资源点击获取
返回列表