Как получить массив данных с плавающей точкой из AudioQueueRef в iOS?
Я работаю над получением звука в iPhone в форме, где я могу передать его алгоритму (С++). Есть, конечно, множество вариантов: учебник AudioQueue на trailsinthesand начинает все начинать.
Звуковой обратный вызов, однако, дает AudioQueueRef
, и я нахожу документацию Apple тонкой по этой стороне вещей. Встроенные методы для записи в файл, но ничего, где вы на самом деле находитесь внутри пакетов, чтобы видеть данные.
Мне нужны данные. Я не хочу ничего записывать в файл, и это, по-видимому, нацелено на все учебники - и даже на объекты ввода-вывода Apple. Apple AVAudioRecorder
(беспричинно) даст вам уровни и напишет данные, но фактически не даст вам доступ к ней. Если я что-то не хватает...
Как это сделать? В приведенном ниже коде есть 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;
}
Ответы
Ответ 1
// 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]
.
Ответ 2
Вышеупомянутое решение не сработало для меня, я сам получал неправильные данные образца. (endian issue) Если вы хотите, чтобы кто-то получил неправильные данные образца в будущем, я надеюсь, что это поможет вам:
- (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);
}