Linux下ALSA音效卡編程__Arduino

來源:互聯網
上載者:User
一 . 介紹

      ALSA 標準是一個先進的 linux 聲音體系。它包含核心驅動集合, API 庫和工具對 Linux 聲音進行支援。 ALSA 包含一系列核心驅動對不同的音效卡進行支援,還提供了 libasound 的 API 庫。用這些進行寫程式不需要開啟裝置等操作,所以編程人員在寫程式的時候不會被底層的東西困擾。與此相反 OSS/Free 驅動在核心層次調用,需要指定裝置名稱和調用 ioctl 。為提供向後相容, ALSA 提供核心模組模仿 OSS/Free 驅動,所以大多數的程式不需要改動。 ALSA 擁有調用外掛程式的能力對新裝置提供擴充,包括那些用軟體類比出來的虛擬設備。 ALSA 還提供一組命令列工具包括   mixer, sound file player 和工具控制一些特別的音效卡的特別的作用。

  二 .ALSA 體系:

ALSA API 被主要分為以下幾種介面:

l         控制介面:提供靈活的方式管理註冊的音效卡和對存在的音效卡進行查詢。

l         PCM 介面:提供管理數字音訊捕捉和回放。

l         原始 MIDI 介面 : 支援 MIDI (Musical Instrument Digital Interface), 一種標準電子音樂指令集。 這些 API 提供訪問音效卡上的 MIDI 匯流排。這些原始借口直接工作在 The  MIDI 事件上,程式員只需要管理協議和時間。

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()

{

       int                               rc;

       snd_pcm_t*                         handle;

       snd_pcm_hw_params_t*      params;

       unsigned int                  val, val2;

       int                               dir;

       snd_pcm_uframes_t             frames;

 

       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);

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.