広告
前回はWAVEファイルからデータを抽出し波形をプロットしてグラフ化した。
今回は逆にWAVEファイルを作成してちゃんと再生できるか試してみる。
ノコギリ波の作成
下記条件でノコギリ波を作成する。
# | 構成要素 | 値 |
---|---|---|
1 | 振幅 | 15000(レンジは-15000~15000) |
2 | 振動数 | 50Hz |
3 | サンプリング周波数 | 44.1kHz |
4 | 再生時間 | 3秒 |
5 | チャンネル数 | 2(ステレオ) |
6 | 量子化精度 | 16bit |
上記ノコギリ波のサンプリング時刻 t における値 S(t) を式にすると次の通りになる。

(サンプリング周波数/振動数)はノコギリ波の傾きを表す。
ノコギリ波生成プログラム
前回のソースを流用して下記の通り作成した。
sawtooth_wav.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <unistd.h> #define WAVE_FORMAT_PCM 0x0001 /* PCM */ #define CHANNEL_STEREO 0x0002 /* ステレオ */ #define SAMPLING_PER_SEC (0x0000AC44) /* 44.1kHz */ #define SOUND_LENGTH (SAMPLING_PER_SEC * 3) /* 3sec */ #define BLOCK_SIZE 0x0004 /* 4byte */ #define DATA_SIZE (SOUND_LENGTH * BLOCK_SIZE) /* DATAサイズ */ #define AMPLITUDE 0x3A98 /* 振幅は±15000 */ #define PERIOD 0x0032 /* 50Hz */ #define BIT_PER_SAMPLE 0x0010 /* 16bit */ #define SLOPE (SAMPLING_PER_SEC/PERIOD) /* 波の傾き */ /* RIFFチャンク */ typedef struct { char chunk_id[4]; /* チャンク識別子('RIFF'固定) */ uint32_t chunk_size; /* チャンクサイズ */ char format_type[4]; /* フォーマットタイプ('WAVE'固定) */ } RIFF_chunk_t; /* fmt チャンク */ typedef struct { char chunk_id[4]; /* チャンク識別子('fmt '固定) */ uint32_t chunk_size; /* チャンクサイズ */ uint16_t format_type; /* フォーマットタイプ */ uint16_t channel; /* チャンネル数 */ uint32_t sample_per_sec; /* サンプリング周波数 */ uint32_t byte_per_sec; /* 1秒あたりバイト数 */ uint16_t block_size; /* ブロックサイズ */ uint16_t bit_per_sample; /* 量子化精度 */ } fmt_chunk_t; /* dataチャンク */ typedef struct { char chunk_id[4]; /* チャンク識別子('data')固定 */ uint32_t chunk_size; /* チャンクサイズ(データ長) */ uint8_t dat[0]; /* データ(可変長) */ } data_chunk_t; typedef struct { RIFF_chunk_t riff; fmt_chunk_t fmt; data_chunk_t data; } wave_format_t; typedef struct { int16_t left; int16_t right; } wave_stereo_t; int main(int argc, char*argv[]) { if (argc != 2) { fprintf(stderr, "usage:%s <output file>\n", argv[0]); goto error_end; } FILE* fp = fopen(argv[1], "wb+"); if (NULL == fp) { perror("fopen"); goto error_end; } wave_format_t* wave = (wave_format_t* )malloc(sizeof(*wave) + DATA_SIZE); if (NULL == wave) { perror("malloc"); goto error_close_end; } /* RIFF */ memcpy(wave->riff.chunk_id, "RIFF", sizeof(wave->riff.chunk_id)); wave->riff.chunk_size = sizeof(*wave)+DATA_SIZE; memcpy(wave->riff.format_type, "WAVE", sizeof(wave->riff.format_type)); /* fmt */ memcpy(wave->fmt.chunk_id, "fmt ", sizeof(wave->fmt.chunk_id)); wave->fmt.chunk_size = sizeof(fmt_chunk_t) - (sizeof(wave->fmt.chunk_id)+sizeof(wave->fmt.chunk_size)); wave->fmt.format_type = WAVE_FORMAT_PCM; wave->fmt.channel = CHANNEL_STEREO; wave->fmt.sample_per_sec = SAMPLING_PER_SEC; wave->fmt.byte_per_sec = SAMPLING_PER_SEC * BLOCK_SIZE; wave->fmt.block_size = BLOCK_SIZE; wave->fmt.bit_per_sample = BIT_PER_SAMPLE; /* data */ memcpy(wave->data.chunk_id, "data", sizeof(wave->data.chunk_id)); wave->data.chunk_size = DATA_SIZE; int t; for (t = 0; t < SOUND_LENGTH; t++) { wave_stereo_t* val = (wave_stereo_t* )&wave->data.dat[t*sizeof(wave_stereo_t)]; val->left = (t % SLOPE) * ((AMPLITUDE*2)/SLOPE) - AMPLITUDE; val->right = (t % SLOPE) * ((AMPLITUDE*2)/SLOPE) - AMPLITUDE; } if (fwrite((void*)wave, 1, sizeof(*wave)+DATA_SIZE, fp) <= 0) { perror("fwrite"); } error_close_end: fclose(fp); error_end: return 0; } |
波形表示と再生
波形表示には前回に作ったバイナリ(plotwav)とgnuplotを使う。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
[user@localhost sawtooth]$ gcc -o sawtooth_wave sawtooth_wave.c [user@localhost sawtooth]$ ./sawtooth_wave sawtooth.wav [user@localhost sawtooth]$ cd ../ [user@localhost wav]$ plot/plotwav sawtooth/sawtooth.wav > sawtooth.plt [user@localhost wav]$ gnuplot G N U P L O T Version 4.6 patchlevel 2 last modified 2013-03-14 Build System: Linux x86_64 Copyright (C) 1986-1993, 1998, 2004, 2007-2013 Thomas Williams, Colin Kelley and many others gnuplot home: http://www.gnuplot.info faq, bugs, etc: type "help FAQ" immediate help: type "help" (plot window: hit 'h') Terminal type set to 'x11' gnuplot> plot [1:10000] "sawtooth.plt" using 1:2 with lines gnuplot> |

再生してみると雑音っぽい音がでる。(下記は便宜上mp3に変換しています)
広告
広告