Sound¶
Overview¶
The PyRend sound submodule allows you to play, modify, record and write sound. It uses two main object types, Sound() and Recording().
This submodule documentation assumes you have read the introduction and understand how to create a basic PyRend loop.
Sound Objects¶
Sound objects are general objects containing everything in PyRend related to sound. They can be created with the createsound() function.
mySound = pyrend.sound.createsound(path, volume=1.0)
The path parameter fully supports the follow formats: .mp3, .ogg .wav, and .mp4. More sound file types may work, but may not be fully supported for all functions.
That’s right; you can extract audio from an mp4 file to turn into a Sound object.
You can also create a sound object from sound data (NumPy Arrays) and a samplerate. To learn more, read the soundfile documentation
mySound = pyrend.sound.array(data, samplerate, volume=1.0)
Playback¶
Sound playback can be controlled through a few simple functions.
mySound.play(volume=None)
Plays the sound. The sound is played in a seperate thread meaning it does not interrupt your script.
mySound.stop()
Stops all playback of that sound.
mySound.wait()
Pauses the script on that function to wait until it has finished playback, if currently playing.
mySound.get_playback_time() -> float
Returns a float of the current time (seconds) that the sound is into playback, if it is playing.
mySound.seek(seconds)
Skip to a certain amount of seconds in the video. As of PyRend 0.1.45, it can be used before playback has started to set a point to start at.
You can combine get_playback_time() with seek() and a stored time, to make a rough pause and resume feature.
Example¶
import pyrend
mySound = pyrend.sound.createsound('sound.mp3', 1.0) # Create the sound object
mySound.seek(1) # Start the playback a second in
mySound.play() # Play the sound
def update():
if pyrend.input.is_key_down("ALT") and pyrend.input.is_key_down("Q"):
pyrend.close()
if pyrend.input.is_key_down("Space"): # If space is pressed, stop playback
mySound.stop()
pyrend.start(update)
Audio manipulation¶
Though PyRend doesn’t support as much audio manipulation as some other libraries, it does have the ability to shift pitch:
mySound.set_pitch(pitch=0)
pitch (float): The number of steps to shift the pitch by. A positive number makes it higher and a negative makes it lower.
Shifting a sounds pitch takes a while, however it will not pause your script or stop you from playing it when working. While shifting pitch, you can still call play(), however it will still play in normal pitch. When the pitch shift is finished, it will switch audio playback to the pitch shifted version, but resume playback from the same point.
Warning
Pitch shifting large audio files can be intensive on the CPU, so use carefully.
mySound.set_volume(volume)
Sets the volume to the specified. You can also just change the volume attribute directly to have the same effect.
You can use the shifting attribute to detect whether it is currently working to shift a sound. This can be used to detect when a sound has finished shifting. This code will wait until sound has finished shifting before continuing:
while mySound.shifting:
pass
You can also save a sound object to a .wav file using write()
mySound.write(path="sound.wav")
path (str): The path to save the audio file under. This must end in .wav.
Note
Writing a sound object to a file saves its pitch.
Recording¶
The PyRend sound submodule allows you to record audio input from the mic. To do this, you need to create a Recording object.
myRecording = pyrend.sound.recording(time, callback=None, args=())
When a recording object has finished recording, it will automatically transform into a sound object. This means you could immediately play it, pitch change it, or write it to a file. Due to this change in object, it could lead to tricky scenarios where your script will crash trying to execute a not yet, or no longer existing method. You could get around this by using pythons try statement, or by using the built in isinstance function like this:
myRecording = pyrend.sound.recording(3, callback=None, args=())
myRecording.start()
while True:
if isinstance(myRecording, pyrend.sound.Sound):
print("Recording finished!")
This will be used in a proper loop later in the example.
Methods¶
Creating a recording will not immediately start it. To start recording audio input, use:
myRecording.start()
This will start the recording for the duration specified on creation. When playing it does not pause your script/loop. While running you can use:
myRecording.pause()
…To pause the recording. Then you can use:
myRecording.resume()
…To resume it.
Usage¶
The following script creates a five second recording, starts it and waits until it’s finished and plays when the space key is pressed. To read about key presses, take a look at the input submodule
import pyrend
myRecording = pyrend.sound.recording(5, callback=None, args=())
myRecording.start() # Create and start a five second recording
while not isinstance(myRecording, pyrend.sound.Sound):
pass # Wait until it has finished
space_pressed = False # Create global variables to check if keys are pressed
bracket_pressed = False
def update():
global alt_q_pressed, space_pressed, bracket_pressed # Get global variables
if pyrend.input.is_key_down("ALT") and pyrend.input.is_key_down("Q"):
pyrend.close() # Safety quit keybind
if pyrend.input.is_key_down("SPACE"):
if not space_pressed:
if myRecording.playing:
myRecording.stop() # If space is pressed, stop or play the recording
else:
myRecording.play()
space_pressed = True # Set global variable to True to avoid repetitive execution
else:
space_pressed = False
if pyrend.input.is_key_down("["):
if not bracket_pressed:
myRecording.write("sound.wav") # If left bracket is pressed, write the audio to file.
bracket_pressed = True
else:
bracket_pressed = False
pyrend.start(update) # Start the update loop
A lot of this code is clutter as the is_key_down method will execute every frame. Obviously we do not want the space key to pause or play the audio every frame, so we need to account for this.
Examples¶
Below are some scripts that combine everything documented in this documentation page.
The following script plays some music, and when the space key is pressed, gently fades it out to a stop:
import pyrend
music = pyrend.sound.createsound('music/track1.ogg')
music.play() # Create and start music
playing = True
def update():
global playing
# Safety quit
if pyrend.input.is_key_down("ALT") and pyrend.input.is_key_down("Q"):
pyrend.close()
# Pause trigger
if playing and pyrend.input.is_key_down("SPACE"):
playing = False
# Fade out
if not playing:
if music.volume > 0:
music.volume = max(0, music.volume - 0.01)
else:
music.stop()
pyrend.start(update)
This script takes a .mp4 file and shifts its audio by one octave, then plays and saves it:
import pyrend
sound = pyrend.sound.createsound('video.mp4') # Create sound from mp4
sound.set_pitch(12) # Pitch sound up by one octave
while sound.shifting:
pass # Wait until pitch shifting has finished
sound.play() # Play sound
sound.write('pitched_sound.wav') # Save it to file