搜索
bottom↓
回复: 6

DIY wav播放器又进一步,WAV文件播放实验成功。

[复制链接]

出0入0汤圆

发表于 2008-9-9 14:16:04 | 显示全部楼层 |阅读模式
今天,看了下wav文件格式,在Linux下尝试了读取wav文件数据写往声卡文件/dev/dsp,播放成功。
没想到Linux下声卡编程竟然如此简单,就是把音频数据写到/dev/dsp文件即可。

源代码如下

/* filename: wavplay.c */

#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <linux/soundcard.h>

#define BUFSIZE 512

struct RIFF_Header{
  char RIFF_ID[4];
  uint32_t RIFF_Size;
  char RIFF_Format[4];
};

struct Chunk_Header{
  char Chunk_ID[4];
  uint32_t Chunk_Size;
};

struct Wave_Format{
  uint16_t AudioFormat;
  uint16_t NumChannels;
  uint32_t SampleRate;
  uint32_t AvgBytesPerSec;
  uint16_t BlockAlign;
  uint16_t BitsPerSample;
};

int main(int argc, char *argv[])
{
  struct RIFF_Header riff_header;
  struct Chunk_Header fmt_chunk, data_chunk;
  struct Wave_Format wavfmt;

  char buf[BUFSIZE];
  FILE * fwave;
  int sndfd;       
  int status;
  int arg;
  int readbytes;
  int writebytes;
  int writed;
  
  if( argc < 2 ){
    fprintf(stderr, "Usage: wavplay <filename>\n");
    exit(-1);
  }
  
  fwave = fopen( argv[1], "r");
  if( fwave == NULL ){
    fprintf(stderr, "Can't open file %s\n", argv[1]);
    exit(-1);
  }
       
  fread(&riff_header, 1, sizeof(struct RIFF_Header), fwave);
  if( strncmp(riff_header.RIFF_ID, "RIFF", 4) || strncmp(riff_header.RIFF_Format, "WAVE",4)){
    fprintf(stderr, "Unknown file format.\n");
    exit(-1);
  }

  sndfd = open("/dev/dsp", O_RDWR);
  if (sndfd < 0) {
    perror("open of /dev/dsp failed");
    exit(-1);
  }

  fread(&fmt_chunk, 1, sizeof(struct Chunk_Header), fwave);
  if( !strncmp(fmt_chunk.Chunk_ID, "fmt ", 4) ){
    /* this is a fmt chunk */
    fread(&wavfmt, 1, sizeof(struct Wave_Format), fwave);
   
    arg = wavfmt.BitsPerSample;
    status = ioctl(sndfd, SOUND_PCM_WRITE_BITS, &arg);
    if (status == -1)
      perror("SOUND_PCM_WRITE_BITS ioctl failed");
    if (arg != wavfmt.BitsPerSample)
      perror("unable to set sample size");
   
    arg = wavfmt.NumChannels;
    status = ioctl(sndfd, SOUND_PCM_WRITE_CHANNELS, &arg);
    if (status == -1)
      perror("SOUND_PCM_WRITE_CHANNELS ioctl failed");
    if (arg != wavfmt.NumChannels)
      perror("unable to set number of channels");

    arg = wavfmt.SampleRate;
    status = ioctl(sndfd, SOUND_PCM_WRITE_RATE, &arg);
    if (status == -1)
      perror("SOUND_PCM_WRITE_WRITE ioctl failed");

    /* skip extra bytes */
    fseek(fwave, fmt_chunk.Chunk_Size - 16 + fmt_chunk.Chunk_Size%2, SEEK_CUR);
  }else{
    fprintf(stderr, "Can't find fmt chunk.\n");
    exit(-1);
  }
  
  while( fread(&data_chunk, 1, sizeof(struct Chunk_Header), fwave) != 0 )
    if( !strncmp(data_chunk.Chunk_ID, "data", 4) ){
      printf("Begin Play\n");
      /* this is a data chunk */
      writed = 0;
      while(writed < data_chunk.Chunk_Size){
        readbytes = fread(buf, 1, BUFSIZE, fwave);
        writebytes = write(sndfd, buf, readbytes);
        if( writebytes != readbytes )
          perror("wrote wrong number of bytes");
        writed += readbytes;
      }
    }else{
      /* skip unknown chunks */
      fseek(fwave, data_chunk.Chunk_Size + fmt_chunk.Chunk_Size%2, SEEK_CUR);
    }
  
  fclose(fwave);
  close(sndfd);
  
  return 0;
}


哈哈,DIY wav播放器的路又向前进了一步。

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2008-9-9 14:23:14 | 显示全部楼层
不错

出0入0汤圆

发表于 2008-9-18 17:57:08 | 显示全部楼层
以前说的,cp到snd文件就能播放了

记不清了

出0入0汤圆

 楼主| 发表于 2008-9-18 18:14:14 | 显示全部楼层
据说这样就可以播放了

#cat&nbsp;haha.wav>&nbsp;/dev/dsp

这个命令在我的一个arm9的开发板实验可以播放wav文件,但在我的PC上不行。上面的程序在PC上可以播放wav在arm9上却又报dma2的一个什么错误。



我这个实验的目的主要是想看看如何解析wav文件,以便于以后用单片机diy一个wav播放器。

出0入0汤圆

发表于 2008-11-21 15:11:54 | 显示全部楼层
正是需要的&nbsp;谢谢

出0入0汤圆

发表于 2011-3-14 14:22:24 | 显示全部楼层
用linux 的好处多多。

出0入0汤圆

发表于 2012-5-27 18:32:54 | 显示全部楼层
收藏了,谢谢楼主分享!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-20 19:15

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表