{"id":34537608,"url":"https://github.com/mkouhia/morse-audio-decoder","last_synced_at":"2025-12-24T06:08:28.467Z","repository":{"id":57443234,"uuid":"462884816","full_name":"mkouhia/morse-audio-decoder","owner":"mkouhia","description":"Solution to Wunderdog Wundernut vol. 11","archived":false,"fork":false,"pushed_at":"2022-03-07T06:46:56.000Z","size":373,"stargazers_count":9,"open_issues_count":0,"forks_count":5,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-24T23:32:26.155Z","etag":null,"topics":["audio-processing","morse-code","python"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/morse-audio-decoder/","language":"Jupyter Notebook","has_issues":true,"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/mkouhia.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-02-23T19:52:01.000Z","updated_at":"2025-09-14T15:10:16.000Z","dependencies_parsed_at":"2022-09-02T21:51:28.526Z","dependency_job_id":null,"html_url":"https://github.com/mkouhia/morse-audio-decoder","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/mkouhia/morse-audio-decoder","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkouhia%2Fmorse-audio-decoder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkouhia%2Fmorse-audio-decoder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkouhia%2Fmorse-audio-decoder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkouhia%2Fmorse-audio-decoder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mkouhia","download_url":"https://codeload.github.com/mkouhia/morse-audio-decoder/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkouhia%2Fmorse-audio-decoder/sbom","scorecard":{"id":652826,"data":{"date":"2025-08-11","repo":{"name":"github.com/mkouhia/morse-audio-decoder","commit":"ed9894f6718b85fbc3025edf94720d814482ab21"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.5,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v0.1.1 not signed: https://api.github.com/repos/mkouhia/morse-audio-decoder/releases/60689100","Warn: release artifact v0.1.0 not signed: https://api.github.com/repos/mkouhia/morse-audio-decoder/releases/60687974","Warn: release artifact v0.1.1 does not have provenance: https://api.github.com/repos/mkouhia/morse-audio-decoder/releases/60689100","Warn: release artifact v0.1.0 does not have provenance: https://api.github.com/repos/mkouhia/morse-audio-decoder/releases/60687974"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":0,"reason":"30 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2024-48 / GHSA-fj7x-q9j7-g6q6","Warn: Project is vulnerable to: GHSA-6673-4983-2vx5","Warn: Project is vulnerable to: GHSA-29gw-9793-fvw7","Warn: Project is vulnerable to: GHSA-cpwx-vrp4-4pq7","Warn: Project is vulnerable to: GHSA-gmj6-6f8f-6699","Warn: Project is vulnerable to: GHSA-h5c8-rqwp-cp95","Warn: Project is vulnerable to: GHSA-h75v-3vvj-5mfj","Warn: Project is vulnerable to: GHSA-q2x7-8rv6-6q7h","Warn: Project is vulnerable to: PYSEC-2022-288 / GHSA-6hrg-qmvc-2xh8","Warn: Project is vulnerable to: GHSA-33p9-3p43-82vq","Warn: Project is vulnerable to: PYSEC-2022-42974 / GHSA-m678-f26j-3hrp","Warn: Project is vulnerable to: GHSA-9jmq-rx5f-8jwq","Warn: Project is vulnerable to: PYSEC-2022-180 / GHSA-m87f-39q9-6f55","Warn: Project is vulnerable to: PYSEC-2022-212 / GHSA-v7vq-3x77-87vg","Warn: Project is vulnerable to: GHSA-3f63-hfp8-52jq","Warn: Project is vulnerable to: GHSA-44wm-f244-xhp3","Warn: Project is vulnerable to: PYSEC-2023-227 / GHSA-8ghj-p4vj-mr35","Warn: Project is vulnerable to: GHSA-j7hp-h8jx-5ppr","Warn: Project is vulnerable to: PYSEC-2022-42979 / GHSA-m2vv-5vj5-2hm7","Warn: Project is vulnerable to: PYSEC-2023-175","Warn: Project is vulnerable to: PYSEC-2022-42969","Warn: Project is vulnerable to: PYSEC-2023-117 / GHSA-mrwq-x4v8-fh7p","Warn: Project is vulnerable to: PYSEC-2024-110 / GHSA-jw8x-6495-233v","Warn: Project is vulnerable to: PYSEC-2023-102","Warn: Project is vulnerable to: GHSA-753j-mpmx-qq6g","Warn: Project is vulnerable to: GHSA-7cx3-6m66-7c5m","Warn: Project is vulnerable to: GHSA-8w49-h785-mj3c","Warn: Project is vulnerable to: PYSEC-2023-75 / GHSA-hj3f-6gcp-jg8j","Warn: Project is vulnerable to: GHSA-qppv-j76h-2rpx","Warn: Project is vulnerable to: GHSA-w235-7p84-xx57"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-21T13:54:03.824Z","repository_id":57443234,"created_at":"2025-08-21T13:54:03.824Z","updated_at":"2025-08-21T13:54:03.824Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27995913,"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","status":"online","status_checked_at":"2025-12-24T02:00:07.193Z","response_time":83,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","morse-code","python"],"created_at":"2025-12-24T06:08:27.730Z","updated_at":"2025-12-24T06:08:28.451Z","avatar_url":"https://github.com/mkouhia.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Morse audio decoder\n\nThis program is in solution to [Wunderdog Wundernut vol. 11][wundernut], whose instructions can be found in [their GitHub][wundernut-11-github].\n\nThe program reads wav audio file, and outputs decoded morse code in standard output.\n\n## Quickstart\n\n### Requirements\nFor now, only Python 3.10 is supported.\n\n### Installation\n\n#### Option 1 - pip\n\nYou can install this package from pip, with\n\n    pip install morse-audio-decoder\n\n#### Option 2 - Local install from sources\n\nClone code repository from your local machine, install from there:\n\n    git clone https://github.com/mkouhia/morse-audio-decoder.git\n    cd morse-audio-decoder\n    poetry build\n    # take note of the build step output, install package from the dist folder\n    pip install dist/PRODUCED_PACKAGE.whl\n\n### Usage\n\nTo run the script installed with pip, perform\n\n    morse-audio-decoder WAVFILE\n\nor alternatively,\n\n    python -m morse_audio_decoder WAVFILE\n\nwhere `WAVFILE` is path to the audio file to be processed.\n\nThe program decodes audio morse code in the WAVFILE argument, and writes translation to standard output.\nSee program help with command line flag `-h`:\n\n    $ morse-audio-decoder -h\n    usage: morse-audio-decoder [-h] WAVFILE\n\n    Read audio file in WAV format, extract the morse code and write translated text into standard output.\n\n    positional arguments:\n    WAVFILE     Input audio file\n\n    options:\n    -h, --help  show this help message and exit\n\n### Usage in Python\n\n```python\nfrom morse_audio_decoder.morse import MorseCode\n\nmorse_code = MorseCode.from_wavfile(\"/path/to/file.wav\")\nout = morse_code.decode()\nprint(out)\n```\n\n\n## Technical description\n\nThe program works in following steps\n\n1. Read in the WAV file.\n2. Extract [analytic envelope][envelope-wikipedia] from the signal by calculating moving RMS amplitude with [Hann window][hann-wikipedia] of default 0.01 second width. This envelope signal is smooth and always greater than or equal to zero.\n3. Convert envelope to binary 0/1 signal by applying threshold, by default `0.5 * max(envelope)`\n4. Calculate durations of continuous on/off samples\n5. Identify dash/dot characters and different breaks with [K-Means clustering][kmeans-wikipedia]. The lengths of periods are compared, and then labeled automatically based on number of samples.\n6. Create dash/dot character array, which is then broken to pieces by character and word space indices\n7. Translate morse coded characters into plain text, print output\n\nExploratory data analysis and first program implementation is performed in [this jupyter notebook][initial-notebook]. The notebook is not updated; actual implementation differs.\n\n\n### Restrictions\n\nThis decoder has been tested and developed with inputs that have\n- no noise\n- constant keying speed\n- constant tone pitch\n- single input channel.\n\nIf the decoder were to be extended to noisy inputs with major differences, at least following changes would be required\n- pitch detection in moving time\n- signal extraction with narrow bandpass filter, based on identified pitch\n- keying speed detection (characters/words per minute)\n- decoding in smaller time steps, taking into account speed changes.\n\nThe program is also not intended to identify single characters, as the precision will be lower with shorter inputs.\n\n## Development\n\n### Environment\n\nRequirements:\n- Python 3.10\n- Poetry (see [installation instructions][poetry-install])\n\nDependencies:\n- Numpy\n- Scikit-learn\n\n1. Install dependencies with `poetry install`\n2. Enter environment with `poetry shell`\n\n\n### Code quality and testing\n\nAll code is to be formatted with `black`:\n\n    black **/*.py\n\nand code quality checked with `pylint`:\n\n    pylint **/*.py\n\nTests should be written in `pytest`, targeting maximum practical code coverage. Tests are run with:\n\n    pytest\n\nand test coverage checked with\n\n    pytest --cov\n\nOptionally, html test coverage reports can be produced with\n\n    pytest --cov morse_audio_decoder --cov-report html\n\n### Contributions\n\nContributions are welcome. Please place an issue or a pull request.\n\n\n[wundernut]: https://www.wunderdog.fi/wundernut\n[wundernut-11-github]: https://github.com/wunderdogsw/wundernut-vol11\n[envelope-wikipedia]: https://en.wikipedia.org/wiki/Envelope_(waves)\n[hann-wikipedia]: https://en.wikipedia.org/wiki/Hann_function\n[initial-notebook]: notebooks/2022-02-23%20Wundernut%2011%20exploration.ipynb\n[kmeans-wikipedia]: https://en.wikipedia.org/wiki/K-means_clustering\n[poetry-install]: https://python-poetry.org/docs/#installation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkouhia%2Fmorse-audio-decoder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmkouhia%2Fmorse-audio-decoder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkouhia%2Fmorse-audio-decoder/lists"}