{"id":13862450,"url":"https://github.com/Quefumas/gensound","last_synced_at":"2025-07-14T12:30:52.890Z","repository":{"id":43919532,"uuid":"298906638","full_name":"Quefumas/gensound","owner":"Quefumas","description":"Pythonic audio processing and generation framework","archived":false,"fork":false,"pushed_at":"2022-11-26T22:08:21.000Z","size":6168,"stargazers_count":80,"open_issues_count":11,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-10-05T08:18:21.242Z","etag":null,"topics":["audio","audio-effect","audio-processing","audio-synthesis","dsp","music","music-composition","sound"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Quefumas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-09-26T22:01:35.000Z","updated_at":"2024-09-14T13:45:00.000Z","dependencies_parsed_at":"2023-01-22T03:47:37.911Z","dependency_job_id":null,"html_url":"https://github.com/Quefumas/gensound","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quefumas%2Fgensound","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quefumas%2Fgensound/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quefumas%2Fgensound/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quefumas%2Fgensound/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Quefumas","download_url":"https://codeload.github.com/Quefumas/gensound/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225974471,"owners_count":17553959,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audio","audio-effect","audio-processing","audio-synthesis","dsp","music","music-composition","sound"],"created_at":"2024-08-05T06:01:44.582Z","updated_at":"2024-11-22T22:31:09.726Z","avatar_url":"https://github.com/Quefumas.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# Gensound\nThe Python way to audio processing \u0026 synthesis. \n\nAn intuitive, flexible and lightweight library for:\n* Experimenting with audio and signal processing\n* Creating and manipulating sounds\n* Electronic composition\n\nCore features:\n* Platform independent\n* Very intuitive syntax\n* Easy to create new effects or experiments and combine them with existing features\n* Great for learning about audio and signals\n* Multi-channel audio for customizable placement of sound sources\n* Parametrization\n* And more to come!\n\n## Setup\n\n1. Install using `pip install gensound`.\nThis will also ensure NumPy is installed.\nFor smoother playback, it is also recommended to have any one of\n[simpleaudio](https://github.com/hamiltron/py-simple-audio),\n[playsound](https://github.com/TaylorSMarks/playsound),\n[PyGame](https://www.pygame.org) installed.\nIt is also recommended to have [FFMPEG](https://ffmpeg.org/) installed,\nwhich enables read/export of file formats other than Wave and AIFF.\n\n2. Run the examples below (or some of the example files in the repository).\n\n## Gensound in less than a minute\nAll audio is a mixture of signals (audio streams), to which we can apply transforms (effects).\n* To apply a transform to a signal we use the syntax: `Signal * Transform`;\n* To mix two signals together we use addition: `Signal + Signal`;\n* And to concatenate two signals (play one after the other): `Signal | Signal`.\n\nEach of these operations results in a new `Signal` object on which we can perform more of these operations.\n\nNow, let's run some basic examples!\n\n## Show Me the Code\n* Load a WAV into a `Signal` object from a file:\n```python\nfrom gensound import WAV, test_wav\n\nwav = WAV(test_wav) # load sample WAV, included with gensound\n```\n\n* Playback or file export:\n```python\nwav.play()\nwav.export(\"test.wav\")\n```\n\n* Play file using different sample rate (results in pitch shift):\n```python\nwav.play(sample_rate=32000) # original sample rate 44.1 kHz\n```\n\n* Play only the R channel:\n```python\nwav[1].play() # wav[0] is L channel, wav[1] is R\n```\n\n* Turn down the volume of L channel:\n```python\nwav[0] *= 0.5 # amplitude halved; wav[1] amplitude remains the same\nwav.play()\n```\n\n* Same thing, but using [dBs](https://en.wikipedia.org/wiki/Decibel):\n```python\nfrom gensound import Gain\nwav[0] *= Gain(-3) # apply Gain transform to attenuate by 3 dB\n```\n\n* Mix a Stereo signal (L-R channels) to mono (center channel only):\n```python\nwav = 0.5*wav[0] + 0.5*wav[1] # sums up L and R channels together, halving the amplitudes\n```\n\n* Switch L/R channels:\n```python\nwav[0], wav[1] = wav[1], wav[0]\n```\n\n* Crop 5 seconds from the beginning (`5e3` is short for `5000.0`, meaning 5,000 milliseconds or 5 seconds):\n```python\nwav = wav[5e3:] # since 5e3 is float, gensound knows we are not talking about channels\n```\nIf we only care about the R channel:\n```python\nwav = wav[1, 5e3:] # 5 seconds onwards, R channel only\n```\nWe can decide to slice using sample numbers (ints) instead of absolute time (floats):\n```python\nwav = wav[:,:1000] # grabs first 1000 samples in both channels; samples are in ints\n```\n\n* Repeat a signal 5 times:\n```python\nwav = wav**5\n```\n\n* Mix a 440Hz (middle A) sine wave to the L channel, 4 seconds after the beginning:\n```python\nfrom gensound import Sine\n\nwav[0,4e3:] += Sine(frequency=440, duration=2e3)*Gain(-9)\n```\n\n* Play a tune (see full syntax [here](https://github.com/Quefumas/gensound/wiki/Melodic-Shorthand-Notation)):\n```python\ns = Sine('D5 C# A F# B G# E# C# F#', duration=0.5e3)\ns.play()\n```\n\n* Reverse the R channel:\n```python\nfrom gensound import Reverse\n\nwav[1] *= Reverse()\n```\n\n* [Haas effect](https://en.wikipedia.org/wiki/Precedence_effect) - delaying the L channel by several samples makes the sound appear to be coming from the right:\n```python\nfrom gensound import Shift\n\nwav[0] *= Shift(80) # try changing the number of samples\n# when listening, pay attention to the direction the audio appears to be coming from\n```\n\n* Stretch effect - slowing down or speeding up the signal by stretching or shrinking it. This affects pitch as well:\n```python\nfrom gensound.effects import Stretch\n\nwav *= Stretch(rate=1.5) # plays the Signal 1.5 times as fast\nwav *= Stretch(duration=30e3) # alternative syntax: fit the Signal into 30 seconds\n```\n\n\n\n* Advanced: AutoPan both L/R channels with different frequency and depth:\n```python\nfrom gensound.curve import SineCurve\n\ns = WAV(test_wav)[10e3:30e3] # pick 20 seconds of audio\n\ncurveL = SineCurve(frequency=0.2, depth=50, baseline=-50, duration=20e3)\n# L channel will move in a Sine pattern between -100 (Hard L) and 0 (C)\n\ncurveR = SineCurve(frequency=0.12, depth=100, baseline=0, duration=20e3)\n# R channel will move in a Sine pattern (different frequency) between -100 and 100\n    \nt = s[0]*Pan(curveL) + s[1]*Pan(curveR)\n```\n\n\n## Syntax Cheatsheet\n\nMeet the two core classes:\n* `Signal` - a stream of multi-channeled samples, either raw (e.g. loaded from WAV file) or mathematically computable (e.g. a Sawtooth wave). Behaves very much like a `numpy.ndarray`.\n* `Transform` - any process that can be applied to a Signal (for example, reverb, filtering, gain, reverse, slicing).\n\n**By combining Signals in various ways and applying Transforms to them, we can generate anything.**\n\nSignals are envisioned as mathematical objects, and Gensound relies greatly on overloading of arithmetic operations on them, in conjunction with Transforms.\nAll of the following expressions return a new Signal object:\n* `amplitude*Signal`: change Signal's amplitude (loudness) by a given factor (float)\n* `-Signal`: inverts the Signal\n* `Signal + Signal`: mix two Signals together\n* `Signal | Signal`: concatenate two Signals one after the other\n* `Signal**4`: repeat the Signal 4 times\n* `Signal*Transform`: apply `Transform` to `Signal`\n* `Signal[start_channel:end_channel,start_ms:end_ms]`: `Signal` sliced to a certain range of channels and time (in ms). The first slice expects integers; the second expects floats.\n* `Signal[start_channel:end_channel,start_sample:end_sample]`: When the second slice finds integers instead of floats, it is interpreted as a range over samples instead of milliseconds.\n   Note that the duration of this Signal changes according to the sample rate.\n* `Signal[start_channel:end_channel]`: when a single slice of ints is given, it is taken to mean the channels.\n* `Signal[start_ms:end_ms]`: if the slice is made up of floats, it is interpreted as timestamps, i.e.: `Signal[:,start_ms:end_ms]`.\n\nThe slice notations may also be used for assignments:\n```python\nwav[4e3:4.5e3] = Sine(frequency=1e3, duration=0.5e3) # censor beep on seconds 4-4.5\nwav[0,6e3:] *= Vibrato(frequency=4, width=0.5) # add vibrato effect to L channel starting from second 6\n```\n\n...and to increase the number of channels implicitly:\n```python\nwav = WAV(\"mono_audio.wav\") # mono Signal object\nwav[1] = -wav[0] # now a stereo Signal with R being a phase inverted version of L\n```\n\n\u003e Note the convention that floats represent time as milliseconds, while integers represent number of samples.\n\n\u003c!--\nThe overloading of basic arithmetic operators means that we can generate complex signals in a Pythonic way:\n```python\nf = 220 # fundamental frequency\nsawtooth = (2/np.pi)*sum([((-1)**k/k)*Sine(frequency=k*f, duration=10e3) for k in range(1,11)])\n# approximates a sawtooth wave by the first 10 harmonics\n```\n--\u003e\n\nWhen performing playback or file export of a Signal,\nGensound resolves the Signal tree recursively, combining the various Signals and applying the transforms.\n\n## More\nI would love to hear about your experience using Gensound - what worked well, what didn't, what do you think is missing.\nDon't hesitate to [drop me a line](https://github.com/Quefumas/gensound/discussions).\n\nThe gradually evolving [Wiki](https://github.com/Quefumas/gensound/wiki) is both a tutorial and a reference,\nand will also provide many fun examples to learn and play with.\nIf you are interested in contributing, check out [Contribution](CONTRIBUTING.md).\n\n\n\n\n\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FQuefumas%2Fgensound","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FQuefumas%2Fgensound","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FQuefumas%2Fgensound/lists"}