2014-04-15 2 views
0

오디오 대기열을 사용하여 PCM 파일을 재생하려면 this이 필요합니다.오디오 대기열을 사용하여 PCM 데이터 재생

#import "PlayPCM.h" 
AudioFileID audioFile; 
SInt64 inStartingPacket = 0; 
AudioQueueRef audioQueue; 

@implementation PlayPCM 


void AudioOutputCallback(
         void* inUserData, 
         AudioQueueRef outAQ, 
         AudioQueueBufferRef outBuffer) 
{ 

    AudioStreamPacketDescription* packetDescs; 

    UInt32 bytesRead; 
    UInt32 numPackets = 8000; 
    OSStatus status; 
    status = AudioFileReadPackets(audioFile, 
            false, 
            &bytesRead, 
            packetDescs, 
            inStartingPacket, 
            &numPackets, 
            outBuffer->mAudioData); 


    if(numPackets) 
    { 
     outBuffer->mAudioDataByteSize = bytesRead; 
     status = AudioQueueEnqueueBuffer(audioQueue, 
             outBuffer, 
             0, 
             packetDescs); 

     inStartingPacket += numPackets; 
    } 
    else 
    { 
     NSLog(@"number of packets = null ") ; 
     AudioQueueFreeBuffer(audioQueue, outBuffer); 
    } 

} 

-(id)init{ 
    if (self = [super init]) { 

    } 
    return self; 
} 
- (void)setupAudioFormat 
{ 

    NSLog(@"setting format"); 
    format.mFormatID = kAudioFormatLinearPCM; 
    format.mSampleRate = 44100; 
    format.mFramesPerPacket = 1; 
    format.mChannelsPerFrame = 1; 
    format.mBytesPerFrame = 2; 
    format.mBytesPerPacket = 2; 
    format.mBitsPerChannel = 16; 
    format.mFormatFlags = kLinearPCMFormatFlagIsBigEndian | 
    kLinearPCMFormatFlagIsSignedInteger | 
    kLinearPCMFormatFlagIsPacked; 
} 

- (void)startPlayback 
{ 

    int counter = 0; 
    [self setupAudioFormat]; 
    OSStatus status; 
    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@ "test1.wav"]; 
    NSLog(@"file path = %@",filePath); 
    //fUrl = [NSURL URLWithPath:@"file:///Users/Inscripts/Desktop/test1.wav"]; 
    fUrl = [NSURL fileURLWithPath:filePath]; 
    //CFURLRef fileURL = (__bridge CFURLRef)(fUrl); 
    CFURLRef fileURL = CFURLCreateWithString(NULL, (CFStringRef) filePath, NULL); 
    status = AudioFileOpenURL(fileURL, kAudioFileReadPermission, 0,&audioFile); 
    NSLog(@"file opening status = %d",(int)status); 
    if(status == 0) 
    { NSLog(@"file opened"); 
     status = AudioQueueNewOutput(&(format), 
            AudioOutputCallback, 
            (__bridge void *)(self), 
            CFRunLoopGetCurrent(), 
            kCFRunLoopCommonModes, 
            0, 
            &audioQueue); 
     NSLog(@"audio queue create status = %d",(int)status); 

     if(status == 0) 
     { 


       AudioQueueAllocateBuffer(audioQueue, 1600000, &audioQueueBuffer); 
       AudioOutputCallback((__bridge void *)(self), audioQueue, audioQueueBuffer); 
      [self performSelector:@selector(startQueue) withObject:self afterDelay:50]; 

     } 
    } 

    if(status != 0) 
    { 
     NSLog(@"failed"); 
     // labelStatus.text = @"Play failed"; 
    } 
} 

-(void)startQueue{ 
    NSLog(@"start queue called"); 
    OSStatus status = AudioQueueStart(audioQueue, NULL); 
    if(status == 0) 
    { 
     NSLog(@"ok"); 

     //  labelStatus.text = @"Playing"; 
    } 
} 

test1.wav 파일은 PCM 속도 44100 헤르츠 스테레오 샘플링, 샘플 당 16 비트를 인코딩 된 다음과 같이 코드이다. 오디오 대기열을 성공적으로 만들고 파일을 읽을 수 있지만 들리는 소리는 모두 들릴 수 있습니다. 누군가가 내게 어떤 문제가 있다고 말할 수 있습니까?

답변

0

정말 큰 엔디안 데이터인가요? WAVE 파일에는 의심의 여지가 있습니다.

당신의 형식 플래그를 참조하십시오, 그래서, 리틀 엔디안 데이터를 사용하도록 변경 : 그 실제 웨이브 형식을 읽을 것이며, 당신이 당신의 오디오에 의존하지 않기 때문에 또한 AudioFileOpenURL 사용을 고려 또는 관련 !kLinearPCMFormatFlagIsBigEndian

을 스트림 설명.

+0

내가 어떤 파일에서 데이터를 읽고 있지 않다면? 들어오는 오디오 데이터를 재생할 뿐이므로 어떤 경우 변경해야합니까? – user2955351

+0

위에서 설명한대로 littleEndian으로 변경하십시오. – Volker

+0

을 재생하기 전에 재생할 때 데이터를 사용할 수 있는지 확인하고 버퍼를 제로화하십시오. 버퍼를 제로라고 말하는 것은 무엇을 의미합니까? – user2955351

0

더 많은 오디오 대기열 버퍼를 준비한 후에는 더 이상 소리가 나지 않습니다. please refer to apple's doc

... 
/* AudioQueueAllocateBuffer(audioQueue, 1600000, &audioQueueBuffer); 
     AudioOutputCallback((__bridge void *)(self), audioQueue, audioQueueBuffer);*/ 

/* add more audio queue buffers, ex:3 */ 
int kNumberOfBuffers = 3; 
AudioQueueBufferRef audioQueueBuffer[kNumberOfBuffers]; 
for (int i = 0; i<kNumberOfBuffers; i++) { 
    AudioQueueAllocateBuffer(audioQueue, 1600000, &audioQueueBuffer[i]); 
    AudioOutputCallback((__bridge void *)(self), audioQueue, audioQueueBuffer[i]); 
} 
[self performSelector:@selector(startQueue) withObject:self afterDelay:50]; 
...