毎度いかおです
前回-周波数440Hzの正弦波をサンプリングレート48Kで作ってみる(考察編)-で考えたことを実行してみます。
データ的にサイン波になったよ〜パチパチ
ではつまらんので実際にWAVを作ります
その前に前回の考察の誤りについて
サンプル取得のステップ幅 = 1回転の長さ / 360
は間違いですね。1つのサンプルでどれだけ角度が変わるかですし、1回転の長さってのも変で、"1回転分のサンプル数"っていうのが正しいですね。
サンプル取得のステップ幅 = 360 / 1回転分のサンプル数
でWAVの作り方はgoogle先生に"wav フォーマット 解析"と聞くと答えて下さります。
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
static const double PI = 3.1415926535f;
static const double Volume = 2048.0f;
static const double SampleRate = 48000.0f;
static const double Heltz = 440.0f;
static const double DegBase = 360.0f;
static const int SampleSec = 5;
static double SampleWidth;
typedef struct {
char header[4];
uint32_t fileLength;
char fmtHead[4];
} FileHeader;
typedef struct {
char chunkID[4];
uint32_t chunkSize;
uint16_t formatCode;
uint16_t channels;
uint32_t sampleRatio;
uint32_t sampleBytePerSeccond;
uint16_t alignment;
uint16_t bitDepth;
} FormatChunk;
typedef struct {
char chunkID[4];
int32_t chunkSize;
} DataChunk;
int main(int argc, char **argv){
FILE *fp = NULL;
double deg = 0.0f;
size_t asize;
short *sample = NULL;
long i;
size_t sumSize = 0;
FileHeader fileHeader;
FormatChunk formatChunk;
DataChunk dataChunk;
fileHeader.fileLength = (sizeof(FileHeader) + sizeof(FormatChunk) +
sizeof(DataChunk) + sizeof(short) * (int)SampleRate * SampleSec) - 8;
memcpy(fileHeader.header, "RIFF", 4);
memcpy(fileHeader.fmtHead, "WAVE", 4);
memcpy(formatChunk.chunkID, "fmt ", 4);
formatChunk.chunkSize = 16;
formatChunk.formatCode = 1;
formatChunk.channels = 1;
formatChunk.sampleRatio = (unsigned long)SampleRate;
formatChunk.sampleBytePerSeccond = (unsigned long)SampleRate * 2;
formatChunk.alignment = 2;
formatChunk.bitDepth = 16;
if(argc < 2){
printf("Argument 1 must be output wav name\n");
return -2;
}
fp = fopen(argv[1], "wb");
if(fp == NULL){
printf("file:%s open error\n", argv[1]);
return -3;
}
sample = (short *)malloc(sizeof(short) * SampleRate * SampleSec);
if(sample == NULL){
fclose(fp);
printf("Allocation error(%lu)\n", sizeof(short) * (int)SampleRate * SampleSec);
return -4;
}
// 今回訂正した部分
SampleWidth = DegBase / (SampleRate / Heltz);
memcpy(dataChunk.chunkID, "data", 4);
dataChunk.chunkSize = sizeof(short) * SampleRate * SampleSec;
for(i=0;i < SampleRate * SampleSec;i++){
// 結果が-Volume から Volume までの値のためVolume分プラスに寄せます
sample[i] = (short)(round(Volume * sin(deg * PI / 180)) + Volume);
deg = deg + SampleWidth;
}
fwrite((char *)&fileHeader, 1, sizeof(FileHeader), fp);
fwrite((char *)&formatChunk, 1, sizeof(FormatChunk), fp);
fwrite((char *)&dataChunk, 1, sizeof(DataChunk), fp);
fwrite((char *)sample, 1, sizeof(short) * (int)SampleRate * SampleSec, fp);
free(sample);
fclose(fp);
return 0;
}
それから、ボリュームですが128では小さい(これでも小さいが・・)ので2048にしてます。
できたのが、これです
おお、ラの音じゃん。