播放声音
<ol>
<li>
<p>插入USB声卡,连接扬声器
<img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=9e2889a353f10414d0ad67afae744694" alt="" /></p>
</li>
<li>
<p>检查USB声卡设备</p>
<pre><code class="language-bash">lsusb
#加入有一条为Bus 001 Device 006: ID 0d8c:0012 C-Media Electronics, Inc. USB Audio Device
#Bus 001: USB 总线编号。系统可能有多个 USB 总线(物理端口),Bus 001 表示该设备连接在第一个 USB 总线上
#Device 00x: 该总线上设备的编号。每条 USB 总线上的设备都有一个唯一的编号。这个编号是动态分配的,每次你插入设备时可能会发生变化,系统启动后设备编号也可能不同。
#ID 0d8c:0012中
#0d8c: 设备的 厂商 ID(Vendor ID)
#0012: 设备的 产品 ID(Product ID)
#C-Media Electronics, Inc. :制造商名称
#USB Audio Device:产品描述</code></pre>
<p>正常会显示含有C-Media Electronics, Inc. USB Audio Device信息条目</p>
<pre><code class="language-bash">#浏览声卡设备文件
ls /dev/snd
#controlC0:内置声卡的控制接口
#pcmC0D0c:内置声卡的捕获设备(麦克风)
#pcmC0D0p:内置声卡的播放设备
#controlC1:插入的USB声卡的控制接口
#pcmC1D0p:差人的USB声卡播放设备</code></pre>
</li>
<li>
<p>使用命令行播放声音测试</p>
<pre><code>#查看所有音频设备
aplay -l
#使用默认设备播放
aplay /usr/share/ibus-table/data/coin9.wav
#如果默认播放没有声音,可使用-D指定播放设备,hw:1,0,表示用card 1,device 0播放,与上面aplay -l 命令列表中的信息一致
aplay -D hw:1,0 /usr/share/ibus-table/data/coin9.wav
#调节音量
alsamixer</code></pre>
</li>
<li>
<p>使用python播放声音</p>
<pre><code class="language-bash">mkdir -p ~/code_test/soundplay_test
cd ~/code_test/soundplay_test
python3 -m venv venv
source ./venv/bin/activate
python3 -m pip install soundplay soundfile
sudo apt install portaudio19-dev</code></pre>
<p>新建一个python测试文件soundplay_test.py,内容如下</p>
<pre><code class="language-python">import sounddevice as sd
import soundfile as sf
# 读取WAV文件
data, samplerate = sf.read('/usr/share/ibus-table/data/coin9.wav')
# 播放音频
sd.play(data, samplerate)
# 等待播放完成
sd.wait()</code></pre>
<pre><code class="language-bash">python soundplay_test.py
deactivate</code></pre>
</li>
<li>
<p>使用用C++播放声音</p>
<pre><code class="language-bash">#安装依赖库
sudo apt install libasound2-dev libsndfile1-dev</code></pre>
<p>新建一个python测试文件soundplay_test.cpp,内容如下</p>
<pre><code class="language-cpp">#include &lt;alsa/asoundlib.h&gt;
#include &lt;sndfile.h&gt;
#include &lt;iostream&gt;
int play_wav(const char *filename)
{
SF_INFO sfinfo;
SNDFILE *infile = sf_open(&quot;/tmp/test.wav&quot;, SFM_READ, &amp;sfinfo);
if (!infile)
{
std::cerr &lt;&lt; &quot;Error opening WAV file: &quot; &lt;&lt; sf_strerror(infile) &lt;&lt; std::endl;
return -1;
}
// 检查通道数
if (sfinfo.channels &gt; 2)
{
std::cerr &lt;&lt; &quot;Only mono and stereo are supported.&quot; &lt;&lt; std::endl;
sf_close(infile);
return -1;
}
// 设置 ALSA 参数
snd_pcm_t *pcm_handle;
snd_pcm_hw_params_t *params;
unsigned int sample_rate = sfinfo.samplerate;
int channels = sfinfo.channels;
int dir;
// 打开 PCM 设备
if (snd_pcm_open(&amp;pcm_handle, &quot;default&quot;, SND_PCM_STREAM_PLAYBACK, 0) &lt; 0)
{
std::cerr &lt;&lt; &quot;Error opening PCM device &quot; &lt;&lt; &quot;default&quot; &lt;&lt; std::endl;
sf_close(infile);
return -1;
}
// 分配参数对象
snd_pcm_hw_params_alloca(&amp;params);
// 填充参数对象
snd_pcm_hw_params_any(pcm_handle, params);
// 设置访问类型
snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
// 设置数据格式 (16位PCM)
snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE);
// 设置采样率
snd_pcm_hw_params_set_rate_near(pcm_handle, params, &amp;sample_rate, 0);
// 设置通道数
snd_pcm_hw_params_set_channels(pcm_handle, params, channels);
// 设置硬件参数
if (snd_pcm_hw_params(pcm_handle, params) &lt; 0)
{
std::cerr &lt;&lt; &quot;Error setting PCM hardware parameters.&quot; &lt;&lt; std::endl;
sf_close(infile);
snd_pcm_close(pcm_handle);
return -1;
}
// 获取周期大小
snd_pcm_uframes_t frames;
snd_pcm_hw_params_get_period_size(params, &amp;frames, &amp;dir);
// 分配缓冲区
int16_t *buffer = new int16_t[frames * channels];
sf_count_t num_frames;
// 播放音频
while ((num_frames = sf_readf_short(infile, buffer, frames)) &gt; 0)
if (snd_pcm_writei(pcm_handle, buffer, num_frames) &lt; 0)
snd_pcm_prepare(pcm_handle);
// 清理
delete[] buffer;
sf_close(infile);
snd_pcm_drain(pcm_handle);
snd_pcm_close(pcm_handle);
return 0;
}
int main()
{
play_wav(&quot;/usr/share/ibus-table/data/coin9.wav&quot;);
return 0;
}
//g++ -o soundplay_test ./soundplay_test.cpp -lasound -lsndfile</code></pre>
<p>编译执行</p>
<pre><code class="language-bash">#编译
g++ -o soundplay_test ./soundplay_test.cpp -lasound -lsndfile
#执行
./soundplay_test</code></pre>
</li>
<li>
<p>开机提示音
创建开机启动文件</p>
<pre><code class="language-bash">sudo vim /etc/systemd/system/startup_sound.service</code></pre>
<p>填入下面内容</p>
<pre><code class="language-bash">[Unit]
Description=Play startup sound
After=graphical.target
[Service]
Type=oneshot
ExecStart=/usr/bin/aplay /usr/share/ibus-table/data/coin9.wav
RemainAfterExit=true
[Install]
WantedBy=graphical.target</code></pre>
<pre><code class="language-bash">#设为开机启动
sudo systemctl enable startup_sound.service
#取消开机启动
sudo systemctl disable startup_sound.service</code></pre>
</li>
</ol>