Audio Processing Platform
Project description
Welcome to the Sudio 🎵
sudio
is an Open-source
, easy-to-use
digital audio processing library featuring both a real-time, non-real-time mix/edit platform.
Abstract
Audio signal processing is a highly active research field where digital signal processing theory meets human sound perception and real-time programming requirements. It has a wide range of applications in computers, gaming, and music technology, to name a few of the largest areas. Successful applications include for example perceptual audio coding, digital music synthesizers, and music recognition software.
Real-time audio processing
For live digital audio systems with high-resolution multichannel functionalities, it is desirable to have accurate latency control and estimation over all the stages of digital audio processing chain.
The sudio is written flexible can used for high level audio processing algorithm and other system factors, which might cause the latency effects. It also can estimate the synchronization and delay of multiple channels.
Non-Realtime processing:
Sudio is a comprehensive library for mixing, editing, and recording audio content.
Audio data maintaining process:
The sudio used additional cached files to reduce dynamic memory usage and improve performance, meaning that audio data storage methods could have different execution times based on the stored files. Thanks to that, Sudo can manage various audio streams from audio files or operating systems without any size limitation.
Installation
Latest PyPI stable release (previous version)
pip install sudio
Latest development release on GitHub
Pull and install pre-release main
branch (recommended):
pip install git+https://github.com/MrZahaki/sudio.git
Quick start
Audio playback
import sudio
su = sudio.Master()
su.add('baroon.mp3')
su.echo('baroon')
the record with the name of baroon will be played on the stdout audio stream.
Audio slicing
Time domain
simple slicing
The following example is used to play the audio record with the name of baroon from 12 to 27.66 seconds on the stdout audio stream.
su = sudio.Master()
baroon = su.add('baroon.mp3')
su.echo(baroon[12: 27.66])
slice & merge
su = sudio.Master()
rec = su.add('baroon.mp3')
# method 1
su.echo(rec[12: 27.66, 65: 90])
# method 2
su.echo(rec[12: 27.66] + rec[65: 90])
The audio record is split into two parts, the first one 12-27.66 seconds, and the last one 65-90 seconds, then the sliced records are merged and played in the stream.
Frequency domain
LPF 100Hz
su = sudio.Master()
baroon = su.add('baroon.mp3')
su.echo(baroon[: '100'])
HPF 1KHz
su = sudio.Master()
baroon = su.add('baroon.mp3')
su.echo(baroon['1000':])
BPF 500Hz - 1KHz
su = sudio.Master()
baroon = su.add('baroon.mp3')
su.echo(baroon['500':'1000'])
Complex Slicing
su = sudio.Master()
baroon = su.add('baroon.mp3')
su.echo(baroon[5:10, :'1000', 10: 20, '1000': '5000'])
In the example above, a low-pass filter with a cutoff frequency of 1 kHz is applied to the record from 5 to 10 seconds, then a band-pass filter is applied from 10 to 20 seconds, and finally they are merged.
Audio Streaming
su = sudio.Master()
# start sudio kernel
su.start()
record = su.add('baroon.mp3')
stream = su.stream(record)
# enable stdout
su.echo()
# start streaming
stream.start()
# wait for 10 seconds
time.sleep(10)
# stop streaming
stream.stop()
Table of contents:
- Sudio
Examples and Advanced Usage
Short-time Fourier transform
The Short-time Fourier transform (STFT), is a Fourier-related transform used to determine the sinusoidal frequency and phase content of local sections of a signal as it changes over time. In practice, the procedure for computing STFTs is to divide a longer time signal into shorter segments of equal length and then compute the Fourier transform separately on each shorter segment. This reveals the Fourier spectrum on each shorter segment. One then usually plots the changing spectra as a function of time, known as a spectrogram or waterfall plot, such as commonly used in Software Defined Radio (SDR) based spectrum displays.
prerequisites
pip install sudio
pip install kivy
API Documentation
Master
sudio.Master
Parameters
-
std_input_dev_id: int, optional os standard input device id. If not given, then the input device id will be selected automatically(ui_mode=False) or manually by the user(ui_mode=True)
-
std_output_dev_id: int, optional os standard output device id. If not given, then the output device id will be selected automatically(ui_mode=False) or manually by the user(ui_mode=True)
-
frame_rate: int, optional Input channel sample rate. If std_input_dev_id is selected as None, the value will be selected automatically.
-
nchannels: int, optional The number of audible perspective directions or dimensions.
If std_input_dev_id is selected as None, the value will be selected automatically.
-
data_format: SampleFormat Specifies the audio bit depths. Supported data format (from sudio): formatFloat32, formatInt32, formatInt24, formatInt16 (default), formatInt8, formatUInt8
-
mono_mode: bool, optional If True, then all the input channels will be mixed into one channel.
-
ui_mode: bool, optional If Enabled then user interface mode will be activated.
-
nperseg: int,optional number of samples per each data frame (in one channel)
-
noverlap: int, default None
The noverlap defines the number of overlap between defined windows. If not given then it's value will be selected as
SE = \frac{nperseg}{2}.
When the length of a data set to be transformed is larger than necessary to provide the desired frequency resolution, a common practice is to subdivide it into smaller sets and window them individually.
To mitigate the "loss" at the edges of the window, the individual sets may overlap in time.
-
NOLA_check: bool, optional Check whether the Nonzero Overlap Add (NOLA) constraint is met.(If true)
-
IO_mode: str, optional Input/Output processing mode that can be:
-
"stdInput2stdOutput":(default) default mode; standard input stream (system audio or any other windows defined streams) to standard defined output stream (system speakers).
-
"usrInput2usrOutput": user defined input stream (callback function defined with input_dev_callback) to user defined output stream (callback function defined with output_dev_callback).
-
"usrInput2stdOutput": user defined input stream (callback function defined with input_dev_callback) to user defined output stream (callback function defined with output_dev_callback).
-
"stdInput2usrOutput": standard input stream (system audio or any other windows defined streams) to user defined output stream (callback function defined with output_dev_callback).
-
-
input_dev_callback: callable; user input callback; default None; this function used in "usrInput2usrOutput" and "usrInput2stdOutput" IO modes and called by the sudio core every 1/frame_rate second and must returns frame data as a numpy array with the dimensions of the (Number of channels, Number of data per segment).
Format:
:inputs: frame_count, time_info, status :outputs: Numpy N-channel data frame in (Number of channels, Number of data per segment) dimensions.
:memo: Note: The data frame in single channel mode has the shape of (Number of data per segment, ).
-
output_dev_callback: callable;
User input callback; default None; This function used in "usrInput2usrOutput" and "stdInput2usrOutput" IO modes and called by the sudio core every 1 / frame_rate second after processing frames and takes the frame data as a numpy array in (Number of channels, Number of data per segment) dimensions numpy array.
format:
:inputs: Numpy N-channel data frame in (Number of channels, Number of data per segment) dimensions. :outputs: customized audio stream.
:memo: Note: The data frame in single channel mode has the shape of (Number of data per segment, ).
-
master_mix_callback: callable, optional This callback is used before the main-processing stage in the master for controlling and mixing all slave channels to a ndarray of shape (master.nchannels, 2, master.nperseg).
If this parameter is not defined, then the number of audio channels in all slaves must be the same as the master.
-
window: string, float, tuple, ndarray, optional The type of window, to create(string) or pre designed window in numpy array format. use None to disable windowing process. Default ("hann") Hanning function.
Notes
- If the window function requires no parameters, then
window
can be a string otherwise thewindow
must be a tuple with the first argument the string name of the window, and the next arguments the needed parameters.
Ifwindow
is a floating point number, it is interpreted as the beta parameter of thekaiser
window. Each of the window types listed above is also the name of a function that can be called directly to create a window of that type.
window types:boxcar, triang , blackman, hamming, hann(default), bartlett, flattop, parzen, bohman, blackmanharris nuttall, barthann, cosine, exponential, tukey, taylor, kaiser (needs beta), gaussian (needs standard deviation), general_cosine (needs weighting coefficients), general_gaussian (needs power, width), general_hamming (needs window coefficient), dpss (needs normalized half-bandwidth), chebwin (needs attenuation)
- "nonzero overlap add" (NOLA): This ensures that the normalization factors in the denominator of the overlap-add inversion equation are not zero. Only very pathological windows will fail the NOLA constraint.
Methods
add_file
sudio.Master.add_file( self, filename: str, sample_format: SampleFormat = SampleFormat.formatUnknown,
nchannels: int = None, sample_rate: int = None ,safe_load=True)
The add_file method used to Add an audio file to the local database. None value for the parameters means that they are automatically selected based on the properties of the audio file.
-
parameters:
- filename: path/name of the audio file
- sample_format: optional; sample format (refer to the SampleFormat data field).
- nchannels: optional; number of audio channels
- sample_rate: optional; sample rate
- safe_load: optional; load an audio file and modify it according to the 'Master' attributes. (sample rate, sample format, number of channels, etc).
-
returns WrapGenerator object
:memo: Note: supported files format: WAV, FLAC, VORBIS, MP3
:memo: Note: The audio data maintaining process has additional cached files to reduce dynamic memory usage and improve performance, meaning that, The audio data storage methods can have different execution times based on the cached files.
add
sudio.Master.add(self, record, safe_load=True)
Add new record to the local database.
-
parameters:
- record: can be an wrapped record, Record object or an audio file in mp3, WAV, FLAC or VORBIS format.
- safe_load: optional; load an audio file and modify it according to the 'Master' attributes.
-
returns Wrapped(WrapGenerator) object
:memo: Note: The name of the new record can be changed with the following tuple that is passed to the function: (record object, new name of ), otherwise automatically generated.
:memo: Note: The audio data maintaining process has additional cached files to reduce dynamic memory usage and improve performance, meaning that, The audio data storage methods can have different execution times based on the cached files.
start
start audio streaming, must be called before audio streaming process. returns master object.
Audio Recorder
The recorder
method provides advanced audio recording capabilities, allowing capture of any signal in the output processing stage.
Features
- Record audio for a specified duration
- Automatic naming with timestamp or custom name option
- Supports multi-channel recording
- Integrated with the local database for efficient storage and retrieval
- Channel shuffling for non-mono recordings
Usage
def recorder(self, record_duration: float, name: str = None) -> WrapGenerator:
"""
Record audio for a specified duration.
Args:
record_duration (float): Duration to record in seconds.
name (str, optional): Name for the recording. If None, a timestamp-based name will be generated.
Returns:
WrapGenerator: A wrapped version of the recorded audio data.
Raises:
KeyError: If the provided name already exists in the database.
"""
<br />
##### load_all
```py
sudio.Master.load_all(self, safe_load=True)
load all of the saved records from the external database(static memory) to the local database(dynamic memory).
-
parameters:
- safe_load: if safe load is enabled then load function tries to load a record in the local database based on the master settings, like the frame rate and etc.
- safe_load: if safe load is enabled then load function tries to load a record in the local database based on the master settings, like the frame rate and etc.
-
returns None
load
sudio.Master.load(self, name: str, load_all: bool=False, safe_load: bool=True,
series: bool=False) -> Union[WrapGenerator, Record])
The load method used to load a predefined recoed from the external database (static memoty) to the local database(dynamic memory). Trying to load a record that was previously loaded, outputs a wrapped version of the named record.
-
parameters:
- name: The name of the predefined record.
- load_all: used to load all of the saved records from the external database to the local database.
- safe_load: if safe load is enabled this method tries to load a record in the local database, based on the master settings, like the frame rate and etc.
- series: If enabled, attempting to load a record that has already been loaded will output the data series of the named record.
-
returns optional; Wrapped object, Record obejct.
get_record_info
sudio.Master.get_record_info(self, name: str) -> Record
get extra info about the record
-
parameters:
- name: name of the registered record on the local or external
-
returns information about saved record ['noiseLevel' 'frameRate' 'sizeInByte' 'duration' 'nchannels' 'nperseg' 'name'].
get_exrecord_info
sudio.Master.get_exrecord_info(self, name: str) -> Record
get extra info about the record
-
parameters:
- name: name of the registered record on the external database(if exists).
-
returns information about saved record ['noiseLevel' 'frameRate' 'sizeInByte' 'duration' 'nchannels' 'nperseg' 'name'].
syncable
sudio.Master.syncable(self,
* target,
nchannels: int = None,
sample_rate: int = None,
sample_format: SampleFormat = SampleFormat.formatUnknown)
Determines whether the wrapped record/s can be synced with specified properties.
-
parameters:
-
target: target: wrapped record\s.(regular records)
-
nchannels: number of channels; if the value is None, the target will be compared to the 'self' properties.
-
sample_rate: sample rate; if the value is None, the target will be compared to the 'self' properties.
-
sample_format: if the value is None, the target will be compared to the 'self' properties.
-
-
returns returns only objects that need to be synchronized.
sync
sudio.Master.sync(self,
* targets,
nchannels: int=None,
sample_rate: int=None,
sample_format: SampleFormat=SampleFormat.formatUnknown,
output='wrapped')
This method used to Synchronize wrapped record/s with the specified properties.
-
parameters:
- targets: wrapped records\s.
- nchannels: number of channels; if the value is None, the target will be synced to the 'self' properties.
- sample_rate: if the value is None, the target will be synced to the 'self' properties.
- sample_format: if the value is None, the target will be synced to the 'self' properties.
- output: can be 'wrapped'(regular records), 'series'(dict type) or 'ndarray_data'
-
returns returns synchronized objects.
del_record
sudio.Master.del_record(self, name: str, deep: bool=False)
The del_record method used to delete a record from the internal/external database.
-
parameters:
-
name str: the name of preloaded record.
-
deep bool: deep delete mode is used to remove the record and its corresponding caches from the external database.
-
returns None
save_as
sudio.Master.save_as(self, record: Union[str, Record, Wrap, WrapGenerator], file_path: str=SAVE_PATH)
Convert the record to the wav audio format.
- Parameters:
- record: name of the registered (wrapped) record, a 'Record' object or a (customized) wrapped record.
- file_path: The name or path of the wav file. A new name for the record to be converted can be placed at the end of the address.
- returns None
save
sudio.Master.save(self, name: str='None', save_all: bool=False)
Save the preloaded record to the external database.
- Parameters:
- name: name of the preloaded record
- save_all: if true then it's tries to save all of the preloaded records
- returns None
save
sudio.Master.save(self, name: str='None', save_all: bool=False)
Save the preloaded record to the external database.
- Parameters:
- name: name of the preloaded record
- save_all: if true then it's tries to save all of the preloaded records
- returns None
save_all
sudio.Master.save_all(self)
Save all of the preloaded records to the external database
- returns None
get_exrecord_names
sudio.Master.get_exrecord_names(self) -> list
:return: list of the saved records in the external database
get_record_names
sudio.Master.get_record_names(self, local_database: bool=True) -> list
param local_database: if false then external database will be selected returns: a list of the saved records in the external or internal database
get_nperseg
sudio.Master.get_nperseg(self)
returns: number of samples per each data frame (single channel)
get_nchannels
sudio.Master.get_nchannels(self)
Returns the number of audible perspective directions or dimensions of the current wrapped record.
get_sample_rate
sudio.Master.get_sample_rate(self)
returns: current master sample rate
stream
sudio.Master.stream(self,
record: Union[str, Wrap, Record, WrapGenerator],
block_mode: bool=False,
safe_load: bool=False,
on_stop: callable=None,
loop_mode: bool=False,
use_cached_files=True,
stream_mode:StreamMode = StreamMode.optimized
) -> StreamControl
'Record' playback on the mainstream.
-
Parameters:
- record: predefined record name, (customized) wrapped record, or a 'Record' object.
- block_mode: This can be true, in which case the current thread will be blocked as long as the stream is busy.
- safe_load: load an audio file and modify it according to the 'Master' attributes(like the frame rate, number oof channels, etc).
- on_stop: An optional callback is called at the end of the streaming process.
- loop_mode: playback continuously.
- use_cached_files: enable additional cache maintaining process.
- stream_mode: (see StreamMode enum).
-
returns StreamControl object
:memo: Note: The recorder can only capture normal streams(Non-optimized streams)
mute
sudio.Master.mute(self)
mute the stdin stream (default)
unmute
sudio.Master.unmute(self)
disable mute mode of the stdin stream
echo
sudio.Master.echo( self,
record: Union[Wrap, str, Record, WrapGenerator]=None,
enable: bool=None,
main_output_enable: bool=False)
start to play "Record" on the operating system's default audio output.
-
Parameters:
-
record: optional, default None; It could be a predefined record name, a wrapped record, or a 'Record' object.
-
enable: optional, default None(trigger mode) determines that the standard output of the master is enable or not.
-
main_output_enable: when the 'record' is not None, controls the standard output activity of the master
-
-
returns self object
:memo: Note: If the 'record' argument takes the value None, the method controls the standard output activity of the master with the 'enable' argument.
:memo: Note: If the 'record' argument takes the value None, the kernel starts streaming the std input to the std output.
wrap
sudio.Master.wrap(self, record: Union[str, Record])
Create a Wrap object.
param record: preloaded record or a Record object returns: Wrap object
clean_cache
sudio.Master.clean_cache(self)
The audio data maintaining process has additional cached files to reduce dynamic memory usage and improve performance, meaning that, The audio data storage methods can have different execution times based on the cached files. This function used to clean additional cached files.
returns: self object
add_pipeline
sudio.Master.add_pipeline( self,
name: str,
pip: Union[Pipeline, list],
process_type: sudio.types.PipelineProcessType=PipelineProcessType.MAIN,
channel: int=None)
Add a new process pipeline to the master object.
-
Parameters:
-
name: string; represents the new pipeline
-
pip: obj; Pipeline object/s In the multi_stream process type, this argument must be a list of the defined pipelines, with the size equal to the nchannel.
-
process_type: PipelineProcessType; MAIN, BRANCH, MULTI_STREAM The sudio kernel inject audio data to the activated pipeline[if exist] and all of the branch type pipelines then takes output from the primary one.
:memo: Note: Use set_pipeline to activate a main branch or a multi_stream one.
:memo: Note: A branch pipeline is used for data monitoring(GUI) purposes.
-
channel: obj; None or [0 to nchannel]; just activated in branched pipelines;
The input data passed to a pipeline can be an numpy array with the shape of the (number of the audio channels, 2 [number of the windows per each frame], nperseg) (in mono mode (2, self._nperseg)).
-
:memo: Note: the pipeline used to process data and return it to the kernel with the dimensions as same as the input.
:memo: Note: Each pipeline used to process data in different threads, so the the performance will be improved.
set_pipeline
sudio.Master.set_pipeline(self, name: str, enable: bool=True)
activate the registered pipeline on the process stream.
-
Parameters:
- name: string; A name that represents the new pipeline
- enable: bool; state of the primary pipeline.
:memo: Note: Only multi_stream and main branches are allowed for activation.
set_window
sudio.Master.set_window(self,
window: object = 'hann',
noverlap: int = None,
NOLA_check: bool = True)
change type of the current processing window.
-
Parameters:
-
window: string, float, tuple, ndarray, optional The type of window, to create (string) or pre designed window in numpy array format. use None to disable windowing process. Default ("hann") Hanning function.
-
noverlap: int, default None
The noverlap defines the number of overlap between defined windows. If not given then it's value will be selected as
SE = \frac{nperseg}{2}.
When the length of a data set to be transformed is larger than necessary to provide the desired frequency resolution, a common practice is to subdivide it into smaller sets and window them individually.
To mitigate the "loss" at the edges of the window, the individual sets may overlap in time.
-
NOLA_check: bool, optional Check whether the Nonzero Overlap Add (NOLA) constraint is met.(If true)
-
StreamControl
sudio.Master.StreamControl
The StreamControl class used to control data flow of an audio record (live control on audio streaming).
Methods
isready
sudio.Master.StreamControl.isready()
check current stream compatibility with the Master object and return true on ready to streaming.
is_streaming
sudio.Master.StreamControl.is_streaming()
return true if current stream was started before.
start
sudio.Master.StreamControl.start()
check current stream compatibility with the Master object and start to streaming.
resume
sudio.Master.StreamControl.resume()
resume current streaming if current stream was paused.
stop
sudio.Master.StreamControl.stop()
stop current streaming if current stream is activated.
pause
sudio.Master.StreamControl.pause()
pause current streaming if current stream is activated.
enable_loop
sudio.Master.StreamControl.enable_loop()
enable to restart at the end of streaming.
disable_loop
sudio.Master.StreamControl.disable_loop()
disable audio streaming loop mode.
Properties
time
sudio.Master.StreamControl.time
Getter
used to retrive elapsed time of the current streamed record.
Setter
Set the current time of streamed record.
WrapGenerator
sudio.WrapGenerator(self, master: Master, record: Union[str, pd.Series])
Generates a Wrap object, which wraps the raw record.
Methods
get_sample_format
sudio.WrapGenerator.get_sample_format(self) -> SampleFormat
Returns sample format of the current generator.
get_sample_width
sudio.WrapGenerator.get_sample_width(self) -> int
Returns sample width of the current wrapped record.
get_master
sudio.WrapGenerator.get_master(self) -> Master
Returns the Master object of the current generator.
get_size
sudio.WrapGenerator.get_size(self) -> int
Returns size of the currently processed record on non-volatile memory.
:memo: Note: Wrapped objects normally stored statically, so all of the calculations need additional IO read/write time, This decrese dynamic memory usage specically for big audio data.
get_cache_size
sudio.WrapGenerator.get_cache_size(self) -> int
Returns size of cached file on non-volatile memory.
:memo: Note: Wrapped objects normally stored statically, so all of the calculations need additional IO read/write time, This decrese dynamic memory usage specically for big audio data.
get_nchannels
sudio.WrapGenerator.get_nchannels(self) -> int
Returns the number of audible perspective directions or dimensions of the current wrapped record.
get_frame_rate
sudio.WrapGenerator.get_frame_rate(self) -> int
Returns frame rate of the current warpped record.
get_duration
sudio.WrapGenerator.get_duration(self) -> float
Returns the duration of the provided audio record.
join
sudio.WrapGenerator.join(self,
*other: Union[Wrap, WrapGenerator],
sync_sample_format: SampleFormat = None,
sync_nchannels: int = None,
sync_sample_rate: int = None,
safe_load: bool = True
) -> Wrap
Returns a new wrapped record by joining and synchronizing all the elements of the 'other' iterable (Wrap, WrapGenerator), separated by the given separator.
-
parameters:
- other: wrapped record\s.
- sync_nchannels: number of channels; if the value is None, the target will be synced
- sync_sample_format: if the value is None, the target will be synced to the master properties.
- sync_sample_rate: sample rate; if the value is None, the target will be compared to the master properties.
- safe_load: load an audio file and modify it according to the 'Master' attributes(like the frame rate, number oof channels, etc).
-
returns new Wrap object.
Magic methods
getitem
sudio.WrapGenerator.__getitem__(self, item) -> Wrap
Slicing : The Wrapped object can be sliced using the standard Python x[start: stop: step] syntax, where x is the wrapped object.
Slicing the time domain:
The basic slice syntax is
[i: j: k, i(2): j(2): k(2), i(n): j(n): k(n)]
where i is the start time, j is the stop time in integer or float types and k is the step(negative number for inversing). This selects the nXm seconds with index times
i, i+1, i+2, ..., j, i(2), i(2)+1, ..., j(2), i(n), ..., j(n)
j where m = j - i (j > i).
:memo: Note: for i < j, i is the stop time and j is the start time, means that audio data read inversely.
Filtering (Slicing the frequency domain):
The basic slice syntax is
['i': 'j': 'filtering options', 'i(2)': 'j(2)': 'options(2)', ..., 'i(n)': 'j(n)': 'options(n)']
where i is the starting frequency and j is the stopping frequency with type of string in the same units as fs that fs is 2 half-cycles/sample. This activates n number of iir filters with specified frequencies and options.
For the slice syntax [x: y: options] we have:
- x= None, y= 'j': low pass filter with a cutoff frequency of the j
- x= 'i', y= None: high pass filter with a cutoff frequency of the i
- x= 'i', y= 'j': bandpass filter with the critical frequencies of the i, j
- x= 'i', y= 'j', options='scale=[Any negative number]': bandstop filter with the critical frequencies of the i, j
Filtering options:
- ftype: optional; The type of IIR filter to design:\n
- Butterworth : ‘butter’(default)
- Chebyshev I : ‘cheby1’
- Chebyshev II : ‘cheby2’
- Cauer/elliptic: ‘ellip’
- Bessel/Thomson: ‘bessel’
- rs: float, optional:\n For Chebyshev and elliptic filters, provides the minimum attenuation in the stop band. (dB)
- rp: float, optional:\n For Chebyshev and elliptic filters, provides the maximum ripple in the passband. (dB)
- order: The order of the filter.(default 5)
- scale: [float, int] optional; The attenuation or Amplification factor, that in the bandstop filter must be a negative number.
Complex slicing: The basic slice syntax is
[a: b, 'i': 'j': 'filtering options', ..., 'i(n)': 'j(n)': 'options(n)', ..., a(n): b(n), 'i': 'j': 'options', ..., 'i(n)': 'j(n)': 'options(n)']
or
[a: b, [Filter block 1)], a(2): b(2), [Filter block 2] ... , a(n): b(n), [Filter block n]]
Where i is the starting frequency, j is the stopping frequency, a is the starting time and b is the stopping time in seconds. This activates n number of filter blocks [described in the filtering section] that each of them operates within a predetermined time range.
note: The sliced object is stored statically so calling the original wrapped returns The sliced object.
del
sudio.WrapGenerator.__del__(self)
Delete the current object and its dependencies (cached files, etc.)
str
sudio.WrapGenerator.__str__(self)
Returns string representation of the current object
mul
sudio.WrapGenerator.__mul__(self, scale) -> Wrap
Returns a new Wrap object, scaling the data of the current record.
truediv
sudio.WrapGenerator.__truediv__(self, scale)
Returns a new Wrap object, dividing the data of the current record.
pow
sudio.WrapGenerator.__pow__(self, power, modulo=None)
Returns a new Wrap object, scaling the data of the current record.
add
sudio.WrapGenerator.__add__(self, other:Union[Wrap, WrapGenerator, int, float])
if the 'other' parameter is a WrapGenerator or a Wrap object this method joins the current object to the other one, otherwise this method used to Return a new Wrap object, scaling the data of the current record.
sub
sudio.WrapGenerator.__sub__(self, other: Union[float, int])
Returns a new Wrap object, subtracting the data of the current record.
call
sudio.WrapGenerator.__call__(self,
*args,
sync_sample_format_id: int = None,
sync_nchannels: int = None,
sync_sample_rate: int = None,
safe_load: bool = True
) -> Wrap
Synchronize the current object with the master (optional) and create a new Wrap object.
-
parameters:
- sync_nchannels: number of channels; if the value is None, the target will be synced
- sync_sample_format_id: if the value is None, the target will be synced to the master properties.
- sync_sample_rate: sample rate; if the value is None, the target will be compared to the master properties.
- safe_load: load an audio file and modify it according to the 'Master' attributes(like the frame rate, number oof channels, etc).
-
returns new Wrap object.
:memo: Note: Wrapped objects normally stored statically, so all of the calculations need additional IO read/write time, This decrese dynamic memory usage specically for big audio data.
Wrap
sudio.Wrap(self, master: Master, record: pd.Series, generator: WrapGenerator)
Methods
get_sample_format
sudio.Wrap.get_sample_format(self) -> SampleFormat
Returns sample format of the current warpped record.
get_sample_width
sudio.Wrap.get_sample_width(self) -> int
Returns sample width.
get_master
sudio.Wrap.get_master(self) -> Master
Returns the Master object.
get_size
sudio.Wrap.get_size(self) -> int
Returns size of the currently processed record on non-volatile memory.
:memo: Note: Wrapped objects normally stored statically, so all of the calculations need additional IO read/write time, This decrese dynamic memory usage specically for big audio data.
get_frame_rate
sudio.Wrap.get_frame_rate(self) -> int
Returns frame rate of the current warpped record.
get_nchannels
sudio.Wrap.get_nchannels(self) -> int
Returns the number of audible perspective directions or dimensions of the current wrapped record.
get_duration
sudio.Wrap.get_duration(self) -> float
Returns the duration of the provided audio record.
join
sudio.Wrap.join(self, *other) -> Wrap
Returns a new wrapped record by joining and synchronizing all the elements of the 'other' iterable (Wrap, WrapGenerator), separated by the given separator.
unpack
@contextmanager
sudio.Wrap.unpack(self, reset=False) -> np.ndarray
Unpack audio data from cached files to the dynamic memory.
:memo: Note: All calculations in the unpacked block are performed on the precached files (not the original audio data).
- parameters:
- reset: Reset the audio pointer to time 0 (Equivalent to slice '[:]').
- Returns audio data in ndarray format with shape of (number of audio channels, block size).
master = Master()
wrapgen = master.add('file.mp3')
wrap = wrapgen()
with wrap.unpack() as data:
wrap.set_data(data * .7)
master.echo(wrap)
get_data
sudio.Wrap.get_data(self) -> Union[pd.Series, numpy.ndarray]
if the current object is unpacked:
- Returns the audio data in a ndarray format with shape of (number of audio channels, block size).
otherwise:
- Returns the current record.
is_packed
sudio.Wrap.is_packed(self) -> bool
Returns true if the Wrap object is packed.
get
@contextmanager
sudio.Wrap.get(self, offset=None, whence=None)
Returns the audio data as a _io.BufferedRandom IO file.
set_data
sudio.Wrap.set_data(self, data: numpy.ndarray)
Set audio data for current wrapped record (object must be unpacked to the volatile memory).
Magic methods
del
sudio.Wrap.__del__(self)
Delete the current object and its dependencies (cached files, etc.)
str
sudio.Wrap.__str__(self)
Returns string representation of the current object
getitem
sudio.Wrap.__getitem__(self, item) -> self
Slicing : The Wrapped object can be sliced using the standard Python x[start: stop: step] syntax, where x is the wrapped object.
Slicing the time domain:
The basic slice syntax is
[i: j: k, i(2): j(2): k(2), i(n): j(n): k(n)]
where i is the start time, j is the stop time in integer or float types and k is the step(negative number for inversing). This selects the nXm seconds with index times
i, i+1, i+2, ..., j, i(2), i(2)+1, ..., j(2), i(n), ..., j(n)
j where m = j - i (j > i).
:memo: Note: for i < j, i is the stop time and j is the start time, means that audio data read inversely.
Filtering (Slicing the frequency domain):
The basic slice syntax is
['i': 'j': 'filtering options', 'i(2)': 'j(2)': 'options(2)', ..., 'i(n)': 'j(n)': 'options(n)']
where i is the starting frequency and j is the stopping frequency with type of string in the same units as fs that fs is 2 half-cycles/sample. This activates n number of iir filters with specified frequencies and options.
For the slice syntax [x: y: options] we have:
- x= None, y= 'j': low pass filter with a cutoff frequency of the j
- x= 'i', y= None: high pass filter with a cutoff frequency of the i
- x= 'i', y= 'j': bandpass filter with the critical frequencies of the i, j
- x= 'i', y= 'j', options='scale=[Any negative number]': bandstop filter with the critical frequencies of the i, j
Filtering options:
- ftype: optional; The type of IIR filter to design:\n
- Butterworth : ‘butter’(default)
- Chebyshev I : ‘cheby1’
- Chebyshev II : ‘cheby2’
- Cauer/elliptic: ‘ellip’
- Bessel/Thomson: ‘bessel’
- rs: float, optional:\n For Chebyshev and elliptic filters, provides the minimum attenuation in the stop band. (dB)
- rp: float, optional:\n For Chebyshev and elliptic filters, provides the maximum ripple in the passband. (dB)
- order: The order of the filter.(default 5)
- scale: [float, int] optional; The attenuation or Amplification factor, that in the bandstop filter must be a negative number.
Complex slicing: The basic slice syntax is
[a: b, 'i': 'j': 'filtering options', ..., 'i(n)': 'j(n)': 'options(n)', ..., a(n): b(n), 'i': 'j': 'options', ..., 'i(n)': 'j(n)': 'options(n)']
or
[a: b, [Filter block 1)], a(2): b(2), [Filter block 2] ... , a(n): b(n), [Filter block n]]
Where i is the starting frequency, j is the stopping frequency, a is the starting time and b is the stopping time in seconds. This activates n number of filter blocks [described in the filtering section] that each of them operates within a predetermined time range.
note: The sliced object is stored statically so calling the original wrapped returns The sliced object.
mul
sudio.Wrap.__mul__(self, scale) -> Wrap
Returns current object, dividing the data of the current record.
truediv
sudio.Wrap.__truediv__(self, scale)
Returns current object, dividing the data of the current record.
pow
sudio.Wrap.__pow__(self, power, modulo=None)
Returns a new Wrap object, scaling the data of the current record.
add
sudio.Wrap.__add__(self, other:Union[Wrap, WrapGenerator, int, float])
if the 'other' parameter is a WrapGenerator or a Wrap object this method joins the current object to the other one, otherwise this method used to Return a current object, scaling the data of the current record.
sub
sudio.Wrap.__sub__(self, other: Union[float, int])
Returns current object, subtracting the data of the current record.
Pipeline
A pipeline is a system of pipes used to transport data, each pipe is a method that processes data and pass it to the next one.
Pipeline helps the audio processing algorithms to break the complexity into smaller blocks, and the use of threading techniques improves the overall performance of the system.
sudio.Pipeline
graph LR;
A(Input Queue)-->B(Pipe 0);
B-->C(Pipe 1);
C-->D(...);
D-->E(Output Queue);
Parameters
-
max_size: int, optional Maximum number of callable per Pipeline object
-
io_buffer_size: int, optional Maximum size of the I/O queues.
-
on_busy: [float, str], optional Determines the behavior of the pipeline after the I/O queues are full. (busy state).
Please use:
- "drop" to drop old data from the output queue and allocate new space for new ones.
- "block" to block the pipeline until the last data arrives.
- timeout in float type to block the pipeline until the end time.
-
list_dispatch: bool, optional dispatch the input list type, to the arguments of the first pipe.
Methods
clear
sudio.Pipeline.clear(self)
Remove all of the items from the I/O queues in block mode.
run
sudio.Pipeline.run(self)
Start data injection into pipeline.
insert
sudio.Pipeline.insert(self,
index: int,
*func: callable,
args: Union[list, tuple, object] = (),
init: Union[list, tuple, callable] = ())
Insert callable/s before index.
Parameters
-
index: int
index value.
-
func: callable
-
Pipeline callable element/s.
-
args: (tuple, list, object), optional
the static argument/s, will be passed to the pipeline element/s.
example:
-
multiple arguments for multiple callables
def f0(arg0, arg1, data): return data def f1(arg, data): return data pip = sudio.Pipeline() pip.insert(2, f0, f1, args=(['arg0 for f0', 'arg1 for f0'], 'single arg for f1'))
-
single argument for multiple callables
def f0(arg, data): return data def f1(arg, data): return data pip = sudio.Pipeline() pip.insert(2, f0, f1, args='single arg for all')
def f0(data): return data def f1(arg, data): return data pip = sudio.Pipeline() pip.insert(2, f0, f1, args=(None, 'single arg for f1'))
-
single argument for single callable
def f0(arg, data): return data pip = sudio.Pipeline() pip.insert(2, f0, args='single arg for f0')
-
-
init: (list, tuple, callable), optional
single or multiple callables suggested for access to the pipeline's shared memory, that called after starting pipeline thread execution.
Reterns
- self object
append
sudio.Pipeline.append(self,
*func: callable,
args: Union[list, tuple, object] = (),
init: Union[list, tuple, callable] = ())
Append callable/s to the end of the pipeline. For more detailes Please refer to the sudio.Pipeline.insert method.
sync
sudio.Pipeline.sync(self, barrier: threading.Barrier)
Synchronize current pipeline with others using a barrier.
aasync
sudio.Pipeline.aasync(self)
Disable pipeline synchronization.
delay
sudio.Pipeline.delay(self)
used to retrive pipeline execution delay in us.
set_timeout
sudio.Pipeline.set_timeout(self, t: Union[float, int])
Determines the blocking timeout of the pipeline after the I/O queues are full.
get_timeout
sudio.Pipeline.get_timeout(self)
used to retrive the blocking timeout of the pipeline after the I/O queues are full.
put
sudio.Pipeline.put(self, data)
Inject new data into the pipeline object
get
sudio.Pipeline.get(self, block=True, timeout=None):
Remove and return an item from the output queue.
If optional args 'block' is true and 'timeout' is None (the default), block if necessary until an item is available. If 'timeout' is a non-negative number, it blocks at most 'timeout' seconds and raises the Empty exception if no item was available within that time. Otherwise ('block' is false), return an item if one is immediately available, else raise the Empty exception ('timeout' is ignored in that case).
Magic methods
call
sudio.Pipeline.__call__(self, data)
The __ call __ magic method used to Inject data into the current pipeline object
delitem
sudio.Pipeline.__delitem__(self, key)
Delete self[key].
len
sudio.Pipeline.__len__(self)
Return len(self).
getitem
sudio.Pipeline.__getitem__(self, key)
Return self[key].
LICENCE
Open Source (OSI approved): Apache License 2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.