Lua API: Binary IO

Recently, I've dreamed about writing a little voice recording app for Playdate but quickly discovered that many APIs are still missing (like: no direct access to buffers and their data, http(s) sockets, and many more). Writing apps like this became impossible right off the bat.

But I had faith in Lua and short after I've discovered a thread about wav files, with a code example on how the PCM data could be manipulated.
I've decided to play around with that idea for a bit, but once more, I've hit immediately another show stopper! (Seems like the example not really works, does it?)

Since there are no APIs to support me, I wanted to make my own workarounds. I'd record audio samples, save them as wave files and then read the raw BINARY contents of those wav file and parse them myself. However, playdate.file seems to only support playdate.file.kFileRead and playdate.file.kFileWrite (equivalent to "r" and "w").

I just wonder, what were the reasons for wrapping and crippling so many of Lua's wonderful native tools and capabilities? (Aside from concern of sandboxing applications.)


Could you add back the abilities to fully and freely work with files, please?!


Lua's greatest strengths are being super simple but VERY powerful and performant at the same time. Lua has only essential building blocks, but you could build almost anything with them, if you really want to. Some of these were added fairly recently, like full UTF-8 support and bitwise operations.

As a Lua enthusiast I was super exited when Panic announced a Lua API. But after looking around I realise it's not on par with the C-API (as was advertised). Moreover, I was kind of sad to see so many parts of Lua being shrunken down, removed entirely or abstracted away in a weird way.

I really hope you do NOT take this as an offence because it wasn't meant to be one. It's not a rant either. I just wanted to say, that Lua is a wonderful language. I think it and it's community deserve some love and attention. - With Playdate Console on the horizon, Lua could potentially have another Renaissance (and Panic's Community could benefit from this). But that will hardly happen, if we turn Lua into some weird Frankenstein monster...

Just my 2Cents.

We don't have text vs binary mode on files: You're always reading and writing the raw data, no weird CRLF translation or anything like that. (At least I think that's the case.. If it's doing that on Windows that's a bug.) That said, in the Lua API we're using its string type to wrap the data, and I don't know how well Lua's string functions handle generic binary data.

But the main reason we don't have what you're looking for is this just isn't going to work like you want. Lua's too slow on the device to process audio data of any reasonable size. This is a perfect use case for the C API, though. You have direct access to the file buffer there via

AudioSample* (*newSampleFromData)(uint8_t* data, SoundFormat format, uint32_t sampleRate, int byteCount);
void (*getData)(AudioSample* sample, uint8_t** data, SoundFormat* format, uint32_t* sampleRate, uint32_t* bytelength);

and you can easily (okay, yeah, if you know C) wrap your sample-processing functions in higher-level Lua code. I'll whip up an example over the weekend.

Overall I'd say the Lua API is much more developed. I almost always implement new features under the Lua API first because it's so much easier to test and iterate on and then if it's something that makes sense in the C API, if it's not something that someone could easily implement themselves, I'll add it there too. But the Lua API has a lot more convenience code. This is just one place where Lua isn't a good fit for the job, given CPU constraints.

Let me know if you have any specific requests for a C demo. How about a bit of hypothetical Lua code that you'd like to see work?

3 Likes

I was able to write a binary file parser by using Lua's string.unpack to operate on a file string. It ended up being way too slow for what I was trying to accomplish when it was running on the device, so I eventually switched to writing the parser in C anyway. I have a feeling it will be slow for working with audio too, but it could be worth a shot at least!

Thank you for answering, @dave! Very much appreciated!

Before writing my own wav parser I wanted to see if I could even grab the buffer data myself. To test this, I was temporarily using a wav parser that I found on the web, which I lightly modified to work with the Panic's Lua API.

(I have attached the code that I was using. Maybe I've broken it since last time I touched it, but generally this was my session:)
chirp.zip (10.1 KB)

However, I wasn't able to even read the bits from the 'voice.wav' file... hence why I created this feature request.

I'd be thankful, if you could show me how I can read the binary data from my wave file and debug it in the console. (Because right now I see nothing there.) From there I'd work my way through it and see if I hit any performance issues. (Maybe I can optimise it somehow or use coroutines to dynamically parse & load the sample buffer data over time. I don't know yet. Hard to say without actual hardware.)

Btw, I've seen the C API but I try to avoid it, tbh, because I really dislike C (mainly for it's pointers and syntax).