Package: poordub
minidubA minimalisticPyDubclone.This small package was written out of curiosity about theaudioopmodule
in the Python standard library.
It implements a subset ofPyDub'sfeatures.You probably should not use it, butit worksand illustrates
how to useaudioopcorrectly.PcmAudioobjectsThe main class in this module isPcmAudio, which is a
shrink-wrapped version of PyDub'sAudioSegment, but a bit less
capable than the original:Supports only file formats that Python understands, i.e. Wave, AIFF, and SunAudio.Does everyting in-memoryHas no fancy audio effects (other than fades)UsageTo read a file from disk, usePcmAudio.from_file(audio_file, audio_format=wave),
whereaudio_filecan be a path or a file-like object, andaudio_formatcan
be eitherwave,aifc, orsunau.Approximately a second of a simple sine wave can be obtained withPcmAudio.sine(hz),
and silence withPcmAudio.silence(millis=0).To add audio parts, use+like so:part1 + part2. To loop, multiply with the
number of repetitions:audio * 3To extract a segment from an audio clip, slice it at the desired time:audio[start:end],
wherestartandendshould be in milliseconds, defaulting to0and the
total audio length, respectively. The total audio length can be obtained withlen(audio).To change the amplitude, add or subtract the desired amplitude change indB:audio - 3.To overlay two audio clips, useclip1 & clip2, but careful: This adds the
signals, which might result in ugly noise if the sum of amplitudes is greater than
the maximum possible amplitude for the sample width. If that happens, add some
negative gain to the clips before overlaying them.Also make certain that audios have the same length before overlaying them.
Otherwise, the longer part will be clipped.A rough measure of the signalstrengthcan be obtained withaudio.dbfs(). If it is too low,audio.normalize(headroom=0.1)will scale it to the max
with a safety margin, given in dB byheadroom.To write audio files, useaudio.to_file(audio_file, audio_format=wave, compression=None).audio_fileandaudio_formatare as above, andcompressionis only supported
forAIFFfiles.A memory buffer containing an audio file can be obtained withaudio.to_buffer(self, audio_format=wave, compression=None).
To play a clip, callaudio.play()which returns asimpleaudio.PlayObject.FadesThe only included effects are fades:audio.fade_in(duration, threshold=float('-inf'))audio.fade_out(duration, threshold=float('-inf'))audio.cross_fade(other, duration, gap=0, threshold=float('-inf'))For these,durationis in milliseconds as usual, andthresholdis the minimum amplitude that needs to be exceeded in the portion
being faded before the actual fade is applied.While this sounds somewhat technical, it improves the audible
result of cross-fades: If one part is already very low at
the beginning or the end, it needs no additional fade,
but can be used as-is in the overlay. Try -9dB for testing.Finally, thegapis the duration (in milliseconds)
of additional silence that is inserted at each end of the
audio parts during cross-fades. It can be used to make the transition from
one clip to another audibly clearer.Miscaudio.to_mono()andaudio.to_stereo()do what their names suggest.
Additionally, there are two technical operationsto_framerate()andto_sample_width()which are used internally to ensure consistency
between clips before appending or overlaying.Playback and recordingPlayback and recording usePyAudio, which in turn depends on the
cross-platformportaudiolibrary. The former can be installed withpip3 install PyAudio, the latter withapt-get,brewor similar.PyAudiois not installed by default as a dependency, it should be
done manually before microphones or speakers are used.TheAudioStreamwrapper takes care of frame I/O inblockingmode. Theopenmethod expectsPcmAudio.Paramswith the desired
number of channels, sample width and frame rate. By default, it
opens a stream in playback mode. Passinput=Truefor recording.AudioStreamcan be used as a context manager that opens
the stream with default settings and closes it on exit.Example code:withAudioStream(AudioStream.CD_AUDIO)asout:out.play(some_audio)withAudioStream(AudioStream.MONO_16KHZ).open(input=True)asin_out:recording=in_out.record(3000)in_out.play(recording)