Phoenixak99 commited on
Commit
e770b38
·
verified ·
1 Parent(s): d5e2dec

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +401 -84
app.py CHANGED
@@ -7,6 +7,8 @@ from datetime import datetime
7
  from io import BytesIO
8
  from tempfile import NamedTemporaryFile
9
  from xmlrpc.client import Binary
 
 
10
  import numpy as np
11
  import requests
12
  import scipy
@@ -21,35 +23,24 @@ from wordpress_xmlrpc import Client
21
  from wordpress_xmlrpc.compat import xmlrpc_client
22
  from wordpress_xmlrpc.methods import media
23
 
24
- # Function to extract nonce from URL parameters
25
- def get_nonce_from_url():
26
- params = st.experimental_get_query_params()
27
- if 'nonce' in params:
28
- return params['nonce'][0] # Extract the nonce from the query parameters
29
- return None
30
-
31
- nonce = get_nonce_from_url()
32
-
33
- # API URLs and Tokens
34
- API_URL = os.getenv("API_URL", None)
35
- BEARER_TOKEN = os.getenv("BEARER_TOKEN", None)
36
 
37
- if not API_URL:
 
 
 
38
  st.error("API_URL environment variable is not set.")
39
  st.stop()
40
 
41
- if not BEARER_TOKEN:
 
 
 
42
  st.error("BEARER_TOKEN environment variable is not set.")
43
  st.stop()
44
 
45
- # Define the headers for requests and include nonce
46
- headers = {
47
- "Authorization": f"Bearer {BEARER_TOKEN}",
48
- "Content-Type": "application/json",
49
- "X-WP-Nonce": nonce # Include nonce in the headers
50
- }
51
 
52
- # Add background image for Streamlit app
53
  page_bg_img = '''
54
  <style>
55
  .stApp {
@@ -60,30 +51,111 @@ background-size: cover;
60
  '''
61
  st.markdown(page_bg_img, unsafe_allow_html=True)
62
 
63
- # Function to check subscription status via WordPress API
64
- def check_subscription():
65
- if nonce:
66
- response = requests.get("https://songlabai.com/wp-json/custom/v1/subscription-status", headers=headers)
67
- if response.status_code == 200:
68
- return response.json()
69
- else:
70
- return None
71
- else:
72
- st.error("Nonce not found in the URL.")
73
- return None
74
-
75
- # Function to update generation timestamp for free users
76
- def update_generation_time():
77
- if nonce:
78
- response = requests.post("https://songlabai.com/wp-json/custom/v1/update-generation-time", headers=headers)
79
- if response.status_code == 200:
80
- st.success("Generation time updated.")
81
- else:
82
- st.error("Failed to update generation time.")
83
- else:
84
- st.error("Nonce not found in the URL.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
- # Display title
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  st.title("Songlab AI")
88
 
89
  # Initialize session state variables
@@ -91,12 +163,14 @@ if "vocal_audio" not in st_state:
91
  st_state.vocal_audio = None
92
  if "vocal_sample_rate" not in st_state:
93
  st_state.vocal_sample_rate = None
 
94
  if "audio" not in st_state:
95
  st_state.audio = None
96
  if "audio_pydub" not in st_state:
97
  st_state.audio_pydub = None
98
  if "audio_sample_rate" not in st_state:
99
  st_state.audio_sample_rate = None
 
100
  if "augmented_audio" not in st_state:
101
  st_state.augmented_audio = None
102
  if "augmented_audio_pydub" not in st_state:
@@ -104,71 +178,314 @@ if "augmented_audio_pydub" not in st_state:
104
  if "augmented_audio_sample_rate" not in st_state:
105
  st_state.augmented_audio_sample_rate = None
106
 
107
- # Select genre and energy level
108
- genres = ["Pop", "Rock", "Hip Hop", "Jazz", "Blues", "Country", "Classical", "Electronic", "Reggae", "Folk", "R&B", "Metal", "Punk", "Indie", "Dance", "World", "Gospel", "Soul", "Funk", "Ambient", "Techno", "Disco", "House", "Trance", "Dubstep"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  genre = st.selectbox("Select Genre:", genres)
110
  energy_levels = ["Low", "Medium", "High"]
111
  energy_level = st.radio("Energy Level:", energy_levels, horizontal=True)
112
-
113
- # Input for description and tempo
114
  description = st.text_input("Description:", "")
115
  tempo = st.slider("Tempo (in bpm):", min_value=40, max_value=100, value=60, step=5)
116
- duration = st.slider("Duration (in seconds):", min_value=15, max_value=300, value=30, step=1)
117
-
118
- # Check subscription status before allowing music generation
119
- subscription_status = check_subscription()
120
-
121
- if subscription_status == "free_plan":
122
- st.success("You can generate music once today!")
123
- elif subscription_status == "free_limit_reached":
124
- st.error("You have reached your limit for today. Please try again tomorrow.")
125
- elif subscription_status == "paid_user":
126
- st.success("You can generate unlimited music.")
127
- elif subscription_status == "not_subscribed":
128
- st.error("You need to subscribe to access this feature.")
129
- elif subscription_status == "not_logged_in":
130
- st.error("Please log in to access this feature.")
131
-
132
- # Function to send POST request and measure response time
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  def time_post_request(api_url, headers=None, payload=None):
 
 
 
 
 
 
 
 
 
 
 
 
134
  start_time = time.time()
135
  response = requests.post(api_url, headers=headers, json=payload)
136
- execution_time = time.time() - start_time
 
 
137
  print(f"Execution time: {execution_time} seconds")
 
138
  return response
139
 
140
- # Function to generate audio
141
  def generate_audio(genre, energy_level, tempo, description, duration):
142
- prompt = f"Genre: {genre}, Energy Level: {energy_level}, Tempo: {tempo}, Description: {description}"
 
143
  payload = {"inputs": {"prompt": prompt, "duration": duration}}
144
  with st.spinner("Generating audio ..."):
145
- response = time_post_request(API_URL, headers=headers, payload=payload)
146
- if response.status_code == 200:
147
- st.success("✔️ Audio Generated, Loading...")
148
- load_and_play_generated_audio(response)
149
- if subscription_status == "free_plan":
150
- update_generation_time() # Update generation time for free users
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  else:
152
- st.error("Failed to generate audio. Please try again later.")
 
 
 
153
 
154
- # Function to load and play the generated audio
155
  def load_and_play_generated_audio(response):
 
156
  response_eval = json.loads(response.content)
157
- channel1 = response_eval[0]["generated_audio"][0]
158
- channel2 = response_eval[0]["generated_audio"][1]
159
  with NamedTemporaryFile() as f1:
160
- scipy.io.wavfile.write(f1.name, rate=32000, data=np.array(channel1).astype(np.float32))
 
 
161
  channel1_temp = AudioSegment.from_file(f1.name)
162
  with NamedTemporaryFile() as f2:
163
- scipy.io.wavfile.write(f2.name, rate=32000, data=np.array(channel2).astype(np.float32))
 
 
164
  channel2_temp = AudioSegment.from_file(f2.name)
165
  audio_pydub = AudioSegment.from_mono_audiosegments(channel1_temp, channel2_temp)
166
  st_state.audio_pydub = audio_pydub
167
- st.audio(st_state.audio_pydub.export().read())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
 
169
- # Generate audio button
170
  if st.button("Generate Audio"):
171
- if description:
172
  generate_audio(genre, energy_level, tempo, description, duration)
173
- else:
 
174
  st.info("Description field is required.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  from io import BytesIO
8
  from tempfile import NamedTemporaryFile
9
  from xmlrpc.client import Binary
10
+ import jwt
11
+
12
  import numpy as np
13
  import requests
14
  import scipy
 
23
  from wordpress_xmlrpc.compat import xmlrpc_client
24
  from wordpress_xmlrpc.methods import media
25
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
+ # Try to get API_URL from environment variables, if not found set to a default value
28
+ try:
29
+ API_URL = os.environ["API_URL"]
30
+ except KeyError:
31
  st.error("API_URL environment variable is not set.")
32
  st.stop()
33
 
34
+ # Try to get the Bearer token from environment variables, if not found set to a default value
35
+ try:
36
+ BEARER_TOKEN = os.environ["BEARER_TOKEN"]
37
+ except KeyError:
38
  st.error("BEARER_TOKEN environment variable is not set.")
39
  st.stop()
40
 
41
+ print("API_URL:", os.environ["API_URL"])
42
+ print("BEARER_TOKEN:", os.environ["BEARER_TOKEN"])
 
 
 
 
43
 
 
44
  page_bg_img = '''
45
  <style>
46
  .stApp {
 
51
  '''
52
  st.markdown(page_bg_img, unsafe_allow_html=True)
53
 
54
+ def save_to_wordpress(channel1, channel2, sample_rate):
55
+
56
+ channel1 = np.array(channel1).astype(np.float32)
57
+ channel2 = np.array(channel2).astype(np.float32)
58
+ stereo_audio = np.column_stack((channel1, channel2))
59
+
60
+ # Define your WordPress site URL and authentication credentials
61
+ wordpress_url = "https://songlabai.com/xmlrpc.php"
62
+ woocommerce_url = "https://songlabai.com"
63
+ consumer_key = "ck_93d516ba12289a6fd0eced56bbc0b05ecbf98735"
64
+ consumer_secret = "cs_9d5eb716d631db408a4c47796b5d18b0313d8559"
65
+ username = "admin_h2ibbgql"
66
+ password = "um^VdaNK0H8Vw2*KNJlYABkh"
67
+
68
+ # Authenticate with WordPress XML-RPC API
69
+ wav_bytes = BytesIO()
70
+ sf.write(wav_bytes, stereo_audio, samplerate=sample_rate, format="WAV")
71
+ title = f"generated_audio_{datetime.now().timestamp()}.wav"
72
+ file_data = {
73
+ "name": title,
74
+ "type": "audio/x-wav", # Change the MIME type according to your file type
75
+ "bits": xmlrpc_client.Binary(wav_bytes.getvalue()),
76
+ }
77
+ wp_client = Client(wordpress_url, username, password)
78
+ for _ in range(4):
79
+ try:
80
+ # Upload the file to WordPress Media Library
81
+
82
+ media_response = wp_client.call(media.UploadFile(file_data))
83
+
84
+ # Handle the response
85
+ if media_response:
86
+ print(
87
+ "File successfully uploaded to WordPress with attachment ID:",
88
+ media_response,
89
+ )
90
+
91
+ # Create product data for WooCommerce
92
+ product_data = {
93
+ "status": "pending",
94
+ "name": title,
95
+ "type": "simple",
96
+ "regular_price": "1.00", # Set the price as needed
97
+ "sku": str(uuid.uuid4()),
98
+ "downloadable": True,
99
+ "download_limit": -1,
100
+ "download_expiry": -1,
101
+ }
102
 
103
+ # Authenticate with WooCommerce API
104
+ wc_api = API(
105
+ url=woocommerce_url,
106
+ consumer_key=consumer_key,
107
+ consumer_secret=consumer_secret,
108
+ version="wc/v3",
109
+ )
110
+
111
+ # Create the product
112
+ response = wc_api.post("products", product_data)
113
+
114
+ # Handle the response
115
+ if response.status_code == 201:
116
+ print(
117
+ "Product successfully created in WooCommerce:", response.json()
118
+ )
119
+ # Update product to add downloadable file URL
120
+ product_update_data = {
121
+ "downloads": [
122
+ {
123
+ "name": media_response["title"],
124
+ "file": media_response["link"],
125
+ }
126
+ ]
127
+ }
128
+ product_id = response.json().get("id")
129
+ response = wc_api.put(f"products/{product_id}", product_update_data)
130
+
131
+ if response.status_code == 200:
132
+ print(
133
+ "Downloadable file URL added to product:", response.json()
134
+ )
135
+ return (
136
+ response.json()["permalink"],
137
+ response.json()["permalink"].split("p=")[-1],
138
+ )
139
+ else:
140
+ print(
141
+ "Error adding downloadable file URL to product:",
142
+ response.text,
143
+ )
144
+ else:
145
+ print("Error creating product in WooCommerce:", response.text)
146
+ else:
147
+ print("Error uploading file to WordPress.")
148
+ break
149
+ except Exception as e:
150
+ print("Error:", e)
151
+
152
+
153
+ headers = {
154
+ "Authorization": f"Bearer {BEARER_TOKEN}",
155
+ "Content-Type": "application/json",
156
+ }
157
+
158
+ # Streamlit app title
159
  st.title("Songlab AI")
160
 
161
  # Initialize session state variables
 
163
  st_state.vocal_audio = None
164
  if "vocal_sample_rate" not in st_state:
165
  st_state.vocal_sample_rate = None
166
+
167
  if "audio" not in st_state:
168
  st_state.audio = None
169
  if "audio_pydub" not in st_state:
170
  st_state.audio_pydub = None
171
  if "audio_sample_rate" not in st_state:
172
  st_state.audio_sample_rate = None
173
+
174
  if "augmented_audio" not in st_state:
175
  st_state.augmented_audio = None
176
  if "augmented_audio_pydub" not in st_state:
 
178
  if "augmented_audio_sample_rate" not in st_state:
179
  st_state.augmented_audio_sample_rate = None
180
 
181
+
182
+ genres = [
183
+ "Pop",
184
+ "Rock",
185
+ "Hip Hop",
186
+ "Jazz",
187
+ "Blues",
188
+ "Country",
189
+ "Classical",
190
+ "Electronic",
191
+ "Reggae",
192
+ "Folk",
193
+ "R&B",
194
+ "Metal",
195
+ "Punk",
196
+ "Indie",
197
+ "Dance",
198
+ "World",
199
+ "Gospel",
200
+ "Soul",
201
+ "Funk",
202
+ "Ambient",
203
+ "Techno",
204
+ "Disco",
205
+ "House",
206
+ "Trance",
207
+ "Dubstep",
208
+ ]
209
+
210
  genre = st.selectbox("Select Genre:", genres)
211
  energy_levels = ["Low", "Medium", "High"]
212
  energy_level = st.radio("Energy Level:", energy_levels, horizontal=True)
 
 
213
  description = st.text_input("Description:", "")
214
  tempo = st.slider("Tempo (in bpm):", min_value=40, max_value=100, value=60, step=5)
215
+
216
+ # Duration input
217
+ duration = st.slider(
218
+ "Duration (in seconds):", min_value=15, max_value=300, value=30, step=1
219
+ )
220
+
221
+ prompt2 = "Classical ,Low, 40, slow calm"
222
+
223
+
224
+ def convert_audio_segment_to_float_array(audio_pydub):
225
+ """
226
+ Convert a pydub AudioSegment to a NumPy array of type float32.
227
+
228
+ Args:
229
+ audio_pydub (AudioSegment): The AudioSegment object to be converted.
230
+
231
+ Returns:
232
+ np.ndarray: A NumPy array containing the audio data as float32.
233
+ """
234
+ # Get the raw audio data as a sequence of samples
235
+ samples = audio_pydub.get_array_of_samples()
236
+
237
+ # Convert the samples to a NumPy array and normalize to float32
238
+ audio_array = np.array(samples).astype(np.float32)
239
+
240
+ # Normalize the audio array to range between -1.0 and 1.0
241
+ max_val = 2**15 # Assuming 16-bit audio, modify this if using different bit depths
242
+ audio_array /= max_val
243
+ return audio_array
244
+
245
  def time_post_request(api_url, headers=None, payload=None):
246
+ """
247
+ Times the execution of a POST request.
248
+
249
+ Parameters:
250
+ - api_url (str): The URL to which the POST request is sent.
251
+ - headers (dict): The headers to include in the POST request.
252
+ - payload (dict): The payload to include in the POST request.
253
+
254
+ Returns:
255
+ - response (requests.Response): The response object returned by the POST request.
256
+ - execution_time (float): The time it took to execute the POST request.
257
+ """
258
  start_time = time.time()
259
  response = requests.post(api_url, headers=headers, json=payload)
260
+ end_time = time.time()
261
+
262
+ execution_time = end_time - start_time
263
  print(f"Execution time: {execution_time} seconds")
264
+
265
  return response
266
 
 
267
  def generate_audio(genre, energy_level, tempo, description, duration):
268
+ count_down = 300
269
+ prompt = f"Genre: {genre}, Energy Level: {energy_level}, Tempo: {tempo}, Description: {description},"
270
  payload = {"inputs": {"prompt": prompt, "duration": duration}}
271
  with st.spinner("Generating audio ..."):
272
+ response = time_post_request(API_URL, headers, payload)
273
+ placeholder1 = st.empty()
274
+ if response.status_code != 200:
275
+ # Temp Jay Start
276
+ print(f"Request Headers: {response.request.headers}")
277
+ print(f"Request Body: {response.request.body}")
278
+ print(f"Response Code: {response.status_code}")
279
+ print(f"Response Body: {response.text}")
280
+ # Temp Jay End
281
+
282
+
283
+ print(str(response.content))
284
+ count_down_placeholder = st.empty()
285
+ for seconds in range(count_down):
286
+ count_down_placeholder.info(
287
+ f"The server is currently loading. Retrying in ⏳ {count_down - seconds} seconds."
288
+ )
289
+ time.sleep(1)
290
+ count_down_placeholder.empty()
291
+ with st.spinner("Generating audio ..."):
292
+ response = time_post_request(API_URL, headers, payload)
293
+ if response.status_code != 200:
294
+ count_down_placeholder = st.empty()
295
+ for seconds in range(count_down):
296
+ count_down_placeholder.info(
297
+ f"2nd attempt failed. trying again one more time in ⏳ {count_down - seconds} seconds."
298
+ )
299
+ time.sleep(1)
300
+ count_down_placeholder.empty()
301
+ with st.spinner("Generating audio ..."):
302
+ response = time_post_request(API_URL, headers, payload)
303
+ if response.status_code != 200:
304
+ placeholder1.error(
305
+ "Failed to generate audio after multiple attempts. Please try again later."
306
+ )
307
+ else:
308
+ placeholder1.success(f"✔️ Audio Generated, Loading...")
309
+ load_and_play_generated_audio(response)
310
+ placeholder1.empty()
311
+ else:
312
+ placeholder1.success(f"✔️ Audio Generated, Loading...")
313
+ load_and_play_generated_audio(response)
314
+ placeholder1.empty()
315
  else:
316
+ placeholder1.success(f"✔️ Audio Generated, Loading...")
317
+ load_and_play_generated_audio(response)
318
+ placeholder1.empty()
319
+
320
 
 
321
  def load_and_play_generated_audio(response):
322
+
323
  response_eval = json.loads(response.content)
324
+ channel1 = response_eval[0]["generated_audio"][0]
325
+ channel2 = response_eval[0]["generated_audio"][1]
326
  with NamedTemporaryFile() as f1:
327
+ scipy.io.wavfile.write(
328
+ f1.name, rate=32000, data=np.array(channel1).astype(np.float32)
329
+ )
330
  channel1_temp = AudioSegment.from_file(f1.name)
331
  with NamedTemporaryFile() as f2:
332
+ scipy.io.wavfile.write(
333
+ f2.name, rate=32000, data=np.array(channel2).astype(np.float32)
334
+ )
335
  channel2_temp = AudioSegment.from_file(f2.name)
336
  audio_pydub = AudioSegment.from_mono_audiosegments(channel1_temp, channel2_temp)
337
  st_state.audio_pydub = audio_pydub
338
+ st_state.audio_pydub_sample_rate = audio_pydub.frame_rate
339
+
340
+ st_state.audio = np.array(st_state.audio_pydub.get_array_of_samples()).astype(np.float32)
341
+ sample_rate = response_eval[0]["sample_rate"]
342
+ perm_link, product_code = save_to_wordpress(
343
+ channel1, channel2, 32000
344
+ )
345
+
346
+ st_state.audio_sample_rate = sample_rate
347
+ st_state.augmented_audio_pydub = st_state.audio_pydub
348
+ st.audio(st_state.audio_pydub.export().read())
349
+ col_btn, col_text = st.columns([2,4])
350
+
351
+ with col_btn:
352
+ st.link_button("Publish your Song", "https://songlabai.com/contact_us/")
353
+ st.link_button("Download Song", "https://songlabai.com/download-music/")
354
+
355
+ with col_text:
356
+ st.write(
357
+ f"To Publish, please contact the admin by sending the following link: {perm_link}"
358
+ )
359
+ st.write(f"To download use the following product code: {product_code}")
360
+
361
 
 
362
  if st.button("Generate Audio"):
363
+ if genre and energy_level and description and tempo:
364
  generate_audio(genre, energy_level, tempo, description, duration)
365
+
366
+ if description == "":
367
  st.info("Description field is required.")
368
+
369
+ # Post-processing options
370
+ st.header("Post-processing Options")
371
+
372
+ vocal_file = st.file_uploader(
373
+ "Upload Vocal File", type=["mp3", "wav", "ogg", "flac", "aac"]
374
+ )
375
+ if vocal_file:
376
+ st_state.vocal_audio = vocal_file.read()
377
+ # st.audio(st_state.vocal_audio, format="audio/wav")
378
+
379
+ # Mixing
380
+ mix_vocals = st.checkbox("Mix Vocals")
381
+
382
+ if mix_vocals and st_state.vocal_audio is not None:
383
+ with NamedTemporaryFile() as f:
384
+ f.write(st_state.vocal_audio)
385
+ st_state.vocal_audio = AudioSegment.from_file(f.name)
386
+ st_state.augmented_audio_pydub = st_state.augmented_audio_pydub.overlay(
387
+ st_state.vocal_audio, position=100
388
+ )
389
+ # st.audio(st_state.augmented_audio_pydub.export().read())
390
+ st_state.augmented_audio = convert_audio_segment_to_float_array(
391
+ st_state.augmented_audio_pydub
392
+ )
393
+ st_state.augmented_audio_sample_rate = st_state.augmented_audio_pydub.frame_rate
394
+ elif not mix_vocals and st_state.vocal_audio is not None:
395
+ st_state.augmented_audio_pydub = st_state.audio_pydub
396
+ st_state.augmented_audio_sample_rate = st_state.audio_pydub.frame_rate
397
+ # Mastering
398
+ st.header("Mastering")
399
+ st.markdown("")
400
+ # Volume Balance, Compression Ratio, and Reverb Amount
401
+ vol_col, pitch_shift,buttons_col = st.columns([2, 2, 2.5,])
402
+ with buttons_col:
403
+ with st.container(height=371, border=True):
404
+ st.markdown("")
405
+ apply_stereo = st.button("Apply Stereo Effect")
406
+ st.markdown("")
407
+ reverse = st.button("Apply Audio Reverse ")
408
+ st.markdown("")
409
+ reset_post_processing = st.button("Undo All Post-processings")
410
+ st.markdown("")
411
+
412
+ with vol_col:
413
+ with st.container(border=True):
414
+ volume_balance = svs.vertical_slider(
415
+ "Volume Balance",
416
+ min_value=-10.0,
417
+ max_value=10.0,
418
+ default_value=0.0,
419
+ step=0.1,
420
+ slider_color="green",
421
+ track_color="lightgray",
422
+ thumb_color="red",
423
+ thumb_shape="pill",
424
+ )
425
+ vol_button = st.button("Apply Vol-Balance")
426
+
427
+
428
+ # Pitch shifting
429
+ with pitch_shift:
430
+ with st.container(border=True):
431
+ pitch_semitones = svs.vertical_slider(
432
+ label="Pitch (semitones)",
433
+ min_value=-12,
434
+ max_value=12,
435
+ default_value=0,
436
+ step=1,
437
+ slider_color="red",
438
+ track_color="lightgray",
439
+ thumb_color="red",
440
+ thumb_shape="pill",
441
+ )
442
+ pitch_shift_button = st.button(
443
+ "Apply Pitch Shift",
444
+ )
445
+
446
+
447
+ if st_state.augmented_audio_pydub is not None:
448
+ if vol_button:
449
+ st_state.augmented_audio_pydub = st_state.augmented_audio_pydub + volume_balance
450
+
451
+ if apply_stereo:
452
+ st_state.augmented_audio_pydub = st_state.augmented_audio_pydub.pan(
453
+ -0.5
454
+ ).overlay(st_state.augmented_audio_pydub.pan(0.5))
455
+ if reverse:
456
+ st_state.augmented_audio_pydub = st_state.augmented_audio_pydub.reverse()
457
+ if pitch_shift_button:
458
+ st_state.augmented_audio_pydub = st_state.augmented_audio_pydub._spawn(
459
+ st_state.augmented_audio_pydub.raw_data,
460
+ overrides={
461
+ "frame_rate": int(
462
+ st_state.augmented_audio_pydub.frame_rate
463
+ * (2 ** (pitch_semitones / 12.0))
464
+ )
465
+ },
466
+ )
467
+
468
+ # Display the final audio
469
+ if st_state.augmented_audio_pydub is not None:
470
+ st.audio(st_state.augmented_audio_pydub.export().read())
471
+ # sample_rate = st_state.augmented_audio_sample_rate
472
+ # st.audio(st_state.augmented_audio, format="audio/wav", sample_rate=sample_rate*2, start_time=0)
473
+
474
+ st.link_button(
475
+ label="⬇️ Download/Save",
476
+ url="https://songlabai.com/subcribe/",
477
+ type="primary",
478
+ use_container_width=True,
479
+ )
480
+ # m = st.markdown("""
481
+ # <style>
482
+ # div.stButton > button:first-child {
483
+ # # color: rgb(204, 49, 49);
484
+ # # background-color: ;
485
+ # # border-radius: 5%;
486
+ # backgroud-color: #00ff00;
487
+ # }
488
+ # # </style>""", unsafe_allow_html=True)
489
+
490
+ if reset_post_processing and st_state.audio_pydub is not None:
491
+ st_state.augmented_audio_pydub = st_state.audio_pydub