Skip to content

Instantly share code, notes, and snippets.

@nna774
Created September 6, 2012 13:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nna774/3656415 to your computer and use it in GitHub Desktop.
Save nna774/3656415 to your computer and use it in GitHub Desktop.
6さいカンファレンス01
#include <stdio.h>
#include <math.h>
/* 7 6 7 6 7 2 5 3 0 0 0 0 0 0 0 0 */
/* 0 3 5 6 7 10 12(ブルーススケール) */
/* -9 -7 -5 -4 -2 0 2 3 3 2 0 -2 -4 -5 -7 -9 */
/* 9 9 7 7 6 6 6 6 4 6 7 4 2 2 2 2 */
/* 100 -100 100 -100 50 -50 25 -25 12 -12 6 -6 3 -3 0 0 */
int main(void)
{
int i, j;
unsigned char header[44] = {0x52, 0x49, 0x46, 0x46, 0x34, 0xb1, 0x02, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x44, 0xac, 0x00, 0x00, 0x44, 0xac, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x64, 0x61, 0x74, 0x61, 0x10, 0xb1, 0x02, 0x00};
FILE* fp = fopen("out.wav", "wb");
double x = 0.0;
double y = 0.0; /* change 2 */
double z = 0.0; /* change 3 */
unsigned char buff[44100/4] = { 0 }; /* change 4 */
int p = 0; /* change 4 */
fwrite(header, 1, 44, fp);
for (i = 0; i < 16; i++)
{
int key;
scanf("%d", &key);
/* scanf 関数は、キーボードからの入力を取得する関数です。 scanf("%d", &変数名); で、int型の入力を受け取り、変数に格納します。 double型の場合は、"%lf" とします。(*) */
for (j = 0; j < 44100 / 4; j++)
/* for(j = 0; j < 44100 / 4; j++) では、1/4秒分の音声波形データを書き込みます。 44100 というのは、1秒間あたりの音声データ量[byte] だと思ってください。 44100byte 書き込むと、1秒になるわけです。*/
{
/*change 1 unsigned char a = (unsigned char)(sin(x) * 127.0 + 128.0); */
/*change 3 unsigned char a = (unsigned char)((sin(x) >= 0.0 ? 1.0 : -1.0) * 127.0 + 128.0); */
/*change 4 unsigned char a = (unsigned char)((sin(x) >= 0.0 ? 1.0 : -1.0) * 64.0 + sin(z) * 63.0 + 128.0); */
unsigned char a = ((unsigned char)((sin(x) >= 0.0 ? 1.0 : -1.0) * 64.0 + sin(z) * 63.0 + 128.0) + buff[p] * 3) / 4;
buff[p] = a;/* change 4 */
p = (p+1) % (44100 / 4);/* change 4 */
/* unsigned char a = (unsigned char)(sin(x) * 127.0 + 128.0); では、波形を生成しているわけですが、ここでみなさんが大好きな三角関数が登場します。 sin(x) で、サイン波を作り出し、 * 127.0 + 128.0 により、.wavデータの規格に沿ったデータへと補正しています。 つまり、サイン波の音が書きこまれるわけですね。 */
fwrite(&a, 1, 1, fp);
/* で、fwrite(&a, 1, 1, fp); で 今作った波形(変数aに入っている)を書き込み、x += の行で、しかるべき角速度に従って、波形 sin(x) の x を進めています。 この長い式が、ドレミファソラシドの音階の周波数ごとの角速度を計算しています。(*)(*)(*) */
/* change 2
x += 441.0 * pow(2.0, (double)key / 12.0) * 2.0 * 3.14159265358979 / 44100.0; */
x += (441.0 + sin(y) * 10.0 ) * pow(2.0, (double)key / 12.0) * 2.0 * 3.14159265358979 / 44100.0; /* change 2 */
y += 5.0 * 2.0 * 3.14159265358979 / 44100.0; /* change 2 */
z += (441.0 + sin(y) * 10.0) * pow(2.0, (double)(key + 7) / 12.0) * 2.0 * 3.14159265358979 / 44100.0; /* change 3 */
}
}
fclose(fp);
return 0;
}
/*
for (j = 0; j < 44100 / 4; j++)をfor (j = 0; j < 44100 ; j++)にしたら16秒の音楽ファイルになるの?
なりません。なぜなら、header内に 4秒のファイルであることが書かれているからです。
*/
/* はい、では、ピロピロした音では頼りないので、しっかりした音色に変更してみましょう。-- change 1
unsigned char a = (unsigned char)(sin(x) * 127.0 + 128.0);
の行を、
unsigned char a = (unsigned char)((sin(x) >= 0.0 ? 1.0 : -1.0) * 127.0 + 128.0);
と書き換えてみてください。
今までは、sin(x) でサイン波の波形の音を鳴らしていましたが、今度は矩形波です。 sin(x) >= 0.0 のとき、1.0になり、それ以外は -1.0 となります。
*/
/*
今度は、音にビブラートをかけてみましょう。3行変更してみてください。 -- change 2
*/
/*
今までは、441.0 という値(実は"ラ"の音) を中心に音を作っていたんですが、その中心音を揺るがすことで、ビブラートをかけています。 y がその揺るぎを生成させるもので、5Hz で振動させています
*/
/* -- fumieval
SuperSaw版できた
#include<stdio.h>
#include<math.h>
#define OSC 7
int main(void)
{
int i, j, k, w;
unsigned char header[44] = {0x52, 0x49, 0x46, 0x46, 0x34, 0xb1, 0x02, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x44, 0xac, 0x00, 0x00, 0x44, 0xac, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x64, 0x61, 0x74, 0x61, 0x10, 0xb1, 0x02, 0x00};
FILE* fp = fopen("out.wav", "wb");
double xs[OSC] = {0.0, 0.13, 0.07, 0.09, 0.39, 0.22, 0.15};
fwrite(header, 1, 44, fp);
for (i = 0; i < 16; i++)
{
int key;
scanf("%d", &key);
for (j = 0; j < 44100 / 4; j++)
{
w = 0;
for (k=0;k < OSC; k++)
{
w += (int)(xs[k] / (2 * 3.14159265358979) * 65536) % 65536;
xs[k] += (441.0 + (k - OSC / 2) * 5.3) * pow(2.0, (double)key / 12.0) * 2.0 * 3.14159265358979 / 44100.0;
}
unsigned char a = (unsigned char)(w / 256 / OSC);
fwrite(&a, 1, 1, fp);
}
}
fclose(fp);
return 0;
}
*/
/*
はい、次は、和音を鳴らしてみます。 主旋律の完全5度上に、パートを合成してみましょう。3行変更してください。 -- change 3
*/
/*
プログラムを眺めたら解ると思いますが、新たな変数 z を定義し、さっき作った矩形派に加算する形で sin(z) が合成されています。 今まで、 * 127.0 + 128.0 となっていましたが、2つの音を合成するので、 * 127.0 を、*64.0 と *63.0 の2つに分割しています。
*/
/*
はい、最後にラスボス、「ディレイ」を実装しちゃいましょう。 これは非常に手ごわい相手ですが、音がかなり幻想的な雰囲気になるので、挑戦しちゃいましょう!
計5行を変更してください。 -- change 4
*/
/*
あらかじめディレイ用のバッファを作成します。 unsigned char buff[44100 / 4] = {0}; により、 44100 / 4、すなわち、1/4秒間のバッファを作成し、 {0} により、全て 0 で初期化します。
*/
/*
int p = 0; は、buff を円環状にするための、位置を保持する変数です。 buff内の、p (初期は0) の部分にデータを書き込み、p を 1ずつ加え、順にデータを書き込んでいきます。 で、pが buffの終端に辿り着いたら p を 0 に戻し、また先頭からデータを書き込むようにします
*/
/*
今言った動作をしている部分が、buff[p] = a;p = (p+1) % (44100 / 4);になります。 buff[p] = a; で、本来wavファイルに出力するデータを buff にも書き込み、p = (p + 1) % (44100 / 4); で、p を 1ずつ進めています。 %演算子は、終端に辿り着いたときに 0 に戻す役割をしています。 割り算の余りを利用して、ネ!
*/
/*
で、24行目(unsigned char a〜の行)の出力波形を計算する部分で、buffに残っている、「1/4秒前に出力した波形」 を上から合成しています。 これにより、残響音の効果が得られ、ディレイとなるわけです。
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment