终端钢琴应用音频输出异常:需两次调用playNote才能正常发声求助
问题原因分析
这种异常大概率是音频输出缓冲区的缓冲机制导致的,结合你使用/dev/audio和padsp的场景,具体原因如下:
- 音频输出系统(包括
padsp模拟的音频设备)通常会维护一块播放缓冲区,只有当缓冲区中的音频数据积累到一定大小(达到驱动的播放阈值)时,才会将数据发送到音频硬件进行播放。 - 当你只调用一次
playNote时,写入的单份音频样本数据量太小,不足以填满缓冲区,数据会被暂时存放在缓冲区中而不触发播放——这就是第一次按键无声音的原因。 - 第二次按键时,再次调用
playNote写入新的样本,此时缓冲区中积累了两次的音频数据,达到了播放阈值,所以两次的音符会被一次性播放出来。 - 而连续调用两次
playNote,相当于单次写入了两倍的音频样本数据,直接满足了缓冲区的播放触发条件,所以每次按键都能立即对应发声。
另外,也有可能是playNote函数内部的实现问题:
- 如果
playNote是每次打开/dev/audio写入数据后立即关闭,那么关闭文件句柄时的缓冲区刷新操作可能需要一定的数据量才能触发播放; - 如果是保持文件句柄持续打开,但没有主动调用
flush类操作刷新缓冲区,也会导致数据滞留在用户空间缓冲区,直到积累到足够量才会被推送至内核播放。
你可以尝试在单次调用playNote后,主动刷新音频文件句柄的缓冲区(比如Perl中用$fh->flush()),或者调整playNote中写入的音频样本长度,让单份样本就能填满最小播放缓冲区,这样应该就能解决问题,无需重复调用两次。
相关循环代码:
ReadMode 'cbreak'; while(1){ sleep 1/$refreshRate; my $key = ReadKey(-1) or next;; last if ( ord($key)==27); # escape key exits playNote( ord($key)%96); # have to call play note twice playNote( ord($key)%96); }
内容的提问来源于stack exchange,提问作者Saif Ahmed
相关产品推荐
相关产品推荐

