Want to seek to a position in a wave file

CircuitPython on hardware including Adafruit's boards, and CircuitPython libraries using Blinka on host computers.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
ntynen
 
Posts: 19
Joined: Sat May 28, 2022 10:15 pm

Want to seek to a position in a wave file

Post by ntynen »

Hello all,

I've been searching the forums and web and I want to make sure I'm not missing something.
I'm building a very simple book reader.
I want to be able to use the .tell() function to track progress in the book
In the even the reader loses power; I want the book reader to pick up where it left off by seeking to the position based on the last .tell() call - that will be written to a file on an SD card.

Hardware (current):
* qtpy ESP 32 Pico
* Micro SD BFF
* Adafruit I2S 3W Class D Amplifier Breakout - MAX98357A

I can get the wave file to play with this code:

Code: Select all

wav = open(wave_file, "rb")
wave = WaveFile(wav)

audio.play(wave)
If I try this:

Code: Select all

wav = open(wave_file, "rb")
wav.seek(seek_position)
wave = WaveFile(wav)
audio.play(wave)
the wav.seek() is completely ignored

if I try to remove audiocore.WaveFile:

Code: Select all

wav = open(wave_file, "rb")
wav.seek(seek_position)
audio.play(wav)
it returns TypeError:'FileIO object does not support 'protocol_audiosample'

If I try to use the adafruit_wave library:

Code: Select all

wav = adafruit_wave.open(wave_file, "rb")
wave = WavFile(wav)
audio.play(wave)
it returns TypeError: file must be file opened in byte mode

So far the only success I've had is to open the primary wave file, seek to a position in it, then write the remainder to a temporary file on the SD card then open that for reading.

Code: Select all

in_wav_file = adafruit_wave.open(wav_file, 'rb')
out_wav_file = adafruit_wave.open(tmp_file, 'wb')
in_wav_file.setpos(seek_position)
out_wav_file.setframerate(in_wav_file.getframerate())
out_wav_file.setnchannels(in_wav_file.getnchannels())
out_wav_file.setsampwidth(in_wav_file.getsampwidth())
frame_rate = in_wav_file.getframerate()
frames_to_read = int(frame_rate*bytes_read)
while frames_to_read > 0:
      chunk_size = min(frame_rate, frames_to_read)
      out_wav_file.writeframes(in_wav_file.readframes(chunk_size))
      frames_to_read -= chunk_size
 frames = in_wav_file.readframes(frame_rate)
 out_wav_file.writeframes(frames)
 in_wav_file.close()
 out_wav_file.close()
 
This is very, very, very slow :(

Can someone help me understand what I'm doing wrong when trying to use the seek() function or the adafruit_wave library?

Thanks,
Nicole

User avatar
tannewt
 
Posts: 3304
Joined: Thu Oct 06, 2016 8:48 pm

Re: Want to seek to a position in a wave file

Post by tannewt »

That sounds like a cool project! Unfortunately, I don't think audiocore.WaveFile was designed to take this into account. We've always assumed it was a song length file or a shorter sample. The code internally resets the file pointer to verify it is a wavefile and read the metadata from it.

Would you mind filing an issue about this on the CircuitPython repo? Thanks! https://github.com/adafruit/circuitpyth ... .md&title=

User avatar
ntynen
 
Posts: 19
Joined: Sat May 28, 2022 10:15 pm

Re: Want to seek to a position in a wave file

Post by ntynen »

Thank you so much for getting back to me on this. It is a relief to understand why I was having so much trouble.

I’d be happy to file an issue and will do it tomorrow.

I’ve been thinking it through and for now I’ll split the book into chapters (thank you OpenAudible for this feature) and then log which chapter is active. Worst case will be if the reader loses power it will start over on the active chapter.

If this feature request makes it into the audiocore library, I can modify the code to take full advantage of seek() and tell().

Thank you again for helping me!

User avatar
tannewt
 
Posts: 3304
Joined: Thu Oct 06, 2016 8:48 pm

Re: Want to seek to a position in a wave file

Post by tannewt »

That sounds like a good work around. It shouldn't be too hard for us to add support for starting in the middle of a file.

Locked
Please be positive and constructive with your questions and comments.

Return to “Adafruit CircuitPython”