2012-03-06 3 views
3

비슷한 것을해야하기 때문에이 example about sound generation on iOS을보고 있습니다.하지만 이해할 수없는 부분이있어서 누군가가 저를 도울 수 있기를 바랬습니다. 코드의이 부분에서 iOS 톤 생성

:

double theta_increment = 2.0 * M_PI * viewController->frequency/viewController->sampleRate; 
    // Generate the samples 
    for (UInt32 frame = 0; frame < inNumberFrames; frame++) 
    { 
     buffer[frame] = sin(theta) * amplitude; 

     theta += theta_increment; 
     if (theta > 2.0 * M_PI) 
     { 
      theta -= 2.0 * M_PI; 
     } 
    } 

난 정말 theta += theta_increment; 일부가 무엇인지 이해하지 않습니다. 나에게 그것은 for 루프 안에서 다음과 같은 것을하는 것이 더 합리적이다 :

buffer[frame] = sin(theta_increment * frame); 

그 이유는 알 수 없다. 또한, 코드의이 부분이 무엇인지 전혀 알지 못합니다 : if (theta > 2.0 * M_PI) 그래서 그것에 대한 설명도 매우 환영받을 것입니다.

답변

1

귀하의 접근 방식은 동일한 결과를 생성하는 데 사용될 수 있습니다. 다르게 표현됩니다. 그러나 theta += theta_increment;은 제안한 것보다 더 간단한 표현식입니다.

단계의 도메인은 sin' 논리 매개 변수 도메인으로 래핑됩니다. 이 단계는 짧은 샘플에는 실제로 필요하지 않습니다. 부동 소수점 저장 용량의 한계로 인해 생성되는 샘플의 수와 float 또는 double을 사용하는지 여부에 따라 값이 랩핑되지 않으면 결과적으로 주파수가 달라질 수 있으며 궁극적으로 값이 래핑되지 않습니다. 이를 다음과 같이 생각하십시오. 포지티브 부동 소수점 수 (위상 누산기 값)가 있고 0.000004을 추가하려고하면 어떻게 될까요? 부동 소수점 오류는 float 또는 double에 맞도록 반올림하며 오류는 단계적으로 발생하고 궁극적으로 피치가 불안정 해집니다. 짧은 샘플 (예를 들어, 몇몇 사이클)의 경우, 랩은이 경우에는 필요하지 않지만, 많은 많은 사이클에 대해, 피치 및 위상 누산기를 시간이 지남에 따라 안정화시키는 역할을한다.

마지막으로 theta는 위상 램프의 마지막 값을 저장하는 데 사용되어 다음 렌더링 호출에서 중단 된 생성을 다시 시작합니다. 이것이 없다면 렌더링 호출 경계에서 출력이 0에서 다시 시작되어 매우 불쾌한 잡음과 잘못된 주파수를 생성합니다.

모든 것이 고려되었습니다 : 그것은 단순한 데모와 그 맥락에서 사인을 생성하는 빠른 방법 이었기 때문에 가능했을 것입니다. 귀하의 접근 방식은 '비용이 많이 드는'전환이 있지만 지점이 없으므로 원래의 것보다 빠를 수 있으며 높은 주파수의 경우 더욱 빨라질 수 있습니다.

1

는 나는 당신의 방법을 세부적으로 그냥 작동 것이다 (하지만 진폭에 의해 번식하는 것을 잊지 마세요) 상상 : 같은 수학을 표현

buffer[frame] = sin(theta_increment * frame) * amplitude; 

그냥 두 가지 방법. 원본 코드를 작성한 사람이 0 < = theta < 2pi를 유지하려고했으나 sin() 호출이 이상한 경우가 아니라면 이것이 필요하지 않을 수 있습니다. 또한, 다른 일부 루프에서 동일한 스 니펫이 표시 될 경우 프레임 변수와 독립적으로 "수학"부분을 유지하려고 할 수도 있지만 이는 추측 일뿐입니다.