博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ALSA howto
阅读量:4058 次
发布时间:2019-05-25

本文共 8666 字,大约阅读时间需要 28 分钟。

ALSA Tutorial 1 - Initialization

This tutorial assumes that you are familiar with the C++ programming language and the Linux operating system.

The Advanced Linux Sound Architecture (ALSA) is the standard audio API of Linux as of kernel version 2.6. It is a higher-level API than its predecessor, the Open Sound System (OSS) and requires less effort on the part of the programmer to implement in an application.

This tutorial assumes that you will be using g++, which is the standard Linux C++ compiler. You will also need to have libasound2 and libasound2-dev installed. In Ubuntu, which was the Linux distribution that was used for this tutorial, g++, libasound2, and libasound2-dev are not installed by default and will need to be installed using the Add/remove applications menu.

ALSA requires the the asoundlib.h header. Is is included with this line:

#include 
The process of initializing ALSA is fairly long and involved. In a nutshell, we open the sound device, create a structure to hold the parameters we want to use, and then tell the sound device to use those settings. If successful, we then prepare the sound device for use.

For the first example, we are using a global variable to keep track of our sound device. Globals are generally a bad idea, but in this case it keeps the example simple.

The first call is to snd_pcm_open. One of the parameters is the sound device, into which we will pass "plughw:0,0", the default sound device, and a constant that tells the device we want to use it for playback.

err = snd_pcm_open( &_soundDevice, "plughw:0,0", SND_PCM_STREAM_PLAYBACK, 0 );
If something goes wrong, we will have an error code, which can be translated into a string using snd_strerror(). We check for errors throughout the code.

Next we allocate memory for the hardware parameter struct.

err = snd_pcm_hw_params_malloc (&hw_params);
Once we have this, we can get the current paramters from the sound device:
err = snd_pcm_hw_params_any (_soundDevice, hw_params);
Now that we have this information, we can change it to suit our needs.

Here we turn on resampling:

unsigned int resample = 1;err = snd_pcm_hw_params_set_rate_resample(_soundDevice, hw_params, resample);
Here we set our samples to interleaved:
err = snd_pcm_hw_params_set_access (_soundDevice, hw_params,SND_PCM_ACCESS_RW_INTERLEAVED)
Interleaving means that we alternate samples for the left and right channel (LRLRLR).

Here we set our sample format to PCM 16-bit little-endian. If you are not using a little-endian (i.e. Intel or AMD) machine you will want to use a different setting.

(err = snd_pcm_hw_params_set_format (_soundDevice, hw_params, SND_PCM_FORMAT_S16_LE)
Here we set our stream to 2 channels (stereo):
err = snd_pcm_hw_params_set_channels (_soundDevice, hw_params, 2)
Here we set our sample playback rate to 44100:
unsigned int actualRate = 44100;err = snd_pcm_hw_params_set_rate_near (_soundDevice, hw_params, &actualRate, 0);
Now that we've made our settings, we apply them to the sound device.
err = snd_pcm_hw_params (_soundDevice, hw_params);
With the sound device set up, we now check what buffer size we've been given:
snd_pcm_uframes_t bufferSize;snd_pcm_hw_params_get_buffer_size( hw_params, &bufferSize );cout << "Init: Buffer size = " << bufferSize << " frames." << endl;_playbackFrames = bufferSize;cout << "Init: Significant bits for linear samples = " << snd_pcm_hw_params_get_sbits(hw_params) << endl;
We the free the memory for the hardware parameter struct:
snd_pcm_hw_params_free (hw_params);
And finally, we prepare the audio interface for use:
err = snd_pcm_prepare (_soundDevice);
When we're done using the audio interface, we can close it like this:
snd_pcm_close (_soundDevice);
There are a lot of changes that can be made to parameters and a lot more settings that can be made, but this should give you the basics.

The code for this tutorial only initializes and then de-initializes the sound device. That isn't much, but it's a start. In the second tutorial we'll actually hear something come from the speakers.

Linking requires the asound library. To link the file, we add -lasound to the linker flags.

g++ -o alsatut1 alsatut1.cpp -lasound
To run the program, enter ./asound at the command prompt. If everything goes as planned, the application should display the following messages, or something similar:

Audio device openened successfully.

Audio device parameters have been set successfully.
Init: Buffer size = 2048 frames.
Init: Significant bits for linear samples = 16
Audio device has been prepared for use.
Audio device has been uninitialized.

Here is the actual code used. Note that we have done everything in a single file, alsatut1.cpp, with no header files:

#include 
#include
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;}

转载地址:http://ddzji.baihongyu.com/

你可能感兴趣的文章
SSH原理与运用
查看>>
SIGN UP BEC2
查看>>
S3C2440中对LED驱动电路的理解
查看>>
《天亮了》韩红
查看>>
Windows CE下USB摄像头驱动开发(以OV511为例,附带全部源代码以及讲解) [转]
查看>>
出现( linker command failed with exit code 1)错误总结
查看>>
iOS开发中一些常见的并行处理
查看>>
iOS获取手机的Mac地址
查看>>
ios7.1发布企业证书测试包的问题
查看>>
如何自定义iOS中的控件
查看>>
iOS 开发百问
查看>>
Mac环境下svn的使用
查看>>
github简单使用教程
查看>>
如何高效利用GitHub
查看>>
环境分支-git版本管理
查看>>
uni-app 全局变量
查看>>
js判断空对象的几种方法
查看>>
java 不用递归写tree
查看>>
springboot2 集成Hibernate JPA 用 声明式事物
查看>>
fhs-framework jetcache 缓存维护之自动清除缓存
查看>>