Тот, кто это решит, должен получить трофей Шерлока Холмса. Вот оно.
Я использую 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);
}
«Конвейер» - это заранее выделенный мной массив с плавающей запятой.