ubuntu下C代码播放音频文件

播放音频文件分两种情况:

一、单纯播放音频文件推荐操作简单使用方便(sox软件、madplay库)。
sox软件播放音频

1、ubuntu安装命令

#sudo apt-get install sox                       // 工具。
#sudo apt-get install libsox-fmt-all            // 包含MP3的解码器和其他格式的解码器。

2、代码通过系统 system 播放(play是sox软件播放的命令)

#include 
#include 
int main() { 
    system("play  1.mp3"); 
    printf("播放结束了 \n");
exit:
    printf("按任意键退出 ...\n"); 
    getchar(); 
    return 0;
}

常用命令和说明推荐文档:
sox常用命令
sox-音频处理工具

madplay库(自己没有测试需要编译就搁置了,推荐网上现成的)

madplay安装及使用

二、想要控制采样率、通道等(alsa库)

安装alsa

#sudo apt-get install alsa-base, alsa-utils, alsa-source,libasound2-dev

如果上述安装不成功或者因为墙的问题可以自己去官网下载源文件编译。

alsa简单使用只能播放wav:
#include 
#include 
#include 
#include 
#include 

struct RIFF_HEADER
{
    char szRiffID[4]; // 'R','I','F','F'
    unsigned int dwRiffSize;
    char szRiffFormat[4]; // 'W','A','V','E'
};

struct WAVE_FORMAT
{
    unsigned short wFormatTag;
    unsigned short wChannels;
    unsigned int dwSamplesPerSec;
    unsigned int dwAvgBytesPerSec;
    unsigned short wBlockAlign;
    unsigned short wBitsPerSample;
};

struct FMT_BLOCK
{
    char szFmtID[4]; // 'f','m','t',' '
    unsigned int dwFmtSize;
    struct WAVE_FORMAT wavFormat;
};

struct DATA_BLOCK
{
    char szDataID[4]; // 'd','a','t','a'
    unsigned int dwDataSize;
};

// 获取音频文件的采样率、通道、采样格式、文件大小等。
void read_wav(unsigned char *wav_buf, unsigned int *fs, int *channels, int *bits_per_sample, int *wav_size, int *file_size)
{
    struct RIFF_HEADER *headblk;
    struct FMT_BLOCK *fmtblk;
    struct DATA_BLOCK *datblk;

    headblk = (struct RIFF_HEADER *)wav_buf;
    fmtblk = (struct FMT_BLOCK *)&headblk[1];
    datblk = (struct DATA_BLOCK *)&fmtblk[1];

    *file_size = headblk->dwRiffSize;

    //采样频率
    *fs = fmtblk->wavFormat.dwSamplesPerSec;

    //通道数
    *channels = fmtblk->wavFormat.wChannels;

    *wav_size = datblk->dwDataSize;
    //采样bit数 16 24
    *bits_per_sample = fmtblk->wavFormat.wBitsPerSample;
}

main(int argc, char *argv[])
{
    int err;
    snd_pcm_t *playback_handle;
    snd_pcm_hw_params_t *hw_params;

    // 打开文件
    FILE *fp = fopen("1.wav", "rb");
    if (fp == NULL)
    {
        exit(0);
    }

    unsigned int dir = 0;
    unsigned int rate;
    int channels, bits_per_sample, wav_size, file_size;
    unsigned char *wav_buf;
    struct stat stat;

    fstat(fp->_fileno, &stat);
    wav_buf = (unsigned char *)mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fp->_fileno, 0);
    read_wav(wav_buf, &rate, &channels, &bits_per_sample, &wav_size, &file_size);

    // 打开PCM
    if ((err = snd_pcm_open(&playback_handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0)
    {
        fprintf(stderr, "cannot open audio device %s (%s)\n",
                argv[1],
                snd_strerror(err));
        exit(1);
    }

    // 分配空间
    if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0)
    {
        fprintf(stderr, "cannot allocate hardware parameter structure (%s)\n",
                snd_strerror(err));
        exit(1);
    }

    // 初始化
    if ((err = snd_pcm_hw_params_any(playback_handle, hw_params)) < 0)
    {
        fprintf(stderr, "cannot initialize hardware parameter structure (%s)\n",
                snd_strerror(err));
        exit(1);
    }

    // 初始化访问权限
    if ((err = snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
    {
        fprintf(stderr, "cannot set access type (%s)\n",
                snd_strerror(err));
        exit(1);
    }

    // 初始化采样格式
    snd_pcm_format_t format;
    if (bits_per_sample == 8)
    {
        format = SND_PCM_FORMAT_U8;
    }
    if (bits_per_sample == 16)
    {
        format = SND_PCM_FORMAT_S16_LE;
    }
    if ((err = snd_pcm_hw_params_set_format(playback_handle, hw_params, format)) < 0)
    {
        fprintf(stderr, "cannot set sample format (%s)\n",
                snd_strerror(err));
        exit(1);
    }

    // 设置采样率
    if ((err = snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &rate, &dir)) < 0)
    {
        fprintf(stderr, "cannot set sample rate (%s)\n",
                snd_strerror(err));
        exit(1);
    }

    // 设置通道数量(1 单声道 2 双声道)
    if ((err = snd_pcm_hw_params_set_channels(playback_handle, hw_params, channels)) < 0)
    {
        fprintf(stderr, "cannot set channel count (%s)\n",
                snd_strerror(err));
        exit(1);
    }

    // 设置参数
    if ((err = snd_pcm_hw_params(playback_handle, hw_params)) < 0)
    {
        fprintf(stderr, "cannot set parameters (%s)\n",
                snd_strerror(err));
        exit(1);
    }

     /* Use a buffer large enough to hold one period */
    snd_pcm_uframes_t frames;
    snd_pcm_hw_params_get_period_size(hw_params, &frames, &dir);

    snd_pcm_hw_params_free(hw_params);

    if ((err = snd_pcm_prepare(playback_handle)) < 0)
    {
        fprintf(stderr, "cannot prepare audio interface for use (%s)\n",
                snd_strerror(err));
        exit(1);
    }

    fseek(fp, 100, SEEK_SET);

    char *buffer;
    int size = frames * 2 * channels;
    buffer = (char *)malloc(size);

    while (1)
    {
        int ret = fread(buffer, 1, size, fp);
        if (ret == 0)
        {
            fprintf(stderr, "end of file on input\n");
            break;
        }
        // 写入音频数据
        if ((err = snd_pcm_writei(playback_handle, buffer, frames)) != frames)
        {
            fprintf(stderr, "write to audio interface failed (%s)\n",
                    snd_strerror(err));
            exit(1);
        }
    }

    free(buffer);
    /* Stop PCM device after pending frames have been played */ 
    snd_pcm_drain(playback_handle);
    snd_pcm_close(playback_handle);
    exit(0);
}
也可以自己读取数据写入到硬件,但是太麻烦了就不研究了。

你可能感兴趣的:(ubuntu下C代码播放音频文件)