Created
January 1, 2016 15:36
-
-
Save munron/a330a8cfb674324ca5c1 to your computer and use it in GitHub Desktop.
ALSAライブラリを使ってC言語でwav再生
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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