FMOD version: 2.03.08
Platform: iOS (Core API). Reproduced on both iOS Simulator (iPhone 17 Pro, Simulator runtime iOS 26.5 and 27.0) and a physical device (iOS 26.6.1).
System::createSound / createStream against any HTTPS URL fails on the first attempt. The failure happens immediately after SystemI::createSoundInternal, before any meaningful data transfer with:
[LOG] FMOD_OS_Net_Read : Connection reset by peer.
or:
*** Error: End of file unexpectedly reached while trying to read essential data (truncated?).
The same request succeeds instantly and completely over plain HTTP (no TLS), and the platform’s own TLS stack (Safari, curl) succeeds against the exact same HTTPS endpoint, from the same device, on the same network, at the same time. This (I think) means the failure is in FMOD’s own TLS/HTTPS client rather than anything server- or network-side.
I built a minimal repro (FMOD’s bundled 3d Core API example, modified only in sound-loading code) and systematically eliminated every variable I could think of:
- http 1.1 vs 2.0
- tls 1.2 vs 1.3
- mp4 vs mp3
- using nonblockcallback
- Certificate trust (safari worked fine)
- Simulator vs physical device
- different backend serving the data (local python server vs GCS)
Is this a known issue?
Is this an internal issue and could you confirm it’s working (or not) your end?
Code example below:
/*==============================================================================
3D Example
Copyright (c), Firelight Technologies Pty, Ltd 2004-2025.
This example shows how to basic 3D positioning of sounds.
For information on using FMOD example code in your own programs, visit
https://www.fmod.com/legal
==============================================================================*/
#include "fmod.hpp"
#include "fmod_errors.h"
#include "common.h"
const int INTERFACE_UPDATETIME = 50; // 50ms update for interface
const float DISTANCEFACTOR = 1.0f; // Units per meter. I.e feet would = 3.28. centimeters would = 100.
int FMOD_Main()
{
FMOD::System *system;
FMOD::Sound *sound1, *sound2, *sound3;
FMOD::Channel *channel1 = 0, *channel2 = 0, *channel3 = 0;
FMOD_RESULT result;
bool listenerflag = true;
FMOD_VECTOR listenerpos = { 0.0f, 0.0f, -1.0f * DISTANCEFACTOR };
void *extradriverdata = 0;
int outputrate;
int fade_ms = 2000;
Common_Init(&extradriverdata);
/*
Create a System object and initialize.
*/
result = FMOD::System_Create(&system);
ERRCHECK(result);
result = system->init(100, FMOD_INIT_NORMAL, extradriverdata);
ERRCHECK(result);
/*
Set the distance units. (meters/feet etc).
*/
result = system->set3DSettings(1.0, DISTANCEFACTOR, 1.0f);
ERRCHECK(result);
/*
Load some sounds
*/
result = system->createStream("https://dolphin.echoes.xyz/sounds/68cacdf906a55799ea050aa9/k60sus7ovj1yc2mw.mp4",
FMOD_3D, 0, &sound1);
ERRCHECK(result);
result = sound1->set3DMinMaxDistance(0.5f * DISTANCEFACTOR, 5000.0f * DISTANCEFACTOR);
ERRCHECK(result);
result = sound1->setMode(FMOD_LOOP_NORMAL);
ERRCHECK(result);
result = system->createSound(Common_MediaPath("jaguar.wav"), FMOD_3D, 0, &sound2);
ERRCHECK(result);
result = sound2->set3DMinMaxDistance(0.5f * DISTANCEFACTOR, 5000.0f * DISTANCEFACTOR);
ERRCHECK(result);
result = sound2->setMode(FMOD_LOOP_NORMAL);
ERRCHECK(result);
result = system->createSound(Common_MediaPath("swish.wav"), FMOD_2D, 0, &sound3);
ERRCHECK(result);
result = system->getSoftwareFormat(&outputrate, 0, 0);
/*
Play sounds at certain positions
*/
{
FMOD_VECTOR pos = { -10.0f * DISTANCEFACTOR, 0.0f, 0.0f };
FMOD_VECTOR vel = { 0.0f, 0.0f, 0.0f };
result = system->playSound(sound1, 0, true, &channel1);
ERRCHECK(result);
result = channel1->set3DAttributes(&pos, &vel);
ERRCHECK(result);
result = channel1->setPaused(false);
ERRCHECK(result);
result = channel1->setVolume(0.5f);
}
{
FMOD_VECTOR pos = { 15.0f * DISTANCEFACTOR, 0.0f, 0.0f };
FMOD_VECTOR vel = { 0.0f, 0.0f, 0.0f };
result = system->playSound(sound2, 0, true, &channel2);
ERRCHECK(result);
result = channel2->set3DAttributes(&pos, &vel);
ERRCHECK(result);
result = channel2->setPaused(false);
ERRCHECK(result);
}
/*
Main loop
*/
do
{
Common_Update();
if (Common_BtnPress(BTN_ACTION1))
{
unsigned long long parentclock;
channel1->getDSPClock(nullptr, &parentclock);
bool isplaying;
result = channel1->isPlaying(&isplaying);
if (!isplaying) {
result = system->playSound(sound1, 0, true, &channel1);
ERRCHECK(result);
}
float volume;
result = channel1->getVolume(&volume);
ERRCHECK(result);
printf("Volume is %f", volume);
bool paused;
result = channel1->getPaused(&paused);
ERRCHECK(result);
unsigned int numpoints;
result = channel1->getFadePoints(&numpoints, nullptr, nullptr);
if (numpoints > 0) {
unsigned long long point_dspclock[numpoints];
float point_volume[numpoints];
result = channel1->getFadePoints(&numpoints, point_dspclock, point_volume);
if (result != FMOD_OK) {
ERRCHECK(result);
return;
}
// it was faded
paused = true;
}
// Clear existing fade points first
result = channel1->removeFadePoints(0, __LONG_MAX__);
ERRCHECK(result);
if (paused) {
// Fade in from pause
unsigned long long fadeOffset = (outputrate * fade_ms) / 1000;
unsigned long long fadePoint = parentclock + fadeOffset;
result = channel1->setDelay(0, 0);
ERRCHECK(result);
// Set up fade in
result = channel1->addFadePoint(parentclock, 0.0f);
ERRCHECK(result);
result = channel1->addFadePoint(fadePoint, 1.0f);
ERRCHECK(result);
channel1->setPaused(false);
} else {
// Fade out and pause
unsigned long long parentclock;
result = channel1->getDSPClock(nullptr, &parentclock);
ERRCHECK(result);
unsigned long long fadeOffset = (outputrate * fade_ms) / 1000;
unsigned long long fadePoint = parentclock + fadeOffset;
// Set up fade out
result = channel1->addFadePoint(parentclock, 1.0f);
ERRCHECK(result);
result = channel1->addFadePoint(fadePoint, 0.0f);
ERRCHECK(result);
// Use a callback or timer to pause after fade completes
result = channel1->setDelay(0, fadePoint - 10); // +10ms buffer
ERRCHECK(result);
}
}
if (Common_BtnPress(BTN_ACTION2))
{
bool paused;
channel2->getPaused(&paused);
channel2->setPaused(!paused);
}
if (Common_BtnPress(BTN_ACTION3))
{
result = system->playSound(sound3, 0, false, &channel3);
ERRCHECK(result);
}
if (Common_BtnPress(BTN_MORE))
{
listenerflag = !listenerflag;
}
if (!listenerflag)
{
if (Common_BtnDown(BTN_LEFT))
{
listenerpos.x -= 1.0f * DISTANCEFACTOR;
if (listenerpos.x < -24 * DISTANCEFACTOR)
{
listenerpos.x = -24 * DISTANCEFACTOR;
}
}
if (Common_BtnDown(BTN_RIGHT))
{
listenerpos.x += 1.0f * DISTANCEFACTOR;
if (listenerpos.x > 23 * DISTANCEFACTOR)
{
listenerpos.x = 23 * DISTANCEFACTOR;
}
}
}
// ==========================================================================================
// UPDATE THE LISTENER
// ==========================================================================================
{
static float t = 0;
static FMOD_VECTOR lastpos = { 0.0f, 0.0f, 0.0f };
FMOD_VECTOR forward = { 0.0f, 0.0f, 1.0f };
FMOD_VECTOR up = { 0.0f, 1.0f, 0.0f };
FMOD_VECTOR vel;
if (listenerflag)
{
listenerpos.x = (float)sin(t * 0.05f) * 24.0f * DISTANCEFACTOR; // left right pingpong
}
// ********* NOTE ******* READ NEXT COMMENT!!!!!
// vel = how far we moved last FRAME (m/f), then time compensate it to SECONDS (m/s).
vel.x = (listenerpos.x - lastpos.x) * (1000 / INTERFACE_UPDATETIME);
vel.y = (listenerpos.y - lastpos.y) * (1000 / INTERFACE_UPDATETIME);
vel.z = (listenerpos.z - lastpos.z) * (1000 / INTERFACE_UPDATETIME);
// store pos for next time
lastpos = listenerpos;
result = system->set3DListenerAttributes(0, &listenerpos, &vel, &forward, &up);
ERRCHECK(result);
t += (30 * (1.0f / (float)INTERFACE_UPDATETIME)); // t is just a time value .. it increments in 30m/s steps in this example
}
result = system->update();
ERRCHECK(result);
// Create small visual display.
char s[80] = "|.............<1>......................<2>.......|";
s[(int)(listenerpos.x / DISTANCEFACTOR) + 25] = 'L';
Common_Draw("==================================================");
Common_Draw("3D Example.");
Common_Draw("Copyright (c) Firelight Technologies 2004-2025.");
Common_Draw("==================================================");
Common_Draw("");
Common_Draw("Press %s to toggle sound 1 (16bit Mono 3D)", Common_BtnStr(BTN_ACTION1));
Common_Draw("Press %s to toggle sound 2 (8bit Mono 3D)", Common_BtnStr(BTN_ACTION2));
Common_Draw("Press %s to play a sound (16bit Stereo 2D)", Common_BtnStr(BTN_ACTION3));
Common_Draw("Press %s or %s to move listener in still mode", Common_BtnStr(BTN_LEFT), Common_BtnStr(BTN_RIGHT));
Common_Draw("Press %s to toggle listener auto movement", Common_BtnStr(BTN_MORE));
Common_Draw("Press %s to quit", Common_BtnStr(BTN_QUIT));
Common_Draw("");
Common_Draw(s);
Common_Sleep(INTERFACE_UPDATETIME - 1);
} while (!Common_BtnPress(BTN_QUIT));
/*
Shut down
*/
result = sound1->release();
ERRCHECK(result);
result = sound2->release();
ERRCHECK(result);
result = sound3->release();
ERRCHECK(result);
result = system->close();
ERRCHECK(result);
result = system->release();
ERRCHECK(result);
Common_Close();
return 0;
}