linux dsp 播放音频文件

#include <unistd.h>

#include <fcntl.h>

#include <sys/types.h>

#include <sys/ioctl.h>

#include <stdlib.h>

#include <stdio.h>

#include <linux/soundcard.h>

/* 下面的三个参数是跟具体文件相关

 * cmd: file 音频文件

 * [file pass.wav] =>> pass.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, mono 44100 Hz

 *  1. 16位

 *  2. mono为当声道=1, Stereo为立体声=2

 *  3. 44100HZ为频率这个大家都知道,及一秒钟采集或者播放音频的bit数量。

 */

#define RATE 44100

#define SIZE 16

#define CHANNELS 1  // 1表示单声道,2为立体/* 缓冲区 */

unsigned char buff[RATE * SIZE * CHANNELS / 8]; //buff里面正好放一秒钟的音频



int main()

{

    int fd;

    int wavfd; /* wav文件的描述符 */

    int arg;   /* ioctl参数 */

    int ret;   /* 返回值 */

    /* 打开dsp音频设备 */

    fd = open("/dev/dsp", O_WRONLY);

    if (fd < 0) {

        printf("open of /dev/dsp failed");

        exit(1);

    }

    wavfd = open("pass.wav",O_RDONLY);

    if (wavfd < 0) {

        printf("open of wav failed");

        close(fd);

        exit(1);

    }



    /* 设置bit */

    arg = SIZE;

    ret = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);

    if (ret == -1)

         perror("SOUND_PCM_WRITE_BITS ioctl failed");

    if (arg != SIZE)

         perror("unable to set sample size");



    /* 设置channels */

    arg = CHANNELS;

    ret = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg);

    if (ret == -1)

        perror("SOUND_PCM_WRITE_CHANNELS ioctl failed");

    if (arg != CHANNELS)

        perror("unable to set number of channels");



    /* 设置rate */

    arg = RATE;

    ret = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg);

    if (ret == -1)

        perror("SOUND_PCM_WRITE_WRITE ioctl failed");



    /* 从wav文件中读buff大小的内容,然后写入/dev/dsp中,直到文件结束 */

  /* Q:这里我试验时播放了两次,不知道啥情况,如果大家也遇到了请指教。*/

    while ((ret = read(wavfd, buff, sizeof(buff))) > 0) {

        //printf("read size = %d\n", ret);

        write(fd, buff, sizeof(buff));

        /* 下面的代码用于在更改播放文件的参数时,播放掉缓冲区内的内容 */

        ret = ioctl(fd, SOUND_PCM_SYNC, 0);

        if (ret == -1)

            perror("SOUND_PCM_SYNC ioctl failed");

    }



    close(fd);

    close(wavfd);

}





下面是封装的接口可以直接拿过来使用:



void play_audio(int rate, int bits, int channels, char *filename)

{

    int fd;

    int wavfd; /* wav文件的描述符 */

    int arg;   /* ioctl arg */

    int ret;   /* return value */



    unsigned char buff[rate * bits * channels / 8]; //buff里面正好放一秒钟的音频

    /* open device */

    fd = open("/dev/dsp", O_WRONLY);

    if (fd < 0) {

        printf("open of /dev/dsp failed");

        exit(1);

    }

    wavfd = open(filename, O_RDONLY);

    if (wavfd < 0) {

        printf("open of wav failed");

        close(fd);

        exit(1);

    }



    /* set bits */

    arg = bits;

    ret = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);

    if (ret == -1)

         perror("SOUND_PCM_WRITE_BITS ioctl failed");

    if (arg != SIZE)

         perror("unable to set sample size");



    /* set channels */

    arg = channels;

    ret = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg);

    if (ret == -1)

        perror("SOUND_PCM_WRITE_CHANNELS ioctl failed");

    if (arg != CHANNELS)

        perror("unable to set number of channels");



    /* set rate */

    arg = rate;

    ret = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg);

    if (ret == -1)

        perror("SOUND_PCM_WRITE_WRITE ioctl failed");



    /* 从wav文件中读buff大小的内容,然后写入/dev/dsp中,直到文件结束 */

    while ((ret = read(wavfd, buff, sizeof(buff))) > 0) {

        printf("read size = %d\n", ret);

        write(fd, buff, sizeof(buff));

        /* 下面的代码用于在更改播放文件的参数时,播放掉缓冲区内的内容 */

        ret = ioctl(fd, SOUND_PCM_SYNC, 0);

        if (ret == -1)

            perror("SOUND_PCM_SYNC ioctl failed");

    }



    close(fd);

    close(wavfd);

}

 

你可能感兴趣的:(linux)