iOS AudioQueues: сбои в плавающем аудиопотоке

Регистрирую поток поплавков, исходящий от микрофона (должна быть тишина)

Я настроил аудиоочереди с размером буфера 256 поплавков.

Типичный буфер выглядит так:

Пакет 0.004791, 0.012512 0.008423,0.000122, -0.000519, -0.002991, -0.000031 0.001801, -0.000641, 0.001190, -0.003143, -0.0015870.001587, -0.015503, -0,019440, -0,01667, -0,017670, -0,018158, -0,019928 , -0.019409, -0.024017, -0.029684, -0.024719, -0.024719, -0.044128, -0.043579, -0.043152, -0.046417, -0.045380, -0,050079, -0,050262, -0.049164, -0,040710, - 0,036713, -0,051056, -0,045868, - 0.035034, -0.033722, -0.028534, -0.028534, -0.027161, -0.022186, -0.018036, -0.012207 0.004303, -0.022024, -0.000610,0.014996 0.01800526, 0.0161440,0013184 0.00900357, -0,011353, - 0.007751, -0.007660, -0.006409, -0.003357, -0.003510, -0.001038, -0.000092 0.007690.002655.007000000, 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.00000000 0.00000000 г., 0.000000 0.000000 0.000000 0.000000, 0,000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000, 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0000 0.00000000 г., 0.0000 0.00000000 0.000000 0.00000 0,0.000000 0.000000 0.000000 0.000000, 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000, 0.000000 0.000000 0.000000 0.000000 0.00000000 0.000000 0.000000 0.000000 г., 0.000000 0.000000 0.000000 0.00000000 г. 0.000000 0.000000 0.000000 0.00000000, 0.000000 0.000000 0.000000, -0.006897, -0.000549 0.0031740.003540.003632, 0.004578 0.005280 0.001831 0.014771 0.014954 0.001801 0.009247 0.011139, 0.005249 0.0077385, 0.007263,0.016571,0.020264,0.010590, 0.014801,0.023132,0.027039,0.031128,0.031799,0.037109,0.038757,0.049438, 0.057098,0.042786,0.045593,0.052032,0.045380,0.045227,0.045837,0.043793, 0.041931,0.043976,0.046570,0.030182,0.024475, 0.029877,0.026184,0.026001, 0.026611,0.031921,0.035736,0.040710,0.053070,0.042572,0.039917,0.051636, 0.053009,0.053528,0.053009,0.054962,0.055603,0.053833,0.060638,0.050171, 0.041779,0.049194,0.046356,0.000000,0.000000,0.000000, 0.000000,0.000000, 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.0 00000 0.000000, 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000, 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 г., 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 г. 0.041931, 0.038879,0.034515,0.031494,0.026337,0.034576,0.028992,0.014038,0.018127, 0.017822,0.015137,0.015778,0.013519,0.015564,0.014832,0.023285,0.022034, 0.006317,0.010254,0.010742,0.004303,0.003784, -0,000153, -0,002502, ~

Я не могу понять, почему у меня во входном сигнале появляются случайные группы нулей. Кажется, что-то прерывистое.

Сначала я подумал, может быть, у меня есть левый и правый канал, а правый канал всегда записывает ноль. Но просматривая свой код, я явно настроил его для одного канала.

Тогда я подумал, может быть, это просто места тишины в сигнале. Но это не имеет смысла. Если бы у меня была только дюжина нулей, 0,000000, я бы, конечно, ожидал, что за ними последуют очень-очень маленькие числа, например, 0,000007 ,000014, но ненулевые числа, похоже, находятся в районе отметки 0,01.

Я только что попытался переключить свой аудиовход на внешний USB-микрофон, и это улучшило разрешение. Ненулевые числа теперь кажутся около отметки 0,001. но все же есть заметный разрыв...

Интересно, выполняются ли на чипе какие-то вычисления, которые округляют до 0. Если это так, то можно ли его откалибровать? Что здесь происходит?

Вторая действительно странная проблема, которую я замечаю, — это мошеннические значения.

Вот пример пакета, который содержит некоторые из этих значений (на этот раз с использованием USB-микрофона; вы можете видеть, как улучшилось разрешение):

Это сбивает меня с толку. возникновение этих глюков низкое; менее одного из 10 кадров.

Означает ли это, что мне нужно предварительно обработать мой аудиопоток?

В прошлый раз, когда я использовал аудиоблоки, я никогда этого не делал. Я просто передал звук прямо в процедуру определения высоты тона. И с этим проблем не было. Вот мне интересно, у меня там тоже глюки были..

У меня возникают проблемы как со встроенным микрофоном MacBook, так и с внешним USB-микрофоном.

Вот мой код:

Мое первое предложение состояло бы в том, чтобы переместить любые

//
//  MicRecord.m
//  PitchDetect
//
//  Created by Pi on 05/01/2011.
//

#import "MicRecord.h"

void AudioInputCallback(
                        void * inUserData, 
                        AudioQueueRef inAQ, 
                        AudioQueueBufferRef inBuffer, 
                        const AudioTimeStamp * inStartTime, 
                        UInt32 inNumberPacketDescriptions, 
                        const AudioStreamPacketDescription * inPacketDescs) ;


@implementation MicRecord

@synthesize fftFrame;

/*
- (id) init 
{
    if (self = [super init]) 
    {
        [self setupWithSampleRate: 44100
                          buffers: 12
                           bufLen: 512 ];
    }

    return self;
}
 */

// - - - - - - - -

- (void) setupWithSampleRate: (int) in_sampRate
                     buffers: (int) in_nBuffers
                        step: (int) in_step
                   frameSize: (int) in_frameSize
                      target: (id) in_target
                         sel: (SEL) in_sel
{
    sampRate = in_sampRate;

    nBuffers = in_nBuffers;

    bufLen = in_step;

    frameSize = in_frameSize;

    targ = in_target;
    sel = in_sel;

    audioBuffer = calloc(nBuffers, sizeof(AudioQueueBufferRef *) );
    [self setupAudioFormat];
    [self setupAudioQueue];

    fftFrame = calloc(frameSize, sizeof(float) );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- (void) setupAudioFormat
{
    // Set the format to 32 bit, single channel, floating point, linear PCM
    const int four_bytes_per_float = 4;
    const int eight_bits_per_byte = 8;

    memset(& dataFormat, 
           (int) 0x00, 
           sizeof(dataFormat) );

    dataFormat.mSampleRate = sampRate;
    dataFormat.mFormatID = kAudioFormatLinearPCM;
    dataFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;
    dataFormat.mBytesPerPacket = four_bytes_per_float;
    dataFormat.mFramesPerPacket = 1;    
    dataFormat.mBytesPerFrame = four_bytes_per_float;       
    dataFormat.mChannelsPerFrame = 1;   
    dataFormat.mBitsPerChannel = four_bytes_per_float * eight_bits_per_byte;
}

// - - - - - - - - - - - - - - - - -

- (void) setupAudioQueue
{
    currentPacket = 0;

    OSStatus status;

    status = AudioQueueNewInput(& dataFormat,
                                AudioInputCallback,
                                self,
                                CFRunLoopGetCurrent(),
                                kCFRunLoopCommonModes,
                                0,
                                & queue);

    for(int i = 0; i < nBuffers; i++)
    {
        status = AudioQueueAllocateBuffer(queue,
                                          bufLen, 
                                          & audioBuffer[i]);

        status = AudioQueueEnqueueBuffer(queue,
                                         audioBuffer[i], 0, NULL);
    }

    status = AudioQueueFlush (queue);

    printf("Status: %d", (int) status);
}

// - - - - - - - - - - - - - - - - -

- (void) start
{
    OSStatus status = AudioQueueStart(queue, NULL);

    printf("Status: %d", (int) status);
}

// - - - - - - - - - - - - - - -

- (void) stop
{
    AudioQueueStop(queue, true);

    for(int i = 0; i < nBuffers; i++)
        AudioQueueFreeBuffer(queue, audioBuffer[i]);

    AudioQueueDispose(queue, true);
}

// - - - - - - - - - -

- (void) dealloc
{
    [self stop];

    free (audioBuffer);

    [super dealloc];
}


@end

// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 

void AudioInputCallback(
                        void                    * inUserData, 
                        AudioQueueRef           inAQ, 
                        AudioQueueBufferRef     inBuffer, 
                        const AudioTimeStamp    * inStartTime, 
                        UInt32                  inNumberPacketDescriptions, 
                        const AudioStreamPacketDescription * inPacketDescs
                        )
{
    MicRecord * x = (MicRecord *) inUserData;

    //if(inNumberPacketDescriptions == 0 && recordState->dataFormat.mBytesPerPacket != 0)
    //{
    //    inNumberPacketDescriptions = inBuffer->mAudioDataByteSize / recordState->dataFormat.mBytesPerPacket;
    //}

    if (0)
        printf("Handling buffer %d\n", (int) x->currentPacket);

    int step = x->bufLen;

    if (inBuffer->mAudioDataBytesCapacity != step)
    {
        printf("---");
    }

    static int k = -1;
    k++;
    static float lastVal = 0;
    static int count = 0;
    if (k < 32) {
        if (k == 0)
            printf("\nfloat buf[32*%d=%d] = {", step, 32*step);
        float * in_buf = (float *) inBuffer->mAudioData;
        printf("\n ~\nPACKET\n");
        for (int i = 0; i < step; i++)
        {
            /*
            if (fabs(in_buf[i]) < .0001 && fabs(lastVal) > .0001)
            {
                printf("%d Nonzeros\n",count);
                count = 0;
            }
            if (fabs(in_buf[i]) > .0001 && fabs(lastVal) < .0001)
            {
                printf("%d Zeros\n",count);
                count = 0;
            }
            count++;
            lastVal = in_buf[i];*/
            printf("%f,", in_buf[i] );

            if (i % 8 == 0)
                printf("\n");
            //if (count % (8 * 64) == 0)
            //  printf("\n");

            count++;
        }
        if (k == 31)
            printf("}\n");
    }


    // shifty frame data down by 'step' elements 
    // to make room for new data
    // imagine cutting out elts [0] thru [step-1] (ie 'step' of them)
    // first new elt at pos [0] will be [step]
    memmove(& x->fftFrame[0], // dest first
            & x->fftFrame[step], // src
            x->frameSize - step
            );

    memcpy(& x->fftFrame[x->frameSize - step],
           inBuffer->mAudioData,
           step * sizeof(float)
           );

    x->currentPacket += inNumberPacketDescriptions;
    // }

    AudioQueueEnqueueBuffer(x->queue, inBuffer, 0, NULL);

    [x->targ performSelector: x->sel];
}
из обратного вызова самого низкого уровня. Если они медленные, вполне возможно, что вам не хватает буфера здесь или там. Я не знаю, будет ли это проявляться в виде блоков нулей или ложных выборок, которые вы наблюдаете, но может.

//
//  MicRecord.m
//  PitchDetect
//
//  Created by Pi on 05/01/2011.
//

#import "MicRecord.h"

void AudioInputCallback(
                        void * inUserData, 
                        AudioQueueRef inAQ, 
                        AudioQueueBufferRef inBuffer, 
                        const AudioTimeStamp * inStartTime, 
                        UInt32 inNumberPacketDescriptions, 
                        const AudioStreamPacketDescription * inPacketDescs) ;


@implementation MicRecord

@synthesize fftFrame;

/*
- (id) init 
{
    if (self = [super init]) 
    {
        [self setupWithSampleRate: 44100
                          buffers: 12
                           bufLen: 512 ];
    }

    return self;
}
 */

// - - - - - - - -

- (void) setupWithSampleRate: (int) in_sampRate
                     buffers: (int) in_nBuffers
                        step: (int) in_step
                   frameSize: (int) in_frameSize
                      target: (id) in_target
                         sel: (SEL) in_sel
{
    sampRate = in_sampRate;

    nBuffers = in_nBuffers;

    bufLen = in_step;

    frameSize = in_frameSize;

    targ = in_target;
    sel = in_sel;

    audioBuffer = calloc(nBuffers, sizeof(AudioQueueBufferRef *) );
    [self setupAudioFormat];
    [self setupAudioQueue];

    fftFrame = calloc(frameSize, sizeof(float) );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- (void) setupAudioFormat
{
    // Set the format to 32 bit, single channel, floating point, linear PCM
    const int four_bytes_per_float = 4;
    const int eight_bits_per_byte = 8;

    memset(& dataFormat, 
           (int) 0x00, 
           sizeof(dataFormat) );

    dataFormat.mSampleRate = sampRate;
    dataFormat.mFormatID = kAudioFormatLinearPCM;
    dataFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;
    dataFormat.mBytesPerPacket = four_bytes_per_float;
    dataFormat.mFramesPerPacket = 1;    
    dataFormat.mBytesPerFrame = four_bytes_per_float;       
    dataFormat.mChannelsPerFrame = 1;   
    dataFormat.mBitsPerChannel = four_bytes_per_float * eight_bits_per_byte;
}

// - - - - - - - - - - - - - - - - -

- (void) setupAudioQueue
{
    currentPacket = 0;

    OSStatus status;

    status = AudioQueueNewInput(& dataFormat,
                                AudioInputCallback,
                                self,
                                CFRunLoopGetCurrent(),
                                kCFRunLoopCommonModes,
                                0,
                                & queue);

    for(int i = 0; i < nBuffers; i++)
    {
        status = AudioQueueAllocateBuffer(queue,
                                          bufLen, 
                                          & audioBuffer[i]);

        status = AudioQueueEnqueueBuffer(queue,
                                         audioBuffer[i], 0, NULL);
    }

    status = AudioQueueFlush (queue);

    printf("Status: %d", (int) status);
}

// - - - - - - - - - - - - - - - - -

- (void) start
{
    OSStatus status = AudioQueueStart(queue, NULL);

    printf("Status: %d", (int) status);
}

// - - - - - - - - - - - - - - -

- (void) stop
{
    AudioQueueStop(queue, true);

    for(int i = 0; i < nBuffers; i++)
        AudioQueueFreeBuffer(queue, audioBuffer[i]);

    AudioQueueDispose(queue, true);
}

// - - - - - - - - - -

- (void) dealloc
{
    [self stop];

    free (audioBuffer);

    [super dealloc];
}


@end

// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 

void AudioInputCallback(
                        void                    * inUserData, 
                        AudioQueueRef           inAQ, 
                        AudioQueueBufferRef     inBuffer, 
                        const AudioTimeStamp    * inStartTime, 
                        UInt32                  inNumberPacketDescriptions, 
                        const AudioStreamPacketDescription * inPacketDescs
                        )
{
    MicRecord * x = (MicRecord *) inUserData;

    //if(inNumberPacketDescriptions == 0 && recordState->dataFormat.mBytesPerPacket != 0)
    //{
    //    inNumberPacketDescriptions = inBuffer->mAudioDataByteSize / recordState->dataFormat.mBytesPerPacket;
    //}

    if (0)
        printf("Handling buffer %d\n", (int) x->currentPacket);

    int step = x->bufLen;

    if (inBuffer->mAudioDataBytesCapacity != step)
    {
        printf("---");
    }

    static int k = -1;
    k++;
    static float lastVal = 0;
    static int count = 0;
    if (k < 32) {
        if (k == 0)
            printf("\nfloat buf[32*%d=%d] = {", step, 32*step);
        float * in_buf = (float *) inBuffer->mAudioData;
        printf("\n ~\nPACKET\n");
        for (int i = 0; i < step; i++)
        {
            /*
            if (fabs(in_buf[i]) < .0001 && fabs(lastVal) > .0001)
            {
                printf("%d Nonzeros\n",count);
                count = 0;
            }
            if (fabs(in_buf[i]) > .0001 && fabs(lastVal) < .0001)
            {
                printf("%d Zeros\n",count);
                count = 0;
            }
            count++;
            lastVal = in_buf[i];*/
            printf("%f,", in_buf[i] );

            if (i % 8 == 0)
                printf("\n");
            //if (count % (8 * 64) == 0)
            //  printf("\n");

            count++;
        }
        if (k == 31)
            printf("}\n");
    }


    // shifty frame data down by 'step' elements 
    // to make room for new data
    // imagine cutting out elts [0] thru [step-1] (ie 'step' of them)
    // first new elt at pos [0] will be [step]
    memmove(& x->fftFrame[0], // dest first
            & x->fftFrame[step], // src
            x->frameSize - step
            );

    memcpy(& x->fftFrame[x->frameSize - step],
           inBuffer->mAudioData,
           step * sizeof(float)
           );

    x->currentPacket += inNumberPacketDescriptions;
    // }

    AudioQueueEnqueueBuffer(x->queue, inBuffer, 0, NULL);

    [x->targ performSelector: x->sel];
}

person P i    schedule 11.01.2011    source источник
comment
Вы также можете удалить вопрос, что быстро и просто. Рад, что вы нашли проблему.   -  person P i    schedule 12.01.2011
comment
Это действительно хорошее предложение, и я его реализовал. Спасибо. К сожалению, это все еще не решает проблему. Я заметил, что сумасшедшие значения всегда появляются в середине кадра 12. Мне нужно будет более внимательно просмотреть код...   -  person mtrw    schedule 12.01.2011


Ответы (1)


Что произойдет с вашей очередью, если вы заполните ее быстрее, чем освободите?

Я голосую, чтобы закрыть это, я обнаружил, что проблема была в моем собственном некачественном кодировании. У меня был malloc'd(n), а не n*sizeof(float), поэтому он читал случайный мусор.

person mtrw    schedule 11.01.2011
comment
Нули всегда в кадре 12 или ложные выборки в кадре 12? Вы получаете либо нули, либо мусор? Имело ли какое-либо значение перемещение _1_? - person P i; 11.01.2011
comment
~ Packet -0.001343, -0.001190, -0.001526, -0.001373, -0.000946, -0.001526, -0.001221, -0.001190, -0.001221, -0.001251, -0.001373, -0.001190, -0.001312, -0.001312, -0.001434, -0.001282, -0.001312, -0.001099, -0.001007, -0.001221, -0.001160, -0.001312, -0.001343, -0.001221, -0.001007, -0.001099, -0.001404, -0.001068, -0.001038, -0.001404, -0.001038, -0.001190, -0.001404 , -0.001099, -0.001282, -0.001221, -0.001007, -0.001007, -0.001099, -0.001221, -0.001160, -0.001038, -0.001038, -0.001007, -0.000946, -0.001129, -0.000916, -0.000946, -0.000946, - 0.000946, -0.000946, - 0,000946, -0.000824, -0.000824, -0.001007, -0.000763, -0.001038, -0.000854, -0.000977, -0.000916, -0.000641, -0.000977, -0.000916, -0.000946, -0.000732, -0.000824 0.000000, 0.000000 0.0000000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.00000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.00000000 0.0000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 г., 0.0000 0.000000 0.000000 г. 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.00 0000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000, 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 г., 0.0000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 г., 0.0000 0.000000 г., 0.000000 0.000000 0.000000 0.000000 0.000000 0.00000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.00000000 0.0000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 г., 0.0000 0.000000 0.000000 г. 0.000000 0.000000 0.000000 0.000000 0.000000, 0,000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000, 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 г., 0.000000 0.000000 0.000000 0.000000 г., 0.000000,0.000000,0.000000,0.000000, -0.000000,2.000000, -2.000000,0.000000, -0.000000,36893488147419103232.000000, -36893488147419103232.000000,0.000000, -0.000000,8589934592.000000, -8589934592.000000,0.000000, -0.000000,158456325028528675187087900672.000000, -158456325028528675187087900672.000000,0.0 00000, -0.000000,131072.000000, -131072.000000,0.000000, -0.000000,2417851639229258349412352.000000, -2417851639229258349412352.000000,0.000000, -0.000000,562949953421312.000000, -562949953421312.000000,0.000031, -0.000031,10384593717069655257060992658440192.000000, -10384593717069655257060992658440192.000000,0.000000, 0.000000,0.000000,0.000000,0.000000, 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0. 000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000, 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0000000000 0.0000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 г., 0.000000 г., 0,000000,0,000000,0,000000,0,000000,0,000000,0,000000, - person mtrw; 11.01.2011