Last active
May 8, 2017 13:56
-
-
Save algon-320/2ce97a41f5171fe2d8ca882dbde167d8 to your computer and use it in GitHub Desktop.
WAVファイルを書き出す (c++版)
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 <iostream> | |
#include <vector> | |
#include <string> | |
#include <cstring> | |
#include <fstream> | |
#include <cmath> | |
// 44100 Hz / 16 bit / ステレオ のリニアPCM | |
#define SAMPLING_RATE (44100) | |
#define CHANNEL (2) | |
#define BIT_PER_SAMPLE (16) | |
#define FILE_NAME "44100_16_2_lpcm.wav" | |
struct wave_header { | |
unsigned char riff[4]; | |
unsigned int file_bytes; | |
unsigned char type[4]; | |
unsigned char fmt[4]; | |
unsigned int fmt_bytes; | |
unsigned short format_id; | |
unsigned short channel; | |
unsigned int sampling; | |
unsigned int bytes_per_sec; | |
unsigned short block_size; | |
unsigned short bit_per_sample; | |
unsigned char data[4]; | |
unsigned int data_bytes; | |
wave_header(const short ch, const int sampling_rate, const short bps) { | |
memcpy(riff, "RIFF", 4); | |
file_bytes = 44 - 8; | |
memcpy(type, "WAVE", 4); | |
memcpy(fmt, "fmt ", 4); | |
fmt_bytes = 16; | |
format_id = 1; | |
channel = ch; | |
sampling = sampling_rate; | |
bytes_per_sec = sampling_rate * ch * bps / 8; | |
block_size = ch * bps; | |
bit_per_sample = bps; | |
memcpy(data, "data", 4); | |
data_bytes = 0; | |
} | |
std::vector<unsigned char> pack() { | |
std::vector<unsigned char> ret(44); | |
unsigned int pos=0; | |
memcpy(&ret[pos], riff, sizeof(riff)); pos+=sizeof(riff); | |
memcpy(&ret[pos], &file_bytes, sizeof(file_bytes)); pos+=sizeof(file_bytes); | |
memcpy(&ret[pos], type, sizeof(type)); pos+=sizeof(type); | |
memcpy(&ret[pos], fmt, sizeof(fmt)); pos+=sizeof(fmt); | |
memcpy(&ret[pos], &fmt_bytes, sizeof(fmt_bytes)); pos+=sizeof(fmt_bytes); | |
memcpy(&ret[pos], &format_id, sizeof(format_id)); pos+=sizeof(format_id); | |
memcpy(&ret[pos], &channel, sizeof(channel)); pos+=sizeof(channel); | |
memcpy(&ret[pos], &sampling, sizeof(sampling)); pos+=sizeof(sampling); | |
memcpy(&ret[pos], &bytes_per_sec, sizeof(bytes_per_sec)); pos+=sizeof(bytes_per_sec); | |
memcpy(&ret[pos], &block_size, sizeof(block_size)); pos+=sizeof(block_size); | |
memcpy(&ret[pos], &bit_per_sample, sizeof(bit_per_sample)); pos+=sizeof(bit_per_sample); | |
memcpy(&ret[pos], data, sizeof(data)); pos+=sizeof(data); | |
memcpy(&ret[pos], &data_bytes, sizeof(data_bytes)); pos+=sizeof(data_bytes); | |
return ret; | |
} | |
}; | |
class wave { | |
public: | |
wave() : wh(CHANNEL, SAMPLING_RATE, BIT_PER_SAMPLE), output_file_name(FILE_NAME) {} | |
bool output() { | |
wh.data_bytes = wave_data.size() * sizeof(signed short); | |
wh.file_bytes = 44 + wh.data_bytes - 8; | |
std::vector<unsigned char> file_bytes(wh.file_bytes + 8); | |
std::vector<unsigned char> header = wh.pack(); | |
memcpy(&file_bytes[0], &header[0], 44); | |
memcpy(&file_bytes[44], &wave_data[0], wh.data_bytes); | |
std::ofstream fout; | |
fout.open(output_file_name, std::ios::out|std::ios::binary|std::ios::trunc); | |
if (!fout) { | |
std::cout << "File opening error" << std::endl; | |
return false; | |
} | |
fout.write((char*)&file_bytes[0], sizeof(unsigned char) * file_bytes.size()); | |
fout.close(); | |
return true; | |
} | |
void gen_wav_sin_ceg() { | |
const int length = 3; // [sec] | |
wave_data = std::vector<signed short>(SAMPLING_RATE * CHANNEL * length, 0); | |
double unit_c = 261.626 / SAMPLING_RATE * 2 * acos(-1); // ド | |
double unit_e = 329.628 / SAMPLING_RATE * 2 * acos(-1); // ミ | |
double unit_g = 391.995 / SAMPLING_RATE * 2 * acos(-1); // ソ | |
for(int i=0; i<SAMPLING_RATE * length; i++) { | |
wave_data[i*CHANNEL+0] += sin(unit_c*i) * 3000; | |
wave_data[i*CHANNEL+0] += sin(unit_e*i) * 3000; | |
wave_data[i*CHANNEL+(CHANNEL==2)] += sin(unit_c*i) * 3000; | |
wave_data[i*CHANNEL+(CHANNEL==2)] += sin(unit_g*i) * 3000; | |
} | |
} | |
void gen_wav_rect_ceg() { | |
const int length = 3; // [sec] | |
wave_data = std::vector<signed short>(SAMPLING_RATE * CHANNEL * length, 0); | |
double unit_c = 261.626 / SAMPLING_RATE * 2 * acos(-1); // ド | |
double unit_e = 329.628 / SAMPLING_RATE * 2 * acos(-1); // ミ | |
double unit_g = 391.995 / SAMPLING_RATE * 2 * acos(-1); // ソ | |
for(int i=0; i<SAMPLING_RATE * length; i++) { | |
wave_data[i*CHANNEL+0] += ((sin(unit_c * i)) > 0 ? 1 : -1) * 2000; | |
wave_data[i*CHANNEL+0] += ((sin(unit_e * i)) > 0 ? 1 : -1) * 2000; | |
wave_data[i*CHANNEL+(CHANNEL==2)] += ((sin(unit_c * i)) > 0 ? 1 : -1) * 2000; | |
wave_data[i*CHANNEL+(CHANNEL==2)] += ((sin(unit_g * i)) > 0 ? 1 : -1) * 2000; | |
} | |
} | |
private: | |
wave_header wh; | |
std::vector<signed short> wave_data; | |
const std::string output_file_name; | |
}; | |
int main() { | |
wave wav; | |
// wav.gen_wav_sin_ceg(); | |
wav.gen_wav_rect_ceg(); | |
if(!wav.output()) return -1; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment