34

I'm recording audio with AVAudioRecorder as seen in How do I record audio on iPhone with AVAudioRecorder?

I then use AVAudioPlayer to play back the recording. However the sound is coming out of the ear speaker, not the loud speaker. How would I go about redirecting the sound to the loud speaker ?

TIA!

Community
  • 1
  • 1
dizy
  • 7,951
  • 10
  • 53
  • 54

11 Answers11

33

I realize this question is fairly old but when I was struggling with the same problem I found a simple solution that hopefully will help anyone else looking to use the louder media speakers as opposed to the receiver speakers. The method I used was setting up the audio session with the DefaultToSpeaker option in AVAudioSessionCategoryOptions:

In Swift (assuming your audio session is named session) -

session.setCategory(AVAudioSessionCategoryPlayAndRecord, withOptions:AVAudioSessionCategoryOptions.DefaultToSpeaker, error: nil)

In Obj-C -

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error: nil];
Daniel
  • 331
  • 3
  • 3
18

From http://www.iphonedevsdk.com/forum/iphone-sdk-development-advanced-discussion/12890-audiosessionsetproperty-problem-playing-sound-listening-mic.html --

UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory);    
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
  • 8
    A note to others who come across this answer: the first two lines in the sample code are irrelevant - and, if you're like the OP (who is ALSO recording audio), these lines will prevent the recording from functioning properly. – Steve Oct 06 '12 at 02:37
  • 1
    This worked for me with one adjustment: I changed sessionCategory to be kAudioSessionCategory_PlayAndRecord. – Jacob Jan 24 '13 at 21:45
  • I have seen this solution several times but I just do not know where to place that piece of code. Can Someone please tell me? – meda Apr 30 '13 at 22:49
  • 1
    `AudioSessionSetProperty` is deprecated in iOS7. How to do it now? – Hubert OG Mar 11 '14 at 12:01
  • 5
    In iOS7 you can do [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil]; – Ernest Jun 16 '14 at 05:55
  • The bottom 2 lines worked like charm! Just add them before calling play. – Prasad Pawar Feb 01 '16 at 13:00
  • `[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayBack error:nil]; ` did it for me in iOS 9 – NSNoob May 21 '16 at 13:30
17

Swift 3

Before recording the sound I set:

AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)

and before playback I set:

AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient)

Objective C

before recording:

[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryRecord error:nil];

before playback:

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
budiDino
  • 13,044
  • 8
  • 95
  • 91
  • Only change the category if it fit your user case. To `AVAudioSessionCategoryAmbient `, apple says "The category for an app in which sound playback is nonprimary—that is, your app can be used successfully with the sound turned off.This category is also appropriate for “play along” style apps, such as a virtual piano that a user plays while the Music app is playing. When you use this category, audio from other apps mixes with your audio. Your audio is silenced by screen locking and by the Silent switch". – KudoCC Sep 24 '15 at 09:54
  • It's strange that this is the only one that worked for me. Although I'm building a song recording app so I'd rather not use Ambient but none of the other answers work. This is the only one that forced the use of device speakers instead of the phone call (small speaker). The volume is still kind of lower than I'd want it to be. – C0D3 Sep 27 '20 at 00:49
13

This works great for me in Swift2

let session = AVAudioSession.sharedInstance()
try! session.setCategory(AVAudioSessionCategoryPlayAndRecord, withOptions: AVAudioSessionCategoryOptions.DefaultToSpeaker)
Spencer Powell
  • 139
  • 1
  • 5
6

This is an old question, but the other answer did not help me... However, I found a solution which I am posting for future reference in case someone (or myself from the future!) needs it.

The solution is described in the following blog post: iOS: Force audio output to speakers while headphones are plugged in .

You need to create new Objective-C class AudioRouter in your project. Then import AudioRouter.h into your header file of the class where you are initiating audio functionality. Next, in the corresponding .m file add the following lines within viewDidLoad method:

AudioRouter *foobar = [[AudioRouter alloc] init];
[foobar initAudioSessionRouting];
[foobar forceOutputToBuiltInSpeakers];

Now you have audio (e.g. AVAudioPlayer) output forced to loudspeaker! Note that if you plug in earphones while the app is running, then all audio output is directed to earphones.

Simo A.
  • 1,330
  • 13
  • 18
6

Swift2:

try session.setCategory(AVAudioSessionCategoryPlayAndRecord,
    withOptions:AVAudioSessionCategoryOptions.DefaultToSpeaker)
Kristian
  • 21,204
  • 19
  • 101
  • 176
3

Swift 5

// Get the singleton instance.
let recordingSession = AVAudioSession.sharedInstance()
do {
    // Set the audio session category, mode, and options.
    try recordingSession.setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker])
    try recordingSession.setActive(true)
} catch {
    print("Failed to set audio session category.")
}

Check the Developer Documentation for more information about AVAudioSession.CategoryOptions.

keishinzzz
  • 113
  • 1
  • 10
2

Swift 5: To work on both Bluetooth devices and default speaker use this:

let recordingSession = AVAudioSession.sharedInstance()
try recordingSession.setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker, .allowBluetooth])
anas.p
  • 2,246
  • 19
  • 26
1

Swift 3

 let audioSession = AVAudioSession.sharedInstance()

    do {
        try audioSession.overrideOutputAudioPort(AVAudioSessionPortOverride.speaker)
    } catch let error as NSError {
        print("Audio Session error: \(error.localizedDescription)")
    }
iOS.Lover
  • 5,923
  • 21
  • 90
  • 162
1

Answer For Swift 4.0

func SetSessionPlayerOn()
{
    do {
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)
    } catch _ {
    }
    do {
        try AVAudioSession.sharedInstance().setActive(true)
    } catch _ {
    }
    do {
        try AVAudioSession.sharedInstance().overrideOutputAudioPort(AVAudioSessionPortOverride.speaker)
    } catch _ {
    }
}
func SetSessionPlayerOff()
{
    do {
        try AVAudioSession.sharedInstance().setActive(false)
    } catch _ {
    }
}
Ali Pishvaee
  • 303
  • 5
  • 7
1

this is the key line to output auido in speaker instead in microphone. Note it should be set while recording

try AVAudioSession.sharedInstance().overrideOutputAudioPort(AVAudioSessionPortOverride.speaker)

Below is complete function to setup recording

private func setupRecorder() {

    if isAudioRecordingGranted {
        let session = AVAudioSession.sharedInstance()
        do {

            if #available(iOS 10.0, *) {
                try! session.setCategory(.playAndRecord, mode:.spokenAudio)
            }
            else {
                // Workaround until https://forums.swift.org/t/using-methods-marked-unavailable-in-swift-4-2/14949 isn't fixed
               session.perform(NSSelectorFromString("setCategory:error:"), with: AVAudioSession.Category.playback)
            }
            try session.setActive(true)
            try session.overrideOutputAudioPort(AVAudioSession.PortOverride.speaker)

            let settings = [
                AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
                AVSampleRateKey: 44100,
                AVNumberOfChannelsKey: 2,
                AVEncoderAudioQualityKey:AVAudioQuality.high.rawValue
            ]
            audioRecorder = try AVAudioRecorder(url: fileUrl(), settings: settings)
            audioRecorder.delegate = self
            audioRecorder.isMeteringEnabled = true
            audioRecorder.prepareToRecord()
            self.recorderState = .Ready
        }
        catch let error {
            recorderState = .error(error)
        }
    }
    else {
        recorderState = .Failed("Don't have access to use your microphone.")
    }
}
Waseem Sarwar
  • 2,645
  • 1
  • 21
  • 18