`
tempsitegoogle
  • 浏览: 885816 次
文章分类
社区版块
存档分类
最新评论

Linux下ALSA声卡编程

 
阅读更多

一.介绍

ALSA标准是一个先进的linux声音体系。它包含内核驱动集合,API库和工具对Linux声音进行支持。ALSA包含一系列内核驱动对不同的声卡进行支持,还提供了libasound的API库。用这些进行写程序不需要打开设备等操作,所以编程人员在写程序的时候不会被底层的东西困扰。与此相反OSS/Free驱动在内核层次调用,需要指定设备名和调用ioctl。为提供向后兼容,ALSA提供内核模块模仿OSS/Free驱动,所以大多数的程序不需要改动。ALSA拥有调用插件的能力对新设备提供扩展,包括那些用软件模拟出来的虚拟设备。ALSA还提供一组命令行工具包括mixer, sound file player和工具控制一些特别的声卡的特别的作用。

二.ALSA体系:

ALSA API被主要分为以下几种接口:

l控制接口:提供灵活的方式管理注册的声卡和对存在的声卡进行查询。

lPCM接口:提供管理数字音频的捕捉和回放。

l原始MIDI接口:支持MIDI (Musical Instrument Digital Interface),一种标准电子音乐指令集。这些API提供访问声卡上的MIDI总线。这些原始借口直接工作在TheMIDI事件上,程序员只需要管理协议和时间。

l记时接口:为支持声音的同步事件提供访问声卡上的定时器。

l音序器接口:一个比原始MIDI接口高级的MIDI编程和声音同步高层接口。它可以处理很多的MIDI协议和定时器。

l混音器接口:控制发送信号和控制声音大小的声卡上的设备。

三.声卡的缓存和数据的传输:

一块声卡有一个声卡内存用来存储记录的样本。当它被写满时就产生中断。内核驱动就使用DMA将数据传输到内存中。同样地,当在播放时就将内存中的声音样本使用DMA传到声卡的内存中!

声卡的缓存是环状的,这里只讨论应用程序中的内存结构:ALSA将数据分成连续的片段然后传到按单元片段传输。

四:典型的声音程序结构:

open interface for capture or playback

set hardware parameters

(access mode, data format, channels, rate, etc.)

while there is data to be processed:

read PCM data (capture)

or write PCM data (playback)

close interface

五.一些例子:

1.显示一些PCM的类型和格式:

#include <iostream>

#include <alsa/asoundlib.h>

int main()

{

std::cout << "ALSA library version: " << SND_LIB_VERSION_STR << std::endl;

std::cout << "PCM stream types: " << std::endl;

for (int val=0; val <= SND_PCM_STREAM_LAST; ++val)

std::cout << snd_pcm_stream_name((snd_pcm_stream_t)val) << std::endl;

std::cout << std::endl;

std::cout << "PCM access types: " << std::endl;

for (int val=0; val <= SND_PCM_ACCESS_LAST; ++val)

std::cout << snd_pcm_access_name((snd_pcm_access_t)val) << std::endl;

std::cout << std::endl;

std::cout << "PCM subformats: " << std::endl;

for (int val=0; val <= SND_PCM_SUBFORMAT_LAST; ++val)

std::cout << snd_pcm_subformat_name((snd_pcm_subformat_t)val) << " (" << snd_pcm_subformat_description((snd_pcm_subformat_t)val) << ")" << std::endl;

std::cout << std::endl;

std::cout << "PCM states: " << std::endl;

for (int val=0; val <= SND_PCM_STATE_LAST; ++val)

std::cout << snd_pcm_state_name((snd_pcm_state_t)val) << std::endl;

std::cout << std::endl;

std::cout << "PCM formats: " << std::endl;

for (int val=0; val <= SND_PCM_FORMAT_LAST; ++val)

std::cout << snd_pcm_format_name((snd_pcm_format_t)val) << " (" << snd_pcm_format_description((snd_pcm_format_t)val) << ")" << std::endl;

std::cout << std::endl;

}

2.打开PCM设备和设置参数

#include <iostream>

#include <alsa/asoundlib.h>

int main()

{

intrc;

snd_pcm_t*handle;

snd_pcm_hw_params_t*params;

unsigned intval, val2;

intdir;

snd_pcm_uframes_tframes;

if ( (rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0)

{

std::cerr << "unable to open pcm devices: " << snd_strerror(rc) << std::endl;

exit(1);

}

snd_pcm_hw_params_alloca(&params);

snd_pcm_hw_params_any(handle, params);

snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);

snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);

snd_pcm_hw_params_set_channels(handle, params, 2);

val = 44100;

snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);

if ( (rc = snd_pcm_hw_params(handle, params)) < 0)

{

std::cerr << "unable to set hw parameters: " << snd_strerror(rc) << std::endl;

exit(1);

}

std::cout << "PCM handle name = " << snd_pcm_name(handle) << std::endl;

std::cout << "PCM state = " << snd_pcm_state_name(snd_pcm_state(handle)) << std::endl;

snd_pcm_hw_params_get_access(params, (snd_pcm_access_t *)&val);

std::cout << "access type = " << snd_pcm_access_name((snd_pcm_access_t)val) << std::endl;

snd_pcm_hw_params_get_format(params, (snd_pcm_format_t*)(&val));

std::cout << "format = '" << snd_pcm_format_name((snd_pcm_format_t)val) << "' (" << snd_pcm_format_description((snd_pcm_format_t)val) << ")" << std::endl;

snd_pcm_hw_params_get_subformat(params, (snd_pcm_subformat_t *)&val);

std::cout << "subformat = '" <<

snd_pcm_subformat_name((snd_pcm_subformat_t)val) << "' (" << snd_pcm_subformat_description((snd_pcm_subformat_t)val) << ")" << std::endl;

snd_pcm_hw_params_get_channels(params, &val);

std::cout << "channels = " << val << std::endl;

snd_pcm_hw_params_get_rate(params, &val, &dir);

std::cout << "rate = " << val << " bps" << std::endl;

snd_pcm_hw_params_get_period_time(params, &val, &dir);

std::cout << "period time = " << val << " us" << std::endl;

snd_pcm_hw_params_get_period_size(params, &frames, &dir);

std::cout << "period size = " << static_cast<int>(frames) << " frames" << std::endl;

snd_pcm_hw_params_get_buffer_time(params, &val, &dir);

std::cout << "buffer time = " << val << " us" << std::endl;

snd_pcm_hw_params_get_buffer_size(params, (snd_pcm_uframes_t *) &val);

std::cout << "buffer size = " << val << " frames" << std::endl;

snd_pcm_hw_params_get_periods(params, &val, &dir);

std::cout << "periods per buffer = " << val << " frames" << std::endl;

snd_pcm_hw_params_get_rate_numden(params, &val, &val2);

std::cout << "exact rate = " << val/val2 << " bps" << std::endl;

val = snd_pcm_hw_params_get_sbits(params);

std::cout << "significant bits = " << val << std::endl;

snd_pcm_hw_params_get_tick_time(params, &val, &dir);

std::cout << "tick time = " << val << " us" << std::endl;

val = snd_pcm_hw_params_is_batch(params);

std::cout << "is batch = " << val << std::endl;

val = snd_pcm_hw_params_is_block_transfer(params);

std::cout << "is block transfer = " << val << std::endl;

val = snd_pcm_hw_params_is_double(params);

std::cout << "is double = " << val << std::endl;

val = snd_pcm_hw_params_is_half_duplex(params);

std::cout << "is half duplex = " << val << std::endl;

val = snd_pcm_hw_params_is_joint_duplex(params);

std::cout << "is joint duplex = " << val << std::endl;

val = snd_pcm_hw_params_can_overrange(params);

std::cout << "can overrange = " << val << std::endl;

val = snd_pcm_hw_params_can_mmap_sample_resolution(params);

std::cout << "can mmap = " << val << std::endl;

val = snd_pcm_hw_params_can_pause(params);

std::cout << "can pause = " << val << std::endl;

val = snd_pcm_hw_params_can_resume(params);

std::cout << "can resume = " << val << std::endl;

val = snd_pcm_hw_params_can_sync_start(params);

std::cout << "can sync start = " << val << std::endl;

snd_pcm_close(handle);

return 0;

}

3.一个简单的声音播放程序

#include <iostream>

#include <alsa/asoundlib.h>

int main()

{

longloops;

intrc;

intsize;

snd_pcm_t*handle;

snd_pcm_hw_params_t*params;

unsigned intval;

intdir;

snd_pcm_uframes_tframes;

char*buffer;

if ( (rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0)

{

std::cerr << "unable to open pcm device: " << snd_strerror(rc) << std::endl;

exit(1);

}

snd_pcm_hw_params_alloca(&params);

snd_pcm_hw_params_any(handle, params);

snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);

snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);

snd_pcm_hw_params_set_channels(handle, params, 2);

val = 44100;

snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);

frames = 32;

snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);

if ( (rc = snd_pcm_hw_params(handle, params)) < 0)

{

std::cerr << "unable to set hw paramseters: " << snd_strerror(rc) << std::endl;

exit(1);

}

snd_pcm_hw_params_get_period_size(params, &frames, &dir);

size = frames * 4;

buffer = new char[size];

snd_pcm_hw_params_get_period_time(params, &val, &dir);

loops = 5000000 / val;

while (loops > 0) {

loops--;

if ( (rc = read(0, buffer, size)) == 0)

{

std::cerr << "end of file on input" << std::endl;

break;

}

else if (rc != size)

std::cerr << "short read: read " << rc << " bytes" << std::endl;

if ( (rc = snd_pcm_writei(handle, buffer, frames)) == -EPIPE)

{

std::cerr << "underrun occurred" << std::endl;

snd_pcm_prepare(handle);

}

else if (rc < 0)

std::cerr << "error from writei: " << snd_strerror(rc) << std::endl;

else if (rc != (int)frames)

std::cerr << "short write, write " << rc << " frames" << std::endl;

}

snd_pcm_drain(handle);

snd_pcm_close(handle);

free(buffer);

return 0;

}

4.一个简单的记录声音的程序

#include <iostream>

#include <alsa/asoundlib.h>

int main()

{

longloops;

intrc;

intsize;

snd_pcm_t*handle;

snd_pcm_hw_params_t*params;

unsigned intval;

intdir;

snd_pcm_uframes_tframes;

char*buffer;

if ( (rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0)) < 0)

{

std::cerr << "unable to open pcm device: " << snd_strerror(rc) << std::endl;

exit(1);

}

snd_pcm_hw_params_alloca(&params);

snd_pcm_hw_params_any(handle, params);

snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);

snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);

snd_pcm_hw_params_set_channels(handle, params, 2);

val = 44100;

snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);

if ( (rc = snd_pcm_hw_params(handle, params)) < 0)

{

std::cerr << "unable to set hw parameters: " << snd_strerror(rc) << std::endl;

exit(1);

}

snd_pcm_hw_params_get_period_size(params, &frames, &dir);

size = frames * 4;

buffer = new char[size];

snd_pcm_hw_params_get_period_time(params, &val, &dir);

loops = 5000000 / val;

while (loops > 0)

{

loops --;

rc = snd_pcm_readi(handle, buffer, frames);

if (rc == -EPIPE)

{

std::cerr << "overrun occurred" << std::endl;

snd_pcm_prepare(handle);

}

else if (rc < 0)

std::cerr << "error from read: " << snd_strerror(rc) << std::endl;

else if ( rc != (int)frames)

std::cerr << "short read, read " << rc << " frames" << std::endl;

rc = write(1, buffer, size);

if (rc != size)

std::cerr << "short write: wrote " << rc << " bytes" << std::endl;

}

snd_pcm_drain(handle);

snd_pcm_close(handle);

free(buffer);

return 0;

}

编译的参数:g++ xxx.cpp -o xxx -lasound

转载地址:http://blog.chinaunix.net/space.php?uid=20664418&do=blog&cuid=2058301

分享到:
评论

相关推荐

    linux alsa 声卡驱动

    Linux ALSA(Advanced Linux Sound Architecture,高级Linux声音架构)是Linux内核中用于处理音频的子系统,它为声卡提供了全面的驱动支持。本文将深入探讨ALSA的工作原理、功能以及如何在Linux环境中配置和使用它。...

    alsa 音频编程例子(源代码)

    在Linux系统中,ALSA(Advanced Linux Sound Architecture,高级...总之,这个压缩包中的ALSA音频编程例子提供了学习和研究Linux音频编程的良好起点,对于熟悉音频设备工作原理和提升Linux系统音频开发技能非常有帮助。

    介绍声卡编程的资料,主要是linux下

    在Linux环境下,声卡编程通常涉及ALSA(Advanced Linux Sound Architecture)和PulseAudio等框架。`Linux音频编程指南.htm`可能涵盖了这些基础,包括如何初始化音频设备、设置采样率、位深度和通道数,以及如何发送...

    Linux平台下的ALSA声音编程.pdf

    Linux 平台下的 ALSA 声音编程 ALSA(Advanced Linux Sound Architecture)是一种高级的 Linux 声音架构,由内核驱动、标准的 API 库和一系列实用程序组成。Linux 2.6 内核抛弃了旧的 OSS,ALSA 被合并到内核中。 ...

    ALSA声卡讲解

    **ALSA声卡详解** ALSA(Advanced Linux Sound Architecture,高级Linux声音架构)是Linux操作系统下的核心音频系统,为各种声卡提供驱动程序和服务。它为应用程序提供了丰富的接口,使得开发者能够灵活地处理声音...

    ALSA架构声卡相关资料

    1. 设备节点:在Linux系统中,ALSA设备通常表示为/dev/snd下的字符或块设备,如pcm(脉冲编码调制)、seq(MIDI序列)等。 2. PCM:PCM是ALSA处理音频流的主要方式,用于模拟音频数据的数字表示。它包含两个主要部分...

    Linux_alsa.zip_alsa_linux 音频驱动

    综上所述,"Linux_alsa.zip"中的文档可能会涵盖ALSA的基本概念、配置方法、编程接口示例以及与其他音频系统的集成等内容,对于理解和使用Linux音频系统非常有帮助。如果你打算在Linux环境中进行音频开发或解决音频...

    Linux ALSA详解.pdf

    ALSA(Advanced Linux Sound Architecture,高级Linux声音架构)是Linux操作系统下目前主流的音频体系结构,它负责处理音频和MIDI数据。它由多个模块构成,包括设备驱动、声音服务和声音应用程序接口,使得Linux系统...

    alsa 声卡应用程序设计指导文档及示范代码

    在本文中,我们将深入探讨`alsa`声卡应用程序的设计与开发,主要基于提供的"alsa 声卡应用程序设计指导文档及示范代码"。`alsa`(Advanced Linux Sound Architecture,高级Linux声音架构)是Linux内核中的一个核心...

    声卡编程程序

    在IT领域,声卡编程程序是一个非常有趣且实用的主题,特别是在多媒体和音频处理技术中。声卡是计算机硬件的一部分,负责处理和传输音频信号,而编程则是为了与这些硬件进行交互,实现各种功能,如录音、播放、音效...

    aplay.tar.gz_alsa arecord源码_aplay 源码_aplay源码_linux alsa 录音_录音

    在Linux操作系统中,音频处理是通过ALSA(Advanced Linux Sound Architecture)库来完成的,它为用户空间的应用程序提供了一套完整的音频驱动接口。本文将深入探讨`aplay`和`arecord`这两个命令行工具的源码,它们是...

    S oPC平台下ALSA标准声卡驱动设计与实现

    #### SoPC平台下的ALSA声卡驱动设计 在SoPC平台上设计和实现符合ALSA标准的声卡驱动是一项复杂但非常有价值的挑战。本文主要关注Xilinx Virtex系列开发板上的AC97控制器IP核,并在此基础上探讨如何设计与实现ALSA...

    Linux-audio-interface.rar_ALSA接口_Audio接口_alsa_linux_linux alsa

    ALSA(Advanced Linux Sound Architecture,高级Linux声音架构)是Linux系统下的核心音频接口,为开发者提供了一个灵活且功能丰富的平台来处理音频输入和输出。本文将深入探讨ALSA接口,以及它如何在Linux中扮演关键...

    alsa_driver.rar_alsa-driver_alsa_driver_linux_linux alsa

    《Linux ALSA驱动详解》 在Linux操作系统中,音频服务主要由Advanced Linux Sound Architecture(ALSA)提供。ALSA是一个底层驱动层,为各种音频硬件设备提供了接口,并且支持多种操作系统层面的应用程序。本文将...

    C语言声卡编程程序下载

    在Linux系统中,可以使用ALSA(Advanced Linux Sound Architecture)或PulseAudio等库。 .wav文件是一种未经压缩的音频文件格式,包含原始的PCM(脉冲编码调制)数据。这种格式的优点是保真度高,但缺点是文件体积...

    ALSA.rar_alsa_linux alsa

    总之,"ALSA.rar_alsa_linux alsa"这个压缩包是学习Linux环境下ALSA驱动的宝贵资源。通过研究驱动范例,开发者能深入理解ALSA的工作原理,并具备在实际项目中集成和操作音频设备的能力。同时,结合www.pudn.com.txt...

    ALSA.rar_alsa_alsa 播放_linux alsa 录音

    在Linux下,通过ALSA API可以打开声卡设备,创建一个PCM(脉冲编码调制)流来捕获声音。首先,需要使用`snd_pcm_open()`函数打开声卡设备,然后设置录音参数如采样率、位深度、通道数等,这些参数决定了录音的质量和...

    linux测试声卡程序

    这个小程序具有很好的学习价值,对于理解Linux下的声音处理和编程有极大的帮助。 首先,我们要了解OSS。OSS是早期Linux系统广泛使用的声音系统,它提供了一套API接口供开发者直接与硬件交互,包括打开设备、读写...

    linux 声卡驱动

    首先,Linux下的声卡驱动通常基于Advanced Linux Sound Architecture(ALSA)或者PulseAudio等框架。ALSA提供了底层的硬件访问接口,而PulseAudio则作为上层的应用程序接口,简化了音频处理和多路复用。开发者在编写...

    linux语音聊天

    基于linux alsa 声卡编程,用c写的代码,能够语音聊天

Global site tag (gtag.js) - Google Analytics