Как получить массив аудиоданных с плавающей запятой из AudioQueueRef в iOS? - PullRequest
12 голосов
/ 24 октября 2011

Я работаю над передачей аудио в iPhone в форме, где я могу передать ее алгоритму анализа (C ++).Есть, конечно, много вариантов: учебник AudioQueue на trailsinthes и запускает процесс.

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

Мне нужны данные.Я не хочу ничего записывать в файл, к чему, похоже, стремятся все учебные пособия - и даже объекты удобства ввода-вывода Apple.AVAudioRecorder от Apple (в бешенстве) даст вам уровни и запишет данные, но на самом деле не даст вам доступа к ним.Если я что-то упустил ...

Как это сделать?В приведенном ниже коде есть inBuffer->mAudioData, который очень заманчиво близок, но я не могу найти информацию о том, в каком формате находятся эти «данные» или как получить к ним доступ.

Обратный вызов AudioQueue:

void AudioInputCallback(void *inUserData,
    AudioQueueRef inAQ,
    AudioQueueBufferRef inBuffer,
    const AudioTimeStamp *inStartTime,
    UInt32 inNumberPacketDescriptions,
    const AudioStreamPacketDescription *inPacketDescs)
{
    static int count = 0;
    RecordState* recordState = (RecordState*)inUserData;    
    AudioQueueEnqueueBuffer(recordState->queue, inBuffer, 0, NULL);

    ++count;
    printf("Got buffer %d\n", count);
}

И код для записи аудио в файл:

OSStatus status = AudioFileWritePackets(recordState->audioFile,
                false,
                inBuffer->mAudioDataByteSize,
                inPacketDescs,
                recordState->currentPacket,
                &inNumberPacketDescriptions,
                inBuffer->mAudioData); // THIS! This is what I want to look inside of.
if(status == 0)
{
     recordState->currentPacket += inNumberPacketDescriptions;
}

Ответы [ 2 ]

10 голосов
/ 01 ноября 2011
  // so you don't have to hunt them all down when you decide to switch to float: 
  #define AUDIO_DATA_TYPE_FORMAT SInt16

  // the actual sample-grabbing code:
  int sampleCount = inBuffer->mAudioDataBytesCapacity / sizeof(AUDIO_DATA_TYPE_FORMAT);
  AUDIO_DATA_TYPE_FORMAT *samples = (AUDIO_DATA_TYPE_FORMAT*)inBuffer->mAudioData;

Тогда у вас есть (в нашем случае SInt16) массив samples, к которому вы можете получить доступ от samples[0] до samples[sampleCount-1].

0 голосов
/ 22 июня 2017

Приведенное выше решение не сработало для меня, я сам получал неправильные данные образца (проблема с порядком байтов) Если в будущем кто-то получит неправильные данные образца, я надеюсь, что это поможет вам:

- (void) feedSamplesToEngine: (UInt32) audioDataBytesCapacity audioData: (void *) audioData { int sampleCount = audioDataBytesCapacity / sizeof (SAMPLE_TYPE);

SAMPLE_TYPE *samples = (SAMPLE_TYPE*)audioData;
//SAMPLE_TYPE *sample_le = (SAMPLE_TYPE *)malloc(sizeof(SAMPLE_TYPE)*sampleCount );//for swapping endians

std::string shorts;
double power = pow(2,10);
for(int i = 0; i < sampleCount; i++)
{
    SAMPLE_TYPE sample_le =  (0xff00 & (samples[i] << 8)) | (0x00ff & (samples[i] >> 8)) ; //Endianess issue
    char dataInterim[30];
    sprintf(dataInterim,"%f ", sample_le/power); // normalize it.
    shorts.append(dataInterim);
}
...