Difficulty reading content of raw audio file

Posted on
  • I am trying to read the content of a raw audio file into the trace. I would much rather the ability to read in chunks (of my choosing), but from looking at the API it would suggest (to me) that it's an all or nothing operation. Anyway, I wanted to confirm the content is reading in the way I am expecting (I am porting a PIC project over).

    I have the following code

    var fs = require('fs');
    var files = fs.readdir();
    if (files.length > 0) {
      var filename = files[0];
      var content = fs.readFileSync(filename);

    Now I am seeing the filename is correct, however the WebIDE hangs when it comes to doing the trace for the file content. It will not even let me disconnect. After 5 minutes of nothing, I hit the reset button, and it's back to normal...

    I would like to assume that it's trying to read the entire file into memory and then falling over.

    Am I doing something wrong? Any suggestions?

  • How big is the file?

    I'm not sure why the web IDE would crash - but it's possible that it's because trace is outputting the string contents on a single line. Trace wasnt really meant for dumping such large amounts of data. Personally I'd just use content.length and content. substr to check small parts of the string are correct.

    I'm planning on adding partial read support - but that may be a while away...

  • This specific file is 438KB in size, so it's not "massive" by any means, but perhaps it's a bit too big to load in one go? I've not actually looked too deep into how much this chip can handle, so just taking wild assumptions based on me getting this working on a cheap PIC16F1825!

    I tried doing a trace on content.length instead of content itself, and unfortunately that gave the same results. I then decided to let it read the file into a variable, but do nothing with it, but instead start to blink an LED, and it does not seem to get as far as blinking the LED. If I remove the readFileSync() line, the LED blinks fine. So it would appear that it's having trouble with that one method rather than the trace() method.

    As for partial read... I'm more than happy doing some substr on the data to view specific chunks at a time (for now), just so I can confirm it is reading what I am expecting before I try to start sending it in chunks to a small speaker over PWM.

  • The chip has 48kB of Ram, and you're tying to load the file in one go - so it's unlikely to work very well :) the fact that it crashes is bad though and I'll try and look into that.

    Honestly I think you're going to have trouble playing the audio back even if I do end up implementing a way to stream from files. I've been pretty clear about Espruino not being great for audio and I don't think it'll be very good at this until I implement a way to push the contents of an array out using irqs I'm afraid...

  • I currently having it working on a PIC16F1825 along with code to read FAT16 on an SD card, which is only 14kB of RAM, so I was kind of assuming that the Espruino would be able to cope as it's got a much more powerful MCU...

    If it was possible to essentially add the following pseudo code, I'm pretty sure it would work!

    var fs = require('fs');
    var filePointer = fs.loadFile('filename.raw'); // Does not load the file, simply keeps reference to the file.
    var data = filePointer.readByte(0); // reads the first byte
    data = filePointer.readByte(24); //skips 24 bytes, reads 1 more byte
    // or readBytes(skip, take); but 1 byte at a time is how my current code works

    Is the problem with how your JavaScript handler is relaying the commands to the MCU, or what's the actual issue? Maybe I can help and send pull some pull requests?

  • I am currently working on an implementation of a Stream like interface. Now that I have the ability to build and flash my own Espruino image, I don't think it will take long.
    My need is for streaming MP3 encoded sound data over a serial port to a card that will decode and play them. I also need streaming for sending file data over HTTP to browser clients. It seems like the same interface would work for you as well.

  • Hi cephdon, that'd be awesome! Could you try and make it like node's filesystem api please? The only issue I see is storing the FILE structure - I guess you could do it the same way the graphics class does.

    Cyber-lane, the other issue is trying to change the PWM frequency fast enough for audio (note that if this wasn't a problem, Espruino also has 2 DACs). You can get around 4kHz with setInterval I believe, but getting much faster is going to be tricky, even in a tight loop. That's why I suggested I'll have to implement an api that allows you to use interrupts to send a buffer to a peripheral.

    Also it looks like the PIC is 32Mhz - I know the processor isn't as good as a 72MHz ARM but you've got to make a lot of allowances for the fact that it's running an interpreter rather than native code.

    Even so with 1kb of ram it must be right on the edge of what's possible when using FAT. The buffers in Espruino come to around 600 bytes.

  • Note: you could use peek and poke to set up DMA, and could send data out that way. A library for that would be awesome :)

  • Funnily enough, similar to cephdon, I am also looking to add MP3, but I thought I would get my RAW audio working first as it's much simpler. That said, the MP3 decoders I use are pretty much the same setup, but instead of sending the raw data via PWM to a speaker, you send the raw data to the IC, wait for it to say "I'm full" and stop, wait for it to say "I'm ready for more" and send more.

    Anyway, you are right... the interpreter would take up a fair amount of from the general performance. I suppose I was kind of expecting magic, allowing me to convert all my low level C into easier to read/maintain JavaScript (wishful thinking!).

    Anyway, if cephdon is working on getting Stream support, then I might just wait! That said, I would be quite keen on getting the Espruino code compiling on one of my dev boxes as well, so I can try contribute some C back, and not just a load of JavaScript libraries.

    Thanks for the replies chaps!

  • Gordon,
    No worries. I have been looking over their FS API and I am planning to make it the same.
    The approach I was going to take with the FILE structure is very similar to how the graphics class works. I will try to mimic the style that you use everywhere else so that the code is uniform. :-)

  • @Gordon, you suggested peek and poke, how can we tell which addresses are safer than others?

  • @randunel process.memory() has some addresses in it and there's a bit of info here: http://www.espruino.com/STM32F1Flash

    What I meant by peek/poke though was setting up the DMA peripheral in the chip. For that, you'd need to look at the chip's datasheet to find the addresses that you needed.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

Difficulty reading content of raw audio file

Posted by Avatar for Cyber-Lane @Cyber-Lane