alsa(Advanced Linux Sound Architecture )
是什么:
简单的说,linux之前的内核里处理声音使用oss,后来大家觉得不好用,重写了声音部分,改名叫alsa(更高级的),并且提供了用户空间库(alsa-lib),供应用程序方便调用。
官方说明:
高级 Linux 声音架构 (ALSA) 为 Linux 操作系统提供音频和 MIDI 功能。ALSA具有以下显着特点:
- 有效支持所有类型的音频接口,从消费级声卡到专业的多声道音频接口。
- 完全模块化的声音驱动程序。
- SMP 和线程安全设计(请阅读本文)。
- 用户空间库 (alsa-lib) 可简化应用程序编程并提供更高级别的功能。
- 支持旧的开放声音系统 (OSS) API,为大多数 OSS 程序提供二进制兼容性。
使用:
安装
apt-get(sudo apt-get install libasound2-dev libasound2)
这是实际使用的代码。请注意,我们在一个文件 alsatut1.cpp 中完成了所有操作,没有头文件:
g++ -oalsatut1 alsatut1.cpp -lasound
然后,您可以在命令行上使用 ./alsatut1 运行该程序。运气好的话,它会成功初始化。
#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( int argv, char **argc )
{
Init(NULL);
UnInit();
return 0;
}
jack:
是什么:
JACK 是一个低延迟音频服务器.
它专注于两个关键领域:所有客户端的同步执行和低延迟操作。
它是一个应用端程序,而不是操作系统的驱动,所以jack需要和读写alsa驱动,实际jack内部需要alsa-lib库来支持alsa硬件。
因为只是一个应用程序,所以jack可以支持多操作系统。
使用:
sudo apt-get install jack-dev
/** @file simple_client.c
*
* @brief This simple client demonstrates the most basic features of JACK
* as they would be used by many applications.
*/
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <jack/jack.h>
#define AMPLITUDE 0.01
jack_port_t *output_port1, *output_port2;
jack_client_t *client;
float randnorm = 1.0/(float)(RAND_MAX);
/**
* The process callback for this JACK application is called in a
* special realtime thread once for each audio cycle.
*
* This client does nothing more than copy data from its input
* port to its output port. It will exit when stopped by
* the user (e.g. using Ctrl-C on a unix-ish operating system)
*/
int
process (jack_nframes_t nframes, void *arg)
{
jack_default_audio_sample_t *out1, *out2;
out1 = jack_port_get_buffer (output_port1, nframes);
out2 = jack_port_get_buffer (output_port2, nframes);
for (int i=0; i<nframes; i++) {
float rand1 = 0.0;
float rand2 = 0.0;
for (int j=0;j<4;j++) {
rand1 += ((float)rand()) * randnorm;
rand2 += ((float)rand()) * randnorm;
}
out1[i] = AMPLITUDE * (rand1 - 2);
out2[i] = AMPLITUDE * (rand2 - 2);
}
return 0;
}
/**
* JACK calls this shutdown_callback if the server ever shuts down or
* decides to disconnect the client.
*/
void
jack_shutdown (void *arg)
{
exit (1);
}
int
main (int argc, char *argv[])
{
const char *client_name = "whitenoise";
const char *server_name = NULL;
jack_options_t options = JackNullOption;
jack_status_t status;
/* open a client connection to the JACK server */
client = jack_client_open (client_name, options, &status, server_name);
if (client == NULL) {
fprintf (stderr, "jack_client_open() failed, "
"status = 0x%2.0x\n", status);
if (status & JackServerFailed) {
fprintf (stderr, "Unable to connect to JACK server\n");
}
exit (1);
}
if (status & JackServerStarted) {
fprintf (stderr, "JACK server started\n");
}
if (status & JackNameNotUnique) {
client_name = jack_get_client_name(client);
fprintf (stderr, "unique name `%s' assigned\n", client_name);
}
/* tell the JACK server to call `process()' whenever
there is work to be done.
*/
jack_set_process_callback (client, process, 0);
/* tell the JACK server to call `jack_shutdown()' if
it ever shuts down, either entirely, or if it
just decides to stop calling us.
*/
jack_on_shutdown (client, jack_shutdown, 0);
/* display the current sample rate.
*/
printf ("engine sample rate: %" PRIu32 "\n",
jack_get_sample_rate (client));
output_port1 = jack_port_register (client, "output_1",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
output_port2 = jack_port_register (client, "output_2",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
if ((output_port1 == NULL) || (output_port2 == NULL)) {
fprintf(stderr, "no more JACK ports available\n");
exit (1);
}
/* Tell the JACK server that we are ready to roll. Our
* process() callback will start running now. */
if (jack_activate (client)) {
fprintf (stderr, "cannot activate client");
exit (1);
}
/* keep running until stopped by the user */
sleep (-1);
/* this is never reached but if the program
had some other way to exit besides being killed,
they would be important to call.
*/
jack_client_close (client);
exit (0);
}
总结
alsa是linux内核驱动,并且有一个用户端库供用户使用。
jack是用户端程序,提供专业的低延时易用功能,供音频处理专业人士使用。
参考网址:
Tutorial: ALSA Tutorial 1 - Initialization
https://zhuanlan.zhihu.com/p/600338119
Demystifying JACK - A Beginners Guide to Getting Started with JACK
标签:JACK,linux,output,include,port,jack,alsa From: https://www.cnblogs.com/qqdpp/p/17927434.html