основной звук ios: изменение aurioTouch для сохранения данных pcm

#ios #core-audio

#iOS #ядро-аудио

Вопрос:

В качестве упражнения я пытаюсь изменить aurioTouch таким образом, чтобы он сохранял первые 60 секунд PCM, которые поступают через микрофон. Я избегаю библиотек более высокого уровня, потому что хочу создать поверх этого некоторую обработку в реальном времени с низкой задержкой. Я сделал это, просто создав большой буфер сохранения, а затем просто добавив значение data_ptr[2], хранящееся в drawBuffers[] для каждого из «бесчисленных фреймов» для каждого вызова PerformThru … затем, по истечении 60 секунд, я сбрасываю буфер на диск одним выстрелом.

Я попробовал этот код, введя его равномерным щелчком мыши. Проблема в том, что когда я визуализирую эти данные буфера сохранения в gnuplot, я получаю пики в неравномерные моменты времени, отклоняющиеся на 30-40% от постоянного щелчка, что означает, что некоторые пики расположены близко друг к другу, в то время как другие далеко друг от друга. Я вижу, что ввод click .wav очень равномерный, но график сохранения в буфере имеет причудливые пики. Это заставляет меня задуматься, правильно ли я сохраняю данные pcm? Возможно, я почему-то занимаю слишком много времени и в результате теряю данные?

Изменения в PerformThru () у меня есть:

{ // выделить буфер static int *saveBuffer = ( int * ) malloc( 10000000 * sizeof( int ) ); . . .

     SInt8 *data_ptr = (SInt8 *)(ioData->mBuffers[0].mData);

    for (i=0; i<inNumberFrames; i  )
    {
        if ((i drawBufferIdx) >= drawBufferLen)
        {
            cycleOscilloscopeLines();
            drawBufferIdx = -i;
        }
        drawBuffers[0][i   drawBufferIdx] = data_ptr[2];

        // XXXX I added this line
        if ( saveBuffer ) { saveBuffer[ saveBufferIdx   ] = ( data_ptr[ 2 ] ); }


        data_ptr  = 4;
    }

    // XXX - I added this block:  dump saveBuffer after 60 seconds
    if ( saveBuffer amp;amp; ( CAHostTimeBase::HostDeltaToNanos( initialHostTime, inTimeStamp->mHostTime ) / 1000000000 ) > 60 )
    {
        std::ofstream bufferOut;
        bufferOut.open( "pcmBuffer.txt" );
        for ( UInt64 i = 0; i < saveBufferIdx; i   )
        {
            bufferOut << saveBuffer[ i ] << std::endl;
        }
        bufferOut.close();
        free( saveBuffer );
        saveBuffer = 0;
    }
    drawBufferIdx  = inNumberFrames;
}
  

Ответ №1:

Используйте CAMediaCurrentTime (текущий носитель / current media — я всегда забываю, в какую сторону)

Черт возьми, этот исходный код уродлив, кому бы ни писали его в Apple, есть чему поучиться в плане написания читаемого кода. Тот факт, что он фактически используется в качестве общедоступного сэмпла, — это просто шутка.

похоже, вы все делаете правильно. Почему бы вам не попробовать отключить все остальное и не загружать сэмплы ТОЛЬКО в свой буфер?

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

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