Запись моно на iPhone в формате IMA4
Я использую пример приложения SpeakHear на сайте разработчиков Apple для создания приложения для записи звука. Я пытаюсь записать напрямую в формат IMA4, используя системную константу kAudioFormatAppleIMA4. Это перечислено как один из используемых форматов, но каждый раз, когда я настраиваю свою переменную аудиоформата и передаю и устанавливаю ее, я получаю 'fmt?' ошибка. Вот код, который я использую для настройки переменной формата аудио:
#define kAudioRecordingFormat kAudioFormatAppleIMA4
#define kAudioRecordingType kAudioFileCAFType
#define kAudioRecordingSampleRate 16000.00
#define kAudioRecordingChannelsPerFrame 1
#define kAudioRecordingFramesPerPacket 1
#define kAudioRecordingBitsPerChannel 16
#define kAudioRecordingBytesPerPacket 2
#define kAudioRecordingBytesPerFrame 2
- (void) setupAudioFormat: (UInt32) formatID {
// Obtains the hardware sample rate for use in the recording
// audio format. Each time the audio route changes, the sample rate
// needs to get updated.
UInt32 propertySize = sizeof (self.hardwareSampleRate);
OSStatus err = AudioSessionGetProperty (
kAudioSessionProperty_CurrentHardwareSampleRate,
&propertySize,
&hardwareSampleRate
);
if(err != 0){
NSLog(@"AudioRecorder::setupAudioFormat - error getting audio session property");
}
audioFormat.mSampleRate = kAudioRecordingSampleRate;
NSLog (@"Hardware sample rate = %f", self.audioFormat.mSampleRate);
audioFormat.mFormatID = formatID;
audioFormat.mChannelsPerFrame = kAudioRecordingChannelsPerFrame;
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioFormat.mFramesPerPacket = kAudioRecordingFramesPerPacket;
audioFormat.mBitsPerChannel = kAudioRecordingBitsPerChannel;
audioFormat.mBytesPerPacket = kAudioRecordingBytesPerPacket;
audioFormat.mBytesPerFrame = kAudioRecordingBytesPerFrame;
}
И вот где я использую эту функцию:
- (id) initWithURL: fileURL {
NSLog (@"initializing a recorder object.");
self = [super init];
if (self != nil) {
// Specify the recording format. Options are:
//
// kAudioFormatLinearPCM
// kAudioFormatAppleLossless
// kAudioFormatAppleIMA4
// kAudioFormatiLBC
// kAudioFormatULaw
// kAudioFormatALaw
//
// When targeting the Simulator, SpeakHere uses linear PCM regardless of the format
// specified here. See the setupAudioFormat: method in this file.
[self setupAudioFormat: kAudioRecordingFormat];
OSStatus result = AudioQueueNewInput (
&audioFormat,
recordingCallback,
self, // userData
NULL, // run loop
NULL, // run loop mode
0, // flags
&queueObject
);
NSLog (@"Attempted to create new recording audio queue object. Result: %f", result);
// get the recording format back from the audio queue's audio converter --
// the file may require a more specific stream description than was
// necessary to create the encoder.
UInt32 sizeOfRecordingFormatASBDStruct = sizeof (audioFormat);
AudioQueueGetProperty (
queueObject,
kAudioQueueProperty_StreamDescription, // this constant is only available in iPhone OS
&audioFormat,
&sizeOfRecordingFormatASBDStruct
);
AudioQueueAddPropertyListener (
[self queueObject],
kAudioQueueProperty_IsRunning,
audioQueuePropertyListenerCallback,
self
);
[self setAudioFileURL: (CFURLRef) fileURL];
[self enableLevelMetering];
}
return self;
}
Спасибо за помощь! Матф
2 ответа
Я не уверен, что все флаги формата, которые вы передаете, верны; IMA4 (который IIRC обозначает IMA ADPCM 4:1) является 4-битным (сжатие 4: 1 из 16 битов) с некоторыми заголовками.
Согласно документации для AudioStreamBasicDescription:
- mBytesPerFrame должно быть 0, так как формат сжат.
- mBitsPerChannel должен быть 0, так как формат сжат.
- mFormatFlags, вероятно, должно быть 0, так как выбирать нечего.
В соответствии с afconvert -f caff -t ima4 -c 1 blah.aiff blah.caf
с последующим afinfo blah.caf
:
- mBytesPerPacket должно быть 34, и
- mFramesPerPacket должно быть 64. Возможно, вы сможете установить их на 0 вместо.
Ссылочный алгоритм в оригинальной спецификации IMA не так уж полезен (это OCR сканирований, на сайте также есть сканы).
Кроме того, @tc. уже сказал, что проще автоматически заполнять ваши описания на основе идентификаторов, используя это:
AudioStreamBasicDescription streamDescription;
UInt32 streamDesSize = sizeof(streamDescription);
memset(&streamDescription, 0, streamDesSize);
streamDescription.mFormatID = kAudioFormatiLBC;
OSStatus status;
status = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &streamDesSize, &streamDescription);
assert(status==noErr);
Таким образом, вам не нужно угадывать особенности определенных форматов. Будьте осторожны, хотя в этом примере kAudioFormatiLBC
не нужна никакая дополнительная информация, другие форматы (обычно количество каналов и частота дискретизации).