adarshadda commited on
Commit
b0dd51d
1 Parent(s): d3fbd97

initial commit

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. Dockerfile +43 -0
  2. LICENSE +201 -0
  3. app/.DS_Store +0 -0
  4. app/__pycache__/app.cpython-311.pyc +0 -0
  5. app/__pycache__/emotion_data.cpython-311.pyc +0 -0
  6. app/app.py +148 -0
  7. app/emotion_data.py +170 -0
  8. app/modules/.DS_Store +0 -0
  9. app/modules/__init__.py +34 -0
  10. app/modules/__pycache__/__init__.cpython-310.pyc +0 -0
  11. app/modules/__pycache__/__init__.cpython-311.pyc +0 -0
  12. app/modules/__pycache__/__init__.cpython-312.pyc +0 -0
  13. app/modules/__pycache__/__init__.cpython-38.pyc +0 -0
  14. app/modules/__pycache__/__init__.cpython-39.pyc +0 -0
  15. app/modules/__pycache__/utils.cpython-310(1).pyc +0 -0
  16. app/modules/__pycache__/utils.cpython-310.pyc +0 -0
  17. app/modules/__pycache__/utils.cpython-311.pyc +0 -0
  18. app/modules/__pycache__/utils.cpython-312.pyc +0 -0
  19. app/modules/__pycache__/utils.cpython-38.pyc +0 -0
  20. app/modules/__pycache__/utils.cpython-39.pyc +0 -0
  21. app/modules/audio/__init__.py +18 -0
  22. app/modules/audio/__pycache__/__init__.cpython-38.pyc +0 -0
  23. app/modules/emotion/__init__.py +24 -0
  24. app/modules/emotion/__pycache__/__init__.cpython-310.pyc +0 -0
  25. app/modules/emotion/__pycache__/__init__.cpython-311.pyc +0 -0
  26. app/modules/emotion/__pycache__/__init__.cpython-312.pyc +0 -0
  27. app/modules/emotion/__pycache__/__init__.cpython-38.pyc +0 -0
  28. app/modules/emotion/__pycache__/__init__.cpython-39.pyc +0 -0
  29. app/modules/transcription/__init__.py +30 -0
  30. app/modules/transcription/__pycache__/__init__.cpython-311.pyc +0 -0
  31. app/modules/transcription/__pycache__/__init__.cpython-312.pyc +0 -0
  32. app/modules/transcription/__pycache__/__init__.cpython-38.pyc +0 -0
  33. app/modules/utils.py +20 -0
  34. app/static/audio_main.js +159 -0
  35. app/static/audio_to_text.css +135 -0
  36. app/static/audiodisplay.js +19 -0
  37. app/static/dem.css +53 -0
  38. app/static/demo.css +40 -0
  39. app/static/distract.js +165 -0
  40. app/static/distractandchange.css +29 -0
  41. app/static/energy.js +163 -0
  42. app/static/engage.js +165 -0
  43. app/static/footer.js +8 -0
  44. app/static/footer_file.css +48 -0
  45. app/static/header.js +8 -0
  46. app/static/header_file.css +77 -0
  47. app/static/login.css +39 -0
  48. app/static/main.css +109 -0
  49. app/static/main.js +202 -0
  50. app/static/recorder.js +99 -0
Dockerfile ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.8.10-slim
2
+
3
+ RUN export DEBIAN_FRONTEND=noninteractive \
4
+ && apt-get -qq update \
5
+ && apt install software-properties-common -y \
6
+ && apt-get install build-essential -y \
7
+ && python3 --version \
8
+ && apt update \
9
+ && apt install ffmpeg -y \
10
+ && rm -rf /var/lib/apt/lists/* \
11
+ && apt update \
12
+ && apt install nginx -y
13
+
14
+ ### Set up user with permissions
15
+ # Set up a new user named "user" with user ID 1000
16
+ RUN useradd -m -u 1000 user
17
+
18
+ # Switch to the "user" user
19
+ USER user
20
+
21
+ # Set home to the user's home directory
22
+ ENV HOME=/home/user \
23
+ PATH=/home/user/.local/bin:$PATH
24
+
25
+ # Set the working directory to the user's home directory
26
+ WORKDIR $HOME/app
27
+
28
+ ### Set up app-specific content
29
+ COPY requirements.txt requirements.txt
30
+ RUN pip3 install -r requirements.txt
31
+ RUN pip3 install gunicorn
32
+
33
+ # Copy the current directory contents into the container at $HOME/app setting the owner to the user
34
+ COPY --chown=user app $HOME/app
35
+
36
+ ### Update permissions for the app
37
+ USER root
38
+ RUN chmod 755 ~/app/*
39
+ USER user
40
+
41
+ # RUN python3 server.py
42
+ ENTRYPOINT ["python3", "app.py"]
43
+ # ENTRYPOINT ["gunicorn", "--timeout 600", "wsgi:app"]
LICENSE ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
app/.DS_Store ADDED
Binary file (6.15 kB). View file
 
app/__pycache__/app.cpython-311.pyc ADDED
Binary file (7 kB). View file
 
app/__pycache__/emotion_data.cpython-311.pyc ADDED
Binary file (4.89 kB). View file
 
app/app.py ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import uuid
3
+ import logging
4
+ from flask import Flask, flash, render_template, request, jsonify, url_for
5
+ from flask.templating import TemplateNotFound
6
+ from flask_cors import CORS
7
+ #from modules import Module
8
+
9
+ #model = Module()
10
+
11
+
12
+ app = Flask(__name__)
13
+ CORS(app)
14
+
15
+ app.secret_key = "Testing"
16
+ app.config['STATIC_FOLDER'] = 'static'
17
+
18
+ emotion_categories = {
19
+ "admiration": "soothieanduplift",
20
+ "amusement": "soothieanduplift",
21
+ "anger": "distractandchange",
22
+ "annoyance": "distractandchange",
23
+ "approval": "soothieanduplift",
24
+ "caring": "soothieanduplift",
25
+ "confusion": "engageandexplore",
26
+ "curiosity": "engageandexplore",
27
+ "desire": "engageandexplore",
28
+ "disappointment": "reflectiveandunderstand",
29
+ "disapproval": "distractandchange",
30
+ "disgust": "distractandchange",
31
+ "embarrassment": "distractandchange",
32
+ "excitement": "energeticandmotivate",
33
+ "fear": "distractandchange",
34
+ "gratitude": "soothieanduplift",
35
+ "grief": "reflectiveandunderstand",
36
+ "joy": "energeticandmotivate",
37
+ "love": "soothieanduplift",
38
+ "nervousness": "distractandchange",
39
+ "optimism": "energeticandmotivate",
40
+ "pride": "energeticandmotivate",
41
+ "realization": "engageandexplore",
42
+ "relief": "soothieanduplift",
43
+ "remorse": "reflectiveandunderstand",
44
+ "sadness": "reflectiveandunderstand",
45
+ "surprise": "engageandexplore",
46
+ "neutral": "soothieanduplift"
47
+ }
48
+
49
+ @app.route('/')
50
+ def index():
51
+ return render_template('index.html')
52
+
53
+ @app.route('/audio_to_text/')
54
+ def audio_to_text():
55
+ return render_template('audio_to_text.html')
56
+
57
+ @app.route('/audio', methods=['POST', 'GET'])
58
+ def audio():
59
+ if request.method == 'POST':
60
+ try:
61
+ output_file = f"./tmp/{uuid.uuid4()}.wav"
62
+ open(output_file, 'wb').write(request.data)
63
+ text, emotion = model.predict(audio_path=output_file)
64
+ os.remove(output_file)
65
+
66
+ predicted_category = emotion_categories.get(emotion, "defaultcategory")
67
+ return jsonify({
68
+ "url": url_for(predicted_category, text=text, emotion=emotion)
69
+ })
70
+ print("Predicted Category:", predicted_category) # Print predicted category
71
+ print("Text:", text) # Print predicted text
72
+ print("Emotion:", emotion) # Print predicted emotion
73
+ logging.info("Predicted Category: %s", predicted_category)
74
+ logging.info("Text: %s", text)
75
+ logging.info("Emotion: %s", emotion)
76
+ return jsonify({"url": url_for(predicted_category)})
77
+
78
+ except (FileNotFoundError, TemplateNotFound) as e:
79
+ logging.error(e)
80
+ return jsonify({"error": "Template file not found."}), 404
81
+
82
+ except Exception as e:
83
+ logging.error(e)
84
+ return jsonify({"error": "An error occurred"}), 500
85
+
86
+ elif request.method == 'GET':
87
+ return jsonify({"message": "This route only accepts POST requests."}), 405
88
+
89
+
90
+ @app.route('/reflectiveandunderstand', methods=['GET'])
91
+ def reflectiveandunderstand():
92
+ text = request.args.get('text', '') # Get predicted text
93
+ emotion = request.args.get('emotion', '') # Get predicted emotion
94
+ if emotion in emotion_data:
95
+ emotionInfo = emotion_data[emotion]
96
+ return render_template('reflectiveandunderstand.html', text=text, emotion=emotion, emotionInfo=emotionInfo)
97
+ else:
98
+ return jsonify({"error": "Emotion not found"}), 404
99
+
100
+ @app.route('/distractandchange', methods=['GET'])
101
+ def distractandchange():
102
+ text = request.args.get('text', '') # Get predicted text
103
+ emotion = request.args.get('emotion', '') # Get predicted emotion
104
+ if emotion in emotion_data:
105
+ emotionInfo = emotion_data[emotion]
106
+ return render_template('distractandchange.html', text=text, emotion=emotion, emotionInfo=emotionInfo)
107
+ else:
108
+ return jsonify({"error": "Emotion not found"}), [email protected]('/energeticandmotivate', methods=['GET'])
109
+
110
+ def energeticandmotivate():
111
+ text = request.args.get('text', '') # Get predicted text
112
+ emotion = request.args.get('emotion', '') # Get predicted emotion
113
+ if emotion in emotion_data:
114
+ emotionInfo = emotion_data[emotion]
115
+ return render_template('energeticandmotivate.html', text=text, emotion=emotion, emotionInfo=emotionInfo)
116
+ else:
117
+ return jsonify({"error": "Emotion not found"}), [email protected]('/energeticandmotivate', methods=['GET'])
118
+
119
+ @app.route('/engageandexplore', methods=['GET'])
120
+ def engageandexplore():
121
+ text = request.args.get('text', '') # Get predicted text
122
+ emotion = request.args.get('emotion', '') # Get predicted emotion
123
+ if emotion in emotion_data:
124
+ emotionInfo = emotion_data[emotion]
125
+ return render_template('engageandexplore.html', text=text, emotion=emotion, emotionInfo=emotionInfo)
126
+ else:
127
+ return jsonify({"error": "Emotion not found"}), [email protected]('/energeticandmotivate', methods=['GET'])
128
+
129
+ # Add more routes as needed, mirroring your category names
130
+ @app.route('/soothieanduplift', methods=['GET'])
131
+ def soothieanduplift():
132
+ text = request.args.get('text', '') # Get predicted text
133
+ emotion = request.args.get('emotion', '') # Get predicted emotion
134
+ if emotion in emotion_data:
135
+ emotionInfo = emotion_data[emotion]
136
+ return render_template('soothieanduplift.html', text=text, emotion=emotion, emotionInfo=emotionInfo)
137
+ else:
138
+ return jsonify({"error": "Emotion not found"}), [email protected]('/energeticandmotivate', methods=['GET'])
139
+
140
+ # Add more routes as needed, mirroring your category names
141
+
142
+
143
+
144
+ if __name__ == "__main__":
145
+ # Configure logging for Hugging Face environment
146
+ logging.basicConfig(level=logging.DEBUG)
147
+
148
+ app.run(debug=True, port=7860, host='0.0.0.0')
app/emotion_data.py ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ emotion_data = {
2
+ "admiration": {
3
+ 'heading': "Time to appreciate the beauty around you!",
4
+ 'info': "We've picked songs that uplift your mood and inspire feelings of wonder.",
5
+ 'category': "soothieanduplift",
6
+ 'class': "emotion-info emotion-heading"
7
+ },
8
+ "amusement": {
9
+ 'heading': "Let's have some fun! Get ready to laugh and lighten up.",
10
+ 'info': "This playlist features playful and lighthearted music to boost your mood.",
11
+ 'category': "soothieanduplift",
12
+ 'class': "emotion-info emotion-heading"
13
+ },
14
+ "anger": {
15
+ 'heading': "Time to cool off!",
16
+ 'info': "Here are some tracks to help you release anger and find peace.",
17
+ 'category': "distractandchange",
18
+ 'class': "emotion-info emotion-heading"
19
+ },
20
+ "annoyance": {
21
+ 'heading': "Feeling annoyed? Let's turn it around!",
22
+ 'info': "Listen to these tunes to shift your mood and find some relief.",
23
+ 'category': "distractandchange",
24
+ 'class': "emotion-info emotion-heading"
25
+ },
26
+ "approval": {
27
+ 'heading': "Feel appreciated and acknowledged!",
28
+ 'info': "Enjoy these tracks that celebrate approval and acceptance.",
29
+ 'category': "soothieanduplift",
30
+ 'class': "emotion-info emotion-heading"
31
+ },
32
+ "caring": {
33
+ 'heading': "Embrace feelings of care and compassion.",
34
+ 'info': "This playlist is all about fostering a sense of warmth and empathy.",
35
+ 'category': "soothieanduplift",
36
+ 'class': "emotion-info emotion-heading"
37
+ },
38
+ "confusion": {
39
+ 'heading': "Embrace the confusion and explore!",
40
+ 'info': "Dive into these tracks to embrace curiosity and explore new perspectives.",
41
+ 'category': "engageandexplore",
42
+ 'class': "emotion-info emotion-heading"
43
+ },
44
+ "curiosity": {
45
+ 'heading': "Fuel your curiosity with these tunes!",
46
+ 'info': "Feed your curiosity and thirst for knowledge with this eclectic playlist.",
47
+ 'category': "engageandexplore",
48
+ 'class': "emotion-info emotion-heading"
49
+ },
50
+ "desire": {
51
+ 'heading': "Embrace your desires and passions!",
52
+ 'info': "Indulge in these tracks that ignite feelings of longing and passion.",
53
+ 'category': "engageandexplore",
54
+ 'class': "emotion-info emotion-heading"
55
+ },
56
+ "disappointment": {
57
+ 'heading': "Feeling disappointed? You're not alone.",
58
+ 'info': "Reflect and understand with these songs that capture the essence of disappointment.",
59
+ 'category': "reflectiveandunderstand",
60
+ 'class': "emotion-info emotion-heading"
61
+ },
62
+ "disapproval": {
63
+ 'heading': "Shake off disapproval and find your groove.",
64
+ 'info': "Listen to these tunes to uplift your spirits and brush off negativity.",
65
+ 'category': "distractandchange",
66
+ 'class': "emotion-info emotion-heading"
67
+ },
68
+ "disgust": {
69
+ 'heading': "Time to cleanse your palate!",
70
+ 'info': "Find solace in these tracks that help you move past feelings of disgust.",
71
+ 'category': "distractandchange",
72
+ 'class': "emotion-info emotion-heading"
73
+ },
74
+ "embarrassment": {
75
+ 'heading': "Embrace the embarrassment and move forward!",
76
+ 'info': "Listen to these tunes to shake off embarrassment and regain confidence.",
77
+ 'category': "distractandchange",
78
+ 'class': "emotion-info emotion-heading"
79
+ },
80
+ "excitement": {
81
+ 'heading': "Get ready to be pumped up!",
82
+ 'info': "Feel the energy with these high-octane tracks that fuel excitement.",
83
+ 'category': "energeticandmotivate",
84
+ 'class': "emotion-info emotion-heading"
85
+ },
86
+ "fear": {
87
+ 'heading': "Facing fear head-on!",
88
+ 'info': "Conquer your fears with these empowering tracks that inspire courage.",
89
+ 'category': "distractandchange",
90
+ 'class': "emotion-info emotion-heading"
91
+ },
92
+ "gratitude": {
93
+ 'heading': "Feel grateful and blessed!",
94
+ 'info': "Express gratitude with these heartfelt tunes that inspire thankfulness.",
95
+ 'category': "soothieanduplift",
96
+ 'class': "emotion-info emotion-heading"
97
+ },
98
+ "grief": {
99
+ 'heading': "Navigating through grief and loss.",
100
+ 'info': "Reflect and understand with these poignant songs that capture the essence of grief.",
101
+ 'category': "reflectiveandunderstand",
102
+ 'class': "emotion-info emotion-heading"
103
+ },
104
+ "joy": {
105
+ 'heading': "Let joy fill your heart!",
106
+ 'info': "Experience pure bliss with these uplifting tracks that radiate joy.",
107
+ 'category': "energeticandmotivate",
108
+ 'class': "emotion-info emotion-heading"
109
+ },
110
+ "love": {
111
+ 'heading': "Celebrate love in all its forms!",
112
+ 'info': "Get lost in these romantic tunes that celebrate the beauty of love.",
113
+ 'category': "soothieanduplift",
114
+ 'class': "emotion-info emotion-heading"
115
+ },
116
+ "nervousness": {
117
+ 'heading': "Embrace the nerves and stay strong!",
118
+ 'info': "Find calmness and strength with these soothing tracks that ease nervousness.",
119
+ 'category': "distractandchange",
120
+ 'class': "emotion-info emotion-heading"
121
+ },
122
+ "optimism": {
123
+ 'heading': "Stay positive and optimistic!",
124
+ 'info': "Fuel your optimism with these uplifting tunes that inspire positivity.",
125
+ 'category': "energeticandmotivate",
126
+ 'class': "emotion-info emotion-heading"
127
+ },
128
+ "pride": {
129
+ 'heading': "Feel proud of your achievements!",
130
+ 'info': "Celebrate your accomplishments with these triumphant tunes that exude pride.",
131
+ 'category': "energeticandmotivate",
132
+ 'class': "emotion-info emotion-heading"
133
+ },
134
+ "realization": {
135
+ 'heading': "Embrace newfound realizations!",
136
+ 'info': "Explore new insights and perspectives with these thought-provoking tunes.",
137
+ 'category': "engageandexplore",
138
+ 'class': "emotion-info emotion-heading"
139
+ },
140
+ "relief": {
141
+ 'heading': "Find relief and comfort!",
142
+ 'info': "Experience a sense of relief and relaxation with these calming tracks.",
143
+ 'category': "soothieanduplift",
144
+ 'class': "emotion-info emotion-heading"
145
+ },
146
+ "remorse": {
147
+ 'heading': "Reflecting on remorse and learning.",
148
+ 'info': "Reflect and understand with these introspective tunes that delve into remorse.",
149
+ 'category': "reflectiveandunderstand",
150
+ 'class': "emotion-info emotion-heading"
151
+ },
152
+ "sadness": {
153
+ 'heading': "Embrace the sadness and find solace.",
154
+ 'info': "Navigate through feelings of sadness with these comforting tracks.",
155
+ 'category': "reflectiveandunderstand",
156
+ 'class': "emotion-info emotion-heading"
157
+ },
158
+ "surprise": {
159
+ 'heading': "Expect the unexpected!",
160
+ 'info': "Embrace the element of surprise with these unpredictable tracks.",
161
+ 'category': "engageandexplore",
162
+ 'class': "emotion-info emotion-heading"
163
+ },
164
+ "neutral": {
165
+ 'heading': "Find balance and neutrality.",
166
+ 'info': "Stay grounded with these tranquil tracks that embody neutrality.",
167
+ 'category': "soothieanduplift",
168
+ 'class':"emotion-info emotion-heading"
169
+ }
170
+ }
app/modules/.DS_Store ADDED
Binary file (6.15 kB). View file
 
app/modules/__init__.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+
4
+ from modules.emotion import Emotion
5
+ from modules.transcription import Transcription
6
+
7
+ transcription_model = "tiny.en"
8
+ emotion_model = "joeddav/distilbert-base-uncased-go-emotions-student"
9
+
10
+ transcription_obj = Transcription(model_name=transcription_model)
11
+ emotion_obj = Emotion(model_name=emotion_model)
12
+
13
+ class Module:
14
+
15
+ def predict(self, audio_path: str) -> str:
16
+ """Loads audio, gets transcription and detects emotion
17
+
18
+ Args:
19
+ audio_path (str): path to the audio file
20
+
21
+ Returns:
22
+ str: emotion
23
+ """
24
+ print("Getting transcription...")
25
+ start_time = time.time()
26
+ if text := transcription_obj.transcribe(audio_path=audio_path):
27
+ print("Text: ", text, time.time() - start_time)
28
+
29
+ start_time = time.time()
30
+ emotion = emotion_obj.detect_emotion(text=text)
31
+ print("Emotion: ", emotion, time.time() - start_time)
32
+ return text, emotion
33
+ return None
34
+
app/modules/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (1.21 kB). View file
 
app/modules/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (1.84 kB). View file
 
app/modules/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (1.61 kB). View file
 
app/modules/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (1.16 kB). View file
 
app/modules/__pycache__/__init__.cpython-39.pyc ADDED
Binary file (1.21 kB). View file
 
app/modules/__pycache__/utils.cpython-310(1).pyc ADDED
Binary file (707 Bytes). View file
 
app/modules/__pycache__/utils.cpython-310.pyc ADDED
Binary file (738 Bytes). View file
 
app/modules/__pycache__/utils.cpython-311.pyc ADDED
Binary file (911 Bytes). View file
 
app/modules/__pycache__/utils.cpython-312.pyc ADDED
Binary file (840 Bytes). View file
 
app/modules/__pycache__/utils.cpython-38.pyc ADDED
Binary file (678 Bytes). View file
 
app/modules/__pycache__/utils.cpython-39.pyc ADDED
Binary file (726 Bytes). View file
 
app/modules/audio/__init__.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Any
2
+
3
+ import whisper
4
+
5
+
6
+ class Audio:
7
+ @classmethod
8
+ def load_audio(cls, audio_path: str) -> Any:
9
+ """Loads audio file from the disk
10
+
11
+ Args:
12
+ audio_path (str): path of the audio file
13
+
14
+ Returns:
15
+ Any: loaded audio file in numbers
16
+ """
17
+ return whisper.load_audio(audio_path)
18
+
app/modules/audio/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (693 Bytes). View file
 
app/modules/emotion/__init__.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Any
2
+
3
+ from modules.utils import Pipeline, load_model
4
+
5
+
6
+ class Emotion:
7
+ task: str = "text-classification"
8
+
9
+ def __init__(self, model_name: str) -> None:
10
+ # model_name: str = "/models/distilbert-base-uncased-go-emotions-student/"
11
+ print("Loading emotion model...")
12
+ self.emotion_model: Pipeline = load_model(task=self.task, model=model_name)
13
+ print("Loaded emotion model")
14
+
15
+ def detect_emotion(self, text: str) -> str:
16
+ """Detects emotion of the given text
17
+
18
+ Args:
19
+ text (str): text
20
+
21
+ Returns:
22
+ str: emotion
23
+ """
24
+ return self.emotion_model(text)[0]['label']
app/modules/emotion/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (1.09 kB). View file
 
app/modules/emotion/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (1.48 kB). View file
 
app/modules/emotion/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (1.27 kB). View file
 
app/modules/emotion/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (1.04 kB). View file
 
app/modules/emotion/__pycache__/__init__.cpython-39.pyc ADDED
Binary file (1.09 kB). View file
 
app/modules/transcription/__init__.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from faster_whisper import WhisperModel
3
+
4
+
5
+ class Transcription:
6
+
7
+ def __init__(self, model_name: str) -> None:
8
+ print("Loading whisper model...")
9
+ self.whisper_model = self.load_whisper(model_id=model_name)
10
+ print("Loaded whisper model")
11
+
12
+ def load_whisper(self, model_id: str):
13
+
14
+ device = "cuda:0" if torch.cuda.is_available() else "cpu"
15
+ torch_dtype = "float16" if torch.cuda.is_available() else "float32"
16
+
17
+ return WhisperModel(model_id, device=device, compute_type=torch_dtype)
18
+
19
+ def transcribe(self, audio_path: str) -> str:
20
+ """Transcribes the given audio data
21
+
22
+ Args:
23
+ audio_path (str): audio path
24
+
25
+ Returns:
26
+ str: text
27
+ """
28
+ segments, info = self.whisper_model.transcribe(audio_path, language="en")
29
+ return "".join(segment.text for segment in segments)
30
+
app/modules/transcription/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (2.23 kB). View file
 
app/modules/transcription/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (1.99 kB). View file
 
app/modules/transcription/__pycache__/__init__.cpython-38.pyc ADDED
Binary file (1.48 kB). View file
 
app/modules/utils.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from transformers import pipeline
3
+ from transformers.pipelines.base import Pipeline
4
+
5
+
6
+ def load_model(task: str, model: str) -> Pipeline:
7
+ """Loads the given transformers model based on the given task
8
+
9
+ Args:
10
+ task (str): NLP task
11
+ model (str): transformers model
12
+
13
+ Returns:
14
+ Pipeline: transformers pipeline object
15
+ """
16
+ return pipeline(
17
+ task=task,
18
+ model=model,
19
+ device = 0 if torch.cuda.is_available() else -1
20
+ )
app/static/audio_main.js ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ let now_playing = document.querySelector(".now-playing");
2
+ let track_art = document.querySelector(".track-art");
3
+ let track_name = document.querySelector(".track-name");
4
+ let track_artist = document.querySelector(".track-artist");
5
+
6
+ let playpause_btn = document.querySelector(".playpause-track");
7
+ let next_btn = document.querySelector(".next-track");
8
+ let prev_btn = document.querySelector(".prev-track");
9
+
10
+ let seek_slider = document.querySelector(".seek_slider");
11
+ let volume_slider = document.querySelector(".volume_slider");
12
+ let curr_time = document.querySelector(".current-time");
13
+ let total_duration = document.querySelector(".total-duration");
14
+
15
+ let track_index = 0;
16
+ let isPlaying = false;
17
+ let updateTimer;
18
+
19
+ // Create new audio element
20
+ let curr_track = document.createElement('audio');
21
+
22
+ // Define the tracks that have to be played
23
+ let track_list = [
24
+ {
25
+ name: "Night Owl",
26
+ artist: "Broke For Free",
27
+ image: "https://images.pexels.com/photos/2264753/pexels-photo-2264753.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=250&w=250",
28
+ path: "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/WFMU/Broke_For_Free/Directionless_EP/Broke_For_Free_-_01_-_Night_Owl.mp3"
29
+ },
30
+ {
31
+ name: "Enthusiast",
32
+ artist: "Tours",
33
+ image: "https://images.pexels.com/photos/3100835/pexels-photo-3100835.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=250&w=250",
34
+ path: "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/no_curator/Tours/Enthusiast/Tours_-_01_-_Enthusiast.mp3"
35
+ },
36
+ {
37
+ name: "Shipping Lanes",
38
+ artist: "Chad Crouch",
39
+ image: "https://images.pexels.com/photos/1717969/pexels-photo-1717969.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=250&w=250",
40
+ path: "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/ccCommunity/Chad_Crouch/Arps/Chad_Crouch_-_Shipping_Lanes.mp3",
41
+ },
42
+ {
43
+ name: "Starboy",
44
+ artist: "Weeknd",
45
+ image: "/static/weeknd.jpeg",
46
+ path: "/static/The Weeknd - Starboy ft.mp3",
47
+ },
48
+
49
+ ];
50
+
51
+ function random_bg_color() {
52
+
53
+ // Get a number between 64 to 256 (for getting lighter colors)
54
+ let red = Math.floor(Math.random() * 256) + 64;
55
+ let green = Math.floor(Math.random() * 256) + 64;
56
+ let blue = Math.floor(Math.random() * 256) + 64;
57
+
58
+ // Construct a color withe the given values
59
+ let bgColor = "rgb(" + red + "," + green + "," + blue + ")";
60
+
61
+ // Set the background to that color
62
+ document.body.style.background = bgColor;
63
+ }
64
+
65
+ function loadTrack(track_index) {
66
+ clearInterval(updateTimer);
67
+ resetValues();
68
+ curr_track.src = track_list[track_index].path;
69
+ curr_track.load();
70
+
71
+ track_art.style.backgroundImage = "url(" + track_list[track_index].image + ")";
72
+ track_name.textContent = track_list[track_index].name;
73
+ track_artist.textContent = track_list[track_index].artist;
74
+ now_playing.textContent = "PLAYING " + (track_index + 1) + " OF " + track_list.length;
75
+
76
+ updateTimer = setInterval(seekUpdate, 1000);
77
+ curr_track.addEventListener("ended", nextTrack);
78
+ random_bg_color();
79
+ }
80
+ function resetValues() {
81
+ curr_time.textContent = "00:00";
82
+ total_duration.textContent = "00:00";
83
+ seek_slider.value = 0;
84
+ }
85
+
86
+ // Load the first track in the tracklist
87
+ loadTrack(track_index);
88
+
89
+ function playpauseTrack() {
90
+ if (!isPlaying) playTrack();
91
+ else pauseTrack();
92
+ }
93
+
94
+ function playTrack() {
95
+ curr_track.play();
96
+ isPlaying = true;
97
+ playpause_btn.innerHTML = '<i class="fa fa-pause-circle fa-5x"></i>';
98
+ }
99
+
100
+ function pauseTrack() {
101
+ curr_track.pause();
102
+ isPlaying = false;
103
+ playpause_btn.innerHTML = '<i class="fa fa-play-circle fa-5x"></i>';;
104
+ }
105
+
106
+ function nextTrack() {
107
+ if (track_index < track_list.length - 1) {
108
+ track_index += 1;
109
+ } else {
110
+ track_index = 0;
111
+ }
112
+
113
+ loadTrack(track_index); // Load the new track
114
+
115
+ // Once the track is loaded, call playTrack
116
+ curr_track.addEventListener('loadeddata', playTrack);
117
+ }
118
+
119
+ function prevTrack() {
120
+ if (track_index > 0)
121
+ track_index -= 1;
122
+ else track_index = track_list.length;
123
+ loadTrack(track_index);
124
+ playTrack();
125
+ }
126
+
127
+ function seekTo() {
128
+ let seekto = curr_track.duration * (seek_slider.value / 100);
129
+ curr_track.currentTime = seekto;
130
+ }
131
+
132
+ function setVolume() {
133
+ curr_track.volume = volume_slider.value / 100;
134
+ }
135
+
136
+ function seekUpdate() {
137
+ let seekPosition = 0;
138
+
139
+ if (!isNaN(curr_track.duration)) {
140
+ seekPosition = curr_track.currentTime * (100 / curr_track.duration);
141
+
142
+ seek_slider.value = seekPosition;
143
+
144
+ let currentMinutes = Math.floor(curr_track.currentTime / 60);
145
+ let currentSeconds = Math.floor(curr_track.currentTime - currentMinutes * 60);
146
+ let durationMinutes = Math.floor(curr_track.duration / 60);
147
+ let durationSeconds = Math.floor(curr_track.duration - durationMinutes * 60);
148
+
149
+ if (currentSeconds < 10) { currentSeconds = "0" + currentSeconds; }
150
+ if (durationSeconds < 10) { durationSeconds = "0" + durationSeconds; }
151
+ if (currentMinutes < 10) { currentMinutes = "0" + currentMinutes; }
152
+ if (durationMinutes < 10) { durationMinutes = "0" + durationMinutes; }
153
+
154
+ curr_time.textContent = currentMinutes + ":" + currentSeconds;
155
+ total_duration.textContent = durationMinutes + ":" + durationSeconds;
156
+ }
157
+ }
158
+
159
+
app/static/audio_to_text.css ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body {
2
+ background: linear-gradient(to right, #0f4da6, #0f4da6, #1e272e, #1e272e);
3
+ margin: 0; /* Remove default body margin */
4
+ padding: 0; /* Remove default body padding */
5
+ }
6
+
7
+ .container {
8
+ position: relative;
9
+ }
10
+
11
+ .row {
12
+ background: linear-gradient(to right, #0f4da6, #0f4da6, #1e272e, #1e272e);
13
+ border-radius: 8px;
14
+ padding: 20px;
15
+ margin-bottom: 20px;
16
+ display: flex; /* Use Flexbox */
17
+ justify-content: space-around;
18
+ }
19
+
20
+ .column {
21
+ width: 45%; /* Adjust as needed */
22
+ padding: 15px;
23
+ color: #f0f0f5;
24
+ }
25
+
26
+ #recording-instructions {
27
+ text-align: left;
28
+ margin-top: 10px;
29
+ font-style: italic;
30
+ }
31
+
32
+ .row {
33
+ display: flex;
34
+ flex-direction: column; /* Stack items vertically */
35
+ align-items: left;
36
+ margin-bottom: 3%;
37
+ background-color: #060073;
38
+ }
39
+
40
+ /* Clear floats after the columns */
41
+ .row:after {
42
+ content: "";
43
+ display: table;
44
+ clear: both;
45
+ }
46
+
47
+ /* Responsive layout - makes the two columns stack on top of each other instead of next to each other */
48
+ @media screen and (max-width: 600px) {
49
+ .column1 {
50
+ width: 100%;
51
+ }
52
+ }
53
+
54
+ @media screen and (max-width: 600px) {
55
+ .column2 {
56
+ width: 100%;
57
+ }
58
+ }
59
+
60
+ #imgInp {
61
+ opacity: 0;
62
+ position: absolute;
63
+ z-index: -1;
64
+ }
65
+
66
+ label {
67
+ cursor: pointer;
68
+ padding-left: 10%;
69
+ padding-right: 10%;
70
+ padding-top: 2%;
71
+ padding-bottom: 2%;
72
+ font-size: 100%;
73
+ color: #000000;
74
+ border-radius: 25px;
75
+ background-color: #228B22;
76
+ }
77
+
78
+ #blah {
79
+ max-width: 60%;
80
+ max-height: 60%;
81
+ }
82
+
83
+ #image_div1 {
84
+ max-width: 70%;
85
+ max-height: 70%;
86
+ }
87
+
88
+ #stop, #start {
89
+ background-color: black;
90
+ color: white;
91
+ padding: 10px 20px;
92
+ border: none;
93
+ border-radius: 4px;
94
+ cursor: pointer;
95
+ margin: 10px; /* Add margin to create gap */
96
+ transition: background-color 0.3s ease; /* Add transition for smooth effect */
97
+ }
98
+
99
+ #stop {
100
+ margin-right: 5px; /* Adjust margin to create gap */
101
+ }
102
+
103
+ #stop:hover, #start:hover {
104
+ background-color: #333; /* Change background color on hover */
105
+ }
106
+
107
+ .animated-title {
108
+ font-size: 2.5rem;
109
+ font-weight: bold;
110
+ color: white;
111
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
112
+ animation: fadeIn 2s forwards;
113
+ transition: color 0.5s ease-in-out, text-shadow 0.5s ease-in-out;
114
+ white-space: nowrap;
115
+ position: absolute;
116
+ left: 200px; /* Adjust the value as needed */
117
+ top: 20px;
118
+ }
119
+
120
+ @keyframes fadeIn {
121
+ 0% {
122
+ opacity: 0;
123
+ transform: translateY(-20px);
124
+ }
125
+ 100% {
126
+ opacity: 1;
127
+ transform: translateY(0);
128
+ }
129
+ }
130
+
131
+ .animated-title:hover {
132
+ color: black;
133
+ text-shadow: 4px 4px 8px rgba(0, 0, 0, 0.8);
134
+ }
135
+
app/static/audiodisplay.js ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function drawBuffer( width, height, context, data ) {
2
+ var step = Math.ceil( data.length / width );
3
+ var amp = height / 2;
4
+ context.fillStyle = "silver";
5
+ context.clearRect(0,0,width,height);
6
+ for(var i=0; i < width; i++){
7
+ var min = 1.0;
8
+ var max = -1.0;
9
+ for (j=0; j<step; j++) {
10
+ var datum = data[(i*step)+j];
11
+ if (datum < min)
12
+ min = datum;
13
+ if (datum > max)
14
+ max = datum;
15
+ }
16
+ context.fillRect(i,(1+min)*amp,1,Math.max(1,(max-min)*amp));
17
+ }
18
+ }
19
+
app/static/dem.css ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *{
2
+ font-family:'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
3
+ color: #171717;
4
+ background-color: antiquewhite;
5
+ }
6
+ header {
7
+ text-align: center;
8
+
9
+ }
10
+ .grid-container {
11
+ display: grid;
12
+ grid-template-columns: repeat(3, 1fr);
13
+ gap: 20px;
14
+ }
15
+
16
+ .card {
17
+ border: 3px solid #f6a503;
18
+ border-radius: 8px;
19
+ overflow: hidden;
20
+ }
21
+
22
+ .card img {
23
+ width: 100%;
24
+ height: 600px;
25
+ display: block;
26
+ }
27
+
28
+ .card-content {
29
+ padding: 20px;
30
+ }
31
+
32
+ .card-content h2 {
33
+ margin-top: 0;
34
+ }
35
+
36
+ .card-content h4 {
37
+ margin-bottom: 10px;
38
+ }
39
+
40
+ .card-content button {
41
+ background-color: #f6a503;
42
+ color: #000000;
43
+ border: none;
44
+ padding: 10px 20px;
45
+ border-radius: 5px;
46
+ cursor: pointer;
47
+ transition: background-color 0.3s ease;
48
+ }
49
+
50
+ .card-content button:hover {
51
+ background-color: #ffffff;
52
+ }
53
+
app/static/demo.css ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* style.css */
2
+ .audio-container {
3
+ display: flex;
4
+ flex-wrap: wrap;
5
+ justify-content: space-around;
6
+ background-color: #2caaf3
7
+ }
8
+
9
+ .audio-player {
10
+ width: 300px;
11
+ margin: 15px;
12
+ border: 1px solid #ccc;
13
+ padding: 15px;
14
+ border-radius: 8px;
15
+ text-align: center;
16
+ background-color: #0af32d; /* Light background color */
17
+ box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.1); /* Subtle shadow effect */
18
+ }
19
+
20
+ .audio-player:nth-child(odd) {
21
+ background-color: #c71a82; /* Alternating background */
22
+ }
23
+
24
+ .audio-image {
25
+ width: 100%;
26
+ height: 200px;
27
+ object-fit: cover;
28
+ border-radius: 8px;
29
+ }
30
+
31
+ .audio-info {
32
+ margin-top: 10px;
33
+ }
34
+
35
+ /* Hover effect on the audio player */
36
+ .audio-player:hover {
37
+ background-color: #fcfbf9;
38
+ cursor: pointer;
39
+ }
40
+
app/static/distract.js ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ let now_playing = document.querySelector(".now-playing");
2
+ let track_art = document.querySelector(".track-art");
3
+ let track_name = document.querySelector(".track-name");
4
+ let track_artist = document.querySelector(".track-artist");
5
+
6
+ let playpause_btn = document.querySelector(".playpause-track");
7
+ let next_btn = document.querySelector(".next-track");
8
+ let prev_btn = document.querySelector(".prev-track");
9
+
10
+ let seek_slider = document.querySelector(".seek_slider");
11
+ let volume_slider = document.querySelector(".volume_slider");
12
+ let curr_time = document.querySelector(".current-time");
13
+ let total_duration = document.querySelector(".total-duration");
14
+
15
+ let track_index = 0;
16
+ let isPlaying = false;
17
+ let updateTimer;
18
+
19
+ // Create new audio element
20
+ let curr_track = document.createElement('audio');
21
+
22
+ // Define the tracks that have to be played
23
+ let track_list = [
24
+ {
25
+ name: "Happy",
26
+ artist: "Pharrell Williams",
27
+ image: "/static/happy.jpeg",
28
+ path: "/static/Pharrell Williams - Happy (Video).mp3"
29
+ },
30
+ {
31
+ name: "CAN'T STOP THE FEELING! ",
32
+ artist: "DreamWorks",
33
+ image: "/static/couldntstopfeel.jpeg",
34
+ path: "/static/CAN'T STOP THE FEELING! (from DreamWorks Animation's TROLLS) (Official Video).mp3"
35
+ },
36
+ {
37
+ name: "I'm Still Standing",
38
+ artist: "Elton John",
39
+ image: "/static/imstillstanding.jpeg",
40
+ path: "/static/Elton John - I'm Still Standing.mp3",
41
+ },
42
+ {
43
+ name: "Starboy",
44
+ artist: "Weeknd",
45
+ image: "/static/weeknd.png",
46
+ path: "/static/The Weeknd - Starboy ft.mp3",
47
+ },
48
+ {
49
+ name: "All Star",
50
+ artist: "Smash Mouth",
51
+ image: "/static/allstarsmash.jpeg",
52
+ path: "/static/Smash Mouth - All Star (Official Music Video).mp3",
53
+ }
54
+
55
+ ];
56
+
57
+ function random_bg_color() {
58
+
59
+ // Get a number between 64 to 256 (for getting lighter colors)
60
+ let red = Math.floor(Math.random() * 256) + 64;
61
+ let green = Math.floor(Math.random() * 256) + 64;
62
+ let blue = Math.floor(Math.random() * 256) + 64;
63
+
64
+ // Construct a color withe the given values
65
+ let bgColor = "rgb(" + red + "," + green + "," + blue + ")";
66
+
67
+ // Set the background to that color
68
+ document.body.style.background = bgColor;
69
+ }
70
+
71
+ function loadTrack(track_index) {
72
+ clearInterval(updateTimer);
73
+ resetValues();
74
+ curr_track.src = track_list[track_index].path;
75
+ curr_track.load();
76
+
77
+ track_art.style.backgroundImage = "url(" + track_list[track_index].image + ")";
78
+ track_name.textContent = track_list[track_index].name;
79
+ track_artist.textContent = track_list[track_index].artist;
80
+ now_playing.textContent = "PLAYING " + (track_index + 1) + " OF " + track_list.length;
81
+
82
+ updateTimer = setInterval(seekUpdate, 1000);
83
+ curr_track.addEventListener("ended", nextTrack);
84
+ random_bg_color();
85
+ }
86
+ function resetValues() {
87
+ curr_time.textContent = "00:00";
88
+ total_duration.textContent = "00:00";
89
+ seek_slider.value = 0;
90
+ }
91
+
92
+ // Load the first track in the tracklist
93
+ loadTrack(track_index);
94
+
95
+ function playpauseTrack() {
96
+ if (!isPlaying) playTrack();
97
+ else pauseTrack();
98
+ }
99
+
100
+ function playTrack() {
101
+ curr_track.play();
102
+ isPlaying = true;
103
+ playpause_btn.innerHTML = '<i class="fa fa-pause-circle fa-5x"></i>';
104
+ }
105
+
106
+ function pauseTrack() {
107
+ curr_track.pause();
108
+ isPlaying = false;
109
+ playpause_btn.innerHTML = '<i class="fa fa-play-circle fa-5x"></i>';;
110
+ }
111
+
112
+ function nextTrack() {
113
+ if (track_index < track_list.length - 1) {
114
+ track_index += 1;
115
+ } else {
116
+ track_index = 0;
117
+ }
118
+
119
+ loadTrack(track_index); // Load the new track
120
+
121
+ // Once the track is loaded, call playTrack
122
+ curr_track.addEventListener('loadeddata', playTrack);
123
+ }
124
+
125
+ function prevTrack() {
126
+ if (track_index > 0)
127
+ track_index -= 1;
128
+ else track_index = track_list.length;
129
+ loadTrack(track_index);
130
+ playTrack();
131
+ }
132
+
133
+ function seekTo() {
134
+ let seekto = curr_track.duration * (seek_slider.value / 100);
135
+ curr_track.currentTime = seekto;
136
+ }
137
+
138
+ function setVolume() {
139
+ curr_track.volume = volume_slider.value / 100;
140
+ }
141
+
142
+ function seekUpdate() {
143
+ let seekPosition = 0;
144
+
145
+ if (!isNaN(curr_track.duration)) {
146
+ seekPosition = curr_track.currentTime * (100 / curr_track.duration);
147
+
148
+ seek_slider.value = seekPosition;
149
+
150
+ let currentMinutes = Math.floor(curr_track.currentTime / 60);
151
+ let currentSeconds = Math.floor(curr_track.currentTime - currentMinutes * 60);
152
+ let durationMinutes = Math.floor(curr_track.duration / 60);
153
+ let durationSeconds = Math.floor(curr_track.duration - durationMinutes * 60);
154
+
155
+ if (currentSeconds < 10) { currentSeconds = "0" + currentSeconds; }
156
+ if (durationSeconds < 10) { durationSeconds = "0" + durationSeconds; }
157
+ if (currentMinutes < 10) { currentMinutes = "0" + currentMinutes; }
158
+ if (durationMinutes < 10) { durationMinutes = "0" + durationMinutes; }
159
+
160
+ curr_time.textContent = currentMinutes + ":" + currentSeconds;
161
+ total_duration.textContent = durationMinutes + ":" + durationSeconds;
162
+ }
163
+ }
164
+
165
+
app/static/distractandchange.css ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* style.css */
2
+ .audio-player {
3
+ background-color: var(--secondary-color);
4
+ background-image: url("path/to/subtle-pattern.png"); /* Optional */
5
+ border-radius: 15px;
6
+ padding: 30px;
7
+ box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15);
8
+ }
9
+
10
+ .player-controls {
11
+ display: flex;
12
+ justify-content: center;
13
+ width: 100%;
14
+ margin-bottom: 15px;
15
+ }
16
+
17
+ .player-controls button {
18
+ /* Style your buttons */
19
+ }
20
+
21
+ .song-info {
22
+ text-align: center;
23
+ }
24
+
25
+ .album-cover {
26
+ width: 150px;
27
+ height: 150px;
28
+ margin-bottom: 10px;
29
+ }
app/static/energy.js ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ let now_playing = document.querySelector(".now-playing");
2
+ let track_art = document.querySelector(".track-art");
3
+ let track_name = document.querySelector(".track-name");
4
+ let track_artist = document.querySelector(".track-artist");
5
+
6
+ let playpause_btn = document.querySelector(".playpause-track");
7
+ let next_btn = document.querySelector(".next-track");
8
+ let prev_btn = document.querySelector(".prev-track");
9
+
10
+ let seek_slider = document.querySelector(".seek_slider");
11
+ let volume_slider = document.querySelector(".volume_slider");
12
+ let curr_time = document.querySelector(".current-time");
13
+ let total_duration = document.querySelector(".total-duration");
14
+
15
+ let track_index = 0;
16
+ let isPlaying = false;
17
+ let updateTimer;
18
+
19
+ // Create new audio element
20
+ let curr_track = document.createElement('audio');
21
+
22
+ // Define the tracks that have to be played
23
+ let track_list = [
24
+ {
25
+ name: "Stronger",
26
+ artist: "Kanye West",
27
+ image: "stronger.jpeg",
28
+ path: "Kanye West - Stronger.mp3"
29
+ },
30
+ {
31
+ name: "Chak De India",
32
+ artist: "Salim-Sulaiman",
33
+ image: "chakdeindia.jpeg",
34
+ path: "Chak De India Song Title Song Shah Rukh Khan Sukhwinder Singh Salim-Sulaiman Jaideep Sahni.mp3 },
35
+ {
36
+ name: "Dhaakad",
37
+ artist: "Pritam",
38
+ image: "dangal.jpeg",
39
+ path: "Dhaakad - Full Video Dangal Aamir Khan Pritam Amitabh Bhattacharya Raftaar.mp3 },
40
+ {
41
+ name: "Roar",
42
+ artist: "Katy Perry",
43
+ image: "/static/roar.jpeg",
44
+ path: "/static/Katy Perry - Roar.mp3",
45
+ },
46
+
47
+ {
48
+ name: "Uptown Funk",
49
+ artist: "Mark Ronson",
50
+ image: "/static/uptownfunk.jpeg",
51
+ path: "/static/Mark Ronson - Uptown Funk (Official Video) ft. Bruno Mars.mp3"
52
+ },
53
+ ];
54
+
55
+ function random_bg_color() {
56
+
57
+ // Get a number between 64 to 256 (for getting lighter colors)
58
+ let red = Math.floor(Math.random() * 256) + 64;
59
+ let green = Math.floor(Math.random() * 256) + 64;
60
+ let blue = Math.floor(Math.random() * 256) + 64;
61
+
62
+ // Construct a color withe the given values
63
+ let bgColor = "rgb(" + red + "," + green + "," + blue + ")";
64
+
65
+ // Set the background to that color
66
+ document.body.style.background = bgColor;
67
+ }
68
+
69
+ function loadTrack(track_index) {
70
+ clearInterval(updateTimer);
71
+ resetValues();
72
+ curr_track.src = track_list[track_index].path;
73
+ curr_track.load();
74
+
75
+ track_art.style.backgroundImage = "url(" + track_list[track_index].image + ")";
76
+ track_name.textContent = track_list[track_index].name;
77
+ track_artist.textContent = track_list[track_index].artist;
78
+ now_playing.textContent = "PLAYING " + (track_index + 1) + " OF " + track_list.length;
79
+
80
+ updateTimer = setInterval(seekUpdate, 1000);
81
+ curr_track.addEventListener("ended", nextTrack);
82
+ random_bg_color();
83
+ }
84
+ function resetValues() {
85
+ curr_time.textContent = "00:00";
86
+ total_duration.textContent = "00:00";
87
+ seek_slider.value = 0;
88
+ }
89
+
90
+ // Load the first track in the tracklist
91
+ loadTrack(track_index);
92
+
93
+ function playpauseTrack() {
94
+ if (!isPlaying) playTrack();
95
+ else pauseTrack();
96
+ }
97
+
98
+ function playTrack() {
99
+ curr_track.play();
100
+ isPlaying = true;
101
+ playpause_btn.innerHTML = '<i class="fa fa-pause-circle fa-5x"></i>';
102
+ }
103
+
104
+ function pauseTrack() {
105
+ curr_track.pause();
106
+ isPlaying = false;
107
+ playpause_btn.innerHTML = '<i class="fa fa-play-circle fa-5x"></i>';;
108
+ }
109
+
110
+ function nextTrack() {
111
+ if (track_index < track_list.length - 1) {
112
+ track_index += 1;
113
+ } else {
114
+ track_index = 0;
115
+ }
116
+
117
+ loadTrack(track_index); // Load the new track
118
+
119
+ // Once the track is loaded, call playTrack
120
+ curr_track.addEventListener('loadeddata', playTrack);
121
+ }
122
+
123
+ function prevTrack() {
124
+ if (track_index > 0)
125
+ track_index -= 1;
126
+ else track_index = track_list.length;
127
+ loadTrack(track_index);
128
+ playTrack();
129
+ }
130
+
131
+ function seekTo() {
132
+ let seekto = curr_track.duration * (seek_slider.value / 100);
133
+ curr_track.currentTime = seekto;
134
+ }
135
+
136
+ function setVolume() {
137
+ curr_track.volume = volume_slider.value / 100;
138
+ }
139
+
140
+ function seekUpdate() {
141
+ let seekPosition = 0;
142
+
143
+ if (!isNaN(curr_track.duration)) {
144
+ seekPosition = curr_track.currentTime * (100 / curr_track.duration);
145
+
146
+ seek_slider.value = seekPosition;
147
+
148
+ let currentMinutes = Math.floor(curr_track.currentTime / 60);
149
+ let currentSeconds = Math.floor(curr_track.currentTime - currentMinutes * 60);
150
+ let durationMinutes = Math.floor(curr_track.duration / 60);
151
+ let durationSeconds = Math.floor(curr_track.duration - durationMinutes * 60);
152
+
153
+ if (currentSeconds < 10) { currentSeconds = "0" + currentSeconds; }
154
+ if (durationSeconds < 10) { durationSeconds = "0" + durationSeconds; }
155
+ if (currentMinutes < 10) { currentMinutes = "0" + currentMinutes; }
156
+ if (durationMinutes < 10) { durationMinutes = "0" + durationMinutes; }
157
+
158
+ curr_time.textContent = currentMinutes + ":" + currentSeconds;
159
+ total_duration.textContent = durationMinutes + ":" + durationSeconds;
160
+ }
161
+ }
162
+
163
+
app/static/engage.js ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ let now_playing = document.querySelector(".now-playing");
2
+ let track_art = document.querySelector(".track-art");
3
+ let track_name = document.querySelector(".track-name");
4
+ let track_artist = document.querySelector(".track-artist");
5
+
6
+ let playpause_btn = document.querySelector(".playpause-track");
7
+ let next_btn = document.querySelector(".next-track");
8
+ let prev_btn = document.querySelector(".prev-track");
9
+
10
+ let seek_slider = document.querySelector(".seek_slider");
11
+ let volume_slider = document.querySelector(".volume_slider");
12
+ let curr_time = document.querySelector(".current-time");
13
+ let total_duration = document.querySelector(".total-duration");
14
+
15
+ let track_index = 0;
16
+ let isPlaying = false;
17
+ let updateTimer;
18
+
19
+ // Create new audio element
20
+ let curr_track = document.createElement('audio');
21
+
22
+ // Define the tracks that have to be played
23
+ let track_list = [
24
+ {
25
+ name: "Smells Like Teen Spirit ",
26
+ artist: "Nirvana",
27
+ image: "/static/smellsliketeen.jpeg",
28
+ path: "/static/Nirvana - Smells Like Teen Spirit (Official Music Video).mp3",
29
+ },
30
+ {
31
+ name: "lifeonmars",
32
+ artist: "David Bowie",
33
+ image: "/static/lifeonmars.jpeg",
34
+ path: "/static/David Bowie Life On Mars_ (Official Video).mp3"
35
+ },
36
+ {
37
+ name: "Queen",
38
+ artist: "Bohemian Rhapsody",
39
+ image: "/static/queen.jpeg",
40
+ path: "/static/Queen Bohemian Rhapsody (Official Video Remastered).mp3"
41
+ },
42
+ {
43
+ name: "Hotel California",
44
+ artist: "Remaster",
45
+ image: "/static/hotelcalifornia.jpeg",
46
+ path: "/static/Hotel California (2013 Remaster).mp3",
47
+ },
48
+ {
49
+ name: "Hallelujah",
50
+ artist: "Leonard Cohen",
51
+ image: "/static/hallelujah.jpeg",
52
+ path: "/static/Leonard Cohen - Hallelujah (Live In London).mp3",
53
+ }
54
+
55
+ ];
56
+
57
+ function random_bg_color() {
58
+
59
+ // Get a number between 64 to 256 (for getting lighter colors)
60
+ let red = Math.floor(Math.random() * 256) + 64;
61
+ let green = Math.floor(Math.random() * 256) + 64;
62
+ let blue = Math.floor(Math.random() * 256) + 64;
63
+
64
+ // Construct a color withe the given values
65
+ let bgColor = "rgb(" + red + "," + green + "," + blue + ")";
66
+
67
+ // Set the background to that color
68
+ document.body.style.background = bgColor;
69
+ }
70
+
71
+ function loadTrack(track_index) {
72
+ clearInterval(updateTimer);
73
+ resetValues();
74
+ curr_track.src = track_list[track_index].path;
75
+ curr_track.load();
76
+
77
+ track_art.style.backgroundImage = "url(" + track_list[track_index].image + ")";
78
+ track_name.textContent = track_list[track_index].name;
79
+ track_artist.textContent = track_list[track_index].artist;
80
+ now_playing.textContent = "PLAYING " + (track_index + 1) + " OF " + track_list.length;
81
+
82
+ updateTimer = setInterval(seekUpdate, 1000);
83
+ curr_track.addEventListener("ended", nextTrack);
84
+ random_bg_color();
85
+ }
86
+ function resetValues() {
87
+ curr_time.textContent = "00:00";
88
+ total_duration.textContent = "00:00";
89
+ seek_slider.value = 0;
90
+ }
91
+
92
+ // Load the first track in the tracklist
93
+ loadTrack(track_index);
94
+
95
+ function playpauseTrack() {
96
+ if (!isPlaying) playTrack();
97
+ else pauseTrack();
98
+ }
99
+
100
+ function playTrack() {
101
+ curr_track.play();
102
+ isPlaying = true;
103
+ playpause_btn.innerHTML = '<i class="fa fa-pause-circle fa-5x"></i>';
104
+ }
105
+
106
+ function pauseTrack() {
107
+ curr_track.pause();
108
+ isPlaying = false;
109
+ playpause_btn.innerHTML = '<i class="fa fa-play-circle fa-5x"></i>';;
110
+ }
111
+
112
+ function nextTrack() {
113
+ if (track_index < track_list.length - 1) {
114
+ track_index += 1;
115
+ } else {
116
+ track_index = 0;
117
+ }
118
+
119
+ loadTrack(track_index); // Load the new track
120
+
121
+ // Once the track is loaded, call playTrack
122
+ curr_track.addEventListener('loadeddata', playTrack);
123
+ }
124
+
125
+ function prevTrack() {
126
+ if (track_index > 0)
127
+ track_index -= 1;
128
+ else track_index = track_list.length;
129
+ loadTrack(track_index);
130
+ playTrack();
131
+ }
132
+
133
+ function seekTo() {
134
+ let seekto = curr_track.duration * (seek_slider.value / 100);
135
+ curr_track.currentTime = seekto;
136
+ }
137
+
138
+ function setVolume() {
139
+ curr_track.volume = volume_slider.value / 100;
140
+ }
141
+
142
+ function seekUpdate() {
143
+ let seekPosition = 0;
144
+
145
+ if (!isNaN(curr_track.duration)) {
146
+ seekPosition = curr_track.currentTime * (100 / curr_track.duration);
147
+
148
+ seek_slider.value = seekPosition;
149
+
150
+ let currentMinutes = Math.floor(curr_track.currentTime / 60);
151
+ let currentSeconds = Math.floor(curr_track.currentTime - currentMinutes * 60);
152
+ let durationMinutes = Math.floor(curr_track.duration / 60);
153
+ let durationSeconds = Math.floor(curr_track.duration - durationMinutes * 60);
154
+
155
+ if (currentSeconds < 10) { currentSeconds = "0" + currentSeconds; }
156
+ if (durationSeconds < 10) { durationSeconds = "0" + durationSeconds; }
157
+ if (currentMinutes < 10) { currentMinutes = "0" + currentMinutes; }
158
+ if (durationMinutes < 10) { durationMinutes = "0" + durationMinutes; }
159
+
160
+ curr_time.textContent = currentMinutes + ":" + currentSeconds;
161
+ total_duration.textContent = durationMinutes + ":" + durationSeconds;
162
+ }
163
+ }
164
+
165
+
app/static/footer.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ function myFunction() {
2
+ var x = document.getElementById("myFootnav");
3
+ if (x.className === "footnov") {
4
+ x.className += " responsive";
5
+ } else {
6
+ x.className = "footnov";
7
+ }
8
+ }
app/static/footer_file.css ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .footnov {
2
+ overflow: hidden;
3
+ background-color: #333; /* Darker gray for better contrast */
4
+ color: #f2f2f2;
5
+ padding: 20px 0; /* Added padding for content */
6
+ }
7
+
8
+ .footnov a {
9
+ float: left;
10
+ display: block;
11
+ color: #f2f2f2;
12
+ text-align: center;
13
+ padding: 16px 20px;
14
+ text-decoration: none;
15
+ font-size: 17px;
16
+ transition: background-color 0.3s ease; /* Adding transition */
17
+ }
18
+
19
+ .footnov a:hover {
20
+ background-color: #555; /* Slightly darker hover effect */
21
+ }
22
+
23
+ .footnov a.active {
24
+ background-color: rgb(80, 61, 226); /* Match header for consistency */
25
+ color: white;
26
+ }
27
+
28
+ @media screen and (max-width: 600px) {
29
+ .footnov a:not(:first-child) {display: none;}
30
+ .footnov a.icon {
31
+ float: right;
32
+ display: block;
33
+ }
34
+ }
35
+
36
+ @media screen and (max-width: 100px) {
37
+ .footnov.responsive {position: relative;}
38
+ .footnov.responsive .icon {
39
+ position: absolute;
40
+ right: 0;
41
+ top: 0;
42
+ }
43
+ .footnov.responsive a {
44
+ float: none;
45
+ display: block;
46
+ text-align: left;
47
+ }
48
+ }
app/static/header.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ function myFunction() {
2
+ var x = document.getElementById("mytopnav");
3
+ if (x.className === "topnav") {
4
+ x.className += " responsive";
5
+ } else {
6
+ x.className = "topnav";
7
+ }
8
+ }
app/static/header_file.css ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body {
2
+ margin: 0;
3
+ text-align: left;
4
+ font-family: 'Roboto', sans-serif; /* More modern font choice */
5
+ }
6
+
7
+ .topnav {
8
+ overflow: hidden;
9
+ background-color: #007bff;
10
+ }
11
+
12
+ .topnav a {
13
+ float: left;
14
+ display: block;
15
+ color: white;
16
+ text-align: center;
17
+ padding: 16px 20px; /* Increased padding for a more spacious look */
18
+ text-decoration: none;
19
+ font-size: 17px;
20
+ margin-right: 15px;
21
+ transition: background-color 0.3s ease; /* Adding transition */
22
+ }
23
+
24
+ .topnav a:hover {
25
+ background-color: black; /* Black with low opacity */
26
+ color: white; /* Cleaner contrast */
27
+ }
28
+
29
+ .topnav a.active {
30
+ color: white;
31
+ }
32
+
33
+ /* Responsive Design */
34
+ @media screen and (max-width: 600px) {
35
+ .topnav a:not(:first-child) { display: none; }
36
+ .topnav a.icon {
37
+ float: right;
38
+ display: block;
39
+ font-size: 24px; /* Larger icon for better visibility */
40
+ }
41
+ }
42
+
43
+ @media screen and (max-width: 600px) {
44
+ .topnav.responsive { position: relative; }
45
+ .topnav.responsive .icon {
46
+ position: absolute;
47
+ right: 0;
48
+ top: 0;
49
+ }
50
+ .topnav.responsive a {
51
+ float: none;
52
+ display: block;
53
+ text-align: left;
54
+ }
55
+ }
56
+
57
+
58
+ .alert {
59
+ padding: 20px;
60
+ background-color: #f44336;
61
+ color: black;
62
+ }
63
+
64
+ .closebtn {
65
+ margin-left: 15px;
66
+ color: white;
67
+ font-weight: bold;
68
+ float: right;
69
+ font-size: 22px;
70
+ line-height: 20px;
71
+ cursor: pointer;
72
+ transition: 0.3s;
73
+ }
74
+
75
+ .closebtn:hover {
76
+ color: black;
77
+ }
app/static/login.css ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* login.css and register.css (adjust as needed) */
2
+ .container {
3
+ width: 400px;
4
+ margin: 50px auto;
5
+ padding: 20px;
6
+ border: 1px solid #ddd;
7
+ border-radius: 8px;
8
+ text-align: center;
9
+ background-color: #f8f8f8;
10
+ box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2);
11
+ }
12
+
13
+ h1 {
14
+ margin-bottom: 20px;
15
+ color: #333;
16
+ }
17
+
18
+ input[type="text"], input[type="email"], input[type="password"] {
19
+ width: 100%;
20
+ padding: 10px;
21
+ margin-bottom: 15px;
22
+ border: 1px solid #ccc;
23
+ border-radius: 4px;
24
+ }
25
+
26
+ .button-primary { /* Reuse from previous example */
27
+ background-color: #007bff;
28
+ color: white;
29
+ border: none;
30
+ padding: 10px 20px;
31
+ text-decoration: none;
32
+ border-radius: 5px;
33
+ font-size: 1rem;
34
+ transition: background-color 0.3s ease;
35
+ }
36
+
37
+ .button-primary:hover {
38
+ background-color: #0056b3;
39
+ }
app/static/main.css ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Add a gradient background color to the body */
2
+ body {
3
+ background: linear-gradient(to right, #0f4da6, #0f4da6, #1e272e, #1e272e);
4
+ }
5
+
6
+ /* Center the content */
7
+ .container {
8
+ display: flex;
9
+ align-items: center;
10
+ justify-content: center;
11
+ flex-direction: column;
12
+ min-height: 100vh;
13
+ }
14
+
15
+ /* Style the header */
16
+ header {
17
+ background-color: #007bff;
18
+ color: white;
19
+ padding: 1rem;
20
+ position: fixed;
21
+ top: 0;
22
+ left: 0;
23
+ width: 100%;
24
+ z-index: 100;
25
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
26
+ }
27
+
28
+ h1.title-font {
29
+ font-family: 'Dancing Script', cursive;
30
+ font-weight: 400;
31
+ margin-bottom: 0.5rem;
32
+ color: white; /* Change the color to your desired color */
33
+ font-size: 2.5rem; /* Increase the font size */
34
+ animation: fadeIn 2s forwards; /* Apply animation */
35
+ }
36
+
37
+ p {
38
+ font-family: 'Dancing Script', cursive;
39
+ font-weight: 400;
40
+ margin-bottom: 0.5rem;
41
+ color: black; /* Change the color to your desired color */
42
+ font-size: 1.5rem; /* Increase the font size */
43
+ animation: fadeIn 2s forwards; /* Apply animation */
44
+ transition: color 0.5s ease-in-out; /* Apply transition */
45
+
46
+ }
47
+
48
+ @keyframes typing {
49
+ from { width: 0; }
50
+ to { width: 100%; }
51
+ }
52
+
53
+ @keyframes blink-caret {
54
+ from, to { border-color: transparent; }
55
+ 50% { border-color: #ff00ff; } /* Change the color to your desired color */
56
+ }
57
+
58
+
59
+ p.title {
60
+ font-size: 2.5rem;
61
+ font-weight: bold;
62
+ text-transform: uppercase;
63
+ letter-spacing: 2px;
64
+ color: white;
65
+ margin-bottom: 2rem;
66
+ text-align: center;
67
+ animation: fadeIn 2s forwards;
68
+ transition: color 0.5s ease-in-out;
69
+ }
70
+
71
+ /* Animation for fading in */
72
+ @keyframes fadeIn {
73
+ 0% {
74
+ opacity: 0;
75
+ }
76
+ 100% {
77
+ opacity: 1;
78
+ }
79
+ }
80
+
81
+ /* Style the button */
82
+ .button-primary {
83
+ background-color: white;
84
+ color: black;
85
+ border: none;
86
+ padding: 10px 20px;
87
+ text-decoration: none;
88
+ border-radius: 5px;
89
+ font-size: 1rem;
90
+ transition: background-color 0.3s ease;
91
+ margin-top: 2rem;
92
+ animation: pulse 1s ease-in-out infinite;
93
+
94
+ }
95
+
96
+ .button-primary:hover {
97
+ background-color: #f0f0f0;
98
+ }
99
+ @keyframes pulse {
100
+ 0% {
101
+ box-shadow: 0 0 0 0px rgba(0, 0, 0, 0.5);
102
+ }
103
+ 50% {
104
+ box-shadow: 0 0 0 10px rgba(0, 0, 0, 0.5);
105
+ }
106
+ 100% {
107
+ box-shadow: 0 0 0 0px rgba(0, 0, 0, 0.5);
108
+ }
109
+ }
app/static/main.js ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright 2013 Chris Wilson
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
14
+ */
15
+
16
+ window.AudioContext = window.AudioContext || window.webkitAudioContext;
17
+
18
+ var audioContext = new AudioContext();
19
+ var audioInput = null,
20
+ realAudioInput = null,
21
+ inputPoint = null,
22
+ audioRecorder = null;
23
+ var rafID = null;
24
+ var analyserContext = null;
25
+ var canvasWidth, canvasHeight;
26
+ var recIndex = 0;
27
+
28
+
29
+ function gotBuffers(buffers) {
30
+ audioRecorder.exportMonoWAV(doneEncoding);
31
+ }
32
+
33
+ function doneEncoding(soundBlob) {
34
+ fetch('/audio', {
35
+ method: "POST", // Specify POST method
36
+ body: soundBlob
37
+ })
38
+ .then(response => {
39
+ if (response.ok) {
40
+ return response.json(); // Parse JSON response
41
+ } else {
42
+ throw new Error("Error in Flask /audio route: " + response.status);
43
+ }
44
+ })
45
+ .then(data => {
46
+ window.location.href = data.url; // Redirect using URL from the response
47
+ })
48
+ .catch(error => {
49
+ console.error(error);
50
+ });
51
+ }
52
+
53
+
54
+ function stopRecording() {
55
+ // stop recording
56
+ audioRecorder.stop();
57
+ document.getElementById('stop').disabled = true;
58
+ document.getElementById('start').removeAttribute('disabled');
59
+ audioRecorder.getBuffers(gotBuffers);
60
+ }
61
+
62
+ function startRecording() {
63
+
64
+ // start recording
65
+ if (!audioRecorder)
66
+ return;
67
+ document.getElementById('start').disabled = true;
68
+ document.getElementById('stop').removeAttribute('disabled');
69
+ audioRecorder.clear();
70
+ audioRecorder.record();
71
+ }
72
+
73
+ function convertToMono(input) {
74
+ var splitter = audioContext.createChannelSplitter(2);
75
+ var merger = audioContext.createChannelMerger(2);
76
+
77
+ input.connect(splitter);
78
+ splitter.connect(merger, 0, 0);
79
+ splitter.connect(merger, 0, 1);
80
+ return merger;
81
+ }
82
+
83
+ function cancelAnalyserUpdates() {
84
+ window.cancelAnimationFrame(rafID);
85
+ rafID = null;
86
+ }
87
+
88
+ function updateAnalysers(time) {
89
+ if (!analyserContext) {
90
+ var canvas = document.getElementById("analyser");
91
+ console.log("Canvas:", canvas); // Log 1
92
+ if (canvas) { // Check canvas exists
93
+ canvasWidth = canvas.width;
94
+ canvasHeight = canvas.height;
95
+ analyserContext = canvas.getContext('2d');
96
+ } else {
97
+ console.error("Canvas with ID 'analyser' not found!");
98
+ }
99
+ }
100
+
101
+ // analyzer draw code here
102
+ {
103
+ var SPACING = 3;
104
+ var BAR_WIDTH = 1;
105
+ var numBars = Math.round(canvasWidth / SPACING);
106
+ var freqByteData = new Uint8Array(analyserNode.frequencyBinCount);
107
+
108
+ analyserNode.getByteFrequencyData(freqByteData);
109
+
110
+ analyserContext.clearRect(0, 0, canvasWidth, canvasHeight);
111
+ analyserContext.fillStyle = '#F6D565';
112
+ analyserContext.lineCap = 'round';
113
+ var multiplier = analyserNode.frequencyBinCount / numBars;
114
+
115
+ // Draw rectangle for each frequency bin.
116
+ for (var i = 0; i < numBars; ++i) {
117
+ var magnitude = 0;
118
+ var offset = Math.floor(i * multiplier);
119
+ // gotta sum/average the block, or we miss narrow-bandwidth spikes
120
+ for (var j = 0; j < multiplier; j++)
121
+ magnitude += freqByteData[offset + j];
122
+ magnitude = magnitude / multiplier;
123
+ var magnitude2 = freqByteData[i * multiplier];
124
+ analyserContext.fillStyle = "hsl( " + Math.round((i * 360) / numBars) + ", 100%, 50%)";
125
+ analyserContext.fillRect(i * SPACING, canvasHeight, BAR_WIDTH, -magnitude);
126
+ }
127
+ }
128
+
129
+ rafID = window.requestAnimationFrame(updateAnalysers);
130
+ }
131
+
132
+ function toggleMono() {
133
+ if (audioInput != realAudioInput) {
134
+ audioInput.disconnect();
135
+ realAudioInput.disconnect();
136
+ audioInput = realAudioInput;
137
+ } else {
138
+ realAudioInput.disconnect();
139
+ audioInput = convertToMono(realAudioInput);
140
+ }
141
+
142
+ audioInput.connect(inputPoint);
143
+ }
144
+
145
+ function gotStream(stream) {
146
+ document.getElementById('start').removeAttribute('disabled');
147
+
148
+ inputPoint = audioContext.createGain();
149
+
150
+ // Create an AudioNode from the stream.
151
+ realAudioInput = audioContext.createMediaStreamSource(stream);
152
+ audioInput = realAudioInput;
153
+ audioInput.connect(inputPoint);
154
+
155
+ // audioInput = convertToMono( input );
156
+
157
+ analyserNode = audioContext.createAnalyser();
158
+ analyserNode.fftSize = 2048;
159
+ inputPoint.connect(analyserNode);
160
+
161
+ audioRecorder = new Recorder(inputPoint);
162
+
163
+ zeroGain = audioContext.createGain();
164
+ zeroGain.gain.value = 0.0;
165
+ inputPoint.connect(zeroGain);
166
+ zeroGain.connect(audioContext.destination);
167
+ updateAnalysers();
168
+ }
169
+
170
+ function initAudio() {
171
+ if (!navigator.getUserMedia)
172
+ navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
173
+ if (!navigator.cancelAnimationFrame)
174
+ navigator.cancelAnimationFrame = navigator.webkitCancelAnimationFrame || navigator.mozCancelAnimationFrame;
175
+ if (!navigator.requestAnimationFrame)
176
+ navigator.requestAnimationFrame = navigator.webkitRequestAnimationFrame || navigator.mozRequestAnimationFrame;
177
+
178
+ navigator.getUserMedia(
179
+ {
180
+ "audio": {
181
+ "mandatory": {
182
+ "googEchoCancellation": "false",
183
+ "googAutoGainControl": "false",
184
+ "googNoiseSuppression": "false",
185
+ "googHighpassFilter": "false"
186
+ },
187
+ "optional": []
188
+ },
189
+ }, gotStream, function (e) {
190
+ alert('Error getting audio');
191
+ console.log(e);
192
+ });
193
+ }
194
+
195
+ window.addEventListener('load', initAudio);
196
+
197
+ function unpause() {
198
+ document.getElementById('init').style.display = 'none';
199
+ audioContext.resume().then(() => {
200
+ console.log('Playback resumed successfully');
201
+ });
202
+ }
app/static/recorder.js ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function(window){
2
+
3
+ var WORKER_PATH = '/static/recorderWorker.js';
4
+
5
+ var Recorder = function(source, cfg){
6
+ var config = cfg || {};
7
+ var bufferLen = config.bufferLen || 4096;
8
+ this.context = source.context;
9
+ if(!this.context.createScriptProcessor){
10
+ this.node = this.context.createJavaScriptNode(bufferLen, 2, 2);
11
+ } else {
12
+ this.node = this.context.createScriptProcessor(bufferLen, 2, 2);
13
+ }
14
+
15
+ var worker = new Worker(config.workerPath || WORKER_PATH);
16
+ worker.postMessage({
17
+ command: 'init',
18
+ config: {
19
+ sampleRate: this.context.sampleRate
20
+ }
21
+ });
22
+ var recording = false,
23
+ currCallback;
24
+
25
+ this.node.onaudioprocess = function(e){
26
+ if (!recording) return;
27
+ worker.postMessage({
28
+ command: 'record',
29
+ buffer: [
30
+ e.inputBuffer.getChannelData(0),
31
+ e.inputBuffer.getChannelData(1)
32
+ ]
33
+ });
34
+ }
35
+
36
+ this.configure = function(cfg){
37
+ for (var prop in cfg){
38
+ if (cfg.hasOwnProperty(prop)){
39
+ config[prop] = cfg[prop];
40
+ }
41
+ }
42
+ }
43
+
44
+ this.record = function(){
45
+ recording = true;
46
+ }
47
+
48
+ this.stop = function(){
49
+ recording = false;
50
+ }
51
+
52
+ this.clear = function(){
53
+ worker.postMessage({ command: 'clear' });
54
+ }
55
+
56
+ this.getBuffers = function(cb) {
57
+ currCallback = cb || config.callback;
58
+ worker.postMessage({ command: 'getBuffers' })
59
+ }
60
+
61
+ this.exportWAV = function(cb, type){
62
+ currCallback = cb || config.callback;
63
+ type = type || config.type || 'audio/wav';
64
+ if (!currCallback) throw new Error('Callback not set');
65
+ worker.postMessage({
66
+ command: 'exportWAV',
67
+ type: type
68
+ });
69
+ }
70
+
71
+ this.exportMonoWAV = function(cb, type){
72
+ currCallback = cb || config.callback;
73
+ type = type || config.type || 'audio/wav';
74
+ if (!currCallback) throw new Error('Callback not set');
75
+ worker.postMessage({
76
+ command: 'exportMonoWAV',
77
+ type: type
78
+ });
79
+ }
80
+
81
+ worker.onmessage = function(e){
82
+ var blob = e.data;
83
+ currCallback(blob);
84
+ }
85
+
86
+ source.connect(this.node);
87
+ this.node.connect(this.context.destination); // if the script node is not connected to an output the "onaudioprocess" event is not triggered in chrome.
88
+ };
89
+
90
+ Recorder.setupDownload = function(blob, filename){
91
+ var url = (window.URL || window.webkitURL).createObjectURL(blob);
92
+ var link = document.getElementById("save");
93
+ link.href = url;
94
+ link.download = filename || 'output.wav';
95
+ }
96
+
97
+ window.Recorder = Recorder;
98
+
99
+ })(window);