Skip to main content

Real-Time Audio Processing Platform

Project description

Sudio

sudio is a powerful, Open-source, fast, cross-platform and 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.


Table of contents:

Installation

Latest PyPI stable release
pip install sudio
Latest development release on GitHub

Pull and install pre-release main branch:

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()

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 the window must be a tuple with the first argument the string name of the window, and the next arguments the needed parameters.
    If window is a floating point number, it is interpreted as the beta parameter of the kaiser 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.


recorder
   sudio.Master.recorder(self,
                        record_duration: Union[int, float] = 10,
                        name: str=None,
                        enable_compressor: bool=False,
                        noise_sampling_duration: Union[int, float]=1,
                        enable_ui: bool=False,
                        play_recorded: bool=False,
                        catching_precision: float=0.1,
                        echo_mode: bool=False,
                        on_start_callback: callable=None,
                        on_sampling_callback: callable=None)

record from main stream for a while.

  • parameters:

    • record_duration: determines duration of the recording process.
    • name: optional; name of new record.
    • enable_compressor: optional; enable to compress the recorded data. The compressor deletes part of the signal that has lower energy than the sampled noise.
    • noise_sampling_duration: optional; noise sampling duration used by the compressor(if enabled).
    • enable_ui: optional; user inteface mode (need to install tqdm module)
    • play_recorded: optional; Determines whether the recorded file will be played after the recording process.
    • catching_precision: optional; Signal compression accuracy, more accuracy can be achieved with a smaller number (default 0.1).
    • echo_mode: It can disable the mainstream's echo mode, when the recorder is online.
    • on_start_callback: called after noise sampling.
      parameters: master object, sampled noise level, record duration time. 
      return true to continiue recording.
      
  • returns Wrapped(WrapGenerator) object


load_all
   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.
  • 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: str='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: string; '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()
wrap = master.add('file.mp3')
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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sudio-1.0.9.2.tar.gz (79.3 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page