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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM