2012-03-15 3 views
0

음색 렌더링에서 나는 주파수를 한 톤으로, 다른 것을 주파수/3으로 채 웁니다.kLinearPCMFormatFlagIsNonInterleaved를 지우거나 설정하지 않는 방법

코드를 실행하면 마치 버퍼가 인터리브되지 않은 것처럼 출력이 읽힌 것처럼 보입니다. 실제로 그것은 createToneUnit에서 설정됩니다. 사운드가 왼쪽 스피커에서만 재생됩니다. 두 주파수가 모두 버퍼에 기록되면 두 톤이 왼쪽 스피커에서 재생됩니다. 주파수가 버퍼에 기입되지 않을 때, 예를 들면. leftON = 0이면 재생되지 않습니다. 그래서 버퍼 작성 코드는 정상적으로 보인다.

kLinearPCMFormatFlagIsNonInterleaved 집합을 createToneUnit으로 설정해서는 안되는 것으로 의심하기 때문에 플래그를 "지우려고"시도했습니다. 나는 몇 시간 동안 문서를 읽었지만 이것을 할 수있는 방법을 찾지 못했습니다. 실험을 통해서만 앱이 시작될 때 충돌이 발생했습니다.

어떻게 kLinearPCMFormatFlagIsNonInterleaved를 지울 수 있습니까?

또는 어떻게 kLinearPCMFormatFlagIsNonInterleaved를 처음부터 설정할 수 있습니까? streamFormat.mFormatFlags를 주석 처리하면 충돌이 발생합니다.

일부 다른 설정이 인터리브 재생을 방해 할 수 있습니다. 계산 된 플래그에 따라서하지 비트 또는 다른 플래그를

streamFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat; 

과 : 귀하의 경우에는

OSStatus RenderTone(
       void *inRefCon, 
       AudioUnitRenderActionFlags *ioActionFlags, 
       const AudioTimeStamp  *inTimeStamp, 
       UInt32      inBusNumber, 
       UInt32      inNumberFrames, 
       AudioBufferList    *ioData) 
{   
    *)inRefCon; 
    float sampleRate = viewController->sampleRate; 
    float frequency = viewController->frequency; 
    // etc. 

    float theta_increment = 2.0 * M_PI * frequency /sampleRate; 

    float wave;  
    float theta2; 
    float wave2; 

    float theta_increment2 =0.3 * theta_increment; 

    const int channel = 0; 
    Float32 *buffer = (Float32 *)ioData->mBuffers[channel].mData; 

    for (UInt32 frame = 0; frame < inNumberFrames;) 
    {     
      theta += theta_increment; 
      wave = sin(theta) * playVolume; 

      theta2 += theta_increment2; 
      wave2 = sin(theta2) * playVolume; 

      buffer[frame++] = wave * leftON; // leftON = 1 or 0 
      buffer[frame++] = wave2 * rightON; // rightON = 1 or 0 

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

    // etc. 
} 


- (void)createToneUnit 
{ 
    AudioComponentDescription defaultOutputDescription; 
    defaultOutputDescription.componentType = kAudioUnitType_Output; 
    defaultOutputDescription.componentSubType = kAudioUnitSubType_RemoteIO; 
    defaultOutputDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 
    defaultOutputDescription.componentFlags = 0; 
    defaultOutputDescription.componentFlagsMask = 0; 

    // etc. 
           kAudioUnitProperty_SetRenderCallback, 
           kAudioUnitScope_Input, 
           0, 
           &input, 
           sizeof(input)); 

    const int four_bytes_per_float = 4; 
    const int eight_bits_per_byte = 8; 

    AudioStreamBasicDescription streamFormat; 
    streamFormat.mSampleRate = sampleRate; 
    streamFormat.mFormatID = kAudioFormatLinearPCM; 
    streamFormat.mFormatFlags = 
    kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsNonInterleaved; 
    streamFormat.mBytesPerPacket = four_bytes_per_float; 
    streamFormat.mFramesPerPacket = 1; 
    streamFormat.mBytesPerFrame = four_bytes_per_float;  
    streamFormat.mChannelsPerFrame = 2; // 2= stereo/
    streamFormat.mBitsPerChannel = four_bytes_per_float * eight_bits_per_byte; 
    err = AudioUnitSetProperty (toneUnit, 
           kAudioUnitProperty_StreamFormat, 
           kAudioUnitScope_Input, 
           0, 
           &streamFormat, 
           sizeof(AudioStreamBasicDescription)); 
} 

답변

1

, 당신은 단지 수행하여 플래그를 설정할 수 없습니다.
(C 비트 단위 연산자 및 그 작동 방식 찾기)

+0

질문에 100 % 답하십시오. 그 우아한 대답 중 하나입니다. 왜 나 자신이 왜 이것을 생각하지 않느냐고 묻습니다. – user1251228

관련 문제