Metadata-Version: 2.5
Name: loopyng
Version: 0.2.2
Summary: Generate synthetic signals for ML pipelines
Project-URL: Homepage, https://github.com/thorwhalen/loopyng
Project-URL: Repository, https://github.com/thorwhalen/loopyng
Project-URL: Documentation, https://thorwhalen.github.io/loopyng
Author: Thor Whalen
License-Expression: MIT
License-File: LICENSE
Keywords: audio,data,signal processing,synthetic-data,waveform
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Sound/Audio
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.10
Requires-Dist: i2
Requires-Dist: more-itertools
Requires-Dist: numpy
Requires-Dist: packaging
Requires-Dist: scipy
Requires-Dist: slink
Requires-Dist: soundfile
Provides-Extra: data
Requires-Dist: pandas; extra == 'data'
Requires-Dist: scikit-learn; extra == 'data'
Provides-Extra: dev
Requires-Dist: ipython; extra == 'dev'
Requires-Dist: matplotlib>=3.6; extra == 'dev'
Requires-Dist: pandas; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Requires-Dist: scikit-learn; extra == 'dev'
Provides-Extra: docs
Requires-Dist: sphinx-rtd-theme>=1.0; extra == 'docs'
Requires-Dist: sphinx>=6.0; extra == 'docs'
Provides-Extra: full
Requires-Dist: ipython; extra == 'full'
Requires-Dist: matplotlib>=3.6; extra == 'full'
Requires-Dist: pandas; extra == 'full'
Requires-Dist: scikit-learn; extra == 'full'
Provides-Extra: notebook
Requires-Dist: ipython; extra == 'notebook'
Requires-Dist: matplotlib>=3.6; extra == 'notebook'
Provides-Extra: viz
Requires-Dist: matplotlib>=3.6; extra == 'viz'
Description-Content-Type: text/markdown


# loopyng
Generate synthetic signals for ML pipelines


To install:	```pip install loopyng```

## Installation and extras

`pip install loopyng` gives you the signal-generation core -- every waveform
generator, the tagged-waveform streams, and `Sound` -- on top of numpy, scipy
and soundfile only.

The visualization, notebook-playback and tabular features live behind extras:

| Install | Adds | Needed for |
|---|---|---|
| `pip install loopyng` | -- | all waveform generation |
| `pip install "loopyng[viz]"` | matplotlib >= 3.6 | `plot_wf`, `disp_wf`, `specshow` |
| `pip install "loopyng[notebook]"` | IPython, matplotlib >= 3.6 | the in-notebook `Audio` playback widget |
| `pip install "loopyng[data]"` | pandas, scikit-learn | `session_to_df`, `voices_df`, `examples.annotated_sounds` |
| `pip install "loopyng[full]"` | all of the above | everything |

> **Changed in 0.2.0.** IPython, matplotlib, pandas and scikit-learn used to be
> hard requirements, so a bare `pip install loopyng` pulled the whole plotting
> and data-science stack in for a library whose core is numpy arrays. They are
> now extras. If you use the plotting or notebook features, install
> `loopyng[viz]`, `loopyng[notebook]` or `loopyng[full]` instead. Nothing fails
> silently -- calling a function that needs a missing extra raises an
> `ImportError` telling you exactly which one to install.

# functionality
This notebook gathers various examples of the functionality of `loopyng`:
- Synthetic datasets
    - sound-like datasets
    - diagnosis datasets
    - signal generation
- Plotting and visualization
    - plot
    - display
    - melspectrograms
- Infinite waveform from spectrums
- Various sample sounds
- Voiced time


```python
from loopyng import (
    mk_sine_wf,
    freq_based_stationary_wf,
    BinarySound,
    WfGen,
    TimeSound,
    mk_some_buzz_wf,
    wf_with_timed_bleeps,
    Sound,
    plot_wf,
    disp_wf,
    InfiniteWaveform,
    Voicer,
    tell_time_continuously,
    random_samples,
    pure_tone,
    triangular_tone,
    square_tone,
    AnnotatedWaveform,
    gen_words,
    categorical_gen,
    bernoulli_gen,
    create_session,
    session_to_df,
)
import matplotlib.pyplot as plt
from numpy.random import randint
import numpy as np
```

## Synthetic datasets
There are several different forms of synthetic data that `loopyng` can produce to be used in machine learning pipelines, with the first being sound-like datasets generally in the form of sine waves 

### Sound-like datasets

`mk_sine_wf` provides an easy way to generate a simple waveform for synthetic testing purposes


```python
DFLT_N_SAMPLES = 21 * 2048
DFLT_SR = 44100
wf = mk_sine_wf(freq=5, n_samples=DFLT_N_SAMPLES, sr=DFLT_SR, phase=0, gain=1)
plt.plot(wf)
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_6_0.png)
    



```python
wf = mk_sine_wf(freq=20, n_samples=DFLT_N_SAMPLES, sr=DFLT_SR, phase=0.25, gain=3)
plt.plot(wf)
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_7_0.png)
    


`freq_based_stationary_wf` provides the ability to generate a more complex waveform by mixing sine waves of different frequencies with potentially different weights


```python
wf_mix = freq_based_stationary_wf(
    freqs=(2, 4, 6, 8), weights=None, n_samples=DFLT_N_SAMPLES, sr=DFLT_SR
)
plt.plot(wf_mix)
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_9_0.png)
    



```python
wf_mix = freq_based_stationary_wf(
    freqs=(2, 4, 6, 8), weights=(3, 3, 1, 1), n_samples=DFLT_N_SAMPLES, sr=DFLT_SR
)
plt.plot(wf_mix)
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_10_0.png)
    


`WfGen` is a class that allows for the generation of sinusoidal waveforms, the generation of lookup tables to be used in generating waveforms, and frequency weighted mixed waveforms


```python
wfgen = WfGen(sr=44100, buf_size_frm=2048, amplitude=0.5)
lookup = np.array(wfgen.mk_lookup_table(freq=880))
wf = wfgen.mk_sine_wf(n_frm=100, freq=880)
```


```python
np.array(lookup).T
```




    array([ 0.        ,  0.06252526,  0.12406892,  0.1836648 ,  0.24037727,
            0.293316  ,  0.34164989,  0.38462013,  0.42155213,  0.45186607,
            0.47508605,  0.49084754,  0.49890309,  0.49912624,  0.49151348,
            0.47618432,  0.45337943,  0.42345682,  0.38688626,  0.34424188,
            0.29619315,  0.24349441,  0.186973  ,  0.12751624,  0.06605758,
            0.00356187, -0.05898977, -0.12061531, -0.18034728, -0.23724793,
           -0.29042397, -0.33904057, -0.38233448, -0.41962604, -0.45032977,
           -0.47396367, -0.4901567 , -0.49865463, -0.49932406, -0.49215447,
           -0.47725843, -0.45486979, -0.42534003, -0.38913276, -0.34681639,
           -0.29905527, -0.2465992 , -0.19027171, -0.13095709, -0.06958655])




```python
plt.plot(wf)
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_14_0.png)
    



```python
wf_weight = wfgen.mk_wf_from_freq_weight_array(
    n_frm=10000, freq_weight_array=(10, 1, 6)
)
plt.plot(wf_weight)
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_15_0.png)
    


### Diagnosis datasets
`loopyng` can also produce diagnosis datasets to be applied to machine learning pipelines

`BinarySound` is a class that generates binary waveforms


```python
bs = BinarySound(nbits=50, redundancy=142, repetition=3, header_size_words=1)
utc = randint(0, 2, 50)
wf = bs.mk_phrase(utc)
plt.plot(wf[:200])
all(bs.decode(wf) == utc)
```




    True




    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_18_1.png)
    


`BinarySound` can also be instantiated using audio parameters using the `for_audio_params` class method


```python
bs = BinarySound.for_audio_params(
    nbits=50, freq=6000, chk_size_frm=43008, sr=44100, header_size_words=1
)
wf = bs.mk_phrase(utc)
plt.plot(wf[:200])
all(bs.decode(wf) == utc)
```




    True




    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_20_1.png)
    


utc phrases can be generated using `mk_utc_phrases` when `BinarySound` is instantiated with audio parameters


```python
plt.plot(bs.mk_utc_phrases()[:200])
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_22_0.png)
    


`TimeSound` is a class that generates timestamped waveform data


```python
time = TimeSound(sr=44100, buf_size_frm=2048, amplitude=0.5, n_ums_bits=30)
wf = time.timestamped_wf()
plt.plot(wf[2000:2300])
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_24_0.png)
    


`mk_some_buzz_wf` and `wf_with_timed_bleeps` are two more options to generate synthetic data of diagnosis sounds


```python
wf = mk_some_buzz_wf(sr=DFLT_SR)
plt.plot(wf[:500])
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_26_0.png)
    



```python
wf = wf_with_timed_bleeps(
    n_samples=DFLT_SR * 2, bleep_loc=400, bleep_spec=100, sr=DFLT_SR
)
plt.plot(wf[:150])
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_27_0.png)
    


### Signal generation

`loopyng` can create signals generated by sequences of symbols, perturbed by outliers injected at given points


```python
symb_res = categorical_gen(gen_words)
out_res = bernoulli_gen(p_out=0.01)
df = session_to_df(
    create_session(symb_res, out_res, alphabet=list("abcde"), session_length=500)
)
df.plot(subplots=True, figsize=(20, 7))
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_30_0.png)
    


## Plotting and visualization
`loopyng` also provides several options for plotting and visualization for the synthetic datasets it generates


```python
wfgen = WfGen()
wf = list()
for i in range(1, 1000, 20):
    wf.extend(list(wfgen.mk_sine_wf(n_frm=2048, freq=i)))
wf = np.array(wf)
sr = 44100
```

### Plot waveform


```python
plot_wf(wf[:20000], sr)
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_34_0.png)
    


### Display waveform


```python
disp_wf(wf, sr)
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_36_0.png)
    


### Melspectrograms with `Sound`


```python
snd = Sound(wf=wf, sr=sr)
```


```python
snd.plot_wf(wf=wf[:20000], sr=sr)
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_39_0.png)
    



```python
snd.melspectrogram(plot_it=False)
```




    array([[-63.34856485, -45.14910401, -36.14726097, ..., -80.        ,
            -73.35788085, -60.58728436],
           [-67.99632241, -74.80503122, -80.        , ..., -80.        ,
            -72.1600597 , -60.16803079],
           [-80.        , -80.        , -80.        , ..., -80.        ,
            -72.90050429, -60.90871386],
           ...,
           [-80.        , -80.        , -80.        , ..., -80.        ,
            -80.        , -80.        ],
           [-80.        , -80.        , -80.        , ..., -80.        ,
            -80.        , -80.        ],
           [-80.        , -80.        , -80.        , ..., -80.        ,
            -80.        , -80.        ]])




```python
snd.display()
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_41_0.png)
    


## Infinite waveform from spectrum
`loopyng` also provides the functionality to create an infinite waveform based on a given spectrum, and a noise amplifier if desired


```python
iwf = InfiniteWaveform(wf)
```


```python
wf = list(iwf.query(0, 500000))
```


```python
disp_wf(wf)
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_45_0.png)
    



```python
Sound(wf=wf).display()
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_46_0.png)
    


## Sample sounds
`loopyng` also provides several functions to generate sample sounds shown below

### Random sample


```python
wf = random_samples(chk_size_frm=21 * 2048, max_amplitude=30000)
disp_wf(wf=wf, sr=sr)
Sound(wf=wf).display()
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_49_0.png)
    



    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_49_1.png)
    


### Pure tone sample


```python
wf = pure_tone(chk_size_frm=21 * 2048, freq=440, sr=44100, max_amplitude=30000)
disp_wf(wf=wf, sr=sr)
Sound(wf=wf).display()
```

    .../site-packages/matplotlib/axes/_axes.py:7723: RuntimeWarning: divide by zero encountered in log10
      Z = 10. * np.log10(spec)



    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_51_1.png)
    



    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_51_2.png)
    


### Triangular tone sample


```python
wf = triangular_tone(chk_size_frm=21 * 2048, freq=440, sr=44100, max_amplitude=30000)
disp_wf(wf=wf, sr=sr)
Sound(wf=wf).display()
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_53_0.png)
    



    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_53_1.png)
    


### Square tone sample


```python
wf = square_tone(chk_size_frm=21 * 2048, freq=440, sr=44100, max_amplitude=30000)
disp_wf(wf=wf, sr=sr)
Sound(wf=wf).display()
```


    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_55_0.png)
    



    
![png](https://github.com/thorwhalen/loopyng/raw/main/notebooks/loopyng_demo_files/loopyng_demo_55_1.png)
    


### Annotated Waveform


```python
awf = AnnotatedWaveform(chk_size_frm=21 * 2048, freq=440, sr=44100, max_amplitude=30000)
gen = awf.chk_and_tag_gen()
list(gen)
```




    [(array([-14025,  11555,  22270, ...,  10243, -18225,   3874], dtype=int16),
      'random'),
     (array([    0,  1902,  3797, ...,  9361, 11149, 12893], dtype=int16),
      'pure_tone'),
     (array([-30000, -29900, -29800, ...,  10500,  10600,  10700], dtype=int16),
      'triangular_tone'),
     (array([30000, 30000, 30000, ..., 30000, 30000, 30000], dtype=int16),
      'square_tone')]




```python
awf.get_wf_and_annots()
```




    (array([  5183,  10421, -21645, ...,  30000,  30000,  30000], dtype=int16),
     {'random': [(0, 43008)],
      'pure_tone': [(43008, 86016)],
      'triangular_tone': [(86016, 129024)],
      'square_tone': [(129024, 172032)]})



## Voiced time
Finally `loopyng` provides a function that will tell the time continuously with parameters for the frequency, speed, voice, volume, and time format


```python
tell_time_continuously(every_secs=5, verbose=True)
```

    15 45 11
    15 45 16
    15 45 21
    15 45 26
    KeyboardInterrupt!!!

