Browse Source

add some stuff

master
Ondřej Hruška 2 years ago
commit
8820089289
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 1
      .gitignore
  2. 11
      .idea/beeptestrs.iml
  3. 8
      .idea/modules.xml
  4. 6
      .idea/vcs.xml
  5. 138
      .idea/workspace.xml
  6. 596
      Cargo.lock
  7. 12
      Cargo.toml
  8. 152
      src/beep.rs
  9. 424
      src/beep/osc.rs
  10. 7
      src/main.rs

1
.gitignore vendored

@ -0,0 +1 @@
/target

11
.idea/beeptestrs.iml

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="CPP_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
.idea/modules.xml

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/beeptestrs.iml" filepath="$PROJECT_DIR$/.idea/beeptestrs.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

138
.idea/workspace.xml

@ -0,0 +1,138 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeRunConfigurationManager" shouldGenerate="true" shouldDeleteObsolete="true">
<generated />
</component>
<component name="CMakeSettings">
<configurations>
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
</configurations>
</component>
<component name="CargoProjects">
<cargoProject FILE="$PROJECT_DIR$/Cargo.toml" />
</component>
<component name="ChangeListManager">
<list default="true" id="10cd9b57-3049-40f7-975a-a181479596b3" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/src/beep/osc.rs" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ClangdSettings">
<option name="formatViaClangd" value="false" />
</component>
<component name="FileColors">
<fileColor scope="Non-Project Files (Material Default)" color="2E3C43" />
<fileColor scope="Non-Project Files (Material Darker)" color="323232" />
<fileColor scope="Non-Project Files (Material Lighter)" color="eae8e8" />
<fileColor scope="Non-Project Files (Material Palenight)" color="2f2e43" />
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Rust File" />
</list>
</option>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="MacroExpansionManager">
<option name="directoryName" value="zqz5wsij" />
</component>
<component name="ProjectId" id="1jMxUiuWWUW9kd7fLhEhnNAF1kh" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="cf.first.check.clang-format" value="false" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.detected.package.tslint" value="true" />
<property name="node.js.path.for.package.eslint" value="project" />
<property name="node.js.path.for.package.tslint" value="project" />
<property name="node.js.selected.package.eslint" value="(autodetect)" />
<property name="node.js.selected.package.tslint" value="(autodetect)" />
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
<property name="org.rust.cargo.project.model.PROJECT_DISCOVERY" value="true" />
<property name="settings.editor.selected.configurable" value="editor.preferences.gutterIcons" />
</component>
<component name="RunManager">
<configuration name="Run" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="channel" value="DEFAULT" />
<option name="command" value="run --package beeptestrs --bin beeptestrs" />
<option name="allFeatures" value="false" />
<option name="emulateTerminal" value="false" />
<option name="backtrace" value="SHORT" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<envs />
<method v="2">
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
</method>
</configuration>
<configuration default="true" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="channel" value="DEFAULT" />
<option name="command" value="run" />
<option name="allFeatures" value="false" />
<option name="emulateTerminal" value="false" />
<option name="backtrace" value="SHORT" />
<envs />
<method v="2">
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
</method>
</configuration>
</component>
<component name="RustProjectSettings">
<option name="toolchainHomeDirectory" value="/usr/bin" />
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="10cd9b57-3049-40f7-975a-a181479596b3" name="Default Changelist" comment="" />
<created>1603627779596</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1603627779596</updated>
<workItem from="1603627780818" duration="18022000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="WindowStateProjectService">
<state x="769" y="331" key="#com.intellij.ide.util.MemberChooser" timestamp="1603643362566">
<screen x="0" y="32" width="1920" height="1168" />
</state>
<state x="769" y="331" key="#com.intellij.ide.util.MemberChooser/0.32.1920.1168/1920.0.1600.1200@0.32.1920.1168" timestamp="1603643362566" />
<state width="1600" height="1109" key="GridCell.Tab.0.bottom" timestamp="1603650855702">
<screen x="0" y="32" width="1920" height="1168" />
</state>
<state width="1600" height="1109" key="GridCell.Tab.0.bottom/0.32.1920.1168/1920.0.1600.1200@0.32.1920.1168" timestamp="1603650855702" />
<state width="1600" height="1109" key="GridCell.Tab.0.center" timestamp="1603650855702">
<screen x="0" y="32" width="1920" height="1168" />
</state>
<state width="1600" height="1109" key="GridCell.Tab.0.center/0.32.1920.1168/1920.0.1600.1200@0.32.1920.1168" timestamp="1603650855702" />
<state width="1600" height="1109" key="GridCell.Tab.0.left" timestamp="1603650855702">
<screen x="0" y="32" width="1920" height="1168" />
</state>
<state width="1600" height="1109" key="GridCell.Tab.0.left/0.32.1920.1168/1920.0.1600.1200@0.32.1920.1168" timestamp="1603650855702" />
<state width="1600" height="1109" key="GridCell.Tab.0.right" timestamp="1603650855702">
<screen x="0" y="32" width="1920" height="1168" />
</state>
<state width="1600" height="1109" key="GridCell.Tab.0.right/0.32.1920.1168/1920.0.1600.1200@0.32.1920.1168" timestamp="1603650855702" />
<state x="651" y="325" width="635" height="580" key="find.popup" timestamp="1603633050478">
<screen x="0" y="32" width="1920" height="1168" />
</state>
<state x="651" y="325" width="635" height="580" key="find.popup/0.32.1920.1168/1920.0.1600.1200@0.32.1920.1168" timestamp="1603633050478" />
<state width="1007" height="578" key="javadoc.popup.new" timestamp="1603640885345">
<screen x="0" y="32" width="1920" height="1168" />
</state>
<state width="1007" height="578" key="javadoc.popup.new/0.32.1920.1168/1920.0.1600.1200@0.32.1920.1168" timestamp="1603640885345" />
</component>
</project>

596
Cargo.lock generated

@ -0,0 +1,596 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "alsa"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44581add1add74ade32aca327b550342359ec00191672c23c1caa3d492b85930"
dependencies = [
"alsa-sys",
"bitflags",
"libc",
"nix",
]
[[package]]
name = "alsa-sys"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5a0559bcd3f7a482690d98be41c08a43e92f669b179433e95ddf5e8b8fd36a3"
dependencies = [
"libc",
"pkg-config",
]
[[package]]
name = "anyhow"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1fd36ffbb1fb7c834eac128ea8d0e310c5aeb635548f9d58861e1308d46e71c"
[[package]]
name = "beeptestrs"
version = "0.1.0"
dependencies = [
"anyhow",
"cpal",
"parking_lot 0.11.0",
]
[[package]]
name = "bindgen"
version = "0.53.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c72a978d268b1d70b0e963217e60fdabd9523a941457a6c42a7315d15c7e89e5"
dependencies = [
"bitflags",
"cexpr",
"cfg-if 0.1.10",
"clang-sys",
"lazy_static",
"lazycell",
"peeking_take_while",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
]
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bumpalo"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
[[package]]
name = "cc"
version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed67cbde08356238e75fc4656be4749481eeffb09e19f320a25237d5221c985d"
[[package]]
name = "cexpr"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clang-sys"
version = "0.29.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
[[package]]
name = "cloudabi"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467"
dependencies = [
"bitflags",
]
[[package]]
name = "core-foundation-sys"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
[[package]]
name = "coreaudio-rs"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f229761965dad3e9b11081668a6ea00f1def7aa46062321b5ec245b834f6e491"
dependencies = [
"bitflags",
"coreaudio-sys",
]
[[package]]
name = "coreaudio-sys"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6570ee6e089131e928d5ec9236db9e818aa3cf850f48b0eec6ef700571271d4"
dependencies = [
"bindgen",
]
[[package]]
name = "cpal"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4410231e181e24e3e4612dfca601601e40942003e6a52a12d9d80f19fd9737"
dependencies = [
"alsa",
"core-foundation-sys",
"coreaudio-rs",
"js-sys",
"lazy_static",
"libc",
"mach",
"nix",
"parking_lot 0.9.0",
"stdweb",
"thiserror",
"web-sys",
"winapi",
]
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "instant"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb1fc4429a33e1f80d41dc9fea4d108a88bec1de8053878898ae448a0b52f613"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "js-sys"
version = "0.3.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743"
[[package]]
name = "libloading"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"
dependencies = [
"cc",
"winapi",
]
[[package]]
name = "lock_api"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
dependencies = [
"scopeguard",
]
[[package]]
name = "lock_api"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
dependencies = [
"cfg-if 0.1.10",
]
[[package]]
name = "mach"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
dependencies = [
"libc",
]
[[package]]
name = "maybe-uninit"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
[[package]]
name = "memchr"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
[[package]]
name = "nix"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229"
dependencies = [
"bitflags",
"cc",
"cfg-if 0.1.10",
"libc",
"void",
]
[[package]]
name = "nom"
version = "5.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
dependencies = [
"memchr",
"version_check",
]
[[package]]
name = "parking_lot"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
dependencies = [
"lock_api 0.3.4",
"parking_lot_core 0.6.2",
"rustc_version",
]
[[package]]
name = "parking_lot"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733"
dependencies = [
"instant",
"lock_api 0.4.1",
"parking_lot_core 0.8.0",
]
[[package]]
name = "parking_lot_core"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
dependencies = [
"cfg-if 0.1.10",
"cloudabi 0.0.3",
"libc",
"redox_syscall",
"rustc_version",
"smallvec 0.6.13",
"winapi",
]
[[package]]
name = "parking_lot_core"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
dependencies = [
"cfg-if 0.1.10",
"cloudabi 0.1.0",
"instant",
"libc",
"redox_syscall",
"smallvec 1.4.2",
"winapi",
]
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "pkg-config"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "proc-macro2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
[[package]]
name = "regex"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8963b85b8ce3074fecffde43b4b0dded83ce2f367dc8d363afc56679f3ee820b"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cab7a364d15cde1e505267766a2d3c4e22a843e1a601f0fa7564c0f82ced11c"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "shlex"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
[[package]]
name = "smallvec"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
dependencies = [
"maybe-uninit",
]
[[package]]
name = "smallvec"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252"
[[package]]
name = "stdweb"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e"
[[package]]
name = "syn"
version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "thiserror"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "318234ffa22e0920fe9a40d7b8369b5f649d490980cf7aadcf1eb91594869b42"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cae2447b6282786c3493999f40a9be2a6ad20cb8bd268b0a0dbf5a065535c0ab"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "version_check"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "wasm-bindgen"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42"
dependencies = [
"cfg-if 0.1.10",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307"
[[package]]
name = "web-sys"
version = "0.3.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

12
Cargo.toml

@ -0,0 +1,12 @@
[package]
name = "beeptestrs"
version = "0.1.0"
authors = ["Ondřej Hruška <ondra@ondrovo.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cpal = "0.12.1"
anyhow = "1.0.33"
parking_lot = "0.11.0"

152
src/beep.rs

@ -0,0 +1,152 @@
use std::sync::Arc;
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use std::ops::{Add, AddAssign, Sub};
use parking_lot::RwLock;
use std::time::Duration;
use std::thread;
use cpal::SampleFormat;
use crate::beep::osc::{Instrument, Oscillator};
pub mod osc;
struct AudioContext {
device: cpal::Device,
sample_format: SampleFormat,
config: cpal::StreamConfig
}
fn al_init() -> Result<AudioContext, anyhow::Error> {
let host = cpal::default_host();
let device = host.default_output_device()
.ok_or_else(|| anyhow::anyhow!("No audio output device!"))?;
let config = device.default_output_config()?;
Ok(AudioContext {
device,
sample_format: config.sample_format(),
config: config.into()
})
}
pub fn beep() -> Result<(), anyhow::Error> {
let ac = al_init()?;
match ac.sample_format {
cpal::SampleFormat::F32 => run::<f32>(&ac.device, &ac.config.into())?,
cpal::SampleFormat::I16 => run::<i16>(&ac.device, &ac.config.into())?,
cpal::SampleFormat::U16 => run::<u16>(&ac.device, &ac.config.into())?,
}
Ok(())
}
fn run<T>(device: &cpal::Device, config: &cpal::StreamConfig) -> Result<(), anyhow::Error>
where
T: cpal::Sample,
{
let sample_rate = config.sample_rate.0 as f32;
let channels = config.channels as usize;
println!("SR={}",sample_rate);
// Produce a sinusoid of maximum amplitude.
let mut ins = Instrument::new(vec![
Oscillator::new(440.0, 1.0, sample_rate),
//Oscillator::new(441.0, 1.0, sample_rate),
], sample_rate);
let instrument = Arc::new(parking_lot::RwLock::new(ins));
let err_fn = |err| eprintln!("an error occurred on stream: {}", err);
let m_instrument = instrument.clone();
let stream = device.build_output_stream(
config,
move |data: &mut [T], _: &cpal::OutputCallbackInfo| {
write_data(data, channels, &m_instrument)
},
err_fn,
)?;
stream.play()?;
// instrument.write().normalize(false);
// instrument.write().set_amp(1.0);
// thread::sleep(Duration::from_millis(500));
//
// instrument.write().set_amp(0.0);
// thread::sleep(Duration::from_millis(250));
instrument.write().set_amp(1.0);
instrument.write().normalize(true);
thread::sleep(Duration::from_millis(500));
instrument.write().set_amp(0.0);
thread::sleep(Duration::from_millis(250));
instrument.write().set_amp(0.5);
thread::sleep(Duration::from_millis(500));
instrument.write().set_amp(0.0);
thread::sleep(Duration::from_millis(250));
instrument.write().fade_amp(1.0, Duration::from_millis(10));
instrument.write().waveforms[0].fade_balance(-1.0, Duration::from_millis(10));
thread::sleep(Duration::from_millis(500));
instrument.write().fade_amp(0.0, Duration::from_millis(10));
thread::sleep(Duration::from_millis(500));
/*
//instrument.write().set_amp_fade(0.0, 4.0);
thread::sleep(Duration::from_millis(1000));
instrument.write().waveforms[1].fade_amp(0.0, Duration::from_millis(500));
thread::sleep(Duration::from_millis(500));
instrument.write().waveforms[0].fade_balance(-1.0, Duration::from_millis(1000));
thread::sleep(Duration::from_millis(1000));
instrument.write().waveforms[0].fade_balance(1.0, Duration::from_millis(2000));
instrument.write().waveforms[0].fade_freq(880.0, Duration::from_millis(1000));
thread::sleep(Duration::from_millis(2000));
instrument.write().waveforms[0].fade_balance(-1.0, Duration::from_millis(1000));
instrument.write().waveforms[0].fade_amp(0.0, Duration::from_millis(1000));
thread::sleep(Duration::from_millis(1000));
*/
// for _ in 0..10
// {
// instrument.write().harmonics[0].set_balance_fade(-1.0, 0.1);
// thread::sleep(Duration::from_millis(100));
// instrument.write().harmonics[0].set_balance_fade(1.0, 0.1);
// thread::sleep(Duration::from_millis(100));
// }
//
// instrument.write().harmonics[0].set_balance_fade(0.0, 0.5);
// instrument.write().harmonics[0].set_amp_fade(0.0, 0.05);
// thread::sleep(Duration::from_millis(200));
Ok(())
}
fn write_data<T>(output: &mut [T], channels: usize, instrument: &Arc<RwLock<Instrument>>)
where
T: cpal::Sample,
{
let mut instrument = instrument.write();
for frame in output.chunks_mut(channels) {
let sample = instrument.sample();
if channels == 1 {
frame[0] = cpal::Sample::from::<f32>(&((sample.left + sample.right) / 2.0));
} else {
frame[0] = cpal::Sample::from::<f32>(&sample.left);
frame[1] = cpal::Sample::from::<f32>(&sample.right);
}
}
}

424
src/beep/osc.rs

@ -0,0 +1,424 @@
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign};
use std::sync::Arc;
use std::time::Duration;
use parking_lot::RwLock;
use hack::StableClamp;
mod hack {
/// Work-around for `f32::clamp()` being unstable
pub(super) trait StableClamp {
fn clamp_(self, min: f32, max: f32) -> f32;
}
impl StableClamp for f32 {
fn clamp_(self, min: f32, max: f32) -> f32 {
assert!(min <= max);
let mut x = self;
if x < min {
x = min;
}
if x > max {
x = max;
}
x
}
}
}
/// Value fader
#[derive(Clone,Debug)]
struct Tween {
/// Actual value
actual: f32,
/// Target value, approached by adding "step" to :actual" every sample
target: f32,
/// Value added to "actual" per sample. None = set to target at the end of a cycle
step: Option<f32>,
// Min value
min: f32,
// Max value
max: f32,
}
/// Scale function amplitude by a gain
trait GainScale {
fn scale_gain(self, gain: f32) -> Self;
}
impl GainScale for f32 {
/// Scale by gain 0-1
fn scale_gain(self, gain: f32) -> Self {
// TODO what scaling to use?
// self * (1.0 + gain * 9.0).log10()
// self * gain.sqrt()
self * gain
}
}
impl Tween {
/// Update values for the next sample
pub fn tick(&mut self) {
if let Some(step) = self.step {
let actual0 = self.actual;
self.actual += step;
if (self.target > actual0 && self.target <= self.actual)
|| (self.target <= actual0 && self.target > self.actual)
{
self.step = None;
self.actual = self.target;
}
}
}
/// Get actual value
pub fn actual(&self) -> f32 {
self.actual
}
/// Check if the change from actual to target is scheduled to happen instantly
/// at the end of a cycle.
pub fn is_change_scheduled_at_crossover(&self) -> bool {
self.target != self.actual
&& self.step.is_none()
}
/// Check if the fading is in progress
pub fn is_fading(&self) -> bool {
self.step.is_some()
}
/// Schedule change at crossover
fn set_at_crossover(&mut self, val: f32) {
self.target = val.clamp_(self.min, self.max);
self.step = None; // change at the earliest convenience
}
/// Start fading
fn fade(&mut self, val: f32, time: Duration, sample_rate: f32) {
self.target = val.clamp_(self.min, self.max);
let nsamples = (time.as_secs_f32() * sample_rate).ceil();
self.step = Some((self.target - self.actual) / nsamples);
}
/// Set value immediately
fn set_immediate(&mut self, val: f32) {
self.target = val;
self.actual = val;
self.step = None;
}
}
#[derive(Clone,Debug)]
pub struct Oscillator {
/// Amplitude fader 0..1
gain: Tween,
/// Frequency fader 1..22050
freq: Tween,
/// Balance fader -1..1
balance: Tween,
/// Left channel multiplier
gain_left: f32,
/// Right channel multiplier
gain_right: f32,
/// Sample rate (Hz)
sample_rate: f32,
/// Phase increment per sample
phase_step: f32,
/// Phase 0-TAU
phase: f32,
}
impl Oscillator {
/// New oscillator with a frequency and amplitude
pub fn new(freq: f32, amp: f32, sample_rate : f32) -> Self {
let mut o = Self {
gain: Tween {
actual: amp,
target: amp,
min: 0.0,
max: 1.0,
step: None
},
freq: Tween {
actual: freq,
target: freq,
min: 1.0,
max: sample_rate / 2.0,
step: None
},
balance: Tween {
actual: 0.0,
target: 0.0,
min: -1.0,
max: 1.0,
step: None
},
phase_step: 0.0,
gain_left: 0.0,
gain_right: 0.0,
sample_rate,
phase: 0.0
};
o.update_step();
o.update_gains(1.0);
o
}
/// Update the step variable
fn update_step(&mut self) {
self.phase_step = (self.freq.actual / self.sample_rate) * std::f32::consts::TAU;
}
/// Update the pre-computed channel gain variables
fn update_gains(&mut self, gain_scale: f32) {
let angle = ((1.0 + self.balance.actual) / 2.0) * std::f32::consts::FRAC_PI_2;
let act = self.gain.actual * gain_scale;
self.gain_left = act.scale_gain(angle.sin());
self.gain_right = act.scale_gain(angle.cos());
}
/// Get actual amplitude (0..1)
pub fn get_amp(&self) -> f32 {
self.gain.actual
}
/// Set amplitude (0..1), change at the end of the current waveform to reduce popping
pub fn set_amp(&mut self, amp : f32) {
self.gain.set_at_crossover(amp);
}
/// Fade to amplitude (0..1) over a given time
pub fn fade_amp(&mut self, amp : f32, time: Duration) {
self.gain.fade(amp, time, self.sample_rate);
}
/// Get balance value (-1..1)
pub fn get_balance(&self) -> f32 {
self.balance.actual
}
/// Set balance (-1..1), change at the end of the current waveform to reduce popping
pub fn set_balance(&mut self, balance : f32) {
self.balance.set_at_crossover(balance);
}
/// Fade to balance (-1..1) over a given time
pub fn fade_balance(&mut self, balance : f32, time: Duration) {
self.balance.fade(balance, time, self.sample_rate);
}
/// Get frequency value (1..22050)
pub fn get_freq(&self) -> f32 {
self.freq.actual
}
/// Set frequency (1..22050), change at the end of the current waveform to reduce popping
pub fn set_freq(&mut self, freq : f32) {
self.freq.set_at_crossover(freq);
}
/// Fade to frequency (1..22050) over a given time
pub fn fade_freq(&mut self, freq : f32, time: Duration) {
self.freq.fade(freq, time, self.sample_rate);
}
/// Take a sample. Mutable to update faders.
pub fn sample(&mut self, gain_scale: f32) -> StereoSample {
if self.freq.is_fading() {
self.freq.tick();
self.update_step();
}
if self.balance.is_fading() || self.gain.is_fading() {
self.balance.tick();
self.gain.tick();
self.update_gains(gain_scale);
}
let ph0 = self.phase;
self.phase = (self.phase + self.phase_step) % std::f32::consts::TAU;
// "zero crossing detection"
if self.phase < ph0 {
if self.gain.is_change_scheduled_at_crossover() {
self.gain.actual = self.gain.target;
self.update_gains(gain_scale);
}
if self.balance.is_change_scheduled_at_crossover() {
self.balance.actual = self.balance.target;
self.update_gains(gain_scale);
}
if self.freq.is_change_scheduled_at_crossover() {
self.freq.actual = self.freq.target;
}
}
let y = self.phase.sin() * self.gain.actual;
StereoSample {
left: self.gain_left * y,
right: self.gain_right * y,
}
}
}
/// Waveform generator with multiple frequencies / waveforms
#[derive(Clone,Debug)]
pub struct Instrument {
/// Waveforms to combine to produce the final sound
pub waveforms: Vec<Oscillator>,
/// Normalize the output to produce constant amplitude of 1.0 (instead of clipping)
normalize: bool,
sample_rate : f32,
master: Tween,
}
impl Instrument {
pub fn new(waveforms: Vec<Oscillator>, sample_rate: f32) -> Self {
let mut o = Self {
waveforms,
normalize: false,
sample_rate,
master: Tween {
actual: 1.0,
target: 1.0,
step: None,
min: 0.0,
max: 1.0
}
};
o
}
pub fn normalize(&mut self, normalize: bool) {
self.normalize = normalize;
// This is an artifact of how Oscillator works internally:
// The left/right gains are pre-computed and updated only when they change
if normalize {
self.force_normalize();
} else {
self.waveforms.iter_mut()
.for_each(|item| item.update_gains(1.0));
}
}
pub fn get_amp(&self) -> f32 {
self.master.actual()
}
pub fn set_amp(&mut self, amp : f32) {
self.master.set_immediate(amp);
}
pub fn fade_amp(&mut self, amp : f32, time: Duration) {
self.master.fade(amp, time, self.sample_rate);
}
fn force_normalize(&mut self) {
let gain_scale = 1.0 / self.waveforms.iter()
.fold((0.0), |acc, item| acc + item.gain.actual);
println!("Gain scale {}", gain_scale);
self.waveforms.iter_mut()
.for_each(|item| item.update_gains(gain_scale));
}
/// Get a sample (left, right)
pub fn sample(&mut self) -> StereoSample {
self.master.tick();
let gain_scaling = if self.normalize {
1.0 / self.waveforms.iter()
.fold((0.0), |acc, item| acc + item.gain.actual)
} else {
1.0
};
let (mut value, gains)= self.waveforms.iter_mut()
.fold((StereoSample::default(), 0.0), |mut acc, item| {
acc.0 += item.sample(gain_scaling);
acc.1 += item.gain.actual;
acc
});
if self.normalize {
value.left /= gains;
value.right /= gains;
}
value.left = value.left.scale_gain(self.master.actual).clamp_(-1.0, 1.0);
value.right = value.right.scale_gain(self.master.actual).clamp_(-1.0, 1.0);
value.clip()
}
}
#[derive(Default, Clone, Copy)]
pub struct StereoSample {
pub left: f32,
pub right: f32,
}
impl StereoSample {
pub fn clip(self) -> Self {
Self {
left: self.left.clamp_(-1.0, 1.0),
right: self.right.clamp_(-1.0, 1.0),
}
}
}
impl Add for StereoSample {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self {
left: self.left + rhs.left,
right: self.right + rhs.right,
}
}
}
impl Div<f32> for StereoSample {
type Output = Self;
fn div(self, rhs: f32) -> Self::Output {
Self {
left: self.left / rhs,
right: self.right / rhs,
}
}
}
impl Mul<f32> for StereoSample {
type Output = Self;
fn mul(self, rhs: f32) -> Self::Output {
Self {
left: self.left * rhs,
right: self.right * rhs,
}
}
}
impl AddAssign<Self> for StereoSample {
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs
}
}
impl DivAssign<f32> for StereoSample {
fn div_assign(&mut self, rhs: f32) {
*self = *self / rhs
}
}
impl MulAssign<f32> for StereoSample {
fn mul_assign(&mut self, rhs: f32) {
*self = *self * rhs
}
}

7
src/main.rs

@ -0,0 +1,7 @@
mod beep;
extern crate anyhow;
extern crate cpal;
fn main() -> Result<(), anyhow::Error> {
beep::beep()
}
Loading…
Cancel
Save