2012-01-01 2 views
0

iphone 오디오 입력에서 버퍼 데이터를 읽습니다. 나는 잠복기가 있고 50ms 변경의 해결책의 밑에 간다. 여기 오디오 입력 대기 시간

가 나는 낮은 것으로 대기 시간을 설정하는 방법을 알 필요가 오디오 데이터 - 버퍼 얻기 위해 전화를 내 수업, 그것은 어떻게 든 버퍼 크기를 변경함으로써 가능하다 또는 내가는 remoteIO
에 필요 그렇게 . 덕분에 많은 : 적절한 작은 값을 설정과 함께, 녹음 RemoteIO 오디오 장치를 사용

#import "SoundSensor.h" 

@interface SoundSensor (Private) 

- (void)updateLevels; 
- (void)setupQueue; 
- (void)setupFormat; 
- (void)setupBuffers; 
- (void)setupMetering; 

@end 


static SoundSensor *sharedListener = nil; 

static void listeningCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime, UInt32 inNumberPacketsDescriptions, const AudioStreamPacketDescription *inPacketDescs) 
{ 
    NSLog(@"listeningCallback "); 
    SoundSensor *listener = (SoundSensor *)inUserData; 
    if ([listener isListening]) 
     AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL); 

} 

@implementation SoundSensor 





+ (SoundSensor *)sharedListener { 
    @synchronized(self) { 
     if (sharedListener == nil) 
      [[self alloc] init]; 
    } 
    NSLog(@"sharedListener "); 
    return sharedListener; 
} 

- (void)dealloc { 
    [sharedListener stop]; 
    [super dealloc]; 
} 

#pragma mark - 
#pragma mark Listening 






- (void)listen { 
    NSLog(@"listen"); 
    if (queue == nil) 
     [self setupQueue]; 
    AudioQueueStart(queue, NULL); 
} 

- (void)pause { 
    NSLog(@"pause "); 
    if (![self isListening]) 

     return; 

    AudioQueueStop(queue, true); 
} 

- (void)stop { 
    NSLog(@"stop "); 
    if (queue == nil) 
     return; 

    AudioQueueDispose(queue, true); 
    queue = nil; 
} 

- (BOOL)isListening { 
    if (queue == nil) 
     return NO; 

    UInt32 isListening, ioDataSize = sizeof(UInt32); 
    OSStatus result = AudioQueueGetProperty(queue, kAudioQueueProperty_IsRunning, &isListening, &ioDataSize); 
    return (result != noErr) ? NO : isListening; 
} 

#pragma mark - 
#pragma mark Levels getters 

- (Float32)averagePower { 
    if (![self isListening]) 
     return 0.0; 
    float tmp = [self levels][0].mAveragePower; 
    tmp = tmp * 100;  
    return tmp; 
} 

- (Float32)peakPower { 
    if (![self isListening]) 
     return 0.0; 

    return [self levels][0].mPeakPower; 
} 

- (AudioQueueLevelMeterState *)levels { 
    if (![self isListening]) 
     return nil; 

    [self updateLevels]; 
    return levels; 
} 

- (void)updateLevels { 
    UInt32 ioDataSize = format.mChannelsPerFrame * sizeof(AudioQueueLevelMeterState); 
    AudioQueueGetProperty(queue, (AudioQueuePropertyID)kAudioQueueProperty_CurrentLevelMeter, levels, &ioDataSize); 
} 

#pragma mark - 
#pragma mark Setup 

- (void)setupQueue { 
    NSLog(@"setupQueue"); 
    if (queue) 
     return; 

    [self setupFormat]; 
    [self setupBuffers]; 
    AudioQueueNewInput(&format, listeningCallback, self, NULL, NULL, 0, &queue); 
    [self setupMetering]; 
} 

- (void)setupFormat { 
    NSLog(@"setupFormat "); 
#if TARGET_IPHONE_SIMULATOR 
    format.mSampleRate = 44100.0; 
#else 
    UInt32 ioDataSize = sizeof(sampleRate); 
    AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, &ioDataSize, &sampleRate); 
    format.mSampleRate = sampleRate; 
#endif 
    format.mFormatID = kAudioFormatLinearPCM; 
    format.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; 
    format.mFramesPerPacket = format.mChannelsPerFrame = 1; 
    format.mBitsPerChannel = 16; 
    format.mBytesPerPacket = format.mBytesPerFrame = 2; 
} 

- (void)setupBuffers { 
    NSLog(@"setupBuffers "); 
    AudioQueueBufferRef buffers[3]; 
    for (NSInteger i = 0; i < 3; ++i) { 
     AudioQueueAllocateBuffer(queue, 735, &buffers[i]); 
     AudioQueueEnqueueBuffer(queue, buffers[i], 0, NULL); 
    } 
} 

- (void)setupMetering { 
    NSLog(@"setupMetering"); 
    levels = (AudioQueueLevelMeterState *)calloc(sizeof(AudioQueueLevelMeterState), format.mChannelsPerFrame); 
    UInt32 trueValue = true; 
    AudioQueueSetProperty(queue, kAudioQueueProperty_EnableLevelMetering, &trueValue, sizeof(UInt32)); 
} 

#pragma mark - 
#pragma mark Singleton Pattern 

+ (id)allocWithZone:(NSZone *)zone { 
    NSLog(@"allocWithZone"); 
    @synchronized(self) { 
     if (sharedListener == nil) { 
      sharedListener = [super allocWithZone:zone]; 
      return sharedListener; 
     } 
    } 

    return nil; 
} 

- (id)copyWithZone:(NSZone *)zone { 
    NSLog(@"copyWithZone"); 
    return self; 
} 

- (id)init { 
    if ([super init] == nil) 
     return nil; 

    return self; 
} 

- (id)retain { 
    return self; 
} 

- (unsigned)retainCount { 
    return UINT_MAX; 
} 

- (void)release { 
    // Do nothing. 
} 

- (id)autorelease { 
    return self; 
} 

@end 
+2

당신의'setupBuffers' 메소드는 깨졌습니다; 나중에 사용하기 위해 시스템 API에 스택 할당 버퍼에 대한 참조를 전달 중입니다 ... – bbum

답변

0

가 kAudioSessionProperty_PreferredHardwareIOBufferDuration 오디오 세션 속성 (5.8 밀리 초를보십시오)는 오디오를 사용하는 것보다 훨씬 낮은 대기 시간을 제공 할 것 녹음을위한 대기열 API. RemoteIO 오디오 장치를 입력으로 사용하는 경우, 어떤 형식의 DSP 엔벨로프 추적 코드를 사용하여 원시 PCM 샘플로부터 자신의 레벨 미터링 값을 계산해야합니다. RemoteIO에 직접 제공하는 내장 API는 없습니다.

kAudioQueueProperty_CurrentLevelMeter를 사용하면 낮은 지연 시간을 위해 설계되거나 구성되지 않은 것처럼 보입니다.