zoukankan      html  css  js  c++  java
  • Linux音频编程--使用ALSA库播放wav文件

    在UBUNTU系统上使用alsa库完成了对外播放的wav文件的案例。

    案例代码:

    /**
    *test.c
    *
    *注意:这个例子在Ubuntu 12.04.1环境下编译运行成功。
    *
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <alsa/asoundlib.h>
    
    int main(int argc, char *argv[])
    {
        int i;
        int ret;
        int buf[128];
        unsigned int val;
        int dir=0;
        char *buffer;
        int size;
        snd_pcm_uframes_t frames;
        snd_pcm_uframes_t periodsize;
        snd_pcm_t *playback_handle;//PCM设备句柄pcm.h
        snd_pcm_hw_params_t *hw_params;//硬件信息和PCM流配置
        if (argc != 2) {
            printf("error: alsa_play_test [music name]
    ");
            exit(1);
        }
        printf("play song %s by wolf
    ", argv[1]);
        FILE *fp = fopen(argv[1], "rb");
        if(fp == NULL)
        return 0;
        fseek(fp, 100, SEEK_SET);
    
        //1. 打开PCM,最后一个参数为0意味着标准配置
        ret = snd_pcm_open(&playback_handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
        if (ret < 0) {
            perror("snd_pcm_open");
            exit(1);
        }
    
        //2. 分配snd_pcm_hw_params_t结构体
        ret = snd_pcm_hw_params_malloc(&hw_params);
        if (ret < 0) {
            perror("snd_pcm_hw_params_malloc");
            exit(1);
        }
        //3. 初始化hw_params
        ret = snd_pcm_hw_params_any(playback_handle, hw_params);
        if (ret < 0) {
            perror("snd_pcm_hw_params_any");
            exit(1);
        }
        //4. 初始化访问权限
        ret = snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
        if (ret < 0) {
            perror("snd_pcm_hw_params_set_access");
            exit(1);
        }
        //5. 初始化采样格式SND_PCM_FORMAT_U8,8位
        ret = snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_S16_LE);
        if (ret < 0) {
            perror("snd_pcm_hw_params_set_format");
            exit(1);
        }
        //6. 设置采样率,如果硬件不支持我们设置的采样率,将使用最接近的
        //val = 44100,有些录音采样频率固定为8KHz
    
    
        val = 16000;
        ret = snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &val, &dir);
        if (ret < 0) {
            perror("snd_pcm_hw_params_set_rate_near");
            exit(1);
        }
        //7. 设置通道数量  1
        ret = snd_pcm_hw_params_set_channels(playback_handle, hw_params, 1);
        if (ret < 0) {
            perror("snd_pcm_hw_params_set_channels");
            exit(1);
        }
    
        /* Set period size to 32 frames. */
        frames = 32;
        periodsize = frames ;
        ret = snd_pcm_hw_params_set_buffer_size_near(playback_handle, hw_params, &periodsize);
        if (ret < 0)
        {
             printf("Unable to set buffer size %li : %s
    ", frames * 2, snd_strerror(ret));
    
        }
        periodsize /= 2;
    
        ret = snd_pcm_hw_params_set_period_size_near(playback_handle, hw_params, &periodsize, 0);
        if (ret < 0)
        {
            printf("Unable to set period size %li : %s
    ", periodsize,  snd_strerror(ret));
        }
    
        //8. 设置hw_params
        ret = snd_pcm_hw_params(playback_handle, hw_params);
        if (ret < 0) {
            perror("snd_pcm_hw_params");
            exit(1);
        }
    
         /* Use a buffer large enough to hold one period */
        snd_pcm_hw_params_get_period_size(hw_params, &frames, &dir);
    
        size = frames * 2; /* 2 bytes/sample, 2 channels */
        buffer = (char *) malloc(size);
        fprintf(stderr,
                "size = %d
    ",
                size);
    
        while (1)
        {
            ret = fread(buffer, 1, size, fp);
            if(ret == 0)
            {
                  fprintf(stderr, "end of file on input
    ");
                  break;
            }
            else if (ret != size)
            {
            }
            //9. 写音频数据到PCM设备
            while(ret = snd_pcm_writei(playback_handle, buffer, frames)<0)
            {
                usleep(2000);
                if (ret == -EPIPE)
                {
                      /* EPIPE means underrun */
                      fprintf(stderr, "underrun occurred
    ");
                      //完成硬件参数设置,使设备准备好
                      snd_pcm_prepare(playback_handle);
                }
                else if (ret < 0)
                {
                      fprintf(stderr,
                          "error from writei: %s
    ",
                          snd_strerror(ret));
                }
            }
    
        }
        //10. 关闭PCM设备句柄
        snd_pcm_close(playback_handle);
    
        return 0;
    }
    
    //注意:编译的时候应该保持“gcc -o test test.c -L. -lasound”的格式,运行的时候应该保持"./test clip2.wav"这种格式。

    gcc -o test wav.c -lasound

  • 相关阅读:
    记第一场省选
    POJ 2083 Fractal 分形
    CodeForces 605A Sorting Railway Cars 思维
    FZU 1896 神奇的魔法数 dp
    FZU 1893 内存管理 模拟
    FZU 1894 志愿者选拔 单调队列
    FZU 1920 Left Mouse Button 简单搜索
    FZU 2086 餐厅点餐
    poj 2299 Ultra-QuickSort 逆序对模版题
    COMP9313 week4a MapReduce
  • 原文地址:https://www.cnblogs.com/ynxf/p/6283142.html
Copyright © 2011-2022 走看看