When does SCAMP create a wav file? (or help debugging from within Blender)

Hello,

I’m running Scamp from within Blender. I’m trying to spit out wav files from my script. It works once: I run the script, the sound plays, the wav file is written.

But when I rerun the script (creating a new session, etc), even though the notes are played, the wav files are not written. There are no errors or warnings.

How does Scamp know when to write the file? I find, tbh, the API for this a bit strange. I’d like to generate a session, maybe assign an output to it (perhaps with a timestamp for the name, etc), and when I play notes on it and the sessions end, I’d expect that file to be rewritten.

If I restart Blender it again works once.

Thanks,
Gabriel

It’s not a Blender thing, though. When I do this from IPython, for example, I have the same problem. I edit the script, it runs, I edit it again, it runs again but doesn’t save the file.

I suspect something is “kept alive” and is waiting to complete.

Curious if you try:

import atexit
atexit._run_exitfuncs()

I think it’s set up to save the wave file when the script exits, but perhaps Blender is keeping Python alive as you say.

Unfortunately, it didn’t like it. It crashes both IPython and Blender,

Here IPython,

Here Blender, – the errors don’t say much. It’s Blender trying to gracefully close (hence shutting down the addons, etc)

The crash report is totally opaque,

@MarcEvanstein , what are you restering on that handler? Can we not call it explicitly?

Yeah, I think we can; just a little awkward. Try:

from scamp.playback_implementations import SoundfontPlaybackImplementation
for host in SoundfontPlaybackImplementation.soundfont_hosts.values():
    print(host.synth.stop_recording())

That didn’t work, but you gave a hint so I checked and that synth (in my case, the ‘alsa’ implementation) is not recording the times after the first.

It seems, then, that the problem is setting up the recording on rounds > 1.

I just now forced a start_recording('/tmp/whareva.wav') and then when I played the notes it did write a file, but on the wav all the notes of the sequence are played at the same time :open_mouth: . Sounds cool, but not yet usable.

I wonder, then, how we could reset that recording the second time around.

I found a workaround for the code by quickly skimming it: I assign an empty {} to SoundfontPlaybackImplementation.soundfont_hosts whenever I create a new session, which forces new ones to be created and start recording. It’s not ideal, but it’s not bad.

I was going to suggest exactly that! I’m glad you figured it out. :slight_smile:

I think hackiness of the solution suggests that a few things need to be changed about the code. But at least we have something that works for now

Thanks a lot @MarcEvanstein, now I have my little iterative setup thing going and can work.

Still in the land of the techincal POCs, here in Blender feeding from animation curves (for now just “abstract”, with some noise) into Scamp piano thing.

Cheers

Thinking out loud, an explicit analogous to start_transcribing(), start_recording() would probably be a much more intuitive API. It’d also be cool that the export was also aligned to the midi version: s.stop_recording().export_to_wav_file('sounds/piano.wav').

I understand there’s a tricky balance between magically doing what we very often do and having to write explicit boilerplate. But mysterious side-effects are, well, sometimes spooky. :ghost:

You’re totally right; the issue is that the way I’m using the pyfluidsynth is to let it connect to the audio driver on its own. If instead I asked it for samples and sent them myself to pyaudio or something, it would be easier to manage the start and stop recording.

At the moment, the wav recording thing is kind of a hack. I hope sometime to rewrite it to be more like you suggest. Also, linking in with pyaudio would make it easier for me to create a form of playback that just plays individual wave files, which I think would be a real plus!