C pow(), abs() crashes on real device

Hi, i recently experiences some issues on the real device with standard C math functions like pow(), abs(), etc. In the simulator, everything works fine, but as my .pdx is copied to the device, it crashes. Is there something i can do, or it is a bug?

Those functions should work fine on device, although you should probably use the float versions of the standard math functions (absf(), powf(), etc), since doubles are very slow on device. Are you sure it's the math functions causing the crashes?

2 Likes

Can you explain what you mean by

but as my .pdx is copied to the device, it crashes

Copying how? Does the game launch? Does the crash happen at the same point with every launch?

I mean, the app was uploaded with the simulator to run on the device, but as the uploaded app starts, it crashes. And yes, i made a simple test app, and by calling pow(), it crashes. However, powf() seems fine.

Does the app run any differently if you start it from the device launcher?

There's currently a bug launching apps with spaces in the name from a simulator upload.

In fact, I'm experiencing a strange issue, that I can't explain. Forget about pow(), abs(). There is a lot more :slight_smile: I'm working with a piece of code, that I successfully used on Mac/Win/Linux ports of my game. When the Playdate dev tools was released, I quickly made a port to test it on the Playdate simulator, and I was glad it worked just as expected. I recently got my Playdate device (which I love, thanks:), but as I try my code on the real device, it crashes just after it was launched. As I do not know about any debug tools on the actual device, I started commenting out big parts of the sourcecode, to get any idea which part is involved. But I got strange results, like creating an unsigned char array of 32 elements, and when filling the last element of it, It crashes. I still don't understand what can cause such issues, when compiling I do not get any errors, nor warnings, the code runs fine in the simulator, but crashes on real device. I will try to rebuild the whole application little by little, so I can maybe get some idea what goes wrong...

I uploaded a small app that plays a SID tune on the simulator, but crashes on real device.
Macc_PDTest.pdx.zip (33.0 KB)
(it was built on Mac M1)

If things were working properly you'd get a Run loop stalled for more than 10 seconds error on the screen and also in errorlog.txt, but for some reason that's not working right. I'm looking into it now. It might be because it's the audio task that's hanging and that has high priority, could be blocking the filesystem.

But yeah, audio is taking way too long to generate on the device. I put in a time check and the audio callback is taking around 41 ms each call. It runs in 256 sample chunks, so at 44100 Hz that's around 172 calls a second, meaning you've only 5.8 ms per call to keep up with audio output. :confused: Hopefully you can find some way to make that code run faster, maybe there are some features you can disable. If you're currently running the engine at 44kHz stereo, changing to 11kHz mono might get you under that threshold. (You'd have to do the sample rate conversion in code, we don't have a way to change the sample rate of the output device.)

1 Like

Thank you! This was very helpful.

I can now run the code without crashing, thanks again.

changing to 11kHz mono might get you under that threshold

I read the documentation for the audio, also the pd_api_sound.h, but I have no clue, how I could change the samplerate to 11kHz, and 8 bit. The sound playback is simply started by this single line of code:

ssrc = pd->sound->addSource(play, context, 0);

Is there any other documentation on this topic?

Yeah, sorry, reading this again I get that it wasn't very clear:

You'd have to do the sample rate conversion in code, we don't have a way to change the sample rate of the output device.

What I meant was if you get 11kHz/8bit data from the emulator, you'd then have to convert that to 44kHz/16bit in your own code, e.g.

int audioSource(void* context, int16_t* left, int16_t* right, int len)
{
	// caller wants 44kHz 16bit data, but sidemu provides 11kHz 8bit
	int8_t* data = alloca(len/4);
	
	// hypothetical sidemu_getData(int8_t* buffer, int buflen) returns 1 if active, 0 if finished
	if ( !sidemu_getData(data, len/4) )
		return 0;
	
	for ( int i = 0; i < len; i += 4 )
	{
		int16_t s = (int16_t)data[i/4] << 8;
		left[i] = right[i] = left[i+1] = right[i+1] = left[i+2] = right[i+2] = left[i+3] = right[i+3] = s;
	}
	
	return 1;
}

In actual usage you'll want to interpolate between samples instead of just copying each sample 4x, which generates bad aliasing noise. But this would be my first pass just to make sure everything is wired up correctly.

1 Like