2015-08-12 1 views
0

Так что я недавно изучил основные данные и до сих пор новичок. Мне трудно понять, какие данные я записываю и как это влияет на общий поток данных. Так что для некоторого фона у меня есть приложение, которое делает потоковое видео/аудио между телефонами с помощью webRTC. Тем не менее, я хочу проверить данные, которые вводятся в устройство через микрофон и данные, выводимые через динамик. Я посмотрел в AurioTouch демо и Core Audio и в настоящее время у меня есть это:Получение микрофонного входа и выхода динамиков с использованием Core Audio

- (void)setupIOUnit 
{ 
    // Create a new instance of AURemoteIO 

    AudioComponentDescription desc; 
    desc.componentType = kAudioUnitType_Output; 
    desc.componentSubType = kAudioUnitSubType_RemoteIO; 
    desc.componentManufacturer = kAudioUnitManufacturer_Apple; 
    desc.componentFlags = 0; 
    desc.componentFlagsMask = 0; 

    AudioComponent comp = AudioComponentFindNext(NULL, &desc); 
    AudioComponentInstanceNew(comp, &rioUnit); 

    // Enable input and output on AURemoteIO 
    // Input is enabled on the input scope of the input element 
    // Output is enabled on the output scope of the output element 

    UInt32 one = 1; 
    AudioUnitSetProperty(rioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &one, sizeof(one)); 
    AudioUnitSetProperty(rioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &one, sizeof(one)); 


    // Set the MaximumFramesPerSlice property. This property is used to describe to an audio unit the maximum number 
    // of samples it will be asked to produce on any single given call to AudioUnitRender 
    UInt32 maxFramesPerSlice = 4096; 
    AudioUnitSetProperty(rioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFramesPerSlice, sizeof(UInt32)); 

    // Get the property value back from AURemoteIO. We are going to use this value to allocate buffers accordingly 
    UInt32 propSize = sizeof(UInt32); 
    AudioUnitGetProperty(rioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFramesPerSlice, &propSize); 

    // Set the render callback on AURemoteIO 
    AURenderCallbackStruct renderCallback; 
    renderCallback.inputProc = performRender; 
    renderCallback.inputProcRefCon = NULL; 
    AudioUnitSetProperty(rioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallback, sizeof(renderCallback)); 

    NSLog(@"render set now"); 
    // Initialize the AURemoteIO instance 
    AudioUnitInitialize(rioUnit); 
    [self startIOUnit]; 
    return; 
} 

- (OSStatus)startIOUnit 
{ 
    OSStatus err = AudioOutputUnitStart(rioUnit); 
    if (err) NSLog(@"couldn't start AURemoteIO: %d", (int)err); 
    return err; 
} 

Рендер функция обратного вызова

static OSStatus performRender (void       *inRefCon, 
          AudioUnitRenderActionFlags *ioActionFlags, 
          const AudioTimeStamp   *inTimeStamp, 
          UInt32      inBusNumber, 
          UInt32      inNumberFrames, 
          AudioBufferList    *ioData) 
{ 
    OSStatus err = noErr; 
// the data gets rendered here 

    err = AudioUnitRender(rioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData); 

    if (ioData->mBuffers[0].mDataByteSize >= 12) { 
     NSData *myAudioData = [NSData dataWithBytes: ioData->mBuffers[0].mData length:12]; 
     NSLog(@" playback's first 12 bytes: %@", myAudioData); 
    } 

    for (UInt32 i=0; i<ioData->mNumberBuffers; ++i) { 
     memset(ioData->mBuffers[i].mData, 0, ioData->mBuffers[i].mDataByteSize); 
    } 

    return err; 
} 

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

Я видел некоторые различные параметры этой линии:

AudioUnitSetProperty(rioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallback, sizeof(renderCallback)); 

и мне интересно, если я просто это не так или что-то. Кроме того, есть эта строка:

err = AudioUnitRender(rioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData); 

под влиянием AudioUnitSetProperty? Что делает установка 1 в этом сценарии?

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

+0

Возможно, вы имели в виду Core Audio или Core Media вместо Core Data? – Razvan

+0

Исправлено и сменили его на основной звук –

ответ

0

Аудиоустройство RemoteIO не изменяет аудио вход или выход, используемые любым другим аудио API. Он только фиксирует данные микрофона в буферах или воспроизводит аудиоданные из буферов, которые отделены от буферов, используемых другими аудио API.

3

Аудиоустройство Remote IO является частью основного звука, который выполняет вход и выход. Это полный блок, который может записывать/воспроизводить аудио либо аппаратное (микрофон/динамик), и/или из вашей программы. Это иногда делает его запутанным. Подумайте об этом так.

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

------- Входы ------------

Bus 0: чтение из приложения (Конструируется аудио осциллограмм программно). Здесь вы пишете обратный вызов, который автоматически вызывается периодически. В нем говорится: «Дайте мне следующие аудио-образцы». Например, ваш код там может дать ему образцы звука треугольной волны, которые вы генерируете программно.
Итак, вы генерируете сигнал для подачи в программу. Вы также можете подавать этот вход с выхода другого аудиоустройства.

Автобус 1: считывание с микрофона. Здесь вы можете читать звуковые сэмплы с микрофона. Обратите внимание, что это только сырые образцы. Вы можете либо сохранить их в файл (например, приложение для записи), отправить их по сети, либо даже подключить их к динамику (см. Ниже).Вы не услышите звук от микрофона ... он не спасет ... если вы ничего не сделаете с ним.

---------- ---------- Выходы

автобус 0: диктор телефона. Здесь вы можете записывать аудиоданные, и они будут воспроизводить их на динамике. Таким образом, вы получаете еще один обратный вызов, который говорит «дайте мне образцы для воспроизведения», и вы заполняете буфер звуком, и он воспроизводит его. Обратный вызов происходит периодически до того, как текущий буфер завершит воспроизведение.

Автобус 1: напишите в своем приложении. Здесь вы можете взять звук, сгенерированный удаленным IO, и сделать что-то с ним в своем приложении. Например, вы можете подключить вывод к другому или записать данные в файл.

Итак, чтобы ответить на ваш вопрос «Что делает установка 1 в этом сценарии?»

Вот спецификации от яблока на AudioUnitRender

OSStatus AudioUnitRender (AudioUnit inUnit, 
AudioUnitRenderActionFlags *ioActionFlags, 
const AudioTimeStamp *inTimeStamp, 
UInt32 inOutputBusNumber, 
UInt32 inNumberFrames, 
AudioBufferList *ioData); 

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

Если вы хотите изучить данные микрофона, используйте шину 1 на входе. Если вы хотите изучить данные динамиков, используйте шину 0 на выходе.

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

+1

спасибо, большое объяснение –