2010-06-06 3 views
2

이 웹 사이트를 사용하여 비트 감지 엔진을 만들려고했습니다. http://www.gamedev.net/reference/articles/article1952.aspwav 파일 및 개방형 iPhone으로 비트 감지

{ 


ALfloat energy = 0; 
ALfloat aEnergy = 0; 
ALint beats = 0; 
bool init = false; 
ALfloat Ei[42]; 
ALfloat V = 0; 
ALfloat C = 0; 


ALshort *hold; 
hold = new ALshort[[myDat length]/2]; 

[myDat getBytes:hold length:[myDat length]]; 

ALuint uiNumSamples; 
uiNumSamples = [myDat length]/4; 

if(alDatal == NULL) 
    alDatal = (ALshort *) malloc(uiNumSamples*2); 
if(alDatar == NULL) 
    alDatar = (ALshort *) malloc(uiNumSamples*2); 
for (int i = 0; i < uiNumSamples; i++) 
{ 
    alDatal[i] = hold[i*2]; 
    alDatar[i] = hold[i*2+1]; 
} 
energy = 0; 
for(int start = 0; start<(22050*10); start+=512){ 
for(int i = start; i<(start+512); i++){ 
    energy+= ((alDatal[i]*alDatal[i]) + (alDatal[i]*alDatar[i])); 

} 
    aEnergy = 0; 
for(int i = 41; i>=0; i--){ 

    if(i ==0){ 
     Ei[0] = energy; 
    } 
    else { 
    Ei[i] = Ei[i-1]; 
    } 
    if(start >= 21504){ 
    aEnergy+=Ei[i]; 
    } 
} 
    aEnergy = aEnergy/43.f; 
    if (start >= 21504) { 
     for(int i = 0; i<42; i++){ 
      V += (Ei[i]-aEnergy); 
     } 
     V = V/43.f; 
     C = (-0.0025714*V)+1.5142857; 
     init = true; 
     if(energy >(C*aEnergy)) beats++; 
    } 

} 

} 

alDatal 및 alDatar는 (short *) 유형입니다.

myDat는 22050 khz 및 16 비트 스테레오로 포맷 된 wav 파일의 실제 오디오 데이터를 보유하는 NSdata입니다.

올바르게 작동하지 않는 것 같습니다. 누군가 나를 도울 수 있다면 그것은 놀라운 일이 될 것입니다. 나는 3 일 동안이 일에 매달 렸습니다.

원하는 결과는 10 초 분량의 데이터가 처리 된 후에 6을 곱할 수 있고 분당 예상 박자 수를 얻을 수 있어야합니다.

나의 현재 결과는 매 10 초마다 389 비트, 2334 BPM 내가 알고있는 노래는 약 120 BPM입니다.

+0

[+ 코드 스 니펫] + [ "올바르게 작동하지 않는 것 같습니다."] = [예상 결과를 설명하는 데 실사를하지 않았으며 3 일간의 결과가 예상과 다를 때] – HostileFork

+0

죄송합니다. 원래 질문을 업데이트했습니다. – Dmacpro

답변

7

그 코드는 추악한 막대기로 정말로 치장되었습니다. 만약 당신이 다른 사람들에게 당신을 위해 당신의 버그를 찾도록 요청한다면, 먼저 그것을 보여줄 수있는 좋은 아이디어입니다. 이상하게도, 이것은 종종 자신을 위해 그들을 찾을 수 있도록 도울 것입니다. 내가 더 근본적인 몇 가지 오류를 지적하기 전에

그래서, 나는 몇 schoolmarmly 제안을해야 :

  1. magic numbers으로 코드를 뿌려하지 마십시오. const ALuint SAMPLE_RATE = 22050과 같은 몇 줄을 입력하는 것이 정말 어려운가요? 나를 믿어 라. 삶을 더운다. 많이.

  2. 쉽게 섞이지 않을 변수 이름을 사용하십시오. 귀하의 버그 중 하나는 alDataralDatal으로 대체 한 것입니다. 그것들은 leftright이라면 아마도 일어나지 않았을 것입니다. 마찬가지로 의미가있는 변수 이름을 가진 점은 무엇입니까? energy과 같이 의미가 있지만 다소 동일하게 붙이면됩니다. aEnergy? 왜 average 같은 유익한 정보가 없습니까?

  3. 변수를 사용할 곳과 적절한 범위에서 변수를 선언하십시오. 또 다른 버그는 평균 창을 이동할 때 계산 된 에너지 합계를 재설정하지 않기 때문에 에너지가 더해질뿐입니다. 하지만 그 루프 밖에서 에너지가 필요하지 않다면, 안에을 선언하면 문제가 발생할 수 없습니다.

다른 것들은 제가 개인적으로 임의의 버팀대 및 들여 쓰기, 그리고 C 및 C++ 할당의 혼합, 헝가리에 접두어 이상한 일관성이 조각처럼, 조금 귀찮은를 찾을 수 있지만, 그 중 적어도 일부가 될 수있다 더 맛의 문제 그래서 나는 가지 않을 것이다.어쨌든

, 여기에 코드가 작동하지 않는 이유를 몇 가지 이유가 있습니다 : 각의 제곱을 원하는

energy+= ((alDatal[i]*alDatal[i]) + (alDatal[i]*alDatar[i])); 

:

첫번째로는,이 라인의 오른쪽에 보면 채널 값이므로 실제로 말해야합니다.

energy+= ((alDatal[i]*alDatal[i]) + (alDatar[i]*alDatar[i])); 

차이점이 있습니까? 그 이름들로 쉽지 않은가?

둘째, 샘플의 각 창에서 총 에너지를 계산해야하지만 바깥 쪽 루프 바깥에만 energy = 0을 설정해야합니다. 따라서 합계가 누적되어 결과적으로 현재 창 에너지는 이고 항상이 가장 큰 것입니다.

셋째, 분산 계산이 잘못되었습니다. 당신은이 :

V += (Ei[i]-aEnergy); 

하지만 그것은 제곱의 합 평균의 차이해야한다 :

V += (Ei[i] - aEnergy) * (Ei[i] - aEnergy); 

가 아니라 다른 오류가있을 수 있습니다. 예를 들어, 데이터 버퍼가 NULL이 아닌 경우 데이터 버퍼를 할당하지는 않지만, 방금 계산 한 데이터 버퍼가 올바른 길이라고 가정합니다. 코드 전반에 걸쳐 일관성있는 사용법을 적용 할 수는 있지만, 여기서 볼 수있는 관점에서 볼 때 매우 나쁜 생각처럼 보일 수 있습니다.

+0

부끄러움 그는 이것을 인정하지 않았다. –