Skip to content

Instantly share code, notes, and snippets.

@munron
Created January 1, 2016 15:36
Show Gist options
  • Save munron/a330a8cfb674324ca5c1 to your computer and use it in GitHub Desktop.
Save munron/a330a8cfb674324ca5c1 to your computer and use it in GitHub Desktop.
ALSAライブラリを使ってC言語でwav再生
#include<stdio.h>
#include<stdlib.h>
#include<alsa/asoundlib.h>
/* wavファイルヘッダー解析プログラム */
/* gcc -o wav wav.c */
/* wavファイル再生 ./wav sample.wav */
/* wavファイル波形データダンプ ./wav sample.wav -dump "ダンプ先ファイル名" */
/* PCMデフォルト設定 */
#define PCM_DEVICE "default"
#define SOFT_RESAMPLE 1
#define LATENCY 50000
#define WAVE_FORMAT_ID 1
#define DEF_CHANNELS 2
#define DEF_SAMPLING_RATE 48000
#define DEF_BITPERSAMPLE 16
#define BUF_SAMPLES 1
char *dumpFileName; //ダンプ先ファイル名
int dumpFlag=0;
/* ヘッダー構造体 */
typedef struct{
char riff[4]; // RIFFヘッダ
unsigned int fileSize; // ファイルサイズ - 8
char wave[4]; // WAVEヘッダ
} wavHeader;
/* データチャンク構造体 */
typedef struct{
unsigned char fmt[4]; // fmt チャンク
int fmtSize; // fmt チャンクのバイト数
} tagChank;
/* データフォーマット構造体 */
typedef struct{
unsigned short id; // フォーマットID
unsigned short channels; // チャンネル数
unsigned int samplingRate; // サンプリングレート
unsigned int bytesPerSec; // データ速度 (Byte/sec)
unsigned short blockSize; // ブロックサイズ
unsigned short bitsPerSample; // サンプルあたりのビット数
} wavFormat;
void wavDump(char *fileName, wavFormat *wf, int dumpFlag){
FILE *fp, *dumpFp;
wavHeader header;
tagChank chank;
int i, j, dump,buffSize,n;
char *pcmBuffer = NULL, str[10] = {0};
snd_pcm_t *handle = NULL;
static snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* 符号付き16bit */
if((fp=fopen(fileName, "rb")) == NULL){
printf("ファイルが開けません");
exit -1;
}
/*ヘッダー情報の読み取り*/
fread(&header, sizeof(wavHeader), 1, fp);
header.riff[4] = '\0';
header.wave[4] = '\0';
printf("#識別子 : %s\n", header.riff);
printf("#ファイルサイズ : %d[bytes]\n", header.fileSize+8);
printf("#ファイル形式 : %s\n", header.wave);
/*チャンクの読み取り*/
fread(&chank, sizeof(chank), 1, fp);
long len = chank.fmtSize;
chank.fmt[4] = '\0';
printf("#fmt : %s\n", chank.fmt);
printf("#fmtチャンクサイズ : %ld[bytes]\n", len);
/*各種フォーマットデータの読み取り*/
fread(wf, sizeof(wavFormat), 1, fp);
printf("#format ID(PCM=1) : %d (0x%04x)\n", wf->id,wf->id);
printf("#チャンネル数 : %d (モノラル=1 ステレオ=2)\n",wf->channels);
printf("#サンプリングレート : %d[Hz]\n", wf->samplingRate);
printf("#データ速度 : %d[bytes/sec]\n", wf->bytesPerSec);
printf("#ブロックサイズ : %d[bytes]\n", wf->blockSize);
printf("#量子化ビット数 : %d[bit]\n", wf->bitsPerSample);
printf("#再生時間 : %.2f[sec]\n", (double)(header.fileSize+8)/wf->bytesPerSec);
/* 再生設定 */
buffSize = BUF_SAMPLES * (wf->bitsPerSample / 8) * wf->channels;
pcmBuffer = (char *)malloc(buffSize);
/* PCMデバイスのオープン */
snd_pcm_open(&handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0);
/* PCMパラメーターの設定 */
snd_pcm_set_params(handle, format, SND_PCM_ACCESS_RW_INTERLEAVED, wf->channels,wf->samplingRate, SOFT_RESAMPLE,LATENCY);
/* ダンプ先ファイルを開く */
if(dumpFlag == 1){
if((dumpFp = fopen(dumpFileName, "w")) == NULL){
printf("ファイルが開けません");
exit -1;
};
}
for(i = 0;i < header.fileSize;i += buffSize){
if(fread(pcmBuffer, buffSize, 1, fp) != 1)goto end;
/* PCMへの書き込み */
snd_pcm_writei(handle, (const void*)pcmBuffer, BUF_SAMPLES);
if(dumpFlag==1){
if(wf->channels == 2 && wf->bitsPerSample / 8 == 2){
sprintf(str, "%d %d\n", pcmBuffer[0]+pcmBuffer[1]*256, pcmBuffer[2]+pcmBuffer[3]*256);
fputs(str, dumpFp);
}else if(wf->channels == 2 && wf->bitsPerSample / 8 == 1){
sprintf(str, "%d %d\n", pcmBuffer[0], pcmBuffer[1]);
fputs(str, dumpFp);
}else if(wf->channels == 1 && wf->bitsPerSample / 8 == 2){
sprintf(str,"%d\n", pcmBuffer[0]+pcmBuffer[1]*256);
fputs(str, dumpFp);
}else if(wf->channels == 1 && wf->bitsPerSample / 8 == 1){
sprintf(str, "%d\n", pcmBuffer[0]);
fputs(str, dumpFp);
}
}
}
end:
snd_pcm_drain(handle);
snd_pcm_close(handle);
fclose(fp);
if(dumpFlag == 1)fclose(dumpFp);
free(pcmBuffer);
}
int main(int argc, char *argv[]){
if(argc == 4 && argv[2][0] == '-' && memcmp(&argv[2][1], "dump", 4) == 0){
dumpFlag = 1;
dumpFileName = argv[3];
}
/* 構造体の初期化 */
wavFormat wf={
WAVE_FORMAT_ID,
DEF_CHANNELS,
DEF_SAMPLING_RATE,
DEF_SAMPLING_RATE * DEF_CHANNELS * (DEF_BITPERSAMPLE/8),
(DEF_BITPERSAMPLE/8) * DEF_CHANNELS,
DEF_BITPERSAMPLE
};
wavDump(argv[1], &wf, dumpFlag);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment