Последний AudioQueueBuffer имеет завышенные значения

Тот, кто это решит, должен получить трофей Шерлока Холмса. Вот оно.

Я использую AudioQueues для записи звука (LPCM, SInt16, 4 буфера). В обратном вызове я попытался измерить среднюю амплитуду, преобразовав образцы в плавающее значение и используя vDSP_meamgv. Вот несколько примеров средств:

Mean, No of samples
44.400364, 44100
36.077393, 44100
27.672422, 41984
2889.821289, 44100
57.481972, 44100
58.967506, 42872
54.691631, 44100
2894.467285, 44100
62.697800, 42872
63.732948, 44100
66.575623, 44100
2979.566406, 42872

Как видите, каждый четвертый (последний) буфер - дикий. Я посмотрел отдельные образцы, там много нулей и много огромных чисел, и нет нормальных чисел, как для других буферов. Все становится интереснее. Если вместо этого я использую 3 буфера, третий (всегда последний) будет ужасным. И это справедливо для любого количества буферов, которое я выберу.

Я помещаю в обратный вызов if, чтобы не ставить в очередь дикие буферы, и как только он исчезнет, ​​больших чисел больше не будет, другие буферы продолжат нормально заполняться. Я вставляю кнопку, которая повторно ставит эту очередь в очередь после того, как она была отброшена, и как только я снова ставлю ее в очередь, она снова заполняется гигантскими выборками (а именно этим буфером!)

А теперь вишенка - я поместил свой код для вычисления среднего значения в другие проекты, например SpeakHere от Apple, и там происходит то же самое, хотя приложение работает нормально, записывая и воспроизводя то, что было записано.

Я просто не понимаю, я ломал голову, пытаясь понять это. Если бы у кого-нибудь была подсказка ...

Вот обратный вызов, если он поможет:

void Recorder::MyInputBufferHandler(void *                             inUserData,
                                    AudioQueueRef                          inAQ,
                                    AudioQueueBufferRef                    inBuffer,
                                    const AudioTimeStamp *                 inStartTime,
                                    UInt32                                 inNumPackets,
                                    const AudioStreamPacketDescription*    inPacketDesc) {
    Recorder* eu = (Recorder*)inUserData;

    vDSP_vflt16((SInt16*)inBuffer->mAudioData, 1, eu->conveier, 1, inBuffer->mAudioDataByteSize);
    float mean;
    vDSP_meamgv(eu->conveier, 1, &mean, inBuffer->mAudioDataByteSize);
    printf("values: %f, %d\n",mean,inBuffer->mAudioDataByteSize); 
//    if (mean<2300)
        AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
}

«Конвейер» - это заранее выделенный мной массив с плавающей запятой.


person Sergiu Todirascu    schedule 27.04.2014    source источник


Ответы (1)


Это я тоже получаю трофей. Ошибка заключалась в том, что функции vDSP не должны были иметь параметр mAudioDataByteSize, потому что им нужно количество ЭЛЕМЕНТОВ в массиве. В моем случае каждый элемент (SInt16) имеет 2 байта, поэтому я должен был передать mAudioDataByteSize / 2. Когда он прочитал последний буфер, он упал с края на другую длину и подсчитал некоторые случайные данные. Вуаля! Основная ошибка, но когда вы смотрите не во всех местах, это не так.

Для тех, кто наступил на одни и те же грабли ...

PS. Это пришло ко мне во время ванны :)

person Sergiu Todirascu    schedule 28.04.2014