From 5aba6f6753fa3debc992f3cc629bf6a5b5388bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=B8=86?= <446962864@qq.com> Date: Mon, 31 May 2021 14:48:24 +0800 Subject: [PATCH 01/11] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d5e595f..57d34f5 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ #### 效果演示 - +![](https://images.gitee.com/uploads/images/2021/0531/144816_81aaac1e_7648707.gif "audio.gif") #### 安装教程 -- Gitee From d4a29951af1c0f6ab7febc0d39deb4c076501e10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=B8=86?= <446962864@qq.com> Date: Mon, 31 May 2021 14:49:16 +0800 Subject: [PATCH 02/11] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 57d34f5..372801a 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ allprojects { ```java dependencies { - implementation('com.gitee.chinasoft_ohos:audio-visualizer-ohos:0.0.1-SNAPSHOT') + implementation 'com.gitee.chinasoft_ohos:audio-visualizer-ohos:0.0.1-SNAPSHOT' ...... } ``` -- Gitee From b75c852799fba8c3f9cc60e9c24acfd9cb1bf52f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=B8=86?= <446962864@qq.com> Date: Mon, 31 May 2021 14:49:43 +0800 Subject: [PATCH 03/11] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 372801a..99daf19 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ CloudTest代码测试无异常 #### 版权和许可信息 -```java +```txt Copyright 2018 Gaurav Kumar Licensed under the Apache License, Version 2.0 (the "License"); -- Gitee From 8804c4b3ccc9c5a4f4d89498e597514a02df5a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=B8=86?= <446962864@qq.com> Date: Mon, 31 May 2021 14:50:55 +0800 Subject: [PATCH 04/11] update README.md. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 99daf19..f272f21 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ 1.在项目根目录下的build.gradle文件中 -```java +```txt allprojects { repositories { maven { @@ -30,9 +30,9 @@ allprojects { 2.在entry模块下的build.gradle文件中 -```java +```text dependencies { - implementation 'com.gitee.chinasoft_ohos:audio-visualizer-ohos:0.0.1-SNAPSHOT' + implementation('com.gitee.chinasoft_ohos:audio-visualizer-ohos:0.0.1-SNAPSHOT') ...... } ``` -- Gitee From 3de350b8d1d8a0770aa84acdea70f0e8d8dd382d Mon Sep 17 00:00:00 2001 From: ZYF949 <446962864@qq.com> Date: Mon, 31 May 2021 15:46:14 +0800 Subject: [PATCH 05/11] =?UTF-8?q?=E4=BF=AE=E6=94=B9README.OPENRESOURCE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AudioVisualizerOhos/.gitignore | 14 ++ AudioVisualizerOhos/CHANGELOG.md | 6 + AudioVisualizerOhos/LICENSE | 201 ++++++++++++++++ AudioVisualizerOhos/README.OPENRESOURCE.md | 10 + AudioVisualizerOhos/README.md | 91 +++++++ .../audiovisualizer/.gitignore | 1 + .../audiovisualizer/build.gradle | 14 ++ .../audiovisualizer/src/main/config.json | 26 ++ .../audiovisualizer/base/BaseVisualizer.java | 210 ++++++++++++++++ .../audiovisualizer/model/AnimSpeed.java | 32 +++ .../audiovisualizer/model/PaintStyle.java | 28 +++ .../model/PositionGravity.java | 28 +++ .../audiovisualizer/utils/AVConstants.java | 46 ++++ .../audiovisualizer/utils/BezierSpline.java | 153 ++++++++++++ .../visualizer/BarVisualizer.java | 182 ++++++++++++++ .../visualizer/BlastVisualizer.java | 117 +++++++++ .../visualizer/BlobVisualizer.java | 225 ++++++++++++++++++ .../visualizer/CircleLineVisualizer.java | 185 ++++++++++++++ .../visualizer/HiFiVisualizer.java | 155 ++++++++++++ .../visualizer/WaveVisualizer.java | 219 +++++++++++++++++ .../main/resources/base/element/string.json | 8 + AudioVisualizerOhos/build.gradle | 46 ++++ AudioVisualizerOhos/entry/.gitignore | 1 + AudioVisualizerOhos/entry/build.gradle | 13 + .../entry/src/main/config.json | 209 ++++++++++++++++ .../audiovisualizersample/MainAbility.java | 18 ++ .../audiovisualizersample/MyApplication.java | 10 + .../slice/MainAbilitySlice.java | 108 +++++++++ .../audiovisualizersample/ui/BarAbility.java | 69 ++++++ .../ui/BlastAbility.java | 70 ++++++ .../audiovisualizersample/ui/BlobAbility.java | 70 ++++++ .../ui/CircleLineAbility.java | 48 ++++ .../audiovisualizersample/ui/HiFiAbility.java | 48 ++++ .../ui/MusicStreamAbility.java | 118 +++++++++ .../audiovisualizersample/ui/WaveAbility.java | 70 ++++++ .../util/MusicFinish.java | 8 + .../util/PermissionUtils.java | 50 ++++ .../util/PlaySoundUtil.java | 65 +++++ .../main/resources/base/element/color.json | 46 ++++ .../main/resources/base/element/string.json | 24 ++ .../base/graphic/background_ability_main.xml | 6 + .../resources/base/graphic/main_bt_bg.xml | 12 + .../resources/base/layout/ability_main.xml | 129 ++++++++++ .../resources/base/layout/activity_bar.xml | 29 +++ .../resources/base/layout/activity_blast.xml | 28 +++ .../resources/base/layout/activity_blob.xml | 28 +++ .../base/layout/activity_circle_line.xml | 28 +++ .../resources/base/layout/activity_hi_fi.xml | 28 +++ .../base/layout/activity_music_stream.xml | 40 ++++ .../resources/base/layout/activity_wave.xml | 28 +++ .../resources/base/layout/progress_layout.xml | 27 +++ .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../src/main/resources/base/media/play.png | Bin 0 -> 583 bytes .../src/main/resources/base/media/stop.png | Bin 0 -> 449 bytes .../main/resources/base/profile/sample.aac | Bin 0 -> 481012 bytes .../src/main/resources/rawfile/Ring10.wav | Bin 0 -> 701708 bytes .../src/main/resources/rawfile/red_e.mp3 | Bin 0 -> 960648 bytes .../src/main/resources/rawfile/sample.aac | Bin 0 -> 481012 bytes .../github/gabrielbb/cutout/ExampleTest.java | 9 + AudioVisualizerOhos/gradle.properties | 10 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 58694 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + AudioVisualizerOhos/gradlew | 183 ++++++++++++++ AudioVisualizerOhos/gradlew.bat | 103 ++++++++ AudioVisualizerOhos/img/audio.gif | Bin 0 -> 1276728 bytes AudioVisualizerOhos/settings.gradle | 1 + README.OPENRESOURCE.md | 4 +- README.md | 10 +- .../visualizer/BlastVisualizer.java | 2 +- .../visualizer/BlobVisualizer.java | 17 +- entry/build.gradle | 11 + .../slice/MainAbilitySlice.java | 1 + .../ui/MusicStreamAbility.java | 4 +- .../util/PermissionUtils.java | 7 +- 74 files changed, 3777 insertions(+), 15 deletions(-) create mode 100644 AudioVisualizerOhos/.gitignore create mode 100644 AudioVisualizerOhos/CHANGELOG.md create mode 100644 AudioVisualizerOhos/LICENSE create mode 100644 AudioVisualizerOhos/README.OPENRESOURCE.md create mode 100644 AudioVisualizerOhos/README.md create mode 100644 AudioVisualizerOhos/audiovisualizer/.gitignore create mode 100644 AudioVisualizerOhos/audiovisualizer/build.gradle create mode 100644 AudioVisualizerOhos/audiovisualizer/src/main/config.json create mode 100644 AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/base/BaseVisualizer.java create mode 100644 AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/model/AnimSpeed.java create mode 100644 AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/model/PaintStyle.java create mode 100644 AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/model/PositionGravity.java create mode 100644 AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/utils/AVConstants.java create mode 100644 AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/utils/BezierSpline.java create mode 100644 AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BarVisualizer.java create mode 100644 AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BlastVisualizer.java create mode 100644 AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BlobVisualizer.java create mode 100644 AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/CircleLineVisualizer.java create mode 100644 AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/HiFiVisualizer.java create mode 100644 AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/WaveVisualizer.java create mode 100644 AudioVisualizerOhos/audiovisualizer/src/main/resources/base/element/string.json create mode 100644 AudioVisualizerOhos/build.gradle create mode 100644 AudioVisualizerOhos/entry/.gitignore create mode 100644 AudioVisualizerOhos/entry/build.gradle create mode 100644 AudioVisualizerOhos/entry/src/main/config.json create mode 100644 AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/MainAbility.java create mode 100644 AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/MyApplication.java create mode 100644 AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/slice/MainAbilitySlice.java create mode 100644 AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/BarAbility.java create mode 100644 AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/BlastAbility.java create mode 100644 AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/BlobAbility.java create mode 100644 AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/CircleLineAbility.java create mode 100644 AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/HiFiAbility.java create mode 100644 AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/MusicStreamAbility.java create mode 100644 AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/WaveAbility.java create mode 100644 AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/util/MusicFinish.java create mode 100644 AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/util/PermissionUtils.java create mode 100644 AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/util/PlaySoundUtil.java create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/element/color.json create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/element/string.json create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/graphic/background_ability_main.xml create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/graphic/main_bt_bg.xml create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/layout/ability_main.xml create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/layout/activity_bar.xml create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/layout/activity_blast.xml create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/layout/activity_blob.xml create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/layout/activity_circle_line.xml create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/layout/activity_hi_fi.xml create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/layout/activity_music_stream.xml create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/layout/activity_wave.xml create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/layout/progress_layout.xml create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/media/icon.png create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/media/play.png create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/media/stop.png create mode 100644 AudioVisualizerOhos/entry/src/main/resources/base/profile/sample.aac create mode 100644 AudioVisualizerOhos/entry/src/main/resources/rawfile/Ring10.wav create mode 100644 AudioVisualizerOhos/entry/src/main/resources/rawfile/red_e.mp3 create mode 100644 AudioVisualizerOhos/entry/src/main/resources/rawfile/sample.aac create mode 100644 AudioVisualizerOhos/entry/src/test/java/com/github/gabrielbb/cutout/ExampleTest.java create mode 100644 AudioVisualizerOhos/gradle.properties create mode 100644 AudioVisualizerOhos/gradle/wrapper/gradle-wrapper.jar create mode 100644 AudioVisualizerOhos/gradle/wrapper/gradle-wrapper.properties create mode 100644 AudioVisualizerOhos/gradlew create mode 100644 AudioVisualizerOhos/gradlew.bat create mode 100644 AudioVisualizerOhos/img/audio.gif create mode 100644 AudioVisualizerOhos/settings.gradle diff --git a/AudioVisualizerOhos/.gitignore b/AudioVisualizerOhos/.gitignore new file mode 100644 index 0000000..603b140 --- /dev/null +++ b/AudioVisualizerOhos/.gitignore @@ -0,0 +1,14 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx diff --git a/AudioVisualizerOhos/CHANGELOG.md b/AudioVisualizerOhos/CHANGELOG.md new file mode 100644 index 0000000..492e3b2 --- /dev/null +++ b/AudioVisualizerOhos/CHANGELOG.md @@ -0,0 +1,6 @@ +## 0.0.1-SNAPSHOT + +ohos第一个版本 + +* 实现了原库大部分api +* 因为缺少对应api,当前仅支持播放wav音频时背景联动,若播放mp3则背景不联动 \ No newline at end of file diff --git a/AudioVisualizerOhos/LICENSE b/AudioVisualizerOhos/LICENSE new file mode 100644 index 0000000..46699c7 --- /dev/null +++ b/AudioVisualizerOhos/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018 Gaurav Kumar + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/AudioVisualizerOhos/README.OPENRESOURCE.md b/AudioVisualizerOhos/README.OPENRESOURCE.md new file mode 100644 index 0000000..f9e6356 --- /dev/null +++ b/AudioVisualizerOhos/README.OPENRESOURCE.md @@ -0,0 +1,10 @@ +[ + { + "Name": "AudioVisualizerOhos", + "License": "Apache License", + "License File": "LICENSE", + "Version Number": "0.9.1", + "Upstream URL": "[](https://github.com/gauravk95/audio-visualizer-android)", + "Description": "A light-weight and easy-to-use Audio Visualizer for Android using the Android Canvas." + } +] \ No newline at end of file diff --git a/AudioVisualizerOhos/README.md b/AudioVisualizerOhos/README.md new file mode 100644 index 0000000..6718247 --- /dev/null +++ b/AudioVisualizerOhos/README.md @@ -0,0 +1,91 @@ +# audio-visualizer-ohos + +#### 项目介绍 + +* 项目名称:audio-visualizer-ohos +* 所属系列:openharmony的第三方组件适配移植 +* 功能:音频播放及背景联动 +* 项目移植状态:当前仅支持播放wav格式音频,若想播放mp3音频,背景无法联动 +* 调用差异:无 +* 开发版本:sdk5,DevEco Studio2.1 beta4 +* 基线版本:Relesase版本号0.9.1 + +#### 效果演示 + + + +#### 安装教程 + +1.在项目根目录下的build.gradle文件中 + +```java +allprojects { + repositories { + maven { + url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' + } + } +} +``` + +2.在entry模块下的build.gradle文件中 + +```java +dependencies { + implementation('com.gitee.chinasoft_ohos:AudioVisualizerOhos:0.0.1-SNAPSHOT') + ...... + } +``` + +在sdk5,DevEco Studio2.1 beta4下项目可直接运行 如无法运行,删除项目.gradle,.idea,build,gradle,build.gradle文件, 并依据自己的版本创建新项目,将新项目的对应文件复制到根目录下 + +#### 使用说明 + +在布局中引入对应的自定义控件用于绘制频率,例如: + +```xml + +``` + +用户可自定义播放器,在类中调用setAudioSessionId,背景即可跟随频率联动 + +#### 测试信息 + +CodeCheck代码测试无异常 + +CloudTest代码测试无异常 + +火绒安全病毒安全检测通过 + +当前版本demo功能与原组件基本无差异 + +#### 版本迭代 + +* 0.0.1-SNAPSHOT + +#### 版权和许可信息 + +```java + Copyright 2018 Gaurav Kumar + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +``` + diff --git a/AudioVisualizerOhos/audiovisualizer/.gitignore b/AudioVisualizerOhos/audiovisualizer/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/AudioVisualizerOhos/audiovisualizer/.gitignore @@ -0,0 +1 @@ +/build diff --git a/AudioVisualizerOhos/audiovisualizer/build.gradle b/AudioVisualizerOhos/audiovisualizer/build.gradle new file mode 100644 index 0000000..76741ae --- /dev/null +++ b/AudioVisualizerOhos/audiovisualizer/build.gradle @@ -0,0 +1,14 @@ +apply plugin: 'com.huawei.ohos.library' +ohos { + compileSdkVersion 5 + defaultConfig { + compatibleSdkVersion 5 + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + testCompile 'junit:junit:4.12' + implementation 'org.jetbrains:annotations:15.0' +} diff --git a/AudioVisualizerOhos/audiovisualizer/src/main/config.json b/AudioVisualizerOhos/audiovisualizer/src/main/config.json new file mode 100644 index 0000000..86c25f7 --- /dev/null +++ b/AudioVisualizerOhos/audiovisualizer/src/main/config.json @@ -0,0 +1,26 @@ +{ + "app": { + "bundleName": "com.gauravk.audiovisualizersample", + "vendor": "gauravk", + "version": { + "code": 1, + "name": "1.0" + }, + "apiVersion": { + "compatible": 5, + "target": 5 + } + }, + "deviceConfig": {}, + "module": { + "package": "com.gauravk.audiovisualizersample", + "deviceType": [ + "phone" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "audiovisualizer", + "moduleType": "har" + } + } +} \ No newline at end of file diff --git a/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/base/BaseVisualizer.java b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/base/BaseVisualizer.java new file mode 100644 index 0000000..533443e --- /dev/null +++ b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/base/BaseVisualizer.java @@ -0,0 +1,210 @@ +/* + Copyright 2018 Gaurav Kumar + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.gauravk.audiovisualizer.base; + +import com.gauravk.audiovisualizer.model.AnimSpeed; +import com.gauravk.audiovisualizer.model.PaintStyle; +import com.gauravk.audiovisualizer.model.PositionGravity; +import com.gauravk.audiovisualizer.utils.AVConstants; + +import ohos.agp.components.AttrSet; +import ohos.agp.components.ComponentContainer; +import ohos.agp.render.Paint; +import ohos.agp.utils.Color; +import ohos.app.Context; +import ohos.media.audio.AudioWaver; + +/** + * Base class for the visualizers + *

+ * Created by gk + */ + +public abstract class BaseVisualizer extends ComponentContainer { + protected byte[] mRawAudioBytes; + protected Paint mPaint; + protected Color mColor = AVConstants.DEFAULT_COLOR; + protected byte[] bytes; + + protected PaintStyle mPaintStyle = PaintStyle.FILL; + protected PositionGravity mPositionGravity = PositionGravity.BOTTOM; + + protected float mStrokeWidth = AVConstants.DEFAULT_STROKE_WIDTH; + protected float mDensity = AVConstants.DEFAULT_DENSITY; + + protected AnimSpeed mAnimSpeed = AnimSpeed.MEDIUM; + protected boolean isVisualizationEnabled = true; + + private AudioWaver audioWaver; + + /** + * 使用java代码实例化调用 + * + * @param context + */ + public BaseVisualizer(Context context) { + super(context); + init(context, null); + init(); + } + + /** + * 使用xml布局引用调用 + * + * @param context + * @param attrSet + */ + public BaseVisualizer(Context context, AttrSet attrSet) { + super(context, attrSet); + init(context, attrSet); + init(); + } + + /** + * 使用xml并设置style调用 + * + * @param context + * @param attrSet + * @param styleName + */ + public BaseVisualizer(Context context, AttrSet attrSet, String styleName) { + super(context, attrSet, styleName); + init(context, attrSet); + init(); + } + + /** + * 子类初始化操作 + */ + protected abstract void init(); + + private void init(Context context, AttrSet attrs) { + this.mDensity = attrs.getAttr("avDensity").get().getFloatValue(); + this.mColor = attrs.getAttr("avColor").get().getColorValue(); + this.mStrokeWidth = attrs.getAttr("avWidth").get().getDimensionValue(); + String avType = attrs.getAttr("avType").get().getStringValue(); + if (avType != null && !avType.equals("")) { + this.mPaintStyle = avType.toLowerCase().equals("outline") ? PaintStyle.OUTLINE : PaintStyle.FILL; + } + String avSpeed = attrs.getAttr("avSpeed").get().getStringValue(); + if (avSpeed != null && !avSpeed.equals("")) { + this.mAnimSpeed = AnimSpeed.MEDIUM; + if (avSpeed.toLowerCase().equals("slow")) { + this.mAnimSpeed = AnimSpeed.SLOW; + } + else if (avSpeed.toLowerCase().equals("fast")) { + this.mAnimSpeed = AnimSpeed.FAST; + } + } + + mPaint = new Paint(); + mPaint.setColor(mColor); + mPaint.setStrokeWidth(mStrokeWidth); + if (mPaintStyle == PaintStyle.FILL) { + mPaint.setStyle(Paint.Style.FILL_STYLE); + } + else { + mPaint.setStyle(Paint.Style.STROKE_STYLE); + } + } + + /** + * Set color to visualizer with color resource id. + * + * @param color color resource id. + */ + public void setColor(Color color) { + this.mColor = color; + this.mPaint.setColor(this.mColor); + } + + /** + * Set the density of the visualizer + * + * @param density density for visualization + */ + public void setDensity(float density) { + synchronized (this) { + this.mDensity = density; + init(); + } + } + + /** + * Sets the paint style of the visualizer + * + * @param paintStyle style of the visualizer. + */ + public void setPaintStyle(PaintStyle paintStyle) { + this.mPaintStyle = paintStyle; + this.mPaint.setStyle(paintStyle == PaintStyle.FILL ? Paint.Style.FILL_STYLE : Paint.Style.STROKE_STYLE); + } + + /** + * Sets the position of the Visualization{@link PositionGravity} + * + * @param positionGravity position of the Visualization + */ + public void setPositionGravity(PositionGravity positionGravity) { + this.mPositionGravity = positionGravity; + } + + /** + * Sets the Animation speed of the visualization{@link AnimSpeed} + * + * @param animSpeed speed of the animation + */ + public void setAnimationSpeed(AnimSpeed animSpeed) { + this.mAnimSpeed = animSpeed; + } + + /** + * Sets the width of the outline {@link PaintStyle} + * + * @param width style of the visualizer. + */ + public void setStrokeWidth(float width) { + this.mStrokeWidth = width; + this.mPaint.setStrokeWidth(width); + } + + /** + * Sets the audio session id for the currently playing audio + * + * @param audioSessionId of the media to be visualised + */ + public void setAudioSessionId(int audioSessionId) { + audioWaver = new AudioWaver(audioSessionId, this.getClass().getName()); + audioWaver.setActivated(false); + audioWaver.setDataSize(AudioWaver.getMaxDataSize()); + audioWaver.setWaveDataObserver(new AudioWaver.WaveDataObserver() { + @Override + public void onWaveData(byte[] mBytes, int i) { + BaseVisualizer.this.mRawAudioBytes = mBytes; + + // 刷新 + getContext().getUITaskDispatcher().syncDispatch(new Runnable() { + @Override + public void run() { + invalidate(); + } + }); + } + }, AudioWaver.getMinInterval()); + audioWaver.setActivated(true); + } +} \ No newline at end of file diff --git a/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/model/AnimSpeed.java b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/model/AnimSpeed.java new file mode 100644 index 0000000..88856d5 --- /dev/null +++ b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/model/AnimSpeed.java @@ -0,0 +1,32 @@ +/* + Copyright 2018 Gaurav Kumar + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.gauravk.audiovisualizer.model; + +public enum AnimSpeed { + /** + * SLOW + */ + SLOW, + /** + * MEDIUM + */ + MEDIUM, + /** + * FAST + */ + FAST +} diff --git a/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/model/PaintStyle.java b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/model/PaintStyle.java new file mode 100644 index 0000000..41fab70 --- /dev/null +++ b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/model/PaintStyle.java @@ -0,0 +1,28 @@ +/* + Copyright 2018 Gaurav Kumar + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.gauravk.audiovisualizer.model; + +public enum PaintStyle { + /** + * OUTLINE + */ + OUTLINE, + /** + * FILL + */ + FILL +} diff --git a/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/model/PositionGravity.java b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/model/PositionGravity.java new file mode 100644 index 0000000..1f2d385 --- /dev/null +++ b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/model/PositionGravity.java @@ -0,0 +1,28 @@ +/* + Copyright 2018 Gaurav Kumar + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.gauravk.audiovisualizer.model; + +public enum PositionGravity { + /** + * TOP + */ + TOP, + /** + * BOTTOM + */ + BOTTOM +} diff --git a/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/utils/AVConstants.java b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/utils/AVConstants.java new file mode 100644 index 0000000..3af76f7 --- /dev/null +++ b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/utils/AVConstants.java @@ -0,0 +1,46 @@ +/* + Copyright 2018 Gaurav Kumar + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.gauravk.audiovisualizer.utils; + +import ohos.agp.utils.Color; + +public class AVConstants { + /** + * 代替0.25 + */ + public static final float DEFAULT_DENSITY = 0.25f; + /** + * 白色 + */ + public static final Color DEFAULT_COLOR = Color.WHITE; + /** + * 代替0.6 + */ + public static final float DEFAULT_STROKE_WIDTH = 6.0f; + /** + * 代替4 + */ + public static final int MAX_ANIM_BATCH_COUNT = 4; + /** + * 代替2 + */ + public static final int NUM_2 = 2; + /** + * 代替3 + */ + public static final int NUM_3 = 3; +} \ No newline at end of file diff --git a/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/utils/BezierSpline.java b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/utils/BezierSpline.java new file mode 100644 index 0000000..25c62e9 --- /dev/null +++ b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/utils/BezierSpline.java @@ -0,0 +1,153 @@ +/* + Copyright 2018 Gaurav Kumar + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.gauravk.audiovisualizer.utils; + +import ohos.agp.utils.Point; + +public class BezierSpline { + private final int nSize; + private final Point[] firstControlPoints; + private final Point[] secondControlPoints; + + /** + * BezierSpline构造方法 + * + * @param size + */ + public BezierSpline(int size) { + this.nSize = size - 1; + firstControlPoints = new Point[nSize]; + secondControlPoints = new Point[nSize]; + for (int i = 0; i < nSize; i++) { + firstControlPoints[i] = new Point(); + secondControlPoints[i] = new Point(); + } + } + + /** + * Get open-ended bezier spline control points. + * + * @param knots bezier spline points + * @throws IllegalArgumentException if less than two knots are passed. + */ + public void updateCurveControlPoints(Point[] knots) { + if (knots == null || knots.length < AVConstants.NUM_2) { + throw new IllegalArgumentException("At least two knot points are required"); + } + final int n = knots.length - 1; + + // Special case: bezier curve should be a straight line + if (n == 1) { + // 3P1 = 2P0 + P3 + float x = (AVConstants.NUM_2 * knots[0].getPointX() + knots[1].getPointX()) / AVConstants.NUM_3; + float y = (AVConstants.NUM_2 * knots[0].getPointY() + knots[1].getPointY()) / AVConstants.NUM_3; + + firstControlPoints[0].modify(x, y); + + // P2 = 2P1 - P0 + x = AVConstants.NUM_2 * firstControlPoints[0].getPointX() - knots[0].getPointX(); + y = AVConstants.NUM_2 * firstControlPoints[0].getPointY() - knots[0].getPointY(); + + secondControlPoints[0].modify(x, y); + + } else { + + // Calculate first bezier control points + // Right hand side vector + float[] rhs = new float[n]; + + // Set right hand side X values + for (int i = 1; i < n - 1; i++) { + rhs[i] = 4 * knots[i].getPointX() + 2 * knots[i + 1].getPointX(); + } + rhs[0] = knots[0].getPointX() + 2 * knots[1].getPointX(); + rhs[n - 1] = (8 * knots[n - 1].getPointX() + knots[n].getPointX()) / 2f; + + // Get first control points X-values + float[] x = getFirstControlPoints(rhs); + + // Set right hand side Y values + for (int i = 1; i < n - 1; i++) { + rhs[i] = 4 * knots[i].getPointY() + 2 * knots[i + 1].getPointY(); + } + rhs[0] = knots[0].getPointY() + 2 * knots[1].getPointY(); + rhs[n - 1] = (8 * knots[n - 1].getPointY() + knots[n].getPointY()) / 2f; + + // Get first control points Y-values + float[] y = getFirstControlPoints(rhs); + + for (int i = 0; i < n; i++) { + // First control point + firstControlPoints[i].modify(x[i], y[i]); + + // Second control point + if (i < n - 1) { + float xx = 2 * knots[i + 1].getPointX() - x[i + 1]; + float yy = 2 * knots[i + 1].getPointY() - y[i + 1]; + secondControlPoints[i].modify(xx, yy); + } else { + float xx = (knots[n].getPointX() + x[n - 1]) / 2; + float yy = (knots[n].getPointY() + y[n - 1]) / 2; + secondControlPoints[i].modify(xx, yy); + } + } + } + } + + private Point pointSet(float x, float y) { + Point point = new Point(x, y); + return point; + } + + /** + * Solves a tridiagonal system for one of coordinates (x or y) of first + * bezier control points. + * + * @param rhs right hand side vector. + * @return Solution vector. + */ + private float[] getFirstControlPoints(float[] rhs) { + int n = rhs.length; + float[] x = new float[n]; // Solution vector + float[] tmp = new float[n]; // Temp workspace + + float b = 2.0f; + x[0] = rhs[0] / b; + + // Decomposition and forward substitution + for (int i = 1; i < n; i++) { + tmp[i] = 1 / b; + b = (i < n - 1 ? 4.0f : 3.5f) - tmp[i]; + x[i] = (rhs[i] - x[i - 1]) / b; + } + + // Backsubstitution + for (int i = 1; i < n; i++) { + x[n - i - 1] -= tmp[n - i] * x[n - i]; + } + + return x; + } + + public Point[] getFirstControlPoints() { + return firstControlPoints; + } + + public Point[] getSecondControlPoints() { + return secondControlPoints; + } +} \ No newline at end of file diff --git a/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BarVisualizer.java b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BarVisualizer.java new file mode 100644 index 0000000..6703126 --- /dev/null +++ b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BarVisualizer.java @@ -0,0 +1,182 @@ +/* + Copyright 2018 Gaurav Kumar + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.gauravk.audiovisualizer.visualizer; + +import com.gauravk.audiovisualizer.base.BaseVisualizer; +import com.gauravk.audiovisualizer.model.AnimSpeed; +import com.gauravk.audiovisualizer.model.PositionGravity; +import com.gauravk.audiovisualizer.utils.AVConstants; + +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.render.Canvas; +import ohos.agp.utils.Rect; +import ohos.app.Context; + +import java.security.SecureRandom; +import java.util.Random; + +/** + * Custom view to create bar visualizer + *

+ * Created by gk + */ +public class BarVisualizer extends BaseVisualizer implements Component.DrawTask { + private static final int BAR_MAX_POINTS = 120; + private static final int BAR_MIN_POINTS = 3; + + private int mMaxBatchCount; + + private int nPoints; + + private float[] mSrcY; + private float[] mDestY; + + private float mBarWidth; + private Rect mClipBounds; + + private int nBatchCount; + + private SecureRandom mRandom = new SecureRandom(); + + /** + * 使用java代码实例化调用 + * + * @param context + */ + public BarVisualizer(Context context) { + super(context); + } + + /** + * 使用xml布局引用调用 + * + * @param context + * @param attrSet + */ + public BarVisualizer(Context context, AttrSet attrSet) { + super(context, attrSet); + } + + /** + * 使用xml并设置style调用 + * + * @param context + * @param attrSet + * @param styleName + */ + public BarVisualizer(Context context, AttrSet attrSet, String styleName) { + super(context, attrSet, styleName); + } + + @Override + protected void init() { + addDrawTask(this::onDraw); + nPoints = (int) (BAR_MAX_POINTS * mDensity); + if (nPoints < BAR_MIN_POINTS) { + nPoints = BAR_MIN_POINTS; + } + + mBarWidth = -1; + nBatchCount = 0; + + setAnimationSpeed(mAnimSpeed); + + mClipBounds = new Rect(); + + mSrcY = new float[nPoints]; + mDestY = new float[nPoints]; + } + + @Override + public void setAnimationSpeed(AnimSpeed animSpeed) { + super.setAnimationSpeed(animSpeed); + mMaxBatchCount = AVConstants.MAX_ANIM_BATCH_COUNT - mAnimSpeed.ordinal(); + } + + @Override + public void onDraw(Component component, Canvas canvas) { + if (mBarWidth == -1) { + canvas.getLocalClipBounds(mClipBounds); + mBarWidth = component.getWidth() / nPoints; + + // initialize points + for (int i = 0; i < mSrcY.length; i++) { + float posY; + if (mPositionGravity == PositionGravity.TOP) { + posY = mClipBounds.top; + } else { + posY = mClipBounds.bottom; + } + + mSrcY[i] = posY; + mDestY[i] = posY; + } + } + + // create the path and draw + if (isVisualizationEnabled && mRawAudioBytes != null) { + if (mRawAudioBytes.length == 0) { + return; + } + + // find the destination bezier point for a batch + if (nBatchCount == 0) { + float randPosY = mDestY[mRandom.nextInt(nPoints)]; + for (int i = 0; i < mSrcY.length; i++) { + + int x = (int) Math.ceil((i + 1) * (mRawAudioBytes.length / nPoints)); + int t = 0; + if (x < 1024) { + t = component.getHeight() + + ((byte) (Math.abs(mRawAudioBytes[x]) + 128)) * component.getHeight() / 128; + } + + float posY; + if (mPositionGravity == PositionGravity.TOP) { + posY = mClipBounds.bottom - t; + } else { + posY = mClipBounds.top + t; + } + + // change the source and destination y + mSrcY[i] = mDestY[i]; + mDestY[i] = posY; + } + + mDestY[mSrcY.length - 1] = randPosY; + } + + // increment batch count + nBatchCount++; + + // calculate bar position and draw + for (int i = 0; i < mSrcY.length; i++) { + float barY = mSrcY[i] + (((float) (nBatchCount) / mMaxBatchCount) * (mDestY[i] - mSrcY[i])); + float barX = (i * mBarWidth) + (mBarWidth / 2); + canvas.drawLine(barX, component.getHeight(), barX, barY, mPaint); + } + + // reset the batch count + if (nBatchCount == mMaxBatchCount) { + nBatchCount = 0; + } + } + + super.addDrawTask(this::onDraw); + } +} \ No newline at end of file diff --git a/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BlastVisualizer.java b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BlastVisualizer.java new file mode 100644 index 0000000..8f26898 --- /dev/null +++ b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BlastVisualizer.java @@ -0,0 +1,117 @@ +/* + Copyright 2018 Gaurav Kumar + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.gauravk.audiovisualizer.visualizer; + +import com.gauravk.audiovisualizer.base.BaseVisualizer; + +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.render.Canvas; +import ohos.agp.render.Path; +import ohos.app.Context; + +import org.jetbrains.annotations.Nullable; + +/** + * Custom view to create blast visualizer + *

+ * Created by gk + */ +public class BlastVisualizer extends BaseVisualizer implements Component.DrawTask { + private static final int BLAST_MAX_POINTS = 1000; + private static final int BLAST_MIN_POINTS = 3; + + private Path mSpikePath; + private int mRadius; + private int nPoints; + + /** + * 使用java代码实例化调用 + * + * @param context + */ + public BlastVisualizer(Context context) { + super(context); + } + + /** + * 使用xml布局引用调用 + * + * @param context + * @param attrSet + */ + public BlastVisualizer(Context context, + @Nullable AttrSet attrSet) { + super(context, attrSet); + } + + @Override + protected void init() { + addDrawTask(this::onDraw); + mRadius = -1; + nPoints = (int) (BLAST_MAX_POINTS * mDensity); + if (nPoints < BLAST_MIN_POINTS) { + nPoints = BLAST_MIN_POINTS; + } + + mSpikePath = new Path(); + } + + @Override + public void onDraw(Component component,Canvas canvas) { + // first time initialization + if (mRadius == -1) { + mRadius = getHeight() < getWidth() ? getHeight() : getWidth(); + mRadius = (int) (mRadius * 0.65 / 2); + } + + // create the path and draw + if (isVisualizationEnabled && mRawAudioBytes != null) { + if (mRawAudioBytes.length == 0) { + return; + } + + mSpikePath.rewind(); + + double angle = 0; + for (int i = 0; i < nPoints; i++, angle += (360.0f / nPoints)) { + int x = (int) Math.ceil(i * (mRawAudioBytes.length / nPoints)); + int t = 0; + if (x < 1024) { + t = ((byte) (-Math.abs(mRawAudioBytes[x]) + 128)) * (component.getHeight() / 4) / 128; + } + + float posX = (float) (getWidth() / 2 + + (mRadius + t) + * Math.cos(Math.toRadians(angle))); + + float posY = (float) (getHeight() / 2 + + (mRadius + t) + * Math.sin(Math.toRadians(angle))); + + if (i == 0) { + mSpikePath.moveTo(posX, posY); + } else { + mSpikePath.lineTo(posX, posY); + } + } + mSpikePath.close(); + canvas.drawPath(mSpikePath, mPaint); + } + + } +} \ No newline at end of file diff --git a/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BlobVisualizer.java b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BlobVisualizer.java new file mode 100644 index 0000000..444c79d --- /dev/null +++ b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BlobVisualizer.java @@ -0,0 +1,225 @@ +/* + Copyright 2018 Gaurav Kumar + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.gauravk.audiovisualizer.visualizer; + +import com.gauravk.audiovisualizer.base.BaseVisualizer; +import com.gauravk.audiovisualizer.model.AnimSpeed; +import com.gauravk.audiovisualizer.model.PaintStyle; +import com.gauravk.audiovisualizer.utils.BezierSpline; + +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.components.element.ShapeElement; +import ohos.agp.render.Canvas; +import ohos.agp.render.Path; +import ohos.agp.utils.Point; +import ohos.app.Context; + +/** + * Custom view to create blob visualizer + *

+ * Created by gk + */ +public class BlobVisualizer extends BaseVisualizer implements Component.DrawTask { + private static final int BLOB_MAX_POINTS = 60; + private static final int BLOB_MIN_POINTS = 3; + + private Path mBlobPath; + private int mRadius; + + private int nPoints; + + private Point[] mBezierPoints; + private BezierSpline mBezierSpline; + + private float mAngleOffset; + private float mChangeFactor; + + /** + * 使用java代码实例化调用 + * + * @param context + */ + public BlobVisualizer(Context context) { + super(context); + } + + /** + * 使用xml布局引用调用 + * + * @param context + * @param attrSet + */ + public BlobVisualizer(Context context, AttrSet attrSet) { + super(context, attrSet); + } + + /** + * 使用xml并设置style调用 + * + * @param context + * @param attrSet + * @param styleName + */ + public BlobVisualizer(Context context, AttrSet attrSet, String styleName) { + super(context, attrSet, styleName); + } + + + + @Override + protected void init() { + addDrawTask(this::onDraw); + mRadius = -1; + nPoints = (int) (mDensity * BLOB_MAX_POINTS); + if (nPoints < BLOB_MIN_POINTS) { + nPoints = BLOB_MIN_POINTS; + } + + mAngleOffset = (360.0f / nPoints); + + updateChangeFactor(mAnimSpeed, false); + + mBlobPath = new Path(); + + // initialize mBezierPoints, 2 extra for the smoothing first and last point + mBezierPoints = new Point[nPoints + 2]; + for (int i = 0; i < mBezierPoints.length; i++) { + mBezierPoints[i] = new Point(); + } + + mBezierSpline = new BezierSpline(mBezierPoints.length); + } + + @Override + public void setAnimationSpeed(AnimSpeed animSpeed) { + super.setAnimationSpeed(animSpeed); + updateChangeFactor(animSpeed, true); + } + + private void updateChangeFactor(AnimSpeed animSpeed, boolean useHeight) { + int height = 1; + if (useHeight) { + height = getHeight() > 0 ? getHeight() : 1000; + } + + if (animSpeed == AnimSpeed.SLOW) { + mChangeFactor = height * 0.003f; + } else if (animSpeed == AnimSpeed.MEDIUM) { + mChangeFactor = height * 0.006f; + } else { + mChangeFactor = height * 0.01f; + } + } + + @Override + public void onDraw(Component component, Canvas canvas) { + + double angle = 0; + // first time initialization + if (mRadius == -1) { + mRadius = getHeight() < getWidth() ? getHeight() : getWidth(); + + // 382 + mRadius = (int) (mRadius * 0.65 / 2); + + // 10.8 + mChangeFactor = getHeight() * mChangeFactor; + + // initialize bezier points + for (int i = 0; i < nPoints; i++, angle += mAngleOffset) { + float posX = (float) (getWidth() / 2 + + (mRadius) + * Math.cos(Math.toRadians(angle))); + + float posY = (float) (getHeight() / 2 + + (mRadius) + * Math.sin(Math.toRadians(angle))); + + mBezierPoints[i].modify(posX, posY); + } + } + + // create the path and draw + if (isVisualizationEnabled && mRawAudioBytes != null) { + if (mRawAudioBytes.length == 0) { + return; + } + + mBlobPath.rewind(); + + // find the destination bezier point for a batch + for (int i = 0; i < nPoints; i++, angle += mAngleOffset) { + Point mBezierPoint = mBezierPoints[i]; + + // 1=1 X=34 i=2 X=68 + int x = (int) Math.ceil((i + 1) * (mRawAudioBytes.length / nPoints)); + int t = 0; + if (x < 1024) { + t = ((byte) (-Math.abs(mRawAudioBytes[x]) + 128)) * (component.getHeight() / 4) / 128; + } + + float posX = (float) (getWidth() / 2 + + (mRadius + t) + * Math.cos(Math.toRadians(angle))); + + float posY = (float) (getHeight() / 2 + + (mRadius + t) + * Math.sin(Math.toRadians(angle))); + + // calculate the new x based on change + if (posX - mBezierPoint.getPointXToInt() > 0) { + mBezierPoint.modify(mBezierPoint.getPointX() + mChangeFactor, mBezierPoint.getPointY()); + } else { + mBezierPoint.modify(mBezierPoint.getPointX() - mChangeFactor, mBezierPoint.getPointY()); + } + + // calculate the new y based on change + if (posY - mBezierPoint.getPointY() > 0) { + mBezierPoint.modify(mBezierPoint.getPointX(), mBezierPoint.getPointY() + mChangeFactor); + } else { + mBezierPoint.modify(mBezierPoint.getPointX(), mBezierPoint.getPointY() - mChangeFactor); + } + } + + // set the first and last point as first + + mBezierPoints[nPoints].modify(mBezierPoints[0].getPointX(), mBezierPoints[0].getPointY()); + mBezierPoints[nPoints + 1].modify(mBezierPoints[0].getPointX(), mBezierPoints[0].getPointY()); + + // update the control points + mBezierSpline.updateCurveControlPoints(mBezierPoints); + Point[] firstCP = mBezierSpline.getFirstControlPoints(); + Point[] secondCP = mBezierSpline.getSecondControlPoints(); + + // create the path + mBlobPath.moveTo(mBezierPoints[0].getPointX(), mBezierPoints[0].getPointY()); + for (int i = 0; i < firstCP.length; i++) { + mBlobPath.cubicTo(firstCP[i].getPointX(), firstCP[i].getPointY(), + secondCP[i].getPointX(), secondCP[i].getPointY(), + mBezierPoints[i + 1].getPointX(), mBezierPoints[i + 1].getPointY()); + } + + // add an extra line to center cover the gap generated by last cubicTo + if (mPaintStyle == PaintStyle.FILL) { + mBlobPath.lineTo(getWidth() / 2, getHeight() / 2); + } + canvas.drawPath(mBlobPath, mPaint); + } + super.addDrawTask(this::onDraw); + } +} \ No newline at end of file diff --git a/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/CircleLineVisualizer.java b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/CircleLineVisualizer.java new file mode 100644 index 0000000..6fd2c2e --- /dev/null +++ b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/CircleLineVisualizer.java @@ -0,0 +1,185 @@ +package com.gauravk.audiovisualizer.visualizer; + +import com.gauravk.audiovisualizer.base.BaseVisualizer; + +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.components.ComponentContainer; +import ohos.agp.render.*; +import ohos.agp.utils.Color; +import ohos.agp.utils.Point; +import ohos.agp.utils.Rect; +import ohos.app.Context; + +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; + +/** + * 圆形 + * + * @author maple on 2019/4/24 15:17. + * @version v1.0 + */ +public class CircleLineVisualizer extends BaseVisualizer implements Component.DrawTask, ComponentContainer.ArrangeListener { + private static final int BAR_MAX_POINTS = 240; + private static final int BAR_MIN_POINTS = 30; + private Rect mClipBounds; + private int mPoints; + private int mPointRadius; + private float[] mSrcY; + private int mRadius; + private Paint mGPaint; + private boolean drawLine; + + /** + * 使用java代码实例化调用 + * + * @param context + */ + public CircleLineVisualizer(Context context) { + super(context); + } + + /** + * 使用xml布局引用调用 + * + * @param context + * @param attrs + */ + public CircleLineVisualizer(Context context, @Nullable AttrSet attrs) { + super(context, attrs); + } + + public boolean isDrawLine() { + return drawLine; + } + + /** + * control the display of drawLine + * + * @param drawLine is show drawLine + */ + public void setDrawLine(boolean drawLine) { + this.drawLine = drawLine; + } + + @Override + protected void init() { + addDrawTask(this::onDraw); + setArrangeListener(this::onArrange); + mPoints = (int) (BAR_MAX_POINTS * mDensity); + if (mPoints < BAR_MIN_POINTS) { + mPoints = BAR_MIN_POINTS; + } + mSrcY = new float[mPoints]; + mClipBounds = new Rect(); + setAnimationSpeed(mAnimSpeed); + mPaint.setAntiAlias(true); + mGPaint = new Paint(); + mGPaint.setAntiAlias(true); + } + + @Override + public void onDraw(Component component, Canvas canvas) { + canvas.getLocalClipBounds(mClipBounds); + updateData(); + + // draw circle's points + for (int i = 0; i < 360; i = i + 360 / mPoints) { + float cx = (float) (getWidth() / 2 + Math.cos(i * Math.PI / 180) * mRadius); + float cy = (float) (getHeight() / 2 - Math.sin(i * Math.PI / 180) * mRadius); + canvas.drawCircle(cx, cy, mPointRadius, mPaint); + } + + // draw lines + if (drawLine) { + drawLines(canvas); + } + + // draw bar + for (int i = 0; i < 360; i = i + 360 / mPoints) { + if (mSrcY[i * mPoints / 360] == 0) { + continue; + } + canvas.save(); + canvas.rotate(-i, getWidth() / 2, getHeight() / 2); + float cx = (float) (getWidth() / 2 + mRadius); + float cy = (float) (getHeight() / 2); + canvas.drawRect(cx, cy - mPointRadius, cx + mSrcY[i * mPoints / 360], + cy + mPointRadius, mPaint); + canvas.drawCircle(cx + mSrcY[i * mPoints / 360], cy, mPointRadius, mPaint); + canvas.restore(); + } + super.addDrawTask(this::onDraw); + } + + /** + * Draw a translucent ray + * + * @param canvas target canvas + */ + private void drawLines(Canvas canvas) { + int lineLen = 14 * mPointRadius; + + // default len, + for (int i = 0; i < 360; i = i + 360 / mPoints) { + canvas.save(); + canvas.rotate(-i, getWidth() / 2, getHeight() / 2); + float cx = (float) (getWidth() / 2 + mRadius) + mSrcY[i * mPoints / 360]; + float cy = (float) (getHeight() / 2); + Path path = new Path(); + path.moveTo(cx, cy + mPointRadius); + path.lineTo(cx, cy - mPointRadius); + path.lineTo(cx + lineLen, cy); + canvas.drawPath(path, mGPaint); + canvas.restore(); + } + } + + private void updateData() { + if (isVisualizationEnabled && mRawAudioBytes != null) { + if (mRawAudioBytes.length == 0) { + return; + } + for (int i = 0; i < mSrcY.length; i++) { + int x = (int) Math.ceil((i + 1) * (mRawAudioBytes.length / mPoints)); + int t = 0; + if (x < 1024) { + t = ((byte) (Math.abs(mRawAudioBytes[x]) + 128)) * mRadius / 128; + } + mSrcY[i] = -t; + } + } + } + + /** + * 大小发生变化调用 + * + * @param w 0 + * @param h 0 + * @param oldw 1176 + * @param oldh 1800 + * @return + */ + @Override + public boolean onArrange(int w, int h, int oldw, int oldh) { + setArrangeListener(this::onArrange); + mRadius = Math.min(oldw, oldh) / 4; + mPointRadius = Math.abs((int) (2 * mRadius * Math.sin(Math.PI / mPoints / 3))); + Point[] newPoints = new Point[]{new Point(getWidth() / 2 + mRadius, getHeight() / 2)}; + float[] newStops = {getWidth() / 2 + mRadius + mPointRadius * 5, getHeight() / 2}; + Color[] newColors = new Color[]{new Color(Color.getIntColor("#77FF5722")), new Color(Color.getIntColor("#10FF5722"))}; + LinearShader lg = new LinearShader( + newPoints, + newStops, + newColors, + Shader.TileMode.CLAMP_TILEMODE); + mGPaint.setShader(lg, Paint.ShaderType.PIXELMAP_SHADER); + return false; + } + + public void setVisualizationEnabled(boolean b) { + isVisualizationEnabled = b; + } +} diff --git a/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/HiFiVisualizer.java b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/HiFiVisualizer.java new file mode 100644 index 0000000..6406bbf --- /dev/null +++ b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/HiFiVisualizer.java @@ -0,0 +1,155 @@ +package com.gauravk.audiovisualizer.visualizer; + +import com.gauravk.audiovisualizer.base.BaseVisualizer; + +import com.gauravk.audiovisualizer.model.PaintStyle; +import ohos.agp.colors.ColorSpec; +import ohos.agp.colors.RgbColor; +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.render.Canvas; +import ohos.agp.render.Paint; +import ohos.agp.render.Path; +import ohos.agp.utils.Color; +import ohos.app.Context; + +import org.jetbrains.annotations.Nullable; + +/** + * 折线图 + * + * @author maple on 2019/4/25 10:17. + * @version v1.0 + */ +public class HiFiVisualizer extends BaseVisualizer implements Component.DrawTask { + private static final int BAR_MAX_POINTS = 240; + private static final int BAR_MIN_POINTS = 30; + private static final float PER_RADIUS = .65f; + private int mRadius; + private int mPoints; + private int[] mHeights; + private Paint paint; + // outward path + private Path mPath; + + // inward path + private Path mPath1; + + /** + * This is the distance from center to bezier control point. + * We can calculate the bezier control points of each segment this distance and its angle; + */ + private int mBezierControlPointLen; + + /** + * 使用java代码实例化调用 + * + * @param context + */ + public HiFiVisualizer(Context context) { + super(context); + } + + /** + * 使用xml布局引用调用 + * + * @param context + * @param attrs + */ + public HiFiVisualizer(Context context, @Nullable AttrSet attrs) { + super(context, attrs); + } + + @Override + protected void init() { + addDrawTask(this::onDraw); + mRadius = -1; + mPath = new Path(); + mPath1 = new Path(); + mPaint.setStyle(Paint.Style.STROKE_STYLE); + mPaint.setAntiAlias(true); + mPaint.setStrokeWidth(1.0f); + mPoints = (int) (BAR_MAX_POINTS * mDensity); + if (mPoints < BAR_MIN_POINTS) { + mPoints = BAR_MIN_POINTS; + } + mHeights = new int[mPoints]; + + paint = new Paint(); + paint.setColor(new Color(Color.getIntColor("#FCB8A3"))); + paint.setStrokeWidth(mStrokeWidth); + if (mPaintStyle == PaintStyle.FILL) { + paint.setStyle(Paint.Style.FILL_STYLE); + } + else { + paint.setStyle(Paint.Style.STROKE_STYLE); + } + } + + @Override + public void onDraw(Component component, Canvas canvas) { + if (mRadius == -1) { + mRadius = (int) (Math.min(getWidth(), getHeight()) / 2 * PER_RADIUS); + mBezierControlPointLen = (int) (mRadius / Math.cos(Math.PI / mPoints)); + } + updateData(); + mPath.reset(); + mPath1.reset(); + + // start the outward path from the last point + float cxL = (float) (getWidth() / 2 + Math.cos((360 - 360 / mPoints) * Math.PI / 180) * (mRadius + mHeights[mPoints - 1])); + float cyL = (float) (getHeight() / 2 - Math.sin((360 - 360 / mPoints) * Math.PI / 180) * (mRadius + mHeights[mPoints - 1])); + mPath.moveTo(cxL, cyL); + + // start the inward path from the last point + float cxL1 = (float) (getWidth() / 2 + Math.cos((360 - 360 / mPoints) * Math.PI / 180) * (mRadius - mHeights[mPoints - 1])); + float cyL1 = (float) (getHeight() / 2 - Math.sin((360 - 360 / mPoints) * Math.PI / 180) * (mRadius - mHeights[mPoints - 1])); + mPath1.moveTo(cxL1, cyL1); + for (int i = 0; i < 360; i = i + 360 / mPoints) { + // outward + // the next point of path + float cx = (float) (getWidth() / 2 + Math.cos(i * Math.PI / 180) * (mRadius + mHeights[i * mPoints / 360])); + float cy = (float) (getHeight() / 2 - Math.sin(i * Math.PI / 180) * (mRadius + mHeights[i * mPoints / 360])); + + // second bezier control point + float bx = (float) (getWidth() / 2 + Math.cos((i - (180 / mPoints)) * Math.PI / 180) * (mBezierControlPointLen + mHeights[i * mPoints / 360])); + float by = (float) (getHeight() / 2 - Math.sin((i - (180 / mPoints)) * Math.PI / 180) * (mBezierControlPointLen + mHeights[i * mPoints / 360])); + int lastPoint = i == 0 ? mPoints - 1 : i * mPoints / 360 - 1; + + // fist bezier control point + float ax = (float) (getWidth() / 2 + Math.cos((i - (180 / mPoints)) * Math.PI / 180) * (mBezierControlPointLen + mHeights[lastPoint])); + float ay = (float) (getHeight() / 2 - Math.sin((i - (180 / mPoints)) * Math.PI / 180) * (mBezierControlPointLen + mHeights[lastPoint])); + mPath.cubicTo(ax, ay, bx, by, cx, cy); + + // inward + float cx1 = (float) (getWidth() / 2 + Math.cos(i * Math.PI / 180) * (mRadius - mHeights[i * mPoints / 360])); + float cy1 = (float) (getHeight() / 2 - Math.sin(i * Math.PI / 180) * (mRadius - mHeights[i * mPoints / 360])); + float bx1 = (float) (getWidth() / 2 + Math.cos((i - (180 / mPoints)) * Math.PI / 180) * (mBezierControlPointLen - mHeights[i * mPoints / 360])); + float by1 = (float) (getHeight() / 2 - Math.sin((i - (180 / mPoints)) * Math.PI / 180) * (mBezierControlPointLen - mHeights[i * mPoints / 360])); + float ax1 = (float) (getWidth() / 2 + Math.cos((i - (180 / mPoints)) * Math.PI / 180) * (mBezierControlPointLen - mHeights[lastPoint])); + float ay1 = (float) (getHeight() / 2 - Math.sin((i - (180 / mPoints)) * Math.PI / 180) * (mBezierControlPointLen - mHeights[lastPoint])); + mPath1.cubicTo(ax1, ay1, bx1, by1, cx1, cy1); + canvas.drawLine(cx, cy, cx1, cy1, mPaint); + } + canvas.drawPath(mPath, mPaint); + canvas.drawPath(mPath1, mPaint); + } + + private void updateData() { + if (isVisualizationEnabled && mRawAudioBytes != null) { + if (mRawAudioBytes.length == 0) return; + for (int i = 0; i < mHeights.length; i++) { + int x = (int) Math.ceil((i + 1) * (mRawAudioBytes.length / mPoints)); + int t = 0; + if (x < 1024) { + t = ((byte) (Math.abs(mRawAudioBytes[x]) + 128)) * mRadius / 128; + } + mHeights[i] = -t; + } + } + } + + public void setVisualizationEnabled(boolean b) { + isVisualizationEnabled = b; + } +} diff --git a/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/WaveVisualizer.java b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/WaveVisualizer.java new file mode 100644 index 0000000..d9cbe3e --- /dev/null +++ b/AudioVisualizerOhos/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/WaveVisualizer.java @@ -0,0 +1,219 @@ +/* + Copyright 2018 Gaurav Kumar + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.gauravk.audiovisualizer.visualizer; + +import com.gauravk.audiovisualizer.base.BaseVisualizer; +import com.gauravk.audiovisualizer.model.AnimSpeed; +import com.gauravk.audiovisualizer.model.PaintStyle; +import com.gauravk.audiovisualizer.model.PositionGravity; +import com.gauravk.audiovisualizer.utils.AVConstants; + +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.render.Canvas; +import ohos.agp.render.Path; +import ohos.agp.utils.Point; +import ohos.agp.utils.Rect; +import ohos.app.Context; + +import org.jetbrains.annotations.Nullable; + +import java.security.SecureRandom; +import java.util.Random; + +/** + * Custom view to create wave visualizer + *

+ * Created by gk + */ +public class WaveVisualizer extends BaseVisualizer implements Component.DrawTask { + private static final int WAVE_MAX_POINTS = 54; + private static final int WAVE_MIN_POINTS = 3; + + private int mMaxBatchCount; + + private Path mWavePath; + + private int nPoints; + + private Point[] mBezierPoints; + private Point[] mBezierControlPoints1; + private Point[] mBezierControlPoints2; + + private float[] mSrcY; + private float[] mDestY; + + private float mWidthOffset; + private Rect mClipBounds; + + private int nBatchCount; + + private SecureRandom mRandom = new SecureRandom(); + + /** + * 使用java代码实例化调用 + * + * @param context + */ + public WaveVisualizer(Context context) { + super(context); + } + + /** + * 使用xml布局引用调用 + * + * @param context + * @param attrs + */ + public WaveVisualizer(Context context, + @Nullable AttrSet attrs) { + super(context, attrs); + } + + @Override + protected void init() { + addDrawTask(this::onDraw); + nPoints = (int) (WAVE_MAX_POINTS * mDensity); + if (nPoints < WAVE_MIN_POINTS) { + nPoints = WAVE_MIN_POINTS; + } + + mWidthOffset = -1; + nBatchCount = 0; + + setAnimationSpeed(mAnimSpeed); + + mClipBounds = new Rect(); + + mWavePath = new Path(); + + mSrcY = new float[nPoints + 1]; + mDestY = new float[nPoints + 1]; + + // initialize mBezierPoints + mBezierPoints = new Point[nPoints + 1]; + mBezierControlPoints1 = new Point[nPoints + 1]; + mBezierControlPoints2 = new Point[nPoints + 1]; + for (int i = 0; i < mBezierPoints.length; i++) { + mBezierPoints[i] = new Point(); + mBezierControlPoints1[i] = new Point(); + mBezierControlPoints2[i] = new Point(); + } + } + + @Override + public void setAnimationSpeed(AnimSpeed animSpeed) { + super.setAnimationSpeed(animSpeed); + this.mMaxBatchCount = AVConstants.MAX_ANIM_BATCH_COUNT - mAnimSpeed.ordinal(); + } + + @Override + public void onDraw(Component component, Canvas canvas) { + if (mWidthOffset == -1) { + canvas.getLocalClipBounds(mClipBounds); + + mWidthOffset = component.getWidth() / nPoints; + + //initialize bezier points + for (int i = 0; i < mBezierPoints.length; i++) { + float posX = mClipBounds.left + (i * mWidthOffset); + + float posY; + if (mPositionGravity == PositionGravity.TOP) { + posY = mClipBounds.top; + } else { + posY = mClipBounds.bottom; + } + + mSrcY[i] = posY; + mDestY[i] = posY; + mBezierPoints[i].modify(posX, posY); + } + } + + // create the path and draw + if (isVisualizationEnabled && mRawAudioBytes != null) { + if (mRawAudioBytes.length == 0) { + return; + } + + mWavePath.rewind(); + + // find the destination bezier point for a batch + if (nBatchCount == 0) { + float randPosY = mDestY[mRandom.nextInt(nPoints)]; + for (int i = 0; i < mBezierPoints.length; i++) { + int x = (int) Math.ceil((i + 1) * (mRawAudioBytes.length / nPoints)); + + int t = 0; + if (x < 1024) { + t = component.getHeight() + + ((byte) (Math.abs(mRawAudioBytes[x]) + 128)) * component.getHeight() / 128; + } + + float posY; + if (mPositionGravity == PositionGravity.TOP) { + posY = mClipBounds.bottom - t; + } else { + posY = mClipBounds.top + t; + } + + //change the source and destination y + mSrcY[i] = mDestY[i]; + mDestY[i] = posY; + } + + mDestY[mBezierPoints.length - 1] = randPosY; + } + + // increment batch count + nBatchCount++; + + // for smoothing animation + for (int i = 0; i < mBezierPoints.length; i++) { + mBezierPoints[i].modify(mBezierPoints[i].getPointX(), mSrcY[i] + (((float) (nBatchCount) / mMaxBatchCount) * (mDestY[i] - mSrcY[i]))); + } + + // reset the batch count + if (nBatchCount == mMaxBatchCount) { + nBatchCount = 0; + } + + // calculate the bezier curve control points + for (int i = 1; i < mBezierPoints.length; i++) { + mBezierControlPoints1[i].modify((mBezierPoints[i].getPointX() + mBezierPoints[i - 1].getPointX()) / 2, mBezierPoints[i - 1].getPointY()); + mBezierControlPoints2[i].modify((mBezierPoints[i].getPointX() + mBezierPoints[i - 1].getPointX()) / 2, mBezierPoints[i].getPointY()); + } + + // create the path + mWavePath.moveTo(mBezierPoints[0].getPointX(), mBezierPoints[0].getPointY()); + for (int i = 1; i < mBezierPoints.length; i++) { + mWavePath.cubicTo(mBezierControlPoints1[i].getPointX(), mBezierControlPoints1[i].getPointY(), + mBezierControlPoints2[i].getPointX(), mBezierControlPoints2[i].getPointY(), + mBezierPoints[i].getPointX(), mBezierPoints[i].getPointY()); + } + + if (mPaintStyle == PaintStyle.FILL) { + mWavePath.lineTo(mClipBounds.right, mClipBounds.bottom); + mWavePath.lineTo(mClipBounds.left, mClipBounds.bottom); + mWavePath.close(); + } + canvas.drawPath(mWavePath, mPaint); + } + super.addDrawTask(this::onDraw); + } +} \ No newline at end of file diff --git a/AudioVisualizerOhos/audiovisualizer/src/main/resources/base/element/string.json b/AudioVisualizerOhos/audiovisualizer/src/main/resources/base/element/string.json new file mode 100644 index 0000000..87682f6 --- /dev/null +++ b/AudioVisualizerOhos/audiovisualizer/src/main/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "audiovisualizer" + } + ] +} diff --git a/AudioVisualizerOhos/build.gradle b/AudioVisualizerOhos/build.gradle new file mode 100644 index 0000000..da99825 --- /dev/null +++ b/AudioVisualizerOhos/build.gradle @@ -0,0 +1,46 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +apply plugin: 'com.huawei.ohos.app' + +ohos { + compileSdkVersion 5 + defaultConfig { + compatibleSdkVersion 5 + } +} + +buildscript { + repositories { + maven { + url 'https://mirrors.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + maven { + url 'http://106.15.92.248:8081/repository/Releases/' + } + jcenter() + } + dependencies { + classpath 'com.huawei.ohos:hap:2.4.2.7' + classpath 'com.huawei.ohos:decctest:1.0.0.6' + } +} + +allprojects { + repositories { + maven { + url 'https://mirrors.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + maven { + url 'http://106.15.92.248:8081/repository/Releases/' + } + repositories{ + mavenCentral() + } + jcenter() + } +} diff --git a/AudioVisualizerOhos/entry/.gitignore b/AudioVisualizerOhos/entry/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/AudioVisualizerOhos/entry/.gitignore @@ -0,0 +1 @@ +/build diff --git a/AudioVisualizerOhos/entry/build.gradle b/AudioVisualizerOhos/entry/build.gradle new file mode 100644 index 0000000..6674e0f --- /dev/null +++ b/AudioVisualizerOhos/entry/build.gradle @@ -0,0 +1,13 @@ +apply plugin: 'com.huawei.ohos.hap' +ohos { + compileSdkVersion 5 + defaultConfig { + compatibleSdkVersion 5 + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar', '*.har']) + implementation project(path: ':audiovisualizer') + testCompile 'junit:junit:4.12' +} diff --git a/AudioVisualizerOhos/entry/src/main/config.json b/AudioVisualizerOhos/entry/src/main/config.json new file mode 100644 index 0000000..3e71dc4 --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/config.json @@ -0,0 +1,209 @@ +{ + "app": { + "bundleName": "com.gauravk.audiovisualizersample", + "vendor": "github", + "version": { + "code": 1, + "name": "1.0" + }, + "apiVersion": { + "compatible": 5, + "target": 5 + } + }, + "deviceConfig": { + "default": { + "network": { + "cleartextTraffic": true + } + } + }, + "module": { + "package": "com.gauravk.audiovisualizersample", + "name": "com.gauravk.audiovisualizersample.MyApplication", + "deviceType": [ + "phone" + ], + "reqPermissions": [ + { + "name": "ohos.permission.MICROPHONE" + }, + { + "name": "ohos.permission.READ_MEDIA" + }, + { + "name": "ohos.permission.WRITE_MEDIA" + }, + { + "name": "ohos.permission.RECORD_AUDIO" + }, + { + "name": "ohos.permission.INTERNET" + }, + { + "name": "ohos.permission.GET_NETWORK_INFO" + } + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry" + }, + "abilities": [ + { + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "orientation": "unspecified", + "name": "com.gauravk.audiovisualizersample.MainAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "AudioVisualizerAndroid", + "type": "page", + "launchType": "standard", + "metaData": { + "customizeData": [ + { + "name": "hwc-theme", + "value": "androidhwext:style/Theme.Emui.NoTitleBar", + "extra": "" + } + ] + } + }, + { + "orientation": "unspecified", + "name": "com.gauravk.audiovisualizersample.ui.BarAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "visualizer", + "type": "page", + "launchType": "standard", + "metaData": { + "customizeData": [ + { + "name": "hwc-theme", + "value": "androidhwext:style/Theme.Emui.NoTitleBar", + "extra": "" + } + ] + } + }, + { + "orientation": "unspecified", + "name": "com.gauravk.audiovisualizersample.ui.BlastAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "visualizer", + "type": "page", + "launchType": "standard", + "metaData": { + "customizeData": [ + { + "name": "hwc-theme", + "value": "androidhwext:style/Theme.Emui.NoTitleBar", + "extra": "" + } + ] + } + }, + { + "orientation": "unspecified", + "name": "com.gauravk.audiovisualizersample.ui.CircleLineAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "visualizer", + "type": "page", + "launchType": "standard", + "metaData": { + "customizeData": [ + { + "name": "hwc-theme", + "value": "androidhwext:style/Theme.Emui.NoTitleBar", + "extra": "" + } + ] + } + }, + { + "orientation": "unspecified", + "name": "com.gauravk.audiovisualizersample.ui.HiFiAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "visualizer", + "type": "page", + "launchType": "standard", + "metaData": { + "customizeData": [ + { + "name": "hwc-theme", + "value": "androidhwext:style/Theme.Emui.NoTitleBar", + "extra": "" + } + ] + } + }, + { + "orientation": "unspecified", + "name": "com.gauravk.audiovisualizersample.ui.MusicStreamAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "visualizer", + "type": "page", + "launchType": "standard", + "metaData": { + "customizeData": [ + { + "name": "hwc-theme", + "value": "androidhwext:style/Theme.Emui.NoTitleBar", + "extra": "" + } + ] + } + }, + { + "orientation": "unspecified", + "name": "com.gauravk.audiovisualizersample.ui.WaveAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "visualizer", + "type": "page", + "launchType": "standard", + "metaData": { + "customizeData": [ + { + "name": "hwc-theme", + "value": "androidhwext:style/Theme.Emui.NoTitleBar", + "extra": "" + } + ] + } + }, + { + "orientation": "unspecified", + "name": "com.gauravk.audiovisualizersample.ui.BlobAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "visualizer", + "type": "page", + "launchType": "standard", + "metaData": { + "customizeData": [ + { + "name": "hwc-theme", + "value": "androidhwext:style/Theme.Emui.NoTitleBar", + "extra": "" + } + ] + } + } + ] + } +} \ No newline at end of file diff --git a/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/MainAbility.java b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/MainAbility.java new file mode 100644 index 0000000..b17955a --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/MainAbility.java @@ -0,0 +1,18 @@ +package com.gauravk.audiovisualizersample; + +import com.gauravk.audiovisualizersample.slice.MainAbilitySlice; + +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; +import ohos.agp.utils.Color; +import ohos.agp.window.service.WindowManager; + +public class MainAbility extends Ability { + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setMainRoute(MainAbilitySlice.class.getName()); + + WindowManager.getInstance().getTopWindow().get().setStatusBarColor(Color.rgb(66, 119, 208)); + } +} diff --git a/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/MyApplication.java b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/MyApplication.java new file mode 100644 index 0000000..e817211 --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/MyApplication.java @@ -0,0 +1,10 @@ +package com.gauravk.audiovisualizersample; + +import ohos.aafwk.ability.AbilityPackage; + +public class MyApplication extends AbilityPackage { + @Override + public void onInitialize() { + super.onInitialize(); + } +} diff --git a/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/slice/MainAbilitySlice.java b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/slice/MainAbilitySlice.java new file mode 100644 index 0000000..5614152 --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/slice/MainAbilitySlice.java @@ -0,0 +1,108 @@ +package com.gauravk.audiovisualizersample.slice; + +import com.gauravk.audiovisualizersample.ResourceTable; +import com.gauravk.audiovisualizersample.ui.*; +import com.gauravk.audiovisualizersample.util.PermissionUtils; +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; +import ohos.aafwk.content.Operation; +import ohos.agp.components.Component; +import ohos.bundle.IBundleManager; +import ohos.global.resource.RawFileDescriptor; +import ohos.media.common.Source; +import ohos.media.player.Player; + +import java.io.IOException; + +public class MainAbilitySlice extends AbilitySlice implements Component.ClickedListener { + + @Override + protected void onStart(Intent intent) { + super.onStart(intent); + + super.setUIContent(ResourceTable.Layout_ability_main); + initReqPermissions(); + initView(); + } + + private void initView() { + findComponentById(ResourceTable.Id_bt_main_blob).setClickedListener(this); + findComponentById(ResourceTable.Id_bt_main_blast).setClickedListener(this); + findComponentById(ResourceTable.Id_bt_main_wave).setClickedListener(this); + findComponentById(ResourceTable.Id_bt_main_bar).setClickedListener(this); + findComponentById(ResourceTable.Id_bt_main_stream).setClickedListener(this); + findComponentById(ResourceTable.Id_bt_main_circle_line).setClickedListener(this); + findComponentById(ResourceTable.Id_bt_main_hifi).setClickedListener(this); + } + + @Override + protected void onActive() { + super.onActive(); + try { + RawFileDescriptor filDescriptor = getResourceManager().getRawFileEntry("resources/rawfile/sample.aac").openRawFileDescriptor(); + Source source = new Source(filDescriptor.getFileDescriptor()); + Player impl = new Player(this); + impl.setSource(source); + impl.prepare(); + impl.play(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void onClick(Component component) { + switch (component.getId()) { + case ResourceTable.Id_bt_main_blob: + nextPage(BlobAbility.class.getName()); + break; + case ResourceTable.Id_bt_main_blast: + nextPage(BlastAbility.class.getName()); + break; + case ResourceTable.Id_bt_main_wave: + nextPage(WaveAbility.class.getName()); + break; + case ResourceTable.Id_bt_main_bar: + nextPage(BarAbility.class.getName()); + break; + case ResourceTable.Id_bt_main_stream: + nextPage(MusicStreamAbility.class.getName()); + break; + case ResourceTable.Id_bt_main_circle_line: + nextPage(CircleLineAbility.class.getName()); + break; + case ResourceTable.Id_bt_main_hifi: + nextPage(HiFiAbility.class.getName()); + break; + default: + break; + } + } + + public void nextPage(String abilityName) { + Intent intent = new Intent(); + Operation build = new Intent.OperationBuilder() + .withBundleName(getBundleName()) + .withAbilityName(abilityName) + .build(); + intent.setOperation(build); + startAbility(intent); + } + + private void initReqPermissions() { + if (verifySelfPermission(PermissionUtils.MICROPHONE) != IBundleManager.PERMISSION_GRANTED + || verifySelfPermission(PermissionUtils.READ_MEDIA) != IBundleManager.PERMISSION_GRANTED + || verifySelfPermission(PermissionUtils.WRITE_MEDIA) != IBundleManager.PERMISSION_GRANTED + || verifySelfPermission(PermissionUtils.RECORD_AUDIO) != IBundleManager.PERMISSION_GRANTED + ) { + if (canRequestPermission(PermissionUtils.MICROPHONE) + || canRequestPermission(PermissionUtils.READ_MEDIA) + || canRequestPermission(PermissionUtils.WRITE_MEDIA) + || canRequestPermission(PermissionUtils.RECORD_AUDIO)) { + requestPermissionsFromUser( + PermissionUtils.permission, PermissionUtils.PERMISSION_CODE); + } + } + } + +} diff --git a/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/BarAbility.java b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/BarAbility.java new file mode 100644 index 0000000..292d6ef --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/BarAbility.java @@ -0,0 +1,69 @@ +/* + Copyright 2018 Gaurav Kumar + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.gauravk.audiovisualizersample.ui; + +import com.gauravk.audiovisualizer.visualizer.BarVisualizer; +import com.gauravk.audiovisualizersample.ResourceTable; +import com.gauravk.audiovisualizersample.util.MusicFinish; +import com.gauravk.audiovisualizersample.util.PlaySoundUtil; +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; +import ohos.agp.components.Component; +import ohos.agp.utils.Color; +import ohos.agp.window.service.WindowManager; +import ohos.media.audio.*; + +public class BarAbility extends Ability { + private BarVisualizer mVisualizer; + private PlaySoundUtil playSoundUtil; + + @Override + protected void onStart(Intent intent) { + super.onStart(intent); + setUIContent(ResourceTable.Layout_activity_bar); + + WindowManager.getInstance().getTopWindow().get().setStatusBarColor(Color.rgb(66, 119, 208)); + + playSoundUtil = new PlaySoundUtil(); + mVisualizer = (BarVisualizer) findComponentById(ResourceTable.Id_bar); + mVisualizer.setAudioSessionId(playSoundUtil.getAudioRenderer().getRendererSessionId()); + new Thread(new Runnable() { + @Override + public void run() { + if (playSoundUtil.getAudioRenderer().getState() != AudioRenderer.State.STATE_PLAYING) { + playSoundUtil.loadSound("Ring10.wav", new MusicFinish() { + @Override + public void finish() { + getUITaskDispatcher().syncDispatch(new Runnable() { + @Override + public void run() { + mVisualizer.setVisibility(Component.HIDE); + } + }); + } + }); + } + } + }).start(); + } + + @Override + protected void onStop() { + super.onStop(); + playSoundUtil.getAudioRenderer().stop(); + } +} diff --git a/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/BlastAbility.java b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/BlastAbility.java new file mode 100644 index 0000000..5e0c0ed --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/BlastAbility.java @@ -0,0 +1,70 @@ +/* + Copyright 2018 Gaurav Kumar + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.gauravk.audiovisualizersample.ui; + +import com.gauravk.audiovisualizer.visualizer.BlastVisualizer; +import com.gauravk.audiovisualizersample.ResourceTable; +import com.gauravk.audiovisualizersample.util.MusicFinish; +import com.gauravk.audiovisualizersample.util.PlaySoundUtil; + +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; +import ohos.agp.components.Component; +import ohos.agp.utils.Color; +import ohos.agp.window.service.WindowManager; +import ohos.media.audio.AudioRenderer; + +public class BlastAbility extends Ability { + private BlastVisualizer mVisualizer; + private PlaySoundUtil playSoundUtil; + + @Override + protected void onStart(Intent intent) { + super.onStart(intent); + setUIContent(ResourceTable.Layout_activity_blast); + + WindowManager.getInstance().getTopWindow().get().setStatusBarColor(Color.rgb(66, 119, 208)); + + playSoundUtil = new PlaySoundUtil(); + mVisualizer = (BlastVisualizer) findComponentById(ResourceTable.Id_blast); + mVisualizer.setAudioSessionId(playSoundUtil.getAudioRenderer().getRendererSessionId()); + new Thread(new Runnable() { + @Override + public void run() { + if (playSoundUtil.getAudioRenderer().getState() != AudioRenderer.State.STATE_PLAYING) { + playSoundUtil.loadSound("Ring10.wav", new MusicFinish() { + @Override + public void finish() { + getUITaskDispatcher().syncDispatch(new Runnable() { + @Override + public void run() { + mVisualizer.setVisibility(Component.HIDE); + } + }); + } + }); + } + } + }).start(); + } + + @Override + protected void onStop() { + super.onStop(); + playSoundUtil.getAudioRenderer().stop(); + } +} diff --git a/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/BlobAbility.java b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/BlobAbility.java new file mode 100644 index 0000000..848e8e9 --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/BlobAbility.java @@ -0,0 +1,70 @@ +/* + Copyright 2018 Gaurav Kumar + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.gauravk.audiovisualizersample.ui; + +import com.gauravk.audiovisualizer.visualizer.BlobVisualizer; +import com.gauravk.audiovisualizersample.ResourceTable; +import com.gauravk.audiovisualizersample.util.MusicFinish; +import com.gauravk.audiovisualizersample.util.PlaySoundUtil; + +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; +import ohos.agp.components.Component; +import ohos.agp.utils.Color; +import ohos.agp.window.service.WindowManager; +import ohos.media.audio.AudioRenderer; + +public class BlobAbility extends Ability { + private BlobVisualizer mVisualizer; + private PlaySoundUtil playSoundUtil; + + @Override + protected void onStart(Intent intent) { + super.onStart(intent); + setUIContent(ResourceTable.Layout_activity_blob); + + WindowManager.getInstance().getTopWindow().get().setStatusBarColor(Color.rgb(66, 119, 208)); + + playSoundUtil = new PlaySoundUtil(); + mVisualizer = (BlobVisualizer) findComponentById(ResourceTable.Id_blob); + mVisualizer.setAudioSessionId(playSoundUtil.getAudioRenderer().getRendererSessionId()); + new Thread(new Runnable() { + @Override + public void run() { + if (playSoundUtil.getAudioRenderer().getState() != AudioRenderer.State.STATE_PLAYING) { + playSoundUtil.loadSound("Ring10.wav", new MusicFinish() { + @Override + public void finish() { + getUITaskDispatcher().syncDispatch(new Runnable() { + @Override + public void run() { + mVisualizer.setVisibility(Component.HIDE); + } + }); + } + }); + } + } + }).start(); + } + + @Override + protected void onStop() { + super.onStop(); + playSoundUtil.getAudioRenderer().stop(); + } +} \ No newline at end of file diff --git a/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/CircleLineAbility.java b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/CircleLineAbility.java new file mode 100644 index 0000000..1df6f82 --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/CircleLineAbility.java @@ -0,0 +1,48 @@ +package com.gauravk.audiovisualizersample.ui; + +import com.gauravk.audiovisualizer.visualizer.CircleLineVisualizer; +import com.gauravk.audiovisualizersample.ResourceTable; +import com.gauravk.audiovisualizersample.util.MusicFinish; +import com.gauravk.audiovisualizersample.util.PlaySoundUtil; +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; +import ohos.agp.utils.Color; +import ohos.agp.window.service.WindowManager; +import ohos.media.audio.AudioRenderer; + +public class CircleLineAbility extends Ability { + private CircleLineVisualizer mVisualizer; + private PlaySoundUtil playSoundUtil; + + @Override + protected void onStart(Intent intent) { + super.onStart(intent); + setUIContent(ResourceTable.Layout_activity_circle_line); + + WindowManager.getInstance().getTopWindow().get().setStatusBarColor(Color.rgb(66, 119, 208)); + + playSoundUtil = new PlaySoundUtil(); + mVisualizer = (CircleLineVisualizer) findComponentById(ResourceTable.Id_circle); + mVisualizer.setAudioSessionId(playSoundUtil.getAudioRenderer().getRendererSessionId()); + mVisualizer.setDrawLine(true); + new Thread(new Runnable() { + @Override + public void run() { + if (playSoundUtil.getAudioRenderer().getState() != AudioRenderer.State.STATE_PLAYING) { + playSoundUtil.loadSound("Ring10.wav", new MusicFinish() { + @Override + public void finish() { + mVisualizer.setVisualizationEnabled(false); + } + }); + } + } + }).start(); + } + + @Override + protected void onStop() { + super.onStop(); + playSoundUtil.getAudioRenderer().stop(); + } +} diff --git a/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/HiFiAbility.java b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/HiFiAbility.java new file mode 100644 index 0000000..9321524 --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/HiFiAbility.java @@ -0,0 +1,48 @@ +package com.gauravk.audiovisualizersample.ui; + +import com.gauravk.audiovisualizer.visualizer.HiFiVisualizer; +import com.gauravk.audiovisualizersample.ResourceTable; +import com.gauravk.audiovisualizersample.util.MusicFinish; +import com.gauravk.audiovisualizersample.util.PlaySoundUtil; +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; +import ohos.agp.components.Component; +import ohos.agp.utils.Color; +import ohos.agp.window.service.WindowManager; +import ohos.media.audio.AudioRenderer; + +public class HiFiAbility extends Ability { + private HiFiVisualizer mVisualizer; + private PlaySoundUtil playSoundUtil; + + @Override + protected void onStart(Intent intent) { + super.onStart(intent); + setUIContent(ResourceTable.Layout_activity_hi_fi); + + WindowManager.getInstance().getTopWindow().get().setStatusBarColor(Color.rgb(66, 119, 208)); + + playSoundUtil = new PlaySoundUtil(); + mVisualizer = (HiFiVisualizer) findComponentById(ResourceTable.Id_hifi); + mVisualizer.setAudioSessionId(playSoundUtil.getAudioRenderer().getRendererSessionId()); + new Thread(new Runnable() { + @Override + public void run() { + if (playSoundUtil.getAudioRenderer().getState() != AudioRenderer.State.STATE_PLAYING) { + playSoundUtil.loadSound("Ring10.wav", new MusicFinish() { + @Override + public void finish() { + mVisualizer.setVisualizationEnabled(false); + } + }); + } + } + }).start(); + } + + @Override + protected void onStop() { + super.onStop(); + playSoundUtil.getAudioRenderer().stop(); + } +} diff --git a/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/MusicStreamAbility.java b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/MusicStreamAbility.java new file mode 100644 index 0000000..292611d --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/MusicStreamAbility.java @@ -0,0 +1,118 @@ +package com.gauravk.audiovisualizersample.ui; + +import com.gauravk.audiovisualizer.visualizer.BlastVisualizer; +import com.gauravk.audiovisualizersample.ResourceTable; + +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; +import ohos.agp.components.*; +import ohos.agp.utils.Color; +import ohos.agp.utils.LayoutAlignment; +import ohos.agp.window.dialog.CommonDialog; +import ohos.agp.window.service.DisplayManager; +import ohos.agp.window.service.WindowManager; +import ohos.media.audio.AudioManager; +import ohos.media.common.Source; +import ohos.media.player.Player; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Timer; +import java.util.TimerTask; + +public class MusicStreamAbility extends Ability { + private Image imgButton; + private BlastVisualizer mVisualizer; + private Player player = new Player(MusicStreamAbility.this); + private String stream = "http://stream.radioreklama.bg/radio1rock128"; + private int progress = 0; + private Timer timer; + private CommonDialog toastDialog; + + @Override + protected void onStart(Intent intent) { + super.onStart(intent); + setUIContent(ResourceTable.Layout_activity_music_stream); + + WindowManager.getInstance().getTopWindow().get().setStatusBarColor(Color.rgb(66, 119, 208)); + + mVisualizer = (BlastVisualizer) findComponentById(ResourceTable.Id_blast); + imgButton = (Image) findComponentById(ResourceTable.Id_playbtn); + imgButton.setPixelMap(ResourceTable.Media_play); + mVisualizer.setAudioSessionId(AudioManager.makeSessionId()); + imgButton.setClickedListener(new Component.ClickedListener() { + @Override + public void onClick(Component component) { + if (player.isNowPlaying()) { + player.pause(); + imgButton.setPixelMap(ResourceTable.Media_play); + } else { + player.play(); + imgButton.setPixelMap(ResourceTable.Media_stop); + } + } + }); + openDialog(); + openNet(); + } + + private void openDialog() { + Component component = LayoutScatter.getInstance(this).parse(ResourceTable.Layout_progress_layout, null, false); + RoundProgressBar bar = (RoundProgressBar) component.findComponentById(ResourceTable.Id_bar); + timer = new Timer(); + timer.schedule(new TimerTask() { + @Override + public void run() { + bar.setProgressValue(progress); + progress += 10; + if (progress == 100) { + progress = 0; + } + } + }, 0, 100); + toastDialog = new CommonDialog(this); + toastDialog.setContentCustomComponent(component); + toastDialog.setAutoClosable(true); + toastDialog.setSize(DisplayManager.getInstance().getDefaultDisplay(this).get().getAttributes().width / 7 * 6, + DirectionalLayout.LayoutConfig.MATCH_CONTENT); + toastDialog.setAlignment(LayoutAlignment.CENTER); + toastDialog.show(); + } + + @Override + protected void onStop() { + super.onStop(); + player.stop(); + } + + private void openNet() { + new Thread(new Runnable() { + @Override + public void run() { + InputStream inputStream = null; + try { + URL url = new URL(stream); + HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); + inputStream = urlConnection.getInputStream(); + Source source = new Source(stream); + player.setSource(source); + player.prepare(); + timer.cancel(); + toastDialog.remove(); + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + }).start(); + } +} diff --git a/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/WaveAbility.java b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/WaveAbility.java new file mode 100644 index 0000000..8cb542e --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/ui/WaveAbility.java @@ -0,0 +1,70 @@ +/* + Copyright 2018 Gaurav Kumar + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.gauravk.audiovisualizersample.ui; + +import com.gauravk.audiovisualizer.visualizer.WaveVisualizer; +import com.gauravk.audiovisualizersample.ResourceTable; +import com.gauravk.audiovisualizersample.util.MusicFinish; +import com.gauravk.audiovisualizersample.util.PlaySoundUtil; + +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; +import ohos.agp.components.Component; +import ohos.agp.utils.Color; +import ohos.agp.window.service.WindowManager; +import ohos.media.audio.AudioRenderer; + +public class WaveAbility extends Ability { + private WaveVisualizer mVisualizer; + private PlaySoundUtil playSoundUtil; + + @Override + protected void onStart(Intent intent) { + super.onStart(intent); + setUIContent(ResourceTable.Layout_activity_wave); + + WindowManager.getInstance().getTopWindow().get().setStatusBarColor(Color.rgb(66, 119, 208)); + + playSoundUtil = new PlaySoundUtil(); + mVisualizer = (WaveVisualizer) findComponentById(ResourceTable.Id_wave); + mVisualizer.setAudioSessionId(playSoundUtil.getAudioRenderer().getRendererSessionId()); + new Thread(new Runnable() { + @Override + public void run() { + if (playSoundUtil.getAudioRenderer().getState() != AudioRenderer.State.STATE_PLAYING) { + playSoundUtil.loadSound("Ring10.wav", new MusicFinish() { + @Override + public void finish() { + getUITaskDispatcher().syncDispatch(new Runnable() { + @Override + public void run() { + mVisualizer.setVisibility(Component.HIDE); + } + }); + } + }); + } + } + }).start(); + } + + @Override + protected void onStop() { + super.onStop(); + playSoundUtil.getAudioRenderer().stop(); + } +} diff --git a/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/util/MusicFinish.java b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/util/MusicFinish.java new file mode 100644 index 0000000..73ec2e2 --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/util/MusicFinish.java @@ -0,0 +1,8 @@ +package com.gauravk.audiovisualizersample.util; + +public interface MusicFinish { + /** + * 播放音频结束回调 + */ + void finish(); +} diff --git a/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/util/PermissionUtils.java b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/util/PermissionUtils.java new file mode 100644 index 0000000..9c9c091 --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/util/PermissionUtils.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2021 The Chinese Software International Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.gauravk.audiovisualizersample.util; + +/** + * PermissionUtils + * + * @since 2021-03-27 + */ +public class PermissionUtils { + /** + * 麦克风权限 + */ + public static final String MICROPHONE = "ohos.permission.MICROPHONE"; + /** + * 读取媒体资源权限 + */ + public static final String READ_MEDIA = "ohos.permission.READ_MEDIA"; + /** + * 写入媒体资源权限 + */ + public static final String WRITE_MEDIA = "ohos.permission.WRITE_MEDIA"; + /** + * 重置权限 + */ + public static final String RECORD_AUDIO = "ohos.permission.RECORD_AUDIO"; + + /** + * 权限号 + */ + public static final int PERMISSION_CODE = 0X000000; + /** + * 权限数组 + */ + public static String[] permission = {MICROPHONE, READ_MEDIA, WRITE_MEDIA,RECORD_AUDIO}; +} \ No newline at end of file diff --git a/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/util/PlaySoundUtil.java b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/util/PlaySoundUtil.java new file mode 100644 index 0000000..a3084ea --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/java/com/gauravk/audiovisualizersample/util/PlaySoundUtil.java @@ -0,0 +1,65 @@ +package com.gauravk.audiovisualizersample.util; + +import ohos.media.audio.*; + +import java.io.InputStream; + +public class PlaySoundUtil { + private final int SAMPLE_RATE = 192000; + private AudioStreamInfo audioStreamInfo = null; + private AudioRendererInfo audioRendererInfo = null; + private AudioRenderer.PlayMode playMode = AudioRenderer.PlayMode.MODE_STREAM; + private AudioRenderer audioRenderer = null; + private InputStream soundInputStream = null; + + /** + * PlaySoundUtil构造方法 初始化音频播放器 + */ + public PlaySoundUtil() { + audioStreamInfo = new AudioStreamInfo.Builder().sampleRate(44100) // 44.1kHz + .audioStreamFlag(AudioStreamInfo.AudioStreamFlag.AUDIO_STREAM_FLAG_MAY_DUCK) // 混音 + .encodingFormat(AudioStreamInfo.EncodingFormat.ENCODING_PCM_16BIT) // 16-bit PCM + .channelMask(AudioStreamInfo.ChannelMask.CHANNEL_OUT_DEFAULT) // 双声道输出 + .streamUsage(AudioStreamInfo.StreamUsage.STREAM_USAGE_MEDIA) // 媒体类音频 + .build(); + + audioRendererInfo = new AudioRendererInfo.Builder().audioStreamInfo(audioStreamInfo) + .audioStreamOutputFlag( + AudioRendererInfo.AudioStreamOutputFlag.AUDIO_STREAM_OUTPUT_FLAG_DIRECT_PCM) // pcm格式的输出流 + .bufferSizeInBytes(1024) + .isOffload(false) // false表示分段传输buffer并播放,true表示整个音频流一次性传输到HAL层播放 + .build(); + audioRenderer = new AudioRenderer(audioRendererInfo, playMode); + } + + /** + * 加载本地音频资源 + * + * @param fileName + * @param musicFinish + */ + public void loadSound(String fileName, MusicFinish musicFinish) { + String filePath = String.format("assets/entry/resources/rawfile/%s", fileName); + soundInputStream = this.getClass().getClassLoader().getResourceAsStream(filePath); + + byte[] buffer = new byte[1024]; + int len; + try { + audioRenderer.start(); + while ((len = soundInputStream.read(buffer, 0, buffer.length)) != -1) { + audioRenderer.write(buffer, 0, buffer.length); + } + soundInputStream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + if (audioRenderer.getState() == AudioRenderer.State.STATE_PLAYING) { + audioRenderer.pause(); + } + musicFinish.finish(); + } + + public AudioRenderer getAudioRenderer() { + return this.audioRenderer; + } +} diff --git a/AudioVisualizerOhos/entry/src/main/resources/base/element/color.json b/AudioVisualizerOhos/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000..edcde0c --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/resources/base/element/color.json @@ -0,0 +1,46 @@ +{ + "color": [ + { + "name": "colorPrimary", + "value": "#E6000000" + }, + { + "name": "colorMainBtBgEmty", + "value": "#D6D7D7" + }, + { + "name": "colorListDividerPressed", + "value": "#C2C4C4" + }, + { + "name": "colorListHeadBackground", + "value": "#77787b" + }, + { + "name": "white", + "value": "#ffffff" + }, + { + "name": "colorPrimaryDark", + "value": "#303F9F" + }, + { + "name": "colorAccent", + "value": "#FF4081" + }, + { + "name": "black", + "value": "#000000" + }, + { + "name": "green", + "value": "#45b97c" + }, + { + "name": "brown", + "value": "#843900" + } + + + ] +} \ No newline at end of file diff --git a/AudioVisualizerOhos/entry/src/main/resources/base/element/string.json b/AudioVisualizerOhos/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000..4903083 --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/resources/base/element/string.json @@ -0,0 +1,24 @@ +{ + "string": [ + { + "name": "app_name", + "value": "AudioVisualizerAndroid" + }, + { + "name": "mainability_description", + "value": "Java_Phone_Empty Feature Ability" + }, + { + "name": "HelloWorld", + "value": "Hello World" + }, + { + "name": "testability_description", + "value": "Java_Phone_Empty Feature Ability" + }, + { + "name": "HelloWorld", + "value": "Hello World" + } + ] +} \ No newline at end of file diff --git a/AudioVisualizerOhos/entry/src/main/resources/base/graphic/background_ability_main.xml b/AudioVisualizerOhos/entry/src/main/resources/base/graphic/background_ability_main.xml new file mode 100644 index 0000000..c0c0a3d --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/resources/base/graphic/background_ability_main.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/AudioVisualizerOhos/entry/src/main/resources/base/graphic/main_bt_bg.xml b/AudioVisualizerOhos/entry/src/main/resources/base/graphic/main_bt_bg.xml new file mode 100644 index 0000000..cb835d6 --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/resources/base/graphic/main_bt_bg.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/AudioVisualizerOhos/entry/src/main/resources/base/layout/ability_main.xml b/AudioVisualizerOhos/entry/src/main/resources/base/layout/ability_main.xml new file mode 100644 index 0000000..e484739 --- /dev/null +++ b/AudioVisualizerOhos/entry/src/main/resources/base/layout/ability_main.xml @@ -0,0 +1,129 @@ + + + + + +