2018-07-03 06:30:43

I've been intrigued by one of joniksters questions about an audio library for recording audio, I knew OpenAL could do it but there didn't seem to be any examples in python available anywhere about it, until now that is, heh. I put together a script demonstrating how to do it [here] for anyone thats interested, you can record the audio output off your PC or from an external device like a microphone.

Note that under some circumstances it gives me a memory access error seemingly at random in IDLE when trying to load the data into a buffer, but seems to operate fine on the command line or run independantly. Your milage may vary.

-BrushTone v1.3.3: Accessible Paint Tool
-AudiMesh3D v1.0.0: Accessible 3D Model Viewer

2018-07-03 10:26:26

Wow great this is awesome. Thank you. Openal is really great but I sometimes get an error saying al_out_of_memory. I don't know what to do to fix it though i coded a function which checks if a source is stopped it destroys it. This redused the amount of that error but that seems still there. Any solutions to fix this please? It mightr be the wrong topic but i think making a new topic for this small perpous isn't a good idea

---
Co-founder of Sonorous Arts.
Check out Sonorous Arts on github: https://github.com/sonorous-arts/
my Discord: kianoosh.shakeri2#2988

2018-07-04 03:26:13

Hm, it could depend on a number of things, do you have any source code demonstrating the problem?

Also as for my memory access error, I think I made a bit of a mix up when allocating alBufferData with the buffer size, on line 243 I changed it from:

al.alBufferData(self.buf, self.alformat, self.wavbuf, len(self.wavbuf)*2, self.samplerate)

to

al.alBufferData(self.buf, self.alformat, self.wavbuf, len(self.wavbuf), self.samplerate)

That seemed to solve the memory access error, I've updated the example in my repository accordingly.

-BrushTone v1.3.3: Accessible Paint Tool
-AudiMesh3D v1.0.0: Accessible 3D Model Viewer

2018-07-04 07:59:56

I'm using pyOpenAl. The code is huge because it's an online game i'm working on and has lots of sources everywhere in it. I put every source in a sourcelist that is repeatidly being checked and when ever a source stopped playing(it's state is changed to AL_STOPPED) It calls the source.destroy() function to free memory and such. The al_out_of_memory is really rare but it happened onese and unfortunately it's not something that i can say exactly where to put an exception for it to prevent it from exiting the game. Even that is rare that breaks the game play when it suddenly makes the game quit. Please tell me if i'm doing a correct way to cleanup memory or not.

---
Co-founder of Sonorous Arts.
Check out Sonorous Arts on github: https://github.com/sonorous-arts/
my Discord: kianoosh.shakeri2#2988

2018-07-05 05:12:06

I'm less familiar with PyOpenAL and its buffer management, though it looks like it treats both a sound sample and a player as a single object. I've seen some open tickets on OpenAL Soft of it giving an out of memory error when its sample limit is reached, which I think is around 256? I believe the maximum number of simultaneous playing instances is limited to 32 as well, which may be for hardware compatibility. It could be that the rate that objects are created or destroyed could be happening too quickly for pythons garbage collector or the OS to clear up memory causing the error, but I would think such an error would probably happen when trying to load or create a new sample, i'm not sure if it would occur if trying to play a sample if too many sounds at once.

How many samples are you creating, and are you dynamically loading or creating them, then destroying them as needed? Usually I try to use a fixed memory footprint by loading all the sound sources and a limited number of player objects before hand, then loading the sources into available players as needed and releasing them to load new sounds when required, only destroying them on clean up when the program ends.

-BrushTone v1.3.3: Accessible Paint Tool
-AudiMesh3D v1.0.0: Accessible 3D Model Viewer

2018-07-05 08:17:22

Yup pyOpenAl has the sound smaple and the player as a single object. The thing is that i didn't understand players correctly so i couldn't use pyglet. Like i want to have some footsteps played as long as a key is being held down so for each soun play i should add a player and a soundsource. Is that correct? Or a single player can be for footsteps, one for firing weapons, one for reloading and alike?
unfortunately there's no straight examples about sound playing in pygletq

---
Co-founder of Sonorous Arts.
Check out Sonorous Arts on github: https://github.com/sonorous-arts/
my Discord: kianoosh.shakeri2#2988

2018-07-06 06:27:28

I'd probably assign a single player for both reloading and firing then switch sources as needed, since you usually can't reload and fire at the same time. Same with walking, jumping, and swimming, etc. Try mapping out the various actions a character can take and the contexts in which they happen to figure out just how many players they may need, that can help you calculate how many sounds you may have playing at once and what your potential load may be. If your dealing with dynamically generated enemies, you could keep a pool of available players and pass them to any newly created characters for use, then release them for reuse when out of range or the characters are killed. This could dictate how many characters could be spawned at a time however, not including players for ambient or environmental effects. Although you could also try assigning players more dynamically based on what characters actions are in the moment and release them back into a central idle player pool when finished as well, so as not to have characters or effects constantly take up players that could be used elsewhere when not in use.

As for Pyglet or PyAL examples, theres a bunch in my repository with listeners, players, and source classes, which you can find [here], [here], and [here], note that for the advanced stuff like HRTF or EFX you'll need to copy over some of pyglets openal driver scripts or use PyAL, and use OpenAL Soft. For an example on what that might look like with a game implementation using those classes:

import pyglet
from pyglet.window import key
from pyglet.media.drivers.openal import lib_openal as al
from pyglet.media.drivers.openal import lib_alc as alc

#imports for sound loading and wait during example
import wave
import time
import sys
import os


class Example(pyglet.window.Window):
    def __init__(self):
        super(Example, self).__init__(640, 480, resizable=False, fullscreen=False, caption="Example")
        self.clear()
    #load listener
        self.listener = listener()
    #initialize sound
        self.sound = load_sound('tone5.wav')
    #load sound player
        self.player = Player()
    #set the player to loop indefinitely until stopped
        self.player.loop = True
    #key input buffer
        self.key_input = []

        pyglet.clock.schedule_interval(self.update, .01)


    def update(self,dt):
        if 'SPACE press' in self.key_input:
        #if player is playing, stop it
            if self.player.playing() == True:
                self.player.stop()
        #make sure there is no source currently in the player
            self.player.remove()
        #load new source
            self.player.add(self.sound)
        #play source
            self.player.play()

        if 'SPACE release' in self.key_input:
        #if player is playing, stop it
            if self.player.playing() == True:
                self.player.stop()
        #purge the player of the current sample, if any
            self.player.remove()
                
    #clear key input buffer
        if len(self.key_input) > 0:
            self.key_input = []

    #draw screen
        self.draw()


    def draw(self):
        self.clear()

        
    def on_key_press(self,symbol,modifiers):
        self.key_input.append(key.symbol_string(symbol) + " press")
        if symbol == key.ESCAPE:
            self.sound.delete()
            self.player.delete()
            self.listener.delete()
            self.close()


    def on_key_release(self,symbol,modifiers):
        self.key_input.append(key.symbol_string(symbol) + " release")
-BrushTone v1.3.3: Accessible Paint Tool
-AudiMesh3D v1.0.0: Accessible 3D Model Viewer

2018-07-06 09:43:30

Thanks a lot. The thing is that in your examples i'm seeing that you are creating the listener and player classes yourself while pyglet already has them. Is there a thing that you prefer to use yours? Is there a problem with that? Again thank you for that example. A good thumbs up for that

---
Co-founder of Sonorous Arts.
Check out Sonorous Arts on github: https://github.com/sonorous-arts/
my Discord: kianoosh.shakeri2#2988

2018-07-07 01:08:41

Loading sounds and using players, or quick creating players with sounds for playback in pyglet tended to cause some issues and occasional artifacts on playback. Not to mention that, at the time at least, Pyglet didn't have the functions or classes to handle 3D positional audio, HRTF, EFX, or recording, so I had to write my own. I also found using my own classes and memory handling provided smoother results that was easier to debug and work with, extending them also didn't involve having to modify pyglets source, and I could easily port them over to other OpenAL libraries like PyAL if needed, providing greater flexibility.

-BrushTone v1.3.3: Accessible Paint Tool
-AudiMesh3D v1.0.0: Accessible 3D Model Viewer