2010-10-23 40 views
10

Tôi đang phát triển một ứng dụng iOS (được nhắm mục tiêu riêng cho iPhone, hiện tại) yêu cầu ứng dụng chỉ ghi âm từ micrô nội bộ iPhone (ngay cả khi tai nghe/tai nghe được cắm vào), và phát lại ở tai nghe (giả sử tai nghe được cắm vào bây giờ).Buộc iPhone Microphone làm đầu vào âm thanh

Tôi tự hỏi liệu điều này có thể thực hiện được với các API có sẵn không? Nếu vậy, bất cứ ai có thể vui lòng làm sáng tỏ một số cách làm thế nào để tôi đi về việc này?

Cảm ơn!

+1

những câu hỏi thú vị và sáng tạo nhất một cách tự nhiên sẽ đi bỏ ngỏ. bạn sẽ có nhiều việc phải làm một mình. – cregox

+0

Ghi âm qua mic nội bộ và phát lại đồng thời thông qua tai nghe của tai nghe (và micrô của tai nghe không sử dụng được) không thể thực hiện được trong iOS6. Trong iOS7, điều này có thể thông qua các phần mở rộng API được tìm thấy trong lớp AVAudioSession. –

+0

@Daniel S. làm thế nào chúng ta có thể ghi lại từ mic nội bộ và phát lại thông qua tai nghe của tai nghe? –

Trả lời

2

Tôi khá tự tin này có thể thông qua ứng dụng của bạn âm thanh Session:

Một âm thanh phiên là một trung gian giữa ứng dụng và iOS của bạn. Mỗi ứng dụng iPhone có chính xác một phiên âm thanh. Bạn định cấu hình nó thành thể hiện âm thanh của ứng dụng ý định của bạn. Để bắt đầu, bạn trả lời một số câu hỏi về cách bạn muốn ứng dụng của bạn để hành xử:

  • Làm thế nào để bạn muốn ứng dụng của đáp ứng với sự gián đoạn, chẳng hạn như một cuộc gọi điện thoại ?
  • Bạn có định trộn âm thanh của ứng dụng với các ứng dụng khác từ các ứng dụng đang chạy khác hoặc bạn có ý định tắt tiếng không?
  • Làm thế nào nên ứng dụng của bạn phản hồi âm thanh thay đổi tuyến đường, ví dụ: khi người dùng cắm vào hoặc rút phích cắm tai nghe?

Với câu trả lời trong tay, bạn sử dụng giao diện phiên âm thanh (khai báo trong AudioToolbox/AudioServices.h) để cấu hình phiên âm thanh của bạn và ứng dụng của bạn.

Dig bằng các tài liệu:

Và hãy để tôi biết làm thế nào nó đi!

+0

Để trả lời điểm. Tôi sẽ đào sâu vào các điểm trên và cho các bạn biết điều gì làm việc cho tôi.Cảm ơn @defbyte –

8

Tôi tin câu trả lời cho câu hỏi này là 'không'. Tôi đã sử dụng iPhone 4 và AVFoundation mới cho iOS 4 để thử nghiệm, tập trung vào lớp học AVCaptureDevice.

tôi đã thêm dòng sau vào một ứng dụng:

NSLog(@"%@", [AVCaptureDevice devices]); 

Vì vậy mà hỏi rằng tất cả các thiết bị có thể được sử dụng để chụp âm thanh và/hoặc video được liệt kê.Nếu không có tai nghe cắm vào, tôi nhận được:

(
    "Back Camera", 
    "Front Camera", 
    "iPhone Microphone" 
) 

Với tai nghe cắm vào tôi nhận được:

(
    "Back Camera", 
    "Front Camera", 
    Headphones 
) 

Vì vậy, micro iPhone rơi ra khỏi danh sách các AVCaptureDevices sẵn ngay sau khi tai nghe trở nên có sẵn. Để tìm hiểu thêm về điều này, tôi đã thêm một đoạn mã nhanh để lấy bản sao AVCaptureDevice cho thiết bị âm thanh có sẵn và in ID duy nhất của nó. Đối với cả hai thiết bị xác định chính nó như là "iPhone Microphone" và thiết bị xác định chính nó như là "tai nghe", tôi nhận:

com.apple.avfoundation.avcapturedevice.built-in_audio:0 

Có vẻ như với tôi để được rõ ràng rằng hai thiết bị không thể có cùng một ID duy nhất , vì vậy rõ ràng đó là cùng một thiết bị thay đổi trạng thái của nó. Mặc dù AVCaptureDevices có rất nhiều thứ để thiết lập trạng thái, nhưng nó chỉ giới hạn ở những thứ trực quan như lấy nét, phơi sáng, flash và cân bằng trắng.

2

Không thể thực hiện được, tôi cố gắng tìm ra người nghe đã thay đổi tuyến đường (với AudioSession). Kết quả của tôi là: bạn không thể định cấu hình đầu vào hoặc đầu ra riêng biệt vì categories do Apple cung cấp. Tôi cố gắng * PlayAndRecord, khi tôi ghép một thiết bị bluetooth, thay đổi lộ trình như thế này:

old route : HeadsetBT 
new route : SpeakerAndMicrophone 

Trong thực tế, bluetooth của tôi không phải là một tai nghe, chỉ cần loa ... Vì vậy, đối với tôi không có giải pháp.

+0

cùng một sự cố. loa BT và tai nghe BT của tôi đều hiển thị BluetoothHFP thay cho BluetoothA2DP cho loa –

4

Có vẻ như nó thực sự không thể.

Mục tiêu của tôi là gửi đầu ra tới tai nghe bluetooth và đầu vào bản ghi từ đó. Theo tôi có thể thấy, các tùy chọn tốt nhất của tôi là: Thuộc tính "PlayAndRecord + AllowBluetoothInput" (iphone 4, tai nghe Nokia BH-214)

Điều quan trọng là theo tài liệu hướng dẫn, bạn luôn phải ghi đè lại danh mục âm thanh của bạn khi thay đổi tuyến đường âm thanh!

NÀY LÀ CỦA TÔI ROUTE ĐỔI phương pháp nghe, rằng bản in: RouteChangeReasons, outputRoute, audioRout:

void RouteChangeListener(void     *inClientData, 
        AudioSessionPropertyID inID, 
        UInt32     inDataSize, 
        const void    *inData) { 


if (inID == kAudioSessionProperty_AudioRouteChange) { 

    NSLog(@"]-----------------[ Audio Route Change ]--------------------["); 

    // ************************************************************************************************ 
    // Check route change reason ********************************************************************** 
    // ************************************************************************************************ 
    CFDictionaryRef routeDict = (CFDictionaryRef)inData; 
    NSNumber* reasonValue = (NSNumber*)CFDictionaryGetValue(routeDict, CFSTR(kAudioSession_AudioRouteChangeKey_Reason)); 
    int reason = [reasonValue intValue]; 

    if (reason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) { 
     NSLog(@"] Logic: audio route change reason: OldDeviceUnavailable"); 
    }else if (reason == kAudioSessionRouteChangeReason_NewDeviceAvailable) { 
     NSLog(@"] Logic: audio route change reason: NewDeviceAvailable"); 
    }else if (reason == kAudioSessionRouteChangeReason_Unknown) { 
     NSLog(@"] Logic: audio route change reason: Unknown"); 
    }else if (reason == kAudioSessionRouteChangeReason_CategoryChange) { 
     NSLog(@"] Logic: audio route change reason: CategoryChange"); 
    }else if (reason == kAudioSessionRouteChangeReason_Override) { 
     NSLog(@"] Logic: audio route change reason: Override"); 
    }else if (reason == kAudioSessionRouteChangeReason_WakeFromSleep) { 
     NSLog(@"] Logic: audio route change reason: WakeFromSleep"); 
    }else if (reason == kAudioSessionRouteChangeReason_NoSuitableRouteForCategory) { 
     NSLog(@"] Logic: audio route chang reasone: NoSuitableRouteForCategory"); 
    } 

    // ************************************************************************************************ 
    // Check output type ****************************************************************************** 
    // ************************************************************************************************ 
    CFDictionaryRef currentRouteDescriptionDictionary = nil; 
    UInt32 dataSize = sizeof(currentRouteDescriptionDictionary); 
    AudioSessionGetProperty(kAudioSessionProperty_AudioRouteDescription, &dataSize, &currentRouteDescriptionDictionary); 
    if (currentRouteDescriptionDictionary) { 
     CFArrayRef outputs = CFDictionaryGetValue(currentRouteDescriptionDictionary, kAudioSession_AudioRouteKey_Outputs); 
     if(CFArrayGetCount(outputs) > 0) { 
      CFDictionaryRef currentOutput = CFArrayGetValueAtIndex(outputs, 0); 
      CFStringRef outputType = CFDictionaryGetValue(currentOutput, kAudioSession_AudioRouteKey_Type); 

      if ((CFStringCompare(outputType, kAudioSessionOutputRoute_AirPlay, 0) == kCFCompareEqualTo)) {    // if Airplay 
       NSLog(@"] Logic: output changed to Airplay"); 
      } 
      else if ((CFStringCompare(outputType, kAudioSessionOutputRoute_BluetoothA2DP, 0) == kCFCompareEqualTo)) {  // if Bluetooth A2DP 
       NSLog(@"] Logic: output changed to A2DP"); 

       // Mix with others category 
       UInt32 doSetProperty = 1; 
       AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers,sizeof(doSetProperty),&doSetProperty); 

       // Bluetooth support enable 
       UInt32 allowBluetoothInput = 1; 
       AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryEnableBluetoothInput,sizeof (allowBluetoothInput),&allowBluetoothInput); 


      } 
      else if ((CFStringCompare(outputType, kAudioSessionOutputRoute_BluetoothHFP, 0) == kCFCompareEqualTo)) {  // if Bluetooth HFP 
       NSLog(@"] Logic: output changed to HFP"); 
       // Mix with others category 
       UInt32 doSetProperty = 1; 
       AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers,sizeof(doSetProperty),&doSetProperty); 

       // Bluetooth support enable 
       UInt32 allowBluetoothInput = 1; 
       AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryEnableBluetoothInput,sizeof (allowBluetoothInput),&allowBluetoothInput); 
      } 
      else if ((CFStringCompare(outputType, kAudioSessionOutputRoute_LineOut, 0) == kCFCompareEqualTo)) {   // if Line Out 
       NSLog(@"] Logic: output changed to Line Out"); 
      } 
      else if ((CFStringCompare(outputType, kAudioSessionOutputRoute_Headphones, 0) == kCFCompareEqualTo)) {  // if Headphones 
       NSLog(@"] Logic: output changed to Headphone"); 

       // Mix with others category 
       UInt32 doSetProperty = 1; 
       AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers,sizeof(doSetProperty),&doSetProperty); 

       // Bluetooth support disable 
       UInt32 allowBluetoothInput = 0; 
       AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryEnableBluetoothInput,sizeof (allowBluetoothInput),&allowBluetoothInput); 

      } 
      else if ((CFStringCompare(outputType, kAudioSessionOutputRoute_BuiltInSpeaker, 0) == kCFCompareEqualTo)) { // if Built In Speaker 
       NSLog(@"] Logic: output changed to Built In Speaker"); 

       // Mix with others category 
       UInt32 doSetProperty = 1; 
       AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers,sizeof(doSetProperty),&doSetProperty); 

      } 
      else if ((CFStringCompare(outputType, kAudioSessionOutputRoute_USBAudio, 0) == kCFCompareEqualTo)) {   // if USB audio 
       NSLog(@"] Logic: output changed to USB Audio"); 
      } 
      else if ((CFStringCompare(outputType, kAudioSessionOutputRoute_HDMI, 0) == kCFCompareEqualTo)) {    // if HDMI 
       NSLog(@"] Logic: output changed to HDMI"); 
      } 
      else if ((CFStringCompare(outputType, kAudioSessionOutputRoute_BuiltInReceiver, 0) == kCFCompareEqualTo)) { // if Built in Reciever 
       NSLog(@"] Logic: output changed to Built in Reciever"); 

       // Mix with others category 
       UInt32 doSetProperty = 1; 
       AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers,sizeof(doSetProperty),&doSetProperty); 
      } 
      else {                           // Unknown audio type 
       NSLog(@"] Logic: WARNING: Unknown audio type: %@",(NSString*)outputType); 
      } 
     } 



    } 

    // ************************************************************************************************ 
    // Check audio route ****************************************************************************** 
    // ************************************************************************************************ 
    UInt32 routeSize = sizeof(CFStringRef); 
    CFStringRef route; 
    AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &routeSize, &route); 
    NSLog(@"] Logic: the audio route is: %@",(NSString*)route); 


    // ************************************************************************************************ 
    NSLog(@"]--------------------------[ ]-----------------------------[");   

} 

}

+0

trong trình mô phỏng iOS 8, bạn cần thay đổi: if (CFArrayGetCount (đầu ra)> 0) thành: if (output && CFArrayGetCount (output)> 0) –

3

Kể từ táo làm thay đổi hệ thống âm thanh một lần nữa bắt đầu từ 7.0 Tôi sẽ đăng mã cập nhật trên đây:

#pragma mark Route change listener 
// ********************************************************************************************************* 
// *********** Route change listener *********************************************************************** 
// ********************************************************************************************************* 
-(void)routeChanged:(NSNotification*)notification { 

    NSLog(@"]-----------------[ Audio Route Change ]--------------------["); 

    AVAudioSession *session = [AVAudioSession sharedInstance]; 

    //AVAudioSessionRouteDescription* prevRoute = [[notification userInfo] objectForKey:AVAudioSessionRouteChangePreviousRouteKey]; 

    // Reason 
    NSInteger reason = [[[notification userInfo] objectForKey:AVAudioSessionRouteChangeReasonKey] integerValue]; 
    switch (reason) { 
     case AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory: 
      NSLog(@"] Audio Route: The route changed because no suitable route is now available for the specified category."); 
      break; 
     case AVAudioSessionRouteChangeReasonWakeFromSleep: 
      NSLog(@"] Audio Route: The route changed when the device woke up from sleep."); 
      break; 
     case AVAudioSessionRouteChangeReasonOverride: 
      NSLog(@"] Audio Route: The output route was overridden by the app."); 
      break; 
     case AVAudioSessionRouteChangeReasonCategoryChange: 
      NSLog(@"] Audio Route: The category of the session object changed."); 
      break; 
     case AVAudioSessionRouteChangeReasonOldDeviceUnavailable: 
      NSLog(@"] Audio Route: The previous audio output path is no longer available."); 
      break; 
     case AVAudioSessionRouteChangeReasonNewDeviceAvailable: 
      NSLog(@"] Audio Route: A preferred new audio output path is now available."); 
      break; 
     case AVAudioSessionRouteChangeReasonUnknown: 
      NSLog(@"] Audio Route: The reason for the change is unknown."); 
      break; 
     default: 
      NSLog(@"] Audio Route: The reason for the change is very unknown."); 
      break; 
    } 

    // Output 
    AVAudioSessionPortDescription *output = [[session.currentRoute.outputs count]?session.currentRoute.outputs:nil objectAtIndex:0]; 
    if ([output.portType isEqualToString:AVAudioSessionPortLineOut]) { 
     NSLog(@"] Audio Route: Output Port: LineOut"); 
    } 
    else if ([output.portType isEqualToString:AVAudioSessionPortHeadphones]) { 
     NSLog(@"] Audio Route: Output Port: Headphones"); 
    } 
    else if ([output.portType isEqualToString:AVAudioSessionPortBluetoothA2DP]) { 
     NSLog(@"] Audio Route: Output Port: BluetoothA2DP"); 
    } 
    else if ([output.portType isEqualToString:AVAudioSessionPortBuiltInReceiver]) { 
     NSLog(@"] Audio Route: Output Port: BuiltInReceiver"); 
    } 
    else if ([output.portType isEqualToString:AVAudioSessionPortBuiltInSpeaker]) { 
     NSLog(@"] Audio Route: Output Port: BuiltInSpeaker"); 
    } 
    else if ([output.portType isEqualToString:AVAudioSessionPortHDMI]) { 
     NSLog(@"] Audio Route: Output Port: HDMI"); 
    } 
    else if ([output.portType isEqualToString:AVAudioSessionPortAirPlay]) { 
     NSLog(@"] Audio Route: Output Port: AirPlay"); 
    } 
    else if ([output.portType isEqualToString:AVAudioSessionPortBluetoothLE]) { 
     NSLog(@"] Audio Route: Output Port: BluetoothLE"); 
    } 
    else { 
     NSLog(@"] Audio Route: Output Port: Unknown: %@",output.portType); 
    } 

    // Input 
    AVAudioSessionPortDescription *input = [[session.currentRoute.inputs count] ? session.currentRoute.inputs:nil objectAtIndex:0]; 

    if ([input.portType isEqualToString:AVAudioSessionPortLineIn]) { 
     NSLog(@"] Audio Route: Input Port: LineIn"); 
    } 
    else if ([input.portType isEqualToString:AVAudioSessionPortBuiltInMic]) { 
     NSLog(@"] Audio Route: Input Port: BuiltInMic"); 
    } 
    else if ([input.portType isEqualToString:AVAudioSessionPortHeadsetMic]) { 
     NSLog(@"] Audio Route: Input Port: HeadsetMic"); 
    } 
    else if ([input.portType isEqualToString:AVAudioSessionPortBluetoothHFP]) { 
     NSLog(@"] Audio Route: Input Port: BluetoothHFP"); 
    } 
    else if ([input.portType isEqualToString:AVAudioSessionPortUSBAudio]) { 
     NSLog(@"] Audio Route: Input Port: USBAudio"); 
    } 
    else if ([input.portType isEqualToString:AVAudioSessionPortCarAudio]) { 
     NSLog(@"] Audio Route: Input Port: CarAudio"); 
    } 
    else { 
     NSLog(@"] Audio Input Port: Unknown: %@",input.portType); 
    } 

    NSLog(@"]--------------------------[ ]-----------------------------["); 

} 

Nhớ thêm người quan sát từ đại biểu của phiên âm thanh e bị phản đối quá:

[[NSNotificationCenter defaultCenter] addObserver: self 
               selector: @selector(audioInterruption:) 
                name: AVAudioSessionInterruptionNotification 
                object: nil]; 

PS: bạn không cần phải thiết lập lại các loại ở đây (như trong 6.0)

Các vấn đề liên quan