2010-09-28 3 views
0

Я использую образец приложения SpeakHear на сайте разработчика Apple для создания приложения для записи звука. Я пытаюсь записать непосредственно в формат IMA4, используя постоянную систему kAudioFormatAppleIMA4. Это указано как один из используемых форматов, но каждый раз, когда я настраиваю переменную аудиоформата и передаю и устанавливаю его, я получаю «fmt?». ошибка. Вот код, который я использую для настройки аудио формата переменной:Запись Моно на iPhone в формате IMA4

#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; 
} 

Спасибо за помощь! -Matt

ответ

3

Я не уверен, что все флаги формата, которые вы проходите, верны; IMA4 (который, IIRC, обозначает IMA ADPCM 4: 1), является 4-разрядным (сжатие 4: 1 из 16 бит) с некоторыми заголовками.

Согласно документации для AudioStreamBasicDescription:

  • mBytesPerFrame должен быть 0, поскольку формат сжимается.
  • mBitsPerChannel должно быть 0, так как формат сжимается.
  • mFormatFlags должно быть 0, так как выбирать нечего.

Aaccording к afconvert -f caff -t ima4 -c 1 blah.aiff blah.caf с последующим afinfo blah.caf:

  • mBytesPerPacket должно быть 34, а
  • mFramesPerPacket должно быть 64. Вы можете быть в состоянии установить их на 0 вместо.

Справочный алгоритм в original IMA spec не так уж и полезен (это OCR сканирования, на сайте также есть сканирование).

1

Наверху, что @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 не нуждался в дополнительной информации, другие форматы (как правило, количество каналов и частота дискретизации).