#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 — это беспорядок, и на выяснение того, как он работает, уйдет больше времени, чем на его фактическую сборку.