├── .gitignore ├── LICENSE ├── Models └── README.md ├── README.md ├── README_PYPI.md ├── assets └── figure.png ├── examples ├── .gitignore ├── SilentCipherStandaloneServer │ ├── README.md │ ├── app.py │ ├── config.yaml │ ├── encoded_flask.wav │ └── requirements.txt ├── WaterMarkingWebsite │ ├── DemoImages │ │ ├── CreateNewProject.png │ │ ├── Decode.jpeg │ │ ├── Distort_Decode.jpeg │ │ ├── Encoded_Decoded_Project.jpeg │ │ └── Login.png │ ├── README.md │ ├── SERVER │ │ ├── .gitignore │ │ ├── DemoServer │ │ │ ├── __init__.py │ │ │ ├── asgi.py │ │ │ ├── settings.py │ │ │ ├── urls.py │ │ │ └── wsgi.py │ │ ├── Readme.md │ │ ├── api │ │ │ ├── __init__.py │ │ │ ├── admin.py │ │ │ ├── apps.py │ │ │ ├── migrations │ │ │ │ └── __init__.py │ │ │ ├── models.py │ │ │ ├── sanitize_path.py │ │ │ ├── tests.py │ │ │ ├── urls.py │ │ │ └── views.py │ │ ├── manage.py │ │ ├── requirements.txt │ │ └── src │ │ │ ├── user.py │ │ │ └── utils.py │ ├── config.json │ └── silentcipherui │ │ ├── .editorconfig │ │ ├── .gitignore │ │ ├── README.md │ │ ├── angular.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── public │ │ └── favicon.ico │ │ ├── src │ │ ├── app │ │ │ ├── app-routing.module.ts │ │ │ ├── app.component.css │ │ │ ├── app.component.html │ │ │ ├── app.component.spec.ts │ │ │ ├── app.component.ts │ │ │ ├── app.module.server.ts │ │ │ ├── app.module.ts │ │ │ ├── decode │ │ │ │ ├── audio │ │ │ │ │ ├── audio-routing.module.ts │ │ │ │ │ ├── audio.module.ts │ │ │ │ │ ├── audio.page.html │ │ │ │ │ ├── audio.page.scss │ │ │ │ │ ├── audio.page.spec.ts │ │ │ │ │ └── audio.page.ts │ │ │ │ ├── decode-routing.module.ts │ │ │ │ ├── decode.module.ts │ │ │ │ ├── decode.page.html │ │ │ │ ├── decode.page.scss │ │ │ │ ├── decode.page.spec.ts │ │ │ │ └── decode.page.ts │ │ │ ├── guard │ │ │ │ ├── auth.guard.spec.ts │ │ │ │ └── auth.guard.ts │ │ │ ├── login │ │ │ │ ├── login-routing.module.ts │ │ │ │ ├── login.module.ts │ │ │ │ ├── login.page.html │ │ │ │ ├── login.page.scss │ │ │ │ ├── login.page.spec.ts │ │ │ │ └── login.page.ts │ │ │ ├── manipulate │ │ │ │ ├── audio │ │ │ │ │ ├── audio-routing.module.ts │ │ │ │ │ ├── audio.module.ts │ │ │ │ │ ├── audio.page.html │ │ │ │ │ ├── audio.page.scss │ │ │ │ │ ├── audio.page.spec.ts │ │ │ │ │ └── audio.page.ts │ │ │ │ ├── manipulate-routing.module.ts │ │ │ │ ├── manipulate.module.ts │ │ │ │ ├── manipulate.page.html │ │ │ │ ├── manipulate.page.scss │ │ │ │ ├── manipulate.page.spec.ts │ │ │ │ └── manipulate.page.ts │ │ │ ├── new │ │ │ │ ├── audio │ │ │ │ │ ├── audio-routing.module.ts │ │ │ │ │ ├── audio.module.ts │ │ │ │ │ ├── audio.page.html │ │ │ │ │ ├── audio.page.scss │ │ │ │ │ ├── audio.page.spec.ts │ │ │ │ │ └── audio.page.ts │ │ │ │ ├── new-routing.module.ts │ │ │ │ ├── new.module.ts │ │ │ │ ├── new.page.html │ │ │ │ ├── new.page.scss │ │ │ │ ├── new.page.spec.ts │ │ │ │ └── new.page.ts │ │ │ ├── project │ │ │ │ ├── project-routing.module.ts │ │ │ │ ├── project.module.ts │ │ │ │ ├── project.page.html │ │ │ │ ├── project.page.scss │ │ │ │ ├── project.page.spec.ts │ │ │ │ └── project.page.ts │ │ │ ├── reusable │ │ │ │ ├── header │ │ │ │ │ ├── header.component.html │ │ │ │ │ ├── header.component.scss │ │ │ │ │ ├── header.component.spec.ts │ │ │ │ │ ├── header.component.ts │ │ │ │ │ └── header.module.ts │ │ │ │ └── projectbar │ │ │ │ │ ├── projectbar.component.html │ │ │ │ │ ├── projectbar.component.scss │ │ │ │ │ ├── projectbar.component.spec.ts │ │ │ │ │ ├── projectbar.component.ts │ │ │ │ │ └── projectbar.module.ts │ │ │ └── services │ │ │ │ ├── http.interceptor.ts │ │ │ │ ├── loading.service.spec.ts │ │ │ │ ├── loading.service.ts │ │ │ │ ├── login.service.spec.ts │ │ │ │ ├── login.service.ts │ │ │ │ └── notification.service.ts │ │ ├── assets │ │ │ ├── images │ │ │ │ ├── Logo-inv.png │ │ │ │ ├── Logo.png │ │ │ │ ├── correct.png │ │ │ │ ├── loading_1.gif │ │ │ │ ├── upload.png │ │ │ │ └── wrong.png │ │ │ └── shapes.svg │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── index.html │ │ ├── main.ts │ │ └── styles.css │ │ ├── tsconfig.app.json │ │ ├── tsconfig.json │ │ └── tsconfig.spec.json └── colab │ ├── cli.py │ ├── demo.ipynb │ ├── demo.py │ ├── encoded.wav │ ├── encoded_test.wav │ ├── encoded_test_multichannel.wav │ ├── test.wav │ └── test_multichannel.wav ├── pyproject.toml ├── requirements.txt └── src └── silentcipher ├── __init__.py ├── model.py ├── server.py └── stft.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control 110 | .pdm.toml 111 | .pdm-python 112 | .pdm-build/ 113 | 114 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 115 | __pypackages__/ 116 | 117 | # Celery stuff 118 | celerybeat-schedule 119 | celerybeat.pid 120 | 121 | # SageMath parsed files 122 | *.sage.py 123 | 124 | # Environments 125 | .env 126 | .venv 127 | env/ 128 | venv/ 129 | ENV/ 130 | env.bak/ 131 | venv.bak/ 132 | 133 | # Spyder project settings 134 | .spyderproject 135 | .spyproject 136 | 137 | # Rope project settings 138 | .ropeproject 139 | 140 | # mkdocs documentation 141 | /site 142 | 143 | # mypy 144 | .mypy_cache/ 145 | .dmypy.json 146 | dmypy.json 147 | 148 | # Pyre type checker 149 | .pyre/ 150 | 151 | # pytype static type analyzer 152 | .pytype/ 153 | 154 | # Cython debug symbols 155 | cython_debug/ 156 | 157 | # PyCharm 158 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 159 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 160 | # and can be added to the global gitignore or merged into this file. For a more nuclear 161 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 162 | #.idea/ 163 | 164 | # See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files. 165 | 166 | # Compiled output 167 | /dist 168 | /tmp 169 | /out-tsc 170 | /bazel-out 171 | 172 | # Node 173 | /node_modules 174 | npm-debug.log 175 | yarn-error.log 176 | 177 | # IDEs and editors 178 | .idea/ 179 | .project 180 | .classpath 181 | .c9/ 182 | *.launch 183 | .settings/ 184 | *.sublime-workspace 185 | 186 | # Visual Studio Code 187 | .vscode/ 188 | !.vscode/settings.json 189 | !.vscode/tasks.json 190 | !.vscode/launch.json 191 | !.vscode/extensions.json 192 | .history/* 193 | 194 | # Miscellaneous 195 | /.angular/cache 196 | .sass-cache/ 197 | /connect.lock 198 | /coverage 199 | /libpeerconnection.log 200 | testem.log 201 | /typings 202 | 203 | # System files 204 | .DS_Store 205 | Thumbs.db 206 | 207 | tests/encoded.wav 208 | tests/test.wav 209 | Models/* 210 | !Models/README.md -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Sony Research Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Models/README.md: -------------------------------------------------------------------------------- 1 | # Put the model files in this directory -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # :loud_sound: SilentCipher: Deep Audio Watermarking: [Link to arxiv](https://arxiv.org/abs/2406.03822) 2 | 3 | Python 4 | 5 | Code for SilentCipher, a method of embedding watermarking in any audio with state-of-the-art robustness.
6 | Currently this repository supports audio at 16kHz and 44.1kHz.
7 | Checkout our [paper](https://arxiv.org/abs/2406.03822) for more details.
8 |
9 | We have posted some examples from existing watermarking algorithms and how they compare to our watermarking method at [EXAMPLES](https://interspeech2024.github.io/silentcipher/) 10 | 11 | [[`arXiv`](https://arxiv.org/abs/2406.03822)] 12 | [[`Colab notebook`](https://colab.research.google.com/github/sony/silentcipher/blob/master/examples/colab/demo.ipynb)] 13 | [[🤗`Hugging Face`](https://huggingface.co/Sony/SilentCipher)] 14 | 15 | # Summary 16 | 17 | In this paper, we address artefacts introduces by Deep learning-based watermarking methods and introduce a way to remove the need for perceptual losses which leads to stable training allowing us to achieve SOTA in terms of both perceptual quality and robustness against distortion. Unlike previous methods which work on 16kHz sampling rate, we also showcase our results on 44.1kHz sampling rates opening the path for practical applications. 18 | 19 | # Abstract 20 | 21 | In the realm of audio watermarking, it is challenging to simultaneously encode imperceptible messages while enhancing the message capacity and robustness. Although recent advancements in deep learning-based methods bolster the message capacity and robustness over traditional methods, the encoded messages introduce audible artefacts that restricts their usage in professional settings. In this study, we introduce three key innovations. Firstly, our work is the first deep learning-based model to integrate psychoacoustic model based thresholding to achieve imperceptible watermarks. Secondly, we introduce psuedo-differentiable compression layers, enhancing the robustness of our watermarking algorithm. Lastly, we introduce a method to eliminate the need for perceptual losses, enabling us to achieve SOTA in both robustness as well as imperceptible watermarking. Our contributions lead us to SilentCipher, a model enabling users to encode messages within audio signals sampled at 44.1kHz. 22 | 23 | # :mate: Installation 24 | 25 | SilentCipher requires Python >=3.8.
26 | I would recommend using a python virtual environment. 27 | ``` 28 | python -m venv env 29 | source env/bin/activate 30 | ``` 31 | 32 | To install from PyPI: 33 | 34 | ``` 35 | pip install silentcipher 36 | ``` 37 | To install from source: Clone this repo and run the following commands: 38 | ``` 39 | git clone https://github.com/sony/silentcipher.git 40 | pip install build 41 | python -m build 42 | pip install dist/.whl 43 | ``` 44 | 45 | # :gear: Models 46 | 47 | Find the latest models for 44.1kHz and 16kHz sampling rate in the release section of this repository [RELEASE](https://github.com/sony/silentcipher/releases)
48 | The models have also been released on [HuggingFace](https://huggingface.co/Sony/SilentCipher)
49 | 50 | **Note**: We are working to release the training code for anyone wants to build their own watermarker. Stay tuned ! 51 | 52 | # :abacus: Usage 53 | 54 | SilentCipher provides a simple API to watermark and detect the watermarks from an audio sample.
55 |
56 | We showcase it in multiple ways as shown in the examples directory.
57 | We provide a simple flask server as documented in [README_FLASK](https://github.com/sony/silentcipher/tree/master/examples/SilentCipherStandaloneServer)
58 | You can also find a simple front-end and backend server which can be used to demonstrate the applications of silentcipher [README_UI](https://github.com/sony/silentcipher/tree/master/examples/WaterMarkingWebsite)
59 | Some simple demo examples are also provided in the [COLAB DIR](https://github.com/sony/silentcipher/tree/master/examples/colab) 60 | 61 | Over here we provide an usage in python: 62 | 63 | ```python 64 | import librosa 65 | import silentcipher 66 | 67 | model = silentcipher.get_model( 68 | model_type='44.1k', # 16k 69 | device='cuda' # use 'cpu' if you want to run it without GPUs 70 | ) 71 | # By default the model is loaded using hugging face APIs, but you can specify the ckpt_path and config_path manually as well 72 | # ckpt_path='Models/44_1_khz/73999_iteration', 73 | # config_path='Models/44_1_khz/73999_iteration/hparams.yaml', 74 | 75 | # Encode from waveform 76 | 77 | y, sr = librosa.load('examples/colab/test.wav', sr=None) 78 | 79 | # The message should be in the form of five 8-bit characters, giving a total message capacity of 40 bits 80 | 81 | encoded, sdr = model.encode_wav(y, sr, [123, 234, 111, 222, 11]) 82 | 83 | # You can specify the message SDR (in dB) along with the encode_wav function. But this may result in unexpected detection accuracy 84 | # encoded, sdr = model.encode_wav(y, sr, [123, 234, 111, 222, 11], message_sdr=47) 85 | 86 | # You should set phase_shift_decoding to True when you want the decoder to be robust to audio crops. 87 | # !Warning, this can increase the decode time quite drastically. 88 | 89 | result = model.decode_wav(encoded, sr, phase_shift_decoding=False) 90 | 91 | print(result['status']) 92 | print(result['messages'][0] == [123, 234, 111, 222, 11]) 93 | print(result['confidences'][0]) 94 | 95 | # Encode from filename 96 | 97 | # The message should be in the form of five 8-bit characters, giving a total message capacity of 40 bits 98 | 99 | model.encode('examples/colab/test.wav', 'examples/colab/encoded.wav', [123, 234, 111, 222, 11]) 100 | 101 | # You can specify the message SDR (in dB) along with the encode function. But this may result in unexpected detection accuracy 102 | # model.encode('test.wav', 'encoded.wav', [123, 234, 111, 222, 11], message_sdr=47) 103 | 104 | # You should set phase_shift_decoding to True when you want the decoder to be robust to audio crops. 105 | # !Warning, this can increase the decode time quite drastically. 106 | 107 | result = model.decode('examples/colab/encoded.wav', phase_shift_decoding=False) 108 | 109 | print(result['messages'][0] == [123, 234, 111, 222, 11], result['messages'][0]) 110 | print(result['confidences'][0]) 111 | ``` 112 | 113 | # Demo Programs 114 | 115 | 1. [Python demo program with more detailed usage](https://github.com/sony/silentcipher/blob/master/examples/colab/demo.py) 116 | 2. [Colab Google](https://colab.research.google.com/github/sony/silentcipher/blob/master/examples/colab/demo.ipynb) 117 | 3. [A standalone flask server](https://github.com/sony/silentcipher/tree/master/examples/SilentCipherStandaloneServer) 118 | 4. [A demo project management UI based on angular + django + flask](https://github.com/sony/silentcipher/tree/master/examples/WaterMarkingWebsite) 119 | 120 | # Want to contribute? 121 | 122 | We welcome Pull Requests with improvements or suggestions. 123 | If you want to flag an issue or propose an improvement, but dont' know how to realize it, create a GitHub Issue. 124 | 125 | 126 | # License 127 | 128 | - The code in this repository is released under the MIT license as found in the [LICENSE file](LICENSE). 129 | 130 | # Maintainers: 131 | - [Mayank Kumar Singh](https://github.com/mayank-git-hub) 132 | 133 | # Citation 134 | 135 | If you find this repository useful, please consider giving a star :star: and please cite as: 136 | 137 | ``` 138 | @inproceedings{singh24_interspeech, 139 | author={Mayank Kumar Singh and Naoya Takahashi and Weihsiang Liao and Yuki Mitsufuji}, 140 | title={{SilentCipher: Deep Audio Watermarking}}, 141 | year=2024, 142 | booktitle={Proc. INTERSPEECH 2024}, 143 | } 144 | ``` 145 | -------------------------------------------------------------------------------- /README_PYPI.md: -------------------------------------------------------------------------------- 1 | # :loud_sound: SilentCipher: Deep Audio Watermarking: [Link to arxiv](https://arxiv.org/abs/2406.03822) 2 | 3 | Python 4 | 5 | Code for SilentCipher, a method of embedding watermarking in any audio with state-of-the-art robustness.
6 | Currently this repository supports audio at 16kHz and 44.1kHz.
7 | Checkout our [paper](https://arxiv.org/abs/2406.03822) for more details. 8 | 9 | [[`arXiv`](https://arxiv.org/abs/2406.03822)] 10 | [[`Colab notebook`](https://colab.research.google.com/github/sony/silentcipher/blob/master/examples/colab/demo.ipynb)] 11 | 12 | 13 | # Summary 14 | 15 | In this paper, we address artefacts introduces by Deep learning-based watermarking methods and introduce a way to remove the need for perceptual losses which leads to stable training allowing us to achieve SOTA in terms of both perceptual quality and robustness against distortion. Unlike previous methods which work on 16kHz sampling rate, we also showcase our results on 44.1kHz sampling rates opening the path for practical applications. 16 | 17 | # Abstract 18 | 19 | In the realm of audio watermarking, it is challenging to simultaneously encode imperceptible messages while enhancing the message capacity and robustness. Although recent advancements in deep learning-based methods bolster the message capacity and robustness over traditional methods, the encoded messages introduce audible artefacts that restricts their usage in professional settings. In this study, we introduce three key innovations. Firstly, our work is the first deep learning-based model to integrate psychoacoustic model based thresholding to achieve imperceptible watermarks. Secondly, we introduce psuedo-differentiable compression layers, enhancing the robustness of our watermarking algorithm. Lastly, we introduce a method to eliminate the need for perceptual losses, enabling us to achieve SOTA in both robustness as well as imperceptible watermarking. Our contributions lead us to SilentCipher, a model enabling users to encode messages within audio signals sampled at 44.1kHz. 20 | 21 | # :mate: Installation 22 | 23 | SilentCipher requires Python >=3.8.
24 | I would recommend using a python virtual environment. 25 | ``` 26 | python -m venv env 27 | source env/bin/activate 28 | ``` 29 | 30 | To install from PyPI: 31 | 32 | ``` 33 | pip install silentcipher 34 | ``` 35 | To install from source: Clone this repo and install in editable mode: 36 | ``` 37 | git clone [GIT_URL] 38 | pip install build 39 | python -m build 40 | pip install dist/.whl 41 | ``` 42 | 43 | # :gear: Models 44 | 45 | **Note**: We will be uploading the model checkpoints soon. Stay Tuned!
46 | **Note**: We are working to release the training code for anyone wants to build their own watermarker. Stay tuned ! 47 | 48 | 49 | 53 | 54 | 55 | # :abacus: Usage 56 | 57 | SilentCipher provides a simple API to watermark and detect the watermarks from an audio sample. Example usage: 58 | 59 | ```python 60 | import librosa 61 | import silentcipher 62 | 63 | model = silentcipher.get_model( 64 | model_type='44.1k', # 16k 65 | ckpt_path='../Models/44_1_khz/73999_iteration', 66 | config_path='../Models/44_1_khz/73999_iteration/hparams.yaml' 67 | ) 68 | 69 | # Encode from waveform 70 | 71 | y, sr = librosa.load('test.wav', sr=None) 72 | 73 | # The message should be in the form of five 8-bit characters, giving a total message capacity of 40 bits 74 | 75 | encoded, sdr = model.encode_wav(y, sr, [123, 234, 111, 222, 11]) 76 | 77 | # You can specify the message SDR (in dB) along with the encode_wav function. But this may result in unexpected detection accuracy 78 | # encoded, sdr = model.encode_wav(y, sr, [123, 234, 111, 222, 11], message_sdr=47) 79 | 80 | result = model.decode_wav(encoded, sr, phase_shift_decoding=False) 81 | 82 | assert result['status'] 83 | assert result['messages'][0] == [123, 234, 111, 222, 11], result['messages'][0] 84 | assert result['confidences'][0] == 1, result['confidences'][0] 85 | 86 | # Encode from filename 87 | 88 | # The message should be in the form of five 8-bit characters, giving a total message capacity of 40 bits 89 | 90 | model.encode('test.wav', 'encoded.wav', [123, 234, 111, 222, 11]) 91 | 92 | # You can specify the message SDR (in dB) along with the encode function. But this may result in unexpected detection accuracy 93 | # model.encode('test.wav', 'encoded.wav', [123, 234, 111, 222, 11], message_sdr=47) 94 | 95 | result = model.decode('encoded.wav', phase_shift_decoding=False) 96 | 97 | assert result['messages'][0] == [123, 234, 111, 222, 11], result['messages'][0] 98 | assert result['confidences'][0] == 1, result['confidences'][0] 99 | ``` 100 | 101 | # Want to contribute? 102 | 103 | We welcome Pull Requests with improvements or suggestions. 104 | If you want to flag an issue or propose an improvement, but dont' know how to realize it, create a GitHub Issue. 105 | 106 | 107 | # License 108 | 109 | - The code in this repository is released under the license as found in the [LICENSE file](LICENSE). 110 | 111 | # Maintainers: 112 | - [Mayank Kumar Singh](https://github.com/mayank-git-hub) 113 | 114 | # Citation 115 | 116 | If you find this repository useful, please consider giving a star :star: and please cite as: 117 | 118 | ``` 119 | @inproceedings{singh24_interspeech, 120 | author={Mayank Kumar Singh and Naoya Takahashi and Weihsiang Liao and Yuki Mitsufuji}, 121 | title={{SilentCipher: Deep Audio Watermarking}}, 122 | year=2024, 123 | booktitle={Proc. INTERSPEECH 2024}, 124 | } 125 | ``` 126 | -------------------------------------------------------------------------------- /assets/figure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/assets/figure.png -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | WaterMarkingWebsiteData 2 | WaterMarkingWebsiteDataDecode 3 | -------------------------------------------------------------------------------- /examples/SilentCipherStandaloneServer/README.md: -------------------------------------------------------------------------------- 1 | # Flask App 2 | 3 | This is a Flask application that serves as the server for the SilentCipher Standalone Package. 4 | 5 | ## Installation 6 | 7 | 1. Follow the installation instructions at [README.md](https://github.com/sony/silentcipher/blob/master/README.md) 8 | 9 | 2. Navigate to the `SilentCipherStandaloneServer` directory: 10 | 11 | ```bash 12 | cd SilentCipherStandalonePackage/examples/SilentCipherStandaloneServer 13 | ``` 14 | 15 | 3. Install the required dependencies: 16 | 17 | ```bash 18 | pip install -r requirements.txt 19 | ``` 20 | 21 | ## Usage 22 | 23 | 1. Start the Flask server: 24 | 25 | ```bash 26 | CUDA_VISIBLE_DEVICES=0 flask run --host 0.0.0.0 --port 8001 27 | ``` 28 | 29 | 2. There are two APIs, one for encode and the other for decode 30 | 31 | ```bash 32 | 33 | curl --location 'http://127.0.0.1:8001/encode' \ 34 | --header 'Content-Type: application/json' \ 35 | --data '{ 36 | "model_type": "44k", 37 | "message_sdr": null, 38 | "in_path": "../colab/test.wav", 39 | "out_path": "encoded_flask.wav", 40 | "message": [111, 222, 121, 131, 141] 41 | }' 42 | ``` 43 | 44 | ```bash 45 | 46 | curl --location 'http://127.0.0.1:8001/decode' \ 47 | --header 'Content-Type: application/json' \ 48 | --data '{ 49 | "model_type": "44k", 50 | "path": "encoded_flask.wav", 51 | "phase_shift_decoding": false 52 | }' 53 | ``` 54 | 55 | ## Contributing 56 | 57 | Currently the standalone server supports only single channel audio.
58 | Feel free to submit a PR for adding the multi-channel support to the standalone server 59 | 60 | ## License 61 | 62 | This project is licensed under the [MIT License](LICENSE). 63 | -------------------------------------------------------------------------------- /examples/SilentCipherStandaloneServer/app.py: -------------------------------------------------------------------------------- 1 | from email import message 2 | from flask import Flask, request 3 | import json 4 | import torch 5 | import silentcipher 6 | import yaml 7 | 8 | config = yaml.safe_load(open('config.yaml')) 9 | 10 | if torch.cuda.is_available(): 11 | device = 'cuda' 12 | else: 13 | device = 'cpu' 14 | 15 | models = {} 16 | 17 | if config['enable_44k']: 18 | models['44k'] = silentcipher.get_model( 19 | model_type='44.1k', 20 | ckpt_path='../../Models/44_1_khz/73999_iteration', 21 | config_path='../../Models/44_1_khz/73999_iteration/hparams.yaml', 22 | device=device 23 | ) 24 | if config['enable_16k']: 25 | models['16k'] = silentcipher.get_model( 26 | model_type='16k', 27 | ckpt_path='../../Models/16_khz/97561_iteration', 28 | config_path='../../Models/16_khz/97561_iteration/hparams.yaml', 29 | device=device 30 | ) 31 | 32 | 33 | app = Flask(__name__) 34 | 35 | @app.route('/encode', methods=['POST']) 36 | def encode(): 37 | if request.json['model_type'] == '44k': # type: ignore 38 | if not config['enable_44k']: 39 | return json.dumps({'status': False, 'message': 'Please enable the 44k model in the config file to be able to encode using the 44k model'}) 40 | model = models['44k'] 41 | elif request.json['model_type'] == '16k': # type: ignore 42 | if not config['enable_16k']: 43 | return json.dumps({'status': False, 'message': 'Please enable the 16k model in the config file to be able to encode using the 16k model'}) 44 | model = models['16k'] 45 | else: 46 | return json.dumps({'status': False, 'message': f'{request.json["model_type"]} Model type not implemented'}) # type: ignore 47 | 48 | if request.json['message_sdr'] is not None: # type: ignore 49 | message_sdr = float(request.json['message_sdr']) # type: ignore 50 | else: 51 | message_sdr = None 52 | 53 | response = json.dumps(model.encode(request.json['in_path'], request.json['out_path'], request.json['message'], message_sdr)) # type: ignore 54 | return response 55 | 56 | @app.route('/decode', methods=['POST']) 57 | def decode(): 58 | if request.json['model_type'] == '44k': # type: ignore 59 | if not config['enable_44k']: 60 | return json.dumps({'status': False, 'message': 'Please enable the 44k model in the config file to be able to encode using the 44k model'}) 61 | model = models['44k'] 62 | elif request.json['model_type'] == '16k': # type: ignore 63 | if not config['enable_16k']: 64 | return json.dumps({'status': False, 'message': 'Please enable the 16k model in the config file to be able to encode using the 16k model'}) 65 | model = models['16k'] 66 | else: 67 | return json.dumps({'status': False, 'message': f'{request.json["model_type"]} Model type not implemented'}) # type: ignore 68 | 69 | response = json.dumps(model.decode(request.json['path'], request.json['phase_shift_decoding'])) # type: ignore 70 | return response 71 | 72 | if __name__ == "__main__": 73 | app.run(host='127.0.0.1', port=8001) 74 | -------------------------------------------------------------------------------- /examples/SilentCipherStandaloneServer/config.yaml: -------------------------------------------------------------------------------- 1 | enable_44k: True 2 | enable_16k: True -------------------------------------------------------------------------------- /examples/SilentCipherStandaloneServer/encoded_flask.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/SilentCipherStandaloneServer/encoded_flask.wav -------------------------------------------------------------------------------- /examples/SilentCipherStandaloneServer/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==2.2.5 -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/DemoImages/CreateNewProject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/DemoImages/CreateNewProject.png -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/DemoImages/Decode.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/DemoImages/Decode.jpeg -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/DemoImages/Distort_Decode.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/DemoImages/Distort_Decode.jpeg -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/DemoImages/Encoded_Decoded_Project.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/DemoImages/Encoded_Decoded_Project.jpeg -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/DemoImages/Login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/DemoImages/Login.png -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/README.md: -------------------------------------------------------------------------------- 1 | # Readme 2 | 3 | This readme file provides information about the Django server and the Angular UI for the WaterMarkingWebsite project. 4 | 5 | ## Demo Images 6 | 7 | ### Login 8 | 9 | 10 | ### Create New Project 11 | 12 | 13 | ### Encode - Decode Project 14 | 15 | 16 | ### Distort and Decode Audio 17 | 18 | 19 | ### Decode Audio 20 | 21 | 22 | ## Silent Cipher Installation 23 | 24 | Follow the installation instructions at [README.md](https://github.com/sony/silentcipher/blob/master/README.md) 25 | 26 | ## Django Server 27 | 28 | The Django server is located at `examples/WaterMarkingWebsite/SERVER`. It serves as the backend for the WaterMarkingWebsite project. 29 | 30 | To run the Django server, follow these steps: 31 | 32 | 1. Navigate to the server directory: `cd examples/WaterMarkingWebsite/SERVER`. 33 | 2. Install the required dependencies: `pip install -r requirements.txt`. 34 | 3. Install mongod on your server [INSTALLATION](https://www.mongodb.com/docs/manual/installation/) 35 | 4. Run the server: `python manage.py runserver 127.0.0.1:8000`. 36 | 37 | The server will start running on `http://localhost:8000`. 38 | 39 | ## Angular UI 40 | 41 | The Angular UI is located at `examples/WaterMarkingWebsite/silentcipherui`. It provides the frontend for the WaterMarkingWebsite project. 42 | 43 | To run the Angular UI, follow these steps: 44 | 45 | 1. Navigate to the UI directory: `cd examples/WaterMarkingWebsite/silentcipherui`. 46 | 2. Install the required dependencies: `npm install`. 47 | 3. Start the development server: `ng serve`. 48 | 49 | ## Warning! You may face issues when installing the correct packages for angular... 50 | 51 | The UI will be accessible at `http://localhost:4200`. 52 | 53 | ## Contributing 54 | 55 | Currently the demo website only supports single channel audio
56 | Feel free to submit a PR for adding the multi-channel support to the demo website.
57 | Also feel free to submit a PR regarding installation challenges faced during the setup of the demo server 58 | 59 | ## License 60 | 61 | This project is licensed under the [MIT License](LICENSE). 62 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | db.sqlite3 -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/DemoServer/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/SERVER/DemoServer/__init__.py -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/DemoServer/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for DemoServer project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DemoServer.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/DemoServer/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for DemoServer project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.1.4. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.1/ref/settings/ 11 | """ 12 | 13 | import json 14 | from pathlib import Path 15 | import datetime 16 | from corsheaders.defaults import default_headers 17 | # Pymongo Collections 18 | from pymongo import MongoClient 19 | 20 | with open('../config.json', 'r') as f: 21 | config = json.load(f) 22 | 23 | client = MongoClient() 24 | 25 | name = config['name'] 26 | db = client[name] 27 | 28 | USER = db['USER'] 29 | PROJECT = db['PROJECT'] 30 | DECODE = db['DECODE'] 31 | MANIPULATE = db['MANIPULATE'] 32 | FILE_UPLOAD_DIR = config['FILE_UPLOAD_DIR'] 33 | DECODE_UPLOAD_DIR = config['DECODE_UPLOAD_DIR'] 34 | FILE_UPLOAD_DIR_REL_MODEL_SERVER = config['FILE_UPLOAD_DIR_REL_MODEL_SERVER'] 35 | DECODE_UPLOAD_DIR_REL_MODEL_SERVER = config['DECODE_UPLOAD_DIR_REL_MODEL_SERVER'] 36 | 37 | ALLOWED_EXTENSIONS = [ 38 | 'wav', 'mp3', 'aac', 'ogg', 'flac', 'alac', 'aiff', 'dsd', 'pcm', 39 | 'MP4', 'MOV', 'WMV', 'AVI', 'AVCHD', 'FLV', 'F4V', 'SWF', 'MKV', 'WEBM' 40 | ] 41 | ENCODE_URL = 'http://127.0.0.1:8001/encode' 42 | DECODE_URL = 'http://127.0.0.1:8001/decode' 43 | 44 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 45 | BASE_DIR = Path(__file__).resolve().parent.parent 46 | 47 | def addUser(email, password=None, name=None): 48 | 49 | existingUser = USER.find_one({'email': email}) 50 | if existingUser: 51 | return None, False 52 | 53 | date = datetime.datetime.now().strftime("%d-%m-%y-%H-%M-%S") 54 | 55 | if name is not None: 56 | name = name.title() 57 | 58 | req_user = { 59 | 'email': email, 60 | 'password': password, 61 | 'name': name, 62 | 'date': date, 63 | 'projects': [] 64 | } 65 | USER.insert_one(req_user) 66 | 67 | return req_user, True 68 | 69 | for admin_user in config['admin_list']: 70 | addUser(admin_user['email'], admin_user['password'], admin_user['name']) 71 | 72 | # Quick-start development settings - unsuitable for production 73 | # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ 74 | 75 | # SECURITY WARNING: keep the secret key used in production secret! 76 | SECRET_KEY = 'qwerasdfqwerasdfqwerasdfasdfasdf' 77 | 78 | # SECURITY WARNING: don't run with debug turned on in production! 79 | DEBUG = True 80 | 81 | ALLOWED_HOSTS=['localhost', '127.0.01', config['host']['ip']] 82 | 83 | # Application definition 84 | 85 | DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' 86 | 87 | 88 | INSTALLED_APPS = [ 89 | 'corsheaders', 90 | 'django.contrib.admin', 91 | 'django.contrib.auth', 92 | 'django.contrib.contenttypes', 93 | 'django.contrib.sessions', 94 | 'django.contrib.messages', 95 | 'django.contrib.staticfiles', 96 | ] 97 | 98 | MIDDLEWARE = [ 99 | 'corsheaders.middleware.CorsMiddleware', 100 | 'django.middleware.security.SecurityMiddleware', 101 | 'django.contrib.sessions.middleware.SessionMiddleware', 102 | 'django.middleware.common.CommonMiddleware', 103 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 104 | 'django.contrib.messages.middleware.MessageMiddleware', 105 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 106 | ] 107 | 108 | ROOT_URLCONF = 'DemoServer.urls' 109 | 110 | TEMPLATES = [ 111 | { 112 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 113 | 'DIRS': [], 114 | 'APP_DIRS': True, 115 | 'OPTIONS': { 116 | 'context_processors': [ 117 | 'django.template.context_processors.debug', 118 | 'django.template.context_processors.request', 119 | 'django.contrib.auth.context_processors.auth', 120 | 'django.contrib.messages.context_processors.messages', 121 | ], 122 | }, 123 | }, 124 | ] 125 | 126 | WSGI_APPLICATION = 'DemoServer.wsgi.application' 127 | 128 | 129 | # Database 130 | # https://docs.djangoproject.com/en/3.1/ref/settings/#databases 131 | 132 | DATABASES = { 133 | 'default': { 134 | 'ENGINE': 'django.db.backends.sqlite3', 135 | 'NAME': BASE_DIR / 'db.sqlite3', 136 | } 137 | } 138 | 139 | 140 | # Password validation 141 | # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators 142 | 143 | AUTH_PASSWORD_VALIDATORS = [ 144 | { 145 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 146 | }, 147 | { 148 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 149 | }, 150 | { 151 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 152 | }, 153 | { 154 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 155 | }, 156 | ] 157 | 158 | 159 | # Internationalization 160 | # https://docs.djangoproject.com/en/3.1/topics/i18n/ 161 | 162 | LANGUAGE_CODE = 'en-us' 163 | 164 | TIME_ZONE = 'UTC' 165 | 166 | USE_I18N = True 167 | 168 | USE_L10N = True 169 | 170 | USE_TZ = True 171 | 172 | 173 | # Static files (CSS, JavaScript, Images) 174 | # https://docs.djangoproject.com/en/3.1/howto/static-files/ 175 | 176 | STATIC_URL = '/files/' 177 | STATICFILES_DIRS = [ 178 | BASE_DIR / 'files' 179 | ] 180 | 181 | # MOS 182 | MOS = { 183 | 'numSamples': 8 184 | } 185 | 186 | # SPKIDEN 187 | SPKIDEN = { 188 | 'numSamples': 10 189 | } 190 | 191 | # ABX 192 | ABX = { 193 | 'numSamples': 8 194 | } 195 | # qualityComp 196 | QUALITYCOMP = { 197 | 'numSamples': 10 198 | } 199 | 200 | 201 | CORS_ORIGIN_ALLOW_ALL = True 202 | CORS_ALLOW_HEADERS = list(default_headers) + [ 203 | 'email', 'token' 204 | ] -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/DemoServer/urls.py: -------------------------------------------------------------------------------- 1 | """DemoServer URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.1/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.urls import path, include 17 | 18 | urlpatterns = [ 19 | path('WaterMarkingWebsite/api/', include('api.urls')), 20 | ] 21 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/DemoServer/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for DemoServer project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DemoServer.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/Readme.md: -------------------------------------------------------------------------------- 1 | # Installation Instructions 2 | 3 | Install the following programs in sequence - 4 | 5 | ## Mongo DB 6 | 7 | To Visualize the data, you can use Compass (Optional) 8 | 9 | https://www.mongodb.com/try/download/compass 10 | 11 | ## Python Libraries 12 | 13 | pip install -r requirements.txt 14 | 15 | ## How to start a new project 16 | 17 | In EvaluationUI/setup/setup.sh change the variable TASK_NAME and set it to the name you want. 18 | Modify the files' directory with the files you want, and you are good to go. 19 | You can change the files/tasks.json file and remove the tasks which are not necessary for you. 20 | The instructions for creating the json files are mentioned below 21 | 22 | To start the server, run the setup.sh file in the UI code. 23 | 24 | (Optional) It is not necessary to run python manage.py migrate, 25 | but you can run it to suppress the warnings 26 | 27 | # Instructions for creating the json files 28 | 29 | ## Path of the samples 30 | 31 | The audio files should be put in the files directory, and 32 | the path of the samples in the JSON files should be api/files + relative path from the files directory. 33 | 34 | Path for an audio file which is inside files and has name hello.wav 35 | - api/files/hello.wav 36 | 37 | ## File formats 38 | 39 | ### files/originals.json 40 | 41 | This will contain one real sample corresponding to each speaker. 42 | 43 | Example - 44 | 45 | { 46 | "SPK1": "/spk1_original.wav", 47 | "SPK2": "/spk2_original.wav", 48 | "SPK3": "/spk3_original.wav" 49 | } 50 | 51 | ### files/model/*.json 52 | 53 | This will contain predictions of experiments in the following format. 54 | 55 | Example - 56 | 57 | { 58 | "modelName": "testingModel1", 59 | "meta": "Some information Here", 60 | "predicted": { 61 | "SOURCE_SPK1": { 62 | "TARGET_SPK1": "/spk1pred/1.wav", 63 | "TARGET_SPK2": "/spk1pred/2.wav", 64 | "TARGET_SPK3": "/spk1pred/3.wav" 65 | }, 66 | "SOURCE_SPK1": { 67 | "TARGET_SPK1": "/spk1pred/1.wav", 68 | "TARGET_SPK2": "/spk1pred/2.wav", 69 | "TARGET_SPK3": "/spk1pred/3.wav" 70 | }, 71 | "SOURCE_SPK1": { 72 | "TARGET_SPK1": "/spk1pred/1.wav", 73 | "TARGET_SPK2": "/spk1pred/2.wav", 74 | "TARGET_SPK3": "/spk1pred/3.wav" 75 | } 76 | } 77 | } 78 | 79 | ### files/abx.json 80 | 81 | This will contain the model combinations which need to be compared in the abx testing 82 | modelName in files/model/*.json should match with the name mentioned in combinations 83 | Example - 84 | 85 | { 86 | "combinations": [ 87 | ["testingModel1", "testingModel2"], 88 | ["testingModel2", "testingModel3"] 89 | ] 90 | } 91 | 92 | ### files/qualityComp.json 93 | 94 | This will contain the model combinations which need to be compared in the quality comparision testing 95 | modelName in files/model/*.json should match with the name mentioned in combinations 96 | 97 | Example - 98 | 99 | { 100 | "combinations": [ 101 | ["testingModel1", "testingModel2"], 102 | ["testingModel2", "testingModel3"] 103 | ] 104 | } 105 | 106 | ## General Information 107 | 108 | A common seed number is generated for each user, which is used for pseudo random generation. 109 | 110 | ## MOS 111 | 112 | ### Files Used - 113 | 114 | 1) files/originals.json 115 | 2) files/mos.json 116 | 3) files/model/*.json 117 | 118 | ### Method - 119 | 120 | I mixed up all the songs of files/model/*.json and the files/originals.json. 121 | The songs are shuffled randomly and the evaluator is asked to score the quality. 122 | 123 | ## Speaker Identity 124 | 125 | ### Files Used - 126 | 127 | 1) files/originals.json 128 | 2) files/model/*.json 129 | 130 | ### Method - 131 | 132 | I mixed up all the songs of files/model/*.json and the files/originals.json. 133 | The songs are shuffled randomly and the evaluator is asked to score the speaker similarity with the song of the target speaker found in files/originals.json. 134 | 135 | ## ABX Testing 136 | 137 | ### Files Used - 138 | 139 | 1) files/originals.json 140 | 2) files/model/*.json 141 | 3) files/abx.json 142 | 143 | ### Method - 144 | 145 | I created combinations of same source speaker and target speaker from different models along with a reference sample of the target speaker. 146 | The combination was shuffled randomly and the evaluator is asked to choose which model sample is closer to the reference sample in terms of speaker identity. 147 | 148 | 149 | ## Quality Comparison Testing 150 | 151 | ### Files Used - 152 | 153 | 1) files/originals.json 154 | 2) files/model/*.json 155 | 3) files/qualityComp.json 156 | 157 | ### Method - 158 | 159 | I created combinations of same source speaker and target speaker from different models. 160 | This was shuffled randomly and the evaluator is asked to choose which model sample has better sound quality. 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/SERVER/api/__init__.py -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/api/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/api/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ApiConfig(AppConfig): 5 | name = 'api' 6 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/api/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/SERVER/api/migrations/__init__.py -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/api/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/api/sanitize_path.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/SERVER/api/sanitize_path.py -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/api/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/api/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from django.urls import path 3 | 4 | from . import views 5 | 6 | urlpatterns = [ 7 | path('create_user', views.create_user, name='create_user'), 8 | path('login', views.login, name='login'), 9 | path('get_user_data', views.get_user_data, name='get_user_data'), 10 | path('new_project', views.new_project, name='new_project'), 11 | path('get_project_data', views.get_project_data, name='get_project_data'), 12 | url(r'files/(?P.+)', views.files, name='files'), 13 | path('encode_project', views.encode_project, name='encode_project'), 14 | path('decode', views.decode, name='decode'), 15 | path('decode_file_location', views.decode_file_location, name='decode_file_location'), 16 | path('apply_distortion', views.apply_distortion, name='apply_distortion') 17 | ] -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/api/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.http import JsonResponse, FileResponse 3 | from django.conf import settings 4 | from bson import ObjectId 5 | import requests 6 | import datetime 7 | from pathlib import Path 8 | 9 | import json 10 | import os 11 | 12 | from src import utils 13 | from src import user 14 | from src.utils import authenticate 15 | 16 | import librosa 17 | import soundfile as sf 18 | 19 | def sanitize_data(data): 20 | if 'password' in data: 21 | del data['password'] 22 | if '_id' in data: 23 | data['_id'] = str(data['_id']) 24 | 25 | return data 26 | 27 | 28 | def create_user(request): 29 | 30 | if request.method == 'POST': 31 | req_user = json.loads(request.body) 32 | email = req_user.get('email') 33 | password = req_user.get('password') 34 | name = req_user.get('name') 35 | if req_user.get('admin_key') != 'asdfzxcvqwer': 36 | return JsonResponse({"status": False, "error": "Stop trying to create new users!"}) 37 | if not email or not password or not name: 38 | return JsonResponse({"status": False, "error": "Please provide email, password & name"}) 39 | 40 | req_user, status = utils.addUser(email, password, name, None, False, settings.USER) 41 | if req_user is None: 42 | return JsonResponse({"status": False, "error": "User already exists!"}) 43 | 44 | return JsonResponse( 45 | {"status": True, "token": user.generate_auth_token(req_user.get('email'))} 46 | ) 47 | 48 | 49 | @authenticate 50 | def get_user_data(request, **kwargs): 51 | 52 | if request.method == 'GET': 53 | 54 | user = settings.USER.find_one({'email': kwargs['email']}) 55 | 56 | if not user: 57 | return JsonResponse({'status': False}) 58 | 59 | return JsonResponse({'status': True, 'user_data': sanitize_data(user)}) 60 | 61 | 62 | @authenticate 63 | def new_project(request, **kwargs): 64 | 65 | if request.method == 'POST': 66 | 67 | user = settings.USER.find_one({'email': kwargs['email']}) 68 | if not user: 69 | return JsonResponse({'status': False}) 70 | 71 | extension = request.FILES['file'].name.split('.')[-1] 72 | 73 | if extension not in settings.ALLOWED_EXTENSIONS: 74 | return JsonResponse({'status': False}) 75 | 76 | _id = settings.PROJECT.insert_one( 77 | { 78 | 'email': kwargs['email'], 79 | 'name': request.POST.get('projectName'), 80 | 'file': request.FILES['file'].name, 81 | 'extension': extension, 82 | 'type': request.POST.get('type'), 83 | 'selected': 0, 84 | 'message': ['']*5, 85 | 'error': [False]*5, 86 | } 87 | ) 88 | print(str(_id.inserted_id)) 89 | _id = str(_id.inserted_id) 90 | 91 | with open(settings.FILE_UPLOAD_DIR + '/' + str(_id) + '.' + extension, 'wb') as f: 92 | f.write(request.FILES['file'].read()) 93 | 94 | 95 | projects = user['projects'] 96 | projects.append({'name': request.POST.get('projectName'), '_id': str(_id)}) 97 | 98 | settings.USER.update_one({'email': kwargs['email']}, {'$set': {'projects': projects}}) 99 | 100 | user = settings.USER.find_one({'email': kwargs['email']}) 101 | 102 | return JsonResponse({'status': True, 'id': str(_id), 'user_data': sanitize_data(user)}) 103 | 104 | @authenticate 105 | def get_project_data(request, **kwargs): 106 | 107 | if request.method == 'POST': 108 | 109 | data = json.loads(request.body) 110 | project = settings.PROJECT.find_one({'email': kwargs['email'], '_id': ObjectId(data.get('projectid'))}) 111 | if project: 112 | return JsonResponse({'status': True, 'project': sanitize_data(project)}) 113 | else: 114 | return JsonResponse({'status': False}) 115 | 116 | def files(request, **kwargs): 117 | 118 | if request.method == 'GET': 119 | 120 | test_path = (Path(settings.FILE_UPLOAD_DIR) / kwargs['path']).resolve() 121 | if test_path.parent != Path(settings.FILE_UPLOAD_DIR).resolve(): 122 | # raise Exception(f"Filename {test_path} is not in {Path(settings.FILE_UPLOAD_DIR)} directory") 123 | return JsonResponse({'status': False}) 124 | 125 | return FileResponse(open(settings.FILE_UPLOAD_DIR + '/' + kwargs['path'], 'rb')) 126 | 127 | @authenticate 128 | def encode_project(request, **kwargs): 129 | 130 | if request.method == 'POST': 131 | data = json.loads(request.body) 132 | print(data['project']) 133 | project_id = ObjectId(data['project']['_id']) 134 | data['project']['message'] = [int(_) for _ in data['project']['message']] 135 | del data['project']['_id'] 136 | # try: 137 | result = json.loads(requests.post(settings.ENCODE_URL, json={ 138 | 'model_type': data['model_type'], 139 | 'in_path': settings.FILE_UPLOAD_DIR_REL_MODEL_SERVER + '/' + str(project_id) + '.' + data['project']['extension'], 140 | 'out_path': settings.FILE_UPLOAD_DIR_REL_MODEL_SERVER + '/' + str(project_id) + '_encoded.' + data['project']['extension'], 141 | 'message': data['project']['message'], 142 | 'message_sdr': data['message_sdr'] 143 | }).text) 144 | # except: 145 | # return JsonResponse({'status': False}) 146 | 147 | print(result) 148 | data['project']['encoded'] = result['status'] 149 | data['project']['sdr'] = result['sdr'] 150 | if not result['status']: 151 | return JsonResponse({'status': False}) 152 | 153 | settings.PROJECT.update_one({'_id': project_id}, {'$set': data['project']}) 154 | data['project']['_id'] = str(project_id) 155 | return JsonResponse({'status': True, 'project': data['project']}) 156 | 157 | @authenticate 158 | def decode(request, **kwargs): 159 | 160 | if request.method == 'POST': 161 | 162 | extension = request.FILES['file'].name.split('.')[-1] 163 | timestamp = datetime.datetime.now() 164 | 165 | if extension not in settings.ALLOWED_EXTENSIONS: 166 | return JsonResponse({'status': False}) 167 | 168 | _id = settings.DECODE.insert_one({'time': timestamp, 'extension': extension, 'email': kwargs['email']}).inserted_id 169 | 170 | with open(settings.DECODE_UPLOAD_DIR + '/' + str(_id) + '.' + extension, 'wb') as f: 171 | f.write(request.FILES['file'].read()) 172 | 173 | try: 174 | result = json.loads(requests.post(settings.DECODE_URL, json={ 175 | 'model_type': request.POST.get('model_type'), 176 | 'path': settings.DECODE_UPLOAD_DIR_REL_MODEL_SERVER + '/' + str(_id) + '.' + extension, 177 | 'phase_shift_decoding': request.POST.get('phase_shift_decoding'), 178 | }).text) 179 | except: 180 | print('Some error in model server') 181 | return JsonResponse({'status': False}) 182 | 183 | if not result['status']: 184 | return JsonResponse({'status': False}) 185 | settings.DECODE.update_one({'_id': ObjectId(_id)}, {'$set': {'messages': result['messages'], 'confidences': result['confidences']}}) 186 | 187 | return JsonResponse({'status': True, 'decode': sanitize_data(settings.DECODE.find_one({'_id': ObjectId(_id)}))}) 188 | 189 | 190 | @authenticate 191 | def decode_file_location(request, **kwargs): 192 | 193 | if request.method == 'POST': 194 | 195 | data = json.loads(request.body) 196 | path = data['path'] 197 | phase_shift_decoding = data['phase_shift_decoding'] 198 | model_type = data['model_type'] 199 | encoded_file_path = settings.FILE_UPLOAD_DIR_REL_MODEL_SERVER + '/' + path 200 | 201 | try: 202 | result = json.loads(requests.post(settings.DECODE_URL, json={ 203 | 'model_type': model_type, 204 | 'path': encoded_file_path, 205 | 'phase_shift_decoding': phase_shift_decoding 206 | }).text) 207 | except: 208 | print('Some error in model server') 209 | return JsonResponse({'status': False}) 210 | 211 | if not result['status']: 212 | return JsonResponse({'status': False}) 213 | 214 | return JsonResponse({'status': True, 'decode': {'messages': result['messages']}}) 215 | 216 | 217 | @authenticate 218 | def apply_distortion(request, **kwargs): 219 | 220 | if request.method == 'POST': 221 | 222 | user = settings.USER.find_one({'email': kwargs['email']}) 223 | if not user: 224 | return JsonResponse({'status': False}) 225 | 226 | extension = request.FILES['file'].name.split('.')[-1] 227 | 228 | if extension not in settings.ALLOWED_EXTENSIONS: 229 | return JsonResponse({'status': False}) 230 | 231 | if request.POST.get('distorted_path') == 'null': 232 | _id = settings.MANIPULATE.insert_one( 233 | { 234 | 'email': kwargs['email'], 235 | 'distorted_path': request.POST.get('distorted_path'), 236 | 'file': request.FILES['file'].name, 237 | 'extension': extension, 238 | } 239 | ) 240 | print(str(_id.inserted_id)) 241 | _id = str(_id.inserted_id) 242 | else: 243 | data = settings.MANIPULATE.find_one({'distorted_path': request.POST.get('distorted_path')}) 244 | if data is None: 245 | return JsonResponse({'status': False}) 246 | _id = str(data['_id']) 247 | 248 | with open(settings.FILE_UPLOAD_DIR + '/' + str(_id) + '.' + extension, 'wb') as f: 249 | f.write(request.FILES['file'].read()) 250 | 251 | distorted_path = str(_id) + '_distorted.wav' 252 | 253 | audio, sr = librosa.load(settings.FILE_UPLOAD_DIR + '/' + str(_id) + '.' + extension, sr=None) 254 | 255 | print(request.POST.get('processList')) 256 | for process in json.loads(request.POST.get('processList')): 257 | print(process) 258 | audio, sr = distort(audio, sr, process, settings.FILE_UPLOAD_DIR + '/' + str(_id) + '_temp_distorted.wav') 259 | 260 | sf.write(settings.FILE_UPLOAD_DIR + '/' + distorted_path, audio, sr) 261 | settings.MANIPULATE.update_one({'_id': ObjectId(_id)}, {'$set': {'distorted_path': distorted_path}}) 262 | 263 | return JsonResponse({'status': True, 'distorted_path': distorted_path}) 264 | 265 | 266 | def login(request): 267 | 268 | if request.method == 'POST': 269 | 270 | req_user = json.loads(request.body) 271 | dbuser = settings.USER.find_one({'email': req_user['email'], 'password': req_user['password']}) 272 | print(dbuser) 273 | if dbuser: 274 | return JsonResponse( 275 | { 276 | "status": True, "name": dbuser.get('name', None), 277 | "token": user.generate_auth_token(req_user.get('email')) # .decode('utf-8') 278 | } 279 | ) 280 | 281 | return JsonResponse({"status": False}) 282 | 283 | 284 | def distort(audio, sr, process, temp_path_audio): 285 | 286 | if process['name'] == 'compression': 287 | sf.write(temp_path_audio, audio, sr) 288 | os.system(f'ffmpeg -y -i {temp_path_audio} -vn -b:a {process["bit_rate"]} {temp_path_audio}.{process["algorithm"]} > /dev/null 2>&1') 289 | os.system(f'ffmpeg -y -i {temp_path_audio}.{process["algorithm"]} {temp_path_audio} > /dev/null 2>&1') # >/dev/null 2>&1 290 | audio, sr = sf.read(temp_path_audio) 291 | elif process['name'] == 'amp': 292 | audio = audio * float(process['scale']) 293 | elif process['name'] == 'crop': 294 | start = int(sr*float(process['startTime'])) 295 | end = int(sr*float(process['endTime'])) 296 | assert start >=0 and end < len(audio) 297 | audio = audio[start:end] 298 | elif process['name'] == 'resample': 299 | audio = librosa.resample(y=audio, orig_sr=sr, target_sr=int(process['sampling_rate'])) 300 | sr = int(process['sampling_rate']) 301 | else: 302 | print('Unknown distortion') 303 | return audio, sr -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DemoServer.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==5.0.6 2 | django-cors-headers==3.6.0 3 | pymongo==4.7.3 4 | requests==2.32.2 5 | passlib==1.7.4 6 | librosa==0.10.2.post1 7 | pyjwt 8 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/src/user.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | from passlib.apps import custom_app_context as pwd_context 4 | import jwt 5 | from django.conf import settings 6 | 7 | 8 | class UserMongo: 9 | 10 | def __init__(self): 11 | 12 | self.db = settings.USER 13 | 14 | def __getitem__(self, email): 15 | 16 | user = self.db.find_one({'email': email}) 17 | if user is None: 18 | return {'error': 'Not Found'} 19 | 20 | return user 21 | 22 | def getByEmail(self, email): 23 | 24 | user = self.db.find_one({'email': email}) 25 | if user is None: 26 | return {'error': 'Not Found'} 27 | 28 | return user 29 | 30 | def putUser(self, user): 31 | 32 | return self.db.insert_one(user) 33 | 34 | def delUser(self, email): 35 | 36 | self.db.delete_one({'email': email}) 37 | 38 | def removeSensitiveInfo(self, email): 39 | 40 | user = self.db.find_one({'email': email}) 41 | if user is None: 42 | return {'error': 'Not Found'} 43 | 44 | del user['passwordHash'] 45 | del user['tokenInitTime'] 46 | del user['_id'] 47 | 48 | return user 49 | 50 | def checkAdmin(self, email): 51 | user = self.__getitem__(email) 52 | return user['role'] == 'admin' 53 | 54 | 55 | userDB = UserMongo() 56 | 57 | 58 | def hash_password(password): 59 | return pwd_context.encrypt(password) 60 | 61 | 62 | def verify_password(password, email): 63 | user = userDB[email] 64 | if 'error' in user: 65 | return None 66 | password_hash = user['passwordHash'] 67 | return pwd_context.verify(password, password_hash) 68 | 69 | 70 | def verify_token(token, email): 71 | user = userDB[email] 72 | 73 | if user is None: 74 | return None 75 | 76 | check = verify_auth_token(token) 77 | 78 | if check is None: 79 | return None 80 | 81 | if email == check['email']: 82 | return True 83 | 84 | return None 85 | 86 | 87 | def generate_auth_token(email): 88 | return jwt.encode({'email': email, 'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=100 * 24 * 60 * 60)}, 89 | settings.SECRET_KEY, 90 | algorithm="HS256") 91 | 92 | 93 | def verify_auth_token(token): 94 | try: 95 | data = jwt.decode(token, settings.SECRET_KEY, algorithms='HS256') 96 | user = userDB[data['email']] 97 | if 'error' in user: 98 | return None 99 | except jwt.ExpiredSignatureError: 100 | print('exp') 101 | return None 102 | except jwt.InvalidTokenError: 103 | print('inv') 104 | return None 105 | except: 106 | return None 107 | 108 | return {'email': data['email']} 109 | 110 | 111 | def get_user_by_token(token): 112 | try: 113 | data = jwt.decode(token, settings.SECRET_KEY, algorithms='HS256') 114 | db_user = userDB[data['email']] 115 | if 'error' in db_user: 116 | print('email does not exist', data['email']) 117 | return None 118 | except jwt.ExpiredSignatureError: 119 | print('exp') 120 | return None 121 | except jwt.InvalidTokenError: 122 | print('inv') 123 | return None 124 | 125 | return db_user 126 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/SERVER/src/utils.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from functools import wraps 3 | from django.conf import settings 4 | import json 5 | import random 6 | import os 7 | from src import user 8 | 9 | def authenticate(to_authenticate_fn): 10 | 11 | @wraps(to_authenticate_fn) 12 | def inner(request, *args, **kwargs): 13 | 14 | email = request.headers.get('email', None) 15 | token = request.headers.get('token', None) 16 | 17 | if token is not None: 18 | 19 | if user.verify_token(token, email): 20 | return to_authenticate_fn(request, *args, **kwargs, email=email, token=token) 21 | else: 22 | print('user verification failed', token) 23 | return HttpResponse(status=401) 24 | else: 25 | return HttpResponse(status=401) 26 | 27 | return inner 28 | 29 | 30 | def create_user(email): 31 | # This function is called when creating a new user. The combinations and random seed are fixed over here. 32 | 33 | tasks = 'files' + '/tasks.json' 34 | with open(tasks, 'r') as f: 35 | tasks = json.load(f) 36 | userSeed = random.randint(0, 9) 37 | settings.USER.insert_one( 38 | { 39 | 'email': email, 40 | 'tasks': {taskI['name']: get_empty_task(taskI['name'], userSeed) for taskI in tasks}, 41 | 'seed': userSeed 42 | } 43 | ) 44 | 45 | return True 46 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "admin_list": [ 3 | { 4 | "name": "Trial User", 5 | "email": "trial@gmail.com", 6 | "password": "trial" 7 | } 8 | ], 9 | "name": "WaterMarkingWebsite", 10 | "host": { 11 | "ip": "43.4.23.101" 12 | }, 13 | "FILE_UPLOAD_DIR": "../../WaterMarkingWebsiteData", 14 | "DECODE_UPLOAD_DIR": "../../WaterMarkingWebsiteDataDecode", 15 | "FILE_UPLOAD_DIR_REL_MODEL_SERVER": "../WaterMarkingWebsiteData", 16 | "DECODE_UPLOAD_DIR_REL_MODEL_SERVER": "../WaterMarkingWebsiteDataDecode" 17 | } -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files. 2 | 3 | # Compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /bazel-out 8 | 9 | # Node 10 | /node_modules 11 | npm-debug.log 12 | yarn-error.log 13 | 14 | # IDEs and editors 15 | .idea/ 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # Visual Studio Code 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | .history/* 30 | 31 | # Miscellaneous 32 | /.angular/cache 33 | .sass-cache/ 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | testem.log 38 | /typings 39 | 40 | # System files 41 | .DS_Store 42 | Thumbs.db 43 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/README.md: -------------------------------------------------------------------------------- 1 | # Silentcipherui 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 18.0.1. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page. 28 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "temp": { 7 | "projectType": "application", 8 | "schematics": { 9 | "@schematics/angular:component": { 10 | "standalone": false 11 | }, 12 | "@schematics/angular:directive": { 13 | "standalone": false 14 | }, 15 | "@schematics/angular:pipe": { 16 | "standalone": false 17 | } 18 | }, 19 | "root": "", 20 | "sourceRoot": "src", 21 | "prefix": "app", 22 | "architect": { 23 | "build": { 24 | "builder": "@angular-devkit/build-angular:application", 25 | "options": { 26 | "baseHref": "/WaterMarkingWebsite/", 27 | "outputPath": "dist/temp", 28 | "index": "src/index.html", 29 | "browser": "src/main.ts", 30 | "polyfills": [ 31 | "zone.js" 32 | ], 33 | "tsConfig": "tsconfig.app.json", 34 | "assets": [ 35 | { 36 | "glob": "**/*", 37 | "input": "public" 38 | }, 39 | "src/assets" 40 | ], 41 | "styles": [ 42 | "node_modules/bootstrap/dist/css/bootstrap.css", 43 | "src/styles.css" 44 | ], 45 | "scripts": [ 46 | "node_modules/jquery/dist/jquery.min.js", 47 | "node_modules/bootstrap/dist/js/bootstrap.min.js" 48 | ] 49 | }, 50 | "configurations": { 51 | "production": { 52 | "budgets": [ 53 | { 54 | "type": "initial", 55 | "maximumWarning": "500kB", 56 | "maximumError": "1MB" 57 | }, 58 | { 59 | "type": "anyComponentStyle", 60 | "maximumWarning": "2kB", 61 | "maximumError": "4kB" 62 | } 63 | ], 64 | "outputHashing": "all" 65 | }, 66 | "development": { 67 | "optimization": false, 68 | "extractLicenses": false, 69 | "sourceMap": true 70 | } 71 | }, 72 | "defaultConfiguration": "production" 73 | }, 74 | "serve": { 75 | "builder": "@angular-devkit/build-angular:dev-server", 76 | "configurations": { 77 | "production": { 78 | "buildTarget": "temp:build:production" 79 | }, 80 | "development": { 81 | "buildTarget": "temp:build:development" 82 | } 83 | }, 84 | "defaultConfiguration": "development" 85 | }, 86 | "extract-i18n": { 87 | "builder": "@angular-devkit/build-angular:extract-i18n" 88 | }, 89 | "test": { 90 | "builder": "@angular-devkit/build-angular:karma", 91 | "options": { 92 | "polyfills": [ 93 | "zone.js", 94 | "zone.js/testing" 95 | ], 96 | "tsConfig": "tsconfig.spec.json", 97 | "assets": [ 98 | { 99 | "glob": "**/*", 100 | "input": "public" 101 | }, 102 | "src/assets" 103 | ], 104 | "styles": [ 105 | "src/styles.css" 106 | ], 107 | "scripts": [] 108 | } 109 | } 110 | } 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "silentcipherui", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "watch": "ng build --watch --configuration development", 9 | "test": "ng test", 10 | "serve:ssr:silentcipherui": "node dist/silentcipherui/server/server.mjs" 11 | }, 12 | "private": true, 13 | "dependencies": { 14 | "@angular/animations": "^18.0.0", 15 | "@angular/common": "^18.0.0", 16 | "@angular/compiler": "^18.0.0", 17 | "@angular/core": "^18.0.0", 18 | "@angular/forms": "^18.0.0", 19 | "@angular/platform-browser": "^18.0.0", 20 | "@angular/platform-browser-dynamic": "^18.0.0", 21 | "@angular/router": "^18.0.0", 22 | "@fortawesome/angular-fontawesome": "^0.15.0", 23 | "@fortawesome/free-regular-svg-icons": "^6.5.2", 24 | "@fortawesome/free-solid-svg-icons": "^6.5.2", 25 | "angular-wavesurfer-service": "^2.1.1", 26 | "bootstrap": "^4.5.3", 27 | "file-saver": "^2.0.5", 28 | "jquery": "^3.7.1", 29 | "ngx-toastr": "^18.0.0", 30 | "rxjs": "~7.8.0", 31 | "tslib": "^2.3.0", 32 | "zone.js": "~0.14.3" 33 | }, 34 | "devDependencies": { 35 | "@angular-devkit/build-angular": "^18.0.1", 36 | "@angular/cli": "^18.0.1", 37 | "@angular/compiler-cli": "^18.0.0", 38 | "@types/jasmine": "~5.1.0", 39 | "jasmine-core": "~5.1.0", 40 | "karma": "~6.4.0", 41 | "karma-chrome-launcher": "~3.2.0", 42 | "karma-coverage": "~2.2.0", 43 | "karma-jasmine": "~5.1.0", 44 | "karma-jasmine-html-reporter": "~2.1.0", 45 | "typescript": "~5.4.2" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/silentcipherui/public/favicon.ico -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { PreloadAllModules, RouterModule, Routes } from '@angular/router'; 3 | import { AuthGuard } from './guard/auth.guard'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | redirectTo: 'login', 9 | pathMatch: 'full' 10 | }, 11 | { 12 | path: 'login', 13 | loadChildren: () => import('./login/login.module').then( m => m.LoginPageModule) 14 | }, 15 | // { 16 | // path: 'main', 17 | // loadChildren: () => import('./main/main.module').then( m => m.MainPageModule), 18 | // canActivate: [AuthGuard] 19 | // }, 20 | { 21 | path: 'main', 22 | redirectTo: 'new/audio', 23 | pathMatch: 'full', 24 | }, 25 | { 26 | path: 'project', 27 | loadChildren: () => import('./project/project.module').then( m => m.ProjectPageModule), 28 | canActivate: [AuthGuard] 29 | }, 30 | { 31 | path: 'new', 32 | loadChildren: () => import('./new/new.module').then( m => m.NewPageModule), 33 | canActivate: [AuthGuard] 34 | }, 35 | { 36 | path: 'decode', 37 | loadChildren: () => import('./decode/decode.module').then( m => m.DecodePageModule), 38 | canActivate: [AuthGuard] 39 | }, 40 | { 41 | path: 'manipulate', 42 | loadChildren: () => import('./manipulate/manipulate.module').then( m => m.ManipulatePageModule), 43 | canActivate: [AuthGuard] 44 | } 45 | ]; 46 | 47 | @NgModule({ 48 | imports: [ 49 | RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules }) 50 | ], 51 | exports: [RouterModule] 52 | }) 53 | export class AppRoutingModule { } 54 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/app.component.css: -------------------------------------------------------------------------------- 1 | .loading-container { 2 | position: fixed; 3 | top: 0; 4 | left: 0; 5 | width: 100vw; 6 | height: 100vh; 7 | background-color: rgba(0,0,0,0.7); 8 | z-index: 5; 9 | } -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | 4 | describe('AppComponent', () => { 5 | beforeEach(async () => { 6 | await TestBed.configureTestingModule({ 7 | imports: [AppComponent], 8 | }).compileComponents(); 9 | }); 10 | 11 | it('should create the app', () => { 12 | const fixture = TestBed.createComponent(AppComponent); 13 | const app = fixture.componentInstance; 14 | expect(app).toBeTruthy(); 15 | }); 16 | 17 | it(`should have the 'silentcipherui' title`, () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.componentInstance; 20 | expect(app.title).toEqual('silentcipherui'); 21 | }); 22 | 23 | it('should render title', () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | fixture.detectChanges(); 26 | const compiled = fixture.nativeElement as HTMLElement; 27 | expect(compiled.querySelector('h1')?.textContent).toContain('Hello, silentcipherui'); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { delay } from 'rxjs/operators'; 3 | import { LoadingService } from './services/loading.service'; 4 | 5 | @Component({ 6 | selector: 'app-root', 7 | templateUrl: 'app.component.html', 8 | styleUrls: ['app.component.scss'] 9 | }) 10 | export class AppComponent implements OnInit { 11 | loading: boolean = false; 12 | constructor( 13 | private _loading: LoadingService 14 | ) { } 15 | 16 | ngOnInit() { 17 | this.listenToLoading(); 18 | } 19 | 20 | /** 21 | * Listen to the loadingSub property in the LoadingService class. This drives the 22 | * display of the loading spinner. 23 | */ 24 | listenToLoading(): void { 25 | this._loading.loadingSub 26 | .pipe(delay(0)) // This prevents a ExpressionChangedAfterItHasBeenCheckedError for subsequent requests 27 | .subscribe((loading) => { 28 | this.loading = loading; 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/app.module.server.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { ServerModule } from '@angular/platform-server'; 3 | 4 | import { AppModule } from './app.module'; 5 | import { AppComponent } from './app.component'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | AppModule, 10 | ServerModule, 11 | ], 12 | bootstrap: [AppComponent], 13 | }) 14 | export class AppServerModule {} 15 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | import { NgModule } from '@angular/core'; 4 | import { BrowserModule } from '@angular/platform-browser'; 5 | 6 | import { AppComponent } from './app.component'; 7 | import { AppRoutingModule } from './app-routing.module'; 8 | 9 | import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; 10 | import { MyHttpLogInterceptor } from './services/http.interceptor'; 11 | 12 | import * as $ from 'jquery'; 13 | import { ToastrModule } from 'ngx-toastr'; 14 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 15 | 16 | @NgModule({ 17 | declarations: [AppComponent], 18 | imports: [BrowserModule, AppRoutingModule, HttpClientModule, BrowserAnimationsModule, 19 | ToastrModule.forRoot({ 20 | positionClass :'toast-bottom-right' 21 | })], 22 | providers: [ 23 | { provide: HTTP_INTERCEPTORS, useClass: MyHttpLogInterceptor, multi: true }, 24 | ], 25 | bootstrap: [AppComponent] 26 | }) 27 | export class AppModule { } -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/decode/audio/audio-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { AudioPage } from './audio.page'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: '', 9 | component: AudioPage 10 | } 11 | ]; 12 | 13 | @NgModule({ 14 | imports: [RouterModule.forChild(routes)], 15 | exports: [RouterModule], 16 | }) 17 | export class AudioPageRoutingModule {} 18 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/decode/audio/audio.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | 5 | 6 | import { AudioPageRoutingModule } from './audio-routing.module'; 7 | 8 | import { AudioPage } from './audio.page'; 9 | 10 | import { HeaderComponentModule } from '../../reusable/header/header.module'; 11 | import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; 12 | 13 | @NgModule({ 14 | imports: [ 15 | CommonModule, 16 | FormsModule, 17 | AudioPageRoutingModule, 18 | HeaderComponentModule, 19 | FontAwesomeModule 20 | ], 21 | declarations: [AudioPage] 22 | }) 23 | export class AudioPageModule {} 24 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/decode/audio/audio.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
Configuration
11 |
12 | You can choose if you want to use the 16khz model or the 44.1khz model. 13 |
14 |
15 |
16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | 31 |
32 |
33 | 34 |
35 |
36 |
37 |
Upload
Audio
38 |
39 |
40 |
41 | 42 |
43 | 44 | 45 | {{fileName ? "Change Audio" : "Upload Audio"}} 46 | 47 | 48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | 59 | 60 | 61 | 62 | 63 |
64 |
65 |
66 | Confidence: {{confidence}} 67 |
68 |
The confidence is quite low. There is probably no message embedded in the waveform
69 |
70 |
71 |
There is no message present in the audio file
72 |
73 | 86 | 87 |
88 |
89 |
90 | 91 | 92 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/decode/audio/audio.page.scss: -------------------------------------------------------------------------------- 1 | .file-input { 2 | display: none; 3 | } 4 | .upload-img { 5 | width: 60px; 6 | } 7 | .upload-img:hover { 8 | box-shadow:0 10px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19); 9 | border-radius: 50%; 10 | } 11 | 12 | .custom-form-group{ 13 | padding:10px; 14 | border:1px solid #d3d3d3; 15 | border-radius: 4px; 16 | // margin:10px; 17 | } 18 | .custom-form-group>label{ 19 | position:relative; 20 | top:-29px; 21 | left:5px; 22 | background-color:white; 23 | } 24 | 25 | .custom-form-group>input{ 26 | border:none; 27 | } 28 | 29 | textarea:focus, input:focus{ 30 | outline: none; 31 | } -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/decode/audio/audio.page.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { IonicModule } from '@ionic/angular'; 3 | 4 | import { AudioPage } from './audio.page'; 5 | 6 | describe('AudioPage', () => { 7 | let component: AudioPage; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [ AudioPage ], 13 | imports: [IonicModule.forRoot()] 14 | }).compileComponents(); 15 | 16 | fixture = TestBed.createComponent(AudioPage); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | })); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/decode/audio/audio.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { environment } from '../../../environments/environment'; 4 | import { HttpClient } from '@angular/common/http'; 5 | import { NotificationService } from '../..//services/notification.service'; 6 | import { LoginService } from '../../services/login.service'; 7 | 8 | @Component({ 9 | selector: 'app-audio', 10 | templateUrl: './audio.page.html', 11 | styleUrls: ['./audio.page.scss'], 12 | }) 13 | export class AudioPage implements OnInit { 14 | 15 | fileName = ''; 16 | formData = null; 17 | message = null; 18 | confidence = null; 19 | no_message_detected = false; 20 | 21 | project = { 22 | message: [], 23 | error: [], 24 | extension: '', 25 | encoded: false, 26 | _id: '', 27 | file: '', 28 | name: '', 29 | selected: 0, 30 | sdr: -1 31 | }; 32 | 33 | model_options = [ 34 | { 35 | 'desc': 'high quality encoding', 36 | 'message_limit': [0, 255], 37 | 'message_len': 5 38 | } 39 | ] 40 | 41 | model_type = '44k'; 42 | 43 | constructor(private notificationService: NotificationService, private router: Router, private http: HttpClient, private loginService: LoginService) {} 44 | 45 | gen_len(num){ 46 | return Array(num); 47 | } 48 | 49 | onFileSelected(event) { 50 | 51 | this.formData = new FormData(); 52 | 53 | const file:File = event.target.files[0]; 54 | 55 | if (file) { 56 | 57 | this.fileName = file.name; 58 | this.formData.append("file", file); 59 | } 60 | } 61 | 62 | submit(){ 63 | if (!this.fileName) { 64 | this.notificationService.presentToastError('Please provide file to be uploaded'); 65 | return; 66 | } 67 | this.formData.append("type", 'audio'); 68 | this.formData.append("phase_shift_decoding", environment.phase_shift_decoding); 69 | this.formData.append("model_type", this.model_type); 70 | this.http.post(environment.SERVER_URL + 'api/decode', this.formData, {params: {loading: 'true'}}).subscribe((res: any) => { 71 | if (res.status){ 72 | this.message = res.decode.messages[0]; 73 | this.confidence = res.decode.confidences[0]; 74 | this.notificationService.presentToastSuccess('Message Decoded Successfully.'); 75 | this.no_message_detected = false; 76 | } 77 | else{ 78 | this.notificationService.presentToastError('No message detected in the audio'); 79 | this.no_message_detected = true; 80 | } 81 | }) 82 | 83 | } 84 | 85 | ngOnInit() { 86 | this.formData = new FormData(); 87 | this.model_type = '44k'; 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/decode/decode-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { DecodePage } from './decode.page'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: '', 9 | component: DecodePage 10 | }, 11 | { 12 | path: 'audio', 13 | loadChildren: () => import('./audio/audio.module').then( m => m.AudioPageModule) 14 | }, 15 | ]; 16 | 17 | @NgModule({ 18 | imports: [RouterModule.forChild(routes)], 19 | exports: [RouterModule], 20 | }) 21 | export class DecodePageRoutingModule {} 22 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/decode/decode.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | 5 | import { DecodePageRoutingModule } from './decode-routing.module'; 6 | 7 | import { DecodePage } from './decode.page'; 8 | 9 | import { HeaderComponentModule } from '../reusable/header/header.module'; 10 | import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; 11 | 12 | @NgModule({ 13 | imports: [ 14 | CommonModule, 15 | FormsModule, 16 | DecodePageRoutingModule, 17 | HeaderComponentModule, 18 | FontAwesomeModule 19 | ], 20 | declarations: [DecodePage] 21 | }) 22 | export class DecodePageModule {} 23 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/decode/decode.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

DECODE

5 |
6 |
7 |
8 |
9 | 10 | 11 |
12 |
13 | 18 |
19 |
20 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/decode/decode.page.scss: -------------------------------------------------------------------------------- 1 | .my-lst :hover{ 2 | /* transform: scale(1.04);*/ 3 | cursor: pointer; 4 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12) !important; 5 | 6 | } -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/decode/decode.page.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { IonicModule } from '@ionic/angular'; 3 | 4 | import { DecodePage } from './decode.page'; 5 | 6 | describe('DecodePage', () => { 7 | let component: DecodePage; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [ DecodePage ], 13 | imports: [IonicModule.forRoot()] 14 | }).compileComponents(); 15 | 16 | fixture = TestBed.createComponent(DecodePage); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | })); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/decode/decode.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-decode', 5 | templateUrl: './decode.page.html', 6 | styleUrls: ['./decode.page.scss'], 7 | }) 8 | export class DecodePage implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/guard/auth.guard.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { AuthGuard } from './auth.guard'; 4 | 5 | describe('AuthGuard', () => { 6 | let guard: AuthGuard; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | guard = TestBed.inject(AuthGuard); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(guard).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/guard/auth.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router'; 3 | import { Observable } from 'rxjs'; 4 | import { NotificationService } from '../services/notification.service'; 5 | import { LoginService } from '../services/login.service' 6 | 7 | @Injectable({ 8 | providedIn: 'root' 9 | }) 10 | export class AuthGuard implements CanActivate { 11 | 12 | constructor(private router: Router, private notification: NotificationService, private loginService: LoginService) {} 13 | 14 | // canActivate( 15 | // next: ActivatedRouteSnapshot, 16 | // state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { 17 | 18 | // // Basic authentication based on if the user provided email id. 19 | 20 | // // If email is set in localStorage then page is accessible otherwise redirected to the login page 21 | 22 | // const email = localStorage.getItem('email'); 23 | // const token = localStorage.getItem('token'); 24 | // console.log('Auth: ', email); 25 | // if (email !== null && email !== 'null'){ 26 | // return true; 27 | // } 28 | // this.notification.presentToast('Please login first!') 29 | // this.router.navigateByUrl('/login'); 30 | // return false; 31 | // } 32 | 33 | canActivate( 34 | next: ActivatedRouteSnapshot, 35 | state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { 36 | if (this.loginService.isLoggedIn()) { 37 | return true; 38 | } 39 | else { 40 | this.router.navigate(['login'], { queryParams: { loginRedirect: state.url } }); 41 | return false; 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/login/login-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { LoginPage } from './login.page'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: '', 9 | component: LoginPage 10 | } 11 | ]; 12 | 13 | @NgModule({ 14 | imports: [RouterModule.forChild(routes)], 15 | exports: [RouterModule], 16 | }) 17 | export class LoginPageRoutingModule {} 18 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/login/login.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | 5 | import { LoginPageRoutingModule } from './login-routing.module'; 6 | 7 | import { LoginPage } from './login.page'; 8 | 9 | import { HeaderComponentModule } from '../reusable/header/header.module'; 10 | import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; 11 | 12 | @NgModule({ 13 | imports: [ 14 | CommonModule, 15 | FormsModule, 16 | LoginPageRoutingModule, 17 | HeaderComponentModule, 18 | FontAwesomeModule 19 | ], 20 | declarations: [LoginPage] 21 | }) 22 | export class LoginPageModule {} 23 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/login/login.page.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 |
7 |

Watermarking Portal

8 | 9 |

Sign in

10 |

to continue

11 |
12 | 13 |
14 |
15 | 16 |
17 |
18 |
19 | 20 |
21 |
22 |
23 |
24 |
25 |
-------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/login/login.page.scss: -------------------------------------------------------------------------------- 1 | .login{ 2 | border-radius: 8px; 3 | background-color: #eeeeee; 4 | font-size: 16px; 5 | } -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/login/login.page.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { IonicModule } from '@ionic/angular'; 3 | 4 | import { LoginPage } from './login.page'; 5 | 6 | describe('LoginPage', () => { 7 | let component: LoginPage; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [ LoginPage ], 13 | imports: [IonicModule.forRoot()] 14 | }).compileComponents(); 15 | 16 | fixture = TestBed.createComponent(LoginPage); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | })); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/login/login.page.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from '@angular/common/http'; 2 | import { Component, OnInit } from '@angular/core'; 3 | import { Router } from '@angular/router'; 4 | import { environment } from '../../environments/environment'; 5 | import { LoginService } from '../services/login.service'; 6 | import { NotificationService } from '../services/notification.service'; 7 | 8 | @Component({ 9 | selector: 'app-login', 10 | templateUrl: './login.page.html', 11 | styleUrls: ['./login.page.scss'], 12 | }) 13 | export class LoginPage implements OnInit { 14 | 15 | email = ""; 16 | password = ""; 17 | 18 | constructor( 19 | public loginService: LoginService) { 20 | } 21 | 22 | ngOnInit() { 23 | } 24 | 25 | ionViewDidEnter(){ 26 | if (this.loginService.email){ 27 | this.loginService.afterLogin(); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/manipulate/audio/audio-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { AudioPage } from './audio.page'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: '', 9 | component: AudioPage 10 | } 11 | ]; 12 | 13 | @NgModule({ 14 | imports: [RouterModule.forChild(routes)], 15 | exports: [RouterModule], 16 | }) 17 | export class AudioPageRoutingModule {} 18 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/manipulate/audio/audio.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | 5 | import { AudioPageRoutingModule } from './audio-routing.module'; 6 | 7 | import { AudioPage } from './audio.page'; 8 | 9 | import { HeaderComponentModule } from '../../reusable/header/header.module'; 10 | import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; 11 | 12 | @NgModule({ 13 | imports: [ 14 | CommonModule, 15 | FormsModule, 16 | AudioPageRoutingModule, 17 | HeaderComponentModule, 18 | FontAwesomeModule 19 | ], 20 | declarations: [AudioPage] 21 | }) 22 | export class AudioPageModule {} 23 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/manipulate/audio/audio.page.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 |
7 |
Upload
8 |
9 | 10 | 11 | {{fileName || "No file uploaded yet."}} 12 | 13 | 14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
Process: {{index}}
23 |
{{visualize(i)}}
24 |
25 | 26 |
27 |
28 |
29 | 30 | Download Distorted Audio 31 | 32 |
33 |
34 | 35 |
36 |
37 |
38 | 39 | 40 | 41 | 42 | 43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
Choose Distortion
52 |
53 | 54 | 55 | 56 | 57 | 58 | 61 | 62 | 63 | 70 | 77 | 78 |
CompressionTypeBit rate 59 | 60 |
64 | 69 | 71 | 76 |
79 |
80 |
81 | 82 | 83 | 84 | 85 | 86 | 89 | 90 | 91 | 94 | 95 | 96 |
LoudnessScaling Factor 87 | 88 |
92 | 93 |
97 |
98 | 99 |
100 | 101 | 102 | 103 | 104 | 105 | 108 | 109 | 110 | 113 | 116 | 117 |
CropStartTime (sec)EndTime (sec) 106 | 107 |
111 | 112 | 114 | 115 |
118 |
119 | 120 |
121 | 122 | 123 | 124 | 125 | 126 | 129 | 130 | 131 | 134 | 136 | 137 |
ResampleSampling Rate 127 | 128 |
132 | 133 | 135 |
138 |
139 | 148 |
149 |
150 |
151 |
152 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/manipulate/audio/audio.page.scss: -------------------------------------------------------------------------------- 1 | .file-input { 2 | display: none; 3 | } 4 | .upload-img { 5 | width: 40px; 6 | } 7 | .upload-img:hover { 8 | box-shadow:0 10px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19); 9 | border-radius: 50%; 10 | } -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/manipulate/audio/audio.page.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { IonicModule } from '@ionic/angular'; 3 | 4 | import { AudioPage } from './audio.page'; 5 | 6 | describe('AudioPage', () => { 7 | let component: AudioPage; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [ AudioPage ], 13 | imports: [IonicModule.forRoot()] 14 | }).compileComponents(); 15 | 16 | fixture = TestBed.createComponent(AudioPage); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | })); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/manipulate/audio/audio.page.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from '@angular/common/http'; 2 | import { Component, OnInit } from '@angular/core'; 3 | import { NotificationService } from '../../services/notification.service'; 4 | import { environment } from '../../../environments/environment'; 5 | 6 | @Component({ 7 | selector: 'app-audio', 8 | templateUrl: './audio.page.html', 9 | styleUrls: ['./audio.page.scss'], 10 | }) 11 | export class AudioPage implements OnInit { 12 | 13 | 14 | constructor(private notificationService: NotificationService, private http: HttpClient) {} 15 | 16 | ngOnInit() { 17 | this.formData = new FormData(); 18 | } 19 | fileName = ''; 20 | formData = null; 21 | projectName = null; 22 | processList = []; 23 | distorted_path = null; 24 | decoded = []; 25 | error=false; 26 | 27 | onFileSelected(event) { 28 | 29 | this.formData = new FormData(); 30 | const file:File = event.target.files[0]; 31 | 32 | if (file) { 33 | this.fileName = file.name; 34 | this.formData.append("file", file); 35 | if (this.projectName == '' || this.projectName == null){ 36 | this.projectName = this.fileName.split('.')[0] 37 | } 38 | } 39 | } 40 | 41 | addProcess(process_info){ 42 | this.processList.push(process_info); 43 | } 44 | visualize(data){ 45 | return JSON.stringify(data); 46 | } 47 | removeProcess(index){ 48 | this.processList.splice(index,1); 49 | } 50 | 51 | applyDistortion(){ 52 | 53 | this.error=false; 54 | this.formData.append("processList", JSON.stringify(this.processList)); 55 | this.formData.append("distorted_path", this.distorted_path); 56 | 57 | this.http.post(environment.SERVER_URL + 'api/apply_distortion', this.formData, {params: {loading: 'true'}}).subscribe((res: any) => { 58 | if (res.status){ 59 | this.distorted_path = res.distorted_path; 60 | console.log(this.distorted_path) 61 | this.decoded = []; 62 | } 63 | else{ 64 | this.notificationService.presentToastError('Error when applying the distortion!'); 65 | } 66 | }) 67 | 68 | } 69 | 70 | decodeDistortedAudio(){ 71 | this.notificationService.presentToastSuccess('Decoding using the 44k model. To use the 16k model, please use the python package or submit a PR to the repo.'); 72 | this.http.post(environment.SERVER_URL + 'api/decode_file_location', {model_type: '44k', path: this.distorted_path, phase_shift_decoding: environment.phase_shift_decoding}, {params: {loading: 'true'}}).subscribe((res: any) => { 73 | if (res.status){ 74 | this.decoded = res.decode.messages[0] 75 | this.error=false; 76 | } 77 | else{ 78 | this.error=true; 79 | this.notificationService.presentToastError('Error when decoding the message!'); 80 | } 81 | }); 82 | } 83 | getEnv(){ 84 | return environment; 85 | } 86 | gen_len(num){ 87 | return Array(num); 88 | } 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/manipulate/manipulate-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { ManipulatePage } from './manipulate.page'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: '', 9 | component: ManipulatePage 10 | }, 11 | { 12 | path: 'audio', 13 | loadChildren: () => import('./audio/audio.module').then( m => m.AudioPageModule) 14 | } 15 | ]; 16 | 17 | @NgModule({ 18 | imports: [RouterModule.forChild(routes)], 19 | exports: [RouterModule], 20 | }) 21 | export class ManipulatePageRoutingModule {} 22 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/manipulate/manipulate.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | 5 | import { ManipulatePageRoutingModule } from './manipulate-routing.module'; 6 | 7 | import { ManipulatePage } from './manipulate.page'; 8 | 9 | import { HeaderComponentModule } from '../reusable/header/header.module'; 10 | import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; 11 | 12 | @NgModule({ 13 | imports: [ 14 | CommonModule, 15 | FormsModule, 16 | ManipulatePageRoutingModule, 17 | HeaderComponentModule, 18 | FontAwesomeModule 19 | ], 20 | declarations: [ManipulatePage] 21 | }) 22 | export class ManipulatePageModule {} 23 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/manipulate/manipulate.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 |

Audio/Video Processing

7 |
8 |
9 |
10 |
11 |
12 | 13 | 14 |
15 |
16 |
17 |
18 | 19 | 20 | 21 |
22 |
23 |
24 |
25 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/manipulate/manipulate.page.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/silentcipherui/src/app/manipulate/manipulate.page.scss -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/manipulate/manipulate.page.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { IonicModule } from '@ionic/angular'; 3 | 4 | import { ManipulatePage } from './manipulate.page'; 5 | 6 | describe('ManipulatePage', () => { 7 | let component: ManipulatePage; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [ ManipulatePage ], 13 | imports: [IonicModule.forRoot()] 14 | }).compileComponents(); 15 | 16 | fixture = TestBed.createComponent(ManipulatePage); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | })); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/manipulate/manipulate.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-manipulate', 5 | templateUrl: './manipulate.page.html', 6 | styleUrls: ['./manipulate.page.scss'], 7 | }) 8 | export class ManipulatePage implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/new/audio/audio-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { AudioPage } from './audio.page'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: '', 9 | component: AudioPage 10 | } 11 | ]; 12 | 13 | @NgModule({ 14 | imports: [RouterModule.forChild(routes)], 15 | exports: [RouterModule], 16 | }) 17 | export class AudioPageRoutingModule {} 18 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/new/audio/audio.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | 5 | import { AudioPageRoutingModule } from './audio-routing.module'; 6 | 7 | import { AudioPage } from './audio.page'; 8 | 9 | import { HeaderComponentModule } from '../../reusable/header/header.module'; 10 | import { ProjectbarComponentModule } from '../../reusable/projectbar/projectbar.module'; 11 | import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; 12 | 13 | @NgModule({ 14 | imports: [ 15 | CommonModule, 16 | FormsModule, 17 | AudioPageRoutingModule, 18 | ProjectbarComponentModule, 19 | HeaderComponentModule, 20 | FontAwesomeModule 21 | ], 22 | declarations: [AudioPage] 23 | }) 24 | export class AudioPageModule {} 25 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/new/audio/audio.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 | 7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Create
New Project
16 |
17 |
18 |
19 | 20 |
21 | 22 | 23 | {{fileName ? "Change Audio" : "Upload Audio"}} 24 | 25 | 26 |
27 |
28 |
29 |
30 | 31 | 32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | 45 | 46 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/new/audio/audio.page.scss: -------------------------------------------------------------------------------- 1 | .file-input { 2 | display: none; 3 | } 4 | .upload-img { 5 | width: 60px; 6 | } 7 | .upload-img:hover { 8 | box-shadow:0 10px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19); 9 | border-radius: 50%; 10 | } 11 | 12 | .custom-form-group{ 13 | padding:10px; 14 | border:1px solid #d3d3d3; 15 | border-radius: 4px; 16 | // margin:10px; 17 | } 18 | .custom-form-group>label{ 19 | position:relative; 20 | top:-29px; 21 | left:5px; 22 | background-color:white; 23 | } 24 | 25 | .custom-form-group>input{ 26 | border:none; 27 | } 28 | 29 | textarea:focus, input:focus{ 30 | outline: none; 31 | } -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/new/audio/audio.page.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { IonicModule } from '@ionic/angular'; 3 | 4 | import { AudioPage } from './audio.page'; 5 | 6 | describe('AudioPage', () => { 7 | let component: AudioPage; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [ AudioPage ], 13 | imports: [IonicModule.forRoot()] 14 | }).compileComponents(); 15 | 16 | fixture = TestBed.createComponent(AudioPage); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | })); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/new/audio/audio.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit , ViewChild, ElementRef, HostListener, AfterViewChecked } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { environment } from '../../../environments/environment'; 4 | import { HttpClient } from '@angular/common/http'; 5 | import { NotificationService } from '../../services/notification.service'; 6 | import { LoginService } from '../../services/login.service'; 7 | 8 | @Component({ 9 | selector: 'app-audio', 10 | templateUrl: './audio.page.html', 11 | styleUrls: ['./audio.page.scss'], 12 | }) 13 | export class AudioPage implements OnInit { 14 | 15 | @ViewChild('container', {read: ElementRef}) container: ElementRef; 16 | @ViewChild('header', {read: ElementRef}) header: ElementRef; 17 | 18 | @HostListener('window:resize', ['$event']) 19 | onResize(event?) { 20 | this.container.nativeElement.style.height = window.innerHeight - this.header.nativeElement.offsetHeight + 'px'; 21 | } 22 | 23 | fileName = ''; 24 | formData = null; 25 | projectName = null; 26 | 27 | constructor(private notificationService: NotificationService, private router: Router, private http: HttpClient, private loginService: LoginService) {} 28 | 29 | 30 | ngOnInit() { 31 | this.formData = new FormData(); 32 | } 33 | 34 | onFileSelected(event) { 35 | this.formData = new FormData(); 36 | 37 | const file:File = event.target.files[0]; 38 | 39 | if (file) { 40 | 41 | this.fileName = file.name; 42 | this.formData.append("file", file); 43 | if (this.projectName == '' || this.projectName == null){ 44 | this.projectName = this.fileName.split('.')[0] 45 | } 46 | } 47 | } 48 | 49 | submit(){ 50 | console.log('submit') 51 | if (!this.fileName) { 52 | this.notificationService.presentToastError('Please provide file to be uploaded'); 53 | return; 54 | } 55 | if (!this.projectName) { 56 | this.notificationService.presentToastError('Please provide a project name for unique identification'); 57 | return; 58 | } 59 | console.log('submit1') 60 | this.formData.append("projectName", this.projectName); 61 | this.formData.append("type", 'audio'); 62 | this.http.post(environment.SERVER_URL + 'api/new_project', this.formData, {params: {loading: 'true'}}).subscribe((res: any) => { 63 | if (res.status){ 64 | this.loginService.user_data = res.user_data; 65 | this.router.navigateByUrl('/project/' + res.id); 66 | this.notificationService.presentToastSuccess('Project Creation Success.'); 67 | } 68 | else{ 69 | this.notificationService.presentToastError('Project Creation Failed. Please contact admin'); 70 | } 71 | }) 72 | 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/new/new-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { NewPage } from './new.page'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: '', 9 | component: NewPage 10 | }, 11 | { 12 | path: 'audio', 13 | loadChildren: () => import('./audio/audio.module').then( m => m.AudioPageModule) 14 | } 15 | ]; 16 | 17 | @NgModule({ 18 | imports: [RouterModule.forChild(routes)], 19 | exports: [RouterModule], 20 | }) 21 | export class NewPageRoutingModule {} 22 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/new/new.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | 5 | import { NewPageRoutingModule } from './new-routing.module'; 6 | 7 | import { NewPage } from './new.page'; 8 | 9 | import { HeaderComponentModule } from '../reusable/header/header.module'; 10 | import { ProjectbarComponentModule } from '../reusable/projectbar/projectbar.module'; 11 | import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; 12 | 13 | @NgModule({ 14 | imports: [ 15 | CommonModule, 16 | FormsModule, 17 | NewPageRoutingModule, 18 | ProjectbarComponentModule, 19 | HeaderComponentModule, 20 | FontAwesomeModule 21 | ], 22 | declarations: [NewPage] 23 | }) 24 | export class NewPageModule {} 25 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/new/new.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 | 7 |
8 |
9 |
10 |
11 |
12 |

13 | Choose which media you want to add watermarking to 14 |

15 |
16 |
17 |
18 |
19 |
20 |
21 | 22 | 23 |
24 |
25 | 30 |
31 |
32 |
33 |
34 |
35 | 36 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/new/new.page.scss: -------------------------------------------------------------------------------- 1 | .my-lst :hover{ 2 | /* transform: scale(1.04);*/ 3 | cursor: pointer; 4 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12) !important; 5 | 6 | } -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/new/new.page.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { IonicModule } from '@ionic/angular'; 3 | 4 | import { NewPage } from './new.page'; 5 | 6 | describe('NewPage', () => { 7 | let component: NewPage; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [ NewPage ], 13 | imports: [IonicModule.forRoot()] 14 | }).compileComponents(); 15 | 16 | fixture = TestBed.createComponent(NewPage); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | })); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/new/new.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit , ViewChild, ElementRef, HostListener } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-new', 5 | templateUrl: './new.page.html', 6 | styleUrls: ['./new.page.scss'], 7 | }) 8 | export class NewPage implements OnInit { 9 | 10 | @ViewChild('container', {read: ElementRef}) container: ElementRef; 11 | @ViewChild('header', {read: ElementRef}) header: ElementRef; 12 | 13 | @HostListener('window:resize', ['$event']) 14 | onResize(event?) { 15 | this.container.nativeElement.style.height = window.innerHeight - this.header.nativeElement.offsetHeight + 'px'; 16 | } 17 | 18 | constructor() { } 19 | 20 | ngOnInit(){ 21 | 22 | } 23 | 24 | ionViewDidEnter() { 25 | this.onResize(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/project/project-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { ProjectPage } from './project.page'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: ':id', 9 | component: ProjectPage 10 | } 11 | ]; 12 | 13 | @NgModule({ 14 | imports: [RouterModule.forChild(routes)], 15 | exports: [RouterModule], 16 | }) 17 | export class ProjectPageRoutingModule {} 18 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/project/project.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | 5 | 6 | import { ProjectPageRoutingModule } from './project-routing.module'; 7 | 8 | import { HeaderComponentModule } from '../reusable/header/header.module'; 9 | 10 | import { ProjectPage } from './project.page'; 11 | import { ProjectbarComponentModule } from '../reusable/projectbar/projectbar.module'; 12 | import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; 13 | 14 | @NgModule({ 15 | imports: [ 16 | CommonModule, 17 | FormsModule, 18 | HeaderComponentModule, 19 | ProjectPageRoutingModule, 20 | ProjectbarComponentModule, 21 | FontAwesomeModule 22 | ], 23 | declarations: [ProjectPage] 24 | }) 25 | export class ProjectPageModule {} 26 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/project/project.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 | 7 |
8 |
9 |

{{project.name}}

10 |
11 |

Original Audio

12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 |
23 | 24 |
25 |

Message Encoded Audio

26 |
27 | 28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
Configuration
42 |
43 | You can choose if you want to use the 16khz model or the 44.1khz model.
44 | You can also modify the SDR, but beware that the model may behave unexpectedly. 45 | If you want to use the default SDR, let the SDR field be -1. 46 |
47 |
48 |
49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 |
57 |
58 | 59 | 60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
Decode Message
73 |
74 | You can test if the model is able to decode the current project by clicking on decode audio button.
75 | If you want to decode an audio from a different project, click on the Decode button on the top-right. 76 |
77 |
78 |
79 |
80 |
81 | 82 | 83 | 84 | 85 |
86 |
87 |
88 |
89 |
90 | 91 | 92 | 93 | 94 | 95 |
96 |
97 |
98 | 99 | 100 | 101 | 102 | 103 |
104 |
105 |
106 |
107 |
Signal to Noise Ratio
108 |
109 | 110 | {{project.sdr}}dB 111 | 112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
Embed a message
124 |
125 | You can embed a 40 bit message inside the audio file.
126 | The message is of the format: A-B-C-D-E, where A, B, C, D, E are numbers which lie in the range of 0-255 (both included) 127 |
128 |
129 |
130 |
131 |
132 | 133 | 134 | 135 | 136 | 137 | 138 |
139 |
140 |
141 |
142 |
143 |
144 | 154 |
155 |
156 | 162 |
163 |
164 |
165 | 166 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/project/project.page.scss: -------------------------------------------------------------------------------- 1 | .wrong_input{ 2 | border-color: red !important; 3 | } 4 | .wrong_input:focus{ 5 | border-color: red !important; 6 | outline: none; 7 | } 8 | 9 | 10 | .file-input { 11 | display: none; 12 | } 13 | .upload-img { 14 | width: 60px; 15 | } 16 | .upload-img:hover { 17 | box-shadow:0 10px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19); 18 | border-radius: 50%; 19 | } 20 | 21 | .custom-form-group{ 22 | padding:10px; 23 | border:1px solid #d3d3d3; 24 | border-radius: 4px; 25 | // margin:10px; 26 | } 27 | .custom-form-group>label{ 28 | position:relative; 29 | top:-29px; 30 | left:5px; 31 | background-color:white; 32 | } 33 | 34 | .custom-form-group>input{ 35 | border:none; 36 | } 37 | 38 | textarea:focus, input:focus{ 39 | outline: none; 40 | } -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/project/project.page.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { IonicModule } from '@ionic/angular'; 3 | 4 | import { ProjectPage } from './project.page'; 5 | 6 | describe('ProjectPage', () => { 7 | let component: ProjectPage; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [ ProjectPage ], 13 | imports: [IonicModule.forRoot()] 14 | }).compileComponents(); 15 | 16 | fixture = TestBed.createComponent(ProjectPage); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | })); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/project/project.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit , ViewChild, ElementRef, HostListener, ChangeDetectorRef } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | import { LoginService } from '../services/login.service'; 4 | import { HttpClient } from '@angular/common/http'; 5 | import { environment } from '../../environments/environment'; 6 | import { NotificationService } from '../services/notification.service'; 7 | 8 | declare var WaveSurfer; 9 | 10 | @Component({ 11 | selector: 'app-project', 12 | templateUrl: './project.page.html', 13 | styleUrls: ['./project.page.scss'], 14 | }) 15 | export class ProjectPage implements OnInit { 16 | id = null; 17 | project = { 18 | message: [], 19 | error: [], 20 | extension: '', 21 | encoded: false, 22 | _id: '', 23 | file: '', 24 | name: '', 25 | selected: 0, 26 | sdr: -1 27 | }; 28 | paused = true; 29 | encoded_paused = true; 30 | wr = null; 31 | wr_encoded = null; 32 | decoded = []; 33 | user_provided_SDR=-1; 34 | model_type='44k'; 35 | 36 | // model_options = [ 37 | // { 38 | // 'desc': 'high quality encoding', 39 | // 'message_dim': 5, 40 | // 'message_len': 21 41 | // }, 42 | // { 43 | // 'desc': 'high message encoding accuracy', 44 | // 'message_dim': 17, 45 | // 'message_len': 11 46 | // } 47 | // ] 48 | model_options = [ 49 | { 50 | 'desc': 'high quality encoding', 51 | 'message_limit': [0, 255], 52 | 'message_len': 5 53 | } 54 | ] 55 | 56 | @ViewChild('container', {read: ElementRef}) container: ElementRef; 57 | @ViewChild('content', {read: ElementRef}) content: ElementRef; 58 | @ViewChild('header', {read: ElementRef}) header: ElementRef; 59 | @ViewChild('waveform', {read: ElementRef}) waveform: ElementRef; 60 | @ViewChild('encoded_waveform', {read: ElementRef}) encoded_waveform: ElementRef; 61 | 62 | select(i) { 63 | this.project.selected = i; 64 | this.project.message = Array(this.model_options[this.project.selected].message_len).fill(''); 65 | this.project.error = Array(this.model_options[this.project.selected].message_len).fill(false); 66 | 67 | } 68 | 69 | onResize(event?) { 70 | this.cd.detectChanges(); 71 | this.container.nativeElement.style.height = window.innerHeight - this.header.nativeElement.offsetHeight + 'px'; 72 | this.waveform.nativeElement.style.width = this.content.nativeElement.offsetWidth - 250 + 'px'; 73 | this.setWR(); 74 | } 75 | 76 | onResizeEncoded(event?) { 77 | this.cd.detectChanges(); 78 | this.container.nativeElement.style.height = window.innerHeight - this.header.nativeElement.offsetHeight + 'px'; 79 | if (this.encoded_waveform){ 80 | this.encoded_waveform.nativeElement.style.width = this.content.nativeElement.offsetWidth - 250 + 'px'; 81 | this.setWREncoded(); 82 | } 83 | } 84 | 85 | @HostListener('window:resize', ['$event']) 86 | resizeEvent(event?) { 87 | this.onResize(event); 88 | this.onResizeEncoded(event); 89 | } 90 | 91 | constructor( 92 | private route: ActivatedRoute, private loginService: LoginService, private http: HttpClient, private notification: NotificationService, 93 | private cd: ChangeDetectorRef 94 | ) {} 95 | 96 | ngOnInit() { 97 | this.id = this.route.snapshot.params['id']; 98 | console.log(this.id) 99 | this.wr = null 100 | this.wr_encoded = null; 101 | 102 | this.project = { 103 | message: Array(this.model_options[this.project.selected].message_len).fill(''), 104 | error: Array(this.model_options[this.project.selected].message_len).fill(false), 105 | extension: '', 106 | encoded: false, 107 | selected: 0, 108 | _id: '', 109 | file: '', 110 | name: '', 111 | sdr: -1 112 | }; 113 | this.user_provided_SDR = -1; 114 | this.model_type = '44k'; 115 | this.paused = true; 116 | this.encoded_paused = true; 117 | this.decoded = Array(this.model_options[this.project.selected].message_len).fill(null); 118 | this.getProjectInfo(); 119 | } 120 | 121 | getEnv(){ 122 | return environment; 123 | } 124 | 125 | setWR(){ 126 | if (!this.project._id){ 127 | return; 128 | } 129 | this.waveform.nativeElement.innerHTML = ''; 130 | this.wr = WaveSurfer.create({ 131 | // container: '#waveform', 132 | container: this.waveform.nativeElement, 133 | waveColor: '#0275d8', 134 | progressColor: 'lightblue', 135 | scrollParent: true 136 | }); 137 | console.log('WR', this.getEnv().SERVER_URL + 'api/files/' + this.project._id + '.' + this.project.extension); 138 | this.wr.load(this.getEnv().SERVER_URL + 'api/files/' + this.project._id + '.' + this.project.extension) 139 | var self = this; 140 | this.wr.on('play', function() { 141 | self.paused = false; 142 | console.log('play', self.paused); 143 | self.cd.detectChanges(); 144 | }); 145 | 146 | this.wr.on('pause', function() { 147 | self.paused = true; 148 | console.log('pause', self.paused); 149 | self.cd.detectChanges(); 150 | }); 151 | 152 | this.wr.on('finish', function() { 153 | self.paused = true; 154 | self.wr.seekTo(0); 155 | console.log('finish', self.paused); 156 | self.cd.detectChanges(); 157 | }); 158 | } 159 | 160 | setWREncoded(){ 161 | if (!this.project._id){ 162 | return; 163 | } 164 | this.encoded_waveform.nativeElement.innerHTML = ''; 165 | this.wr_encoded = WaveSurfer.create({ 166 | container: this.encoded_waveform.nativeElement, 167 | waveColor: '#0275d8', 168 | progressColor: 'lightblue', 169 | scrollParent: true 170 | }); 171 | console.log('WR_encoded', this.getEnv().SERVER_URL + 'api/files/' + this.project._id + '_encoded.' + this.project.extension); 172 | this.wr_encoded.load(this.getEnv().SERVER_URL + 'api/files/' + this.project._id + '_encoded.' + this.project.extension) 173 | var self = this; 174 | this.wr_encoded.on('play', function() { 175 | self.encoded_paused = false; 176 | console.log('play', self.encoded_paused); 177 | self.cd.detectChanges(); 178 | }); 179 | 180 | this.wr_encoded.on('pause', function() { 181 | self.encoded_paused = true; 182 | console.log('pause', self.encoded_paused); 183 | self.cd.detectChanges(); 184 | }); 185 | 186 | this.wr_encoded.on('finish', function() { 187 | self.encoded_paused = true; 188 | self.wr_encoded.seekTo(0); 189 | console.log('finish', self.encoded_paused); 190 | self.cd.detectChanges(); 191 | }); 192 | } 193 | 194 | getProjectInfo() { 195 | this.paused = true; 196 | this.encoded_paused = true; 197 | this.http.post(environment.SERVER_URL + 'api/get_project_data', {email: this.loginService.email, projectid: this.id}).subscribe((res: any) => { 198 | if (res.status){ 199 | this.project = res.project; 200 | this.onResize(); 201 | if (this.project.encoded){ 202 | this.onResizeEncoded(); 203 | } 204 | } 205 | else{ 206 | this.notification.presentToastError('Error when getting project!'); 207 | } 208 | }); 209 | } 210 | 211 | check_message(){ 212 | let error = false; 213 | for(let i=0; i < this.project.message.length; ++i){ 214 | if (this.project.message[i] == '' || this.project.message[i]==null){ 215 | this.notification.presentToastError('None of the fields should be blank in the message'); 216 | error = true; 217 | break; 218 | } 219 | if (!/^\d+$/.test(this.project.message[i])){ 220 | this.notification.presentToastError('Message should only be integers between 0-255 (0 and 255 are included)'); 221 | error = true; 222 | break; 223 | } 224 | else if (Number(this.project.message[i]) < this.model_options[this.project.selected].message_limit[0] || Number(this.project.message[i]) > this.model_options[this.project.selected].message_limit[1]){ 225 | this.notification.presentToastError('Message should have values less than or equal to ' + this.model_options[this.project.selected].message_limit[1] + ' and greater than or equal to ' + this.model_options[this.project.selected].message_limit[0]); 226 | error = true; 227 | break; 228 | } 229 | } 230 | return !error; 231 | } 232 | 233 | check_message_i(i){ 234 | if (this.project.message[i] == '' || this.project.message[i] == null){ 235 | return 236 | } 237 | if (!/^\d+$/.test(this.project.message[i])){ 238 | this.project.error[i] = true; 239 | this.notification.presentToastError('Message should only be integers between 0-255 (0 and 255 are included)'); 240 | } 241 | else if (Number(this.project.message[i]) < this.model_options[this.project.selected].message_limit[0] || Number(this.project.message[i]) > this.model_options[this.project.selected].message_limit[1]){ 242 | this.project.error[i] = true; 243 | this.notification.presentToastError('Message should have values less than or equal to ' + this.model_options[this.project.selected].message_limit[1] + ' and greater than or equal to ' + this.model_options[this.project.selected].message_limit[0]); 244 | } 245 | else{ 246 | this.project.error[i] = false; 247 | } 248 | } 249 | encode() { 250 | this.check_message(); 251 | this.project.encoded = false; 252 | this.decoded = Array(this.model_options[this.project.selected].message_len).fill(null); 253 | this.http.post(environment.SERVER_URL + 'api/encode_project', { 254 | email: this.loginService.email, 255 | project: this.project, 256 | message_sdr: this.user_provided_SDR == -1? null: this.user_provided_SDR, 257 | model_type: this.model_type 258 | }, {params: {loading: 'true'}}).subscribe((res: any) => { 259 | if (res.status){ 260 | this.project = res.project; 261 | this.cd.detectChanges(); 262 | if (this.project.encoded){ 263 | this.onResizeEncoded(); 264 | } 265 | } 266 | else{ 267 | this.notification.presentToastError('Error when encoding the message!'); 268 | } 269 | }); 270 | } 271 | 272 | decode(){ 273 | if (!this.project.encoded){ 274 | this.notification.presentToastError('Please Encode the Audio First'); 275 | return; 276 | } 277 | console.log('Decoding') 278 | this.http.post(environment.SERVER_URL + 'api/decode_file_location', { 279 | path: this.project._id + '_encoded.' + this.project.extension, 280 | phase_shift_decoding: environment.phase_shift_decoding, 281 | model_type: this.model_type 282 | }, {params: {loading: 'true'}}).subscribe((res: any) => { 283 | if (res.status){ 284 | this.decoded = res.decode.messages[0] 285 | } 286 | else{ 287 | this.notification.presentToastError('Error when decoding the message!'); 288 | } 289 | }); 290 | } 291 | 292 | check_match(){ 293 | if (this.decoded.length == 0){ 294 | return false; 295 | } 296 | if (this.decoded[0] === null){ 297 | return false; 298 | } 299 | let result = true; 300 | for(let i =0;i(num); 312 | } 313 | 314 | } 315 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/reusable/header/header.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/reusable/header/header.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/silentcipherui/src/app/reusable/header/header.component.scss -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/reusable/header/header.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { IonicModule } from '@ionic/angular'; 3 | 4 | import { HeaderComponent } from './header.component'; 5 | 6 | describe('HeaderComponent', () => { 7 | let component: HeaderComponent; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [ HeaderComponent ], 13 | imports: [IonicModule.forRoot()] 14 | }).compileComponents(); 15 | 16 | fixture = TestBed.createComponent(HeaderComponent); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | })); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/reusable/header/header.component.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from '@angular/common/http'; 2 | import { Component, OnInit } from '@angular/core'; 3 | import { Router } from '@angular/router'; 4 | import { LoginService } from '../../services/login.service'; 5 | import { environment } from '../../../environments/environment'; 6 | import { saveAs } from 'file-saver'; 7 | import { NotificationService } from '../../services/notification.service'; 8 | 9 | @Component({ 10 | selector: 'app-header', 11 | templateUrl: './header.component.html', 12 | styleUrls: ['./header.component.scss'], 13 | }) 14 | export class HeaderComponent implements OnInit { 15 | 16 | constructor(public loginService: LoginService, private http: HttpClient, private router: Router, private notification: NotificationService) { } 17 | 18 | ngOnInit() { 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/reusable/header/header.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | import { HeaderComponent } from './header.component'; 5 | import { RouterModule } from '@angular/router'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | CommonModule, 10 | FormsModule, 11 | RouterModule 12 | ], 13 | declarations: [HeaderComponent], 14 | exports: [HeaderComponent], 15 | }) 16 | export class HeaderComponentModule {} 17 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/reusable/projectbar/projectbar.component.html: -------------------------------------------------------------------------------- 1 |
2 |
YOUR PROJECTS
3 |
4 |
{{i.name}}
5 |
6 |
7 |
8 | Start New Project 9 | 10 | 11 |
12 |
13 |
14 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/reusable/projectbar/projectbar.component.scss: -------------------------------------------------------------------------------- 1 | .hover :hover{ 2 | text-decoration: underline; 3 | } -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/reusable/projectbar/projectbar.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { IonicModule } from '@ionic/angular'; 3 | 4 | import { ProjectbarComponent } from './projectbar.component'; 5 | 6 | describe('ProjectbarComponent', () => { 7 | let component: ProjectbarComponent; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [ ProjectbarComponent ], 13 | imports: [IonicModule.forRoot()] 14 | }).compileComponents(); 15 | 16 | fixture = TestBed.createComponent(ProjectbarComponent); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | })); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/reusable/projectbar/projectbar.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | import {LoginService} from '../../services/login.service' 3 | 4 | @Component({ 5 | selector: 'app-projectbar', 6 | templateUrl: './projectbar.component.html', 7 | styleUrls: ['./projectbar.component.scss'], 8 | }) 9 | export class ProjectbarComponent implements OnInit { 10 | 11 | @Input() name: string; 12 | 13 | constructor(public loginService: LoginService) { } 14 | 15 | ngOnInit() { 16 | this.loginService.updateUserData() 17 | } 18 | 19 | getWindow(){ 20 | return window; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/reusable/projectbar/projectbar.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | import { ProjectbarComponent } from './projectbar.component'; 5 | import { RouterModule } from '@angular/router'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | CommonModule, 10 | FormsModule, 11 | RouterModule 12 | ], 13 | declarations: [ProjectbarComponent], 14 | exports: [ProjectbarComponent], 15 | }) 16 | export class ProjectbarComponentModule {} 17 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/services/http.interceptor.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { LoadingService } from './loading.service'; 3 | import { 4 | HttpInterceptor, 5 | HttpRequest, 6 | HttpHandler, 7 | HttpEvent, 8 | HttpHeaders, 9 | HttpErrorResponse, 10 | HttpResponse 11 | } from '@angular/common/http'; 12 | 13 | import { EMPTY, Observable, of, throwError } from 'rxjs'; 14 | import { catchError, map } from 'rxjs/operators'; 15 | import { LoginService } from './login.service'; 16 | 17 | @Injectable() 18 | export class MyHttpLogInterceptor implements HttpInterceptor { 19 | 20 | constructor(private loginService: LoginService, private _loading: LoadingService) { } 21 | 22 | handleAuthError(err: HttpErrorResponse): Observable { 23 | 24 | // Handling unauthorized error by logging the user out and asking to login again 25 | if (err.status === 401){ 26 | localStorage.removeItem('email'); 27 | localStorage.removeItem('token'); 28 | this.loginService.logout(); 29 | return of(EMPTY); 30 | } 31 | return throwError(err); 32 | } 33 | intercept(request: HttpRequest, next: HttpHandler): Observable> { 34 | 35 | // Intercepting the HTTP request and adding the email id of the user in the header 36 | let show_loader = 'false'; 37 | if (request.params.get('loading')){ 38 | show_loader = request.params.get('loading') 39 | } 40 | 41 | const token = localStorage.getItem('token') || 'null'; 42 | const email = localStorage.getItem('email') || 'null'; 43 | if (!email) { 44 | return next.handle(request); 45 | } 46 | const headers = new HttpHeaders({ email, token }); 47 | const customReq = request.clone({ headers }); 48 | 49 | if (show_loader === 'true'){ 50 | this._loading.setLoading(true, request.url); 51 | return next.handle(customReq) 52 | .pipe(catchError((err) => { 53 | this._loading.setLoading(false, request.url); 54 | this.handleAuthError(err); 55 | return err; 56 | })) 57 | .pipe(map, any>((evt: HttpEvent) => { 58 | if (evt instanceof HttpResponse) { 59 | this._loading.setLoading(false, request.url); 60 | } 61 | return evt; 62 | })); 63 | } 64 | 65 | return next.handle(customReq).pipe(catchError(x => this.handleAuthError(x))); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/services/loading.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { LoadingService } from './loading.service'; 4 | 5 | describe('LoadingService', () => { 6 | let service: LoadingService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(LoadingService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/services/loading.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { BehaviorSubject } from 'rxjs'; 3 | 4 | @Injectable({ 5 | providedIn: 'root' 6 | }) 7 | export class LoadingService { 8 | loadingSub: BehaviorSubject = new BehaviorSubject(false); 9 | /** 10 | * Contains in-progress loading requests 11 | */ 12 | loadingMap: Map = new Map(); 13 | 14 | constructor() { } 15 | 16 | /** 17 | * Sets the loadingSub property value based on the following: 18 | * - If loading is true, add the provided url to the loadingMap with a true value, set loadingSub value to true 19 | * - If loading is false, remove the loadingMap entry and only when the map is empty will we set loadingSub to false 20 | * This pattern ensures if there are multiple requests awaiting completion, we don't set loading to false before 21 | * other requests have completed. At the moment, this function is only called from the @link{HttpRequestInterceptor} 22 | * @param loading {boolean} 23 | * @param url {string} 24 | */ 25 | setLoading(loading: boolean, url: string): void { 26 | if (!url) { 27 | throw new Error('The request URL must be provided to the LoadingService.setLoading function'); 28 | } 29 | if (loading === true) { 30 | this.loadingMap.set(url, loading); 31 | this.loadingSub.next(true); 32 | }else if (loading === false && this.loadingMap.has(url)) { 33 | this.loadingMap.delete(url); 34 | } 35 | if (this.loadingMap.size === 0) { 36 | this.loadingSub.next(false); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/services/login.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { LoginService } from './login.service'; 4 | 5 | describe('LoginService', () => { 6 | let service: LoginService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(LoginService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/services/login.service.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from '@angular/common/http'; 2 | import { Injectable, Inject } from '@angular/core'; 3 | import { Router } from '@angular/router'; 4 | import { environment } from '../../environments/environment'; 5 | import { NotificationService } from './notification.service'; 6 | import { DOCUMENT } from '@angular/common'; 7 | 8 | @Injectable({ 9 | providedIn: 'root' 10 | }) 11 | export class LoginService { 12 | 13 | email = null; 14 | name = null; 15 | 16 | // Set admin email IDs. Only admin email IDs can see the analysis! 17 | 18 | user_data = null; 19 | admin = false; 20 | localStorage; 21 | 22 | constructor(private notification: NotificationService, private router: Router, private http: HttpClient, @Inject(DOCUMENT) private document: Document) { 23 | // If user has already logged into the browser earlier, they won't need to login again 24 | this.localStorage = document.defaultView?.localStorage 25 | const email = this.localStorage.getItem('email'); 26 | if (email !== null && email !== 'null') 27 | { 28 | this.email = email; 29 | this.name = name; 30 | } 31 | } 32 | 33 | login(email, password){ 34 | // Login into the server. If the user is looging in for the first time, songs are randomly sampled and initialized in the database 35 | 36 | // Ensuring that the emails should end with @sony.com (Not necessary can be removed) 37 | 38 | // Making the email id lower case for consistency 39 | email = email.toLowerCase(); 40 | 41 | // This API call will intiialize the Database 42 | console.log('Trying to login') 43 | this.http.post(environment.SERVER_URL + 'api/login', {email, password}).subscribe((res: any) => { 44 | console.log('Got the response') 45 | if (res.status){ 46 | this.email = email; 47 | this.name = res.name; 48 | this.localStorage.setItem('email', email); 49 | this.localStorage.setItem('name', res.name); 50 | this.localStorage.setItem('token', res.token); 51 | console.log(res); 52 | this.afterLogin(); 53 | } 54 | else{ 55 | // If the login fails this notification toast is presented 56 | this.notification.presentToastError('Login Failed! Please contact the admin or provide correct password!'); 57 | } 58 | }) 59 | 60 | } 61 | 62 | updateUserData(){ 63 | this.http.get(environment.SERVER_URL + 'api/get_user_data').subscribe((res: any) => { 64 | if (res.status){ 65 | this.user_data = res.user_data; 66 | } 67 | else{ 68 | this.notification.presentToastError('Error when getting tasks!'); 69 | this.logout(); 70 | } 71 | }); 72 | } 73 | 74 | afterLogin(){ 75 | 76 | // This function is used to get the current status of the tasks. 77 | 78 | this.http.get(environment.SERVER_URL + 'api/get_user_data').subscribe((res: any) => { 79 | if (res.status){ 80 | this.user_data = res.user_data; 81 | this.router.navigateByUrl('/main'); 82 | } 83 | else{ 84 | this.notification.presentToastError('Error when getting tasks!'); 85 | this.logout(); 86 | } 87 | }); 88 | } 89 | logout(){ 90 | 91 | // Function to logout the user and redirect to login page 92 | 93 | this.email = null; 94 | this.name = null; 95 | this.localStorage.removeItem('email'); 96 | this.localStorage.removeItem('token'); 97 | this.router.navigate(['/login']) 98 | } 99 | 100 | isLoggedIn() { 101 | const email = this.localStorage.getItem('email'); 102 | const token = this.localStorage.getItem('token'); 103 | return email !== 'null' && email !== null && token !== 'null' && token !== null; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/app/services/notification.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | // import { ToastController } from '@ionic/angular'; 3 | import { ToastrService } from 'ngx-toastr'; 4 | 5 | @Injectable({ 6 | providedIn: 'root' 7 | }) 8 | export class NotificationService { 9 | // constructor(public toastController: ToastController) { 10 | // } 11 | constructor(private toastr: ToastrService) {} 12 | unlimitedToast = null; 13 | presenting = false; 14 | // ToDo change the CSS class of the notification bar 15 | dangerCSS = 'bg-danger'; 16 | 17 | async presentToastSuccess(text: string) { 18 | this.toastr.success(text, '', { 19 | timeOut: 3000, 20 | }); 21 | } 22 | 23 | async presentToastError(text: string) { 24 | this.toastr.error(text, '', { 25 | timeOut: 3000, 26 | }); 27 | } 28 | async presentUnlimitedToast(text: string) { 29 | // const position = 'top'; 30 | // this.unlimitedToast = await this.toastController.create({ 31 | // position, 32 | // message: text, 33 | // duration: 2000000 34 | // }); 35 | // this.unlimitedToast.present(); 36 | this.presenting = true; 37 | 38 | this.toastr.error(text, text, { 39 | timeOut: 3000000000, 40 | }); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/assets/images/Logo-inv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/silentcipherui/src/assets/images/Logo-inv.png -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/assets/images/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/silentcipherui/src/assets/images/Logo.png -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/assets/images/correct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/silentcipherui/src/assets/images/correct.png -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/assets/images/loading_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/silentcipherui/src/assets/images/loading_1.gif -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/assets/images/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/silentcipherui/src/assets/images/upload.png -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/assets/images/wrong.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/WaterMarkingWebsite/silentcipherui/src/assets/images/wrong.png -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/assets/shapes.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | 2 | export const environment = { 3 | production: true, 4 | SERVER_URL: 'http://43.88.62.147/WaterMarkingWebsite/', 5 | phase_shift_decoding: true 6 | }; 7 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | 2 | export const environment = { 3 | production: false, 4 | SERVER_URL: 'http://43.4.23.101:8000/WaterMarkingWebsite/', 5 | phase_shift_decoding: true 6 | }; 7 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WaterMarkingWebsite 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | 3 | import { AppModule } from './app/app.module'; 4 | 5 | platformBrowserDynamic().bootstrapModule(AppModule, { 6 | ngZoneEventCoalescing: true 7 | }) 8 | .catch(err => console.error(err)); 9 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | .clickable { 3 | cursor: pointer; 4 | } 5 | .heading { 6 | font-size: 28px 7 | } 8 | .heading-2 { 9 | font-size: 24px 10 | } 11 | .heading-3 { 12 | font-size: 20px 13 | } 14 | .heading-3 { 15 | font-size: 16px 16 | } 17 | .subheading { 18 | font-size: 14px 19 | } 20 | .subheading-2 { 21 | font-size: 16px 22 | } 23 | .circle-5 { 24 | width: 40px; 25 | height: 40px; 26 | line-height: 40px; 27 | border-radius: 50%; 28 | font-size: 20px; 29 | color: #fff; 30 | text-align: center; 31 | background: #0f0; 32 | margin-left: auto; 33 | margin-right: auto; 34 | box-shadow: 0 0 0 2px #eeeeee; 35 | } 36 | .circle-4 { 37 | width: 40px; 38 | height: 40px; 39 | line-height: 40px; 40 | border-radius: 50%; 41 | font-size: 20px; 42 | color: #fff; 43 | text-align: center; 44 | background: #4b0; 45 | margin-left: auto; 46 | margin-right: auto; 47 | box-shadow: 0 0 0 2px #eeeeee; 48 | } 49 | .circle-3 { 50 | width: 40px; 51 | height: 40px; 52 | line-height: 40px; 53 | border-radius: 50%; 54 | font-size: 20px; 55 | color: #fff; 56 | text-align: center; 57 | background: #870; 58 | margin-left: auto; 59 | margin-right: auto; 60 | box-shadow: 0 0 0 2px #eeeeee; 61 | } 62 | .circle-2 { 63 | width: 40px; 64 | height: 40px; 65 | line-height: 40px; 66 | border-radius: 50%; 67 | font-size: 20px; 68 | color: #fff; 69 | text-align: center; 70 | background: #c30; 71 | margin-left: auto; 72 | margin-right: auto; 73 | box-shadow: 0 0 0 2px #eeeeee; 74 | } 75 | .circle-1 { 76 | width: 40px; 77 | height: 40px; 78 | line-height: 40px; 79 | border-radius: 50%; 80 | font-size: 20px; 81 | color: #fff; 82 | text-align: center; 83 | background: #f00; 84 | margin-left: auto; 85 | margin-right: auto; 86 | box-shadow: 0 0 0 2px #eeeeee; 87 | } 88 | .disable-arrow{ 89 | color: #ddd; 90 | cursor: auto; 91 | } 92 | .selected-option{ 93 | background-color: #000000; 94 | } 95 | .checked { 96 | color: orange; 97 | } 98 | .fa-star{ 99 | font-size: 30px; 100 | } 101 | td { 102 | max-width:200px; 103 | word-wrap:break-word; 104 | } 105 | th { 106 | max-width:200px; 107 | word-wrap:break-word; 108 | } 109 | * { 110 | font-family: 'Noto Serif', serif; 111 | } 112 | .btn-primary{ 113 | border-radius: 5px; 114 | } 115 | body { 116 | margin: 0; 117 | } 118 | 119 | 120 | 121 | /* based on angular-toastr css https://github.com/Foxandxss/angular-toastr/blob/cb508fe6801d6b288d3afc525bb40fee1b101650/dist/angular-toastr.css */ 122 | 123 | /* position */ 124 | .toast-center-center { 125 | top: 50%; 126 | left: 50%; 127 | transform: translate(-50%, -50%); 128 | } 129 | .toast-top-center { 130 | top: 0; 131 | right: 0; 132 | width: 100%; 133 | } 134 | .toast-bottom-center { 135 | bottom: 0; 136 | right: 0; 137 | width: 100%; 138 | } 139 | .toast-top-full-width { 140 | top: 0; 141 | right: 0; 142 | width: 100%; 143 | } 144 | .toast-bottom-full-width { 145 | bottom: 0; 146 | right: 0; 147 | width: 100%; 148 | } 149 | .toast-top-left { 150 | top: 12px; 151 | left: 12px; 152 | } 153 | .toast-top-right { 154 | top: 12px; 155 | right: 12px; 156 | } 157 | .toast-bottom-right { 158 | right: 12px; 159 | bottom: 12px; 160 | } 161 | .toast-bottom-left { 162 | bottom: 12px; 163 | left: 12px; 164 | } 165 | 166 | /* toast styles */ 167 | .toast-title { 168 | font-weight: bold; 169 | } 170 | .toast-message { 171 | word-wrap: break-word; 172 | } 173 | .toast-message a, 174 | .toast-message label { 175 | color: #FFFFFF; 176 | } 177 | .toast-message a:hover { 178 | color: #CCCCCC; 179 | text-decoration: none; 180 | } 181 | .toast-close-button { 182 | position: relative; 183 | right: -0.3em; 184 | top: -0.3em; 185 | float: right; 186 | font-size: 20px; 187 | font-weight: bold; 188 | color: #FFFFFF; 189 | text-shadow: 0 1px 0 #ffffff; 190 | /* opacity: 0.8; */ 191 | } 192 | .toast-close-button:hover, 193 | .toast-close-button:focus { 194 | color: #000000; 195 | text-decoration: none; 196 | cursor: pointer; 197 | opacity: 0.4; 198 | } 199 | /*Additional properties for button version 200 | iOS requires the button element instead of an anchor tag. 201 | If you want the anchor version, it requires `href="#"`.*/ 202 | button.toast-close-button { 203 | padding: 0; 204 | cursor: pointer; 205 | background: transparent; 206 | border: 0; 207 | } 208 | .toast-container { 209 | pointer-events: none; 210 | position: fixed; 211 | z-index: 999999; 212 | } 213 | .toast-container * { 214 | box-sizing: border-box; 215 | } 216 | .toast-container .ngx-toastr { 217 | position: relative; 218 | overflow: hidden; 219 | margin: 0 0 6px; 220 | padding: 15px 15px 15px 50px; 221 | width: 300px; 222 | border-radius: 3px 3px 3px 3px; 223 | background-position: 15px center; 224 | background-repeat: no-repeat; 225 | background-size: 24px; 226 | box-shadow: 0 0 12px #999999; 227 | color: #FFFFFF; 228 | } 229 | .toast-container .ngx-toastr:hover { 230 | box-shadow: 0 0 12px #000000; 231 | opacity: 1; 232 | cursor: pointer; 233 | } 234 | /* https://github.com/FortAwesome/Font-Awesome-Pro/blob/master/advanced-options/raw-svg/regular/info-circle.svg */ 235 | .toast-info { 236 | background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCA1MTIgNTEyJyB3aWR0aD0nNTEyJyBoZWlnaHQ9JzUxMic+PHBhdGggZmlsbD0ncmdiKDI1NSwyNTUsMjU1KScgZD0nTTI1NiA4QzExOS4wNDMgOCA4IDExOS4wODMgOCAyNTZjMCAxMzYuOTk3IDExMS4wNDMgMjQ4IDI0OCAyNDhzMjQ4LTExMS4wMDMgMjQ4LTI0OEM1MDQgMTE5LjA4MyAzOTIuOTU3IDggMjU2IDh6bTAgMTEwYzIzLjE5NiAwIDQyIDE4LjgwNCA0MiA0MnMtMTguODA0IDQyLTQyIDQyLTQyLTE4LjgwNC00Mi00MiAxOC44MDQtNDIgNDItNDJ6bTU2IDI1NGMwIDYuNjI3LTUuMzczIDEyLTEyIDEyaC04OGMtNi42MjcgMC0xMi01LjM3My0xMi0xMnYtMjRjMC02LjYyNyA1LjM3My0xMiAxMi0xMmgxMnYtNjRoLTEyYy02LjYyNyAwLTEyLTUuMzczLTEyLTEydi0yNGMwLTYuNjI3IDUuMzczLTEyIDEyLTEyaDY0YzYuNjI3IDAgMTIgNS4zNzMgMTIgMTJ2MTAwaDEyYzYuNjI3IDAgMTIgNS4zNzMgMTIgMTJ2MjR6Jy8+PC9zdmc+"); 237 | } 238 | /* https://github.com/FortAwesome/Font-Awesome-Pro/blob/master/advanced-options/raw-svg/regular/times-circle.svg */ 239 | .toast-error { 240 | background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCA1MTIgNTEyJyB3aWR0aD0nNTEyJyBoZWlnaHQ9JzUxMic+PHBhdGggZmlsbD0ncmdiKDI1NSwyNTUsMjU1KScgZD0nTTI1NiA4QzExOSA4IDggMTE5IDggMjU2czExMSAyNDggMjQ4IDI0OCAyNDgtMTExIDI0OC0yNDhTMzkzIDggMjU2IDh6bTEyMS42IDMxMy4xYzQuNyA0LjcgNC43IDEyLjMgMCAxN0wzMzggMzc3LjZjLTQuNyA0LjctMTIuMyA0LjctMTcgMEwyNTYgMzEybC02NS4xIDY1LjZjLTQuNyA0LjctMTIuMyA0LjctMTcgMEwxMzQuNCAzMzhjLTQuNy00LjctNC43LTEyLjMgMC0xN2w2NS42LTY1LTY1LjYtNjUuMWMtNC43LTQuNy00LjctMTIuMyAwLTE3bDM5LjYtMzkuNmM0LjctNC43IDEyLjMtNC43IDE3IDBsNjUgNjUuNyA2NS4xLTY1LjZjNC43LTQuNyAxMi4zLTQuNyAxNyAwbDM5LjYgMzkuNmM0LjcgNC43IDQuNyAxMi4zIDAgMTdMMzEyIDI1Nmw2NS42IDY1LjF6Jy8+PC9zdmc+"); 241 | } 242 | /* https://github.com/FortAwesome/Font-Awesome-Pro/blob/master/advanced-options/raw-svg/regular/check.svg */ 243 | .toast-success { 244 | background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCA1MTIgNTEyJyB3aWR0aD0nNTEyJyBoZWlnaHQ9JzUxMic+PHBhdGggZmlsbD0ncmdiKDI1NSwyNTUsMjU1KScgZD0nTTE3My44OTggNDM5LjQwNGwtMTY2LjQtMTY2LjRjLTkuOTk3LTkuOTk3LTkuOTk3LTI2LjIwNiAwLTM2LjIwNGwzNi4yMDMtMzYuMjA0YzkuOTk3LTkuOTk4IDI2LjIwNy05Ljk5OCAzNi4yMDQgMEwxOTIgMzEyLjY5IDQzMi4wOTUgNzIuNTk2YzkuOTk3LTkuOTk3IDI2LjIwNy05Ljk5NyAzNi4yMDQgMGwzNi4yMDMgMzYuMjA0YzkuOTk3IDkuOTk3IDkuOTk3IDI2LjIwNiAwIDM2LjIwNGwtMjk0LjQgMjk0LjQwMWMtOS45OTggOS45OTctMjYuMjA3IDkuOTk3LTM2LjIwNC0uMDAxeicvPjwvc3ZnPg=="); 245 | } 246 | /* https://github.com/FortAwesome/Font-Awesome-Pro/blob/master/advanced-options/raw-svg/regular/exclamation-triangle.svg */ 247 | .toast-warning { 248 | background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCA1NzYgNTEyJyB3aWR0aD0nNTc2JyBoZWlnaHQ9JzUxMic+PHBhdGggZmlsbD0ncmdiKDI1NSwyNTUsMjU1KScgZD0nTTU2OS41MTcgNDQwLjAxM0M1ODcuOTc1IDQ3Mi4wMDcgNTY0LjgwNiA1MTIgNTI3Ljk0IDUxMkg0OC4wNTRjLTM2LjkzNyAwLTU5Ljk5OS00MC4wNTUtNDEuNTc3LTcxLjk4N0wyNDYuNDIzIDIzLjk4NWMxOC40NjctMzIuMDA5IDY0LjcyLTMxLjk1MSA4My4xNTQgMGwyMzkuOTQgNDE2LjAyOHpNMjg4IDM1NGMtMjUuNDA1IDAtNDYgMjAuNTk1LTQ2IDQ2czIwLjU5NSA0NiA0NiA0NiA0Ni0yMC41OTUgNDYtNDYtMjAuNTk1LTQ2LTQ2LTQ2em0tNDMuNjczLTE2NS4zNDZsNy40MTggMTM2Yy4zNDcgNi4zNjQgNS42MDkgMTEuMzQ2IDExLjk4MiAxMS4zNDZoNDguNTQ2YzYuMzczIDAgMTEuNjM1LTQuOTgyIDExLjk4Mi0xMS4zNDZsNy40MTgtMTM2Yy4zNzUtNi44NzQtNS4wOTgtMTIuNjU0LTExLjk4Mi0xMi42NTRoLTYzLjM4M2MtNi44ODQgMC0xMi4zNTYgNS43OC0xMS45ODEgMTIuNjU0eicvPjwvc3ZnPg=="); 249 | } 250 | .toast-container.toast-top-center .ngx-toastr, 251 | .toast-container.toast-bottom-center .ngx-toastr { 252 | width: 300px; 253 | margin-left: auto; 254 | margin-right: auto; 255 | } 256 | .toast-container.toast-top-full-width .ngx-toastr, 257 | .toast-container.toast-bottom-full-width .ngx-toastr { 258 | width: 96%; 259 | margin-left: auto; 260 | margin-right: auto; 261 | } 262 | .ngx-toastr { 263 | background-color: #030303; 264 | pointer-events: auto; 265 | } 266 | .toast-success { 267 | background-color: #51A351; 268 | } 269 | .toast-error { 270 | background-color: #BD362F; 271 | } 272 | .toast-info { 273 | background-color: #2F96B4; 274 | } 275 | .toast-warning { 276 | background-color: #F89406; 277 | } 278 | .toast-progress { 279 | position: absolute; 280 | left: 0; 281 | bottom: 0; 282 | height: 4px; 283 | background-color: #000000; 284 | opacity: 0.4; 285 | } 286 | /* Responsive Design */ 287 | @media all and (max-width: 240px) { 288 | .toast-container .ngx-toastr.div { 289 | padding: 8px 8px 8px 50px; 290 | width: 11em; 291 | } 292 | .toast-container .toast-close-button { 293 | right: -0.2em; 294 | top: -0.2em; 295 | } 296 | } 297 | @media all and (min-width: 241px) and (max-width: 480px) { 298 | .toast-container .ngx-toastr.div { 299 | padding: 8px 8px 8px 50px; 300 | width: 18em; 301 | } 302 | .toast-container .toast-close-button { 303 | right: -0.2em; 304 | top: -0.2em; 305 | } 306 | } 307 | @media all and (min-width: 481px) and (max-width: 768px) { 308 | .toast-container .ngx-toastr.div { 309 | padding: 15px 15px 15px 50px; 310 | width: 25em; 311 | } 312 | } -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "allowSyntheticDefaultImports": true, 6 | "outDir": "./dist/out-tsc", 7 | "strict": false, 8 | "noImplicitOverride": true, 9 | "noPropertyAccessFromIndexSignature": true, 10 | "noImplicitReturns": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "skipLibCheck": true, 13 | "esModuleInterop": true, 14 | "sourceMap": true, 15 | "declaration": false, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "bundler", 18 | "importHelpers": true, 19 | "target": "ES2022", 20 | "module": "ES2022", 21 | "useDefineForClassFields": false, 22 | "lib": [ 23 | "ES2022", 24 | "dom" 25 | ] 26 | }, 27 | "angularCompilerOptions": { 28 | "enableI18nLegacyMessageIdFormat": false, 29 | "strictInjectionParameters": false, 30 | "strictInputAccessModifiers": false, 31 | "strictTemplates": false 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/WaterMarkingWebsite/silentcipherui/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "include": [ 11 | "src/**/*.spec.ts", 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /examples/colab/cli.py: -------------------------------------------------------------------------------- 1 | import silentcipher 2 | import librosa 3 | import json 4 | import argparse 5 | 6 | 7 | def encode(model, filename, encoded_filename, msg=None, message_sdr=None, calc_sdr=True, disable_checks=False): 8 | try: 9 | return model.encode(filename, encoded_filename, msg, message_sdr=message_sdr, calc_sdr=calc_sdr, disable_checks=disable_checks) 10 | except: 11 | return {'status': False} 12 | 13 | def decode(model, encoded_filename, phase_shift_decoding=True): 14 | try: 15 | result = model.decode(encoded_filename, phase_shift_decoding) 16 | except: 17 | result = {'status': False} 18 | return result 19 | 20 | 21 | if __name__ == "__main__": 22 | 23 | parser = argparse.ArgumentParser( 24 | prog='ProgramName', 25 | description='What the program does', 26 | epilog='Text at the bottom of help') 27 | 28 | parser.add_argument('--filename', type=str, help='Input audio file', required=True) 29 | parser.add_argument('--results_json_path', type=str, help='Store the results of the run', required=True) 30 | parser.add_argument('--mode', type=str, help='Mode of operation', choices=['encode', 'decode'], required=True) 31 | parser.add_argument('--model_type', type=str, help='44.1khz or 16khz', choices=['44.1k', '16k'], required=True) 32 | parser.add_argument('--use_gpu', type=bool, help='Whether to use cuda or not', default=True) 33 | 34 | # Encode parameters 35 | parser.add_argument('--msg', type=str, help='Message to encode in the form of five 8-bit comma separated digits, eg. 111,222,123,234,12', default=None) 36 | parser.add_argument('--encoded_filename', type=str, help='Path to save the encoded audio file', default=None) 37 | parser.add_argument('--message_sdr', type=str, help='Message SDR to encode | default is None which will use the default value of SDR of the model', default=None) 38 | 39 | # Decode parameters 40 | parser.add_argument('--phase_shift_decoding', type=bool, help='Whether to detect messages even in the case when the audio may be cropped. WARNING! INCREASES THE DETECTION TIME CONSIDERABLY', default=True) 41 | args = parser.parse_args() 42 | 43 | if args.model_type == '44.1k': 44 | model = silentcipher.get_model(model_type='44.1k', device='cuda' if args.use_gpu else 'cpu') 45 | elif args.model_type == '16k': 46 | model = silentcipher.get_model(model_type='16k', device='cuda' if args.use_gpu else 'cpu') 47 | else: 48 | raise ValueError('Invalid model type') 49 | 50 | if args.mode == 'encode': 51 | assert args.filename is not None, 'Path to original file is required for encoding' 52 | assert args.encoded_filename is not None, 'Path to save the encoded file is required' 53 | assert args.msg is not None, 'Message to encode is required' 54 | 55 | msg = [int(i) for i in args.msg.split(',')] 56 | 57 | with open(args.results_json_path, 'w') as f: 58 | result = encode(model, args.filename, args.encoded_filename, msg, args.message_sdr) 59 | json.dump(result, f, indent=4) 60 | elif args.mode == 'decode': 61 | assert args.filename is not None, 'Path to encoded file is required for decoding' 62 | with open(args.results_json_path, 'w') as f: 63 | result = decode(model, args.filename, args.phase_shift_decoding) 64 | json.dump(result, f, indent=4) 65 | 66 | # Encoding Example: 67 | 68 | # python cli.py --filename test.wav --mode encode --model_type 44.1k --use_gpu true --msg 12,13,14,15,16 --encoded_filename enc_cli.wav --results_json_path out.json 69 | 70 | # Decoding Example: 71 | 72 | # python cli.py --filename enc_cli.wav --mode decode --model_type 44.1k --use_gpu true --results_json_path decode_out.json 73 | -------------------------------------------------------------------------------- /examples/colab/demo.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%pip install silentcipher --force-reinstall --no-deps\n", 10 | "%pip install pydub" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": null, 16 | "metadata": {}, 17 | "outputs": [], 18 | "source": [ 19 | "import silentcipher\n", 20 | "import librosa" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": null, 26 | "metadata": {}, 27 | "outputs": [], 28 | "source": [ 29 | "device='cuda'\n", 30 | "\n", 31 | "# You will need to upload the models on colab https://github.com/sony/silentcipher/releases/tag/release\n", 32 | "\n", 33 | "model = silentcipher.get_model(\n", 34 | " model_type='44.1k',\n", 35 | " device=device\n", 36 | ")\n", 37 | "\n", 38 | "\"\"\"\n", 39 | "For 16khz model\n", 40 | "\n", 41 | "model = silentcipher.get_model(\n", 42 | " model_type='16k',\n", 43 | " device=device\n", 44 | ")\n", 45 | "\"\"\"" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": null, 51 | "metadata": {}, 52 | "outputs": [], 53 | "source": [ 54 | "def test(y, sr, filename, encoded_filename):\n", 55 | " \n", 56 | " # The message should be in the form of five 8-bit characters, giving a total message capacity of 40 bits\n", 57 | "\n", 58 | " # Single Channel encoding example\n", 59 | " # If you want to really speedup the watermarking process then set disable_checks=True, but beware as this may cause unexpected results\n", 60 | " # Set calc_sdr=False to not calculate the SDR of the encoded audio\n", 61 | " encoded, sdr = model.encode_wav(y, sr, [123, 234, 111, 222, 11], message_sdr=None, calc_sdr=True, disable_checks=False)\n", 62 | "\n", 63 | " # You can specify the message SDR (in dB) as a float along with the encode_wav function. But this may result in unexpected detection accuracy\n", 64 | " # encoded, sdr = model.encode_wav(y, sr, [123, 234, 111, 222, 11], message_sdr=47)\n", 65 | "\n", 66 | " # For multi-channel audio, you can use the following function\n", 67 | " # Here y is a 2 channel audio with shape [num_frames, num_channels] and you can specify the message for each channel\n", 68 | " # encoded, sdr = model.encode_wav(y, sr, [[123, 234, 111, 222, 11], [132, 214, 121, 122, 211]])\n", 69 | "\n", 70 | " # Single Channel decoding example\n", 71 | " result = model.decode_wav(encoded, sr, phase_shift_decoding=False)\n", 72 | "\n", 73 | " if type(result) is list:\n", 74 | " for result_i in result:\n", 75 | " assert result_i['status']\n", 76 | " assert result_i['messages'][0] == [123, 234, 111, 222, 11], result_i['messages'][0]\n", 77 | " assert result_i['confidences'][0] == 0.9746031761169434, result_i['confidences'][0]\n", 78 | " else:\n", 79 | " assert result['status']\n", 80 | " assert result['messages'][0] == [123, 234, 111, 222, 11], result['messages'][0]\n", 81 | " assert result['confidences'][0] == 0.9746031761169434, result['confidences'][0]\n", 82 | "\n", 83 | " # When decoding multi-channel audio, The result would be a list of dictionaries with the status, message and confidence for each channel\n", 84 | "\n", 85 | " # Encode from filename\n", 86 | "\n", 87 | " model.encode(filename, encoded_filename, [123, 234, 111, 222, 11], message_sdr=None, calc_sdr=True, disable_checks=False)\n", 88 | " result = model.decode(encoded_filename, phase_shift_decoding=False)\n", 89 | "\n", 90 | " if type(result) is list:\n", 91 | " for result_i in result:\n", 92 | " assert result_i['status']\n", 93 | " assert result_i['messages'][0] == [123, 234, 111, 222, 11], result_i['messages'][0]\n", 94 | " assert result_i['confidences'][0] == 0.9746031761169434, result_i['confidences'][0]\n", 95 | " else:\n", 96 | " assert result['status']\n", 97 | " assert result['messages'][0] == [123, 234, 111, 222, 11], result['messages'][0]\n", 98 | " assert result['confidences'][0] == 0.9746031761169434, result['confidences'][0]\n", 99 | "\n", 100 | " # When decoding multi-channel audio, The result would be a list of dictionaries with the status, message and confidence for each channel" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": null, 106 | "metadata": {}, 107 | "outputs": [], 108 | "source": [ 109 | "# You will need to upload the test.wav and test_multichannel.wav from the examples/colab directory\n", 110 | "\n", 111 | "y, sr = librosa.load('test.wav', sr=None)\n", 112 | "test(y, sr, 'test.wav', 'encoded_test.wav')\n", 113 | "y, sr = librosa.load('test_multichannel.wav', sr=None)\n", 114 | "test(y, sr, 'test_multichannel.wav', 'encoded_test_multichannel.wav')\n", 115 | "\n", 116 | "print('Test Successful')" 117 | ] 118 | } 119 | ], 120 | "metadata": { 121 | "kernelspec": { 122 | "display_name": "Python 3 (ipykernel)", 123 | "language": "python", 124 | "name": "python3" 125 | }, 126 | "language_info": { 127 | "codemirror_mode": { 128 | "name": "ipython", 129 | "version": 3 130 | }, 131 | "file_extension": ".py", 132 | "mimetype": "text/x-python", 133 | "name": "python", 134 | "nbconvert_exporter": "python", 135 | "pygments_lexer": "ipython3", 136 | "version": "3.11.7" 137 | } 138 | }, 139 | "nbformat": 4, 140 | "nbformat_minor": 4 141 | } 142 | -------------------------------------------------------------------------------- /examples/colab/demo.py: -------------------------------------------------------------------------------- 1 | import silentcipher 2 | import librosa 3 | 4 | device='cuda' 5 | 6 | model = silentcipher.get_model( 7 | model_type='44.1k', 8 | device=device 9 | ) 10 | # ckpt_path='../../Models/44_1_khz/73999_iteration', 11 | # config_path='../../Models/44_1_khz/73999_iteration/hparams.yaml', 12 | 13 | """ 14 | For 16khz model 15 | 16 | model = silentcipher.get_model( 17 | model_type='16k', 18 | device=device 19 | ) 20 | # ckpt_path='../Models/16_khz/97561_iteration', 21 | # config_path='../Models/16_khz/97561_iteration/hparams.yaml', 22 | """ 23 | 24 | def test(y, sr, filename, encoded_filename): 25 | 26 | # The message should be in the form of five 8-bit characters, giving a total message capacity of 40 bits 27 | 28 | # Single Channel encoding example 29 | # If you want to really speedup the watermarking process then set disable_checks=True, but beware as this may cause unexpected results 30 | # Set calc_sdr=False to not calculate the SDR of the encoded audio 31 | encoded, sdr = model.encode_wav(y, sr, [123, 234, 111, 222, 11], message_sdr=None, calc_sdr=True, disable_checks=False) 32 | 33 | # You can specify the message SDR (in dB) as a float along with the encode_wav function. But this may result in unexpected detection accuracy 34 | # encoded, sdr = model.encode_wav(y, sr, [123, 234, 111, 222, 11], message_sdr=47) 35 | 36 | # For multi-channel audio, you can use the following function 37 | # Here y is a 2 channel audio with shape [num_frames, num_channels] and you can specify the message for each channel 38 | # encoded, sdr = model.encode_wav(y, sr, [[123, 234, 111, 222, 11], [132, 214, 121, 122, 211]]) 39 | 40 | # Single Channel decoding example 41 | result = model.decode_wav(encoded, sr, phase_shift_decoding=False) 42 | 43 | if type(result) is list: 44 | for result_i in result: 45 | assert result_i['status'] 46 | assert result_i['messages'][0] == [123, 234, 111, 222, 11], result_i['messages'][0] 47 | assert result_i['confidences'][0] == 0.9746031761169434, result_i['confidences'][0] 48 | else: 49 | assert result['status'] 50 | assert result['messages'][0] == [123, 234, 111, 222, 11], result['messages'][0] 51 | assert result['confidences'][0] == 0.9746031761169434, result['confidences'][0] 52 | 53 | # When decoding multi-channel audio, The result would be a list of dictionaries with the status, message and confidence for each channel 54 | 55 | # Encode from filename 56 | 57 | model.encode(filename, encoded_filename, [123, 234, 111, 222, 11], message_sdr=None, calc_sdr=True, disable_checks=False) 58 | result = model.decode(encoded_filename, phase_shift_decoding=False) 59 | 60 | if type(result) is list: 61 | for result_i in result: 62 | assert result_i['status'] 63 | assert result_i['messages'][0] == [123, 234, 111, 222, 11], result_i['messages'][0] 64 | assert result_i['confidences'][0] == 0.9746031761169434, result_i['confidences'][0] 65 | else: 66 | assert result['status'] 67 | assert result['messages'][0] == [123, 234, 111, 222, 11], result['messages'][0] 68 | assert result['confidences'][0] == 0.9746031761169434, result['confidences'][0] 69 | 70 | # When decoding multi-channel audio, The result would be a list of dictionaries with the status, message and confidence for each channel 71 | 72 | 73 | y, sr = librosa.load('test.wav', sr=None) 74 | test(y, sr, 'test.wav', 'encoded_test.wav') 75 | y, sr = librosa.load('test_multichannel.wav', sr=None) 76 | test(y, sr, 'test_multichannel.wav', 'encoded_test_multichannel.wav') 77 | 78 | print('Test Successful') -------------------------------------------------------------------------------- /examples/colab/encoded.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/colab/encoded.wav -------------------------------------------------------------------------------- /examples/colab/encoded_test.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/colab/encoded_test.wav -------------------------------------------------------------------------------- /examples/colab/encoded_test_multichannel.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/colab/encoded_test_multichannel.wav -------------------------------------------------------------------------------- /examples/colab/test.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/colab/test.wav -------------------------------------------------------------------------------- /examples/colab/test_multichannel.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SesameAILabs/silentcipher/d46d7d0893a583d8968ab3a6626e2289faec9152/examples/colab/test_multichannel.wav -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "silentcipher" 3 | version = "1.0.5" 4 | authors = [ 5 | { name="Mayank Kumar Singh", email="mayank.a.singh@sony.com" }, 6 | ] 7 | description = "Artefact free robust high quality audio watermarking" 8 | readme = "README_PYPI.md" 9 | requires-python = ">=3.8" 10 | classifiers = [ 11 | "Programming Language :: Python :: 3", 12 | "License :: OSI Approved :: MIT License", 13 | "Operating System :: OS Independent", 14 | ] 15 | dynamic = ["dependencies"] 16 | 17 | [project.urls] 18 | Homepage = "https://github.com/sony/silentcipher" 19 | Issues = "https://github.com/sony/silentcipher/issues" 20 | 21 | [tool.setuptools.dynamic] 22 | dependencies = {file = ["requirements.txt"]} -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | torch>=2.4.0 2 | torchaudio>=2.4.0 3 | librosa>=0.10.0 4 | numpy>=1.25.2 5 | SoundFile>=0.12.1 6 | scipy>=1.11.4 7 | pyaml>=24.4.0 8 | Flask>=2.2.5 9 | pydub>=0.25.1 10 | huggingface-hub>=0.23.4 11 | -------------------------------------------------------------------------------- /src/silentcipher/__init__.py: -------------------------------------------------------------------------------- 1 | from .server import get_model 2 | 3 | __version__ = '1.0.4' -------------------------------------------------------------------------------- /src/silentcipher/model.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import numpy as np 4 | 5 | 6 | class Layer(nn.Module): 7 | def __init__(self, dim_in, dim_out, kernel_size, stride, padding): 8 | super(Layer, self).__init__() 9 | self.conv = nn.Conv2d(dim_in, dim_out, kernel_size=kernel_size, stride=stride, padding=padding, bias=True) 10 | self.gate = nn.Conv2d(dim_in, dim_out, kernel_size=kernel_size, stride=stride, padding=padding, bias=True) 11 | self.bn = nn.BatchNorm2d(dim_out) 12 | 13 | def forward(self, x): 14 | return self.bn(self.conv(x) * torch.sigmoid(self.gate(x))) 15 | 16 | class Encoder(nn.Module): 17 | def __init__(self, out_dim=32, n_layers=3, message_dim=0, message_band_size=None, n_fft=None): 18 | super(Encoder, self).__init__() 19 | assert message_band_size is not None 20 | assert n_fft is not None 21 | self.message_band_size = message_band_size 22 | main = [Layer(dim_in=1, dim_out=32, kernel_size=3, stride=1, padding=1)] 23 | 24 | for i in range(n_layers-2): 25 | main.append(Layer(dim_in=32, dim_out=32, kernel_size=3, stride=1, padding=1)) 26 | main.append(Layer(dim_in=32, dim_out=out_dim, kernel_size=3, stride=1, padding=1)) 27 | 28 | self.main = nn.Sequential(*main) 29 | self.linear = nn.Linear(message_dim, message_band_size) 30 | self.n_fft = n_fft 31 | 32 | def forward(self, x): 33 | h = self.main(x) 34 | return h 35 | 36 | def transform_message(self, msg): 37 | output = self.linear(msg.transpose(2, 3)).transpose(2, 3) 38 | if self.message_band_size != self.n_fft // 2 + 1: 39 | output = torch.nn.functional.pad(output, (0, 0, 0, self.n_fft // 2 + 1 - self.message_band_size)) 40 | return output 41 | 42 | class CarrierDecoder(nn.Module): 43 | def __init__(self, config, conv_dim, n_layers=4, message_band_size=1024): 44 | super(CarrierDecoder, self).__init__() 45 | self.config = config 46 | self.message_band_size = message_band_size 47 | layers = [Layer(dim_in=conv_dim, dim_out=96, kernel_size=3, stride=1, padding=1)] 48 | 49 | for i in range(n_layers-2): 50 | layers.append(Layer(dim_in=96, dim_out=96, kernel_size=3, stride=1, padding=1)) 51 | 52 | layers.append(Layer(dim_in=96, dim_out=1, kernel_size=1, stride=1, padding=0)) 53 | 54 | self.main = nn.Sequential(*layers) 55 | 56 | def forward(self, x, message_sdr): 57 | h = self.main(x) 58 | 59 | if self.config.ensure_negative_message: 60 | h = torch.abs(h) 61 | 62 | h[:, :, self.message_band_size:, :] = 0 63 | 64 | if not self.config.no_normalization: 65 | h = h / torch.mean(h**2, dim=2, keepdim=True)**0.5 / (10**(message_sdr/20)) 66 | 67 | return h 68 | 69 | class MsgDecoder(nn.Module): 70 | def __init__(self, message_dim=0, message_band_size=None, channel_dim=128, num_layers=10): 71 | super(MsgDecoder, self).__init__() 72 | assert message_band_size is not None 73 | self.message_band_size = message_band_size 74 | 75 | main = [ 76 | nn.Dropout(0), 77 | Layer(dim_in=1, dim_out=channel_dim, kernel_size=3, stride=1, padding=1) 78 | ] 79 | for l in range(num_layers - 2): 80 | main += [ 81 | nn.Dropout(0), 82 | Layer(dim_in=channel_dim, dim_out=channel_dim, kernel_size=3, stride=1, padding=1), 83 | ] 84 | main += [ 85 | nn.Dropout(0), 86 | Layer(dim_in=channel_dim, dim_out=message_dim, kernel_size=3, stride=1, padding=1) 87 | ] 88 | self.main = nn.Sequential(*main) 89 | self.linear = nn.Linear(self.message_band_size, 1) 90 | 91 | def forward(self, x): 92 | 93 | h = self.main(x[:, :, :self.message_band_size]) 94 | h = self.linear(h.transpose(2, 3)).squeeze(3).unsqueeze(1) 95 | return h 96 | -------------------------------------------------------------------------------- /src/silentcipher/stft.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | class Singleton(type): 4 | _instances = {} 5 | def __call__(cls, *args, **kwargs): 6 | if cls not in cls._instances: 7 | cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) 8 | return cls._instances[cls] 9 | 10 | class STFT(torch.nn.Module, metaclass=Singleton): 11 | def __init__(self, filter_length=1024, hop_length=512): 12 | super(STFT, self).__init__() 13 | 14 | self.filter_length = filter_length 15 | self.hop_len = hop_length 16 | self.win_len = filter_length 17 | self.window = torch.hann_window(self.win_len) 18 | self.num_samples = -1 19 | 20 | def transform(self, x): 21 | x = torch.nn.functional.pad(x, (0, self.win_len - x.shape[1]%self.win_len)) 22 | fft = torch.stft(x, self.filter_length, self.hop_len, self.win_len, window=self.window.to(x.device), return_complex=True) 23 | 24 | real_part, imag_part = fft.real, fft.imag 25 | 26 | squared = real_part**2 + imag_part**2 27 | additive_epsilon = torch.ones_like(squared) * (squared == 0).float() * 1e-24 28 | magnitude = torch.sqrt(squared + additive_epsilon) - torch.sqrt(additive_epsilon) 29 | 30 | phase = torch.autograd.Variable(torch.atan2(imag_part.data, real_part.data)).float() 31 | return magnitude, phase 32 | 33 | def inverse(self, magnitude, phase): 34 | 35 | recombine_magnitude_phase = magnitude*torch.cos(phase) + 1j*magnitude*torch.sin(phase) 36 | inverse_transform = torch.istft(recombine_magnitude_phase, self.filter_length, hop_length=self.hop_len, win_length=self.win_len, window=self.window.to(magnitude.device)).unsqueeze(1) # , length=self.num_samples 37 | padding = self.win_len - (self.num_samples % self.win_len) 38 | inverse_transform = inverse_transform[:, :, :-padding] 39 | return inverse_transform 40 | 41 | --------------------------------------------------------------------------------