일상_이야기

wav 분석 및 fft 활용

조규현15 2015. 1. 31. 11:45
반응형

fft를 활용하여 외부 mp3, wav 음악 data를 분석하여 스펙트럼을 만들고

일정 주파에 따라 노트(리듬게임의 건반)을 만드는 프로젝트를 진행하고 있다.

 

우선 wav 파일을 fft로 만들기 전 wav 파일 포맷을 하고 있으며

wav파일을 생성하는 작업을 공부하고 있다.

 

c언어로 개발한 뒤 차후에 js로 변환할것이다.

 

#include <stdio.h>
#include <math.h>
#include "wave.h"

#define NUM_SCALE 8
#define PI 3.1415926535897

int main( void )
{
	char *filename = "synthesis.wav";

	double baseFrequency = 220.0;
	int    scaleIndex[NUM_SCALE] = {3, 5, 7, 8, 10, 12, 14, 15};
	double freq[NUM_SCALE];

	DWORD  nSamplesPerSec = 44100; // 44.1kHz sampling
	WORD   nBitsPerSample = 8; // 16bits
	WORD   nChannels = 2; // stereo
  	double fSamplesInterval = 1.0/nSamplesPerSec;
  	double fPlayTime = 1.0;
	long   nSampleDataSize;
	BYTE  *sampleData;
  	double t;
	int    result = 0;
	long index;
		
	// 주파수에 따른 음 생성
	for( index=0; index<NUM_SCALE; index++ )
		freq[index] = baseFrequency * pow(2.0, scaleIndex[index]/12.0);

	nSampleDataSize = (long)( fPlayTime * nSamplesPerSec * nChannels * nBitsPerSample /8 );
	sampleData = (BYTE *) malloc(sizeof(BYTE) * nSampleDataSize * NUM_SCALE);

	for (index = 0; index < NUM_SCALE; index++)
		result = insertSound(freq[index], nBitsPerSample, nChannels, fSamplesInterval,
		result, nSampleDataSize, sampleData);

	result = WritePCMSamples(filename, nSamplesPerSec, nBitsPerSample, nChannels, nSampleDataSize * NUM_SCALE, sampleData);
	if( result == 0 )
		printf( "Success \n" );

	free( sampleData );

	return 0;
}

int insertSound(double freq, WORD nBitsPerSample, WORD nChannels, double fSamplesInterval, int start, long nSampleDataSize, BYTE *sampleData)
{
	double t;
	int index;

	t = 0.0;
	for (index = 0; index<nSampleDataSize; index++)
	{
		if (nBitsPerSample == 8)
		{
			BYTE left;
			int  k;
			double value = 0;
			for (k = 1; k <= 10; k++)
				value += sin((2.0*k) * PI * freq * t);
			left = sampleData[start + index] = (BYTE) (128.0 + (100.0 / (k - 1))*value + 0.5);
			if (nChannels == 2)
			{
				sampleData[start + (++index)] = left;
			}
		}
		else if (nBitsPerSample == 16)
		{
			union {
				BYTE channel[2];
				short sample;
			} value;
			BYTE leftLow, leftHigh;
			int  k;
			double tvalue = 0;
			for (k = 1; k <= 10; k++)
				tvalue += sin((2.0*k) * PI * freq * t);

			value.sample = (short) (30000 / (k - 1) * tvalue + 0.5);
			leftLow = sampleData[start + index] = value.channel[0];
			leftHigh = sampleData[start + (++index)] = value.channel[1];
			if (nChannels == 2)
			{
				sampleData[start + (++index)] = leftLow;
				sampleData[start + (++index)] = leftHigh;
			}
		}

		t += fSamplesInterval;
	}

	return start + nSampleDataSize;
}
반응형

'일상_이야기' 카테고리의 다른 글

램 오버  (0) 2015.02.05
dx11 예제를 위한 과정  (0) 2015.02.02
아마존 직구 처음부터 끝까지  (0) 2015.01.23
마이오투  (0) 2015.01.18
올해 목표!  (0) 2015.01.08