2012-05-14 2 views
1

현재 IOS에서 TCP 소켓을 통해 IMA-ADPCM 오디오 데이터를 읽고 PCM으로 변환 한 다음 스트림을 재생하는 앱을 개발 중입니다. 이 단계에서 스트림에서 데이터를 가져와 (또는 푸시에 반응해야한다고 말하는) 클래스를 완성하고이를 PCM으로 디코딩했습니다. Audio Queue 클래스를 설정하고 테스트 톤을 재생하도록했습니다. 데이터 큐를 오디오 큐에 전달하는 가장 좋은 방법은 도움이 필요한 곳입니다.Objective-C - 스트리밍 된 데이터를 오디오 큐로 전달

오디오 데이터는 청크 640 바이트에서 8Khz 16 비트 LPCM으로 ADPCM 디코더에서 출력됩니다. (160 바이트의 ADPCM 데이터로 시작하지만 640으로 압축을 푸십시오). uint_8t 배열로 함수에 들어오고 NSData 객체를 전달합니다. 스트림은 '푸시 (push)'스트림이므로 오디오가 전송 될 때마다 객체를 작성/플러시합니다.

-(NSData*)convertADPCM:(uint8_t[]) adpcmdata { 

물론 오디오 큐 콜백 각 패스에서 실행 루프의 각 패스에 대한 자료를 찾고 간다 끌어 오기 함수가 실행 :이 작업을했습니다

-(OSStatus) fillBuffer: (AudioQueueBufferRef) buffer { 

며칠 동안 PCM 변환은 상당히 과세되어 있었고 두 가지 사이에서 데이터를 연결하는 가장 좋은 방법은 내 머리 속에 모으는 데 약간의 어려움이 있습니다. 데이터를 생성하는 것과 같지 않고 데이터 작성을 필 버퍼 루틴에 간단하게 통합 할 수 있습니다. 데이터가 푸시되고 있습니다.

uint16_t [] ~에서 순환 버퍼를 0.5 초 설정했지만 뇌가 닳아서 버퍼에서 밀고 당기는 깔끔한 방법을 찾을 수 없어 결국 스냅 딱딱 소리가 튀다.

주로 Android에서 프로젝트를 완료했지만 AudioTrack은 Core-Audio Queues와 매우 다른 짐승입니다.

이 단계에서 저는 Adamson과 Avila가 Learning Core Audio를 한 권 가져 왔으며 핵심 오디오를 잘 모르는 사람들에게 훌륭한 자료라고 생각합니다.

업데이트 : 내가 말했듯이 내가 쓴 때

-(OSStatus) fillBuffer: (AudioQueueBufferRef) buffer { 

    int frame = 0; 
    double frameCount = bufferSize/self.streamFormat.mBytesPerFrame; 
    // buffersize = framecount = 8000/2 = 4000 
    //  

    // incoming buffer uint16_t[] convAudio holds 64400 bytes (big I know - 100 x 644 bytes) 
    // playedHead is set by the function to say where in the buffer the 
    // next starting point should be 

    if (playHead > 99) { 
     playHead = 0; 
    } 

    // Playstep factors playhead to get starting position 
    int playStep = playHead * 644; 

    // filling the buffer 
    for (frame = 0; frame < frameCount; ++frame) 
     // framecount = 4000 
     { 
     // pointer to buffer 
     SInt16 *data = (SInt16*)buffer->mAudioData; 
     // load data from uint16_t[] convAudio array into frame 
     (data)[frame] = convAudio[(frame + playStep)]; 
    } 

    // set buffersize 
    buffer->mAudioDataByteSize = bufferSize; 

    // return no Error - Osstatus will return an error otherwise if there is one. (I think) 
    return noErr; 
} 

, 내 뇌가 퍼지, 그리고 내가 놓친 거지 눈부시게 분명 뭔가 거기에 아마 : 여기 버퍼 관리 코드입니다. 내가 로그인 할을 덤프하고 그것을 채워 순환 방식으로 채워지고 사물의 convAudio 배열 측면에서

static void MyAQOutputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inCompleteAQBuffer) 
{ 
    soundHandler *sHandler = (__bridge soundHandler*)inUserData; 

    CheckError([sHandler fillBuffer: inCompleteAQBuffer], 
       "can't refill buffer", 
       "buffer refilled"); 
    CheckError(AudioQueueEnqueueBuffer(inAQ, 
             inCompleteAQBuffer, 
             0, 
             NULL), 
       "Couldn't enqueue buffer (refill)", 
       "buffer enqued (refill)"); 

} 

, 그래서 나는 적어도 알고 코드 위

는 콜백에 의해 호출된다 그 비트가 작동합니다.

+0

버퍼 관리 코드를 게시하십시오. 문제가있는 것으로 보입니다. – hotpaw2

+0

버퍼 코드가 추가되었습니다. – DoctorDbx

답변

0

요금 관리에서 어려운 부분과 일치하지 않는 경우 수행 할 작업. 처음에는 커다란 순환 버퍼 (수초)를 사용하고 오디오 큐를 시작하기 전에 대부분 채 웁니다. 그런 다음 버퍼 수준을 모니터링하여 자신이 겪고있는 비율 일치 문제를 확인하십시오.