【发布时间】:2016-08-26 16:40:05
【问题描述】:
我正在尝试使用 EEG 输入构建大脑设备,并在 Raspberry PI 上“接近实时”输出光脉冲和双耳节拍。使用 WiringPi 的光输出没有问题,但任何音频输出似乎都是一个主要障碍。为缓冲区计算正弦波的数学很简单,但是通过任何标准库在两个通道上播放两个频率似乎是一个非常复杂的过程,我想不出任何相关的例子。感谢this tutorial,我已经成功打开和关闭了一个 ALSA 设备,这使我相当简单的代码非常复杂,但对于 ALSA 来说似乎是必要的。如果有人能告诉我在左右声道上播放两种不同的计算音调的最简单方法,我将非常感激。下面的代码是我能找到的最简单的 ALSA 播放示例。
#include <alsa/asoundlib.h>
#include <iostream>
using namespace std;
// Globals are generally a bad idea in code. We're using one here to keep it simple.
snd_pcm_t * _soundDevice;
bool Init(const char *name)
{
int i;
int err;
snd_pcm_hw_params_t *hw_params;
if( name == NULL )
{
// Try to open the default device
err = snd_pcm_open( &_soundDevice, "plughw:0,0", SND_PCM_STREAM_PLAYBACK, 0 );
}
else
{
// Open the device we were told to open.
err = snd_pcm_open (&_soundDevice, name, SND_PCM_STREAM_PLAYBACK, 0);
}
// Check for error on open.
if( err < 0 )
{
cout << "Init: cannot open audio device " << name << " (" << snd_strerror (err) << ")" << endl;
return false;
}
else
{
cout << "Audio device opened successfully." << endl;
}
// Allocate the hardware parameter structure.
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0)
{
cout << "Init: cannot allocate hardware parameter structure (" << snd_strerror (err) << ")" << endl;
return false;
}
if ((err = snd_pcm_hw_params_any (_soundDevice, hw_params)) < 0)
{
cout << "Init: cannot initialize hardware parameter structure (" << snd_strerror (err) << ")" << endl;
return false;
}
// Enable resampling.
unsigned int resample = 1;
err = snd_pcm_hw_params_set_rate_resample(_soundDevice, hw_params, resample);
if (err < 0)
{
cout << "Init: Resampling setup failed for playback: " << snd_strerror(err) << endl;
return err;
}
// Set access to RW interleaved.
if ((err = snd_pcm_hw_params_set_access (_soundDevice, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
{
cout << "Init: cannot set access type (" << snd_strerror (err) << ")" << endl;
return false;
}
if ((err = snd_pcm_hw_params_set_format (_soundDevice, hw_params, SND_PCM_FORMAT_S16_LE)) < 0)
{
cout << "Init: cannot set sample format (" << snd_strerror (err) << ")" << endl;
return false;
}
// Set channels to stereo (2).
if ((err = snd_pcm_hw_params_set_channels (_soundDevice, hw_params, 2)) < 0)
{
cout << "Init: cannot set channel count (" << snd_strerror (err) << ")" << endl;
return false;
}
// Set sample rate.
unsigned int actualRate = 44100;
if ((err = snd_pcm_hw_params_set_rate_near (_soundDevice, hw_params, &actualRate, 0)) < 0)
{
cout << "Init: cannot set sample rate to 44100. (" << snd_strerror (err) << ")" << endl;
return false;
}
if( actualRate < 44100 )
{
cout << "Init: sample rate does not match requested rate. (" << "44100 requested, " << actualRate << " acquired)" << endl;
}
// Apply the hardware parameters that we've set.
if ((err = snd_pcm_hw_params (_soundDevice, hw_params)) < 0)
{
cout << "Init: cannot set parameters (" << snd_strerror (err) << ")" << endl;
return false;
}
else
{
cout << "Audio device parameters have been set successfully." << endl;
}
// Get the buffer size.
snd_pcm_uframes_t bufferSize;
snd_pcm_hw_params_get_buffer_size( hw_params, &bufferSize );
// If we were going to do more with our sound device we would want to store
// the buffer size so we know how much data we will need to fill it with.
cout << "Init: Buffer size = " << bufferSize << " frames." << endl;
// Display the bit size of samples.
cout << "Init: Significant bits for linear samples = " << snd_pcm_hw_params_get_sbits(hw_params) << endl;
// Free the hardware parameters now that we're done with them.
snd_pcm_hw_params_free (hw_params);
// Prepare interface for use.
if ((err = snd_pcm_prepare (_soundDevice)) < 0)
{
cout << "Init: cannot prepare audio interface for use (" << snd_strerror (err) << ")" << endl;
return false;
}
else
{
cout << "Audio device has been prepared for use." << endl;
}
return true;
}
bool UnInit()
{
snd_pcm_close (_soundDevice);
cout << "Audio device has been uninitialized." << endl;
return true;
}
int main( char *argc, int argv )
{
Init(NULL);
UnInit();
return 0;
}
【问题讨论】:
-
这不是问题...?
-
一种简单的方法是从您的代码中调用 shell 命令“aplay”。
标签: c++ linux audio raspberry-pi alsa