首页 > 系统相关 >linux声音处理 alsa & jack 是什么

linux声音处理 alsa & jack 是什么

时间:2023-12-26 09:45:52浏览次数:42  
标签:JACK linux output include port jack alsa

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

JACK Audio Connection Kit

 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

相关文章

  • node.js安装到Linux
    下载地址:https://nodejs.org/dist/1、准备node安装包,可以进入镜像站 ,自行选择版本进行下载,这里下载的是 node-v12.22.3-linux-x64.tar.xz2、将本地的安装包上传到linux服务器上,我这里放在/home/software目录下3、在/usr/local下创建node文件夹mkdir/usr/local/......
  • Maven安装步骤--linux
    安装 maven环境前,需要先安装java环境Linux安装jdk1、maven 官网下载安装包maven官网地址:Maven–DownloadApacheMaven历史版本3.6.3为例:  2、安装maven 2.1创建maven文件夹,仓库文件夹mkdir-p/usr/local/maven  mkdir-p/usr/local/maven/reposi......
  • Linux配置NFS文件共享
    一、NFS简介NFS是NetworkFileSystem的缩写,是一种分布式文件系统协议,用于在计算机网络上共享文件。它允许客户端计算机通过网络远程访问和处理远程服务器上的文件和目录。NFS最初由SunMicrosystems开发并在1984年发布,被设计为可在不同操作系统和硬件平台之间共享文件。它基于客户......
  • Linux文件系统(以ext2为例)
    所有的计算机程序都需要存储和检索信息。长期存储信息有三个基本要求:能够存储大量信息。存储必须持久化。多个进程可以并发访问这些信息。这些任务一般由磁盘来进行。虽然固态硬盘在近年逐渐流行,但传统磁盘依然是存储大量数据的首选。本文只针对磁盘,不对固态硬盘进行讨论。使用磁盘......
  • 1.Linux是什么与如何学习
    第1章Linux是什么与如何学习历史部分略过。1.2.5Linux的内核版本Linux的内核版本编号有点类似如下的样子:3.10.0-123.el7.x86_64主版本.次版本.发布版本-修改版本虽然编号就是如上的方式来编的,不过依据Linux内核的发展期程,内核版本的定义有点不太相同奇数、偶数版......
  • Linux收包之数据L3层是如何流转的
    一、环境说明内核版本:Linux3.10内核源码地址:https://elixir.bootlin.com/linux/v3.10/source(包含各个版本内核源码,且网页可全局搜索函数)网卡:Intel的igb网卡网卡驱动源码目录:drivers/net/ethernet/intel/igb/二、L3层概览 本章主要介绍收包的流程,在L3层是如何处理的。......
  • linux 用户注销
    1.先用w命令查看当前登录系统的用户:[root@centos~]#w11:48:09up 3:13, 2users, loadaverage:0.00,0.01,0.00USER  TTY   FROM       LOGIN@ IDLE JCPU PCPUWHATroot  pts/0  218.17.167.82  11:47  0.00s......
  • linux生成ssh的一对公钥和私钥
    1.首先进入.SSH目录中Linux中,每个用户的根目录下都有一个.ssh目录,保存了ssh相关的key和一些记录文件。例如:cd~/ll-a 2. 使用ssh-keygen生成keyssh-keygen可以生成ssh协议所需要的公钥和私钥,例如:ssh-keygen-trsa然后回提示让你输入一些文件名啥的,别管那些,一路按E......
  • linux-DNS服务器
    一、1、理解区域(zone)DNS的每一个区域都是一个域---一个区域可以管辖多个子域、2、解析正向解析:通过域名解析出ip地址反向解析:根据ip地址解析出dns名称解析过程客户端dns(host文件)本地dns区域dns服务器缓存3、部署dns服务器一般使用传统BIND软件包或者unbound、......
  • linux编译器:gcc/g++的使用
    原文连接:https://blog.csdn.net/weixin_72060925/article/details/131274627原文链接:https://blog.csdn.net/qq_65207641/article/details/128629904一、编辑器与编译器的区别vim是代码编辑器,代码编辑器的功能是让我们输入代码的。所以从这个角度出发,我们常见的记事本也可以......