{"id":21486356,"url":"https://github.com/dnknth/poordub","last_synced_at":"2025-03-17T10:12:09.711Z","repository":{"id":62559744,"uuid":"331417785","full_name":"dnknth/poordub","owner":"dnknth","description":"Poor man's PyDub","archived":false,"fork":false,"pushed_at":"2023-04-28T09:12:02.000Z","size":9,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-25T02:07:13.005Z","etag":null,"topics":["audio-processing","python3"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dnknth.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-01-20T20:02:52.000Z","updated_at":"2023-04-27T19:14:18.000Z","dependencies_parsed_at":"2025-01-23T19:35:58.904Z","dependency_job_id":"ba7f1d75-8d46-4a79-a263-820c103c6450","html_url":"https://github.com/dnknth/poordub","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnknth%2Fpoordub","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnknth%2Fpoordub/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnknth%2Fpoordub/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnknth%2Fpoordub/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dnknth","download_url":"https://codeload.github.com/dnknth/poordub/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244014179,"owners_count":20383715,"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-processing","python3"],"created_at":"2024-11-23T13:20:32.065Z","updated_at":"2025-03-17T10:12:09.683Z","avatar_url":"https://github.com/dnknth.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# minidub\n\nA minimalistic [PyDub](http://pydub.com) clone.\n\nThis small package was written out of curiosity about the\n[audioop](https://docs.python.org/3/library/audioop.html) module \nin the Python standard library.\nIt implements a subset of [PyDub's](http://pydub.com) features.\n\nYou probably should not use it, but [it works](tests.py) and illustrates\nhow to use [audioop](https://docs.python.org/3/library/audioop.html)\ncorrectly.\n\n## `PcmAudio` objects\n\nThe main class in this module is `PcmAudio`, which is a\nshrink-wrapped version of PyDub's `AudioSegment`, but a bit less\ncapable than the original:\n\n* Supports only file formats that Python understands, i.e. Wave, AIFF, and SunAudio.\n* Does everyting in-memory\n* Has no fancy audio effects (other than fades)\n\n## Usage\n\nTo read a file from disk, use `PcmAudio.from_file(audio_file, audio_format=wave)`,\nwhere `audio_file` can be a path or a file-like object, and `audio_format` can\nbe either `wave`, `aifc`, or `sunau`.\n\nApproximately a second of a simple sine wave can be obtained with `PcmAudio.sine(hz)`,\nand silence with `PcmAudio.silence(millis=0)`.\n\nTo add audio parts, use `+` like so: `part1 + part2`. To loop, multiply with the \nnumber of repetitions: `audio * 3`\n\nTo extract a segment from an audio clip, slice it at the desired time: `audio[start:end]`,\nwhere `start` and `end` should be in milliseconds, defaulting to `0` and the\ntotal audio length, respectively. The total audio length can be obtained with \n`len(audio)`.\n\nTo change the amplitude, add or subtract the desired amplitude change in\n[dB](https://en.wikipedia.org/wiki/Decibel): `audio - 3`.\n\nTo overlay two audio clips, use `clip1 \u0026 clip2`, but careful: This adds the \nsignals, which might result in ugly noise if the sum of amplitudes is greater than \nthe maximum possible amplitude for the sample width. If that happens, add some\nnegative gain to the clips before overlaying them.\n\nAlso make certain that audios have the same length before overlaying them.\nOtherwise, the longer part will be clipped.\n\nA rough measure of the signal [strength](https://en.wikipedia.org/wiki/DBFS)\ncan be obtained with `audio.dbfs()`. If it is too low,\n`audio.normalize(headroom=0.1)` will scale it to the max\nwith a safety margin, given in dB by `headroom`.\n\nTo write audio files, use `audio.to_file(audio_file, audio_format=wave, compression=None)`.\n`audio_file` and `audio_format` are as above, and `compression` is only supported\nfor [AIFF](https://docs.python.org/3/library/aifc.html#aifc.aifc.setcomptype) files.\n\nA memory buffer containing an audio file can be obtained with\n`audio.to_buffer(self, audio_format=wave, compression=None)`.\nTo play a clip, call `audio.play()` which returns a `simpleaudio.PlayObject`.\n\n### Fades\n\nThe only included effects are fades:\n\n* `audio.fade_in(duration, threshold=float('-inf'))`\n* `audio.fade_out(duration, threshold=float('-inf'))`\n* `audio.cross_fade(other, duration, gap=0, threshold=float('-inf'))`\n\nFor these, `duration` is in milliseconds as usual, and `threshold`\nis the minimum amplitude that needs to be exceeded in the portion \nbeing faded before the actual fade is applied.\n\nWhile this sounds somewhat technical, it improves the audible \nresult of cross-fades: If one part is already very low at \nthe beginning or the end, it needs no additional fade,\nbut can be used as-is in the overlay. Try -9dB for testing.\n\nFinally, the `gap` is the duration (in milliseconds)\nof additional silence that is inserted at each end of the \naudio parts during cross-fades. It can be used to make the transition from \none clip to another audibly clearer.\n\n### Misc\n\n`audio.to_mono()` and `audio.to_stereo()` do what their names suggest.\nAdditionally, there are two technical operations `to_framerate()` and \n`to_sample_width()` which are used internally to ensure consistency\nbetween clips before appending or overlaying. \n\n## Playback and recording\n\nPlayback and recording use `PyAudio`, which in turn depends on the \ncross-platform `portaudio` library. The former can be installed with \n`pip3 install PyAudio`, the latter with `apt-get`, `brew` or similar.\n`PyAudio` is not installed by default as a dependency, it should be\ndone manually before microphones or speakers are used.\n\nThe `AudioStream` wrapper takes care of frame I/O in **blocking**\nmode. The `open` method expects `PcmAudio.Params` with the desired\nnumber of channels, sample width and frame rate. By default, it \nopens a stream in playback mode. Pass `input=True` for recording.\n\n`AudioStream` can be used as a context manager that opens\nthe stream with default settings and closes it on exit.\n\nExample code:\n\n```python\nwith AudioStream( AudioStream.CD_AUDIO) as out:\n    out.play( some_audio)\n\nwith AudioStream( AudioStream.MONO_16KHZ).open( input=True) as in_out:\n    recording = in_out.record( 3000)\n    in_out.play( recording)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdnknth%2Fpoordub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdnknth%2Fpoordub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdnknth%2Fpoordub/lists"}