libsdl-org / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
10.2k stars 1.86k forks source link

COREAUDIO_OpenDevice on iOS ignores sample rate #9635

Open ivan-ushakov opened 7 months ago

ivan-ushakov commented 7 months ago

Function COREAUDIO_OpenDevice has following code:

AVAudioSession *session = [AVAudioSession sharedInstance];
[session setPreferredSampleRate:this->spec.freq error:nil];
this->spec.freq = (int)session.sampleRate;

It has several problems:

  1. Does not check if it was successful so you don't know if sample rate was changed
  2. Will fail to 48000 Hz in many cases

Is it possible to put this code under #if guard? Now if I use SDL_OpenAudio with sample rate 44100 Hz then I get 48000 Hz on my iPhone. If I remove that setPreferredSampleRate call then it works and I get 44100 Hz.

icculus commented 7 months ago

Do you actually get 44100Hz if you don't explicitly set that? It's a weird choice of defaults, and it's even weirder that explicitly asking for it gets you something different than not asking for it, if it is the default.

(We don't check for errors here because we don't care if it fails, since we have to take whatever frequency the session tells us in any case.)

ivan-ushakov commented 7 months ago

Do you actually get 44100Hz

Yes, I check obtained spec from SDL_OpenAudio() call. Also I checked how that code works on my device, and it looks like setPreferredSampleRate: returns YES, but when I print this->spec.freq after this line:

this->spec.freq = (int)session.sampleRate;
printf("this->spec.freq=%d\n", this->spec.freq);

I see 48000 Hz. Since you use spec.freq below to setup output source, you set it to 48000 Hz too:

/* Setup a AudioStreamBasicDescription with the requested format */
SDL_zerop(strdesc);
strdesc->mFormatID = kAudioFormatLinearPCM;
strdesc->mFormatFlags = kLinearPCMFormatFlagIsPacked;
strdesc->mChannelsPerFrame = this->spec.channels;
strdesc->mSampleRate = this->spec.freq;
strdesc->mFramesPerPacket = 1;