#Playing sounds without pausing a loop

1 messages · Page 1 of 1 (latest)

green dune
#

I'm not wedded to .play_tone(), and indeed eventually want to use something with a range of timbres. I just need to be able to play notes on the fly (the idea is to make something like a step sequencer).

#

Also, if you're curious about the philosophy, check the README in the repo. The goal is to build an ecosystem like logo, but adapted to circuitpython and more music / less geometry

vestal plume
#

@green dune Consider asyncio. Its Cooperative MultiTasking. Seemly allows multiple tasks to run simultaneously ( seemly being the operative word). Example: One can have two co-routines each controlling its own LED. So routine 1 might control Blinka, while routine 2 might control PlayTune.

green dune
#

I'll try that, thanks... Wasn't sure if play_tone would play well with async. I'll report back!

hoary glen
green dune
#

.play_tone() is indeed blocking. So I had a quick look, and there is also a .start_tone() and .end_tone() approach, which let me do a "good enough" fix to play songs without interrupting blinka, as seen here: https://github.com/davclark/pygamer-constructionism/blob/c0a4c43fd0adebcd73677b3990ada9f79dfed827/musical_snake/code.py#L24

That said, it still feels janky for a musical thing, which I think is due to the resolution of the event loop. So, I shall now proceed to split the display / joystick logic from the sound logic via asyncio.

GitHub

Experiments in constructionism and community with a focus on the Adafruit PyGamer - pygamer-constructionism/code.py at c0a4c43fd0adebcd73677b3990ada9f79dfed827 · davclark/pygamer-constructionism

#

Thank you both for the encouragement to look at asyncio! I use that professionally, so hopefully there won't be any weird gotchas and it'll "just work"

green dune
#

It did just work! Thanks again. (And I've pushed the async changes)

green dune
#

The last bit that would be nice - thinking down the road to using this as a "real" instrument - is something like an async display.refresh(). My guess is one of these interrupts could be used with countio to do this? In case anyone knows off the top of your head, I'd not mind a hint. Here's the list of attributes on board:

A0              A1              A2              A3
A4              A5              A6              A7
A8              A9              ACCELEROMETER_INTERRUPT
BUTTON_CLOCK    BUTTON_LATCH    BUTTON_OUT      D0
D1              D10             D11             D12
D13             D2              D3              D4
D5              D6              D7              D8
D9              DISPLAY         I2C             JOYSTICK_X
JOYSTICK_Y      LED             LIGHT           MISO
MOSI            NEOPIXEL        RX              SCK
SCL             SDA             SD_CS           SPEAKER
SPEAKER_ENABLE  SPI             STEMMA_I2C      TFT_CS
TFT_DC          TFT_LITE        TFT_MOSI        TFT_RST
TFT_SCK         TX              UART            board_id
#

Pretty sure that approach is not gonna work... those TFT pins are in use. Probably we need to get into the guts of the display driver.

#

After a casual look around, I think the effort for me to figure that out on my own is a bit high considering tight timing relative to the screen refresh is a "nice to have", and maybe that's not even a reliable clock anyway.

If the ability to async await a display refresh is of general interest (this is a relatively "normal" thing in game libraries), then I'd be happy to pair with someone who can get me oriented or whatever makes sense. No pressure and thanks!

hoary glen
green dune
#

No i just want a reliable time that i can keep the game synchronized to, so it functions well as an instrument. I haven't implemented it yet, but blinka will run over items that will make sounds. Right now, the movement loop is a constant async sleep (which is just a minimum) as well as the sprite update logic, which i guess could vary in time just a bit.

Above, i was also trying to say that timing will probably be good enough anyway... So i don't need a super reliable duration for each iteration of the loop

#

It's not clear if there is even a regular screen refresh (something like vsync) - the Display object attributes aren't all there on the pygamer

hoary glen
#

You could use supervisor.ticks_ms() or one of the time functions to get the time to calculate last frame vs now.