Подсчет пиков мощности звука iOS - PullRequest
1 голос
/ 02 июня 2011

Отредактировал вопрос из-за прогрессивного понимания: -)

Я создаю приложение, которое прослушивает аудиовход.Я хочу, чтобы он считал пики.(пики будут на максимальной частоте около 10 Гц.)

После долгих поисков я в конечном итоге воспользовался сервисом AudioQueue, так как он сможет дать мне необработанные входные данные.Я использую урезанную версию (без воспроизведения) примера SpeakHere, но вместо того, чтобы просто записывать буфер в файловую систему, я хочу посмотреть на отдельные примеры данных.

Думаю, я на правильном путисейчас, но я не понимаю, как работать с буферами.Я пытаюсь выделить данные одного образца.Так что для цикла for в следующей функции, имеет ли это смысл, и что я должен добавить туда, чтобы получить один образец?

void AQRecorder::MyInputBufferHandler( void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime, UInt32 inNumPackets, const AudioStreamPacketDescription* inPacketDesc)
{
    // AudioQueue callback function, called when an input buffers has been filled.

    AQRecorder *aqr = (AQRecorder *)inUserData;
    try {
        if (inNumPackets > 0) {
            /*          // write packets to file
            XThrowIfError(AudioFileWritePackets(aqr->mRecordFile,FALSE,inBuffer->mAudioDataByteSize,inPacketDesc,aqr->mRecordPacket,&inNumPackets,inBuffer->mAudioData),
                      "AudioFileWritePackets failed");*/

            SInt16 sample;
        for (UInt32 sampleIndex=0; sampleIndex < inNumPackets; ++sampleIndex) {


            // What do I put here to look at one sample at index sampleIndex ??


        }
        aqr->mRecordPacket += inNumPackets;
        }

    // if we're not stopping, re-enqueue the buffe so that it gets filled again
    if (aqr->IsRunning())
        XThrowIfError(AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL),
                      "AudioQueueEnqueueBuffer failed");
    } catch (CAXException e) {
    char buf[256];
    fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf));
}
}

(возможно, мне не следовало удалять так много исходного вопроса... что такое политика?)

Изначально я думал об использовании примера AurioTouch, но, как было отмечено в комментарии, он использует пропускную способность, и мне нужен только ввод данных.Это также гораздо более сложный пример, чем SpeakHere.

Ответы [ 2 ]

0 голосов
/ 13 июля 2011

Это перебирает все сэмплы в буфере.

    SInt16 sample;
    for (UInt32 sampleIndex=0; sampleIndex < inNumPackets; ++sampleIndex) {
        sample = buffer[sampleIndex]; // Get the power of one sample from the buffer
        aqr->AnalyseSample(sample);
    }

Была сложная часть: aqr указывает на экземпляр рекордера. Обратный вызов является статической функцией и не может напрямую обращаться к переменным-членам или функциям-членам.

Чтобы посчитать пики, я отслеживаю долгосрочное среднее и краткосрочное среднее. Если среднесрочное среднее значение является определенным фактором, превышающим долгосрочное среднее значение, существует пик. Когда краткосрочное среднее снова снижается, пик прошел.

0 голосов
/ 24 июня 2011

Вы, вероятно, захотите применить какое-то сглаживание к вашему пиковому уровню мощности, может быть, это БИХ-фильтр, что-то вроде:

x_out = 0.9 * x_old + 0.1 * x_in;
:
x_old = x_out;

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

обратите внимание, что во входном обратном вызове вы должны создавать свои собственные буферы, не думайте только потому, что вы получаете указатель буфера в качестве последнего параметра, который означает, что он указывает на что-то допустимое. это не так.

в любом случае, вы можете использовать некоторую функцию vDSP для получения квадрата для вектора целого буфера (1024 с плавающей запятой или любого другого размера буфера / формата потока)

и тогда вы можете сгладить это самостоятельно

...