'화니 프로젝트/Air Drum for VSTi'에 해당되는 글 8건
- 2008.10.06 완성 결과물~
- 2008.10.06 적외선 센서 전압
- 2008.10.06 가상드럼 페달~
- 2008.10.06 Hi - Hat에 대한 고찰..
- 2008.10.06 위모트 좌표값의 한계??
- 2008.10.06 소프트웨어적인 동시음 처리방법
- 2008.10.03 파일쓰기중 0A입력시 실제파일에 0D 0A입력 현상 2
- 2008.10.03 char → wchar, wchar → char
개발도구 :
애초에 생각했던 작품에 한 70%밖에 안 미친~안타까운 작품~ 교훈은 하나~ 미리미리 영어공부합시다!!!
또 욕을 했죠. 해외연수간 팀원을...ㅡㅡ;;;;;
전압을 재어보니까 1볼트도 안됩니다..헐...알아보니 전압이 너무 낮다고 하더군요.
다행히 가변저항을 달아서 납땜하는 일은 안 벌어졌습니다..휴우~~
1.3정도까지 전압을 올리니 왠만한 각도에서도 위모트에서 적외선을 잡아냅니다.
하드웨어하는 후배의 말로는 5볼트가까이도 써봤다고 하던데. 이론적으로는 탈 가능성이 높다고 하네요.
사상 최소경비 페달 완성..
펀치 2000원짜리...발판 승욱이 마우스패드 뺏어서 반 짜르고..ㅡㅇㅡㅋㅋㅋ
한번씩 프레임에 돈 다 때려박고!! 껍대기로 승부하는 사람들 보면 참~~안타깝습니다.
위험성 발언인가..ㅡㅁㅡ;;;;;;;;
우리가 만들고 있는 가상드럼에서도 Hi - Hat이 있습니다.
근데 GM 타악기 테이블( 9번채널 )을 보니 Open Hi hat, Close Hi hat, Pedal Hi hat외에
다른 심볼에도 Open, Close가 붙은게 보이더군요..
이게머지..ㅡㅡ;;;; 첨에 어떤 걸 선택할지 몰랐는데 의미가 대충 이렇더군요.
Hi - hat 은 심볼인데 페달과 서로 관련이 있습니다. Hi - Hat의 페달을 밟으면 그냥 '틱'
하면서 Hi - hat의 위쪽 부분과 아랫쪽 부분이 부딧치는 소리가 납니다 '챙~~' 하는 소리가 아니구요~
이것이 Pedal Hi hat입니다.
그리고 Close Hi hat은 페달을 밟은 상태에서 스틱으로 심볼을 때리는 소리입니다. Pedal Hi hat소리처럼
'틱'하는 소리가 나는데 조금은 다른거 같더군요..
Open Hi hat은 밟지 않은 상태에서 스틱으로 쳐서 내는 소리입니다. 일반적으로 생각하는 심볼처럼
'챙~~'하는 소리가 나죠~
참~ 세상에 모르는게 너무 많네요...ㅎㅎ 그냥 상식으로 적어봤습니다.
제가 알고 있기로 위모트는 최대 4개의 좌표값을 잡을 수 있다고 합니다.
근데..희안한거는 첫번째 좌표값이 받고 두번째 좌표값을 잡고 있는 상태가 계속되면 현재 좌표값이
몇번 좌표값인지 그 인덱스값을 파악할 수 있지만 만일 첫번째 좌표값을 잠깐 잃게 된다면 두번째였던 좌표값이
첫번째 좌표값으로 바뀌게 됩니다. 머..하드웨어 입장에서 보면 당연할 수 있지만 그걸 이용해서 프로그램을
만드는 입장에서 문제가 생길 수 있더군요. 스틱에 진동센서를 두어 가상으로 드럼을 쳤을 때 진동이 오게끔
했습니다. 지그비를 썻죠...
근데 지그비 프로토콜을 각 스틱마다 따로 줬기 때문에 위에서 처럼 위모트에서 좌표값의 인덱스가 두번째였다가
첫번째로 바뀌게 되면 엉뚱한 스틱에 진동이 오게 되는 문제점이 발생했습니다..
역시나~~하드웨어와 소프트웨어중 어느쪽을 고칠지 고민중에 하드웨어 한 팀원이 해외연수를..ㅡㅡ 두둥!!!!!
하는 수 없이 어떻게 소프트웨어적으로 해야 했죠..ㅎㅎ
좌표값을 이용하는 것입니다. 일단 환경적 조건을 주었습니다. 스틱1,2이 두어 쥐어야 하는 손이 결정되어 있는 거
죠.....어처구니없는 경우가..ㅜㅁㅜ
그리고 두개의 스틱이 크로스 되면 좌표X값의 크기가 서로 바뀌기 때문에 진동정보을 전달하기 위한 정보 또한
바꾸어 주었습니다. 일단 크로스 문제가 해결되니 좌표값 하나가 사라졌다 나왔다해도 문제 없이 진동이
전달 되었습니다. 근데 이것들이 서로 물고 또 물어져서 결국에는 완벽하게 구현할려면 하드웨어적으로 스틱의
위치가 서로 바뀌어도 관계없도록 만들어야지 완벽한 사용이 가능했습니다..
마지막으로 걸리는 문제는
하나의 스틱만 있는데 2번스틱을 사용하면 진동은 1번 스틱으로 오는 거였죠. 결국 하드웨어적인 문제...
하나의 좌표값으로는 소프트웨어적으로 도저히 알 수 있는 방법이 없습니다..위모트는 순수한 좌표값만
던져주니까요..
허무하네요..ㅎㅎ 소프트웨어 코딩하는 입장에서 이런 문제로 고민을 하니...^^
그래도 재밌는 노다가 였습니다.
flag값 만들고 나니 생각보다 깔끔해서 올려 봅니다.
#define STICK_NOCROSS_CNT 1 // 일반적인 상태에서 계속 유지
#define STICK_CROSS_CHANGE_CROSS 2 // 초기크로스 상태에서 크로스됨
#define STICK_NOCROSS_CHANGE_CROSS 3 // 일반적인 상태에서 크로스 됨
#define STICK_CROSS_CNT 4 // 초기크로스 상태 계속 유지
if( g_nStickCnt == 2 )
{
// 크로스 되지 않은 상태에서 연주 시작 - 두개의 스틱좌표x값 비교
if( nLeftStickX <= nRightStickX )
{
if( g_bCurCrossFlag == false && g_bFirstFlag == false )
{
g_bCurCrossFlag = true; // 도중부터 크로스 상태임
g_bFirstFlag = true;
}
if( g_bCurCrossFlag == true ) // 일반적인 상태에서 계속 유지
{
g_nStateNum = STICK_NOCROSS_CNT;
}
else if( g_bStartCrossFlag == true ) // 초기크로스 상태에서 크로스됨
{
g_nStateNum = STICK_CROSS_CHANGE_CROSS;
}
}
else if( nLeftStickX > nRightStickX )
{ // 크로스 된 상태에서 연주 시작 - 두개의 스틱좌표x값 비교
if( g_bStartCrossFlag == false && g_bFirstFlag == false )
{
g_bStartCrossFlag = true; // 처음부터 크로스 상태임
g_bFirstFlag = true;
}
if( g_bCurCrossFlag == true ) // 일반적인 상태에서 크로스 됨
{
g_nStateNum = STICK_NOCROSS_CHANGE_CROSS;
}
else if( g_bStartCrossFlag == true ) // 초기크로스 상태 계속 유지
{
g_nStateNum = STICK_CROSS_CNT;
}
}
}
가상드럼에서 실시간으로 연주하는 악기에 대한 녹음 기능을 추가하기로 결정되었습니다.
가상드럼에서 총 입력되는 곳은 두개의 스틱과 두개의 페달입니다.
총 4개의 입력을 동시에 입력 받아 하나의 미디음으로 동기화 하기 위해서, 그리고 미디내의 트랙수도 최소 4개로 늘어나기 때문에 미디메시지의 상태메시지간의 동기화도 맞춰줘야 되고 하니 자료구조의 관리가 중요했습니다..
먼저 동시음인지를 알기 위해 하나의 버퍼를 두고 연주될 때마다 한 입력값씩 그 악기정보를 넣어줍니다.
버퍼에서 값을 뺄때는 일정한 시간을 두고 빼는거죠..그러면 동시음에 대한 소프트웨어적인 구현자체는
가능합니다..의외로 성능도 괜찮더군요..ㅎㅎ 따로 동시화문제가 생길 것도 없고...ㅎㅎ
자료구조에서는 입력되는 악기에 대한 정보를 저장하고 그에 대한 연주된 타이밍을 입력합니다.
이때 타이밍(delta time)은 동시에 연주된 음에 대해서 같은 타이밍(delta time)을 입력하는 것이 주된 과제였죠..
그러니까 타이밍(delta time)값은 결국 전에 입력된 연주정보에서 갱신되어야 미디포멧으로 맞기 때문에
동시음들이 줄줄이 저장되어 있는 경우 그 전에 따로 연주된 음을 찾아서 타이밍값(delta time)을
갱신해야 나중에 관리하기가 편합니다.
세그먼트내의 Tick값을 이용하여 현재 연주되는 악기의 타이밍값(delta time)을 계산하고..
대충 Tick값이 7.5배 큽니다..대충 이정도에서 값을 바꾸며 타이밍을 잡으시면 될듯..
아무튼 문제는 동시음에 대해서 처리인데...만일 두개의 드럼스틱과 페달에서
동시음에 대한 정보를 같이 던져준다면 별로 번거로움이 없었을 겁니다.
문제는 팀원파트에서 하드웨어적으로 제공을 해주지 않았던거죠.ㅡㅡ;;;;;;
별수없이 소프트웨어적으로 해결을...~~
미디파일 포멧을 작성하던중 계속 미디재생이 안되는 현상이 있었습니다.
내가 미디포멧자체를 잘못 넣은건가 하고 계속 원인을 분석중..이상한 것이 들어가 있더군요
0x0A를 추가하면 0x0D, 0x0A가 들어가버리는 어처구니 없는 현상이...이걸로 또 노가다를 했군요..ㅎㅎ
0x0A를 추가시키면 0x0D, 0x0A가 둘다 들어가버려서 unicode 포맷을 깨트려 그 후에 오는 모든 text가 산산조각이 난다고 합니다. 0x0D는 잘 들어간다는데..ㅡㅡㅎ
ex) 비정상 : 0D 00 0D 0A 00
정상 : 0D 00 0A 00
이걸 방지하기 위해서는 FileStream을 써야만 한다고 합니다. 아래의 소스 참조~
wchar_t wszNBuf[2048] = {0,};
wchar_t wszCR[4] = { 0x000D, 0x000A, 0x0000, 0x0000 };
WideString wszPath, wszTmp, wszBuf;
TFileStream *fsLog = NULL;
wszPath = "C:\\test.txt";
_wmemset( wszNBuf, 0x00, 2048 );
//뒤에 text를 wchar_t*로 변환해야 한다..
swprintf( wszNBuf, "내용을 넣는다." );
wcscat( wszNBuf, wszCR );
//본인은 .txt파일 생성시 unicode파일을 미리 생성하고 내용을 추가 시켰다.
MakeUnicodeFile( wszPath );
try
{
fsLog = new TFileStream( wszPath, fmOpenReadWrite );
if( fsLog == NULL )
return;
}
catch( ... )
{
return;
}
//반드시 시작 부분을 잡아 주어야 덮어쓰지 않는다.
fsLog->Seek( fsLog->Size, soFromBeginning );
fsLog->WriteBuffer( wszNBuf, wcslen( wszNBuf ) * sizeof(wchar_t) );
delete fsLog;
그러나!! 두둥!!!!!!!!!!!!!!!!!
반전이 있었으니..파일을 열 때 그냥 텍스트모드로 열어서 그렇다는 정보를 입수하고!!
열기 mode 에서 binary 를 넣으니까 잘 됩니다. wt모드에서 wb모드로...해서
그냥 해결봤습니다...이럴때마다..제 자신이 부끄러워지는..ㅎㅎ
표준을 따르는 것이 프로그래머로써 당연하지만 유니코드는 일단 피하고 보자는 못된 버릇으로
찾게된 변환 코드입니다.ㅎㅎ
중요한거는 쓰고난후 따로 메모리해제를 해주어야한다는거!!!!
// <char → wchar>
wchar_t* char2wchar(const char* src)
{
ASSERT(src);
int nlen = strlen(src)+1;
wchar_t* pdst = (LPWSTR) malloc ( sizeof( wchar_t )* nlen);
mbstowcs(pdst, src, nlen);
return pdst;
}
// <wchar → char>
char* wchar2har(const wchar_t* src)
{
ASSERT(src);
int len = 0;
len = (wcslen(src) + 1)*2;
char* pdst = (char*) malloc ( sizeof( char) * len);
WideCharToMultiByte( 949, 0, src, -1, pdst, len, NULL, NULL);
return pdst;
}